+static int +netxen_loopback_test(struct net_device *netdev, int fint, void *ptr) +{ + int ii, ret; + unsigned char *data; + netxen_send_test_t args; + + if ((ret = copy_from_user(&args, ptr, sizeof(args)))) { + return (-LB_UCOPY_PARAM_ERR); + } + + if (tx_user_packet_data != NULL) { + kfree(tx_user_packet_data); + tx_user_packet_data = NULL; + } + + if (args.count != 0) { /* user data */ + tx_user_packet_data = kmalloc(args.count + 16, GFP_KERNEL); + if (tx_user_packet_data == NULL) + return (-LB_NOMEM_ERR); + memset(tx_user_packet_data, 0xFF, 16); + /* XXX args.ifg should be u64 */ + if (copy_from_user(tx_user_packet_data+16, + (char *)(uptr_t)args.ifg, args.count)) { + kfree(tx_user_packet_data); + tx_user_packet_data = NULL; + return (-LB_UCOPY_DATA_ERR); + } + tx_user_packet_length = args.count + 16; + rx_datalen = (tx_user_packet_length - 14) * 16; + } else { /* use local data */ + tx_user_packet_data = kmalloc(sizeof(XMIT_DATA) + 16, GFP_KERNEL); + if (tx_user_packet_data == NULL) + return (-LB_NOMEM_ERR); + memset(tx_user_packet_data, 0xFF, 14); + memcpy(tx_user_packet_data + 16, XMIT_DATA, sizeof(XMIT_DATA)); + tx_user_packet_length = sizeof(XMIT_DATA) + 16; + rx_datalen = (sizeof(XMIT_DATA) + 2) * 16; + } + if ((rx_user_packet_data = kmalloc(rx_datalen, GFP_KERNEL)) == NULL){ + ret = -LB_NOMEM_ERR; + goto end; + } + rx_user_pos = 0; + + if (fint == 1) { + loopback_start = 1; + xge_loopback(1); + } + + tx_stop = 0; + capture_input = 1; + captured = 0; + args.count = 16; + if ((ret = tx_test(netdev, &args)) != 0) { + ret = -LB_TX_NOSKB_ERR; + capture_input = 0; + goto end; + } + + mdelay(1000); /* wait for data to come back */ + capture_input = 0; + + if (rx_user_pos != rx_datalen) { + ret = -LB_SHORT_DATA_ERR; + goto end; + } + + data = rx_user_packet_data; + /* check received bytes against tx_user_packet_data */ + for (ii = 0; ii < 16; ++ii) { + if (*((uint16_t *)data) != (uint16_t)ii) { + ret = -LB_SEQUENCE_ERR; + goto end; + } + if (memcmp(tx_user_packet_data + 16, data + 2, + tx_user_packet_length - 16) + != 0) { + ret = -LB_DATA_ERR; + goto end; + } + data += (tx_user_packet_length - 14); + } + ret = LB_TEST_OK; + +end: + tx_stop = 1; + if (fint == 1) { + xge_loopback(0); + loopback_start = 0; + } + if (tx_user_packet_data != NULL) { + kfree(tx_user_packet_data); + tx_user_packet_data = NULL; + } + kfree(rx_user_packet_data); + rx_user_packet_data = NULL; + return(ret); +} + +static int +netxen_link_test(netxen_adapter *adapter) +{ + long rv; + + rv = xge_link_status (); + return((rv == XG_LINK_DOWN) ? (-1) : (0)); +} + +int netxentest_pegstuck(netxen_crbword_t addr, U64 reg, int loop, struct netxen_adapter_s *adapter) +{ + int i; + netxen_crbword_t temp; + + for (i = 0; i < loop; ++i) { + NetXen_CRB_READ_CHECK_ADAPTER(reg, &temp, adapter); + if (temp != addr) + return (0); + } + return (-1); +} + +static int +netxen_hw_test(netxen_adapter *adapter) +{ + netxen_crbword_t temp; + int ii, rc = HW_TEST_OK; + uint64_t base, address; + + /* DMA Status*/ + NetXen_CRB_READ_CHECK_ADAPTER(NetXen_DMA_COMMAND(0), &temp, adapter); + if ((temp & 0x3) == 0x3) { + rc = -HW_DMA_BZ_0; + goto done; + } + NetXen_CRB_READ_CHECK_ADAPTER(NetXen_DMA_COMMAND(1), &temp, adapter); + if ((temp & 0x3) == 0x3) { + rc = -HW_DMA_BZ_1; + goto done; + } + NetXen_CRB_READ_CHECK_ADAPTER(NetXen_DMA_COMMAND(2), &temp, adapter); + if ((temp & 0x3) == 0x3) { + rc = -HW_DMA_BZ_2; + goto done; + } + NetXen_CRB_READ_CHECK_ADAPTER(NetXen_DMA_COMMAND(3), &temp, adapter); + if ((temp & 0x3) == 0x3) { + rc = -HW_DMA_BZ_3; + goto done; + } + + /* SRE Status */ + NetXen_CRB_READ_CHECK_ADAPTER(NetXen_SRE_PBI_ACTIVE_STATUS, &temp, adapter); + if ((temp & 0x1) == 0) { + rc = -HW_SRE_PBI_HALT; + goto done; + } + NetXen_CRB_READ_CHECK_ADAPTER(NetXen_SRE_L1RE_CTL, &temp, adapter); + if ((temp & 0x20000000) != 0) { + rc = -HW_SRE_L1IPQ; + goto done; + } + NetXen_CRB_READ_CHECK_ADAPTER(NetXen_SRE_L2RE_CTL, &temp, adapter); + if ((temp & 0x20000000) != 0) { + rc = -HW_SRE_L2IFQ; + goto done; + } + + NetXen_CRB_READ_CHECK_ADAPTER(NetXen_SRE_INT_STATUS, &temp, adapter); + if ((temp & 0xc0ff) != 0) { + if ((temp & 0x1) != 0) { + rc = -HW_PQ_W_PAUSE; + goto done; + } + if ((temp & 0x2) != 0) { + rc = -HW_PQ_W_FULL; + goto done; + } + if ((temp & 0x4) != 0) { + rc = -HW_IFQ_W_PAUSE; + goto done; + } + if ((temp & 0x8) != 0) { + rc = -HW_IFQ_W_FULL; + goto done; + } + if ((temp & 0x10) != 0) { + rc = -HW_MEN_BP_TOUT; + goto done; + } + if ((temp & 0x20) != 0) { + rc = -HW_DOWN_BP_TOUT; + goto done; + } + if ((temp & 0x40) != 0) { + rc = -HW_FBUFF_POOL_WM; + goto done; + } + if ((temp & 0x80) != 0) { + rc = -HW_PBUF_ERR; + goto done; + } + if ((temp & 0x4000) != 0) { + rc = -HW_FM_MSG_HDR; + goto done; + } + if ((temp & 0x8000) != 0) { + rc = -HW_FM_MSG; + goto done; + } + } + + NetXen_CRB_READ_CHECK_ADAPTER(NetXen_SRE_INT_STATUS, &temp, adapter); + + if ((temp & 0x3f00) != 0) { + if ((temp & 0x100) != 0) { + rc = -HW_EPG_MSG_BUF; + goto done; + } + if ((temp & 0x200) != 0) { + rc = -HW_EPG_QREAD_TOUT; + goto done; + } + if ((temp & 0x400) != 0) { + rc = -HW_EPG_QWRITE_TOUT; + goto done; + } + if ((temp & 0x800) != 0) { + rc = -HW_EPG_CQ_W_FULL; + goto done; + } + if ((temp & 0x1000) != 0) { + rc = -HW_EPG_MSG_CHKSM; + goto done; + } + if ((temp & 0x2000) != 0) { + rc = -HW_EPG_MTLQ_TOUT; + goto done; + } + } + + /* Pegs */ + + for (ii = 0; ii < 4; ++ii) { + base = PEG_NETWORK_BASE(ii); + address = base | CRB_REG_EX_PC; + NetXen_CRB_READ_CHECK_ADAPTER(address, &temp, adapter); + rc = netxentest_pegstuck(temp, address, PEG_LOOP, adapter); + if (rc != 0) { + rc = -(HW_PEG0 + ii); + goto done; + } + } + +done: + return (rc); +} + +static int +netxen_cis_test(netxen_adapter *adapter) +{ + netxen_crbword_t temp, temp1; + int ret = CIS_TEST_OK; + + /* Read CAM RAM CRB registers: producer and consumer index for + command descriptors. Make sure that P==C or P-C=n0, + where n is acceptable number (what range?)*/ + NetXen_CRB_READ_CHECK_ADAPTER(CRB_CMD_PRODUCER_OFFSET, &temp, adapter); + NetXen_CRB_READ_CHECK_ADAPTER(CRB_CMD_CONSUMER_OFFSET, &temp1, adapter); + + if (DIDX_DIF(temp, temp1) > CIS_WATERMARK) + ret = -CIS_WMARK; + return (ret); +} + +static int +netxen_cr_test(netxen_adapter *adapter) +{ + + netxen_crbword_t temp; + int ret = CR_TEST_OK; + + NetXen_CRB_READ_CHECK_ADAPTER(NetXen_NIU_MODE, &temp, adapter); + + if ((temp & 0x03) == 0) { + ret = -CR_NIU_MODE; + goto done; + } + + if (adapter->ahw.board_type == NetXen_BRDTYPE_P2_SB31_10G || + adapter->ahw.board_type == NetXen_BRDTYPE_P2_SB31_10G_IMEZ || + adapter->ahw.board_type == NetXen_BRDTYPE_P2_SB31_10G_HMEZ || + adapter->ahw.board_type == NetXen_BRDTYPE_P2_SB31_10G_CX4) + NetXen_CRB_READ_CHECK_ADAPTER(NetXen_NIU_XGE_CONFIG_0, &temp, adapter); + else + NetXen_CRB_READ_CHECK_ADAPTER(NetXen_NIU_GB_MAC_CONFIG_0(0), &temp, adapter); + + if ((temp & 0x5) != 0x5) /* Tx or Rx not enabled */ + ret = -CR_PHY; + +done: + return (ret); +} + +/* + * netxen_nic_ioctl () We provide the tcl/phanmon support through these + * ioctls. + */ +static int +netxen_nic_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + int err = 0; + struct netxen_port *port = netdev->priv; + struct netxen_adapter_s *adapter = port->adapter; + + DPRINTK(1, INFO, "doing ioctl for %s\n", netdev->name); + switch (cmd) { + case NetXen_NIC_CMD: + err = netxen_nic_do_ioctl(adapter, (void *) ifr->ifr_data, port); + break; + + case NetXen_NIC_NAME: + DPRINTK(1, INFO, "ioctl cmd for NetXen\n"); + if (ifr->ifr_data) { + put_user(port->portnum, (uint16_t *)ifr->ifr_data); + } + break; + + case NetXen_NIC_SEND_TEST: + err = netxen_send_test(netdev, (void *)ifr->ifr_data); + break; + + case NetXen_NIC_IRQ_TEST: + err = netxen_irq_test(adapter); + break; + + case NetXen_NIC_ILB_TEST: + err = netxen_loopback_test(netdev, 1, (void *)ifr->ifr_data); + break; + + case NetXen_NIC_ELB_TEST: + err = netxen_loopback_test(netdev, 0, (void *)ifr->ifr_data); + break; + + case NetXen_NIC_LINK_TEST: + err = netxen_link_test(adapter); + break; + + case NetXen_NIC_HW_TEST: + err = netxen_hw_test(adapter); + break; + + case NetXen_NIC_CIS_TEST: + err = netxen_cis_test(adapter); + break; + + case NetXen_NIC_CR_TEST: + err = netxen_cr_test(adapter); + break; + + default: + DPRINTK(1, INFO, "ioctl cmd %x not supported\n", cmd); + err = -EOPNOTSUPP; + break; + } + + return err; +} + +static int +netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct netxen_port *port = netdev->priv; + + netif_device_detach(netdev); + + if(netif_running(netdev)) { + netif_carrier_off(netdev); + netif_stop_queue(netdev); + port->state = PORT_SUSPEND; + netxen_nic_down(port); + } + +/* pci_save_state(pdev, port->pci_state); */ +/* pci_disable_device(pdev); */ + + return 0; +} + +static int +netxen_nic_resume(struct pci_dev *pdev) +{ + uint32_t ret; + struct net_device *netdev = pci_get_drvdata(pdev); + struct netxen_port *port = netdev->priv; + ret = pci_enable_device(pdev); + port->state = PORT_UP; + netif_device_attach(netdev); + return ret; +} + +int +netxen_nic_fill_statistics(struct netxen_adapter_s *adapter, struct netxen_port *port, + struct netxen_statistics *netxen_stats) +{ + unsigned long flags; + void* addr; + if(adapter->ahw.board_type == NetXen_NIC_XGBE) { + write_lock_irqsave(&adapter->adapter_lock, flags); + netxen_nic_pci_change_crbwindow(adapter, 0); + NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_TX_BYTE_CNT, &(netxen_stats->tx_bytes)); + NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_TX_FRAME_CNT, &(netxen_stats->tx_packets)); + NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_RX_BYTE_CNT, &(netxen_stats->rx_bytes)); + NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_RX_FRAME_CNT, &(netxen_stats->rx_packets)); + NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_AGGR_ERROR_CNT, &(netxen_stats->rx_errors)); + NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_CRC_ERROR_CNT, &(netxen_stats->rx_CRC_errors)); + NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_OVERSIZE_FRAME_ERR, &(netxen_stats->rx_long_length_error)); + NetXen_NIC_LOCKED_READ_REG(NetXen_NIU_XGE_UNDERSIZE_FRAME_ERR, &(netxen_stats->rx_short_length_error)); + + /* For reading rx_MAC_error bit different procedure */ +/* NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_TEST_MUX_CTL, 0x15); + NetXen_NIC_LOCKED_READ_REG((NetXen_CRB_NIU + 0xC0), &temp); + netxen_stats->rx_MAC_errors = temp & 0xff; */ + + netxen_nic_pci_change_crbwindow(adapter, 1); + write_unlock_irqrestore(&adapter->adapter_lock, flags); + } else { + spin_lock_bh(&adapter->tx_lock); + netxen_stats->tx_bytes = port->stats.txbytes; + netxen_stats->tx_packets = port->stats.xmitedframes + + port->stats.xmitfinished; + netxen_stats->rx_bytes = port->stats.rxbytes; + netxen_stats->rx_packets = port->stats.no_rcv; + netxen_stats->rx_errors = port->stats.rcvdbadskb; + netxen_stats->tx_errors = port->stats.nocmddescriptor; + netxen_stats->rx_short_length_error = port->stats.uplcong; + netxen_stats->rx_long_length_error = port->stats.uphcong; + netxen_stats->rx_CRC_errors = 0; + netxen_stats->rx_MAC_errors = 0; + spin_unlock_bh(&adapter->tx_lock); + } + return 0; +} + +int +netxen_nic_clear_statistics(struct netxen_adapter_s *adapter, + struct netxen_port *port) +{ + unsigned long flags; + void* addr; + int data = 0; + + write_lock_irqsave(&adapter->adapter_lock, flags); + netxen_nic_pci_change_crbwindow(adapter, 0); + + NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_TX_BYTE_CNT, &data); + NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_TX_FRAME_CNT, &data); + NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_RX_BYTE_CNT, &data); + NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_RX_FRAME_CNT, &data); + NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_AGGR_ERROR_CNT, &data); + NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_CRC_ERROR_CNT, &data); + NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_OVERSIZE_FRAME_ERR, &data); + NetXen_NIC_LOCKED_WRITE_REG(NetXen_NIU_XGE_UNDERSIZE_FRAME_ERR, &data); + + netxen_nic_pci_change_crbwindow(adapter, 1); + write_unlock_irqrestore(&adapter->adapter_lock, flags); + netxen_nic_clear_stats(adapter); + return 0; +} +static int +netxen_nic_do_ioctl(struct netxen_adapter_s *adapter, void * u_data, + struct netxen_port *port) +{ + netxen_nic_ioctl_data_t data; + netxen_nic_ioctl_data_t *up_data; + int retval = 0; + struct netxen_statistics netxen_stats; + + up_data = (void*)u_data; + + DPRINTK(1, INFO, "doing ioctl for %p\n", adapter); + if (copy_from_user(&data, up_data, sizeof(data))) { + /* evil user tried to crash the kernel */ + DPRINTK(1, ERR, "bad copy from userland: %d\n", + (int)sizeof(data)); + retval = -EFAULT; + goto error_out; + } + + /* Shouldn't access beyond legal limits of "char u[64];" member */ + if (!data.ptr && (data.size > sizeof(data.u))) { + /* evil user tried to crash the kernel */ + DPRINTK(1, ERR, "bad size: %d\n", data.size); + retval = -EFAULT; + goto error_out; + } + + switch (data.cmd) { + case netxen_nic_cmd_pci_read: + if ((retval = netxen_nic_hw_read_wx(adapter, data.off, + &(data.u), data.size))) + goto error_out; + if (copy_to_user((void*)&(up_data->u), &(data.u), + data.size)) { + DPRINTK(1, ERR, "bad copy to userland: %d\n", + (int)sizeof(data)); + retval = -EFAULT; + goto error_out; + } + data.rv = 0; + break; + + case netxen_nic_cmd_pci_write: + data.rv = netxen_nic_hw_write_wx(adapter, data.off, &(data.u), + data.size); + break; + + case netxen_nic_cmd_pci_mem_read: + DPRINTK(1, INFO, "doing %s for %p\n", "netxen_nic_cmd_pci_mm_rd", + adapter); + netxen_nic_pci_mem_read(adapter, data.off, &(data.u), data.size); + if (copy_to_user((void*)&(up_data->u), &(data.u), data.size)){ + DPRINTK(1, ERR, "bad copy to userland: %d\n", + (int)sizeof(data)); + retval = -EFAULT; + goto error_out; + } + data.rv = 0; + DPRINTK(1, INFO, "read %lx\n", (unsigned long)data.u); + break; + + case netxen_nic_cmd_pci_mem_write: + netxen_nic_pci_mem_write(adapter, data.off, &(data.u), + data.size); + data.rv = 0; /* write always succeeds */ + break; + + case netxen_nic_cmd_pci_config_read: + switch(data.size) { + case 1: + data.rv = pci_read_config_byte(adapter->ahw.pdev, + data.off, + (char *)&(data.u)); + break; + case 2: + data.rv = pci_read_config_word(adapter->ahw.pdev, + data.off, + (short *)&(data.u)); + break; + case 4: + data.rv = pci_read_config_dword(adapter->ahw.pdev, + data.off, + (u32 *)&(data.u)); + break; + } + if(copy_to_user((void*)&(up_data->u), &(data.u), data.size)) { + DPRINTK(1, ERR, "bad copy to userland: %d\n", + (int)sizeof(data)); + retval = -EFAULT; + goto error_out; + } + break; + + case netxen_nic_cmd_pci_config_write: + switch(data.size) { + case 1: + data.rv = pci_write_config_byte(adapter->ahw.pdev, + data.off, + *(char *)&(data.u)); + break; + case 2: + data.rv = pci_write_config_word(adapter->ahw.pdev, + data.off, + *(short *)&(data.u)); + break; + case 4: + data.rv = pci_write_config_dword(adapter->ahw.pdev, + data.off, + *(u32 *)&(data.u)); + break; + } + break; + + case netxen_nic_cmd_get_stats: + data.rv = netxen_nic_fill_statistics(adapter, port, &netxen_stats); + if(copy_to_user((void*) (up_data->ptr), (void*)&netxen_stats, + sizeof(struct netxen_statistics))) { + DPRINTK(1, ERR, "bad copy to userland: %d\n", + (int)sizeof(netxen_stats)); + retval = -EFAULT; + goto error_out; + } + up_data->rv = data.rv; + break; + + case netxen_nic_cmd_clear_stats: + data.rv = netxen_nic_clear_statistics(adapter, port); + up_data->rv = data.rv; + break; + + case netxen_nic_cmd_get_version: + if(copy_to_user((void*)&(up_data->u), NetXen_NIC_LINUX_VERSIONID, + sizeof(NetXen_NIC_LINUX_VERSIONID))) { + DPRINTK(1, ERR, "bad copy to userland: %d\n", + (int)sizeof(data)); + retval = -EFAULT; + goto error_out; + } + break; + + + default: + DPRINTK(1, INFO, "bad command %d for %p\n", data.cmd, adapter); + retval = -EOPNOTSUPP; + goto error_out; + } + put_user(data.rv, &(up_data->rv)); + DPRINTK(1, INFO, "done ioctl for %p well.\n", adapter); + +error_out: + return retval; + +} + +static int +netxen_nic_port_read_proc(char *buf, char **start, off_t offset, int count, + int *eof, void *data) +{ + struct net_device *netdev = (struct net_device *)data; + int len = 0; + struct netxen_port *port = netdev->priv; + + if (netdev == NULL) { + len = sprintf(buf, "No Statistics available now. Device is" + " NULL\n"); + *eof = 1; + return len; + } + len = sprintf(buf, "NetXen NIC port statistics\n"); + len += sprintf(buf+len, "\n"); + len += sprintf(buf+len, "Interface Name : %s\n", + netdev->name); + len += sprintf(buf+len, "Port Number : %d\n", + port->portnum); + len += sprintf(buf+len, "Bad SKB : %lld\n", + port->stats.rcvdbadskb); + len += sprintf(buf+len, "Xmit called : %lld\n", + port->stats.xmitcalled); + len += sprintf(buf+len, "Xmited Frames : %lld\n", + port->stats.xmitedframes); + len += sprintf(buf+len, "Bad SKB length : %lld\n", + port->stats.badskblen); + len += sprintf(buf+len, "Cmd Desc Error : %lld\n", + port->stats.nocmddescriptor); + len += sprintf(buf+len, "Polled for Rcv : %lld\n", + port->stats.polled); + len += sprintf(buf+len, "Recieved Desc : %lld\n", + port->stats.no_rcv); + len += sprintf(buf+len, "Rcv to stack : %lld\n", + port->stats.uphappy); + len += sprintf(buf+len, "Stack dropped : %lld\n", + port->stats.updropped); + len += sprintf(buf+len, "Low congestion : %lld\n", + port->stats.uplcong); + len += sprintf(buf+len, "High congestion : %lld\n", + port->stats.uphcong); + len += sprintf(buf+len, "Medium congestion : %lld\n", + port->stats.upmcong); + len += sprintf(buf+len, "Rcv bad return : %lld\n", + port->stats.updunno); + len += sprintf(buf+len, "SKBs Freed : %lld\n", + port->stats.skbfreed); + len += sprintf(buf+len, "Xmit finished : %lld\n", + port->stats.xmitfinished); + len += sprintf(buf+len, "Tx dropped SKBs : %lld\n", + port->stats.txdropped); + len += sprintf(buf+len, "Tx got NULL SKBs : %lld\n", + port->stats.txnullskb); + len += sprintf(buf+len, "Rcv of CSUMed SKB : %lld\n", + port->stats.csummed); + len += sprintf(buf+len, "\n"); + *eof = 1; + return len; +} + +/* /proc interface to export debug info to the userland */ +static int +netxen_nic_read_proc(char *buf, char **start, off_t offset, int count,int *eof, + void *data) +{ + struct netxen_adapter_s *adapter = (struct netxen_adapter_s *)data; + int i, j; + int len = 0; + + if (adapter == NULL) { + len = sprintf(buf, "No Statistics available now." + " Adapter is NULL\n"); + *eof = 1; + return len; + } + len = sprintf(buf, "NetXen NIC statistics\n"); + len += sprintf(buf+len, "\n"); + len += sprintf(buf+len, "Ring Statistics\n"); + len += sprintf(buf+len, "Command Producer : %d\n", + adapter->cmdProducer); + len += sprintf(buf+len, "LastCommand Consumer: %d\n", + adapter->lastCmdConsumer); + for (i = 0; i < MAX_RCV_CTX; ++i) { + for (j = 0; j < NUM_RCV_DESC_RINGS; j++) { + len += sprintf(buf+len, "Rcv Ring %d\n", j); + len += sprintf(buf+len, "\tRecieve Producer [%d]:" + " %d\n", i, + adapter->recv_ctx[i].rcv_desc[j].producer); + } + len += sprintf(buf+len, "Status(Rcv) Producer[%d]: %d\n", + i, adapter->recv_ctx[i].statusRxProducer); + len += sprintf(buf+len, "Status(Rcv) Consumer[%d]: %d\n", + i, adapter->recv_ctx[i].statusRxConsumer); + } + len += sprintf(buf+len, "\n"); + len += sprintf(buf+len, "Adapter Statistics\n"); + len += sprintf(buf+len, "Interrupts : %lld\n", + adapter->stats.ints); + len += sprintf(buf+len, "Host Interrupts : %lld\n", + adapter->stats.hostints); + len += sprintf(buf+len, "Other Interrupts: %lld\n", + adapter->stats.otherints); + len += sprintf(buf+len, "Recieve Events : %lld\n", + adapter->stats.process_rcv); + len += sprintf(buf+len, "Transmit : %lld\n", + adapter->stats.process_xmit); + len += sprintf(buf+len, "No Transmit : %lld\n", + adapter->stats.noxmitdone); + len += sprintf(buf+len, "Xmit csummed : %lld\n", + adapter->stats.xmitcsummed); + len += sprintf(buf+len, "Posted : %lld\n", + adapter->stats.post_called); + len += sprintf(buf+len, "Posted : %lld\n", + adapter->stats.posted); + len += sprintf(buf+len, "Last post count : %lld\n", + adapter->stats.lastposted); + for (i = 0; i < MAX_RCV_CTX; ++i) { + for (j = 0; j < NUM_RCV_DESC_RINGS; j++) { + len += sprintf(buf+len, "Rcv Ring %d\n", j); + len += sprintf(buf+len, "\tfree Rx buffers[%d] : %d\n", + i, + adapter->recv_ctx[i].rcv_desc[j].rcv_free); + len += sprintf(buf+len, "\tpending Rx[%d] : %d\n", + i, + adapter->recv_ctx[i].rcv_desc[j].rcv_pending); + } + } + len += sprintf(buf+len, "Pending Cmd cnt : %d\n", + adapter->pendingCmdCount); + len += sprintf(buf+len, "Free Cmd Count : %d\n", + adapter->freeCmdCount); + len += sprintf(buf+len, "Good SKB posts : %lld\n", + adapter->stats.goodskbposts); + *eof = 1; + return len; +} + +static struct pci_driver netxen_driver = { + .name = netxen_nic_driver_name, + .id_table = netxen_pci_tbl, + .probe = netxen_nic_probe, + .remove = __devexit_p(netxen_nic_remove), + .suspend = netxen_nic_suspend, + .resume = netxen_nic_resume +}; + +/* Driver Registration on NetXen card */ + +static int __init +netxen_init_module(void) +{ + int i; + printk(KERN_INFO "%s \n", netxen_nic_driver_string); + netxen_proc_dir_entry = proc_mkdir(netxen_nic_driver_name, proc_net); + if (!netxen_proc_dir_entry) { + printk(KERN_WARNING "%s: Unable to create /proc/net/%s", + netxen_nic_driver_name, netxen_nic_driver_name); + return -ENOMEM; + } + netxen_proc_dir_entry->owner = THIS_MODULE; + + cmd_desc_cache = kmem_cache_create("cmd_desc_cache", + sizeof(cmdDescType0_t) * ((MAX_BUFFERS_PER_CMD/4)+3), + ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS, NULL, NULL); + cmd_buff_cache = kmem_cache_create("cmd_buff_cache", + sizeof(struct netxen_cmd_buffer), ARCH_KMALLOC_MINALIGN, + ARCH_KMALLOC_FLAGS, NULL, NULL); + for (i=0; i<NR_CPUS; i++) { + cmd_desc_array[i] = + (cmdDescType0_t *) kmem_cache_alloc (cmd_desc_cache, + SLAB_ATOMIC); + cmd_buff_array[i] = + (struct netxen_cmd_buffer *) kmem_cache_alloc (cmd_buff_cache, + SLAB_ATOMIC); + } + + pci_module_init(&netxen_driver); + + if (netxen_nic_probe_err != 0) { + for (i=0; i<NR_CPUS; i++) { + if (cmd_desc_array[i]) + kmem_cache_free(cmd_desc_cache, + cmd_desc_array[i]); + if (cmd_buff_array[i]) + kmem_cache_free(cmd_buff_cache, + cmd_buff_array[i]); + } + kmem_cache_destroy(cmd_desc_cache); + kmem_cache_destroy(cmd_buff_cache); + remove_proc_entry(netxen_proc_dir_entry->name, proc_net); + } + return netxen_nic_probe_err; +} + +module_init(netxen_init_module); + +static void __exit +netxen_exit_module(void) +{ + int i; + struct netxen_adapter_s *adapter; + + if (tx_user_packet_data != NULL) { + kfree(tx_user_packet_data); + tx_user_packet_data = NULL; + tx_user_packet_length = 0; + } + for(i=0; i<MAX_NUM_CARDS; i++) + { + adapter = adapterlist[i]; + if (adapter == NULL) + continue; + if (adapter->netlist != NULL && adapter->netlist->netdev != NULL) { +/* struct net_device *netdev = netxen_netlist->netdev; + struct netxen_port *port = netdev->priv; + struct netxen_adapter_s *adapter = port->adapter; +*/ + read_lock(&adapter->adapter_lock); + netxen_nic_disable_int(adapter); + read_unlock(&adapter->adapter_lock); + pinit_from_rom(adapter, 0); + } + } + + /* + * Wait for some time to allow the dma to drain, if any. + */ + mdelay(5); + pci_unregister_driver(&netxen_driver); + remove_proc_entry(netxen_proc_dir_entry->name, proc_net); + for (i=0; i<NR_CPUS; i++) { + if (cmd_desc_array[i]) + kmem_cache_free(cmd_desc_cache, cmd_desc_array[i]); + if (cmd_buff_array[i]) + kmem_cache_free(cmd_buff_cache, cmd_buff_array[i]); + } + kmem_cache_destroy(cmd_desc_cache); + kmem_cache_destroy(cmd_buff_cache); +} +module_exit(netxen_exit_module); +
- 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