nes.c revision a4435febd4c0f14b25159dca249ecf91301c7c76
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 nics_per_function = 1; 693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffint interrupt_mod_interval = 0; 703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/* Interoperability */ 733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffint mpa_version = 1; 743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffmodule_param(mpa_version, int, 0); 753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_PARM_DESC(mpa_version, "MPA version to be used int MPA Req/Resp (0 or 1)"); 763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/* Interoperability */ 783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffint disable_mpa_crc = 0; 793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffmodule_param(disable_mpa_crc, int, 0); 803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_PARM_DESC(disable_mpa_crc, "Disable checking of MPA CRC"); 813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffunsigned int send_first = 0; 833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffmodule_param(send_first, int, 0); 843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_PARM_DESC(send_first, "Send RDMA Message First on Active Connection"); 853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffunsigned int nes_drv_opt = 0; 883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffmodule_param(nes_drv_opt, int, 0); 893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_PARM_DESC(nes_drv_opt, "Driver option parameters"); 903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffunsigned int nes_debug_level = 0; 923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffmodule_param_named(debug_level, nes_debug_level, uint, 0644); 933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_PARM_DESC(debug_level, "Enable debug output level"); 943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffLIST_HEAD(nes_adapter_list); 963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffLIST_HEAD(nes_dev_list); 973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffatomic_t qps_destroyed; 993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffatomic_t cqp_reqs_allocated; 1003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffatomic_t cqp_reqs_freed; 1013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffatomic_t cqp_reqs_dynallocated; 1023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffatomic_t cqp_reqs_dynfreed; 1033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffatomic_t cqp_reqs_queued; 1043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffatomic_t cqp_reqs_redriven; 1053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void nes_print_macaddr(struct net_device *netdev); 1073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic irqreturn_t nes_interrupt(int, void *); 1083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int __devinit nes_probe(struct pci_dev *, const struct pci_device_id *); 1093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void __devexit nes_remove(struct pci_dev *); 1103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int __init nes_init_module(void); 1113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void __exit nes_exit_module(void); 1123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic unsigned int ee_flsh_adapter; 1133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic unsigned int sysfs_nonidx_addr; 1143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic unsigned int sysfs_idx_addr; 1153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic struct pci_device_id nes_pci_table[] = { 1173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff {PCI_VENDOR_ID_NETEFFECT, PCI_DEVICE_ID_NETEFFECT_NE020, PCI_ANY_ID, PCI_ANY_ID}, 1183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff {0} 1193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff}; 1203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn StreiffMODULE_DEVICE_TABLE(pci, nes_pci_table); 1223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_inetaddr_event(struct notifier_block *, unsigned long, void *); 1243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_net_event(struct notifier_block *, unsigned long, void *); 1253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_notifiers_registered; 1263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic struct notifier_block nes_inetaddr_notifier = { 1293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .notifier_call = nes_inetaddr_event 1303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff}; 1313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic struct notifier_block nes_net_notifier = { 1333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .notifier_call = nes_net_event 1343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff}; 1353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 1403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_inetaddr_event 1413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 1423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_inetaddr_event(struct notifier_block *notifier, 1433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned long event, void *ptr) 1443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 1453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct in_ifaddr *ifa = ptr; 1463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct net_device *event_netdev = ifa->ifa_dev->dev; 1473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 1483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct net_device *netdev; 1493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_vnic *nesvnic; 1503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned int addr; 1513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned int mask; 1523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff addr = ntohl(ifa->ifa_address); 1543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff mask = ntohl(ifa->ifa_mask); 1553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address %08X, netmask %08X.\n", 1563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff addr, mask); 1573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 1583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "Nesdev list entry = 0x%p. (%s)\n", 1593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev, nesdev->netdev[0]->name); 1603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev = nesdev->netdev[0]; 1613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesvnic = netdev_priv(netdev); 1623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (netdev == event_netdev) { 1633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesvnic->rdma_enabled == 0) { 1643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "Returning without processing event for %s since" 1653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff " RDMA is not enabled.\n", 1663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev->name); 1673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_OK; 1683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 1693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* we have ifa->ifa_address/mask here if we need it */ 1703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff switch (event) { 1713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff case NETDEV_DOWN: 1723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "event:DOWN\n"); 1733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, 1743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)), 0); 1753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_manage_arp_cache(netdev, netdev->dev_addr, 1773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ntohl(nesvnic->local_ipaddr), NES_ARP_DELETE); 1783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesvnic->local_ipaddr = 0; 1793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_OK; 1803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 1813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff case NETDEV_UP: 1823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "event:UP\n"); 1833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesvnic->local_ipaddr != 0) { 1853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "Interface already has local_ipaddr\n"); 1863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_OK; 1873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 1883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Add the address to the IP table */ 1893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesvnic->local_ipaddr = ifa->ifa_address; 1903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 1913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, 1923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)), 1933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ntohl(ifa->ifa_address)); 1943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_manage_arp_cache(netdev, netdev->dev_addr, 1953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ntohl(nesvnic->local_ipaddr), NES_ARP_ADD); 1963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_OK; 1973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 1983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff default: 1993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 2003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_DONE; 2053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 2063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 2093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_net_event 2103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 2113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_net_event(struct notifier_block *notifier, 2123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned long event, void *ptr) 2133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 2143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct neighbour *neigh = ptr; 2153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 2163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct net_device *netdev; 2173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_vnic *nesvnic; 2183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff switch (event) { 2203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff case NETEVENT_NEIGH_UPDATE: 2213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 2223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* nes_debug(NES_DBG_NETDEV, "Nesdev list entry = 0x%p.\n", nesdev); */ 2233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev = nesdev->netdev[0]; 2243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesvnic = netdev_priv(netdev); 2253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (netdev == neigh->dev) { 2263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesvnic->rdma_enabled == 0) { 2273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "Skipping device %s since no RDMA\n", 2283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev->name); 2293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 2303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (neigh->nud_state & NUD_VALID) { 2313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_manage_arp_cache(neigh->dev, neigh->ha, 2323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ntohl(*(__be32 *)neigh->primary_key), NES_ARP_ADD); 2333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 2343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_manage_arp_cache(neigh->dev, neigh->ha, 2353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ntohl(*(__be32 *)neigh->primary_key), NES_ARP_DELETE); 2363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_OK; 2393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 2423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff default: 2433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_NETDEV, "NETEVENT_ %lu undefined\n", event); 2443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 2453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NOTIFY_DONE; 2483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 2493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 2523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_add_ref 2533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 2543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffvoid nes_add_ref(struct ib_qp *ibqp) 2553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 2563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_qp *nesqp; 2573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp = to_nesqp(ibqp); 2593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_QP, "Bumping refcount for QP%u. Pre-inc value = %u\n", 2603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ibqp->qp_num, atomic_read(&nesqp->refcount)); 2613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff atomic_inc(&nesqp->refcount); 2623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 2633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void nes_cqp_rem_ref_callback(struct nes_device *nesdev, struct nes_cqp_request *cqp_request) 2653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 2663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned long flags; 2673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_qp *nesqp = cqp_request->cqp_callback_pointer; 2683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_adapter *nesadapter = nesdev->nesadapter; 2693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 qp_id; 2703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff atomic_inc(&qps_destroyed); 2723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Free the control structures */ 2743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff qp_id = nesqp->hwqp.qp_id; 2763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesqp->pbl_vbase) { 2773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, 2783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp->hwqp.q2_vbase, nesqp->hwqp.q2_pbase); 2793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff spin_lock_irqsave(&nesadapter->pbl_lock, flags); 2803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesadapter->free_256pbl++; 2813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); 2823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_free_consistent(nesdev->pcidev, 256, nesqp->pbl_vbase, nesqp->pbl_pbase); 2833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp->pbl_vbase = NULL; 2843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 2863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, 2873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp->hwqp.sq_vbase, nesqp->hwqp.sq_pbase); 2883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 2893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_free_resource(nesadapter, nesadapter->allocated_qps, nesqp->hwqp.qp_id); 2903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff kfree(nesqp->allocated_buffer); 2923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 2943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 2953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 2963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_rem_ref 2973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 2983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffvoid nes_rem_ref(struct ib_qp *ibqp) 2993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 3003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u64 u64temp; 3013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_qp *nesqp; 3023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_vnic *nesvnic = to_nesvnic(ibqp->device); 3033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev = nesvnic->nesdev; 3043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_adapter *nesadapter = nesdev->nesadapter; 3053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_hw_cqp_wqe *cqp_wqe; 3063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_cqp_request *cqp_request; 3073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 opcode; 3083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp = to_nesqp(ibqp); 3103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (atomic_read(&nesqp->refcount) == 0) { 3123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_INFO PFX "%s: Reference count already 0 for QP%d, last aeq = 0x%04X.\n", 3133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff __FUNCTION__, ibqp->qp_num, nesqp->last_aeq); 3143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff BUG(); 3153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 3163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (atomic_dec_and_test(&nesqp->refcount)) { 3183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = NULL; 3193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Destroy the QP */ 3213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_request = nes_get_cqp_request(nesdev); 3223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (cqp_request == NULL) { 3233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n"); 3243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return; 3253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 3263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_request->waiting = 0; 3273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_request->callback = 1; 3283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_request->cqp_callback = nes_cqp_rem_ref_callback; 3293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_request->cqp_callback_pointer = nesqp; 3303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff cqp_wqe = &cqp_request->cqp_wqe; 3313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_fill_init_cqp_wqe(cqp_wqe, nesdev); 3333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff opcode = NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_IWARP; 3343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesqp->hte_added) { 3363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff opcode |= NES_CQP_QP_DEL_HTE; 3373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesqp->hte_added = 0; 3383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 3393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode); 3403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id); 3413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u64temp = (u64)nesqp->nesqp_context_pbase; 3423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp); 3433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL); 3443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 3453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 3463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 3493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_get_qp 3503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 3513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstruct ib_qp *nes_get_qp(struct ib_device *device, int qpn) 3523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 3533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_vnic *nesvnic = to_nesvnic(device); 3543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev = nesvnic->nesdev; 3553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_adapter *nesadapter = nesdev->nesadapter; 3563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((qpn < NES_FIRST_QPN) || (qpn >= (NES_FIRST_QPN + nesadapter->max_qp))) 3583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return NULL; 3593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return &nesadapter->qp_table[qpn - NES_FIRST_QPN]->ibqp; 3613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 3623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 3653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_print_macaddr 3663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 3673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void nes_print_macaddr(struct net_device *netdev) 3683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 3693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "%s: MAC %02X:%02X:%02X:%02X:%02X:%02X, IRQ %u\n", 3703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev->name, 3713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], 3723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5], 3733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev->irq); 3743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 3753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 3783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_interrupt - handle interrupts 3793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 3803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic irqreturn_t nes_interrupt(int irq, void *dev_id) 3813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 3823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev = (struct nes_device *)dev_id; 3833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int handled = 0; 3843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 int_mask; 3853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 int_req; 3863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 int_stat; 3873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 intf_int_stat; 3883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 timer_stat; 3893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 3903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesdev->msi_enabled) { 3913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* No need to read the interrupt pending register if msi is enabled */ 3923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff handled = 1; 3933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 3943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (unlikely(nesdev->nesadapter->hw_rev == NE020_REV)) { 3953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Master interrupt enable provides synchronization for kicking off bottom half 3963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff when interrupt sharing is going on */ 3973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int_mask = nes_read32(nesdev->regs + NES_INT_MASK); 3983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (int_mask & 0x80000000) { 3993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Check interrupt status to see if this might be ours */ 4003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int_stat = nes_read32(nesdev->regs + NES_INT_STAT); 4013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int_req = nesdev->int_req; 4023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (int_stat&int_req) { 4033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* if interesting CEQ or AEQ is pending, claim the interrupt */ 4043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((int_stat&int_req) & (~(NES_INT_TIMER|NES_INT_INTF))) { 4053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff handled = 1; 4063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 4073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (((int_stat & int_req) & NES_INT_TIMER) == NES_INT_TIMER) { 4083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Timer might be running but might be for another function */ 4093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff timer_stat = nes_read32(nesdev->regs + NES_TIMER_STAT); 4103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((timer_stat & nesdev->timer_int_req) != 0) { 4113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff handled = 1; 4123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((((int_stat & int_req) & NES_INT_INTF) == NES_INT_INTF) && 4153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (handled == 0)) { 4163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff intf_int_stat = nes_read32(nesdev->regs+NES_INTF_INT_STAT); 4173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((intf_int_stat & nesdev->intf_int_req) != 0) { 4183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff handled = 1; 4193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (handled) { 4233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs+NES_INT_MASK, int_mask & (~0x80000000)); 4243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int_mask = nes_read32(nesdev->regs+NES_INT_MASK); 4253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Save off the status to save an additional read */ 4263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->int_stat = int_stat; 4273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->napi_isr_ran = 1; 4283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 4323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff handled = nes_read32(nesdev->regs+NES_INT_PENDING); 4333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (handled) { 4373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_napi_isr(nesdev) == 0) { 4393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff tasklet_schedule(&nesdev->dpc_tasklet); 4403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return IRQ_HANDLED; 4433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 4443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return IRQ_NONE; 4453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 4473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 4503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_probe - Device initialization 4513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 4523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_id *ent) 4533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 4543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct net_device *netdev = NULL; 4553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev = NULL; 4563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int ret = 0; 4573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_vnic *nesvnic = NULL; 4583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff void __iomem *mmio_regs = NULL; 4593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u8 hw_rev; 4603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff assert(pcidev != NULL); 4623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff assert(ent != NULL); 4633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_INFO PFX "NetEffect RNIC driver v%s loading. (%s)\n", 4653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff DRV_VERSION, pci_name(pcidev)); 4663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = pci_enable_device(pcidev); 4683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 4693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to enable PCI device. (%s)\n", pci_name(pcidev)); 4703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail0; 4713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "BAR0 (@0x%08lX) size = 0x%lX bytes\n", 4743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (long unsigned int)pci_resource_start(pcidev, BAR_0), 4753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (long unsigned int)pci_resource_len(pcidev, BAR_0)); 4763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "BAR1 (@0x%08lX) size = 0x%lX bytes\n", 4773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (long unsigned int)pci_resource_start(pcidev, BAR_1), 4783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (long unsigned int)pci_resource_len(pcidev, BAR_1)); 4793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Make sure PCI base addr are MMIO */ 4813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (!(pci_resource_flags(pcidev, BAR_0) & IORESOURCE_MEM) || 4823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff !(pci_resource_flags(pcidev, BAR_1) & IORESOURCE_MEM)) { 4833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "PCI regions not an MMIO resource\n"); 4843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = -ENODEV; 4853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail1; 4863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Reserve PCI I/O and memory resources */ 4893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = pci_request_regions(pcidev, DRV_NAME); 4903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 4913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to request regions. (%s)\n", pci_name(pcidev)); 4923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail1; 4933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 4943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 4953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((sizeof(dma_addr_t) > 4)) { 4963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = pci_set_dma_mask(pcidev, DMA_64BIT_MASK); 4973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret < 0) { 4983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "64b DMA mask configuration failed\n"); 4993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail2; 5003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = pci_set_consistent_dma_mask(pcidev, DMA_64BIT_MASK); 5023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 5033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "64b DMA consistent mask configuration failed\n"); 5043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail2; 5053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 5073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = pci_set_dma_mask(pcidev, DMA_32BIT_MASK); 5083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret < 0) { 5093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "32b DMA mask configuration failed\n"); 5103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail2; 5113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = pci_set_consistent_dma_mask(pcidev, DMA_32BIT_MASK); 5133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 5143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "32b DMA consistent mask configuration failed\n"); 5153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail2; 5163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_set_master(pcidev); 5203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Allocate hardware structure */ 5223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev = kzalloc(sizeof(struct nes_device), GFP_KERNEL); 5233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (!nesdev) { 5243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "%s: Unable to alloc hardware struct\n", pci_name(pcidev)); 5253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = -ENOMEM; 5263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail2; 5273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "Allocated nes device at %p\n", nesdev); 5303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->pcidev = pcidev; 5313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_set_drvdata(pcidev, nesdev); 5323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_read_config_byte(pcidev, 0x0008, &hw_rev); 5343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "hw_rev=%u\n", hw_rev); 5353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff spin_lock_init(&nesdev->indexed_regs_lock); 5373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Remap the PCI registers in adapter BAR0 to kernel VA space */ 5393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff mmio_regs = ioremap_nocache(pci_resource_start(pcidev, BAR_0), sizeof(mmio_regs)); 5403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (mmio_regs == NULL) { 5413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to remap BAR0\n"); 5423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = -EIO; 5433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail3; 5443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->regs = mmio_regs; 5463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->index_reg = 0x50 + (PCI_FUNC(pcidev->devfn)*8) + mmio_regs; 5473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Ensure interrupts are disabled */ 5493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs+NES_INT_MASK, 0x7fffffff); 5503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_drv_opt & NES_DRV_OPT_ENABLE_MSI) { 5523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (!pci_enable_msi(nesdev->pcidev)) { 5533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->msi_enabled = 1; 5543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "MSI is enabled for device %s\n", 5553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_name(pcidev)); 5563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 5573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "MSI is disabled by linux for device %s\n", 5583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_name(pcidev)); 5593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 5613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "MSI not requested due to driver options for device %s\n", 5623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_name(pcidev)); 5633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->csr_start = pci_resource_start(nesdev->pcidev, BAR_0); 5663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->doorbell_region = pci_resource_start(nesdev->pcidev, BAR_1); 5673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Init the adapter */ 5693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter = nes_init_adapter(nesdev, hw_rev); 5703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (!nesdev->nesadapter) { 5713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to initialize adapter.\n"); 5723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = -ENOMEM; 5733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail5; 5743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 575a4435febd4c0f14b25159dca249ecf91301c7c76Adrian Bunk nesdev->nesadapter->et_rx_coalesce_usecs_irq = interrupt_mod_interval; 5763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* nesdev->base_doorbell_index = 5783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter->pd_config_base[PCI_FUNC(nesdev->pcidev->devfn)]; */ 5793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->base_doorbell_index = 1; 5803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->doorbell_start = nesdev->nesadapter->doorbell_start; 5813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->mac_index = PCI_FUNC(nesdev->pcidev->devfn) % nesdev->nesadapter->port_count; 5823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff tasklet_init(&nesdev->dpc_tasklet, nes_dpc, (unsigned long)nesdev); 5843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* bring up the Control QP */ 5863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_init_cqp(nesdev)) { 5873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = -ENODEV; 5883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail6; 5893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 5903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Arm the CCQ */ 5923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT | 5933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff PCI_FUNC(nesdev->pcidev->devfn)); 5943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_read32(nesdev->regs+NES_CQE_ALLOC); 5953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 5963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Enable the interrupts */ 5973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->int_req = (0x101 << PCI_FUNC(nesdev->pcidev->devfn)) | 5983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff (1 << (PCI_FUNC(nesdev->pcidev->devfn)+16)); 5993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (PCI_FUNC(nesdev->pcidev->devfn) < 4) { 6003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->int_req |= (1 << (PCI_FUNC(nesdev->pcidev->devfn)+24)); 6013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* TODO: This really should be the first driver to load, not function 0 */ 6043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (PCI_FUNC(nesdev->pcidev->devfn) == 0) { 6053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* pick up PCI and critical errors if the first driver to load */ 6063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->intf_int_req = NES_INTF_INT_PCIERR | NES_INTF_INT_CRITERR; 6073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->int_req |= NES_INT_INTF; 6083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } else { 6093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->intf_int_req = 0; 6103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->intf_int_req |= (1 << (PCI_FUNC(nesdev->pcidev->devfn)+16)); 6123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS0, 0); 6133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS1, 0); 6143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS2, 0x00001265); 6153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS4, 0x18021804); 6163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS3, 0x17801790); 6183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* deal with both periodic and one_shot */ 6203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->timer_int_req = 0x101 << PCI_FUNC(nesdev->pcidev->devfn); 6213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter->timer_int_req |= nesdev->timer_int_req; 6223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "setting int_req for function %u, nesdev = 0x%04X, adapter = 0x%04X\n", 6233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff PCI_FUNC(nesdev->pcidev->devfn), 6243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->timer_int_req, nesdev->nesadapter->timer_int_req); 6253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req)); 6273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_add_tail(&nesdev->list, &nes_dev_list); 6293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Request an interrupt line for the driver */ 6313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = request_irq(pcidev->irq, nes_interrupt, IRQF_SHARED, DRV_NAME, nesdev); 6323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 6333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "%s: requested IRQ %u is busy\n", 6343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_name(pcidev), pcidev->irq); 6353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail65; 6363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req); 6393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_notifiers_registered == 0) { 6413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff register_inetaddr_notifier(&nes_inetaddr_notifier); 6423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff register_netevent_notifier(&nes_net_notifier); 6433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_notifiers_registered++; 6453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Initialize network devices */ 6473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL) { 6483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail7; 6493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Register network device */ 6523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ret = register_netdev(netdev); 6533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (ret) { 6543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to register netdev, ret = %d\n", ret); 6553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_netdev_destroy(netdev); 6563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff goto bail7; 6573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_print_macaddr(netdev); 6603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* create a CM core for this netdev */ 6613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesvnic = netdev_priv(netdev); 6623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->netdev_count++; 6643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter->netdev_count++; 6653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "%s: NetEffect RNIC driver successfully loaded.\n", 6683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_name(pcidev)); 6693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return 0; 6703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail7: 6723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "bail7\n"); 6733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff while (nesdev->netdev_count > 0) { 6743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->netdev_count--; 6753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter->netdev_count--; 6763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_netdev(nesdev->netdev[nesdev->netdev_count]); 6783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_netdev_destroy(nesdev->netdev[nesdev->netdev_count]); 6793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_debug(NES_DBG_INIT, "netdev_count=%d, nesadapter->netdev_count=%d\n", 6823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->netdev_count, nesdev->nesadapter->netdev_count); 6833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_notifiers_registered--; 6853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_notifiers_registered == 0) { 6863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_netevent_notifier(&nes_net_notifier); 6873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_inetaddr_notifier(&nes_inetaddr_notifier); 6883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_del(&nesdev->list); 6913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_destroy_cqp(nesdev); 6923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 6933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail65: 6943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "bail65\n"); 6953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff free_irq(pcidev->irq, nesdev); 6963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesdev->msi_enabled) { 6973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_disable_msi(pcidev); 6983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 6993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail6: 7003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "bail6\n"); 7013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff tasklet_kill(&nesdev->dpc_tasklet); 7023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Deallocate the Adapter Structure */ 7033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_destroy_adapter(nesdev->nesadapter); 7043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail5: 7063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "bail5\n"); 7073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff iounmap(nesdev->regs); 7083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail3: 7103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "bail3\n"); 7113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff kfree(nesdev); 7123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail2: 7143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_release_regions(pcidev); 7153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail1: 7173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_disable_device(pcidev); 7183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bail0: 7203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return ret; 7213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 7223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 7253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_remove - unload from kernel 7263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 7273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void __devexit nes_remove(struct pci_dev *pcidev) 7283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 7293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev = pci_get_drvdata(pcidev); 7303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct net_device *netdev; 7313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int netdev_index = 0; 7323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesdev->netdev_count) { 7343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netdev = nesdev->netdev[netdev_index]; 7353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (netdev) { 7363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff netif_stop_queue(netdev); 7373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_netdev(netdev); 7383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_netdev_destroy(netdev); 7393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->netdev[netdev_index] = NULL; 7413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->netdev_count--; 7423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nesdev->nesadapter->netdev_count--; 7433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_notifiers_registered--; 7473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nes_notifiers_registered == 0) { 7483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_netevent_notifier(&nes_net_notifier); 7493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unregister_inetaddr_notifier(&nes_inetaddr_notifier); 7503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_del(&nesdev->list); 7533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_destroy_cqp(nesdev); 7543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff tasklet_kill(&nesdev->dpc_tasklet); 7553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* Deallocate the Adapter Structure */ 7573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_destroy_adapter(nesdev->nesadapter); 7583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff free_irq(pcidev->irq, nesdev); 7603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (nesdev->msi_enabled) { 7623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_disable_msi(pcidev); 7633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff iounmap(nesdev->regs); 7663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff kfree(nesdev); 7673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff /* nes_debug(NES_DBG_SHUTDOWN, "calling pci_release_regions.\n"); */ 7693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_release_regions(pcidev); 7703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_disable_device(pcidev); 7713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_set_drvdata(pcidev, NULL); 7723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 7733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic struct pci_driver nes_pci_driver = { 7763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .name = DRV_NAME, 7773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .id_table = nes_pci_table, 7783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .probe = nes_probe, 7793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff .remove = __devexit_p(nes_remove), 7803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff}; 7813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_adapter(struct device_driver *ddp, char *buf) 7833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 7843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned int devfn = 0xffffffff; 7853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned char bus_number = 0xff; 7863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff unsigned int i = 0; 7873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 7883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 7903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 7913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff devfn = nesdev->nesadapter->devfn; 7923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff bus_number = nesdev->nesadapter->bus_number; 7933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 7943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 7963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 7973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 7983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "%x:%x", bus_number, devfn); 7993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_adapter(struct device_driver *ddp, 8023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 8033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 8053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff ee_flsh_adapter = simple_strtoul(p, &p, 10); 8073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 8083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_ee_cmd(struct device_driver *ddp, char *buf) 8113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 eeprom_cmd = 0xdead; 8133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 8143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 8153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 8173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 8183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff eeprom_cmd = nes_read32(nesdev->regs + NES_EEPROM_COMMAND); 8193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 8203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 8223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", eeprom_cmd); 8243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_ee_cmd(struct device_driver *ddp, 8273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 8283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 8303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 8313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 8323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 8333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 8353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 8363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 8373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 8383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs + NES_EEPROM_COMMAND, val); 8393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 8403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 8423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 8453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_ee_data(struct device_driver *ddp, char *buf) 8483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 eeprom_data = 0xdead; 8503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 8513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 8523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 8543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 8553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff eeprom_data = nes_read32(nesdev->regs + NES_EEPROM_DATA); 8563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 8573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 8593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", eeprom_data); 8623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_ee_data(struct device_driver *ddp, 8653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 8663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 8683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 8693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 8703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 8713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 8733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 8743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 8753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 8763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs + NES_EEPROM_DATA, val); 8773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 8783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 8803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 8833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 8843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_flash_cmd(struct device_driver *ddp, char *buf) 8863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 8873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 flash_cmd = 0xdead; 8883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 8893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 8903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 8923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 8933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff flash_cmd = nes_read32(nesdev->regs + NES_FLASH_COMMAND); 8943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 8953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 8973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 8983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 8993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", flash_cmd); 9003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_flash_cmd(struct device_driver *ddp, 9033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 9043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 9063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 9073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 9083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 9093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 9113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 9123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 9133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 9143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs + NES_FLASH_COMMAND, val); 9153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 9163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 9183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 9213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_flash_data(struct device_driver *ddp, char *buf) 9243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 flash_data = 0xdead; 9263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 9273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 9283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 9303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 9313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff flash_data = nes_read32(nesdev->regs + NES_FLASH_DATA); 9323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 9333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 9353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", flash_data); 9383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_flash_data(struct device_driver *ddp, 9413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 9423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 9443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 9453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 9463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 9473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 9493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 9503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 9513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 9523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs + NES_FLASH_DATA, val); 9533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 9543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 9563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 9593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_nonidx_addr(struct device_driver *ddp, char *buf) 9623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", sysfs_nonidx_addr); 9643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_nonidx_addr(struct device_driver *ddp, 9673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 9683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 9703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') 9723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff sysfs_nonidx_addr = simple_strtoul(p, &p, 16); 9733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 9753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_nonidx_data(struct device_driver *ddp, char *buf) 9783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 nonidx_data = 0xdead; 9803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 9813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 9823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 9843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 9853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nonidx_data = nes_read32(nesdev->regs + sysfs_nonidx_addr); 9863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 9873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 9893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 9903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", nonidx_data); 9923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 9933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 9943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_nonidx_data(struct device_driver *ddp, 9953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 9963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 9973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 9983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 9993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 10003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 10013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 10033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 10043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 10053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 10063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write32(nesdev->regs + sysfs_nonidx_addr, val); 10073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 10083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 10103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 10133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_idx_addr(struct device_driver *ddp, char *buf) 10163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", sysfs_idx_addr); 10183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_idx_addr(struct device_driver *ddp, 10213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 10223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 10243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') 10263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff sysfs_idx_addr = simple_strtoul(p, &p, 16); 10273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 10293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_show_idx_data(struct device_driver *ddp, char *buf) 10323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 idx_data = 0xdead; 10343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 10353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 10363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 10383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 10393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff idx_data = nes_read_indexed(nesdev, sysfs_idx_addr); 10403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 10413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 10433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return snprintf(buf, PAGE_SIZE, "0x%x\n", idx_data); 10463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic ssize_t nes_store_idx_data(struct device_driver *ddp, 10493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff const char *buf, size_t count) 10503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff char *p = (char *)buf; 10523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 val; 10533c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff u32 i = 0; 10543c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff struct nes_device *nesdev; 10553c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10563c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { 10573c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff val = simple_strtoul(p, &p, 16); 10583c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff list_for_each_entry(nesdev, &nes_dev_list, list) { 10593c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (i == ee_flsh_adapter) { 10603c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_write_indexed(nesdev, sysfs_idx_addr, val); 10613c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff break; 10623c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10633c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff i++; 10643c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10653c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 10663c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return strnlen(buf, count); 10673c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 10683c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10693c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(adapter, S_IRUSR | S_IWUSR, 10703c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_adapter, nes_store_adapter); 10713c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(eeprom_cmd, S_IRUSR | S_IWUSR, 10723c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_ee_cmd, nes_store_ee_cmd); 10733c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(eeprom_data, S_IRUSR | S_IWUSR, 10743c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_ee_data, nes_store_ee_data); 10753c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(flash_cmd, S_IRUSR | S_IWUSR, 10763c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_flash_cmd, nes_store_flash_cmd); 10773c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(flash_data, S_IRUSR | S_IWUSR, 10783c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_flash_data, nes_store_flash_data); 10793c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(nonidx_addr, S_IRUSR | S_IWUSR, 10803c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_nonidx_addr, nes_store_nonidx_addr); 10813c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(nonidx_data, S_IRUSR | S_IWUSR, 10823c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_nonidx_data, nes_store_nonidx_data); 10833c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(idx_addr, S_IRUSR | S_IWUSR, 10843c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_idx_addr, nes_store_idx_addr); 10853c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic DRIVER_ATTR(idx_data, S_IRUSR | S_IWUSR, 10863c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_show_idx_data, nes_store_idx_data); 10873c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 10883c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int nes_create_driver_sysfs(struct pci_driver *drv) 10893c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 10903c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int error; 10913c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error = driver_create_file(&drv->driver, &driver_attr_adapter); 10923c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_eeprom_cmd); 10933c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_eeprom_data); 10943c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_flash_cmd); 10953c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_flash_data); 10963c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_nonidx_addr); 10973c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_nonidx_data); 10983c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_idx_addr); 10993c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff error |= driver_create_file(&drv->driver, &driver_attr_idx_data); 11003c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return error; 11013c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 11023c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 11033c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void nes_remove_driver_sysfs(struct pci_driver *drv) 11043c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 11053c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_adapter); 11063c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_eeprom_cmd); 11073c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_eeprom_data); 11083c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_flash_cmd); 11093c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_flash_data); 11103c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_nonidx_addr); 11113c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_nonidx_data); 11123c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_idx_addr); 11133c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff driver_remove_file(&drv->driver, &driver_attr_idx_data); 11143c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 11153c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 11163c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 11173c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_init_module - module initialization entry point 11183c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 11193c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic int __init nes_init_module(void) 11203c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 11213c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int retval; 11223c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff int retval1; 11233c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 11243c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff retval = nes_cm_start(); 11253c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (retval) { 11263c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to start NetEffect iWARP CM.\n"); 11273c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return retval; 11283c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 11293c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff retval = pci_register_driver(&nes_pci_driver); 11303c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (retval >= 0) { 11313c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff retval1 = nes_create_driver_sysfs(&nes_pci_driver); 11323c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff if (retval1 < 0) 11333c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff printk(KERN_ERR PFX "Unable to create NetEffect sys files.\n"); 11343c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff } 11353c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff return retval; 11363c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 11373c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 11383c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 11393c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff/** 11403c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff * nes_exit_module - module unload entry point 11413c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff */ 11423c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffstatic void __exit nes_exit_module(void) 11433c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff{ 11443c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_cm_stop(); 11453c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff nes_remove_driver_sysfs(&nes_pci_driver); 11463c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 11473c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff pci_unregister_driver(&nes_pci_driver); 11483c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff} 11493c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 11503c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiff 11513c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffmodule_init(nes_init_module); 11523c2d774cad5bf4fad576363da77870e9e6530b7aGlenn Streiffmodule_exit(nes_exit_module); 1153