13c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/* 2c5488c571f08b2e21b060a1b43aa840d0a3c6e7aTatyana Nikolova * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved. 33c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. 43c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * 53c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * This software is available to you under a choice of one of two 63c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * licenses. You may choose to be licensed under the terms of the GNU 73c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * General Public License (GPL) Version 2, available from the file 83c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * COPYING in the main directory of this source tree, or the 93c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * OpenIB.org BSD license below: 103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * 113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * Redistribution and use in source and binary forms, with or 123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * without modification, are permitted provided that the following 133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * conditions are met: 143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * 153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * - Redistributions of source code must retain the above 163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * copyright notice, this list of conditions and the following 173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * disclaimer. 183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * 193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * - Redistributions in binary form must reproduce the above 203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * copyright notice, this list of conditions and the following 213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * disclaimer in the documentation and/or other materials 223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * provided with the distribution. 233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * 243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * SOFTWARE. 323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <linux/module.h> 353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <linux/moduleparam.h> 363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <linux/netdevice.h> 373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <linux/etherdevice.h> 383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <linux/ethtool.h> 393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <linux/mii.h> 403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <linux/if_vlan.h> 413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <linux/crc32.h> 423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <linux/in.h> 433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <linux/fs.h> 443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <linux/init.h> 453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <linux/if_arp.h> 463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <linux/highmem.h> 475a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <asm/io.h> 493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <asm/irq.h> 503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <asm/byteorder.h> 513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <rdma/ib_smi.h> 523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <rdma/ib_verbs.h> 533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <rdma/ib_pack.h> 543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <rdma/iw_cm.h> 553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include "nes.h" 573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <net/netevent.h> 593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <net/neighbour.h> 603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <linux/route.h> 613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <net/ip_fib.h> 623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_AUTHOR("NetEffect"); 643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_DESCRIPTION("NetEffect RNIC Low-level iWARP Driver"); 653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_LICENSE("Dual BSD/GPL"); 663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_VERSION(DRV_VERSION); 673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffint max_mtu = 9000; 693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffint interrupt_mod_interval = 0; 703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/* Interoperability */ 733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffint mpa_version = 1; 74de182149c31786b2b07fa408fb076599b29232a1Chien Tungmodule_param(mpa_version, int, 0644); 753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_PARM_DESC(mpa_version, "MPA version to be used int MPA Req/Resp (0 or 1)"); 763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/* Interoperability */ 783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffint disable_mpa_crc = 0; 79de182149c31786b2b07fa408fb076599b29232a1Chien Tungmodule_param(disable_mpa_crc, int, 0644); 803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_PARM_DESC(disable_mpa_crc, "Disable checking of MPA CRC"); 813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffunsigned int send_first = 0; 83de182149c31786b2b07fa408fb076599b29232a1Chien Tungmodule_param(send_first, int, 0644); 843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_PARM_DESC(send_first, "Send RDMA Message First on Active Connection"); 853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 870f0bee8bbc2b3e49baa703118041f99db9ef41a1Faisal Latifunsigned int nes_drv_opt = NES_DRV_OPT_DISABLE_INT_MOD | NES_DRV_OPT_ENABLE_PAU; 88de182149c31786b2b07fa408fb076599b29232a1Chien Tungmodule_param(nes_drv_opt, int, 0644); 893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_PARM_DESC(nes_drv_opt, "Driver option parameters"); 903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffunsigned int nes_debug_level = 0; 923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffmodule_param_named(debug_level, nes_debug_level, uint, 0644); 933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_PARM_DESC(debug_level, "Enable debug output level"); 943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 952b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tungunsigned int wqm_quanta = 0x10000; 962b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tungmodule_param(wqm_quanta, int, 0644); 972b537c2824194d50072ab260f54d6fe4cb8d17e8Chien TungMODULE_PARM_DESC(wqm_quanta, "WQM quanta"); 982b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 9990ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool limit_maxrdreqsz; 100633693660045b3e46a63ed618eb38a54339fbcc0Chien Tungmodule_param(limit_maxrdreqsz, bool, 0644); 101633693660045b3e46a63ed618eb38a54339fbcc0Chien TungMODULE_PARM_DESC(limit_maxrdreqsz, "Limit max read request size to 256 Bytes"); 102633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung 1033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffLIST_HEAD(nes_adapter_list); 1041a855fbfb65e0b7b5cce00d7c6a61185ed765edfRoland Dreierstatic LIST_HEAD(nes_dev_list); 1053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffatomic_t qps_destroyed; 1073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic unsigned int ee_flsh_adapter; 1093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic unsigned int sysfs_nonidx_addr; 1103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic unsigned int sysfs_idx_addr; 1113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic struct pci_device_id nes_pci_table[] = { 11333085bb8da9c77c2d5572125385efa87627d8b59Peter Huewe { PCI_VDEVICE(NETEFFECT, PCI_DEVICE_ID_NETEFFECT_NE020), }, 11433085bb8da9c77c2d5572125385efa87627d8b59Peter Huewe { PCI_VDEVICE(NETEFFECT, PCI_DEVICE_ID_NETEFFECT_NE020_KR), }, 1153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff {0} 1163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff}; 1173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_DEVICE_TABLE(pci, nes_pci_table); 1193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_inetaddr_event(struct notifier_block *, unsigned long, void *); 1213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_net_event(struct notifier_block *, unsigned long, void *); 1223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_notifiers_registered; 1233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic struct notifier_block nes_inetaddr_notifier = { 1263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .notifier_call = nes_inetaddr_event 1273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff}; 1283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic struct notifier_block nes_net_notifier = { 1303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .notifier_call = nes_net_event 1313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff}; 1323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 1343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_inetaddr_event 1353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 1363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_inetaddr_event(struct notifier_block *notifier, 1373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned long event, void *ptr) 1383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 1393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct in_ifaddr *ifa = ptr; 1403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct net_device *event_netdev = ifa->ifa_dev->dev; 1413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 1423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct net_device *netdev; 1433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_vnic *nesvnic; 1442a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski unsigned int is_bonded; 1458cf14e38372d84ea09ba45fb60b61f6e36c18546Harvey Harrison 1468cf14e38372d84ea09ba45fb60b61f6e36c18546Harvey Harrison nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address %pI4, netmask %pI4.\n", 1478cf14e38372d84ea09ba45fb60b61f6e36c18546Harvey Harrison &ifa->ifa_address, &ifa->ifa_mask); 1483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 1493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "Nesdev list entry = 0x%p. (%s)\n", 1503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev, nesdev->netdev[0]->name); 1513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev = nesdev->netdev[0]; 1523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesvnic = netdev_priv(netdev); 1531765a575334f1a232c1478accdee5c7d19f4b3e3Jiri Pirko is_bonded = netif_is_bond_slave(netdev) && 1541765a575334f1a232c1478accdee5c7d19f4b3e3Jiri Pirko (netdev->master == event_netdev); 1552a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski if ((netdev == event_netdev) || is_bonded) { 1563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesvnic->rdma_enabled == 0) { 1573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "Returning without processing event for %s since" 1583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff " RDMA is not enabled.\n", 1593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev->name); 1603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_OK; 1613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 1623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* we have ifa->ifa_address/mask here if we need it */ 1633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff switch (event) { 1643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff case NETDEV_DOWN: 1653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "event:DOWN\n"); 1663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, 1673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)), 0); 1683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_manage_arp_cache(netdev, netdev->dev_addr, 1703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ntohl(nesvnic->local_ipaddr), NES_ARP_DELETE); 1713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesvnic->local_ipaddr = 0; 1722a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski if (is_bonded) 1732a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski continue; 1742a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski else 1752a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski return NOTIFY_OK; 1763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 1773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff case NETDEV_UP: 1783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "event:UP\n"); 1793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesvnic->local_ipaddr != 0) { 1813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "Interface already has local_ipaddr\n"); 1823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_OK; 1833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 1842a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski /* fall through */ 1852a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski case NETDEV_CHANGEADDR: 1863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Add the address to the IP table */ 1872a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski if (netdev->master) 1882a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski nesvnic->local_ipaddr = 1892a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski ((struct in_device *)netdev->master->ip_ptr)->ifa_list->ifa_address; 1902a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski else 1912a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski nesvnic->local_ipaddr = ifa->ifa_address; 1923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, 1943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)), 1952a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski ntohl(nesvnic->local_ipaddr)); 1963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_manage_arp_cache(netdev, netdev->dev_addr, 1973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ntohl(nesvnic->local_ipaddr), NES_ARP_ADD); 1982a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski if (is_bonded) 1992a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski continue; 2002a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski else 2012a4c97ead4b375a64063523210939b87ad225b85Maciej Sosnowski return NOTIFY_OK; 2023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 2033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff default: 2043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 2053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_DONE; 2103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 2113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 2143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_net_event 2153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 2163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_net_event(struct notifier_block *notifier, 2173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned long event, void *ptr) 2183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 2193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct neighbour *neigh = ptr; 2203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 2213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct net_device *netdev; 2223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_vnic *nesvnic; 2233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff switch (event) { 2253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff case NETEVENT_NEIGH_UPDATE: 2263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 2273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* nes_debug(NES_DBG_NETDEV, "Nesdev list entry = 0x%p.\n", nesdev); */ 2283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev = nesdev->netdev[0]; 2293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesvnic = netdev_priv(netdev); 2303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (netdev == neigh->dev) { 2313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesvnic->rdma_enabled == 0) { 2323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "Skipping device %s since no RDMA\n", 2333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev->name); 2343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 2353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (neigh->nud_state & NUD_VALID) { 2363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_manage_arp_cache(neigh->dev, neigh->ha, 2373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ntohl(*(__be32 *)neigh->primary_key), NES_ARP_ADD); 2383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 2393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_manage_arp_cache(neigh->dev, neigh->ha, 2403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ntohl(*(__be32 *)neigh->primary_key), NES_ARP_DELETE); 2413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_OK; 2443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 2473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff default: 2483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "NETEVENT_ %lu undefined\n", event); 2493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 2503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_DONE; 2533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 2543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 2573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_add_ref 2583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 2593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffvoid nes_add_ref(struct ib_qp *ibqp) 2603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 2613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_qp *nesqp; 2623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp = to_nesqp(ibqp); 2643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_QP, "Bumping refcount for QP%u. Pre-inc value = %u\n", 2653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ibqp->qp_num, atomic_read(&nesqp->refcount)); 2663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff atomic_inc(&nesqp->refcount); 2673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 2683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void nes_cqp_rem_ref_callback(struct nes_device *nesdev, struct nes_cqp_request *cqp_request) 2703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 2713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned long flags; 2723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_qp *nesqp = cqp_request->cqp_callback_pointer; 2733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_adapter *nesadapter = nesdev->nesadapter; 2743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff atomic_inc(&qps_destroyed); 2763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Free the control structures */ 2783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesqp->pbl_vbase) { 2803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, 2813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp->hwqp.q2_vbase, nesqp->hwqp.q2_pbase); 2823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff spin_lock_irqsave(&nesadapter->pbl_lock, flags); 2833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesadapter->free_256pbl++; 2843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); 2853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_free_consistent(nesdev->pcidev, 256, nesqp->pbl_vbase, nesqp->pbl_pbase); 2863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp->pbl_vbase = NULL; 2873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 2893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, 2903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp->hwqp.sq_vbase, nesqp->hwqp.sq_pbase); 2913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_free_resource(nesadapter, nesadapter->allocated_qps, nesqp->hwqp.qp_id); 2933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2946492cdf3a24fd620660c399745b5e169a0ed27d6Faisal Latif nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = NULL; 2953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff kfree(nesqp->allocated_buffer); 2963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 2983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 3003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_rem_ref 3013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 3023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffvoid nes_rem_ref(struct ib_qp *ibqp) 3033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 3043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u64 u64temp; 3053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_qp *nesqp; 3063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_vnic *nesvnic = to_nesvnic(ibqp->device); 3073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev = nesvnic->nesdev; 3083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_hw_cqp_wqe *cqp_wqe; 3093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_cqp_request *cqp_request; 3103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 opcode; 3113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp = to_nesqp(ibqp); 3133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (atomic_read(&nesqp->refcount) == 0) { 3153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_INFO PFX "%s: Reference count already 0 for QP%d, last aeq = 0x%04X.\n", 3163371836383d63b627b228875f5ac63023cbf11d2Harvey Harrison __func__, ibqp->qp_num, nesqp->last_aeq); 3173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff BUG(); 3183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 3193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (atomic_dec_and_test(&nesqp->refcount)) { 3210f0bee8bbc2b3e49baa703118041f99db9ef41a1Faisal Latif if (nesqp->pau_mode) 3220f0bee8bbc2b3e49baa703118041f99db9ef41a1Faisal Latif nes_destroy_pau_qp(nesdev, nesqp); 3230f0bee8bbc2b3e49baa703118041f99db9ef41a1Faisal Latif 3243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Destroy the QP */ 3253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_request = nes_get_cqp_request(nesdev); 3263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (cqp_request == NULL) { 3273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n"); 3283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return; 3293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 3303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_request->waiting = 0; 3313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_request->callback = 1; 3323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_request->cqp_callback = nes_cqp_rem_ref_callback; 3333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_request->cqp_callback_pointer = nesqp; 3343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_wqe = &cqp_request->cqp_wqe; 3353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_fill_init_cqp_wqe(cqp_wqe, nesdev); 3373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff opcode = NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_IWARP; 3383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesqp->hte_added) { 3403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff opcode |= NES_CQP_QP_DEL_HTE; 3413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp->hte_added = 0; 3423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 3433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode); 3443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id); 3453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u64temp = (u64)nesqp->nesqp_context_pbase; 3463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp); 3478294f29767c53e97664a27db9974adea8e2ea95bRoland Dreier nes_post_cqp_request(nesdev, cqp_request); 3483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 3493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 3503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 3533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_get_qp 3543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 3553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstruct ib_qp *nes_get_qp(struct ib_device *device, int qpn) 3563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 3573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_vnic *nesvnic = to_nesvnic(device); 3583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev = nesvnic->nesdev; 3593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_adapter *nesadapter = nesdev->nesadapter; 3603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((qpn < NES_FIRST_QPN) || (qpn >= (NES_FIRST_QPN + nesadapter->max_qp))) 3623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NULL; 3633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return &nesadapter->qp_table[qpn - NES_FIRST_QPN]->ibqp; 3653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 3663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 3693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_print_macaddr 3703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 3713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void nes_print_macaddr(struct net_device *netdev) 3723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 373e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg nes_debug(NES_DBG_INIT, "%s: %pM, IRQ %u\n", 374e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg netdev->name, netdev->dev_addr, netdev->irq); 3752bd01c5d2ed04838d50548cb7b955505a20ac0bdRoland Dreier} 3763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 3783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_interrupt - handle interrupts 3793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 3803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic irqreturn_t nes_interrupt(int irq, void *dev_id) 3813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 3823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev = (struct nes_device *)dev_id; 3833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int handled = 0; 3843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 int_mask; 3853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 int_req; 3863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 int_stat; 3873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 intf_int_stat; 3883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 timer_stat; 3893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesdev->msi_enabled) { 3913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* No need to read the interrupt pending register if msi is enabled */ 3923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff handled = 1; 3933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 3943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (unlikely(nesdev->nesadapter->hw_rev == NE020_REV)) { 3953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Master interrupt enable provides synchronization for kicking off bottom half 3963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff when interrupt sharing is going on */ 3973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int_mask = nes_read32(nesdev->regs + NES_INT_MASK); 3983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (int_mask & 0x80000000) { 3993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Check interrupt status to see if this might be ours */ 4003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int_stat = nes_read32(nesdev->regs + NES_INT_STAT); 4013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int_req = nesdev->int_req; 4023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (int_stat&int_req) { 4033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* if interesting CEQ or AEQ is pending, claim the interrupt */ 4043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((int_stat&int_req) & (~(NES_INT_TIMER|NES_INT_INTF))) { 4053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff handled = 1; 4063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 4073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (((int_stat & int_req) & NES_INT_TIMER) == NES_INT_TIMER) { 4083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Timer might be running but might be for another function */ 4093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff timer_stat = nes_read32(nesdev->regs + NES_TIMER_STAT); 4103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((timer_stat & nesdev->timer_int_req) != 0) { 4113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff handled = 1; 4123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((((int_stat & int_req) & NES_INT_INTF) == NES_INT_INTF) && 4153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (handled == 0)) { 4163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff intf_int_stat = nes_read32(nesdev->regs+NES_INTF_INT_STAT); 4173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((intf_int_stat & nesdev->intf_int_req) != 0) { 4183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff handled = 1; 4193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (handled) { 4233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs+NES_INT_MASK, int_mask & (~0x80000000)); 4243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int_mask = nes_read32(nesdev->regs+NES_INT_MASK); 4253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Save off the status to save an additional read */ 4263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->int_stat = int_stat; 4273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->napi_isr_ran = 1; 4283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 4323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff handled = nes_read32(nesdev->regs+NES_INT_PENDING); 4333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (handled) { 4373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_napi_isr(nesdev) == 0) { 4393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff tasklet_schedule(&nesdev->dpc_tasklet); 4403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return IRQ_HANDLED; 4433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 4443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return IRQ_NONE; 4453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 4473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 4503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_probe - Device initialization 4513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 4523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) 4533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 4543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct net_device *netdev = NULL; 4553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev = NULL; 4563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int ret = 0; 4573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff void __iomem *mmio_regs = NULL; 4583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u8 hw_rev; 4593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff assert(pcidev != NULL); 4613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff assert(ent != NULL); 4623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_INFO PFX "NetEffect RNIC driver v%s loading. (%s)\n", 4643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff DRV_VERSION, pci_name(pcidev)); 4653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = pci_enable_device(pcidev); 4673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 4683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to enable PCI device. (%s)\n", pci_name(pcidev)); 4693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail0; 4703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "BAR0 (@0x%08lX) size = 0x%lX bytes\n", 4733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (long unsigned int)pci_resource_start(pcidev, BAR_0), 4743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (long unsigned int)pci_resource_len(pcidev, BAR_0)); 4753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "BAR1 (@0x%08lX) size = 0x%lX bytes\n", 4763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (long unsigned int)pci_resource_start(pcidev, BAR_1), 4773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (long unsigned int)pci_resource_len(pcidev, BAR_1)); 4783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Make sure PCI base addr are MMIO */ 4803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (!(pci_resource_flags(pcidev, BAR_0) & IORESOURCE_MEM) || 4813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff !(pci_resource_flags(pcidev, BAR_1) & IORESOURCE_MEM)) { 4823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "PCI regions not an MMIO resource\n"); 4833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = -ENODEV; 4843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail1; 4853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Reserve PCI I/O and memory resources */ 4883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = pci_request_regions(pcidev, DRV_NAME); 4893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 4903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to request regions. (%s)\n", pci_name(pcidev)); 4913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail1; 4923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((sizeof(dma_addr_t) > 4)) { 4956a35528a8346f6e6fd32ed7e51f04d1fa4ca2c01Yang Hongyang ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(64)); 4963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret < 0) { 4973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "64b DMA mask configuration failed\n"); 4983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail2; 4993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5006a35528a8346f6e6fd32ed7e51f04d1fa4ca2c01Yang Hongyang ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64)); 5013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 5023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "64b DMA consistent mask configuration failed\n"); 5033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail2; 5043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 506284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(32)); 5073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret < 0) { 5083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "32b DMA mask configuration failed\n"); 5093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail2; 5103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 511284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32)); 5123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 5133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "32b DMA consistent mask configuration failed\n"); 5143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail2; 5153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_set_master(pcidev); 5193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Allocate hardware structure */ 5213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev = kzalloc(sizeof(struct nes_device), GFP_KERNEL); 5223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (!nesdev) { 5233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "%s: Unable to alloc hardware struct\n", pci_name(pcidev)); 5243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = -ENOMEM; 5253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail2; 5263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "Allocated nes device at %p\n", nesdev); 5293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->pcidev = pcidev; 5303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_set_drvdata(pcidev, nesdev); 5313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_read_config_byte(pcidev, 0x0008, &hw_rev); 5333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "hw_rev=%u\n", hw_rev); 5343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff spin_lock_init(&nesdev->indexed_regs_lock); 5363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Remap the PCI registers in adapter BAR0 to kernel VA space */ 538d85ddd835b33a9a0f2276ce068318da3fd1ad76aJulia Lawall mmio_regs = ioremap_nocache(pci_resource_start(pcidev, BAR_0), 539d85ddd835b33a9a0f2276ce068318da3fd1ad76aJulia Lawall pci_resource_len(pcidev, BAR_0)); 5403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (mmio_regs == NULL) { 5413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to remap BAR0\n"); 5423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = -EIO; 5433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail3; 5443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->regs = mmio_regs; 5463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->index_reg = 0x50 + (PCI_FUNC(pcidev->devfn)*8) + mmio_regs; 5473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Ensure interrupts are disabled */ 5493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs+NES_INT_MASK, 0x7fffffff); 5503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_drv_opt & NES_DRV_OPT_ENABLE_MSI) { 5523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (!pci_enable_msi(nesdev->pcidev)) { 5533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->msi_enabled = 1; 5543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "MSI is enabled for device %s\n", 5553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_name(pcidev)); 5563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 5573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "MSI is disabled by linux for device %s\n", 5583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_name(pcidev)); 5593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 5613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "MSI not requested due to driver options for device %s\n", 5623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_name(pcidev)); 5633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->csr_start = pci_resource_start(nesdev->pcidev, BAR_0); 5663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->doorbell_region = pci_resource_start(nesdev->pcidev, BAR_1); 5673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Init the adapter */ 5693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter = nes_init_adapter(nesdev, hw_rev); 5703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (!nesdev->nesadapter) { 5713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to initialize adapter.\n"); 5723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = -ENOMEM; 5733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail5; 5743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 575a4435febd4c0f14b25159dca249ecf91301c7c76Adrian Bunk nesdev->nesadapter->et_rx_coalesce_usecs_irq = interrupt_mod_interval; 5762b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung nesdev->nesadapter->wqm_quanta = wqm_quanta; 5773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* nesdev->base_doorbell_index = 5793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter->pd_config_base[PCI_FUNC(nesdev->pcidev->devfn)]; */ 5803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->base_doorbell_index = 1; 5813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->doorbell_start = nesdev->nesadapter->doorbell_start; 582fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung if (nesdev->nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) { 583fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung switch (PCI_FUNC(nesdev->pcidev->devfn) % 584fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->nesadapter->port_count) { 585fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung case 1: 586fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->mac_index = 2; 587fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung break; 588fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung case 2: 589fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->mac_index = 1; 590fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung break; 591fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung case 3: 592fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->mac_index = 3; 593fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung break; 594fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung case 0: 595fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung default: 596fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->mac_index = 0; 597fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung } 598fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung } else { 599fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->mac_index = PCI_FUNC(nesdev->pcidev->devfn) % 600fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->nesadapter->port_count; 601fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung } 6023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 603633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung if ((limit_maxrdreqsz || 604633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung ((nesdev->nesadapter->phy_type[0] == NES_PHY_TYPE_GLADIUS) && 605633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung (hw_rev == NE020_REV1))) && 606633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung (pcie_get_readrq(pcidev) > 256)) { 607633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung if (pcie_set_readrq(pcidev, 256)) 608633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung printk(KERN_ERR PFX "Unable to set max read request" 609633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung " to 256 bytes\n"); 610633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung else 611633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung nes_debug(NES_DBG_INIT, "Max read request size set" 612633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung " to 256 bytes\n"); 613633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung } 614633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung 6153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff tasklet_init(&nesdev->dpc_tasklet, nes_dpc, (unsigned long)nesdev); 6163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* bring up the Control QP */ 6183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_init_cqp(nesdev)) { 6193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = -ENODEV; 6203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail6; 6213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Arm the CCQ */ 6243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT | 6253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff PCI_FUNC(nesdev->pcidev->devfn)); 6263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_read32(nesdev->regs+NES_CQE_ALLOC); 6273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Enable the interrupts */ 6293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->int_req = (0x101 << PCI_FUNC(nesdev->pcidev->devfn)) | 6303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (1 << (PCI_FUNC(nesdev->pcidev->devfn)+16)); 6313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (PCI_FUNC(nesdev->pcidev->devfn) < 4) { 632fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->int_req |= (1 << (PCI_FUNC(nesdev->mac_index)+24)); 6333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* TODO: This really should be the first driver to load, not function 0 */ 6363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (PCI_FUNC(nesdev->pcidev->devfn) == 0) { 6373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* pick up PCI and critical errors if the first driver to load */ 6383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->intf_int_req = NES_INTF_INT_PCIERR | NES_INTF_INT_CRITERR; 6393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->int_req |= NES_INT_INTF; 6403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 6413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->intf_int_req = 0; 6423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->intf_int_req |= (1 << (PCI_FUNC(nesdev->pcidev->devfn)+16)); 6443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS0, 0); 6453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS1, 0); 6463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS2, 0x00001265); 6473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS4, 0x18021804); 6483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS3, 0x17801790); 6503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* deal with both periodic and one_shot */ 6523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->timer_int_req = 0x101 << PCI_FUNC(nesdev->pcidev->devfn); 6533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter->timer_int_req |= nesdev->timer_int_req; 6543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "setting int_req for function %u, nesdev = 0x%04X, adapter = 0x%04X\n", 6553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff PCI_FUNC(nesdev->pcidev->devfn), 6563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->timer_int_req, nesdev->nesadapter->timer_int_req); 6573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req)); 6593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_add_tail(&nesdev->list, &nes_dev_list); 6613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Request an interrupt line for the driver */ 6633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = request_irq(pcidev->irq, nes_interrupt, IRQF_SHARED, DRV_NAME, nesdev); 6643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 6653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "%s: requested IRQ %u is busy\n", 6663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_name(pcidev), pcidev->irq); 6673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail65; 6683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req); 6713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_notifiers_registered == 0) { 6733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff register_inetaddr_notifier(&nes_inetaddr_notifier); 6743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff register_netevent_notifier(&nes_net_notifier); 6753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_notifiers_registered++; 6773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6785f61b2c6939bb6d26393df15765bc3cb260db063Maciej Sosnowski INIT_DELAYED_WORK(&nesdev->work, nes_recheck_link_status); 6795f61b2c6939bb6d26393df15765bc3cb260db063Maciej Sosnowski 6803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Initialize network devices */ 681b2a899eaf3ab78cab380ef7e331c549d771cc2caRoland Dreier if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL) 682b2a899eaf3ab78cab380ef7e331c549d771cc2caRoland Dreier goto bail7; 6833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 684b2a899eaf3ab78cab380ef7e331c549d771cc2caRoland Dreier /* Register network device */ 685b2a899eaf3ab78cab380ef7e331c549d771cc2caRoland Dreier ret = register_netdev(netdev); 686b2a899eaf3ab78cab380ef7e331c549d771cc2caRoland Dreier if (ret) { 687b2a899eaf3ab78cab380ef7e331c549d771cc2caRoland Dreier printk(KERN_ERR PFX "Unable to register netdev, ret = %d\n", ret); 688b2a899eaf3ab78cab380ef7e331c549d771cc2caRoland Dreier nes_netdev_destroy(netdev); 689b2a899eaf3ab78cab380ef7e331c549d771cc2caRoland Dreier goto bail7; 690b2a899eaf3ab78cab380ef7e331c549d771cc2caRoland Dreier } 6913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 692b2a899eaf3ab78cab380ef7e331c549d771cc2caRoland Dreier nes_print_macaddr(netdev); 6933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 694b2a899eaf3ab78cab380ef7e331c549d771cc2caRoland Dreier nesdev->netdev_count++; 695b2a899eaf3ab78cab380ef7e331c549d771cc2caRoland Dreier nesdev->nesadapter->netdev_count++; 6963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 697748bfd9c1ded8419e7fdba4ca6f0c1dc1642df63Roland Dreier printk(KERN_INFO PFX "%s: NetEffect RNIC driver successfully loaded.\n", 6983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_name(pcidev)); 6993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return 0; 7003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail7: 7023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "bail7\n"); 7033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff while (nesdev->netdev_count > 0) { 7043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->netdev_count--; 7053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter->netdev_count--; 7063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_netdev(nesdev->netdev[nesdev->netdev_count]); 7083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_netdev_destroy(nesdev->netdev[nesdev->netdev_count]); 7093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "netdev_count=%d, nesadapter->netdev_count=%d\n", 7123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->netdev_count, nesdev->nesadapter->netdev_count); 7133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_notifiers_registered--; 7153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_notifiers_registered == 0) { 7163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_netevent_notifier(&nes_net_notifier); 7173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_inetaddr_notifier(&nes_inetaddr_notifier); 7183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_del(&nesdev->list); 7213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_destroy_cqp(nesdev); 7223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail65: 7243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "bail65\n"); 7253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff free_irq(pcidev->irq, nesdev); 7263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesdev->msi_enabled) { 7273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_disable_msi(pcidev); 7283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail6: 7303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "bail6\n"); 7313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff tasklet_kill(&nesdev->dpc_tasklet); 7323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Deallocate the Adapter Structure */ 7333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_destroy_adapter(nesdev->nesadapter); 7343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail5: 7363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "bail5\n"); 7373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff iounmap(nesdev->regs); 7383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail3: 7403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "bail3\n"); 7413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff kfree(nesdev); 7423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail2: 7443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_release_regions(pcidev); 7453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail1: 7473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_disable_device(pcidev); 7483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail0: 7503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return ret; 7513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 7523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 7553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_remove - unload from kernel 7563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 7573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void __devexit nes_remove(struct pci_dev *pcidev) 7583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 7593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev = pci_get_drvdata(pcidev); 7603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct net_device *netdev; 7613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int netdev_index = 0; 7625f61b2c6939bb6d26393df15765bc3cb260db063Maciej Sosnowski unsigned long flags; 7633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesdev->netdev_count) { 7653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev = nesdev->netdev[netdev_index]; 7663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (netdev) { 7673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netif_stop_queue(netdev); 7683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_netdev(netdev); 7693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_netdev_destroy(netdev); 7703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->netdev[netdev_index] = NULL; 7723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->netdev_count--; 7733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter->netdev_count--; 7743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_notifiers_registered--; 7783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_notifiers_registered == 0) { 7793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_netevent_notifier(&nes_net_notifier); 7803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_inetaddr_notifier(&nes_inetaddr_notifier); 7813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_del(&nesdev->list); 7843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_destroy_cqp(nesdev); 7854cd1e5eb3cbe6e0cc934959770b4c60eac6ecf66Roland Dreier 7864cd1e5eb3cbe6e0cc934959770b4c60eac6ecf66Roland Dreier free_irq(pcidev->irq, nesdev); 7873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff tasklet_kill(&nesdev->dpc_tasklet); 7883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7895f61b2c6939bb6d26393df15765bc3cb260db063Maciej Sosnowski spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags); 7905f61b2c6939bb6d26393df15765bc3cb260db063Maciej Sosnowski if (nesdev->link_recheck) { 7915f61b2c6939bb6d26393df15765bc3cb260db063Maciej Sosnowski spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags); 7925f61b2c6939bb6d26393df15765bc3cb260db063Maciej Sosnowski cancel_delayed_work_sync(&nesdev->work); 7935f61b2c6939bb6d26393df15765bc3cb260db063Maciej Sosnowski } else { 7945f61b2c6939bb6d26393df15765bc3cb260db063Maciej Sosnowski spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags); 7955f61b2c6939bb6d26393df15765bc3cb260db063Maciej Sosnowski } 7965f61b2c6939bb6d26393df15765bc3cb260db063Maciej Sosnowski 7973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Deallocate the Adapter Structure */ 7983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_destroy_adapter(nesdev->nesadapter); 7993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesdev->msi_enabled) { 8013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_disable_msi(pcidev); 8023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff iounmap(nesdev->regs); 8053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff kfree(nesdev); 8063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* nes_debug(NES_DBG_SHUTDOWN, "calling pci_release_regions.\n"); */ 8083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_release_regions(pcidev); 8093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_disable_device(pcidev); 8103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_set_drvdata(pcidev, NULL); 8113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic struct pci_driver nes_pci_driver = { 8153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .name = DRV_NAME, 8163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .id_table = nes_pci_table, 8173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .probe = nes_probe, 8183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .remove = __devexit_p(nes_remove), 8193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff}; 8203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_adapter(struct device_driver *ddp, char *buf) 8223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned int devfn = 0xffffffff; 8243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned char bus_number = 0xff; 8253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned int i = 0; 8263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 8273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 8293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 830fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung devfn = nesdev->pcidev->devfn; 831fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung bus_number = nesdev->pcidev->bus->number; 8323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 8333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 8353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 837fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung return snprintf(buf, PAGE_SIZE, "%x:%x\n", bus_number, devfn); 8383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_adapter(struct device_driver *ddp, 8413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 8423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 8443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ee_flsh_adapter = simple_strtoul(p, &p, 10); 8463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 8473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_ee_cmd(struct device_driver *ddp, char *buf) 8503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 eeprom_cmd = 0xdead; 8523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 8533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 8543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 8563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 8573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff eeprom_cmd = nes_read32(nesdev->regs + NES_EEPROM_COMMAND); 8583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 8593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 8613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", eeprom_cmd); 8633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_ee_cmd(struct device_driver *ddp, 8663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 8673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 8693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 8703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 8713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 8723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 8743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 8753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 8763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 8773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs + NES_EEPROM_COMMAND, val); 8783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 8793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 8813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 8843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_ee_data(struct device_driver *ddp, char *buf) 8873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 eeprom_data = 0xdead; 8893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 8903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 8913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 8933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 8943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff eeprom_data = nes_read32(nesdev->regs + NES_EEPROM_DATA); 8953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 8963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 8983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", eeprom_data); 9013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_ee_data(struct device_driver *ddp, 9043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 9053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 9073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 9083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 9093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 9103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 9123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 9133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 9143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 9153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs + NES_EEPROM_DATA, val); 9163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 9173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 9193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 9223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_flash_cmd(struct device_driver *ddp, char *buf) 9253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 flash_cmd = 0xdead; 9273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 9283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 9293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 9313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 9323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff flash_cmd = nes_read32(nesdev->regs + NES_FLASH_COMMAND); 9333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 9343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 9363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", flash_cmd); 9393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_flash_cmd(struct device_driver *ddp, 9423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 9433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 9453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 9463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 9473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 9483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 9503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 9513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 9523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 9533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs + NES_FLASH_COMMAND, val); 9543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 9553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 9573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 9603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_flash_data(struct device_driver *ddp, char *buf) 9633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 flash_data = 0xdead; 9653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 9663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 9673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 9693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 9703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff flash_data = nes_read32(nesdev->regs + NES_FLASH_DATA); 9713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 9723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 9743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", flash_data); 9773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_flash_data(struct device_driver *ddp, 9803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 9813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 9833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 9843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 9853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 9863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 9883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 9893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 9903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 9913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs + NES_FLASH_DATA, val); 9923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 9933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 9953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 9983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_nonidx_addr(struct device_driver *ddp, char *buf) 10013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", sysfs_nonidx_addr); 10033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_nonidx_addr(struct device_driver *ddp, 10063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 10073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 10093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') 10113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff sysfs_nonidx_addr = simple_strtoul(p, &p, 16); 10123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 10143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_nonidx_data(struct device_driver *ddp, char *buf) 10173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 nonidx_data = 0xdead; 10193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 10203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 10213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 10233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 10243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nonidx_data = nes_read32(nesdev->regs + sysfs_nonidx_addr); 10253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 10263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 10283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", nonidx_data); 10313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_nonidx_data(struct device_driver *ddp, 10343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 10353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 10373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 10383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 10393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 10403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 10423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 10433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 10443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 10453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs + sysfs_nonidx_addr, val); 10463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 10473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 10493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 10523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_idx_addr(struct device_driver *ddp, char *buf) 10553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", sysfs_idx_addr); 10573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_idx_addr(struct device_driver *ddp, 10603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 10613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 10633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') 10653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff sysfs_idx_addr = simple_strtoul(p, &p, 16); 10663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 10683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_idx_data(struct device_driver *ddp, char *buf) 10713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 idx_data = 0xdead; 10733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 10743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 10753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 10773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 10783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff idx_data = nes_read_indexed(nesdev, sysfs_idx_addr); 10793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 10803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 10823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", idx_data); 10853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_idx_data(struct device_driver *ddp, 10883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 10893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 10913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 10923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 10933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 10943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 10963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 10973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 10983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 10993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, sysfs_idx_addr, val); 11003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 11013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 11023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 11033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 11043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 11053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 11063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 11073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 11082b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 11092b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung/** 11102b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung * nes_show_wqm_quanta 11112b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung */ 11122b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tungstatic ssize_t nes_show_wqm_quanta(struct device_driver *ddp, char *buf) 11132b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung{ 11142b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung u32 wqm_quanta_value = 0xdead; 11152b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung u32 i = 0; 11162b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung struct nes_device *nesdev; 11172b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 11182b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung list_for_each_entry(nesdev, &nes_dev_list, list) { 11192b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung if (i == ee_flsh_adapter) { 11202b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung wqm_quanta_value = nesdev->nesadapter->wqm_quanta; 11212b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung break; 11222b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung } 11232b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung i++; 11242b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung } 11252b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 1126df924f833c0389c9f5206b073e87e9f5f3e857d3Roland Dreier return snprintf(buf, PAGE_SIZE, "0x%X\n", wqm_quanta_value); 11272b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung} 11282b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 11292b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 11302b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung/** 11312b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung * nes_store_wqm_quanta 11322b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung */ 11332b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tungstatic ssize_t nes_store_wqm_quanta(struct device_driver *ddp, 11342b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung const char *buf, size_t count) 11352b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung{ 11362b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung unsigned long wqm_quanta_value; 11372b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung u32 wqm_config1; 11382b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung u32 i = 0; 11392b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung struct nes_device *nesdev; 11402b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 114152f81dbaf1378faf64c3ecea5129cebf826ef126Liu Yuan if (kstrtoul(buf, 0, &wqm_quanta_value) < 0) 114252f81dbaf1378faf64c3ecea5129cebf826ef126Liu Yuan return -EINVAL; 114352f81dbaf1378faf64c3ecea5129cebf826ef126Liu Yuan 11442b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung list_for_each_entry(nesdev, &nes_dev_list, list) { 11452b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung if (i == ee_flsh_adapter) { 11462b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung nesdev->nesadapter->wqm_quanta = wqm_quanta_value; 11472b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung wqm_config1 = nes_read_indexed(nesdev, 11482b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung NES_IDX_WQM_CONFIG1); 11492b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG1, 11502b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung ((wqm_quanta_value << 1) | 11512b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung (wqm_config1 & 0x00000001))); 11522b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung break; 11532b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung } 11542b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung i++; 11552b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung } 11562b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung return strnlen(buf, count); 11572b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung} 11582b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 11593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(adapter, S_IRUSR | S_IWUSR, 11603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_adapter, nes_store_adapter); 11613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(eeprom_cmd, S_IRUSR | S_IWUSR, 11623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_ee_cmd, nes_store_ee_cmd); 11633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(eeprom_data, S_IRUSR | S_IWUSR, 11643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_ee_data, nes_store_ee_data); 11653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(flash_cmd, S_IRUSR | S_IWUSR, 11663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_flash_cmd, nes_store_flash_cmd); 11673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(flash_data, S_IRUSR | S_IWUSR, 11683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_flash_data, nes_store_flash_data); 11693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(nonidx_addr, S_IRUSR | S_IWUSR, 11703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_nonidx_addr, nes_store_nonidx_addr); 11713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(nonidx_data, S_IRUSR | S_IWUSR, 11723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_nonidx_data, nes_store_nonidx_data); 11733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(idx_addr, S_IRUSR | S_IWUSR, 11743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_idx_addr, nes_store_idx_addr); 11753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(idx_data, S_IRUSR | S_IWUSR, 11763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_idx_data, nes_store_idx_data); 11772b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tungstatic DRIVER_ATTR(wqm_quanta, S_IRUSR | S_IWUSR, 11782b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung nes_show_wqm_quanta, nes_store_wqm_quanta); 11793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 11803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_create_driver_sysfs(struct pci_driver *drv) 11813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 11823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int error; 11833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error = driver_create_file(&drv->driver, &driver_attr_adapter); 11843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_eeprom_cmd); 11853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_eeprom_data); 11863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_flash_cmd); 11873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_flash_data); 11883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_nonidx_addr); 11893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_nonidx_data); 11903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_idx_addr); 11913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_idx_data); 11922b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung error |= driver_create_file(&drv->driver, &driver_attr_wqm_quanta); 11933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return error; 11943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 11953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 11963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void nes_remove_driver_sysfs(struct pci_driver *drv) 11973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 11983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_adapter); 11993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_eeprom_cmd); 12003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_eeprom_data); 12013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_flash_cmd); 12023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_flash_data); 12033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_nonidx_addr); 12043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_nonidx_data); 12053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_idx_addr); 12063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_idx_data); 12072b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung driver_remove_file(&drv->driver, &driver_attr_wqm_quanta); 12083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 12093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 12103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 12113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_init_module - module initialization entry point 12123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 12133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int __init nes_init_module(void) 12143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 12153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int retval; 12163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int retval1; 12173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 12183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff retval = nes_cm_start(); 12193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (retval) { 12203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to start NetEffect iWARP CM.\n"); 12213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return retval; 12223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 12233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff retval = pci_register_driver(&nes_pci_driver); 12243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (retval >= 0) { 12253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff retval1 = nes_create_driver_sysfs(&nes_pci_driver); 12263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (retval1 < 0) 12273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to create NetEffect sys files.\n"); 12283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 12293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return retval; 12303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 12313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 12323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 12333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 12343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_exit_module - module unload entry point 12353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 12363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void __exit nes_exit_module(void) 12373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 12383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_cm_stop(); 12393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_remove_driver_sysfs(&nes_pci_driver); 12403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 12413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_unregister_driver(&nes_pci_driver); 12423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 12433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 12443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 12453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffmodule_init(nes_init_module); 12463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffmodule_exit(nes_exit_module); 1247