nes.c revision 633693660045b3e46a63ed618eb38a54339fbcc0
13c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/* 23c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * Copyright (c) 2006 - 2008 NetEffect, Inc. 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> 473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <asm/io.h> 483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <asm/irq.h> 493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <asm/byteorder.h> 503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <rdma/ib_smi.h> 513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <rdma/ib_verbs.h> 523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <rdma/ib_pack.h> 533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <rdma/iw_cm.h> 543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include "nes.h" 563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <net/netevent.h> 583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <net/neighbour.h> 593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <linux/route.h> 603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff#include <net/ip_fib.h> 613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_AUTHOR("NetEffect"); 633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_DESCRIPTION("NetEffect RNIC Low-level iWARP Driver"); 643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_LICENSE("Dual BSD/GPL"); 653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_VERSION(DRV_VERSION); 663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffint max_mtu = 9000; 683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffint interrupt_mod_interval = 0; 693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/* Interoperability */ 723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffint mpa_version = 1; 73de182149c31786b2b07fa408fb076599b29232a1Chien Tungmodule_param(mpa_version, int, 0644); 743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_PARM_DESC(mpa_version, "MPA version to be used int MPA Req/Resp (0 or 1)"); 753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/* Interoperability */ 773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffint disable_mpa_crc = 0; 78de182149c31786b2b07fa408fb076599b29232a1Chien Tungmodule_param(disable_mpa_crc, int, 0644); 793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_PARM_DESC(disable_mpa_crc, "Disable checking of MPA CRC"); 803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffunsigned int send_first = 0; 82de182149c31786b2b07fa408fb076599b29232a1Chien Tungmodule_param(send_first, int, 0644); 833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_PARM_DESC(send_first, "Send RDMA Message First on Active Connection"); 843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffunsigned int nes_drv_opt = 0; 87de182149c31786b2b07fa408fb076599b29232a1Chien Tungmodule_param(nes_drv_opt, int, 0644); 883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_PARM_DESC(nes_drv_opt, "Driver option parameters"); 893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffunsigned int nes_debug_level = 0; 913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffmodule_param_named(debug_level, nes_debug_level, uint, 0644); 923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_PARM_DESC(debug_level, "Enable debug output level"); 933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 942b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tungunsigned int wqm_quanta = 0x10000; 952b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tungmodule_param(wqm_quanta, int, 0644); 962b537c2824194d50072ab260f54d6fe4cb8d17e8Chien TungMODULE_PARM_DESC(wqm_quanta, "WQM quanta"); 972b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 98633693660045b3e46a63ed618eb38a54339fbcc0Chien Tungstatic unsigned int limit_maxrdreqsz; 99633693660045b3e46a63ed618eb38a54339fbcc0Chien Tungmodule_param(limit_maxrdreqsz, bool, 0644); 100633693660045b3e46a63ed618eb38a54339fbcc0Chien TungMODULE_PARM_DESC(limit_maxrdreqsz, "Limit max read request size to 256 Bytes"); 101633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung 1023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffLIST_HEAD(nes_adapter_list); 1031a855fbfb65e0b7b5cce00d7c6a61185ed765edfRoland Dreierstatic LIST_HEAD(nes_dev_list); 1043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffatomic_t qps_destroyed; 1063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic unsigned int ee_flsh_adapter; 1083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic unsigned int sysfs_nonidx_addr; 1093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic unsigned int sysfs_idx_addr; 1103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic struct pci_device_id nes_pci_table[] = { 1123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff {PCI_VENDOR_ID_NETEFFECT, PCI_DEVICE_ID_NETEFFECT_NE020, PCI_ANY_ID, PCI_ANY_ID}, 1133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff {0} 1143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff}; 1153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_DEVICE_TABLE(pci, nes_pci_table); 1173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_inetaddr_event(struct notifier_block *, unsigned long, void *); 1193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_net_event(struct notifier_block *, unsigned long, void *); 1203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_notifiers_registered; 1213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic struct notifier_block nes_inetaddr_notifier = { 1243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .notifier_call = nes_inetaddr_event 1253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff}; 1263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic struct notifier_block nes_net_notifier = { 1283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .notifier_call = nes_net_event 1293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff}; 1303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 1353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_inetaddr_event 1363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 1373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_inetaddr_event(struct notifier_block *notifier, 1383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned long event, void *ptr) 1393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 1403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct in_ifaddr *ifa = ptr; 1413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct net_device *event_netdev = ifa->ifa_dev->dev; 1423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 1433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct net_device *netdev; 1443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_vnic *nesvnic; 1453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned int addr; 1463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned int mask; 1473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff addr = ntohl(ifa->ifa_address); 1493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff mask = ntohl(ifa->ifa_mask); 150e447703123d817b3f802c6eb69171d5342c8832eRoland Dreier nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address " NIPQUAD_FMT 151e447703123d817b3f802c6eb69171d5342c8832eRoland Dreier ", netmask " NIPQUAD_FMT ".\n", 152e447703123d817b3f802c6eb69171d5342c8832eRoland Dreier HIPQUAD(addr), HIPQUAD(mask)); 1533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 1543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "Nesdev list entry = 0x%p. (%s)\n", 1553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev, nesdev->netdev[0]->name); 1563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev = nesdev->netdev[0]; 1573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesvnic = netdev_priv(netdev); 1583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (netdev == event_netdev) { 1593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesvnic->rdma_enabled == 0) { 1603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "Returning without processing event for %s since" 1613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff " RDMA is not enabled.\n", 1623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev->name); 1633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_OK; 1643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 1653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* we have ifa->ifa_address/mask here if we need it */ 1663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff switch (event) { 1673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff case NETDEV_DOWN: 1683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "event:DOWN\n"); 1693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, 1703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)), 0); 1713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_manage_arp_cache(netdev, netdev->dev_addr, 1733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ntohl(nesvnic->local_ipaddr), NES_ARP_DELETE); 1743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesvnic->local_ipaddr = 0; 1753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 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 } 1843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Add the address to the IP table */ 1853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesvnic->local_ipaddr = ifa->ifa_address; 1863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, 1883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)), 1893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ntohl(ifa->ifa_address)); 1903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_manage_arp_cache(netdev, netdev->dev_addr, 1913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ntohl(nesvnic->local_ipaddr), NES_ARP_ADD); 1923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_OK; 1933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 1943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff default: 1953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 1963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 1973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 1983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 1993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_DONE; 2013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 2023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 2053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_net_event 2063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 2073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_net_event(struct notifier_block *notifier, 2083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned long event, void *ptr) 2093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 2103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct neighbour *neigh = ptr; 2113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 2123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct net_device *netdev; 2133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_vnic *nesvnic; 2143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff switch (event) { 2163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff case NETEVENT_NEIGH_UPDATE: 2173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 2183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* nes_debug(NES_DBG_NETDEV, "Nesdev list entry = 0x%p.\n", nesdev); */ 2193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev = nesdev->netdev[0]; 2203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesvnic = netdev_priv(netdev); 2213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (netdev == neigh->dev) { 2223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesvnic->rdma_enabled == 0) { 2233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "Skipping device %s since no RDMA\n", 2243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev->name); 2253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 2263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (neigh->nud_state & NUD_VALID) { 2273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_manage_arp_cache(neigh->dev, neigh->ha, 2283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ntohl(*(__be32 *)neigh->primary_key), NES_ARP_ADD); 2293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 2303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_manage_arp_cache(neigh->dev, neigh->ha, 2313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ntohl(*(__be32 *)neigh->primary_key), NES_ARP_DELETE); 2323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_OK; 2353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 2383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff default: 2393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "NETEVENT_ %lu undefined\n", event); 2403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 2413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_DONE; 2443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 2453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 2483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_add_ref 2493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 2503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffvoid nes_add_ref(struct ib_qp *ibqp) 2513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 2523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_qp *nesqp; 2533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp = to_nesqp(ibqp); 2553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_QP, "Bumping refcount for QP%u. Pre-inc value = %u\n", 2563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ibqp->qp_num, atomic_read(&nesqp->refcount)); 2573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff atomic_inc(&nesqp->refcount); 2583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 2593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void nes_cqp_rem_ref_callback(struct nes_device *nesdev, struct nes_cqp_request *cqp_request) 2613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 2623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned long flags; 2633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_qp *nesqp = cqp_request->cqp_callback_pointer; 2643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_adapter *nesadapter = nesdev->nesadapter; 2653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 qp_id; 2663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff atomic_inc(&qps_destroyed); 2683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Free the control structures */ 2703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff qp_id = nesqp->hwqp.qp_id; 2723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesqp->pbl_vbase) { 2733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, 2743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp->hwqp.q2_vbase, nesqp->hwqp.q2_pbase); 2753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff spin_lock_irqsave(&nesadapter->pbl_lock, flags); 2763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesadapter->free_256pbl++; 2773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); 2783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_free_consistent(nesdev->pcidev, 256, nesqp->pbl_vbase, nesqp->pbl_pbase); 2793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp->pbl_vbase = NULL; 2803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 2823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, 2833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp->hwqp.sq_vbase, nesqp->hwqp.sq_pbase); 2843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_free_resource(nesadapter, nesadapter->allocated_qps, nesqp->hwqp.qp_id); 2863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2876492cdf3a24fd620660c399745b5e169a0ed27d6Faisal Latif nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = NULL; 2883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff kfree(nesqp->allocated_buffer); 2893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 2913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 2933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_rem_ref 2943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 2953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffvoid nes_rem_ref(struct ib_qp *ibqp) 2963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 2973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u64 u64temp; 2983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_qp *nesqp; 2993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_vnic *nesvnic = to_nesvnic(ibqp->device); 3003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev = nesvnic->nesdev; 3013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_hw_cqp_wqe *cqp_wqe; 3023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_cqp_request *cqp_request; 3033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 opcode; 3043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp = to_nesqp(ibqp); 3063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (atomic_read(&nesqp->refcount) == 0) { 3083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_INFO PFX "%s: Reference count already 0 for QP%d, last aeq = 0x%04X.\n", 3093371836383d63b627b228875f5ac63023cbf11d2Harvey Harrison __func__, ibqp->qp_num, nesqp->last_aeq); 3103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff BUG(); 3113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 3123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (atomic_dec_and_test(&nesqp->refcount)) { 3143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Destroy the QP */ 3153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_request = nes_get_cqp_request(nesdev); 3163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (cqp_request == NULL) { 3173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n"); 3183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return; 3193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 3203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_request->waiting = 0; 3213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_request->callback = 1; 3223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_request->cqp_callback = nes_cqp_rem_ref_callback; 3233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_request->cqp_callback_pointer = nesqp; 3243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_wqe = &cqp_request->cqp_wqe; 3253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_fill_init_cqp_wqe(cqp_wqe, nesdev); 3273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff opcode = NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_IWARP; 3283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesqp->hte_added) { 3303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff opcode |= NES_CQP_QP_DEL_HTE; 3313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp->hte_added = 0; 3323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 3333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode); 3343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id); 3353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u64temp = (u64)nesqp->nesqp_context_pbase; 3363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp); 3378294f29767c53e97664a27db9974adea8e2ea95bRoland Dreier nes_post_cqp_request(nesdev, cqp_request); 3383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 3393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 3403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 3433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_get_qp 3443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 3453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstruct ib_qp *nes_get_qp(struct ib_device *device, int qpn) 3463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 3473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_vnic *nesvnic = to_nesvnic(device); 3483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev = nesvnic->nesdev; 3493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_adapter *nesadapter = nesdev->nesadapter; 3503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((qpn < NES_FIRST_QPN) || (qpn >= (NES_FIRST_QPN + nesadapter->max_qp))) 3523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NULL; 3533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return &nesadapter->qp_table[qpn - NES_FIRST_QPN]->ibqp; 3553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 3563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 3593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_print_macaddr 3603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 3613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void nes_print_macaddr(struct net_device *netdev) 3623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 3632bd01c5d2ed04838d50548cb7b955505a20ac0bdRoland Dreier DECLARE_MAC_BUF(mac); 3643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3652bd01c5d2ed04838d50548cb7b955505a20ac0bdRoland Dreier nes_debug(NES_DBG_INIT, "%s: %s, IRQ %u\n", 3662bd01c5d2ed04838d50548cb7b955505a20ac0bdRoland Dreier netdev->name, print_mac(mac, netdev->dev_addr), netdev->irq); 3672bd01c5d2ed04838d50548cb7b955505a20ac0bdRoland Dreier} 3683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 3703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_interrupt - handle interrupts 3713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 3723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic irqreturn_t nes_interrupt(int irq, void *dev_id) 3733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 3743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev = (struct nes_device *)dev_id; 3753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int handled = 0; 3763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 int_mask; 3773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 int_req; 3783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 int_stat; 3793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 intf_int_stat; 3803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 timer_stat; 3813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesdev->msi_enabled) { 3833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* No need to read the interrupt pending register if msi is enabled */ 3843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff handled = 1; 3853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 3863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (unlikely(nesdev->nesadapter->hw_rev == NE020_REV)) { 3873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Master interrupt enable provides synchronization for kicking off bottom half 3883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff when interrupt sharing is going on */ 3893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int_mask = nes_read32(nesdev->regs + NES_INT_MASK); 3903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (int_mask & 0x80000000) { 3913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Check interrupt status to see if this might be ours */ 3923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int_stat = nes_read32(nesdev->regs + NES_INT_STAT); 3933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int_req = nesdev->int_req; 3943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (int_stat&int_req) { 3953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* if interesting CEQ or AEQ is pending, claim the interrupt */ 3963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((int_stat&int_req) & (~(NES_INT_TIMER|NES_INT_INTF))) { 3973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff handled = 1; 3983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 3993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (((int_stat & int_req) & NES_INT_TIMER) == NES_INT_TIMER) { 4003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Timer might be running but might be for another function */ 4013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff timer_stat = nes_read32(nesdev->regs + NES_TIMER_STAT); 4023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((timer_stat & nesdev->timer_int_req) != 0) { 4033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff handled = 1; 4043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((((int_stat & int_req) & NES_INT_INTF) == NES_INT_INTF) && 4073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (handled == 0)) { 4083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff intf_int_stat = nes_read32(nesdev->regs+NES_INTF_INT_STAT); 4093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((intf_int_stat & nesdev->intf_int_req) != 0) { 4103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff handled = 1; 4113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (handled) { 4153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs+NES_INT_MASK, int_mask & (~0x80000000)); 4163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int_mask = nes_read32(nesdev->regs+NES_INT_MASK); 4173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Save off the status to save an additional read */ 4183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->int_stat = int_stat; 4193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->napi_isr_ran = 1; 4203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 4243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff handled = nes_read32(nesdev->regs+NES_INT_PENDING); 4253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (handled) { 4293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_napi_isr(nesdev) == 0) { 4313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff tasklet_schedule(&nesdev->dpc_tasklet); 4323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return IRQ_HANDLED; 4353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 4363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return IRQ_NONE; 4373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 4393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 4423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_probe - Device initialization 4433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 4443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) 4453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 4463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct net_device *netdev = NULL; 4473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev = NULL; 4483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int ret = 0; 4493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_vnic *nesvnic = NULL; 4503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff void __iomem *mmio_regs = NULL; 4513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u8 hw_rev; 4523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff assert(pcidev != NULL); 4543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff assert(ent != NULL); 4553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_INFO PFX "NetEffect RNIC driver v%s loading. (%s)\n", 4573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff DRV_VERSION, pci_name(pcidev)); 4583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = pci_enable_device(pcidev); 4603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 4613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to enable PCI device. (%s)\n", pci_name(pcidev)); 4623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail0; 4633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "BAR0 (@0x%08lX) size = 0x%lX bytes\n", 4663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (long unsigned int)pci_resource_start(pcidev, BAR_0), 4673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (long unsigned int)pci_resource_len(pcidev, BAR_0)); 4683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "BAR1 (@0x%08lX) size = 0x%lX bytes\n", 4693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (long unsigned int)pci_resource_start(pcidev, BAR_1), 4703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (long unsigned int)pci_resource_len(pcidev, BAR_1)); 4713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Make sure PCI base addr are MMIO */ 4733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (!(pci_resource_flags(pcidev, BAR_0) & IORESOURCE_MEM) || 4743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff !(pci_resource_flags(pcidev, BAR_1) & IORESOURCE_MEM)) { 4753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "PCI regions not an MMIO resource\n"); 4763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = -ENODEV; 4773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail1; 4783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Reserve PCI I/O and memory resources */ 4813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = pci_request_regions(pcidev, DRV_NAME); 4823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 4833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to request regions. (%s)\n", pci_name(pcidev)); 4843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail1; 4853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((sizeof(dma_addr_t) > 4)) { 4883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = pci_set_dma_mask(pcidev, DMA_64BIT_MASK); 4893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret < 0) { 4903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "64b DMA mask configuration failed\n"); 4913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail2; 4923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = pci_set_consistent_dma_mask(pcidev, DMA_64BIT_MASK); 4943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 4953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "64b DMA consistent mask configuration failed\n"); 4963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail2; 4973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 4993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = pci_set_dma_mask(pcidev, DMA_32BIT_MASK); 5003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret < 0) { 5013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "32b DMA mask configuration failed\n"); 5023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail2; 5033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = pci_set_consistent_dma_mask(pcidev, DMA_32BIT_MASK); 5053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 5063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "32b DMA consistent mask configuration failed\n"); 5073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail2; 5083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_set_master(pcidev); 5123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Allocate hardware structure */ 5143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev = kzalloc(sizeof(struct nes_device), GFP_KERNEL); 5153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (!nesdev) { 5163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "%s: Unable to alloc hardware struct\n", pci_name(pcidev)); 5173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = -ENOMEM; 5183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail2; 5193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "Allocated nes device at %p\n", nesdev); 5223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->pcidev = pcidev; 5233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_set_drvdata(pcidev, nesdev); 5243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_read_config_byte(pcidev, 0x0008, &hw_rev); 5263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "hw_rev=%u\n", hw_rev); 5273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff spin_lock_init(&nesdev->indexed_regs_lock); 5293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Remap the PCI registers in adapter BAR0 to kernel VA space */ 5313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff mmio_regs = ioremap_nocache(pci_resource_start(pcidev, BAR_0), sizeof(mmio_regs)); 5323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (mmio_regs == NULL) { 5333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to remap BAR0\n"); 5343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = -EIO; 5353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail3; 5363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->regs = mmio_regs; 5383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->index_reg = 0x50 + (PCI_FUNC(pcidev->devfn)*8) + mmio_regs; 5393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Ensure interrupts are disabled */ 5413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs+NES_INT_MASK, 0x7fffffff); 5423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_drv_opt & NES_DRV_OPT_ENABLE_MSI) { 5443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (!pci_enable_msi(nesdev->pcidev)) { 5453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->msi_enabled = 1; 5463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "MSI is enabled for device %s\n", 5473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_name(pcidev)); 5483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 5493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "MSI is disabled by linux for device %s\n", 5503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_name(pcidev)); 5513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 5533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "MSI not requested due to driver options for device %s\n", 5543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_name(pcidev)); 5553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->csr_start = pci_resource_start(nesdev->pcidev, BAR_0); 5583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->doorbell_region = pci_resource_start(nesdev->pcidev, BAR_1); 5593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Init the adapter */ 5613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter = nes_init_adapter(nesdev, hw_rev); 5623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (!nesdev->nesadapter) { 5633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to initialize adapter.\n"); 5643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = -ENOMEM; 5653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail5; 5663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 567a4435febd4c0f14b25159dca249ecf91301c7c76Adrian Bunk nesdev->nesadapter->et_rx_coalesce_usecs_irq = interrupt_mod_interval; 5682b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung nesdev->nesadapter->wqm_quanta = wqm_quanta; 5693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* nesdev->base_doorbell_index = 5713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter->pd_config_base[PCI_FUNC(nesdev->pcidev->devfn)]; */ 5723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->base_doorbell_index = 1; 5733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->doorbell_start = nesdev->nesadapter->doorbell_start; 574fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung if (nesdev->nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) { 575fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung switch (PCI_FUNC(nesdev->pcidev->devfn) % 576fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->nesadapter->port_count) { 577fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung case 1: 578fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->mac_index = 2; 579fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung break; 580fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung case 2: 581fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->mac_index = 1; 582fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung break; 583fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung case 3: 584fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->mac_index = 3; 585fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung break; 586fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung case 0: 587fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung default: 588fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->mac_index = 0; 589fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung } 590fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung } else { 591fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->mac_index = PCI_FUNC(nesdev->pcidev->devfn) % 592fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->nesadapter->port_count; 593fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung } 5943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 595633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung if ((limit_maxrdreqsz || 596633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung ((nesdev->nesadapter->phy_type[0] == NES_PHY_TYPE_GLADIUS) && 597633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung (hw_rev == NE020_REV1))) && 598633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung (pcie_get_readrq(pcidev) > 256)) { 599633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung if (pcie_set_readrq(pcidev, 256)) 600633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung printk(KERN_ERR PFX "Unable to set max read request" 601633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung " to 256 bytes\n"); 602633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung else 603633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung nes_debug(NES_DBG_INIT, "Max read request size set" 604633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung " to 256 bytes\n"); 605633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung } 606633693660045b3e46a63ed618eb38a54339fbcc0Chien Tung 6073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff tasklet_init(&nesdev->dpc_tasklet, nes_dpc, (unsigned long)nesdev); 6083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* bring up the Control QP */ 6103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_init_cqp(nesdev)) { 6113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = -ENODEV; 6123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail6; 6133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Arm the CCQ */ 6163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT | 6173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff PCI_FUNC(nesdev->pcidev->devfn)); 6183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_read32(nesdev->regs+NES_CQE_ALLOC); 6193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Enable the interrupts */ 6213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->int_req = (0x101 << PCI_FUNC(nesdev->pcidev->devfn)) | 6223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (1 << (PCI_FUNC(nesdev->pcidev->devfn)+16)); 6233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (PCI_FUNC(nesdev->pcidev->devfn) < 4) { 624fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung nesdev->int_req |= (1 << (PCI_FUNC(nesdev->mac_index)+24)); 6253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* TODO: This really should be the first driver to load, not function 0 */ 6283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (PCI_FUNC(nesdev->pcidev->devfn) == 0) { 6293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* pick up PCI and critical errors if the first driver to load */ 6303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->intf_int_req = NES_INTF_INT_PCIERR | NES_INTF_INT_CRITERR; 6313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->int_req |= NES_INT_INTF; 6323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 6333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->intf_int_req = 0; 6343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->intf_int_req |= (1 << (PCI_FUNC(nesdev->pcidev->devfn)+16)); 6363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS0, 0); 6373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS1, 0); 6383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS2, 0x00001265); 6393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS4, 0x18021804); 6403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS3, 0x17801790); 6423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* deal with both periodic and one_shot */ 6443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->timer_int_req = 0x101 << PCI_FUNC(nesdev->pcidev->devfn); 6453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter->timer_int_req |= nesdev->timer_int_req; 6463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "setting int_req for function %u, nesdev = 0x%04X, adapter = 0x%04X\n", 6473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff PCI_FUNC(nesdev->pcidev->devfn), 6483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->timer_int_req, nesdev->nesadapter->timer_int_req); 6493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req)); 6513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_add_tail(&nesdev->list, &nes_dev_list); 6533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Request an interrupt line for the driver */ 6553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = request_irq(pcidev->irq, nes_interrupt, IRQF_SHARED, DRV_NAME, nesdev); 6563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 6573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "%s: requested IRQ %u is busy\n", 6583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_name(pcidev), pcidev->irq); 6593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail65; 6603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req); 6633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_notifiers_registered == 0) { 6653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff register_inetaddr_notifier(&nes_inetaddr_notifier); 6663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff register_netevent_notifier(&nes_net_notifier); 6673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_notifiers_registered++; 6693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Initialize network devices */ 6713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL) { 6723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail7; 6733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Register network device */ 6763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = register_netdev(netdev); 6773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 6783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to register netdev, ret = %d\n", ret); 6793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_netdev_destroy(netdev); 6803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail7; 6813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_print_macaddr(netdev); 6843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* create a CM core for this netdev */ 6853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesvnic = netdev_priv(netdev); 6863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->netdev_count++; 6883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter->netdev_count++; 6893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "%s: NetEffect RNIC driver successfully loaded.\n", 6923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_name(pcidev)); 6933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return 0; 6943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail7: 6963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "bail7\n"); 6973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff while (nesdev->netdev_count > 0) { 6983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->netdev_count--; 6993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter->netdev_count--; 7003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_netdev(nesdev->netdev[nesdev->netdev_count]); 7023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_netdev_destroy(nesdev->netdev[nesdev->netdev_count]); 7033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "netdev_count=%d, nesadapter->netdev_count=%d\n", 7063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->netdev_count, nesdev->nesadapter->netdev_count); 7073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_notifiers_registered--; 7093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_notifiers_registered == 0) { 7103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_netevent_notifier(&nes_net_notifier); 7113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_inetaddr_notifier(&nes_inetaddr_notifier); 7123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_del(&nesdev->list); 7153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_destroy_cqp(nesdev); 7163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail65: 7183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "bail65\n"); 7193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff free_irq(pcidev->irq, nesdev); 7203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesdev->msi_enabled) { 7213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_disable_msi(pcidev); 7223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail6: 7243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "bail6\n"); 7253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff tasklet_kill(&nesdev->dpc_tasklet); 7263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Deallocate the Adapter Structure */ 7273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_destroy_adapter(nesdev->nesadapter); 7283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail5: 7303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "bail5\n"); 7313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff iounmap(nesdev->regs); 7323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail3: 7343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "bail3\n"); 7353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff kfree(nesdev); 7363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail2: 7383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_release_regions(pcidev); 7393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail1: 7413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_disable_device(pcidev); 7423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail0: 7443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return ret; 7453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 7463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 7493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_remove - unload from kernel 7503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 7513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void __devexit nes_remove(struct pci_dev *pcidev) 7523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 7533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev = pci_get_drvdata(pcidev); 7543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct net_device *netdev; 7553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int netdev_index = 0; 7563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesdev->netdev_count) { 7583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev = nesdev->netdev[netdev_index]; 7593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (netdev) { 7603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netif_stop_queue(netdev); 7613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_netdev(netdev); 7623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_netdev_destroy(netdev); 7633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->netdev[netdev_index] = NULL; 7653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->netdev_count--; 7663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter->netdev_count--; 7673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_notifiers_registered--; 7713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_notifiers_registered == 0) { 7723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_netevent_notifier(&nes_net_notifier); 7733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_inetaddr_notifier(&nes_inetaddr_notifier); 7743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_del(&nesdev->list); 7773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_destroy_cqp(nesdev); 7784cd1e5eb3cbe6e0cc934959770b4c60eac6ecf66Roland Dreier 7794cd1e5eb3cbe6e0cc934959770b4c60eac6ecf66Roland Dreier free_irq(pcidev->irq, nesdev); 7803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff tasklet_kill(&nesdev->dpc_tasklet); 7813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Deallocate the Adapter Structure */ 7833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_destroy_adapter(nesdev->nesadapter); 7843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesdev->msi_enabled) { 7863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_disable_msi(pcidev); 7873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff iounmap(nesdev->regs); 7903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff kfree(nesdev); 7913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* nes_debug(NES_DBG_SHUTDOWN, "calling pci_release_regions.\n"); */ 7933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_release_regions(pcidev); 7943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_disable_device(pcidev); 7953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_set_drvdata(pcidev, NULL); 7963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 7973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic struct pci_driver nes_pci_driver = { 8003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .name = DRV_NAME, 8013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .id_table = nes_pci_table, 8023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .probe = nes_probe, 8033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .remove = __devexit_p(nes_remove), 8043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff}; 8053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_adapter(struct device_driver *ddp, char *buf) 8073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned int devfn = 0xffffffff; 8093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned char bus_number = 0xff; 8103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned int i = 0; 8113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 8123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 8143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 815fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung devfn = nesdev->pcidev->devfn; 816fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung bus_number = nesdev->pcidev->bus->number; 8173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 8183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 8203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 822fcb7ad31beda842804167f0645ca54660713bcd6Chien Tung return snprintf(buf, PAGE_SIZE, "%x:%x\n", bus_number, devfn); 8233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_adapter(struct device_driver *ddp, 8263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 8273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 8293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ee_flsh_adapter = simple_strtoul(p, &p, 10); 8313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 8323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_ee_cmd(struct device_driver *ddp, char *buf) 8353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 eeprom_cmd = 0xdead; 8373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 8383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 8393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 8413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 8423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff eeprom_cmd = nes_read32(nesdev->regs + NES_EEPROM_COMMAND); 8433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 8443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 8463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", eeprom_cmd); 8483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_ee_cmd(struct device_driver *ddp, 8513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 8523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 8543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 8553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 8563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 8573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 8593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 8603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 8613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 8623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs + NES_EEPROM_COMMAND, val); 8633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 8643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 8663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 8693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_ee_data(struct device_driver *ddp, char *buf) 8723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 eeprom_data = 0xdead; 8743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 8753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 8763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 8783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 8793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff eeprom_data = nes_read32(nesdev->regs + NES_EEPROM_DATA); 8803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 8813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 8833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", eeprom_data); 8863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_ee_data(struct device_driver *ddp, 8893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 8903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 8923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 8933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 8943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 8953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 8973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 8983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 8993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 9003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs + NES_EEPROM_DATA, val); 9013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 9023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 9043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 9073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_flash_cmd(struct device_driver *ddp, char *buf) 9103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 flash_cmd = 0xdead; 9123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 9133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 9143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 9163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 9173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff flash_cmd = nes_read32(nesdev->regs + NES_FLASH_COMMAND); 9183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 9193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 9213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", flash_cmd); 9243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_flash_cmd(struct device_driver *ddp, 9273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 9283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 9303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 9313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 9323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 9333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 9353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 9363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 9373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 9383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs + NES_FLASH_COMMAND, val); 9393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 9403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 9423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 9453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_flash_data(struct device_driver *ddp, char *buf) 9483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 flash_data = 0xdead; 9503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 9513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 9523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 9543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 9553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff flash_data = nes_read32(nesdev->regs + NES_FLASH_DATA); 9563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 9573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 9593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", flash_data); 9623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_flash_data(struct device_driver *ddp, 9653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 9663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 9683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 9693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 9703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 9713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 9733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 9743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 9753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 9763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs + NES_FLASH_DATA, val); 9773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 9783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 9803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 9833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_nonidx_addr(struct device_driver *ddp, char *buf) 9863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", sysfs_nonidx_addr); 9883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_nonidx_addr(struct device_driver *ddp, 9913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 9923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 9943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') 9963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff sysfs_nonidx_addr = simple_strtoul(p, &p, 16); 9973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 9993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_nonidx_data(struct device_driver *ddp, char *buf) 10023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 nonidx_data = 0xdead; 10043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 10053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 10063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 10083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 10093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nonidx_data = nes_read32(nesdev->regs + sysfs_nonidx_addr); 10103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 10113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 10133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", nonidx_data); 10163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_nonidx_data(struct device_driver *ddp, 10193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 10203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 10223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 10233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 10243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 10253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 10273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 10283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 10293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 10303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs + sysfs_nonidx_addr, val); 10313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 10323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 10343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 10373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_idx_addr(struct device_driver *ddp, char *buf) 10403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", sysfs_idx_addr); 10423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_idx_addr(struct device_driver *ddp, 10453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 10463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 10483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') 10503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff sysfs_idx_addr = simple_strtoul(p, &p, 16); 10513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 10533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_idx_data(struct device_driver *ddp, char *buf) 10563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 idx_data = 0xdead; 10583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 10593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 10603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 10623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 10633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff idx_data = nes_read_indexed(nesdev, sysfs_idx_addr); 10643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 10653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 10673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", idx_data); 10703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_idx_data(struct device_driver *ddp, 10733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 10743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 10763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 10773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 10783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 10793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 10813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 10823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 10833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 10843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, sysfs_idx_addr, val); 10853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 10863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 10883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 10913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10932b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 10942b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung/** 10952b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung * nes_show_wqm_quanta 10962b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung */ 10972b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tungstatic ssize_t nes_show_wqm_quanta(struct device_driver *ddp, char *buf) 10982b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung{ 10992b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung u32 wqm_quanta_value = 0xdead; 11002b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung u32 i = 0; 11012b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung struct nes_device *nesdev; 11022b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 11032b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung list_for_each_entry(nesdev, &nes_dev_list, list) { 11042b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung if (i == ee_flsh_adapter) { 11052b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung wqm_quanta_value = nesdev->nesadapter->wqm_quanta; 11062b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung break; 11072b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung } 11082b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung i++; 11092b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung } 11102b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 11112b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung return snprintf(buf, PAGE_SIZE, "0x%X\n", wqm_quanta); 11122b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung} 11132b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 11142b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 11152b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung/** 11162b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung * nes_store_wqm_quanta 11172b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung */ 11182b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tungstatic ssize_t nes_store_wqm_quanta(struct device_driver *ddp, 11192b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung const char *buf, size_t count) 11202b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung{ 11212b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung unsigned long wqm_quanta_value; 11222b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung u32 wqm_config1; 11232b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung u32 i = 0; 11242b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung struct nes_device *nesdev; 11252b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 11262b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung strict_strtoul(buf, 0, &wqm_quanta_value); 11272b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung list_for_each_entry(nesdev, &nes_dev_list, list) { 11282b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung if (i == ee_flsh_adapter) { 11292b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung nesdev->nesadapter->wqm_quanta = wqm_quanta_value; 11302b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung wqm_config1 = nes_read_indexed(nesdev, 11312b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung NES_IDX_WQM_CONFIG1); 11322b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG1, 11332b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung ((wqm_quanta_value << 1) | 11342b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung (wqm_config1 & 0x00000001))); 11352b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung break; 11362b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung } 11372b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung i++; 11382b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung } 11392b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung return strnlen(buf, count); 11402b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung} 11412b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung 11423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(adapter, S_IRUSR | S_IWUSR, 11433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_adapter, nes_store_adapter); 11443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(eeprom_cmd, S_IRUSR | S_IWUSR, 11453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_ee_cmd, nes_store_ee_cmd); 11463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(eeprom_data, S_IRUSR | S_IWUSR, 11473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_ee_data, nes_store_ee_data); 11483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(flash_cmd, S_IRUSR | S_IWUSR, 11493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_flash_cmd, nes_store_flash_cmd); 11503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(flash_data, S_IRUSR | S_IWUSR, 11513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_flash_data, nes_store_flash_data); 11523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(nonidx_addr, S_IRUSR | S_IWUSR, 11533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_nonidx_addr, nes_store_nonidx_addr); 11543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(nonidx_data, S_IRUSR | S_IWUSR, 11553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_nonidx_data, nes_store_nonidx_data); 11563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(idx_addr, S_IRUSR | S_IWUSR, 11573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_idx_addr, nes_store_idx_addr); 11583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(idx_data, S_IRUSR | S_IWUSR, 11593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_idx_data, nes_store_idx_data); 11602b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tungstatic DRIVER_ATTR(wqm_quanta, S_IRUSR | S_IWUSR, 11612b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung nes_show_wqm_quanta, nes_store_wqm_quanta); 11623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 11633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_create_driver_sysfs(struct pci_driver *drv) 11643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 11653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int error; 11663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error = driver_create_file(&drv->driver, &driver_attr_adapter); 11673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_eeprom_cmd); 11683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_eeprom_data); 11693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_flash_cmd); 11703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_flash_data); 11713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_nonidx_addr); 11723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_nonidx_data); 11733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_idx_addr); 11743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_idx_data); 11752b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung error |= driver_create_file(&drv->driver, &driver_attr_wqm_quanta); 11763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return error; 11773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 11783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 11793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void nes_remove_driver_sysfs(struct pci_driver *drv) 11803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 11813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_adapter); 11823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_eeprom_cmd); 11833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_eeprom_data); 11843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_flash_cmd); 11853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_flash_data); 11863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_nonidx_addr); 11873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_nonidx_data); 11883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_idx_addr); 11893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_idx_data); 11902b537c2824194d50072ab260f54d6fe4cb8d17e8Chien Tung driver_remove_file(&drv->driver, &driver_attr_wqm_quanta); 11913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 11923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 11933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 11943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_init_module - module initialization entry point 11953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 11963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int __init nes_init_module(void) 11973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 11983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int retval; 11993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int retval1; 12003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 12013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff retval = nes_cm_start(); 12023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (retval) { 12033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to start NetEffect iWARP CM.\n"); 12043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return retval; 12053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 12063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff retval = pci_register_driver(&nes_pci_driver); 12073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (retval >= 0) { 12083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff retval1 = nes_create_driver_sysfs(&nes_pci_driver); 12093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (retval1 < 0) 12103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to create NetEffect sys files.\n"); 12113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 12123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return retval; 12133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 12143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 12153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 12163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 12173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_exit_module - module unload entry point 12183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 12193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void __exit nes_exit_module(void) 12203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 12213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_cm_stop(); 12223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_remove_driver_sysfs(&nes_pci_driver); 12233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 12243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_unregister_driver(&nes_pci_driver); 12253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 12263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 12273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 12283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffmodule_init(nes_init_module); 12293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffmodule_exit(nes_exit_module); 1230