diff -Naru linux-2.6.16_orig/drivers/net/netxen/netxen_nic_main.c linux-2.6.16/drivers/net/netxen/netxen_nic_main.c --- linux-2.6.16_orig/drivers/net/netxen/netxen_nic_main.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.16/drivers/net/netxen/netxen_nic_main.c 2006-03-24 14:19:19.000000000 -0800 @@ -0,0 +1,3847 @@ +/* + * Copyright (C) 2003 - 2006 NetXen Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE. + * + * Contact Information: + * [EMAIL PROTECTED] + * NetXen, 3965 Freedom Circle, Fourth Floor, + * Santa Clara, CA 95054 + */ +/* + * Main source file for NetXen NIC Driver on Linux + * + * $Id: netxen_nic_main.c,v 1.179.4.36 2006/03/21 00:31:29 vijo Exp $ + */ + +#include <linux/config.h> + +#include <linux/module.h> + +#include <linux/kernel.h> +#include <linux/types.h> +//#include <linux/kgdb-defs.h> +#include <linux/compiler.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/pci.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/ip.h> +#include <linux/in.h> +#include <linux/tcp.h> +#include <linux/skbuff.h> +#include <linux/version.h> + +#include <linux/ethtool.h> +#include <linux/mii.h> +#include <linux/interrupt.h> +#include <linux/timer.h> +#include <linux/proc_fs.h> + +#include <linux/mm.h> +#include <linux/mman.h> +#include <asm/system.h> +#include <asm/io.h> +#include <asm/byteorder.h> +#include <asm/uaccess.h> +#include <asm/pgtable.h> + +#include "netxen_nic_hw.h" +#include "netxen_nic_config.h" + +#undef NetXen_LOOPBACK +#undef SINGLE_DMA_BUF +#define NetXen_NIC_HW_CSUM +#define NetXen_NIC_NAPI +// #undef NetXen_NIC_NAPI + +#define NetXen_NETIF_F_TSO + +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +//#define NetXen_NIC_HW_VLAN 1 +#else +#define NetXen_NIC_HW_VLAN 0 +#endif + +#ifdef NetXen_NETIF_F_TSO +#define NetXen_DO_TSO 1 +#else +#define NetXen_DO_TSO 0 +#endif + +#include "netxen_nic.h" + +#define DEFINE_GLOBAL_RECV_CRB +#include "nic_phan_reg.h" + +#include "netxen_nic_ioctl.h" +#include "nic_cmn.h" +#include "netxen_nic_config.h" + +#include "netxen_nic_hw.h" +#include "netxen_version.h" + +// for cmd line parameteres---------- +#define NetXen_PARAM(X,S) \ +static int X=0; \ +MODULE_PARM(X,"i"); \ +MODULE_PARM_DESC(X,S); + + +/* + * Disable this for now. + * NetXen_PARAM(MaxTxCount,"No of TX descriptors"); + * NetXen_PARAM(MaxRxCount,"No of Rx descriptors"); + */ + +//----------- cmd line parameters------- + + + +MODULE_AUTHOR("NetXen"); +MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); +MODULE_LICENSE("GPL"); + +/*static int netxen_nic_debug = NETIF_MSG_DRV | NETIF_MSG_PROBE; TODO */ +int netxen_nic_debug; + +MODULE_PARM(netxen_nic_debug, "i"); +MODULE_PARM_DESC(netxen_nic_debug, "Debug level (0=none,...,16=all)"); + + +char netxen_nic_driver_name[] = "netxen"; +char netxen_nic_driver_string[] = "NetXen Network Driver version " + NetXen_NIC_LINUX_VERSIONID + "-" + NetXen_NIC_BUILD_NO + " generated " + NetXen_NIC_TIMESTAMP; + +#ifndef ARCH_KMALLOC_MINALIGN +#define ARCH_KMALLOC_MINALIGN 0 +#endif +#ifndef ARCH_KMALLOC_FLAGS +#define ARCH_KMALLOC_FLAGS SLAB_HWCACHE_ALIGN +#endif + +#define NetXen_NETDEV_WEIGHT 120 +#define ADAPTER_UP_MAGIC 777 + +kmem_cache_t *cmd_desc_cache = NULL; +kmem_cache_t *cmd_buff_cache = NULL; +cmdDescType0_t *cmd_desc_array[NR_CPUS]; +struct netxen_cmd_buffer *cmd_buff_array[NR_CPUS]; + +static int netxen_nic_probe_err = 0; + +#define RCV_DESC_RINGSIZE (sizeof(rcvDesc_t) * adapter->MaxRxDescCount) +#define STATUS_DESC_RINGSIZE (sizeof(statusDesc_t)* adapter->MaxRxDescCount) +#define JUMBO_DESC_RINGSIZE (sizeof(rcvDesc_t) * adapter->MaxJumboRxDescCount) +#define TX_RINGSIZE (sizeof(struct netxen_cmd_buffer) * adapter->MaxTxDescCount) +#define RCV_BUFFSIZE (sizeof(struct netxen_rx_buffer) * rcv_desc->MaxRxDescCount) + +#define NetXen_NIC_INT_RESET 0x2004 + +/* Local functions to NetXen NIC driver */ +static int __devinit netxen_nic_probe(struct pci_dev *pdev, + const struct pci_device_id *ent); +static void __devexit netxen_nic_remove(struct pci_dev *pdev); +static void netxen_nic_hw_reset (struct netxen_adapter_s *adapter); +static int netxen_nic_open(struct net_device *netdev); +static int netxen_nic_close(struct net_device *netdev); +static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *); +static int netxen_nic_set_mac(struct net_device *netdev, void *p); +static int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); +static int netxen_nic_hw_resources(struct netxen_adapter_s *adapter); +static void netxen_nic_set_multi(struct net_device *netdev); +static void initialize_adapter_sw(struct netxen_adapter_s *adapter); +static void netxen_post_rx_buffers(struct netxen_adapter_s *adapter, uint32_t ctx, + uint32_t num, uint32_t type); +static void netxen_process_rcv(struct netxen_adapter_s *adapter,int ctx, + statusDesc_t *desc); +static void netxen_tx_timeout(struct net_device *netdev); +static void netxen_tx_timeout_task(struct net_device *netdev); +static void netxen_process_cmd_ring(unsigned long data); +static void netxen_nic_down(struct netxen_port *port); +static int netxen_nic_do_ioctl(struct netxen_adapter_s *adapter, void*u_data, + struct netxen_port *port); +static int initialize_adapter_hw(struct netxen_adapter_s *adapter); +static void netxen_watchdog(unsigned long); +static void netxen_watchdog_task(unsigned long adapter); +static void netxen_nic_tune_phantom(struct pci_dev *pdev, + struct netxen_adapter_s*); +static void netxen_nic_enable_int(netxen_adapter *adapter); +static void netxen_nic_disable_int(netxen_adapter *adapter); +static uint32_t netxen_process_rcv_ring(struct netxen_adapter_s *, int, int); +static void netxen_nic_clear_stats(struct netxen_adapter_s *); +static struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev); +static void netxen_nic_irq_enable(struct netxen_adapter_s *adapter); +static int netxen_handle_int(netxen_adapter *, struct net_device *); +static int netxen_nic_ioctl(struct net_device *netdev, + struct ifreq *ifr, int cmd); +static int netxen_nic_read_proc(char *buf, char **start, off_t offset, + int count, int *eof, void *data); +static int netxen_nic_port_read_proc(char *buf, char **start, off_t offset, + int count, int *eof, void *data); +#ifdef NetXen_NIC_NAPI +static int netxen_nic_rx_has_work(struct netxen_adapter_s *adapter); +static int netxen_nic_tx_has_work(struct netxen_adapter_s *adapter); +static int netxen_nic_poll(struct net_device *dev, int *budget); +#endif +#ifdef CONFIG_NET_POLL_CONTROLLER +static void netxen_nic_poll_controller(struct net_device *netdev); +#endif +#ifdef NetXen_NIC_HW_CSUM +static int netxen_tx_csum(struct netxen_adapter_s *adapter, cmdDescType0_t *desc, + struct sk_buff *skb); +#endif +static irqreturn_t netxen_intr(int irq, void *data, struct pt_regs *regs); + +extern void set_ethtool_ops(struct net_device *netdev); +struct netxen_adapter_s *g_adapter; +spinlock_t hal_lock; + +unsigned int loopback_start = 0; + +static struct proc_dir_entry *netxen_proc_dir_entry; + +static unsigned char *tx_user_packet_data = NULL, *rx_user_packet_data; +static unsigned int tx_user_packet_length = 0, rx_datalen, rx_user_pos = 0; +static int capture_input = 0, captured = 0; + +#define DIDX_DIF(p, c) \ + ((p >= c) ? (p - c) : (MAX_CMD_DESCRIPTORS - p + c)) + +#define CIS_WATERMARK 0x60 + +#define PEG_LOOP 1000 /* loop to pegstuck? */ + +#define QMAJ(hdr) ((hdr >> 19) & 0xF) +#define QMIN(hdr) (hdr & 0x3ffff) +#define QSUB(hdr) ((hdr >> 18) & 0x1) + +extern void xge_loopback(int on); +extern long xge_link_status (void); + +void __devinit +netxen_check_options(netxen_adapter *adapter) +{ + adapter->MaxTxDescCount = MAX_CMD_DESCRIPTORS; + adapter->MaxRxDescCount = MAX_RCV_DESCRIPTORS; + adapter->MaxJumboRxDescCount = MAX_JUMBO_RCV_DESCRIPTORS; + return; +} + +/* PCI Device ID Table */ +static struct pci_device_id netxen_pci_tbl[] __devinitdata = { + {PCI_VENDOR_ID_NetXen,PCI_DEVICE_ID_NetXen_4PORT,PCI_ANY_ID, + PCI_ANY_ID,0,0,0UL}, + {0,} +}; + +MODULE_DEVICE_TABLE(pci, netxen_pci_tbl); + +struct netxen_adapter_s *adapterlist[MAX_NUM_CARDS]; + +/* +netxen_nic_probe() + +Linux system will invoke this after identifying the vendor ID and device Id +in the pci_tbl where this module will search for NetXen vedonr and device ID for +quad port adapter. + +Even though there are 4 seperate devices (functions) on the quad port NIC, but +the probe will be invoked for the first device (function) only. This will +initialize the adapter, and setup the global parameters along with the port's +specific structure. +*/ +static int __devinit +netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct net_device *netdev = NULL; + struct netxen_adapter_s *adapter = NULL; + struct netxen_port *port = NULL; + uint8_t *mem_ptr = NULL; + unsigned long mem_base, mem_len; + int pci_using_dac, i, err; + int boardno = 0; + int ring; + netdev_list_t *netlist = NULL; + netxen_recv_context_t *recv_ctx = NULL; + netxen_rcv_desc_ctx_t *rcv_desc = NULL; + struct netxen_cmd_buffer *cmd_buf_arr = NULL; + struct proc_dir_entry *procfile; + static int netxen_cards_found = 0; + + printk("NetXen: adapter %d\n", netxen_cards_found); + + if((err = pci_enable_device(pdev))) { + DPRINTK(1, ERR, "Cannot enable PCI device, aborting. %d\n", + err); + netxen_nic_probe_err = err; + return err; + } + + if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { + DPRINTK(1, ERR, "Cannot find proper PCI device " + "base address, aborting. %p\n", pdev); + err = -ENODEV; + goto err_out_disable_pdev; + } + + if((err = pci_request_regions(pdev, netxen_nic_driver_name))) { + DPRINTK(1, ERR, "Cannot find proper PCI resources" + " aborting:%d\n", err); + goto err_out_disable_pdev; + } + + pci_set_master(pdev); + + if(!(err = pci_set_dma_mask(pdev, PCI_DMA_64BIT)) && + !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) { + pci_using_dac = 1; + } else { + if((err = pci_set_dma_mask(pdev, PCI_DMA_32BIT)) || + (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) { + DPRINTK(1, ERR, "No usable DMA configuration," + " aborting:%d\n", err); + goto err_out_free_res; + } + pci_using_dac = 0; + } + DPRINTK(1, INFO, "pci_using_dac: %d\n", pci_using_dac); + + /* remap phys address */ + mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ + mem_len = pci_resource_len(pdev, 0); + + /* 128 Meg of memory */ + DPRINTK(1, INFO, "ioremap from %lx a size of %lx\n", mem_base, + mem_len); + mem_ptr = ioremap(mem_base, NetXen_PCI_MAPSIZE_BYTES); + if (mem_ptr == 0UL) { + DPRINTK(1, ERR, "Cannot remap adapter memory aborting.:%p\n", + mem_ptr); + err = -EIO; + goto err_out_free_res; + } + DPRINTK(1, ERR, "ioremaped at %p\n", mem_ptr); + +/* + * Allocate a adapter structure which will manage all the initialization + * as well as the common resources for all ports... + * all the ports will have pointer to this adapter as well as Adapter + * will have pointers of all the ports structures. + */ + + /* One adapter structure for all 4 ports.... */ + adapter = (struct netxen_adapter_s *)kmalloc(sizeof(struct netxen_adapter_s), + GFP_KERNEL); + if (adapter == NULL) { + DPRINTK(1, ERR, "Could not allocate adapter memory:%d\n", + (int)sizeof(struct netxen_adapter_s)); + err = -ENOMEM; + goto err_out_iounmap; + } + + if (netxen_cards_found == 0) { + g_adapter = adapter; + spin_lock_init(&hal_lock); + } + + /* Initialize to 0 */ + memset(adapter, 0 , sizeof(struct netxen_adapter_s)); + DPRINTK(1, INFO, "malloced memory at %p\n", adapter); + + netxen_check_options(adapter); + + cmd_buf_arr = (struct netxen_cmd_buffer*) vmalloc(TX_RINGSIZE); + if (cmd_buf_arr == NULL) { + DPRINTK(1, ERR, "Could not allocate command buffer array," + " order :%d\n", get_order(TX_RINGSIZE)); + err = -ENOMEM; + goto err_out_free_adapter; + } + memset (cmd_buf_arr, 0, TX_RINGSIZE); + + for (i = 0; i < MAX_RCV_CTX; ++i) { + recv_ctx = &adapter->recv_ctx[i]; + for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { + rcv_desc = &recv_ctx->rcv_desc[ring]; + switch (RCV_DESC_TYPE(ring)) { + case RCV_RING_STD: + rcv_desc->MaxRxDescCount = + adapter->MaxRxDescCount; + rcv_desc->flags = RCV_DESC_NORMAL; + rcv_desc->dma_size = RX_DMA_MAP_LEN; + rcv_desc->skb_size = MAX_RX_BUFFER_LENGTH; + break; + + case RCV_RING_JUMBO: + rcv_desc->MaxRxDescCount = + adapter->MaxJumboRxDescCount; + rcv_desc->flags = RCV_DESC_JUMBO; + rcv_desc->dma_size = RX_JUMBO_DMA_MAP_LEN; + rcv_desc->skb_size = + MAX_RX_JUMBO_BUFFER_LENGTH; + break; + + default: + printk("%s: netxen_nic_probe: bad receive " + "descriptor type %d\n", + netxen_nic_driver_name, + RCV_DESC_TYPE(ring)); + break; + } + rcv_desc->rx_buf_arr = (struct netxen_rx_buffer*) + pci_alloc_consistent(pdev, + RCV_BUFFSIZE, + &rcv_desc->rx_buf_phys); + + if(rcv_desc->rx_buf_arr == NULL) { + DPRINTK(1, ERR, "Could not allocate rx" + " buffer array ring %d," + " size:%u\n", ring, + (unsigned int)RCV_BUFFSIZE); + err = -ENOMEM; + goto err_out_free_rx_buffer; + } + memset (rcv_desc->rx_buf_arr, 0, RCV_BUFFSIZE); + } + + } + + adapter->cmd_buf_arr = cmd_buf_arr; + adapter->ahw.pci_base = (unsigned long)mem_ptr; + adapter->ahw.pci_len = mem_len; + adapter->ahw.crb_base = adapter->ahw.pci_base + NetXen_PCI_CRBSPACE; + rwlock_init(&adapter->adapter_lock); + spin_lock_init(&adapter->tx_lock); + spin_lock_init(&adapter->lock); + initialize_adapter_sw(adapter); /* initialize the buffers in adapter */ + /* + * Set the CRB window to invalid. If any register in window 0 is + * accessed it should set the window to 0 and then reset it to 1. + */ + adapter->curr_window = 255; + /* + * Adapter in our case is quad port so initialize it beofore + * initializing the ports + */ + initialize_adapter_hw(adapter); /* initialize the adapter */ + adapter->port = + (struct netxen_port**) kmalloc(sizeof(struct netxen_adapter_s)* + (adapter->ahw.max_ports), + GFP_KERNEL); + if (adapter->port == NULL) { + DPRINTK(1, ERR, "Could not allocate port-array memory:%d\n", + (int)sizeof(struct netxen_adapter_s) * + (adapter->ahw.max_ports)); + err = -ENOMEM; + goto err_out_free_rx_buffer; + } + init_timer(&adapter->watchdog_timer); + adapter->ahw.xg_linkup = 0; + adapter->watchdog_timer.function = &netxen_watchdog; + adapter->watchdog_timer.data = (unsigned long) adapter; + INIT_WORK(&adapter->watchdog_task, + (void (*)(void *))netxen_watchdog_task, adapter); + adapter->ahw.vendor_id = pdev->vendor; + adapter->ahw.device_id = pdev->device; + adapter->ahw.pdev = pdev; + adapter->procCmdBufCounter = 0; + pci_read_config_byte(pdev, PCI_REVISION_ID, &adapter->ahw.revision_id); + pci_read_config_word(pdev, PCI_COMMAND, &adapter->ahw.pci_cmd_word); + +#if defined(CONFIG_PCI_MSI) + adapter->flags |= NetXen_NIC_MSI_ENABLED; + if (pci_enable_msi(pdev)) { + adapter->flags &= ~NetXen_NIC_MSI_ENABLED; + printk(KERN_WARNING "%s: unable to allocate MSI interrupt" + " error\n",netxen_nic_driver_name); + } +#endif + netxen_nic_tune_phantom(pdev, adapter); + + /* initialize the all the ports */ + DPRINTK(1, INFO, "about to allocate all the %d net devs.\n", + adapter->ahw.max_ports); + for (i = 0; i < adapter->ahw.max_ports; i ++) { + netlist = kmalloc(sizeof(netdev_list_t), GFP_KERNEL); + if (netlist == NULL) { + goto err_out_free_dev; + } + netlist->netdev = alloc_etherdev(sizeof(struct netxen_port)); + if(!netlist->netdev) { + DPRINTK(1, ERR, " could not allocate netdev for port" + " %d\n",i+1); + kfree(netlist); + goto err_out_free_dev; + } + netdev = netlist->netdev; + + SET_MODULE_OWNER(netdev); + + port = netdev->priv; + port->netdev = netdev; + port->pdev = pdev; + port->hw.port = port; + port->adapter = adapter; + port->portnum = i; /* Gigabit port number starting from 0-3 */ + port->flags &= ~NETDEV_STATUS; + + netdev->open = netxen_nic_open; + netdev->stop = netxen_nic_close; + netdev->hard_start_xmit = netxen_nic_xmit_frame; + netdev->get_stats = netxen_nic_get_stats; + netdev->set_multicast_list = netxen_nic_set_multi; + netdev->set_mac_address = netxen_nic_set_mac; + netdev->change_mtu = netxen_nic_change_mtu; + netdev->do_ioctl = netxen_nic_ioctl; + netdev->tx_timeout = netxen_tx_timeout; + set_ethtool_ops(netdev); + /* FIXME: maybe SET_ETHTOOL_OPS(netdev,&netxen_nic_ethtool_ops);*/ + netdev->irq = pdev->irq; +#ifdef NetXen_NIC_NAPI + netdev->poll = netxen_nic_poll; + netdev->weight = NetXen_NETDEV_WEIGHT; +#endif +#ifdef CONFIG_NET_POLL_CONTROLLER + netdev->poll_controller = netxen_nic_poll_controller; +#endif +#ifdef NetXen_NIC_HW_CSUM + /* ScatterGather support */ + netdev->features = NETIF_F_SG ; + netdev->features |= NETIF_F_IP_CSUM; +#endif +#ifdef NetXen_NIC_HW_VLAN + netdev->features |= NETIF_F_HW_VLAN_TX; + netdev->features |= NETIF_F_HW_VLAN_RX; +#endif +#ifdef NetXen_NETIF_F_TSO + netdev->features |= NETIF_F_TSO; +#endif + + if(pci_using_dac) + netdev->features |= NETIF_F_HIGHDMA; + DPRINTK(1, INFO, "setting mac address: %p\n", port); + + /* + * Allocate h/w address and set in h/w. + * Eventually, we will read from the flash and set the mac + * address. + * For now set the lower 3 bytes to be same as board number + */ + boardno = netxen_nic_get_board_num(adapter); + port->hw.mac_addr[0] = 0x00; + port->hw.mac_addr[1] = 0x0e; + port->hw.mac_addr[2] = 0x1e; + port->hw.mac_addr[3] = ((boardno & (0xff << 16)) >> 16) + i; + port->hw.mac_addr[4] = (boardno & (0xff << 8)) >> 8; + port->hw.mac_addr[5] = boardno & 0xff; + netxen_nic_macaddr_set (port, port->hw.mac_addr); + memcpy(netdev->dev_addr, port->hw.mac_addr, netdev->addr_len); + if(!is_valid_ether_addr(netdev->dev_addr)) { + DPRINTK(1, ERR, "BAD MAC :is_valid_ether_addr" + " aborting:%d\n", err); + break; + } + INIT_WORK(adapter->tx_timeout_task + i, + (void (*)(void *))netxen_tx_timeout_task, netdev); + netif_carrier_off(netdev); + netif_stop_queue(netdev); + + if((err = register_netdev(netdev))) { + DPRINTK(1, ERR, "register_netdev failed port #%d" + " aborting\n", i+1); + break; + } + procfile = create_proc_entry(netdev->name, S_IRUGO, + netxen_proc_dir_entry); + if (procfile) { + procfile->data = netdev; + procfile->owner = THIS_MODULE; + procfile->read_proc = netxen_nic_port_read_proc; + } + adapter->activePorts = 0; + adapter->portCount ++; /* number of ports allocated */ + adapter->port[i] = port; + netlist->next = pci_get_drvdata(pdev); + pci_set_drvdata(pdev, netlist); + } /* For loop added by for number of ports */ + + /* + * check how many ports were configured. If due to some errors, + * the port count == NULL, then free up the adapter structure, + * do ionetxenap() else add the adapter to the global adapter list + */ + + if (!adapter->portCount) { + /* unable to configure any port */ + err = -EIO; + goto err_out_free_dev; + } + + adapter->netlist = netlist; + + /* + * Initialize all the CRB registers here. + */ + /* Window = 1 */ + read_lock(&adapter->adapter_lock); + NetXen_NIC_PCI_WRITE_32(0, CRB_NORMALIZE(adapter, + CRB_CMD_PRODUCER_OFFSET)); + NetXen_NIC_PCI_WRITE_32(0, CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET)); + NetXen_NIC_PCI_WRITE_32(0, CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO)); + read_unlock(&adapter->adapter_lock); + + +// tasklet_init(&adapter->tx_tasklet, netxen_process_cmd_ring, +// (unsigned long)adapter); +// tasklet_disable(&adapter->tx_tasklet); + if (create_proc_read_entry(PROC_ENTRY_NAME, 0, netxen_proc_dir_entry, + netxen_nic_read_proc, adapter) == NULL) { + DPRINTK(1,INFO,"Error in creating proc entry.\n"); + } + + phantom_init(adapter); + /* + * delay a while to ensure that the Pegs are up & running. + * Otherwise, we might see some flaky behaviour. + */ + mdelay(1000); + + switch (adapter->ahw.board_type) { + case NetXen_BRDTYPE_P2_SB35_4G: + printk("%s: QUAD GbE board initialized\n",netxen_nic_driver_name); + break; + + case NetXen_BRDTYPE_P2_SB31_10G: + case NetXen_BRDTYPE_P2_SB31_10G_CX4: + case NetXen_BRDTYPE_P2_SB31_10G_IMEZ: + case NetXen_BRDTYPE_P2_SB31_10G_HMEZ: + printk("%s: XGbE board initialized\n",netxen_nic_driver_name); + break; + } + + adapter->driver_mismatch = 0; + netxen_nic_flash_print(adapter); + + adapterlist[netxen_cards_found++] = adapter; + adapter->number = netxen_cards_found; + netxen_nic_probe_err = 0; + return 0; + +err_out_free_dev: + for (netlist = pci_get_drvdata(pdev); netlist != NULL; ) { + netdev_list_t *prev; + unregister_netdev(netlist->netdev); + free_netdev(netlist->netdev); + prev = netlist; + netlist = netlist->next; + kfree(prev); + } + kfree(netlist); + pci_set_drvdata(pdev, NULL); + + +err_out_free_rx_buffer: + for (i = 0; i < MAX_RCV_CTX; ++i) { + recv_ctx = &adapter->recv_ctx[i]; + for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { + rcv_desc = &recv_ctx->rcv_desc[ring]; + if (rcv_desc->rx_buf_arr != NULL) { + pci_free_consistent(pdev, RCV_BUFFSIZE, + rcv_desc->rx_buf_arr, + rcv_desc->rx_buf_phys); + rcv_desc->rx_buf_arr = NULL; + } + } + } + + vfree (cmd_buf_arr); + + kfree(adapter->port); + +err_out_free_adapter: + kfree (adapter); + +err_out_iounmap: + iounmap ((uint8_t *)mem_ptr) ; +err_out_free_res: + pci_release_regions(pdev); +err_out_disable_pdev: + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + netxen_nic_probe_err = err; + return err; +} + +static void +initialize_adapter_sw (struct netxen_adapter_s *adapter) +{ + int ctx, ring; + uint32_t i; + uint32_t num_rx_bufs = 0; + netxen_rcv_desc_ctx_t *rcv_desc; + + adapter->freeCmdCount = adapter->MaxTxDescCount; + DPRINTK(1, INFO, "initializing some queues: %p\n", adapter); + for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { + for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { + struct netxen_rx_buffer *rxBuf; + rcv_desc = &adapter->recv_ctx[ctx].rcv_desc[ring]; + rcv_desc->rcv_free = rcv_desc->MaxRxDescCount; + /* Initialize the queues for both receive and + command buffers */ + (&rcv_desc->free_rxbuf_list)->tqh_first = NULL; + (&rcv_desc->free_rxbuf_list)->tqh_last = + &(&rcv_desc->free_rxbuf_list)->tqh_first; + (&rcv_desc->busy_rxbuf_list)->tqh_first = NULL; + (&rcv_desc->busy_rxbuf_list)->tqh_last = + &(&rcv_desc->busy_rxbuf_list)->tqh_first; + + rxBuf = rcv_desc->rx_buf_arr; + num_rx_bufs = rcv_desc->MaxRxDescCount; + /* + * Now go through all of them, set reference handles + * and put them in the queues. + */ + for (i=0; i < num_rx_bufs; i ++) { + rxBuf->refHandle = i; + + rxBuf->link.tqe_next = NULL; + rxBuf->link.tqe_prev = + (&rcv_desc->free_rxbuf_list)->tqh_last; + *(&rcv_desc->free_rxbuf_list)->tqh_last =rxBuf; + (&rcv_desc->free_rxbuf_list)->tqh_last = + &(rxBuf)->link.tqe_next; + + DPRINTK(1, INFO, "Rx buf:ctx%d i(%d) rxBuf:" + "%p\n", ctx, i,rxBuf); + rxBuf ++; + } + } + } + DPRINTK(1, INFO, "initialized buffers for %s and %s\n", + "adapter->free_cmd_buf_list", + "adapter->free_rxbuf"); + return; +} + +static int +initialize_adapter_hw(struct netxen_adapter_s *adapter) +{ + uint32_t value = 0; + + if (netxen_nic_get_board_info(adapter) != 0) { + printk("%s: Error getting board config info.\n", + netxen_nic_driver_name); + } + + switch (adapter->ahw.board_type) { + case NetXen_NIC_GBE: + adapter->ahw.max_ports = 4; + break; + + case NetXen_NIC_XGBE: + adapter->ahw.max_ports = 1; + break; + + default: + printk(KERN_ERR "%s: Unknown board type\n",netxen_nic_driver_name); + } + + + /* now we do the loadimage...so wait before doing anytining alselll */ + + return value; +} + +/* Tuning for performance */ +static void +netxen_nic_tune_phantom(struct pci_dev *pdev, struct netxen_adapter_s *adapter) +{ + struct pci_dev *bdev; + uint16_t dcr_word; + uint32_t netxen_dcr_word; + int cap, maxpayload; + + bdev = pdev->bus->self; + if (bdev) { + + /* override minimum read request, payload size settings */ + netxen_nic_write_w0 (adapter, NetXen_PCIE_REG(PCIE_IMBUS_CONTROL), + 0); + + /* DMA transfer size */ + netxen_nic_write_w0 (adapter, + NetXen_PCIE_REG(PCIE_MAX_DMA_XFER_SIZE), + 0x201); + + cap = pci_find_capability(bdev, PCI_CAP_ID_EXP); + + if (cap) { + if (pci_read_config_word(bdev, cap + PCI_EXP_DEVCTL, + &dcr_word)) { + printk(KERN_ERR "%s: could not read PCI EXP" + " device control.\n",netxen_nic_driver_name); + return; + } + } else { + printk(KERN_ERR "%s: could not find bridge express" + " cpability .\n",netxen_nic_driver_name); + return; + } + maxpayload = ((dcr_word & PCI_EXP_DEVCTL_PAYLOAD) >> 5); + printk(KERN_ERR "%s: got maxpayload = %x from dcr_word:%x\n", + netxen_nic_driver_name, maxpayload, dcr_word); + + /* enable error reporting, read requst size = 256 */ + netxen_dcr_word = PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_FERE + | (1<<12); + + /*match max payload size of the bridge, but no more than 512*/ + if ((dcr_word & PCI_EXP_DEVCTL_PAYLOAD) <= (2 << 5)) { + /* set equal to bridge's payload size */ + netxen_dcr_word |= (dcr_word & PCI_EXP_DEVCTL_PAYLOAD); + } else { + /* set to 512 byte payload size */ + netxen_dcr_word |= (2<<5); + } + + printk(KERN_ERR "%s: Writing 0x%x to NetXen PCIE_DCR\n", + netxen_nic_driver_name,netxen_dcr_word); + netxen_nic_write_w0 (adapter, NetXen_PCIE_REG(PCIE_DCR), + netxen_dcr_word); + switch (maxpayload) { + case 0: + printk(KERN_INFO "%s: 128 Byte Max payload size\n", + netxen_nic_driver_name); + /* DMA transfer size */ + netxen_nic_write_w0 (adapter, + NetXen_PCIE_REG(PCIE_TGT_SPLIT_CHICKEN), + 0x08b000ba); + /* max splits = 8 */ + netxen_nic_write_w0 (adapter, + NetXen_PCIE_REG(PCIE_MAX_MASTER_SPLIT), + 0x844); + break; + + case 1: + printk(KERN_INFO "%s: 256 Byte max payload size\n", + netxen_nic_driver_name); + /* DMA transfer size */ + netxen_nic_write_w0 (adapter, + NetXen_PCIE_REG(PCIE_TGT_SPLIT_CHICKEN), + 0x08b010ba); + /* max splits = 4 */ + netxen_nic_write_w0 (adapter, + NetXen_PCIE_REG(PCIE_MAX_MASTER_SPLIT), + 0x422); + break; + + default: + printk(KERN_INFO "%s: default(128B) max payload size\n", + netxen_nic_driver_name); + /* DMA transfer size */ + netxen_nic_write_w0 (adapter, + NetXen_PCIE_REG(PCIE_TGT_SPLIT_CHICKEN), + 0x08b000ba); + /* max splits = 8 */ + netxen_nic_write_w0 (adapter, + NetXen_PCIE_REG(PCIE_MAX_MASTER_SPLIT), + 0x844); + break; + + } + + } + + return; +} + +static void +netxen_free_hw_resources(struct netxen_adapter_s *adapter) +{ + netxen_recv_context_t *recv_ctx; + netxen_rcv_desc_ctx_t *rcv_desc; + int ctx, ring; + + if (adapter->ahw.cmdDescHead != NULL) { + pci_free_consistent(adapter->ahw.pdev, + sizeof(cmdDescType0_t) * + adapter->MaxTxDescCount, + adapter->ahw.cmdDescHead, + adapter->ahw.cmdDesc_physAddr); + adapter->ahw.cmdDescHead = NULL; + } + + for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { + recv_ctx = &adapter->recv_ctx[ctx]; + for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { + rcv_desc = &recv_ctx->rcv_desc[ring]; + + if (rcv_desc->desc_head != NULL) { + pci_free_consistent(adapter->ahw.pdev, + RCV_DESC_RINGSIZE, + rcv_desc->desc_head, + rcv_desc->phys_addr); + rcv_desc->desc_head = NULL; + } + } + + if (recv_ctx->rcvStatusDescHead != NULL) { + pci_free_consistent(adapter->ahw.pdev, + STATUS_DESC_RINGSIZE, + recv_ctx->rcvStatusDescHead, + recv_ctx->rcvStatusDesc_physAddr); + recv_ctx->rcvStatusDescHead = NULL; + } + } + + return; +} + +static void __devexit +netxen_nic_remove(struct pci_dev *pdev) +{ + struct netxen_adapter_s *adapter; + netdev_list_t *netlist; + struct netxen_rx_buffer *buffer; + netxen_recv_context_t *recv_ctx; + netxen_rcv_desc_ctx_t *rcv_desc; + int i; + int ctx, ring; + + remove_proc_entry(PROC_ENTRY_NAME, netxen_proc_dir_entry); + netlist = pci_get_drvdata(pdev); + if (netlist == NULL || netlist->netdev == NULL) { + return; + } + adapter = ((struct netxen_port *)(netlist->netdev->priv))->adapter; + if (adapter == NULL) { + return; + } + + netxen_nic_stop_all_ports(adapter); + /* leave the hw in the same state as reboot */ + pinit_from_rom(adapter, 0); + udelay(500); + load_firmware(adapter); + +#ifndef SINGLE_DMA_BUF + if ((adapter->flags & NetXen_NIC_MSI_ENABLED)) { + read_lock(&adapter->adapter_lock); + netxen_nic_disable_int(adapter); + read_unlock(&adapter->adapter_lock); + } +#endif + udelay(500); /* Delay for a while to drain the DMA engines */ + + netlist = pci_get_drvdata(pdev); + if (netlist != NULL) { +#ifndef SINGLE_DMA_BUF + free_irq(netlist->netdev->irq, adapter); +#endif + if ((adapter->flags & NetXen_NIC_MSI_ENABLED)) { + pci_disable_msi(pdev); + } + } + while (netlist != NULL) { + netdev_list_t *prev; + + remove_proc_entry(netlist->netdev->name, netxen_proc_dir_entry); + unregister_netdev(netlist->netdev); + free_netdev(netlist->netdev); + prev = netlist; + netlist = netlist->next; + kfree(prev); + } + adapter->netlist = NULL; + pci_set_drvdata(pdev, NULL); + + netxen_free_hw_resources(adapter); + + iounmap((uint8_t*)adapter->ahw.pci_base); + + pci_release_regions(pdev); + pci_disable_device(pdev); +
- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html