X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fnet%2Fs2io.c;h=001a56254efc1c70ef6ac20597fa198ae2171777;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=c68c1c0e7163926950a0129e71bba1faf4dc6f03;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index c68c1c0e7..001a56254 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -26,17 +26,13 @@ * * The module loadable parameters that are supported by the driver and a brief * explaination of all the variables. - * ring_num : This can be used to program the number of receive rings used + * rx_ring_num : This can be used to program the number of receive rings used * in the driver. - * frame_len: This is an array of size 8. Using this we can set the maximum - * size of the received frame that can be steered into the corrsponding - * receive ring. - * ring_len: This defines the number of descriptors each ring can have. This + * rx_ring_len: This defines the number of descriptors each ring can have. This * is also an array of size 8. - * fifo_num: This defines the number of Tx FIFOs thats used int the driver. - * fifo_len: This too is an array of 8. Each element defines the number of + * tx_fifo_num: This defines the number of Tx FIFOs thats used int the driver. + * tx_fifo_len: This too is an array of 8. Each element defines the number of * Tx descriptors that can be associated with each corresponding FIFO. - * latency_timer: This input is programmed into the Latency timer register * in PCI Configuration space. ************************************************************************/ @@ -69,21 +65,30 @@ /* S2io Driver name & version. */ static char s2io_driver_name[] = "s2io"; -static char s2io_driver_version[] = "Version 1.0"; +static char s2io_driver_version[] = "Version 1.7.5.1"; + +/* + * Cards with following subsystem_id have a link state indication + * problem, 600B, 600C, 600D, 640B, 640C and 640D. + * macro below identifies these cards given the subsystem_id. + */ +#define CARDS_WITH_FAULTY_LINK_INDICATORS(subid) \ + (((subid >= 0x600B) && (subid <= 0x600D)) || \ + ((subid >= 0x640B) && (subid <= 0x640D))) ? 1 : 0 #define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \ ADAPTER_STATUS_RMAC_LOCAL_FAULT))) -#define TASKLET_IN_USE test_and_set_bit(0, \ - (unsigned long *)(&sp->tasklet_status)) +#define TASKLET_IN_USE test_and_set_bit(0, (&sp->tasklet_status)) #define PANIC 1 #define LOW 2 static inline int rx_buffer_level(nic_t * sp, int rxb_size, int ring) { int level = 0; - if ((sp->pkt_cnt[ring] - rxb_size) > 128) { + if ((sp->pkt_cnt[ring] - rxb_size) > 16) { level = LOW; - if (rxb_size < sp->pkt_cnt[ring] / 8) + if ((sp->pkt_cnt[ring] - rxb_size) < MAX_RXDS_PER_BLOCK) { level = PANIC; + } } return level; @@ -99,45 +104,45 @@ static char s2io_gstrings[][ETH_GSTRING_LEN] = { }; static char ethtool_stats_keys[][ETH_GSTRING_LEN] = { - "tmac_frms", - "tmac_data_octets", - "tmac_drop_frms", - "tmac_mcst_frms", - "tmac_bcst_frms", - "tmac_pause_ctrl_frms", - "tmac_any_err_frms", - "tmac_vld_ip_octets", - "tmac_vld_ip", - "tmac_drop_ip", - "tmac_icmp", - "tmac_rst_tcp", - "tmac_tcp", - "tmac_udp", - "rmac_vld_frms", - "rmac_data_octets", - "rmac_fcs_err_frms", - "rmac_drop_frms", - "rmac_vld_mcst_frms", - "rmac_vld_bcst_frms", - "rmac_in_rng_len_err_frms", - "rmac_long_frms", - "rmac_pause_ctrl_frms", - "rmac_discarded_frms", - "rmac_usized_frms", - "rmac_osized_frms", - "rmac_frag_frms", - "rmac_jabber_frms", - "rmac_ip", - "rmac_ip_octets", - "rmac_hdr_err_ip", - "rmac_drop_ip", - "rmac_icmp", - "rmac_tcp", - "rmac_udp", - "rmac_err_drp_udp", - "rmac_pause_cnt", - "rmac_accepted_ip", - "rmac_err_tcp", + {"tmac_frms"}, + {"tmac_data_octets"}, + {"tmac_drop_frms"}, + {"tmac_mcst_frms"}, + {"tmac_bcst_frms"}, + {"tmac_pause_ctrl_frms"}, + {"tmac_any_err_frms"}, + {"tmac_vld_ip_octets"}, + {"tmac_vld_ip"}, + {"tmac_drop_ip"}, + {"tmac_icmp"}, + {"tmac_rst_tcp"}, + {"tmac_tcp"}, + {"tmac_udp"}, + {"rmac_vld_frms"}, + {"rmac_data_octets"}, + {"rmac_fcs_err_frms"}, + {"rmac_drop_frms"}, + {"rmac_vld_mcst_frms"}, + {"rmac_vld_bcst_frms"}, + {"rmac_in_rng_len_err_frms"}, + {"rmac_long_frms"}, + {"rmac_pause_ctrl_frms"}, + {"rmac_discarded_frms"}, + {"rmac_usized_frms"}, + {"rmac_osized_frms"}, + {"rmac_frag_frms"}, + {"rmac_jabber_frms"}, + {"rmac_ip"}, + {"rmac_ip_octets"}, + {"rmac_hdr_err_ip"}, + {"rmac_drop_ip"}, + {"rmac_icmp"}, + {"rmac_tcp"}, + {"rmac_udp"}, + {"rmac_err_drp_udp"}, + {"rmac_pause_cnt"}, + {"rmac_accepted_ip"}, + {"rmac_err_tcp"}, }; #define S2IO_STAT_LEN sizeof(ethtool_stats_keys)/ ETH_GSTRING_LEN @@ -147,7 +152,8 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = { #define S2IO_STRINGS_LEN S2IO_TEST_LEN * ETH_GSTRING_LEN -/* Constants to be programmed into the Xena's registers to configure +/* + * Constants to be programmed into the Xena's registers, to configure * the XAUI. */ @@ -188,7 +194,9 @@ static u64 default_dtx_cfg[] = { END_SIGN }; -/* Constants for Fixing the MacAddress problem seen mostly on + +/* + * Constants for Fixing the MacAddress problem seen mostly on * Alpha machines. */ static u64 fix_mac[] = { @@ -209,16 +217,23 @@ static u64 fix_mac[] = { END_SIGN }; - /* Module Loadable parameters. */ -static u32 ring_num; -static u32 frame_len[MAX_RX_RINGS]; -static u32 ring_len[MAX_RX_RINGS]; -static u32 fifo_num; -static u32 fifo_len[MAX_TX_FIFOS]; -static u32 rx_prio; -static u32 tx_prio; -static u8 latency_timer = 0; +static unsigned int tx_fifo_num = 1; +static unsigned int tx_fifo_len[MAX_TX_FIFOS] = + {[0 ...(MAX_TX_FIFOS - 1)] = 0 }; +static unsigned int rx_ring_num = 1; +static unsigned int rx_ring_sz[MAX_RX_RINGS] = + {[0 ...(MAX_RX_RINGS - 1)] = 0 }; +static unsigned int Stats_refresh_time = 4; +static unsigned int rmac_pause_time = 65535; +static unsigned int mc_pause_threshold_q0q3 = 187; +static unsigned int mc_pause_threshold_q4q7 = 187; +static unsigned int shared_splits; +static unsigned int tmac_util_period = 5; +static unsigned int rmac_util_period = 5; +#ifndef CONFIG_S2IO_NAPI +static unsigned int indicate_max_pkts; +#endif /* * S2IO device table. @@ -241,24 +256,30 @@ static struct pci_driver s2io_driver = { .remove = __devexit_p(s2io_rem_nic), }; -/* - * Input Arguments: - * Device private variable. - * Return Value: - * SUCCESS on success and an appropriate -ve value on failure. - * Description: - * The function allocates the all memory areas shared - * between the NIC and the driver. This includes Tx descriptors, - * Rx descriptors and the statistics block. +/* A simplifier macro used both by init and free shared_mem Fns(). */ +#define TXD_MEM_PAGE_CNT(len, per_each) ((len+per_each - 1) / per_each) + +/** + * init_shared_mem - Allocation and Initialization of Memory + * @nic: Device private variable. + * Description: The function allocates all the memory areas shared + * between the NIC and the driver. This includes Tx descriptors, + * Rx descriptors and the statistics block. */ -static int initSharedMem(struct s2io_nic *nic) + +static int init_shared_mem(struct s2io_nic *nic) { u32 size; void *tmp_v_addr, *tmp_v_addr_next; dma_addr_t tmp_p_addr, tmp_p_addr_next; RxD_block_t *pre_rxd_blk = NULL; int i, j, blk_cnt; + int lst_size, lst_per_page; struct net_device *dev = nic->dev; +#ifdef CONFIG_2BUFF_MODE + unsigned long tmp; + buffAdd_t *ba; +#endif mac_info_t *mac_control; struct config_param *config; @@ -269,8 +290,8 @@ static int initSharedMem(struct s2io_nic *nic) /* Allocation and initialization of TXDLs in FIOFs */ size = 0; - for (i = 0; i < config->TxFIFONum; i++) { - size += config->TxCfg[i].FifoLen; + for (i = 0; i < config->tx_fifo_num; i++) { + size += config->tx_cfg[i].fifo_len; } if (size > MAX_AVAILABLE_TXDS) { DBG_PRINT(ERR_DBG, "%s: Total number of Tx FIFOs ", @@ -279,77 +300,96 @@ static int initSharedMem(struct s2io_nic *nic) DBG_PRINT(ERR_DBG, "that can be used\n"); return FAILURE; } - size *= (sizeof(TxD_t) * config->MaxTxDs); - - mac_control->txd_list_mem = pci_alloc_consistent - (nic->pdev, size, &mac_control->txd_list_mem_phy); - if (!mac_control->txd_list_mem) { - return -ENOMEM; - } - mac_control->txd_list_mem_sz = size; - - tmp_v_addr = mac_control->txd_list_mem; - tmp_p_addr = mac_control->txd_list_mem_phy; - memset(tmp_v_addr, 0, size); - DBG_PRINT(INIT_DBG, "%s:List Mem PHY: 0x%llx\n", dev->name, - (unsigned long long) tmp_p_addr); + lst_size = (sizeof(TxD_t) * config->max_txds); + lst_per_page = PAGE_SIZE / lst_size; - for (i = 0; i < config->TxFIFONum; i++) { - mac_control->txdl_start_phy[i] = tmp_p_addr; - mac_control->txdl_start[i] = (TxD_t *) tmp_v_addr; + for (i = 0; i < config->tx_fifo_num; i++) { + int fifo_len = config->tx_cfg[i].fifo_len; + int list_holder_size = fifo_len * sizeof(list_info_hold_t); + nic->list_info[i] = kmalloc(list_holder_size, GFP_KERNEL); + if (!nic->list_info[i]) { + DBG_PRINT(ERR_DBG, + "Malloc failed for list_info\n"); + return -ENOMEM; + } + memset(nic->list_info[i], 0, list_holder_size); + } + for (i = 0; i < config->tx_fifo_num; i++) { + int page_num = TXD_MEM_PAGE_CNT(config->tx_cfg[i].fifo_len, + lst_per_page); mac_control->tx_curr_put_info[i].offset = 0; mac_control->tx_curr_put_info[i].fifo_len = - config->TxCfg[i].FifoLen - 1; + config->tx_cfg[i].fifo_len - 1; mac_control->tx_curr_get_info[i].offset = 0; mac_control->tx_curr_get_info[i].fifo_len = - config->TxCfg[i].FifoLen - 1; - - tmp_p_addr += - (config->TxCfg[i].FifoLen * (sizeof(TxD_t)) * - config->MaxTxDs); - tmp_v_addr += - (config->TxCfg[i].FifoLen * (sizeof(TxD_t)) * - config->MaxTxDs); + config->tx_cfg[i].fifo_len - 1; + for (j = 0; j < page_num; j++) { + int k = 0; + dma_addr_t tmp_p; + void *tmp_v; + tmp_v = pci_alloc_consistent(nic->pdev, + PAGE_SIZE, &tmp_p); + if (!tmp_v) { + DBG_PRINT(ERR_DBG, + "pci_alloc_consistent "); + DBG_PRINT(ERR_DBG, "failed for TxDL\n"); + return -ENOMEM; + } + while (k < lst_per_page) { + int l = (j * lst_per_page) + k; + if (l == config->tx_cfg[i].fifo_len) + goto end_txd_alloc; + nic->list_info[i][l].list_virt_addr = + tmp_v + (k * lst_size); + nic->list_info[i][l].list_phy_addr = + tmp_p + (k * lst_size); + k++; + } + } } + end_txd_alloc: /* Allocation and initialization of RXDs in Rings */ size = 0; - for (i = 0; i < config->RxRingNum; i++) { - if (config->RxCfg[i].NumRxd % (MAX_RXDS_PER_BLOCK + 1)) { + for (i = 0; i < config->rx_ring_num; i++) { + if (config->rx_cfg[i].num_rxd % (MAX_RXDS_PER_BLOCK + 1)) { DBG_PRINT(ERR_DBG, "%s: RxD count of ", dev->name); DBG_PRINT(ERR_DBG, "Ring%d is not a multiple of ", i); DBG_PRINT(ERR_DBG, "RxDs per Block"); return FAILURE; } - size += config->RxCfg[i].NumRxd; + size += config->rx_cfg[i].num_rxd; nic->block_count[i] = - config->RxCfg[i].NumRxd / (MAX_RXDS_PER_BLOCK + 1); + config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1); nic->pkt_cnt[i] = - config->RxCfg[i].NumRxd - nic->block_count[i]; + config->rx_cfg[i].num_rxd - nic->block_count[i]; } - size = (size * (sizeof(RxD_t))); - mac_control->rxd_ring_mem_sz = size; - for (i = 0; i < config->RxRingNum; i++) { + for (i = 0; i < config->rx_ring_num; i++) { mac_control->rx_curr_get_info[i].block_index = 0; mac_control->rx_curr_get_info[i].offset = 0; mac_control->rx_curr_get_info[i].ring_len = - config->RxCfg[i].NumRxd - 1; + config->rx_cfg[i].num_rxd - 1; mac_control->rx_curr_put_info[i].block_index = 0; mac_control->rx_curr_put_info[i].offset = 0; mac_control->rx_curr_put_info[i].ring_len = - config->RxCfg[i].NumRxd - 1; + config->rx_cfg[i].num_rxd - 1; blk_cnt = - config->RxCfg[i].NumRxd / (MAX_RXDS_PER_BLOCK + 1); + config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1); /* Allocating all the Rx blocks */ for (j = 0; j < blk_cnt; j++) { +#ifndef CONFIG_2BUFF_MODE size = (MAX_RXDS_PER_BLOCK + 1) * (sizeof(RxD_t)); +#else + size = SIZE_OF_BLOCK; +#endif tmp_v_addr = pci_alloc_consistent(nic->pdev, size, &tmp_p_addr); if (tmp_v_addr == NULL) { - /* In case of failure, freeSharedMem() + /* + * In case of failure, free_shared_mem() * is called, which should free any * memory that was alloced till the * failure happened. @@ -377,20 +417,68 @@ static int initSharedMem(struct s2io_nic *nic) pre_rxd_blk->reserved_1 = END_OF_BLOCK; /* last RxD * marker. */ +#ifndef CONFIG_2BUFF_MODE pre_rxd_blk->reserved_2_pNext_RxD_block = (unsigned long) tmp_v_addr_next; +#endif pre_rxd_blk->pNext_RxD_Blk_physical = (u64) tmp_p_addr_next; } } +#ifdef CONFIG_2BUFF_MODE + /* + * Allocation of Storages for buffer addresses in 2BUFF mode + * and the buffers as well. + */ + for (i = 0; i < config->rx_ring_num; i++) { + blk_cnt = + config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1); + nic->ba[i] = kmalloc((sizeof(buffAdd_t *) * blk_cnt), + GFP_KERNEL); + if (!nic->ba[i]) + return -ENOMEM; + for (j = 0; j < blk_cnt; j++) { + int k = 0; + nic->ba[i][j] = kmalloc((sizeof(buffAdd_t) * + (MAX_RXDS_PER_BLOCK + 1)), + GFP_KERNEL); + if (!nic->ba[i][j]) + return -ENOMEM; + while (k != MAX_RXDS_PER_BLOCK) { + ba = &nic->ba[i][j][k]; + + ba->ba_0_org = kmalloc + (BUF0_LEN + ALIGN_SIZE, GFP_KERNEL); + if (!ba->ba_0_org) + return -ENOMEM; + tmp = (unsigned long) ba->ba_0_org; + tmp += ALIGN_SIZE; + tmp &= ~((unsigned long) ALIGN_SIZE); + ba->ba_0 = (void *) tmp; + + ba->ba_1_org = kmalloc + (BUF1_LEN + ALIGN_SIZE, GFP_KERNEL); + if (!ba->ba_1_org) + return -ENOMEM; + tmp = (unsigned long) ba->ba_1_org; + tmp += ALIGN_SIZE; + tmp &= ~((unsigned long) ALIGN_SIZE); + ba->ba_1 = (void *) tmp; + k++; + } + } + } +#endif + /* Allocation and initialization of Statistics block */ size = sizeof(StatInfo_t); mac_control->stats_mem = pci_alloc_consistent (nic->pdev, size, &mac_control->stats_mem_phy); if (!mac_control->stats_mem) { - /* In case of failure, freeSharedMem() is called, which + /* + * In case of failure, free_shared_mem() is called, which * should free any memory that was alloced till the * failure happened. */ @@ -399,7 +487,7 @@ static int initSharedMem(struct s2io_nic *nic) mac_control->stats_mem_sz = size; tmp_v_addr = mac_control->stats_mem; - mac_control->StatsInfo = (StatInfo_t *) tmp_v_addr; + mac_control->stats_info = (StatInfo_t *) tmp_v_addr; memset(tmp_v_addr, 0, size); DBG_PRINT(INIT_DBG, "%s:Ring Mem PHY: 0x%llx\n", dev->name, @@ -408,22 +496,21 @@ static int initSharedMem(struct s2io_nic *nic) return SUCCESS; } -/* - * Input Arguments: - * Device peivate variable. - * Return Value: - * NONE - * Description: - * This function is to free all memory locations allocated by - * the initSharedMem() function and return it to the kernel. +/** + * free_shared_mem - Free the allocated Memory + * @nic: Device private variable. + * Description: This function is to free all memory locations allocated by + * the init_shared_mem() function and return it to the kernel. */ -static void freeSharedMem(struct s2io_nic *nic) + +static void free_shared_mem(struct s2io_nic *nic) { int i, j, blk_cnt, size; void *tmp_v_addr; dma_addr_t tmp_p_addr; mac_info_t *mac_control; struct config_param *config; + int lst_size, lst_per_page; if (!nic) @@ -432,15 +519,31 @@ static void freeSharedMem(struct s2io_nic *nic) mac_control = &nic->mac_control; config = &nic->config; - if (mac_control->txd_list_mem) { - pci_free_consistent(nic->pdev, - mac_control->txd_list_mem_sz, - mac_control->txd_list_mem, - mac_control->txd_list_mem_phy); + lst_size = (sizeof(TxD_t) * config->max_txds); + lst_per_page = PAGE_SIZE / lst_size; + + for (i = 0; i < config->tx_fifo_num; i++) { + int page_num = TXD_MEM_PAGE_CNT(config->tx_cfg[i].fifo_len, + lst_per_page); + for (j = 0; j < page_num; j++) { + int mem_blks = (j * lst_per_page); + if (!nic->list_info[i][mem_blks].list_virt_addr) + break; + pci_free_consistent(nic->pdev, PAGE_SIZE, + nic->list_info[i][mem_blks]. + list_virt_addr, + nic->list_info[i][mem_blks]. + list_phy_addr); + } + kfree(nic->list_info[i]); } +#ifndef CONFIG_2BUFF_MODE size = (MAX_RXDS_PER_BLOCK + 1) * (sizeof(RxD_t)); - for (i = 0; i < config->RxRingNum; i++) { +#else + size = SIZE_OF_BLOCK; +#endif + for (i = 0; i < config->rx_ring_num; i++) { blk_cnt = nic->block_count[i]; for (j = 0; j < blk_cnt; j++) { tmp_v_addr = nic->rx_blocks[i][j].block_virt_addr; @@ -452,6 +555,42 @@ static void freeSharedMem(struct s2io_nic *nic) } } +#ifdef CONFIG_2BUFF_MODE + /* Freeing buffer storage addresses in 2BUFF mode. */ + for (i = 0; i < config->rx_ring_num; i++) { + blk_cnt = + config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1); + if (!nic->ba[i]) + goto end_free; + for (j = 0; j < blk_cnt; j++) { + int k = 0; + if (!nic->ba[i][j]) { + kfree(nic->ba[i]); + goto end_free; + } + while (k != MAX_RXDS_PER_BLOCK) { + buffAdd_t *ba = &nic->ba[i][j][k]; + if (!ba || !ba->ba_0_org || !ba->ba_1_org) + { + kfree(nic->ba[i]); + kfree(nic->ba[i][j]); + if(ba->ba_0_org) + kfree(ba->ba_0_org); + if(ba->ba_1_org) + kfree(ba->ba_1_org); + goto end_free; + } + kfree(ba->ba_0_org); + kfree(ba->ba_1_org); + k++; + } + kfree(nic->ba[i][j]); + } + kfree(nic->ba[i]); + } +end_free: +#endif + if (mac_control->stats_mem) { pci_free_consistent(nic->pdev, mac_control->stats_mem_sz, @@ -460,21 +599,21 @@ static void freeSharedMem(struct s2io_nic *nic) } } -/* - * Input Arguments: - * device peivate variable - * Return Value: - * SUCCESS on success and '-1' on failure (endian settings incorrect). - * Description: - * The function sequentially configures every block +/** + * init_nic - Initialization of hardware + * @nic: device peivate variable + * Description: The function sequentially configures every block * of the H/W from their reset values. + * Return Value: SUCCESS on success and + * '-1' on failure (endian settings incorrect). */ -static int initNic(struct s2io_nic *nic) + +static int init_nic(struct s2io_nic *nic) { - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; struct net_device *dev = nic->dev; register u64 val64 = 0; - void *add; + void __iomem *add; u32 time; int i, j; mac_info_t *mac_control; @@ -485,11 +624,13 @@ static int initNic(struct s2io_nic *nic) mac_control = &nic->mac_control; config = &nic->config; - /* Set proper endian settings and verify the same by - * reading the PIF Feed-back register. + /* + * Set proper endian settings and verify the same by + * reading the PIF Feed-back register. */ #ifdef __BIG_ENDIAN - /* The device by default set to a big endian format, so + /* + * The device by default set to a big endian format, so * a big endian driver need not set anything. */ writeq(0xffffffffffffffffULL, &bar0->swapper_ctrl); @@ -510,7 +651,8 @@ static int initNic(struct s2io_nic *nic) SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE); writeq(val64, &bar0->swapper_ctrl); #else - /* Initially we enable all bits to make it accessible by + /* + * Initially we enable all bits to make it accessible by * the driver, then we selectively enable only those bits * that we want to set. */ @@ -537,8 +679,9 @@ static int initNic(struct s2io_nic *nic) writeq(val64, &bar0->swapper_ctrl); #endif - /* Verifying if endian settings are accurate by reading - * a feedback register. + /* + * Verifying if endian settings are accurate by + * reading a feedback register. */ val64 = readq(&bar0->pif_rd_swapper_fb); if (val64 != 0x0123456789ABCDEFULL) { @@ -559,10 +702,13 @@ static int initNic(struct s2io_nic *nic) schedule_timeout(HZ / 2); /* Enable Receiving broadcasts */ + add = &bar0->mac_cfg; val64 = readq(&bar0->mac_cfg); val64 |= MAC_RMAC_BCAST_ENABLE; writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); - writeq(val64, &bar0->mac_cfg); + writel((u32) val64, add); + writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); + writel((u32) (val64 >> 32), (add + 4)); /* Read registers in all blocks */ val64 = readq(&bar0->mac_int_mask); @@ -573,8 +719,9 @@ static int initNic(struct s2io_nic *nic) val64 = dev->mtu; writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len); - /* Configuring the XAUI Interface of Xena. - ***************************************** + /* + * Configuring the XAUI Interface of Xena. + * *************************************** * To Configure the Xena's XAUI, one has to write a series * of 64 bit values into two registers in a particular * sequence. Hence a macro 'SWITCH_SIGN' has been defined @@ -593,8 +740,8 @@ static int initNic(struct s2io_nic *nic) dtx_cnt++; goto mdio_cfg; } - writeq(default_dtx_cfg[dtx_cnt], - &bar0->dtx_control); + SPECIAL_REG_WRITE(default_dtx_cfg[dtx_cnt], + &bar0->dtx_control, UF); val64 = readq(&bar0->dtx_control); dtx_cnt++; } @@ -604,8 +751,8 @@ static int initNic(struct s2io_nic *nic) mdio_cnt++; goto dtx_cfg; } - writeq(default_mdio_cfg[mdio_cnt], - &bar0->mdio_control); + SPECIAL_REG_WRITE(default_mdio_cfg[mdio_cnt], + &bar0->mdio_control, UF); val64 = readq(&bar0->mdio_control); mdio_cnt++; } @@ -625,13 +772,13 @@ static int initNic(struct s2io_nic *nic) writeq(val64, &bar0->tx_fifo_partition_3); - for (i = 0, j = 0; i < config->TxFIFONum; i++) { + for (i = 0, j = 0; i < config->tx_fifo_num; i++) { val64 |= - vBIT(config->TxCfg[i].FifoLen - 1, ((i * 32) + 19), - 13) | vBIT(config->TxCfg[i].FifoPriority, + vBIT(config->tx_cfg[i].fifo_len - 1, ((i * 32) + 19), + 13) | vBIT(config->tx_cfg[i].fifo_priority, ((i * 32) + 5), 3); - if (i == (config->TxFIFONum - 1)) { + if (i == (config->tx_fifo_num - 1)) { if (i % 2 == 0) i++; } @@ -675,56 +822,59 @@ static int initNic(struct s2io_nic *nic) /* Rx DMA intialization. */ val64 = 0; - for (i = 0; i < config->RxRingNum; i++) { + for (i = 0; i < config->rx_ring_num; i++) { val64 |= - vBIT(config->RxCfg[i].RingPriority, (5 + (i * 8)), 3); + vBIT(config->rx_cfg[i].ring_priority, (5 + (i * 8)), + 3); } writeq(val64, &bar0->rx_queue_priority); - /* Allocating equal share of memory to all the configured - * Rings. + /* + * Allocating equal share of memory to all the + * configured Rings. */ val64 = 0; - for (i = 0; i < config->RxRingNum; i++) { + for (i = 0; i < config->rx_ring_num; i++) { switch (i) { case 0: - mem_share = (64 / config->RxRingNum + - 64 % config->RxRingNum); + mem_share = (64 / config->rx_ring_num + + 64 % config->rx_ring_num); val64 |= RX_QUEUE_CFG_Q0_SZ(mem_share); continue; case 1: - mem_share = (64 / config->RxRingNum); + mem_share = (64 / config->rx_ring_num); val64 |= RX_QUEUE_CFG_Q1_SZ(mem_share); continue; case 2: - mem_share = (64 / config->RxRingNum); + mem_share = (64 / config->rx_ring_num); val64 |= RX_QUEUE_CFG_Q2_SZ(mem_share); continue; case 3: - mem_share = (64 / config->RxRingNum); + mem_share = (64 / config->rx_ring_num); val64 |= RX_QUEUE_CFG_Q3_SZ(mem_share); continue; case 4: - mem_share = (64 / config->RxRingNum); + mem_share = (64 / config->rx_ring_num); val64 |= RX_QUEUE_CFG_Q4_SZ(mem_share); continue; case 5: - mem_share = (64 / config->RxRingNum); + mem_share = (64 / config->rx_ring_num); val64 |= RX_QUEUE_CFG_Q5_SZ(mem_share); continue; case 6: - mem_share = (64 / config->RxRingNum); + mem_share = (64 / config->rx_ring_num); val64 |= RX_QUEUE_CFG_Q6_SZ(mem_share); continue; case 7: - mem_share = (64 / config->RxRingNum); + mem_share = (64 / config->rx_ring_num); val64 |= RX_QUEUE_CFG_Q7_SZ(mem_share); continue; } } writeq(val64, &bar0->rx_queue_cfg); - /* Initializing the Tx round robin registers to 0. + /* + * Initializing the Tx round robin registers to 0. * Filling Tx and Rx round robin registers as per the * number of FIFOs and Rings is still TODO. */ @@ -734,20 +884,13 @@ static int initNic(struct s2io_nic *nic) writeq(0, &bar0->tx_w_round_robin_3); writeq(0, &bar0->tx_w_round_robin_4); - /* Disable Rx steering. Hard coding all packets be steered to + /* + * TODO + * Disable Rx steering. Hard coding all packets be steered to * Queue 0 for now. - * TODO*/ - if (rx_prio) { - u64 def = 0x8000000000000000ULL, tmp; - for (i = 0; i < MAX_RX_RINGS; i++) { - tmp = (u64) (def >> (i % config->RxRingNum)); - val64 |= (u64) (tmp >> (i * 8)); - } - writeq(val64, &bar0->rts_qos_steering); - } else { - val64 = 0x8080808080808080ULL; - writeq(val64, &bar0->rts_qos_steering); - } + */ + val64 = 0x8080808080808080ULL; + writeq(val64, &bar0->rts_qos_steering); /* UDP Fix */ val64 = 0; @@ -760,34 +903,40 @@ static int initNic(struct s2io_nic *nic) /* Enable statistics */ writeq(mac_control->stats_mem_phy, &bar0->stat_addr); - val64 = SET_UPDT_PERIOD(8) | STAT_CFG_STAT_RO | STAT_CFG_STAT_EN; + val64 = SET_UPDT_PERIOD(Stats_refresh_time) | + STAT_CFG_STAT_RO | STAT_CFG_STAT_EN; writeq(val64, &bar0->stat_cfg); - /* Initializing the sampling rate for the device to calculate the + /* + * Initializing the sampling rate for the device to calculate the * bandwidth utilization. */ - val64 = MAC_TX_LINK_UTIL_VAL(0x5) | MAC_RX_LINK_UTIL_VAL(0x5); + val64 = MAC_TX_LINK_UTIL_VAL(tmac_util_period) | + MAC_RX_LINK_UTIL_VAL(rmac_util_period); writeq(val64, &bar0->mac_link_util); - /* Initializing the Transmit and Receive Traffic Interrupt + /* + * Initializing the Transmit and Receive Traffic Interrupt * Scheme. */ /* TTI Initialization */ val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0xFFF) | - TTI_DATA1_MEM_TX_URNG_A(0xA) | TTI_DATA1_MEM_TX_URNG_B(0x10) | + TTI_DATA1_MEM_TX_URNG_A(0xA) | + TTI_DATA1_MEM_TX_URNG_B(0x10) | TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN; writeq(val64, &bar0->tti_data1_mem); - val64 = - TTI_DATA2_MEM_TX_UFC_A(0x10) | TTI_DATA2_MEM_TX_UFC_B(0x20) | + val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) | + TTI_DATA2_MEM_TX_UFC_B(0x20) | TTI_DATA2_MEM_TX_UFC_C(0x40) | TTI_DATA2_MEM_TX_UFC_D(0x80); writeq(val64, &bar0->tti_data2_mem); val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD; writeq(val64, &bar0->tti_command_mem); - /* Once the operation completes, the Strobe bit of the command + /* + * Once the operation completes, the Strobe bit of the command * register will be reset. We poll for this particular condition * We wait for a maximum of 500ms for the operation to complete, * if it's not complete by then we return error. @@ -810,18 +959,22 @@ static int initNic(struct s2io_nic *nic) /* RTI Initialization */ val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF) | - RTI_DATA1_MEM_RX_URNG_A(0xA) | RTI_DATA1_MEM_RX_URNG_B(0x10) | + RTI_DATA1_MEM_RX_URNG_A(0xA) | + RTI_DATA1_MEM_RX_URNG_B(0x10) | RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN; + writeq(val64, &bar0->rti_data1_mem); - val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) | RTI_DATA2_MEM_RX_UFC_B(0x2) | + val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) | + RTI_DATA2_MEM_RX_UFC_B(0x2) | RTI_DATA2_MEM_RX_UFC_C(0x40) | RTI_DATA2_MEM_RX_UFC_D(0x80); writeq(val64, &bar0->rti_data2_mem); val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD; writeq(val64, &bar0->rti_command_mem); - /* Once the operation completes, the Strobe bit of the command + /* + * Once the operation completes, the Strobe bit of the command * register will be reset. We poll for this particular condition * We wait for a maximum of 500ms for the operation to complete, * if it's not complete by then we return error. @@ -842,14 +995,15 @@ static int initNic(struct s2io_nic *nic) schedule_timeout(HZ / 20); } - /* Initializing proper values as Pause threshold into all + /* + * Initializing proper values as Pause threshold into all * the 8 Queues on Rx side. */ writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q0q3); writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q4q7); /* Disable RMAC PAD STRIPPING */ - add = (void *) &bar0->mac_cfg; + add = &bar0->mac_cfg; val64 = readq(&bar0->mac_cfg); val64 &= ~(MAC_CFG_RMAC_STRIP_PAD); writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); @@ -858,24 +1012,64 @@ static int initNic(struct s2io_nic *nic) writel((u32) (val64 >> 32), (add + 4)); val64 = readq(&bar0->mac_cfg); + /* + * Set the time value to be inserted in the pause frame + * generated by xena. + */ + val64 = readq(&bar0->rmac_pause_cfg); + val64 &= ~(RMAC_PAUSE_HG_PTIME(0xffff)); + val64 |= RMAC_PAUSE_HG_PTIME(nic->mac_control.rmac_pause_time); + writeq(val64, &bar0->rmac_pause_cfg); + + /* + * Set the Threshold Limit for Generating the pause frame + * If the amount of data in any Queue exceeds ratio of + * (mac_control.mc_pause_threshold_q0q3 or q4q7)/256 + * pause frame is generated + */ + val64 = 0; + for (i = 0; i < 4; i++) { + val64 |= + (((u64) 0xFF00 | nic->mac_control. + mc_pause_threshold_q0q3) + << (i * 2 * 8)); + } + writeq(val64, &bar0->mc_pause_thresh_q0q3); + + val64 = 0; + for (i = 0; i < 4; i++) { + val64 |= + (((u64) 0xFF00 | nic->mac_control. + mc_pause_threshold_q4q7) + << (i * 2 * 8)); + } + writeq(val64, &bar0->mc_pause_thresh_q4q7); + + /* + * TxDMA will stop Read request if the number of read split has + * exceeded the limit pointed by shared_splits + */ + val64 = readq(&bar0->pic_control); + val64 |= PIC_CNTL_SHARED_SPLITS(shared_splits); + writeq(val64, &bar0->pic_control); + return SUCCESS; } -/* - * Input Arguments: - * device private variable, - * A mask indicating which Intr block must be modified and, - * A flag indicating whether to enable or disable the Intrs. - * Return Value: - * NONE. - * Description: - * This function will either disable or enable the interrupts +/** + * en_dis_able_nic_intrs - Enable or Disable the interrupts + * @nic: device private variable, + * @mask: A mask indicating which Intr block must be modified and, + * @flag: A flag indicating whether to enable or disable the Intrs. + * Description: This function will either disable or enable the interrupts * depending on the flag argument. The mask argument can be used to * enable/disable any Intr block. + * Return Value: NONE. */ -static void en_dis_able_NicIntrs(struct s2io_nic *nic, u16 mask, int flag) + +static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag) { - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64 = 0, temp64 = 0; /* Top level interrupt classification */ @@ -887,15 +1081,20 @@ static void en_dis_able_NicIntrs(struct s2io_nic *nic, u16 mask, int flag) temp64 = readq(&bar0->general_int_mask); temp64 &= ~((u64) val64); writeq(temp64, &bar0->general_int_mask); - /* Disabled all PCIX, Flash, MDIO, IIC and GPIO - * interrupts for now. - * TODO */ + /* + * Disabled all PCIX, Flash, MDIO, IIC and GPIO + * interrupts for now. + * TODO + */ writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask); - /* No MSI Support is available presently, so TTI and + /* + * No MSI Support is available presently, so TTI and * RTI interrupts are also disabled. */ } else if (flag == DISABLE_INTRS) { - /* Disable PIC Intrs in the general intr mask register + /* + * Disable PIC Intrs in the general + * intr mask register */ writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask); temp64 = readq(&bar0->general_int_mask); @@ -907,24 +1106,34 @@ static void en_dis_able_NicIntrs(struct s2io_nic *nic, u16 mask, int flag) /* DMA Interrupts */ /* Enabling/Disabling Tx DMA interrupts */ if (mask & TX_DMA_INTR) { - /* Enable TxDMA Intrs in the general intr mask register */ + /* Enable TxDMA Intrs in the general intr mask register */ val64 = TXDMA_INT_M; if (flag == ENABLE_INTRS) { temp64 = readq(&bar0->general_int_mask); temp64 &= ~((u64) val64); writeq(temp64, &bar0->general_int_mask); - /* Disable all interrupts other than PFC interrupt in - * DMA level. + /* + * Keep all interrupts other than PFC interrupt + * and PCC interrupt disabled in DMA level. */ - val64 = DISABLE_ALL_INTRS & (~TXDMA_PFC_INT_M); + val64 = DISABLE_ALL_INTRS & ~(TXDMA_PFC_INT_M | + TXDMA_PCC_INT_M); writeq(val64, &bar0->txdma_int_mask); - /* Enable only the MISC error 1 interrupt in PFC block + /* + * Enable only the MISC error 1 interrupt in PFC block */ val64 = DISABLE_ALL_INTRS & (~PFC_MISC_ERR_1); writeq(val64, &bar0->pfc_err_mask); + /* + * Enable only the FB_ECC error interrupt in PCC block + */ + val64 = DISABLE_ALL_INTRS & (~PCC_FB_ECC_ERR); + writeq(val64, &bar0->pcc_err_mask); } else if (flag == DISABLE_INTRS) { - /* Disable TxDMA Intrs in the general intr mask - * register */ + /* + * Disable TxDMA Intrs in the general intr mask + * register + */ writeq(DISABLE_ALL_INTRS, &bar0->txdma_int_mask); writeq(DISABLE_ALL_INTRS, &bar0->pfc_err_mask); temp64 = readq(&bar0->general_int_mask); @@ -941,12 +1150,16 @@ static void en_dis_able_NicIntrs(struct s2io_nic *nic, u16 mask, int flag) temp64 = readq(&bar0->general_int_mask); temp64 &= ~((u64) val64); writeq(temp64, &bar0->general_int_mask); - /* All RxDMA block interrupts are disabled for now - * TODO */ + /* + * All RxDMA block interrupts are disabled for now + * TODO + */ writeq(DISABLE_ALL_INTRS, &bar0->rxdma_int_mask); } else if (flag == DISABLE_INTRS) { - /* Disable RxDMA Intrs in the general intr mask - * register */ + /* + * Disable RxDMA Intrs in the general intr mask + * register + */ writeq(DISABLE_ALL_INTRS, &bar0->rxdma_int_mask); temp64 = readq(&bar0->general_int_mask); val64 |= temp64; @@ -962,9 +1175,11 @@ static void en_dis_able_NicIntrs(struct s2io_nic *nic, u16 mask, int flag) temp64 = readq(&bar0->general_int_mask); temp64 &= ~((u64) val64); writeq(temp64, &bar0->general_int_mask); - /* All MAC block error interrupts are disabled for now + /* + * All MAC block error interrupts are disabled for now * except the link status change interrupt. - * TODO*/ + * TODO + */ val64 = MAC_INT_STATUS_RMAC_INT; temp64 = readq(&bar0->mac_int_mask); temp64 &= ~((u64) val64); @@ -974,7 +1189,8 @@ static void en_dis_able_NicIntrs(struct s2io_nic *nic, u16 mask, int flag) val64 &= ~((u64) RMAC_LINK_STATE_CHANGE_INT); writeq(val64, &bar0->mac_rmac_err_mask); } else if (flag == DISABLE_INTRS) { - /* Disable MAC Intrs in the general intr mask register + /* + * Disable MAC Intrs in the general intr mask register */ writeq(DISABLE_ALL_INTRS, &bar0->mac_int_mask); writeq(DISABLE_ALL_INTRS, @@ -993,11 +1209,14 @@ static void en_dis_able_NicIntrs(struct s2io_nic *nic, u16 mask, int flag) temp64 = readq(&bar0->general_int_mask); temp64 &= ~((u64) val64); writeq(temp64, &bar0->general_int_mask); - /* All XGXS block error interrupts are disabled for now - * TODO */ + /* + * All XGXS block error interrupts are disabled for now + * TODO + */ writeq(DISABLE_ALL_INTRS, &bar0->xgxs_int_mask); } else if (flag == DISABLE_INTRS) { - /* Disable MC Intrs in the general intr mask register + /* + * Disable MC Intrs in the general intr mask register */ writeq(DISABLE_ALL_INTRS, &bar0->xgxs_int_mask); temp64 = readq(&bar0->general_int_mask); @@ -1013,11 +1232,14 @@ static void en_dis_able_NicIntrs(struct s2io_nic *nic, u16 mask, int flag) temp64 = readq(&bar0->general_int_mask); temp64 &= ~((u64) val64); writeq(temp64, &bar0->general_int_mask); - /* All MC block error interrupts are disabled for now - * TODO */ + /* + * All MC block error interrupts are disabled for now + * TODO + */ writeq(DISABLE_ALL_INTRS, &bar0->mc_int_mask); } else if (flag == DISABLE_INTRS) { - /* Disable MC Intrs in the general intr mask register + /* + * Disable MC Intrs in the general intr mask register */ writeq(DISABLE_ALL_INTRS, &bar0->mc_int_mask); temp64 = readq(&bar0->general_int_mask); @@ -1034,15 +1256,15 @@ static void en_dis_able_NicIntrs(struct s2io_nic *nic, u16 mask, int flag) temp64 = readq(&bar0->general_int_mask); temp64 &= ~((u64) val64); writeq(temp64, &bar0->general_int_mask); - /* Enable all the Tx side interrupts */ - writeq(0x0, &bar0->tx_traffic_mask); /* '0' Enables - * all 64 TX - * interrupt - * levels. - */ + /* + * Enable all the Tx side interrupts + * writing 0 Enables all 64 TX interrupt levels + */ + writeq(0x0, &bar0->tx_traffic_mask); } else if (flag == DISABLE_INTRS) { - /* Disable Tx Traffic Intrs in the general intr mask - * register. + /* + * Disable Tx Traffic Intrs in the general intr mask + * register. */ writeq(DISABLE_ALL_INTRS, &bar0->tx_traffic_mask); temp64 = readq(&bar0->general_int_mask); @@ -1058,14 +1280,12 @@ static void en_dis_able_NicIntrs(struct s2io_nic *nic, u16 mask, int flag) temp64 = readq(&bar0->general_int_mask); temp64 &= ~((u64) val64); writeq(temp64, &bar0->general_int_mask); - writeq(0x0, &bar0->rx_traffic_mask); /* '0' Enables - * all 8 RX - * interrupt - * levels. - */ + /* writing 0 Enables all 8 RX interrupt levels */ + writeq(0x0, &bar0->rx_traffic_mask); } else if (flag == DISABLE_INTRS) { - /* Disable Rx Traffic Intrs in the general intr mask - * register. + /* + * Disable Rx Traffic Intrs in the general intr mask + * register. */ writeq(DISABLE_ALL_INTRS, &bar0->rx_traffic_mask); temp64 = readq(&bar0->general_int_mask); @@ -1075,17 +1295,19 @@ static void en_dis_able_NicIntrs(struct s2io_nic *nic, u16 mask, int flag) } } -/* - * Input Arguments: - * val64 - Value read from adapter status register. - * flag - indicates if the adapter enable bit was ever written once before. - * Return Value: - * void. - * Description: - * Returns whether the H/W is ready to go or not. Depending on whether - * adapter enable bit was written or not the comparison differs and the - * calling function passes the input argument flag to indicate this. +/** + * verify_xena_quiescence - Checks whether the H/W is ready + * @val64 : Value read from adapter status register. + * @flag : indicates if the adapter enable bit was ever written once + * before. + * Description: Returns whether the H/W is ready to go or not. Depending + * on whether adapter enable bit was written or not the comparison + * differs and the calling function passes the input argument flag to + * indicate this. + * Return: 1 If xena is quiescence + * 0 If Xena is not quiescence */ + static int verify_xena_quiescence(u64 val64, int flag) { int ret = 0; @@ -1122,13 +1344,17 @@ static int verify_xena_quiescence(u64 val64, int flag) return ret; } -/* +/** + * fix_mac_address - Fix for Mac addr problem on Alpha platforms + * @sp: Pointer to device specifc structure + * Description : * New procedure to clear mac address reading problems on Alpha platforms * */ -void FixMacAddress(nic_t * sp) + +void fix_mac_address(nic_t * sp) { - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64; int i = 0; @@ -1138,21 +1364,22 @@ void FixMacAddress(nic_t * sp) } } -/* - * Input Arguments: - * device private variable. - * Return Value: - * SUCCESS on success and -1 on failure. +/** + * start_nic - Turns the device on + * @nic : device private variable. * Description: - * This function actually turns the device on. Before this - * function is called, all Registers are configured from their reset states + * This function actually turns the device on. Before this function is + * called,all Registers are configured from their reset states * and shared memory is allocated but the NIC is still quiescent. On * calling this function, the device interrupts are cleared and the NIC is * literally switched on by writing into the adapter control register. + * Return Value: + * SUCCESS on success and -1 on failure. */ -static int startNic(struct s2io_nic *nic) + +static int start_nic(struct s2io_nic *nic) { - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; struct net_device *dev = nic->dev; register u64 val64 = 0; u16 interruptible, i; @@ -1164,22 +1391,34 @@ static int startNic(struct s2io_nic *nic) config = &nic->config; /* PRC Initialization and configuration */ - for (i = 0; i < config->RxRingNum; i++) { + for (i = 0; i < config->rx_ring_num; i++) { writeq((u64) nic->rx_blocks[i][0].block_dma_addr, &bar0->prc_rxd0_n[i]); val64 = readq(&bar0->prc_ctrl_n[i]); +#ifndef CONFIG_2BUFF_MODE val64 |= PRC_CTRL_RC_ENABLED; +#else + val64 |= PRC_CTRL_RC_ENABLED | PRC_CTRL_RING_MODE_3; +#endif writeq(val64, &bar0->prc_ctrl_n[i]); } - /* Enabling MC-RLDRAM. After enabling the device, we timeout +#ifdef CONFIG_2BUFF_MODE + /* Enabling 2 buffer mode by writing into Rx_pa_cfg reg. */ + val64 = readq(&bar0->rx_pa_cfg); + val64 |= RX_PA_CFG_IGNORE_L2_ERR; + writeq(val64, &bar0->rx_pa_cfg); +#endif + + /* + * Enabling MC-RLDRAM. After enabling the device, we timeout * for around 100ms, which is approximately the time required * for the device to be ready for operation. */ val64 = readq(&bar0->mc_rldram_mrs); val64 |= MC_RLDRAM_QUEUE_SIZE_ENABLE | MC_RLDRAM_MRS_ENABLE; - writeq(val64, &bar0->mc_rldram_mrs); + SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_mrs, UF); val64 = readq(&bar0->mc_rldram_mrs); set_current_state(TASK_UNINTERRUPTIBLE); @@ -1190,14 +1429,16 @@ static int startNic(struct s2io_nic *nic) val64 &= ~ADAPTER_ECC_EN; writeq(val64, &bar0->adapter_control); - /* Clearing any possible Link state change interrupts that + /* + * Clearing any possible Link state change interrupts that * could have popped up just before Enabling the card. */ val64 = readq(&bar0->mac_rmac_err_reg); if (val64) writeq(val64, &bar0->mac_rmac_err_reg); - /* Verify if the device is ready to be enabled, if so enable + /* + * Verify if the device is ready to be enabled, if so enable * it. */ val64 = readq(&bar0->adapter_status); @@ -1211,9 +1452,10 @@ static int startNic(struct s2io_nic *nic) /* Enable select interrupts */ interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR | RX_MAC_INTR; - en_dis_able_NicIntrs(nic, interruptible, ENABLE_INTRS); + en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS); - /* With some switches, link might be already up at this point. + /* + * With some switches, link might be already up at this point. * Because of this weird behavior, when we enable laser, * we may not get link. We need to handle this. We cannot * figure out which switch is misbehaving. So we are forced to @@ -1232,92 +1474,90 @@ static int startNic(struct s2io_nic *nic) val64 |= 0x0000800000000000ULL; writeq(val64, &bar0->gpio_control); val64 = 0x0411040400000000ULL; - writeq(val64, (void *) ((u8 *) bar0 + 0x2700)); + writeq(val64, (void __iomem *) bar0 + 0x2700); } + /* + * Don't see link state interrupts on certain switches, so + * directly scheduling a link state task from here. + */ + schedule_work(&nic->set_link_task); + /* * Here we are performing soft reset on XGXS to * force link down. Since link is already up, we will get * link state change interrupt after this reset */ - writeq(0x8007051500000000ULL, &bar0->dtx_control); + SPECIAL_REG_WRITE(0x80010515001E0000ULL, &bar0->dtx_control, UF); val64 = readq(&bar0->dtx_control); - writeq(0x80070515000000E0ULL, &bar0->dtx_control); + udelay(50); + SPECIAL_REG_WRITE(0x80010515001E00E0ULL, &bar0->dtx_control, UF); val64 = readq(&bar0->dtx_control); - writeq(0x80070515001F00E4ULL, &bar0->dtx_control); + udelay(50); + SPECIAL_REG_WRITE(0x80070515001F00E4ULL, &bar0->dtx_control, UF); val64 = readq(&bar0->dtx_control); + udelay(50); return SUCCESS; } -/* - * Input Arguments: - * nic - device private variable. - * Return Value: - * void. +/** + * free_tx_buffers - Free all queued Tx buffers + * @nic : device private variable. * Description: - * Free all queued Tx buffers. - */ -void freeTxBuffers(struct s2io_nic *nic) + * Free all queued Tx buffers. + * Return Value: void +*/ + +void free_tx_buffers(struct s2io_nic *nic) { struct net_device *dev = nic->dev; struct sk_buff *skb; TxD_t *txdp; int i, j; -#if DEBUG_ON - int cnt = 0; -#endif mac_info_t *mac_control; struct config_param *config; + int cnt = 0; mac_control = &nic->mac_control; config = &nic->config; - for (i = 0; i < config->TxFIFONum; i++) { - for (j = 0; j < config->TxCfg[i].FifoLen - 1; j++) { - txdp = mac_control->txdl_start[i] + - (config->MaxTxDs * j); - - if (!(txdp->Control_1 & TXD_LIST_OWN_XENA)) { - /* If owned by host, ignore */ - continue; - } + for (i = 0; i < config->tx_fifo_num; i++) { + for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) { + txdp = (TxD_t *) nic->list_info[i][j]. + list_virt_addr; skb = (struct sk_buff *) ((unsigned long) txdp-> Host_Control); if (skb == NULL) { - DBG_PRINT(ERR_DBG, "%s: NULL skb ", - dev->name); - DBG_PRINT(ERR_DBG, "in Tx Int\n"); - return; + memset(txdp, 0, sizeof(TxD_t)); + continue; } -#if DEBUG_ON - cnt++; -#endif dev_kfree_skb(skb); memset(txdp, 0, sizeof(TxD_t)); + cnt++; } -#if DEBUG_ON DBG_PRINT(INTR_DBG, "%s:forcibly freeing %d skbs on FIFO%d\n", dev->name, cnt, i); -#endif + mac_control->tx_curr_get_info[i].offset = 0; + mac_control->tx_curr_put_info[i].offset = 0; } } -/* - * Input Arguments: - * nic - device private variable. - * Return Value: +/** + * stop_nic - To stop the nic + * @nic ; device private variable. + * Description: + * This function does exactly the opposite of what the start_nic() + * function does. This function is called to stop the device. + * Return Value: * void. - * Description: - * This function does exactly the opposite of what the startNic() - * function does. This function is called to stop - * the device. */ -static void stopNic(struct s2io_nic *nic) + +static void stop_nic(struct s2io_nic *nic) { - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64 = 0; u16 interruptible, i; mac_info_t *mac_control; @@ -1326,24 +1566,23 @@ static void stopNic(struct s2io_nic *nic) mac_control = &nic->mac_control; config = &nic->config; -/* Disable all interrupts */ + /* Disable all interrupts */ interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR | RX_MAC_INTR; - en_dis_able_NicIntrs(nic, interruptible, DISABLE_INTRS); + en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS); -/* Disable PRCs */ - for (i = 0; i < config->RxRingNum; i++) { + /* Disable PRCs */ + for (i = 0; i < config->rx_ring_num; i++) { val64 = readq(&bar0->prc_ctrl_n[i]); val64 &= ~((u64) PRC_CTRL_RC_ENABLED); writeq(val64, &bar0->prc_ctrl_n[i]); } } -/* - * Input Arguments: - * device private variable - * Return Value: - * SUCCESS on success or an appropriate -ve value on failure. +/** + * fill_rx_buffers - Allocates the Rx side skbs + * @nic: device private variable + * @ring_no: ring number * Description: * The function allocates Rx side skbs and puts the physical * address of these buffers into the RxD buffer pointers, so that the NIC @@ -1354,9 +1593,13 @@ static void stopNic(struct s2io_nic *nic) * 3. Five buffer modes. * Each mode defines how many fragments the received frame will be split * up into by the NIC. The frame is split into L3 header, L4 Header, - * L4 payload in three buffer mode and in 5 buffer mode, L4 payload itself - * is split into 3 fragments. As of now only single buffer mode is supported. + * L4 payload in three buffer mode and in 5 buffer mode, L4 payload itself + * is split into 3 fragments. As of now only single buffer mode is + * supported. + * Return Value: + * SUCCESS on success or an appropriate -ve value on failure. */ + int fill_rx_buffers(struct s2io_nic *nic, int ring_no) { struct net_device *dev = nic->dev; @@ -1369,19 +1612,22 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no) atomic_read(&nic->rx_bufs_left[ring_no]); mac_info_t *mac_control; struct config_param *config; +#ifdef CONFIG_2BUFF_MODE + RxD_t *rxdpnext; + int nextblk; + unsigned long tmp; + buffAdd_t *ba; + dma_addr_t rxdpphys; +#endif +#ifndef CONFIG_S2IO_NAPI + unsigned long flags; +#endif mac_control = &nic->mac_control; config = &nic->config; - if (frame_len[ring_no]) { - if (frame_len[ring_no] > dev->mtu) - dev->mtu = frame_len[ring_no]; - size = frame_len[ring_no] + HEADER_ETHERNET_II_802_3_SIZE + - HEADER_802_2_SIZE + HEADER_SNAP_SIZE; - } else { - size = dev->mtu + HEADER_ETHERNET_II_802_3_SIZE + - HEADER_802_2_SIZE + HEADER_SNAP_SIZE; - } + size = dev->mtu + HEADER_ETHERNET_II_802_3_SIZE + + HEADER_802_2_SIZE + HEADER_SNAP_SIZE; while (alloc_tab < alloc_cnt) { block_no = mac_control->rx_curr_put_info[ring_no]. @@ -1390,8 +1636,13 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no) block_index; off = mac_control->rx_curr_put_info[ring_no].offset; off1 = mac_control->rx_curr_get_info[ring_no].offset; +#ifndef CONFIG_2BUFF_MODE offset = block_no * (MAX_RXDS_PER_BLOCK + 1) + off; offset1 = block_no1 * (MAX_RXDS_PER_BLOCK + 1) + off1; +#else + offset = block_no * (MAX_RXDS_PER_BLOCK) + off; + offset1 = block_no1 * (MAX_RXDS_PER_BLOCK) + off1; +#endif rxdp = nic->rx_blocks[ring_no][block_no]. block_virt_addr + off; @@ -1400,7 +1651,7 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no) DBG_PRINT(INTR_DBG, " info equated\n"); goto end; } - +#ifndef CONFIG_2BUFF_MODE if (rxdp->Control_1 == END_OF_BLOCK) { mac_control->rx_curr_put_info[ring_no]. block_index++; @@ -1412,25 +1663,86 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no) off %= (MAX_RXDS_PER_BLOCK + 1); mac_control->rx_curr_put_info[ring_no].offset = off; - /*rxdp = nic->rx_blocks[ring_no][block_no]. - block_virt_addr + off; */ rxdp = (RxD_t *) ((unsigned long) rxdp->Control_2); DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n", dev->name, rxdp); } +#ifndef CONFIG_S2IO_NAPI + spin_lock_irqsave(&nic->put_lock, flags); + nic->put_pos[ring_no] = + (block_no * (MAX_RXDS_PER_BLOCK + 1)) + off; + spin_unlock_irqrestore(&nic->put_lock, flags); +#endif +#else + if (rxdp->Host_Control == END_OF_BLOCK) { + mac_control->rx_curr_put_info[ring_no]. + block_index++; + mac_control->rx_curr_put_info[ring_no]. + block_index %= nic->block_count[ring_no]; + block_no = mac_control->rx_curr_put_info + [ring_no].block_index; + off = 0; + DBG_PRINT(INTR_DBG, "%s: block%d at: 0x%llx\n", + dev->name, block_no, + (unsigned long long) rxdp->Control_1); + mac_control->rx_curr_put_info[ring_no].offset = + off; + rxdp = nic->rx_blocks[ring_no][block_no]. + block_virt_addr; + } +#ifndef CONFIG_S2IO_NAPI + spin_lock_irqsave(&nic->put_lock, flags); + nic->put_pos[ring_no] = (block_no * + (MAX_RXDS_PER_BLOCK + 1)) + off; + spin_unlock_irqrestore(&nic->put_lock, flags); +#endif +#endif - if (rxdp->Control_1 & RXD_OWN_XENA) { +#ifndef CONFIG_2BUFF_MODE + if (rxdp->Control_1 & RXD_OWN_XENA) +#else + if (rxdp->Control_2 & BIT(0)) +#endif + { mac_control->rx_curr_put_info[ring_no]. offset = off; goto end; } +#ifdef CONFIG_2BUFF_MODE + /* + * RxDs Spanning cache lines will be replenished only + * if the succeeding RxD is also owned by Host. It + * will always be the ((8*i)+3) and ((8*i)+6) + * descriptors for the 48 byte descriptor. The offending + * decsriptor is of-course the 3rd descriptor. + */ + rxdpphys = nic->rx_blocks[ring_no][block_no]. + block_dma_addr + (off * sizeof(RxD_t)); + if (((u64) (rxdpphys)) % 128 > 80) { + rxdpnext = nic->rx_blocks[ring_no][block_no]. + block_virt_addr + (off + 1); + if (rxdpnext->Host_Control == END_OF_BLOCK) { + nextblk = (block_no + 1) % + (nic->block_count[ring_no]); + rxdpnext = nic->rx_blocks[ring_no] + [nextblk].block_virt_addr; + } + if (rxdpnext->Control_2 & BIT(0)) + goto end; + } +#endif +#ifndef CONFIG_2BUFF_MODE skb = dev_alloc_skb(size + NET_IP_ALIGN); +#else + skb = dev_alloc_skb(dev->mtu + ALIGN_SIZE + BUF0_LEN + 4); +#endif if (!skb) { DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name); DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n"); return -ENOMEM; } +#ifndef CONFIG_2BUFF_MODE skb_reserve(skb, NET_IP_ALIGN); memset(rxdp, 0, sizeof(RxD_t)); rxdp->Buffer0_ptr = pci_map_single @@ -1442,6 +1754,35 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no) off++; off %= (MAX_RXDS_PER_BLOCK + 1); mac_control->rx_curr_put_info[ring_no].offset = off; +#else + ba = &nic->ba[ring_no][block_no][off]; + skb_reserve(skb, BUF0_LEN); + tmp = (unsigned long) skb->data; + tmp += ALIGN_SIZE; + tmp &= ~ALIGN_SIZE; + skb->data = (void *) tmp; + skb->tail = (void *) tmp; + + memset(rxdp, 0, sizeof(RxD_t)); + rxdp->Buffer2_ptr = pci_map_single + (nic->pdev, skb->data, dev->mtu + BUF0_LEN + 4, + PCI_DMA_FROMDEVICE); + rxdp->Buffer0_ptr = + pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN, + PCI_DMA_FROMDEVICE); + rxdp->Buffer1_ptr = + pci_map_single(nic->pdev, ba->ba_1, BUF1_LEN, + PCI_DMA_FROMDEVICE); + + rxdp->Control_2 = SET_BUFFER2_SIZE(dev->mtu + 4); + rxdp->Control_2 |= SET_BUFFER0_SIZE(BUF0_LEN); + rxdp->Control_2 |= SET_BUFFER1_SIZE(1); /* dummy. */ + rxdp->Control_2 |= BIT(0); /* Set Buffer_Empty bit. */ + rxdp->Host_Control = (u64) ((unsigned long) (skb)); + rxdp->Control_1 |= RXD_OWN_XENA; + off++; + mac_control->rx_curr_put_info[ring_no].offset = off; +#endif atomic_inc(&nic->rx_bufs_left[ring_no]); alloc_tab++; } @@ -1450,15 +1791,16 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no) return SUCCESS; } -/* - * Input Arguments: - * device private variable. - * Return Value: - * NONE. +/** + * free_rx_buffers - Frees all Rx buffers + * @sp: device private variable. * Description: * This function will free all Rx buffers allocated by host. + * Return Value: + * NONE. */ -static void freeRxBuffers(struct s2io_nic *sp) + +static void free_rx_buffers(struct s2io_nic *sp) { struct net_device *dev = sp->dev; int i, j, blk = 0, off, buf_cnt = 0; @@ -1466,15 +1808,19 @@ static void freeRxBuffers(struct s2io_nic *sp) struct sk_buff *skb; mac_info_t *mac_control; struct config_param *config; +#ifdef CONFIG_2BUFF_MODE + buffAdd_t *ba; +#endif mac_control = &sp->mac_control; config = &sp->config; - for (i = 0; i < config->RxRingNum; i++) { - for (j = 0, blk = 0; j < config->RxCfg[i].NumRxd; j++) { + for (i = 0; i < config->rx_ring_num; i++) { + for (j = 0, blk = 0; j < config->rx_cfg[i].num_rxd; j++) { off = j % (MAX_RXDS_PER_BLOCK + 1); rxdp = sp->rx_blocks[i][blk].block_virt_addr + off; +#ifndef CONFIG_2BUFF_MODE if (rxdp->Control_1 == END_OF_BLOCK) { rxdp = (RxD_t *) ((unsigned long) rxdp-> @@ -1482,11 +1828,23 @@ static void freeRxBuffers(struct s2io_nic *sp) j++; blk++; } +#else + if (rxdp->Host_Control == END_OF_BLOCK) { + blk++; + continue; + } +#endif + + if (!(rxdp->Control_1 & RXD_OWN_XENA)) { + memset(rxdp, 0, sizeof(RxD_t)); + continue; + } skb = (struct sk_buff *) ((unsigned long) rxdp-> Host_Control); if (skb) { +#ifndef CONFIG_2BUFF_MODE pci_unmap_single(sp->pdev, (dma_addr_t) rxdp->Buffer0_ptr, dev->mtu + @@ -1494,6 +1852,21 @@ static void freeRxBuffers(struct s2io_nic *sp) + HEADER_802_2_SIZE + HEADER_SNAP_SIZE, PCI_DMA_FROMDEVICE); +#else + ba = &sp->ba[i][blk][off]; + pci_unmap_single(sp->pdev, (dma_addr_t) + rxdp->Buffer0_ptr, + BUF0_LEN, + PCI_DMA_FROMDEVICE); + pci_unmap_single(sp->pdev, (dma_addr_t) + rxdp->Buffer1_ptr, + BUF1_LEN, + PCI_DMA_FROMDEVICE); + pci_unmap_single(sp->pdev, (dma_addr_t) + rxdp->Buffer2_ptr, + dev->mtu + BUF0_LEN + 4, + PCI_DMA_FROMDEVICE); +#endif dev_kfree_skb(skb); atomic_dec(&sp->rx_bufs_left[i]); buf_cnt++; @@ -1510,32 +1883,38 @@ static void freeRxBuffers(struct s2io_nic *sp) } } -/* - * Input Argument: - * dev - pointer to the device structure. - * budget - The number of packets that were budgeted to be processed during - * one pass through the 'Poll" function. - * Return value: - * 0 on success and 1 if there are No Rx packets to be processed. - * Description: - * Comes into picture only if NAPI support has been incorporated. It does - * the same thing that rxIntrHandler does, but not in a interrupt context - * also It will process only a given number of packets. +/** + * s2io_poll - Rx interrupt handler for NAPI support + * @dev : pointer to the device structure. + * @budget : The number of packets that were budgeted to be processed + * during one pass through the 'Poll" function. + * Description: + * Comes into picture only if NAPI support has been incorporated. It does + * the same thing that rx_intr_handler does, but not in a interrupt context + * also It will process only a given number of packets. + * Return value: + * 0 on success and 1 if there are No Rx packets to be processed. */ + #ifdef CONFIG_S2IO_NAPI static int s2io_poll(struct net_device *dev, int *budget) { nic_t *nic = dev->priv; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; int pkts_to_process = *budget, pkt_cnt = 0; register u64 val64 = 0; - rx_curr_get_info_t offset_info; - int i, block_no; + rx_curr_get_info_t get_info, put_info; + int i, get_block, put_block, get_offset, put_offset, ring_bufs; +#ifndef CONFIG_2BUFF_MODE u16 val16, cksum; +#endif struct sk_buff *skb; RxD_t *rxdp; mac_info_t *mac_control; struct config_param *config; +#ifdef CONFIG_2BUFF_MODE + buffAdd_t *ba; +#endif mac_control = &nic->mac_control; config = &nic->config; @@ -1546,30 +1925,42 @@ static int s2io_poll(struct net_device *dev, int *budget) val64 = readq(&bar0->rx_traffic_int); writeq(val64, &bar0->rx_traffic_int); - for (i = 0; i < config->RxRingNum; i++) { - if (--pkts_to_process < 0) { - goto no_rx; - } - offset_info = mac_control->rx_curr_get_info[i]; - block_no = offset_info.block_index; - rxdp = nic->rx_blocks[i][block_no].block_virt_addr + - offset_info.offset; - while (!(rxdp->Control_1 & RXD_OWN_XENA)) { + for (i = 0; i < config->rx_ring_num; i++) { + get_info = mac_control->rx_curr_get_info[i]; + get_block = get_info.block_index; + put_info = mac_control->rx_curr_put_info[i]; + put_block = put_info.block_index; + ring_bufs = config->rx_cfg[i].num_rxd; + rxdp = nic->rx_blocks[i][get_block].block_virt_addr + + get_info.offset; +#ifndef CONFIG_2BUFF_MODE + get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) + + get_info.offset; + put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) + + put_info.offset; + while ((!(rxdp->Control_1 & RXD_OWN_XENA)) && + (((get_offset + 1) % ring_bufs) != put_offset)) { + if (--pkts_to_process < 0) { + goto no_rx; + } if (rxdp->Control_1 == END_OF_BLOCK) { rxdp = (RxD_t *) ((unsigned long) rxdp-> Control_2); - offset_info.offset++; - offset_info.offset %= + get_info.offset++; + get_info.offset %= (MAX_RXDS_PER_BLOCK + 1); - block_no++; - block_no %= nic->block_count[i]; + get_block++; + get_block %= nic->block_count[i]; mac_control->rx_curr_get_info[i]. - offset = offset_info.offset; + offset = get_info.offset; mac_control->rx_curr_get_info[i]. - block_index = block_no; + block_index = get_block; continue; } + get_offset = + (get_block * (MAX_RXDS_PER_BLOCK + 1)) + + get_info.offset; skb = (struct sk_buff *) ((unsigned long) rxdp-> Host_Control); @@ -1577,7 +1968,7 @@ static int s2io_poll(struct net_device *dev, int *budget) DBG_PRINT(ERR_DBG, "%s: The skb is ", dev->name); DBG_PRINT(ERR_DBG, "Null in Rx Intr\n"); - return 0; + goto no_rx; } val64 = RXD_GET_BUFFER0_SIZE(rxdp->Control_2); val16 = (u16) (val64 >> 48); @@ -1589,97 +1980,184 @@ static int s2io_poll(struct net_device *dev, int *budget) HEADER_802_2_SIZE + HEADER_SNAP_SIZE, PCI_DMA_FROMDEVICE); - rxOsmHandler(nic, val16, rxdp, i); + rx_osm_handler(nic, val16, rxdp, i); pkt_cnt++; - offset_info.offset++; - offset_info.offset %= (MAX_RXDS_PER_BLOCK + 1); + get_info.offset++; + get_info.offset %= (MAX_RXDS_PER_BLOCK + 1); rxdp = - nic->rx_blocks[i][block_no].block_virt_addr + - offset_info.offset; + nic->rx_blocks[i][get_block].block_virt_addr + + get_info.offset; mac_control->rx_curr_get_info[i].offset = - offset_info.offset; + get_info.offset; } - } - if (!pkt_cnt) - pkt_cnt = 1; +#else + get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) + + get_info.offset; + put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) + + put_info.offset; + while (((!(rxdp->Control_1 & RXD_OWN_XENA)) && + !(rxdp->Control_2 & BIT(0))) && + (((get_offset + 1) % ring_bufs) != put_offset)) { + if (--pkts_to_process < 0) { + goto no_rx; + } + skb = (struct sk_buff *) ((unsigned long) + rxdp->Host_Control); + if (skb == NULL) { + DBG_PRINT(ERR_DBG, "%s: The skb is ", + dev->name); + DBG_PRINT(ERR_DBG, "Null in Rx Intr\n"); + goto no_rx; + } + + pci_unmap_single(nic->pdev, (dma_addr_t) + rxdp->Buffer0_ptr, + BUF0_LEN, PCI_DMA_FROMDEVICE); + pci_unmap_single(nic->pdev, (dma_addr_t) + rxdp->Buffer1_ptr, + BUF1_LEN, PCI_DMA_FROMDEVICE); + pci_unmap_single(nic->pdev, (dma_addr_t) + rxdp->Buffer2_ptr, + dev->mtu + BUF0_LEN + 4, + PCI_DMA_FROMDEVICE); + ba = &nic->ba[i][get_block][get_info.offset]; - for (i = 0; i < config->RxRingNum; i++) - fill_rx_buffers(nic, i); + rx_osm_handler(nic, rxdp, i, ba); + + get_info.offset++; + mac_control->rx_curr_get_info[i].offset = + get_info.offset; + rxdp = + nic->rx_blocks[i][get_block].block_virt_addr + + get_info.offset; + + if (get_info.offset && + (!(get_info.offset % MAX_RXDS_PER_BLOCK))) { + get_info.offset = 0; + mac_control->rx_curr_get_info[i]. + offset = get_info.offset; + get_block++; + get_block %= nic->block_count[i]; + mac_control->rx_curr_get_info[i]. + block_index = get_block; + rxdp = + nic->rx_blocks[i][get_block]. + block_virt_addr; + } + get_offset = + (get_block * (MAX_RXDS_PER_BLOCK + 1)) + + get_info.offset; + pkt_cnt++; + } +#endif + } + if (!pkt_cnt) + pkt_cnt = 1; dev->quota -= pkt_cnt; *budget -= pkt_cnt; netif_rx_complete(dev); -/* Re enable the Rx interrupts. */ - en_dis_able_NicIntrs(nic, RX_TRAFFIC_INTR, ENABLE_INTRS); + for (i = 0; i < config->rx_ring_num; i++) { + if (fill_rx_buffers(nic, i) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name); + DBG_PRINT(ERR_DBG, " in Rx Poll!!\n"); + break; + } + } + /* Re enable the Rx interrupts. */ + en_dis_able_nic_intrs(nic, RX_TRAFFIC_INTR, ENABLE_INTRS); return 0; no_rx: - for (i = 0; i < config->RxRingNum; i++) - fill_rx_buffers(nic, i); dev->quota -= pkt_cnt; *budget -= pkt_cnt; + + for (i = 0; i < config->rx_ring_num; i++) { + if (fill_rx_buffers(nic, i) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name); + DBG_PRINT(ERR_DBG, " in Rx Poll!!\n"); + break; + } + } return 1; } #else -/* - * Input Arguments: - * device private variable. - * Return Value: - * NONE. +/** + * rx_intr_handler - Rx interrupt handler + * @nic: device private variable. * Description: - * If the interrupt is because of a received frame or if the - * receive ring contains fresh as yet un-processed frames, this function is + * If the interrupt is because of a received frame or if the + * receive ring contains fresh as yet un-processed frames,this function is * called. It picks out the RxD at which place the last Rx processing had * stopped and sends the skb to the OSM's Rx handler and then increments * the offset. + * Return Value: + * NONE. */ -static void rxIntrHandler(struct s2io_nic *nic) + +static void rx_intr_handler(struct s2io_nic *nic) { struct net_device *dev = (struct net_device *) nic->dev; XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; - rx_curr_get_info_t offset_info; + rx_curr_get_info_t get_info, put_info; RxD_t *rxdp; struct sk_buff *skb; +#ifndef CONFIG_2BUFF_MODE u16 val16, cksum; +#endif register u64 val64 = 0; - int i, block_no; + int get_block, get_offset, put_block, put_offset, ring_bufs; + int i, pkt_cnt = 0; mac_info_t *mac_control; struct config_param *config; +#ifdef CONFIG_2BUFF_MODE + buffAdd_t *ba; +#endif mac_control = &nic->mac_control; config = &nic->config; -#if DEBUG_ON - nic->rxint_cnt++; -#endif - -/* rx_traffic_int reg is an R1 register, hence we read and write back - * the samevalue in the register to clear it. - */ + /* + * rx_traffic_int reg is an R1 register, hence we read and write back + * the samevalue in the register to clear it. + */ val64 = readq(&bar0->rx_traffic_int); writeq(val64, &bar0->rx_traffic_int); - for (i = 0; i < config->RxRingNum; i++) { - offset_info = mac_control->rx_curr_get_info[i]; - block_no = offset_info.block_index; - rxdp = nic->rx_blocks[i][block_no].block_virt_addr + - offset_info.offset; - while (!(rxdp->Control_1 & RXD_OWN_XENA)) { + for (i = 0; i < config->rx_ring_num; i++) { + get_info = mac_control->rx_curr_get_info[i]; + get_block = get_info.block_index; + put_info = mac_control->rx_curr_put_info[i]; + put_block = put_info.block_index; + ring_bufs = config->rx_cfg[i].num_rxd; + rxdp = nic->rx_blocks[i][get_block].block_virt_addr + + get_info.offset; +#ifndef CONFIG_2BUFF_MODE + get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) + + get_info.offset; + spin_lock(&nic->put_lock); + put_offset = nic->put_pos[i]; + spin_unlock(&nic->put_lock); + while ((!(rxdp->Control_1 & RXD_OWN_XENA)) && + (((get_offset + 1) % ring_bufs) != put_offset)) { if (rxdp->Control_1 == END_OF_BLOCK) { rxdp = (RxD_t *) ((unsigned long) rxdp->Control_2); - offset_info.offset++; - offset_info.offset %= + get_info.offset++; + get_info.offset %= (MAX_RXDS_PER_BLOCK + 1); - block_no++; - block_no %= nic->block_count[i]; + get_block++; + get_block %= nic->block_count[i]; mac_control->rx_curr_get_info[i]. - offset = offset_info.offset; + offset = get_info.offset; mac_control->rx_curr_get_info[i]. - block_index = block_no; + block_index = get_block; continue; } + get_offset = + (get_block * (MAX_RXDS_PER_BLOCK + 1)) + + get_info.offset; skb = (struct sk_buff *) ((unsigned long) rxdp->Host_Control); if (skb == NULL) { @@ -1698,35 +2176,102 @@ static void rxIntrHandler(struct s2io_nic *nic) HEADER_802_2_SIZE + HEADER_SNAP_SIZE, PCI_DMA_FROMDEVICE); - rxOsmHandler(nic, val16, rxdp, i); - offset_info.offset++; - offset_info.offset %= (MAX_RXDS_PER_BLOCK + 1); + rx_osm_handler(nic, val16, rxdp, i); + get_info.offset++; + get_info.offset %= (MAX_RXDS_PER_BLOCK + 1); rxdp = - nic->rx_blocks[i][block_no].block_virt_addr + - offset_info.offset; + nic->rx_blocks[i][get_block].block_virt_addr + + get_info.offset; mac_control->rx_curr_get_info[i].offset = - offset_info.offset; + get_info.offset; + pkt_cnt++; + if ((indicate_max_pkts) + && (pkt_cnt > indicate_max_pkts)) + break; } +#else + get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) + + get_info.offset; + spin_lock(&nic->put_lock); + put_offset = nic->put_pos[i]; + spin_unlock(&nic->put_lock); + while (((!(rxdp->Control_1 & RXD_OWN_XENA)) && + !(rxdp->Control_2 & BIT(0))) && + (((get_offset + 1) % ring_bufs) != put_offset)) { + skb = (struct sk_buff *) ((unsigned long) + rxdp->Host_Control); + if (skb == NULL) { + DBG_PRINT(ERR_DBG, "%s: The skb is ", + dev->name); + DBG_PRINT(ERR_DBG, "Null in Rx Intr\n"); + return; + } + + pci_unmap_single(nic->pdev, (dma_addr_t) + rxdp->Buffer0_ptr, + BUF0_LEN, PCI_DMA_FROMDEVICE); + pci_unmap_single(nic->pdev, (dma_addr_t) + rxdp->Buffer1_ptr, + BUF1_LEN, PCI_DMA_FROMDEVICE); + pci_unmap_single(nic->pdev, (dma_addr_t) + rxdp->Buffer2_ptr, + dev->mtu + BUF0_LEN + 4, + PCI_DMA_FROMDEVICE); + ba = &nic->ba[i][get_block][get_info.offset]; + + rx_osm_handler(nic, rxdp, i, ba); + + get_info.offset++; + mac_control->rx_curr_get_info[i].offset = + get_info.offset; + rxdp = + nic->rx_blocks[i][get_block].block_virt_addr + + get_info.offset; + + if (get_info.offset && + (!(get_info.offset % MAX_RXDS_PER_BLOCK))) { + get_info.offset = 0; + mac_control->rx_curr_get_info[i]. + offset = get_info.offset; + get_block++; + get_block %= nic->block_count[i]; + mac_control->rx_curr_get_info[i]. + block_index = get_block; + rxdp = + nic->rx_blocks[i][get_block]. + block_virt_addr; + } + get_offset = + (get_block * (MAX_RXDS_PER_BLOCK + 1)) + + get_info.offset; + pkt_cnt++; + if ((indicate_max_pkts) + && (pkt_cnt > indicate_max_pkts)) + break; + } +#endif + if ((indicate_max_pkts) && (pkt_cnt > indicate_max_pkts)) + break; } } #endif - -/* - * Input Arguments: - * device private variable - * Return Value: - * NONE +/** + * tx_intr_handler - Transmit interrupt handler + * @nic : device private variable * Description: * If an interrupt was raised to indicate DMA complete of the - * Tx packet, this function is called. It identifies the last TxD whose buffer - * was freed and frees all skbs whose data have already DMA'ed into the NICs - * internal memory. + * Tx packet, this function is called. It identifies the last TxD + * whose buffer was freed and frees all skbs whose data have already + * DMA'ed into the NICs internal memory. + * Return Value: + * NONE */ -static void txIntrHandler(struct s2io_nic *nic) + +static void tx_intr_handler(struct s2io_nic *nic) { - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; struct net_device *dev = (struct net_device *) nic->dev; - tx_curr_get_info_t offset_info, offset_info1; + tx_curr_get_info_t get_info, put_info; struct sk_buff *skb; TxD_t *txdlp; register u64 val64 = 0; @@ -1734,27 +2279,24 @@ static void txIntrHandler(struct s2io_nic *nic) u16 j, frg_cnt; mac_info_t *mac_control; struct config_param *config; -#if DEBUG_ON - int cnt = 0; - nic->txint_cnt++; -#endif mac_control = &nic->mac_control; config = &nic->config; - /* tx_traffic_int reg is an R1 register, hence we read and write + /* + * tx_traffic_int reg is an R1 register, hence we read and write * back the samevalue in the register to clear it. */ val64 = readq(&bar0->tx_traffic_int); writeq(val64, &bar0->tx_traffic_int); - for (i = 0; i < config->TxFIFONum; i++) { - offset_info = mac_control->tx_curr_get_info[i]; - offset_info1 = mac_control->tx_curr_put_info[i]; - txdlp = mac_control->txdl_start[i] + - (config->MaxTxDs * offset_info.offset); + for (i = 0; i < config->tx_fifo_num; i++) { + get_info = mac_control->tx_curr_get_info[i]; + put_info = mac_control->tx_curr_put_info[i]; + txdlp = (TxD_t *) nic->list_info[i][get_info.offset]. + list_virt_addr; while ((!(txdlp->Control_1 & TXD_LIST_OWN_XENA)) && - (offset_info.offset != offset_info1.offset) && + (get_info.offset != put_info.offset) && (txdlp->Host_Control)) { /* Check for TxD errors */ if (txdlp->Control_1 & TXD_T_CODE) { @@ -1797,28 +2339,20 @@ static void txIntrHandler(struct s2io_nic *nic) txdlp = temp; } memset(txdlp, 0, - (sizeof(TxD_t) * config->MaxTxDs)); + (sizeof(TxD_t) * config->max_txds)); /* Updating the statistics block */ nic->stats.tx_packets++; nic->stats.tx_bytes += skb->len; -#if DEBUG_ON - nic->txpkt_bytes += skb->len; - cnt++; -#endif dev_kfree_skb_irq(skb); - offset_info.offset++; - offset_info.offset %= offset_info.fifo_len + 1; - txdlp = mac_control->txdl_start[i] + - (config->MaxTxDs * offset_info.offset); + get_info.offset++; + get_info.offset %= get_info.fifo_len + 1; + txdlp = (TxD_t *) nic->list_info[i] + [get_info.offset].list_virt_addr; mac_control->tx_curr_get_info[i].offset = - offset_info.offset; + get_info.offset; } -#if DEBUG_ON - DBG_PRINT(INTR_DBG, "%s: freed %d Tx Pkts\n", dev->name, - cnt); -#endif } spin_lock(&nic->tx_lock); @@ -1827,67 +2361,79 @@ static void txIntrHandler(struct s2io_nic *nic) spin_unlock(&nic->tx_lock); } -/* - * Input Arguments: - * device private variable - * Return Value: +/** + * alarm_intr_handler - Alarm Interrrupt handler + * @nic: device private variable + * Description: If the interrupt was neither because of Rx packet or Tx + * complete, this function is called. If the interrupt was to indicate + * a loss of link, the OSM link status handler is invoked for any other + * alarm interrupt the block that raised the interrupt is displayed + * and a H/W reset is issued. + * Return Value: * NONE - * Description: - * If the interrupt was neither because of Rx packet or Tx - * complete, this function is called. If the interrupt was to indicate a loss - * of link, the OSM link status handler is invoked for any other alarm - * interrupt the block that raised the interrupt is displayed and a H/W reset - * is issued. - */ -static void alarmIntrHandler(struct s2io_nic *nic) +*/ + +static void alarm_intr_handler(struct s2io_nic *nic) { struct net_device *dev = (struct net_device *) nic->dev; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; + XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64 = 0, err_reg = 0; - /* Handling link status change error Intr */ err_reg = readq(&bar0->mac_rmac_err_reg); + writeq(err_reg, &bar0->mac_rmac_err_reg); if (err_reg & RMAC_LINK_STATE_CHANGE_INT) { schedule_work(&nic->set_link_task); } - /* Handling SERR errors by stopping device Xmit queue and forcing - * a H/W reset. - */ + /* In case of a serious error, the device will be Reset. */ val64 = readq(&bar0->serr_source); if (val64 & SERR_SOURCE_ANY) { DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name); DBG_PRINT(ERR_DBG, "serious error!!\n"); netif_stop_queue(dev); + schedule_work(&nic->rst_timer_task); } -/* Other type of interrupts are not being handled now, TODO*/ + + /* + * Also as mentioned in the latest Errata sheets if the PCC_FB_ECC + * Error occurs, the adapter will be recycled by disabling the + * adapter enable bit and enabling it again after the device + * becomes Quiescent. + */ + val64 = readq(&bar0->pcc_err_reg); + writeq(val64, &bar0->pcc_err_reg); + if (val64 & PCC_FB_ECC_DB_ERR) { + u64 ac = readq(&bar0->adapter_control); + ac &= ~(ADAPTER_CNTL_EN); + writeq(ac, &bar0->adapter_control); + ac = readq(&bar0->adapter_control); + schedule_work(&nic->set_link_task); + } + + /* Other type of interrupts are not being handled now, TODO */ } -/* - * Input Argument: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. +/** + * wait_for_cmd_complete - waits for a command to complete. + * @sp : private member of the device structure, which is a pointer to the + * s2io_nic structure. + * Description: Function that waits for a command to Write into RMAC + * ADDR DATA registers to be completed and returns either success or + * error depending on whether the command was complete or not. * Return value: * SUCCESS on success and FAILURE on failure. - * Description: - * Function that waits for a command to Write into RMAC ADDR DATA registers - * to be completed and returns either success or error depending on whether - * the command was complete or not. */ -int waitForCmdComplete(nic_t * sp) + +int wait_for_cmd_complete(nic_t * sp) { - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; int ret = FAILURE, cnt = 0; u64 val64; while (TRUE) { - val64 = - RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD - | RMAC_ADDR_CMD_MEM_OFFSET(0); - writeq(val64, &bar0->rmac_addr_cmd_mem); val64 = readq(&bar0->rmac_addr_cmd_mem); - if (!val64) { + if (!(val64 & RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) { ret = SUCCESS; break; } @@ -1900,27 +2446,27 @@ int waitForCmdComplete(nic_t * sp) return ret; } -/* - * Input Argument: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. +/** + * s2io_reset - Resets the card. + * @sp : private member of the device structure. + * Description: Function to Reset the card. This function then also + * restores the previously saved PCI configuration space registers as + * the card reset also resets the configuration space. * Return value: - * void. - * Description: - * Function to Reset the card. This function then also restores the previously - * saved PCI configuration space registers as the card reset also resets the - * Configration space. + * void. */ + void s2io_reset(nic_t * sp) { - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64; u16 subid; val64 = SW_RESET_ALL; writeq(val64, &bar0->sw_reset); - /* At this stage, if the PCI write is indeed completed, the + /* + * At this stage, if the PCI write is indeed completed, the * card is reset and so is the PCI Config space of the device. * So a read cannot be issued at this stage on any of the * registers to ensure the write into "sw_reset" register @@ -1935,7 +2481,7 @@ void s2io_reset(nic_t * sp) schedule_timeout(HZ / 4); /* Restore the PCI state saved during initializarion. */ - pci_restore_state(sp->pdev, sp->config_space); + pci_restore_state(sp->pdev); s2io_init_pci(sp); set_current_state(TASK_UNINTERRUPTIBLE); @@ -1948,35 +2494,37 @@ void s2io_reset(nic_t * sp) val64 |= 0x0000800000000000ULL; writeq(val64, &bar0->gpio_control); val64 = 0x0411040400000000ULL; - writeq(val64, (void *) ((u8 *) bar0 + 0x2700)); + writeq(val64, (void __iomem *) bar0 + 0x2700); } sp->device_enabled_once = FALSE; } -/* - * Input Argument: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. +/** + * s2io_set_swapper - to set the swapper controle on the card + * @sp : private member of the device structure, + * pointer to the s2io_nic structure. + * Description: Function to set the swapper control on the card + * correctly depending on the 'endianness' of the system. * Return value: * SUCCESS on success and FAILURE on failure. - * Description: - * Function to set the swapper control on the card correctly depending on the - * 'endianness' of the system. */ + int s2io_set_swapper(nic_t * sp) { struct net_device *dev = sp->dev; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64; -/* Set proper endian settings and verify the same by reading the PIF - * Feed-back register. - */ + /* + * Set proper endian settings and verify the same by reading + * the PIF Feed-back register. + */ #ifdef __BIG_ENDIAN -/* The device by default set to a big endian format, so a big endian - * driver need not set anything. - */ + /* + * The device by default set to a big endian format, so a + * big endian driver need not set anything. + */ writeq(0xffffffffffffffffULL, &bar0->swapper_ctrl); val64 = (SWAPPER_CTRL_PIF_R_FE | SWAPPER_CTRL_PIF_R_SE | @@ -1995,9 +2543,11 @@ int s2io_set_swapper(nic_t * sp) SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE); writeq(val64, &bar0->swapper_ctrl); #else -/* Initially we enable all bits to make it accessible by the driver, - * then we selectively enable only those bits that we want to set. - */ + /* + * Initially we enable all bits to make it accessible by the + * driver, then we selectively enable only those bits that + * we want to set. + */ writeq(0xffffffffffffffffULL, &bar0->swapper_ctrl); val64 = (SWAPPER_CTRL_PIF_R_FE | SWAPPER_CTRL_PIF_R_SE | @@ -2021,9 +2571,10 @@ int s2io_set_swapper(nic_t * sp) writeq(val64, &bar0->swapper_ctrl); #endif -/* Verifying if endian settings are accurate by reading a feedback - * register. - */ + /* + * Verifying if endian settings are accurate by reading a + * feedback register. + */ val64 = readq(&bar0->pif_rd_swapper_fb); if (val64 != 0x0123456789ABCDEFULL) { /* Endian settings are incorrect, calls for another dekko. */ @@ -2041,216 +2592,139 @@ int s2io_set_swapper(nic_t * sp) * Functions defined below concern the OS part of the driver * * ********************************************************* */ -/* - * Input Argument: - * dev - pointer to the device structure. - * Return value: - * '0' on success and an appropriate (-)ve integer as defined in errno.h - * file on failure. +/** + * s2io_open - open entry point of the driver + * @dev : pointer to the device structure. * Description: * This function is the open entry point of the driver. It mainly calls a * function to allocate Rx buffers and inserts them into the buffer * descriptors and then enables the Rx part of the NIC. + * Return value: + * 0 on success and an appropriate (-)ve integer as defined in errno.h + * file on failure. */ + int s2io_open(struct net_device *dev) { nic_t *sp = dev->priv; - int i, ret = 0, err = 0; - mac_info_t *mac_control; - struct config_param *config; - + int err = 0; -/* Make sure you have link off by default every time Nic is initialized*/ + /* + * Make sure you have link off by default every time + * Nic is initialized + */ netif_carrier_off(dev); sp->last_link_state = LINK_DOWN; -/* Initialize the H/W I/O registers */ - if (initNic(sp) != 0) { + /* Initialize H/W and enable interrupts */ + if (s2io_card_up(sp)) { DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n", dev->name); return -ENODEV; } -/* After proper initialization of H/W, register ISR */ - err = - request_irq((int) sp->irq, s2io_isr, SA_SHIRQ, sp->name, dev); + /* After proper initialization of H/W, register ISR */ + err = request_irq((int) sp->irq, s2io_isr, SA_SHIRQ, + sp->name, dev); if (err) { s2io_reset(sp); DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n", dev->name); return err; } + if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) { DBG_PRINT(ERR_DBG, "Set Mac Address Failed\n"); s2io_reset(sp); return -ENODEV; } - -/* Setting its receive mode */ - s2io_set_multicast(dev); - -/* Initializing the Rx buffers. For now we are considering only 1 Rx ring - * and initializing buffers into 1016 RxDs or 8 Rx blocks - */ - mac_control = &sp->mac_control; - config = &sp->config; - - for (i = 0; i < config->RxRingNum; i++) { - if ((ret = fill_rx_buffers(sp, i))) { - DBG_PRINT(ERR_DBG, "%s: Out of memory in Open\n", - dev->name); - s2io_reset(sp); - free_irq(dev->irq, dev); - freeRxBuffers(sp); - return -ENOMEM; - } - DBG_PRINT(INFO_DBG, "Buf in ring:%d is %d:\n", i, - atomic_read(&sp->rx_bufs_left[i])); - } - -/* Enable tasklet for the device */ - tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev); - -/* Enable Rx Traffic and interrupts on the NIC */ - if (startNic(sp)) { - DBG_PRINT(ERR_DBG, "%s: Starting NIC failed\n", dev->name); - tasklet_kill(&sp->task); - s2io_reset(sp); - free_irq(dev->irq, dev); - freeRxBuffers(sp); - return -ENODEV; - } - - sp->device_close_flag = FALSE; /* Device is up and running. */ netif_start_queue(dev); - return 0; } -/* - * Input Argument/s: - * dev - device pointer. - * Return value: - * '0' on success and an appropriate (-)ve integer as defined in errno.h - * file on failure. +/** + * s2io_close -close entry point of the driver + * @dev : device pointer. * Description: * This is the stop entry point of the driver. It needs to undo exactly - * whatever was done by the open entry point, thus it's usually referred to - * as the close function. Among other things this function mainly stops the + * whatever was done by the open entry point,thus it's usually referred to + * as the close function.Among other things this function mainly stops the * Rx side of the NIC and frees all the Rx buffers in the Rx rings. + * Return value: + * 0 on success and an appropriate (-)ve integer as defined in errno.h + * file on failure. */ + int s2io_close(struct net_device *dev) { nic_t *sp = dev->priv; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; - register u64 val64 = 0; - u16 cnt = 0; - spin_lock(&sp->isr_lock); + flush_scheduled_work(); netif_stop_queue(dev); + /* Reset card, kill tasklet and free Tx and Rx buffers. */ + s2io_card_down(sp); -/* disable Tx and Rx traffic on the NIC */ - stopNic(sp); - - spin_unlock(&sp->isr_lock); - -/* If the device tasklet is running, wait till its done before killing it */ - while (atomic_read(&(sp->tasklet_status))) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 10); - } - tasklet_kill(&sp->task); - -/* Check if the device is Quiescent and then Reset the NIC */ - do { - val64 = readq(&bar0->adapter_status); - if (verify_xena_quiescence(val64, sp->device_enabled_once)) { - break; - } - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 20); - cnt++; - if (cnt == 10) { - DBG_PRINT(ERR_DBG, - "s2io_close:Device not Quiescent "); - DBG_PRINT(ERR_DBG, "adaper status reads 0x%llx\n", - (unsigned long long) val64); - break; - } - } while (1); - s2io_reset(sp); - -/* Free the Registered IRQ */ free_irq(dev->irq, dev); - -/* Free all Tx Buffers waiting for transmission */ - freeTxBuffers(sp); - -/* Free all Rx buffers allocated by host */ - freeRxBuffers(sp); - sp->device_close_flag = TRUE; /* Device is shut down. */ - return 0; } -/* - * Input Argument/s: - * skb - the socket buffer containing the Tx data. - * dev - device pointer. - * Return value: - * '0' on success & 1 on failure. - * NOTE: when device cant queue the pkt, just the trans_start variable will - * not be upadted. - * Description: +/** + * s2io_xmit - Tx entry point of te driver + * @skb : the socket buffer containing the Tx data. + * @dev : device pointer. + * Description : * This function is the Tx entry point of the driver. S2IO NIC supports * certain protocol assist features on Tx side, namely CSO, S/G, LSO. + * NOTE: when device cant queue the pkt,just the trans_start variable will + * not be upadted. + * Return value: + * 0 on success & 1 on failure. */ + int s2io_xmit(struct sk_buff *skb, struct net_device *dev) { nic_t *sp = dev->priv; - u16 off, txd_len, frg_cnt, frg_len, i, queue, off1, queue_len; + u16 frg_cnt, frg_len, i, queue, queue_len, put_off, get_off; register u64 val64; TxD_t *txdp; - TxFIFO_element_t *tx_fifo; + TxFIFO_element_t __iomem *tx_fifo; unsigned long flags; #ifdef NETIF_F_TSO int mss; #endif mac_info_t *mac_control; struct config_param *config; + XENA_dev_config_t __iomem *bar0 = sp->bar0; mac_control = &sp->mac_control; config = &sp->config; DBG_PRINT(TX_DBG, "%s: In S2IO Tx routine\n", dev->name); - spin_lock_irqsave(&sp->tx_lock, flags); - queue = 0; - /* Multi FIFO Tx is disabled for now. */ - if (!queue && tx_prio) { - u8 x = (skb->data)[5]; - queue = x % config->TxFIFONum; - } + if (atomic_read(&sp->card_state) == CARD_DOWN) { + DBG_PRINT(ERR_DBG, "%s: Card going down for reset\n", + dev->name); + spin_unlock_irqrestore(&sp->tx_lock, flags); + return 1; + } - off = (u16) mac_control->tx_curr_put_info[queue].offset; - off1 = (u16) mac_control->tx_curr_get_info[queue].offset; - txd_len = mac_control->txdl_len; - txdp = mac_control->txdl_start[queue] + (config->MaxTxDs * off); + queue = 0; + put_off = (u16) mac_control->tx_curr_put_info[queue].offset; + get_off = (u16) mac_control->tx_curr_get_info[queue].offset; + txdp = (TxD_t *) sp->list_info[queue][put_off].list_virt_addr; queue_len = mac_control->tx_curr_put_info[queue].fifo_len + 1; /* Avoid "put" pointer going beyond "get" pointer */ - if (txdp->Host_Control || (((off + 1) % queue_len) == off1)) { + if (txdp->Host_Control || (((put_off + 1) % queue_len) == get_off)) { DBG_PRINT(ERR_DBG, "Error in xmit, No free TXDs.\n"); netif_stop_queue(dev); dev_kfree_skb(skb); spin_unlock_irqrestore(&sp->tx_lock, flags); return 0; } - #ifdef NETIF_F_TSO mss = skb_shinfo(skb)->tso_size; if (mss) { @@ -2271,7 +2745,7 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev) TXD_TX_CKO_UDP_EN); } - txdp->Control_2 |= config->TxIntrType; + txdp->Control_2 |= config->tx_intr_type; txdp->Control_1 |= (TXD_BUFFER0_SIZE(frg_len) | TXD_GATHER_CODE_FIRST); @@ -2289,8 +2763,7 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev) txdp->Control_1 |= TXD_GATHER_CODE_LAST; tx_fifo = mac_control->tx_FIFO_start[queue]; - val64 = (mac_control->txdl_start_phy[queue] + - (sizeof(TxD_t) * txd_len * off)); + val64 = sp->list_info[queue][put_off].list_phy_addr; writeq(val64, &tx_fifo->TxDL_Pointer); val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST | @@ -2301,15 +2774,18 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev) #endif writeq(val64, &tx_fifo->List_Control); - off++; - off %= mac_control->tx_curr_put_info[queue].fifo_len + 1; - mac_control->tx_curr_put_info[queue].offset = off; + /* Perform a PCI read to flush previous writes */ + val64 = readq(&bar0->general_int_status); + + put_off++; + put_off %= mac_control->tx_curr_put_info[queue].fifo_len + 1; + mac_control->tx_curr_put_info[queue].offset = put_off; /* Avoid "put" pointer going beyond "get" pointer */ - if (((off + 1) % queue_len) == off1) { - DBG_PRINT(TX_DBG, - "No free TxDs for xmit, Put: 0x%x Get:0x%x\n", - off, off1); + if (((put_off + 1) % queue_len) == get_off) { + DBG_PRINT(TX_DBG, + "No free TxDs for xmit, Put: 0x%x Get:0x%x\n", + put_off, get_off); netif_stop_queue(dev); } @@ -2319,36 +2795,37 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } -/* - * Input Argument/s: - * irq: the irq of the device. - * dev_id: a void pointer to the dev structure of the NIC. - * ptregs: pointer to the registers pushed on the stack. +/** + * s2io_isr - ISR handler of the device . + * @irq: the irq of the device. + * @dev_id: a void pointer to the dev structure of the NIC. + * @pt_regs: pointer to the registers pushed on the stack. + * Description: This function is the ISR handler of the device. It + * identifies the reason for the interrupt and calls the relevant + * service routines. As a contongency measure, this ISR allocates the + * recv buffers, if their numbers are below the panic value which is + * presently set to 25% of the original number of rcv buffers allocated. * Return value: - * void. - * Description: - * This function is the ISR handler of the device. It identifies the reason - * for the interrupt and calls the relevant service routines. - * As a contongency measure, this ISR allocates the recv buffers, if their - * numbers are below the panic value which is presently set to 25% of the - * original number of rcv buffers allocated. + * IRQ_HANDLED: will be returned if IRQ was handled by this routine + * IRQ_NONE: will be returned if interrupt is not from our device */ - static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; nic_t *sp = dev->priv; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; - u64 reason = 0, general_mask = 0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; +#ifndef CONFIG_S2IO_NAPI + int i, ret; +#endif + u64 reason = 0; mac_info_t *mac_control; struct config_param *config; mac_control = &sp->mac_control; config = &sp->config; - spin_lock(&sp->isr_lock); - - /* Identify the cause for interrupt and call the appropriate + /* + * Identify the cause for interrupt and call the appropriate * interrupt handler. Causes for the interrupt could be; * 1. Rx of packet. * 2. Tx complete. @@ -2359,101 +2836,73 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs) if (!reason) { /* The interrupt was not raised by Xena. */ - spin_unlock(&sp->isr_lock); return IRQ_NONE; } - /* Mask the interrupts on the NIC */ - general_mask = readq(&bar0->general_int_mask); - writeq(0xFFFFFFFFFFFFFFFFULL, &bar0->general_int_mask); - -#if DEBUG_ON - sp->int_cnt++; -#endif /* If Intr is because of Tx Traffic */ if (reason & GEN_INTR_TXTRAFFIC) { - txIntrHandler(sp); + tx_intr_handler(sp); } /* If Intr is because of an error */ if (reason & (GEN_ERROR_INTR)) - alarmIntrHandler(sp); + alarm_intr_handler(sp); #ifdef CONFIG_S2IO_NAPI if (reason & GEN_INTR_RXTRAFFIC) { if (netif_rx_schedule_prep(dev)) { - en_dis_able_NicIntrs(sp, RX_TRAFFIC_INTR, - DISABLE_INTRS); - /* We retake the snap shot of the general interrupt - * register. - */ - general_mask = readq(&bar0->general_int_mask); + en_dis_able_nic_intrs(sp, RX_TRAFFIC_INTR, + DISABLE_INTRS); __netif_rx_schedule(dev); } } #else /* If Intr is because of Rx Traffic */ if (reason & GEN_INTR_RXTRAFFIC) { - rxIntrHandler(sp); + rx_intr_handler(sp); } #endif -/* If the Rx buffer count is below the panic threshold then reallocate the - * buffers from the interrupt handler itself, else schedule a tasklet to - * reallocate the buffers. - */ -#if 1 - { - int i; - - for (i = 0; i < config->RxRingNum; i++) { + /* + * If the Rx buffer count is below the panic threshold then + * reallocate the buffers from the interrupt handler itself, + * else schedule a tasklet to reallocate the buffers. + */ +#ifndef CONFIG_S2IO_NAPI + for (i = 0; i < config->rx_ring_num; i++) { int rxb_size = atomic_read(&sp->rx_bufs_left[i]); int level = rx_buffer_level(sp, rxb_size, i); if ((level == PANIC) && (!TASKLET_IN_USE)) { - int ret; - - DBG_PRINT(ERR_DBG, "%s: Rx BD hit ", dev->name); - DBG_PRINT(ERR_DBG, "PANIC levels\n"); + DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", dev->name); + DBG_PRINT(INTR_DBG, "PANIC levels\n"); if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) { DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name); DBG_PRINT(ERR_DBG, " in ISR!!\n"); - writeq(general_mask, - &bar0->general_int_mask); - spin_unlock(&sp->isr_lock); + clear_bit(0, (&sp->tasklet_status)); return IRQ_HANDLED; } - clear_bit(0, - (unsigned long *) (&sp->tasklet_status)); - } else if ((level == LOW) - && (!atomic_read(&sp->tasklet_status))) { + clear_bit(0, (&sp->tasklet_status)); + } else if (level == LOW) { tasklet_schedule(&sp->task); } - - } - } -#else - tasklet_schedule(&sp->task); #endif - /* Unmask all the previously enabled interrupts on the NIC */ - writeq(general_mask, &bar0->general_int_mask); - - spin_unlock(&sp->isr_lock); return IRQ_HANDLED; } -/* - * Input Argument/s: - * dev - pointer to the device structure. - * Return value: - * pointer to the updated net_device_stats structure. +/** + * s2io_get_stats - Updates the device statistics structure. + * @dev : pointer to the device structure. * Description: * This function updates the device statistics structure in the s2io_nic * structure and returns a pointer to the same. + * Return value: + * pointer to the updated net_device_stats structure. */ + struct net_device_stats *s2io_get_stats(struct net_device *dev) { nic_t *sp = dev->priv; @@ -2463,37 +2912,38 @@ struct net_device_stats *s2io_get_stats(struct net_device *dev) mac_control = &sp->mac_control; config = &sp->config; - sp->stats.tx_errors = mac_control->StatsInfo->tmac_any_err_frms; - sp->stats.rx_errors = mac_control->StatsInfo->rmac_drop_frms; - sp->stats.multicast = mac_control->StatsInfo->rmac_vld_mcst_frms; + sp->stats.tx_errors = mac_control->stats_info->tmac_any_err_frms; + sp->stats.rx_errors = mac_control->stats_info->rmac_drop_frms; + sp->stats.multicast = mac_control->stats_info->rmac_vld_mcst_frms; sp->stats.rx_length_errors = - mac_control->StatsInfo->rmac_long_frms; + mac_control->stats_info->rmac_long_frms; return (&sp->stats); } -/* - * Input Argument/s: - * dev - pointer to the device structure - * Return value: - * void. +/** + * s2io_set_multicast - entry point for multicast address enable/disable. + * @dev : pointer to the device structure * Description: * This function is a driver entry point which gets called by the kernel * whenever multicast addresses must be enabled/disabled. This also gets * called to set/reset promiscuous mode. Depending on the deivce flag, we * determine, if multicast address must be enabled or if promiscuous mode * is to be disabled etc. + * Return value: + * void. */ + static void s2io_set_multicast(struct net_device *dev) { int i, j, prev_cnt; struct dev_mc_list *mclist; nic_t *sp = dev->priv; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64 = 0, multi_mac = 0x010203040506ULL, mask = 0xfeffffffffffULL; u64 dis_addr = 0xffffffffffffULL, mac_addr = 0; - void *add; + void __iomem *add; if ((dev->flags & IFF_ALLMULTI) && (!sp->m_cast_flg)) { /* Enable all Multicast addresses */ @@ -2506,7 +2956,7 @@ static void s2io_set_multicast(struct net_device *dev) RMAC_ADDR_CMD_MEM_OFFSET(MAC_MC_ALL_MC_ADDR_OFFSET); writeq(val64, &bar0->rmac_addr_cmd_mem); /* Wait till command completes */ - waitForCmdComplete(sp); + wait_for_cmd_complete(sp); sp->m_cast_flg = 1; sp->all_multi_pos = MAC_MC_ALL_MC_ADDR_OFFSET; @@ -2519,7 +2969,7 @@ static void s2io_set_multicast(struct net_device *dev) RMAC_ADDR_CMD_MEM_OFFSET(sp->all_multi_pos); writeq(val64, &bar0->rmac_addr_cmd_mem); /* Wait till command completes */ - waitForCmdComplete(sp); + wait_for_cmd_complete(sp); sp->m_cast_flg = 0; sp->all_multi_pos = 0; @@ -2527,7 +2977,7 @@ static void s2io_set_multicast(struct net_device *dev) if ((dev->flags & IFF_PROMISC) && (!sp->promisc_flg)) { /* Put the NIC into promiscuous mode */ - add = (void *) &bar0->mac_cfg; + add = &bar0->mac_cfg; val64 = readq(&bar0->mac_cfg); val64 |= MAC_CFG_RMAC_PROM_ENABLE; @@ -2542,7 +2992,7 @@ static void s2io_set_multicast(struct net_device *dev) dev->name); } else if (!(dev->flags & IFF_PROMISC) && (sp->promisc_flg)) { /* Remove the NIC from promiscuous mode */ - add = (void *) &bar0->mac_cfg; + add = &bar0->mac_cfg; val64 = readq(&bar0->mac_cfg); val64 &= ~MAC_CFG_RMAC_PROM_ENABLE; @@ -2575,6 +3025,8 @@ static void s2io_set_multicast(struct net_device *dev) for (i = 0; i < prev_cnt; i++) { writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr), &bar0->rmac_addr_data0_mem); + writeq(RMAC_ADDR_DATA1_MEM_MASK(0ULL), + &bar0->rmac_addr_data1_mem); val64 = RMAC_ADDR_CMD_MEM_WE | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | RMAC_ADDR_CMD_MEM_OFFSET @@ -2582,7 +3034,7 @@ static void s2io_set_multicast(struct net_device *dev) writeq(val64, &bar0->rmac_addr_cmd_mem); /* Wait for command completes */ - if (waitForCmdComplete(sp)) { + if (wait_for_cmd_complete(sp)) { DBG_PRINT(ERR_DBG, "%s: Adding ", dev->name); DBG_PRINT(ERR_DBG, "Multicasts failed\n"); @@ -2599,8 +3051,11 @@ static void s2io_set_multicast(struct net_device *dev) mac_addr |= mclist->dmi_addr[j]; mac_addr <<= 8; } + mac_addr >>= 8; writeq(RMAC_ADDR_DATA0_MEM_ADDR(mac_addr), &bar0->rmac_addr_data0_mem); + writeq(RMAC_ADDR_DATA1_MEM_MASK(0ULL), + &bar0->rmac_addr_data1_mem); val64 = RMAC_ADDR_CMD_MEM_WE | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | @@ -2609,7 +3064,7 @@ static void s2io_set_multicast(struct net_device *dev) writeq(val64, &bar0->rmac_addr_cmd_mem); /* Wait for command completes */ - if (waitForCmdComplete(sp)) { + if (wait_for_cmd_complete(sp)) { DBG_PRINT(ERR_DBG, "%s: Adding ", dev->name); DBG_PRINT(ERR_DBG, "Multicasts failed\n"); @@ -2619,21 +3074,20 @@ static void s2io_set_multicast(struct net_device *dev) } } -/* - * Input Argument/s: - * dev - pointer to the device structure. - * new_mac - a uchar pointer to the new mac address which is to be set. - * Return value: - * SUCCESS on success and an appropriate (-)ve integer as defined in errno.h - * file on failure. - * Description: - * This procedure will program the Xframe to receive frames with new - * Mac Address +/** + * s2io_set_mac_addr - Programs the Xframe mac address + * @dev : pointer to the device structure. + * @addr: a uchar pointer to the new mac address which is to be set. + * Description : This procedure will program the Xframe to receive + * frames with new Mac Address + * Return value: SUCCESS on success and an appropriate (-)ve integer + * as defined in errno.h file on failure. */ + int s2io_set_mac_addr(struct net_device *dev, u8 * addr) { nic_t *sp = dev->priv; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; register u64 val64, mac_addr = 0; int i; @@ -2655,7 +3109,7 @@ int s2io_set_mac_addr(struct net_device *dev, u8 * addr) RMAC_ADDR_CMD_MEM_OFFSET(0); writeq(val64, &bar0->rmac_addr_cmd_mem); /* Wait till command completes */ - if (waitForCmdComplete(sp)) { + if (wait_for_cmd_complete(sp)) { DBG_PRINT(ERR_DBG, "%s: set_mac_addr failed\n", dev->name); return FAILURE; } @@ -2663,18 +3117,18 @@ int s2io_set_mac_addr(struct net_device *dev, u8 * addr) return SUCCESS; } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * info - pointer to the structure with parameters given by ethtool to set - * link information. - * Return value: - * 0 on success. +/** + * s2io_ethtool_sset - Sets different link parameters. + * @sp : private member of the device structure, which is a pointer to the * s2io_nic structure. + * @info: pointer to the structure with parameters given by ethtool to set + * link information. * Description: - * The function sets different link parameters provided by the user onto - * the NIC. - */ + * The function sets different link parameters provided by the user onto + * the NIC. + * Return value: + * 0 on success. +*/ + static int s2io_ethtool_sset(struct net_device *dev, struct ethtool_cmd *info) { @@ -2690,17 +3144,18 @@ static int s2io_ethtool_sset(struct net_device *dev, return 0; } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * info - pointer to the structure with parameters given by ethtool to return - * link information. - * Return value: - * void +/** + * s2io_ethtol_gset - Return link specific information. + * @sp : private member of the device structure, pointer to the + * s2io_nic structure. + * @info : pointer to the structure with parameters given by ethtool + * to return link information. * Description: - * Returns link specefic information like speed, duplex etc.. to ethtool. + * Returns link specific information like speed, duplex etc.. to ethtool. + * Return value : + * return 0 on success. */ + int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info) { nic_t *sp = dev->priv; @@ -2721,17 +3176,18 @@ int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info) return 0; } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * info - pointer to the structure with parameters given by ethtool to return - * driver information. +/** + * s2io_ethtool_gdrvinfo - Returns driver specific information. + * @sp : private member of the device structure, which is a pointer to the + * s2io_nic structure. + * @info : pointer to the structure with parameters given by ethtool to + * return driver information. + * Description: + * Returns driver specefic information like name, version etc.. to ethtool. * Return value: * void - * Description: - * Returns driver specefic information like name, version etc.. to ethtool. */ + static void s2io_ethtool_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { @@ -2748,19 +3204,20 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev, info->n_stats = S2IO_STAT_LEN; } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * regs - pointer to the structure with parameters given by ethtool for +/** + * s2io_ethtool_gregs - dumps the entire space of Xfame into the buffer. + * @sp: private member of the device structure, which is a pointer to the + * s2io_nic structure. + * @regs : pointer to the structure with parameters given by ethtool for * dumping the registers. - * reg_space - The input argumnet into which all the registers are dumped. - * Return value: - * void - * Description: - * Dumps the entire register space of xFrame NIC into the user given buffer - * area. - */ + * @reg_space: The input argumnet into which all the registers are dumped. + * Description: + * Dumps the entire register space of xFrame NIC into the user given + * buffer area. + * Return value : + * void . +*/ + static void s2io_ethtool_gregs(struct net_device *dev, struct ethtool_regs *regs, void *space) { @@ -2773,26 +3230,24 @@ static void s2io_ethtool_gregs(struct net_device *dev, regs->version = sp->pdev->subsystem_device; for (i = 0; i < regs->len; i += 8) { - reg = readq((void *) (sp->bar0 + i)); + reg = readq(sp->bar0 + i); memcpy((reg_space + i), ®, 8); } } -/* - * Input Argument/s: - * data - address of the private member of the device structure, which +/** + * s2io_phy_id - timer function that alternates adapter LED. + * @data : address of the private member of the device structure, which * is a pointer to the s2io_nic structure, provided as an u32. - * Return value: - * void - * Description: - * This is actually the timer function that alternates the adapter LED bit - * of the adapter control bit to set/reset every time on invocation. - * The timer is set for 1/2 a second, hence tha NIC blinks once every second. - */ + * Description: This is actually the timer function that alternates the + * adapter LED bit of the adapter control bit to set/reset every time on + * invocation. The timer is set for 1/2 a second, hence tha NIC blinks + * once every second. +*/ static void s2io_phy_id(unsigned long data) { nic_t *sp = (nic_t *) data; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64 = 0; u16 subid; @@ -2810,28 +3265,30 @@ static void s2io_phy_id(unsigned long data) mod_timer(&sp->id_timer, jiffies + HZ / 2); } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * id - pointer to the structure with identification parameters given by - * ethtool. +/** + * s2io_ethtool_idnic - To physically identify the nic on the system. + * @sp : private member of the device structure, which is a pointer to the + * s2io_nic structure. + * @id : pointer to the structure with identification parameters given by + * ethtool. + * Description: Used to physically identify the NIC on the system. + * The Link LED will blink for a time specified by the user for + * identification. + * NOTE: The Link has to be Up to be able to blink the LED. Hence + * identification is possible only if it's link is up. * Return value: - * int , returns '0' on success - * Description: - * Used to physically identify the NIC on the system. The Link LED will blink - * for a time specified by the user for identification. - * NOTE: The Link has to be Up to be able to blink the LED. Hence - * identification is possible only if it's link is up. + * int , returns 0 on success */ + static int s2io_ethtool_idnic(struct net_device *dev, u32 data) { - u64 val64 = 0; + u64 val64 = 0, last_gpio_ctrl_val; nic_t *sp = dev->priv; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u16 subid; subid = sp->pdev->subsystem_device; + last_gpio_ctrl_val = readq(&bar0->gpio_control); if ((subid & 0xFF) < 0x07) { val64 = readq(&bar0->adapter_control); if (!(val64 & ADAPTER_CNTL_EN)) { @@ -2853,25 +3310,29 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data) schedule_timeout(MAX_SCHEDULE_TIMEOUT); del_timer_sync(&sp->id_timer); + if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) { + writeq(last_gpio_ctrl_val, &bar0->gpio_control); + last_gpio_ctrl_val = readq(&bar0->gpio_control); + } + return 0; } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * ep - pointer to the structure with pause parameters given by ethtool. +/** + * s2io_ethtool_getpause_data -Pause frame frame generation and reception. + * @sp : private member of the device structure, which is a pointer to the * s2io_nic structure. + * @ep : pointer to the structure with pause parameters given by ethtool. + * Description: + * Returns the Pause frame generation and reception capability of the NIC. * Return value: * void - * Description: - * Returns the Pause frame generation and reception capability of the NIC. */ static void s2io_ethtool_getpause_data(struct net_device *dev, struct ethtool_pauseparam *ep) { u64 val64; nic_t *sp = dev->priv; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; val64 = readq(&bar0->rmac_pause_cfg); if (val64 & RMAC_PAUSE_GEN_ENABLE) @@ -2881,23 +3342,24 @@ static void s2io_ethtool_getpause_data(struct net_device *dev, ep->autoneg = FALSE; } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * ep - pointer to the structure with pause parameters given by ethtool. - * Return value: - * int, returns '0' on Success +/** + * s2io_ethtool_setpause_data - set/reset pause frame generation. + * @sp : private member of the device structure, which is a pointer to the + * s2io_nic structure. + * @ep : pointer to the structure with pause parameters given by ethtool. * Description: - * It can be used to set or reset Pause frame generation or reception support - * of the NIC. + * It can be used to set or reset Pause frame generation or reception + * support of the NIC. + * Return value: + * int, returns 0 on Success */ + int s2io_ethtool_setpause_data(struct net_device *dev, struct ethtool_pauseparam *ep) { u64 val64; nic_t *sp = dev->priv; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; val64 = readq(&bar0->rmac_pause_cfg); if (ep->tx_pause) @@ -2912,35 +3374,40 @@ int s2io_ethtool_setpause_data(struct net_device *dev, return 0; } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * off - offset at which the data must be written - * Return value: - * -1 on failure and the value read from the Eeprom if successful. +/** + * read_eeprom - reads 4 bytes of data from user given offset. + * @sp : private member of the device structure, which is a pointer to the + * s2io_nic structure. + * @off : offset at which the data must be written + * @data : Its an output parameter where the data read at the given + * offset is stored. * Description: - * Will read 4 bytes of data from the user given offset and return the - * read data. + * Will read 4 bytes of data from the user given offset and return the + * read data. * NOTE: Will allow to read only part of the EEPROM visible through the - * I2C bus. + * I2C bus. + * Return value: + * -1 on failure and 0 on success. */ + #define S2IO_DEV_ID 5 -static u32 readEeprom(nic_t * sp, int off) +static int read_eeprom(nic_t * sp, int off, u32 * data) { - u32 data = -1, exit_cnt = 0; + int ret = -1; + u32 exit_cnt = 0; u64 val64; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) | I2C_CONTROL_BYTE_CNT(0x3) | I2C_CONTROL_READ | I2C_CONTROL_CNTL_START; - writeq(val64, &bar0->i2c_control); + SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF); while (exit_cnt < 5) { val64 = readq(&bar0->i2c_control); if (I2C_CONTROL_CNTL_END(val64)) { - data = I2C_CONTROL_GET_DATA(val64); + *data = I2C_CONTROL_GET_DATA(val64); + ret = 0; break; } set_current_state(TASK_UNINTERRUPTIBLE); @@ -2948,33 +3415,34 @@ static u32 readEeprom(nic_t * sp, int off) exit_cnt++; } - return data; + return ret; } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * off - offset at which the data must be written - * data - The data that is to be written - * cnt - Number of bytes of the data that are actually to be written into +/** + * write_eeprom - actually writes the relevant part of the data value. + * @sp : private member of the device structure, which is a pointer to the + * s2io_nic structure. + * @off : offset at which the data must be written + * @data : The data that is to be written + * @cnt : Number of bytes of the data that are actually to be written into * the Eeprom. (max of 3) - * Return value: - * '0' on success, -1 on failure. * Description: * Actually writes the relevant part of the data value into the Eeprom * through the I2C bus. + * Return value: + * 0 on success, -1 on failure. */ -static int writeEeprom(nic_t * sp, int off, u32 data, int cnt) + +static int write_eeprom(nic_t * sp, int off, u32 data, int cnt) { int exit_cnt = 0, ret = -1; u64 val64; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) | I2C_CONTROL_BYTE_CNT(cnt) | I2C_CONTROL_SET_DATA(data) | I2C_CONTROL_CNTL_START; - writeq(val64, &bar0->i2c_control); + SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF); while (exit_cnt < 5) { val64 = readq(&bar0->i2c_control); @@ -2991,39 +3459,19 @@ static int writeEeprom(nic_t * sp, int off, u32 data, int cnt) return ret; } -/* - * A helper function used to invert the 4 byte u32 data field - * byte by byte. This will be used by the Read Eeprom function - * for display purposes. +/** + * s2io_ethtool_geeprom - reads the value stored in the Eeprom. + * @sp : private member of the device structure, which is a pointer to the * s2io_nic structure. + * @eeprom : pointer to the user level structure provided by ethtool, + * containing all relevant information. + * @data_buf : user defined value to be written into Eeprom. + * Description: Reads the values stored in the Eeprom at given offset + * for a given length. Stores these values int the input argument data + * buffer 'data_buf' and returns these to the caller (ethtool.) + * Return value: + * int 0 on success */ -u32 inv(u32 data) -{ - static u32 ret = 0; - - if (data) { - u8 c = data; - ret = ((ret << 8) + c); - data >>= 8; - inv(data); - } - return ret; -} - -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * eeprom - pointer to the user level structure provided by ethtool, - * containing all relevant information. - * data_buf - user defined value to be written into Eeprom. - * Return value: - * int '0' on success - * Description: - * Reads the values stored in the Eeprom at given offset for a given length. - * Stores these values int the input argument data buffer 'data_buf' and - * returns these to the caller (ethtool.) - */ int s2io_ethtool_geeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 * data_buf) { @@ -3036,30 +3484,30 @@ int s2io_ethtool_geeprom(struct net_device *dev, eeprom->len = XENA_EEPROM_SPACE - eeprom->offset; for (i = 0; i < eeprom->len; i += 4) { - data = readEeprom(sp, eeprom->offset + i); - if (data < 0) { + if (read_eeprom(sp, (eeprom->offset + i), &data)) { DBG_PRINT(ERR_DBG, "Read of EEPROM failed\n"); return -EFAULT; } - valid = inv(data); + valid = INV(data); memcpy((data_buf + i), &valid, 4); } return 0; } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * eeprom - pointer to the user level structure provided by ethtool, - * containing all relevant information. - * data_buf - user defined value to be written into Eeprom. - * Return value: - * '0' on success, -EFAULT on failure. - * Description: +/** + * s2io_ethtool_seeprom - tries to write the user provided value in Eeprom + * @sp : private member of the device structure, which is a pointer to the + * s2io_nic structure. + * @eeprom : pointer to the user level structure provided by ethtool, + * containing all relevant information. + * @data_buf ; user defined value to be written into Eeprom. + * Description: * Tries to write the user provided value in the Eeprom, at the offset * given by the user. + * Return value: + * 0 on success, -EFAULT on failure. */ + static int s2io_ethtool_seeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 * data_buf) @@ -3083,7 +3531,7 @@ static int s2io_ethtool_seeprom(struct net_device *dev, } else valid = data; - if (writeEeprom(sp, (eeprom->offset + cnt), valid, 0)) { + if (write_eeprom(sp, (eeprom->offset + cnt), valid, 0)) { DBG_PRINT(ERR_DBG, "ETHTOOL_WRITE_EEPROM Err: Cannot "); DBG_PRINT(ERR_DBG, @@ -3097,21 +3545,22 @@ static int s2io_ethtool_seeprom(struct net_device *dev, return 0; } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * data - variable that returns the result of each of the test conducted by - * the driver. - * Return value: - * '0' on success. +/** + * s2io_register_test - reads and writes into all clock domains. + * @sp : private member of the device structure, which is a pointer to the + * s2io_nic structure. + * @data : variable that returns the result of each of the test conducted b + * by the driver. * Description: - * Read and write into all clock domains. The NIC has 3 clock domains, - * see that registers in all the three regions are accessible. + * Read and write into all clock domains. The NIC has 3 clock domains, + * see that registers in all the three regions are accessible. + * Return value: + * 0 on success. */ -static int s2io_registerTest(nic_t * sp, uint64_t * data) + +static int s2io_register_test(nic_t * sp, uint64_t * data) { - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64 = 0; int fail = 0; @@ -3159,88 +3608,91 @@ static int s2io_registerTest(nic_t * sp, uint64_t * data) return 0; } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * data - variable that returns the result of each of the test conducted by - * the driver. - * Return value: - * '0' on success. +/** + * s2io_eeprom_test - to verify that EEprom in the xena can be programmed. + * @sp : private member of the device structure, which is a pointer to the + * s2io_nic structure. + * @data:variable that returns the result of each of the test conducted by + * the driver. * Description: - * Verify that EEPROM in the xena can be programmed using I2C_CONTROL - * register. + * Verify that EEPROM in the xena can be programmed using I2C_CONTROL + * register. + * Return value: + * 0 on success. */ -static int s2io_eepromTest(nic_t * sp, uint64_t * data) + +static int s2io_eeprom_test(nic_t * sp, uint64_t * data) { - int fail = 0, ret_data; + int fail = 0; + u32 ret_data; /* Test Write Error at offset 0 */ - if (!writeEeprom(sp, 0, 0, 3)) + if (!write_eeprom(sp, 0, 0, 3)) fail = 1; /* Test Write at offset 4f0 */ - if (writeEeprom(sp, 0x4F0, 0x01234567, 3)) + if (write_eeprom(sp, 0x4F0, 0x01234567, 3)) fail = 1; - if ((ret_data = readEeprom(sp, 0x4f0)) < 0) + if (read_eeprom(sp, 0x4F0, &ret_data)) fail = 1; if (ret_data != 0x01234567) fail = 1; /* Reset the EEPROM data go FFFF */ - writeEeprom(sp, 0x4F0, 0xFFFFFFFF, 3); + write_eeprom(sp, 0x4F0, 0xFFFFFFFF, 3); /* Test Write Request Error at offset 0x7c */ - if (!writeEeprom(sp, 0x07C, 0, 3)) + if (!write_eeprom(sp, 0x07C, 0, 3)) fail = 1; /* Test Write Request at offset 0x7fc */ - if (writeEeprom(sp, 0x7FC, 0x01234567, 3)) + if (write_eeprom(sp, 0x7FC, 0x01234567, 3)) fail = 1; - if ((ret_data = readEeprom(sp, 0x7FC)) < 0) + if (read_eeprom(sp, 0x7FC, &ret_data)) fail = 1; if (ret_data != 0x01234567) fail = 1; /* Reset the EEPROM data go FFFF */ - writeEeprom(sp, 0x7FC, 0xFFFFFFFF, 3); + write_eeprom(sp, 0x7FC, 0xFFFFFFFF, 3); /* Test Write Error at offset 0x80 */ - if (!writeEeprom(sp, 0x080, 0, 3)) + if (!write_eeprom(sp, 0x080, 0, 3)) fail = 1; /* Test Write Error at offset 0xfc */ - if (!writeEeprom(sp, 0x0FC, 0, 3)) + if (!write_eeprom(sp, 0x0FC, 0, 3)) fail = 1; /* Test Write Error at offset 0x100 */ - if (!writeEeprom(sp, 0x100, 0, 3)) + if (!write_eeprom(sp, 0x100, 0, 3)) fail = 1; /* Test Write Error at offset 4ec */ - if (!writeEeprom(sp, 0x4EC, 0, 3)) + if (!write_eeprom(sp, 0x4EC, 0, 3)) fail = 1; *data = fail; return 0; } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * data - variable that returns the result of each of the test conducted by - * the driver. - * Return value: - * '0' on success and -1 on failure. +/** + * s2io_bist_test - invokes the MemBist test of the card . + * @sp : private member of the device structure, which is a pointer to the + * s2io_nic structure. + * @data:variable that returns the result of each of the test conducted by + * the driver. * Description: - * This invokes the MemBist test of the card. We give around - * 2 secs time for the Test to complete. If it's still not complete - * within this peiod, we consider that the test failed. + * This invokes the MemBist test of the card. We give around + * 2 secs time for the Test to complete. If it's still not complete + * within this peiod, we consider that the test failed. + * Return value: + * 0 on success and -1 on failure. */ -static int s2io_bistTest(nic_t * sp, uint64_t * data) + +static int s2io_bist_test(nic_t * sp, uint64_t * data) { u8 bist = 0; int cnt = 0, ret = -1; @@ -3264,21 +3716,22 @@ static int s2io_bistTest(nic_t * sp, uint64_t * data) return ret; } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * data - variable that returns the result of each of the test conducted by - * the driver. - * Return value: - * '0' on success. +/** + * s2io-link_test - verifies the link state of the nic + * @sp ; private member of the device structure, which is a pointer to the + * s2io_nic structure. + * @data: variable that returns the result of each of the test conducted by + * the driver. * Description: - * The function verifies the link state of the NIC and updates the input - * argument 'data' appropriately. + * The function verifies the link state of the NIC and updates the input + * argument 'data' appropriately. + * Return value: + * 0 on success. */ -static int s2io_linkTest(nic_t * sp, uint64_t * data) + +static int s2io_link_test(nic_t * sp, uint64_t * data) { - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64; val64 = readq(&bar0->adapter_status); @@ -3288,21 +3741,22 @@ static int s2io_linkTest(nic_t * sp, uint64_t * data) return 0; } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * data - variable that returns the result of each of the test conducted by - * the driver. - * Return value: - * '0' on success. +/** + * s2io_rldram_test - offline test for access to the RldRam chip on the NIC + * @sp - private member of the device structure, which is a pointer to the + * s2io_nic structure. + * @data - variable that returns the result of each of the test + * conducted by the driver. * Description: * This is one of the offline test that tests the read and write * access to the RldRam chip on the NIC. + * Return value: + * 0 on success. */ -static int s2io_rldramTest(nic_t * sp, uint64_t * data) + +static int s2io_rldram_test(nic_t * sp, uint64_t * data) { - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64; int cnt, iteration = 0, test_pass = 0; @@ -3316,10 +3770,10 @@ static int s2io_rldramTest(nic_t * sp, uint64_t * data) val64 = readq(&bar0->mc_rldram_mrs); val64 |= MC_RLDRAM_QUEUE_SIZE_ENABLE; - writeq(val64, &bar0->mc_rldram_mrs); + SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_mrs, UF); val64 |= MC_RLDRAM_MRS_ENABLE; - writeq(val64, &bar0->mc_rldram_mrs); + SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_mrs, UF); while (iteration < 2) { val64 = 0x55555555aaaa0000ULL; @@ -3395,20 +3849,21 @@ static int s2io_rldramTest(nic_t * sp, uint64_t * data) return 0; } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * ethtest - pointer to a ethtool command specific structure that will be - * returned to the user. - * data - variable that returns the result of each of the test conducted by - * the driver. - * Return value: - * SUCCESS on success and an appropriate -1 on failure. +/** + * s2io_ethtool_test - conducts 6 tsets to determine the health of card. + * @sp : private member of the device structure, which is a pointer to the + * s2io_nic structure. + * @ethtest : pointer to a ethtool command specific structure that will be + * returned to the user. + * @data : variable that returns the result of each of the test + * conducted by the driver. * Description: * This function conducts 6 tests ( 4 offline and 2 online) to determine - * the health of the card. + * the health of the card. + * Return value: + * void */ + static void s2io_ethtool_test(struct net_device *dev, struct ethtool_test *ethtest, uint64_t * data) @@ -3424,22 +3879,22 @@ static void s2io_ethtool_test(struct net_device *dev, } else s2io_set_swapper(sp); - if (s2io_registerTest(sp, &data[0])) + if (s2io_register_test(sp, &data[0])) ethtest->flags |= ETH_TEST_FL_FAILED; s2io_reset(sp); s2io_set_swapper(sp); - if (s2io_rldramTest(sp, &data[3])) + if (s2io_rldram_test(sp, &data[3])) ethtest->flags |= ETH_TEST_FL_FAILED; s2io_reset(sp); s2io_set_swapper(sp); - if (s2io_eepromTest(sp, &data[1])) + if (s2io_eeprom_test(sp, &data[1])) ethtest->flags |= ETH_TEST_FL_FAILED; - if (s2io_bistTest(sp, &data[4])) + if (s2io_bist_test(sp, &data[4])) ethtest->flags |= ETH_TEST_FL_FAILED; if (orig_state) @@ -3459,7 +3914,7 @@ static void s2io_ethtool_test(struct net_device *dev, data[4] = -1; } - if (s2io_linkTest(sp, &data[2])) + if (s2io_link_test(sp, &data[2])) ethtest->flags |= ETH_TEST_FL_FAILED; data[0] = 0; @@ -3475,7 +3930,7 @@ static void s2io_get_ethtool_stats(struct net_device *dev, { int i = 0; nic_t *sp = dev->priv; - StatInfo_t *stat_info = sp->mac_control.StatsInfo; + StatInfo_t *stat_info = sp->mac_control.stats_info; tmp_stats[i++] = stat_info->tmac_frms; tmp_stats[i++] = stat_info->tmac_data_octets; @@ -3567,6 +4022,17 @@ static int s2io_ethtool_get_stats_count(struct net_device *dev) return (S2IO_STAT_LEN); } +int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data) +{ + if (data) + dev->features |= NETIF_F_IP_CSUM; + else + dev->features &= ~NETIF_F_IP_CSUM; + + return 0; +} + + static struct ethtool_ops netdev_ethtool_ops = { .get_settings = s2io_ethtool_gset, .set_settings = s2io_ethtool_sset, @@ -3582,7 +4048,7 @@ static struct ethtool_ops netdev_ethtool_ops = { .get_rx_csum = s2io_ethtool_get_rx_csum, .set_rx_csum = s2io_ethtool_set_rx_csum, .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, + .set_tx_csum = s2io_ethtool_op_set_tx_csum, .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, #ifdef NETIF_F_TSO @@ -3597,40 +4063,41 @@ static struct ethtool_ops netdev_ethtool_ops = { .get_ethtool_stats = s2io_get_ethtool_stats }; -/* - * Input Argument/s: - * dev - Device pointer. - * ifr - An IOCTL specefic structure, that can contain a pointer to - * a proprietary structure used to pass information to the driver. - * cmd - This is used to distinguish between the different commands that - * can be passed to the IOCTL functions. - * Return value: - * '0' on success and an appropriate (-)ve integer as defined in errno.h - * file on failure. +/** + * s2io_ioctl - Entry point for the Ioctl + * @dev : Device pointer. + * @ifr : An IOCTL specefic structure, that can contain a pointer to + * a proprietary structure used to pass information to the driver. + * @cmd : This is used to distinguish between the different commands that + * can be passed to the IOCTL functions. * Description: * This function has support for ethtool, adding multiple MAC addresses on * the NIC and some DBG commands for the util tool. + * Return value: + * Currently the IOCTL supports no operations, hence by default this + * function returns OP NOT SUPPORTED value. */ + int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { return -EOPNOTSUPP; } -/* - * Input Argument/s: - * dev - device pointer. - * new_mtu - the new MTU size for the device. +/** + * s2io_change_mtu - entry point to change MTU size for the device. + * @dev : device pointer. + * @new_mtu : the new MTU size for the device. + * Description: A driver entry point to change MTU size for the device. + * Before changing the MTU the device must be stopped. * Return value: - * '0' on success and an appropriate (-)ve integer as defined in errno.h + * 0 on success and an appropriate (-)ve integer as defined in errno.h * file on failure. - * Description: - * A driver entry point to change MTU size for the device. Before changing - * the MTU the device must be stopped. */ + int s2io_change_mtu(struct net_device *dev, int new_mtu) { nic_t *sp = dev->priv; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; register u64 val64; if (netif_running(dev)) { @@ -3645,7 +4112,7 @@ int s2io_change_mtu(struct net_device *dev, int new_mtu) return -EPERM; } -/* Set the new MTU into the PYLD register of the NIC */ + /* Set the new MTU into the PYLD register of the NIC */ val64 = new_mtu; writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len); @@ -3654,18 +4121,19 @@ int s2io_change_mtu(struct net_device *dev, int new_mtu) return 0; } -/* - * Input Argument/s: - * dev_adr - address of the device structure in dma_addr_t format. - * Return value: - * void. +/** + * s2io_tasklet - Bottom half of the ISR. + * @dev_adr : address of the device structure in dma_addr_t format. * Description: * This is the tasklet or the bottom half of the ISR. This is * an extension of the ISR which is scheduled by the scheduler to be run * when the load on the CPU is low. All low priority tasks of the ISR can * be pushed into the tasklet. For now the tasklet is used only to * replenish the Rx buffers in the Rx buffer descriptors. + * Return value: + * void. */ + static void s2io_tasklet(unsigned long dev_addr) { struct net_device *dev = (struct net_device *) dev_addr; @@ -3678,37 +4146,46 @@ static void s2io_tasklet(unsigned long dev_addr) config = &sp->config; if (!TASKLET_IN_USE) { - for (i = 0; i < config->RxRingNum; i++) { + for (i = 0; i < config->rx_ring_num; i++) { ret = fill_rx_buffers(sp, i); if (ret == -ENOMEM) { DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name); DBG_PRINT(ERR_DBG, "memory in tasklet\n"); - return; + break; } else if (ret == -EFILL) { DBG_PRINT(ERR_DBG, "%s: Rx Ring %d is full\n", dev->name, i); - return; + break; } } - clear_bit(0, (unsigned long *) (&sp->tasklet_status)); + clear_bit(0, (&sp->tasklet_status)); } } - -/* - * Description: - * +/** + * s2io_set_link - Set the LInk status + * @data: long pointer to device private structue + * Description: Sets the link status for the adapter */ + static void s2io_set_link(unsigned long data) { nic_t *nic = (nic_t *) data; struct net_device *dev = nic->dev; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; - register u64 val64, err_reg; + XENA_dev_config_t __iomem *bar0 = nic->bar0; + register u64 val64; + u16 subid; + + if (test_and_set_bit(0, &(nic->link_state))) { + /* The card is being reset, no point doing anything */ + return; + } - /* Allow a small delay for the NICs self initiated + subid = nic->pdev->subsystem_device; + /* + * Allow a small delay for the NICs self initiated * cleanup to complete. */ set_current_state(TASK_UNINTERRUPTIBLE); @@ -3716,16 +4193,19 @@ static void s2io_set_link(unsigned long data) val64 = readq(&bar0->adapter_status); if (verify_xena_quiescence(val64, nic->device_enabled_once)) { - /* Acknowledge interrupt and clear the R1 register */ - err_reg = readq(&bar0->mac_rmac_err_reg); - writeq(err_reg, &bar0->mac_rmac_err_reg); - if (LINK_IS_UP(val64)) { val64 = readq(&bar0->adapter_control); val64 |= ADAPTER_CNTL_EN; writeq(val64, &bar0->adapter_control); - val64 |= ADAPTER_LED_ON; - writeq(val64, &bar0->adapter_control); + if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) { + val64 = readq(&bar0->gpio_control); + val64 |= GPIO_CTRL_GPIO_0; + writeq(val64, &bar0->gpio_control); + val64 = readq(&bar0->gpio_control); + } else { + val64 |= ADAPTER_LED_ON; + writeq(val64, &bar0->adapter_control); + } val64 = readq(&bar0->adapter_status); if (!LINK_IS_UP(val64)) { DBG_PRINT(ERR_DBG, "%s:", dev->name); @@ -3739,6 +4219,12 @@ static void s2io_set_link(unsigned long data) } s2io_link(nic, LINK_UP); } else { + if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) { + val64 = readq(&bar0->gpio_control); + val64 &= ~GPIO_CTRL_GPIO_0; + writeq(val64, &bar0->gpio_control); + val64 = readq(&bar0->gpio_control); + } s2io_link(nic, LINK_DOWN); } } else { /* NIC is not Quiescent. */ @@ -3746,39 +4232,149 @@ static void s2io_set_link(unsigned long data) DBG_PRINT(ERR_DBG, "device is not Quiescent\n"); netif_stop_queue(dev); } + clear_bit(0, &(nic->link_state)); +} + +static void s2io_card_down(nic_t * sp) +{ + int cnt = 0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; + unsigned long flags; + register u64 val64 = 0; + + /* If s2io_set_link task is executing, wait till it completes. */ + while (test_and_set_bit(0, &(sp->link_state))) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 20); + } + atomic_set(&sp->card_state, CARD_DOWN); + + /* disable Tx and Rx traffic on the NIC */ + stop_nic(sp); + + /* Kill tasklet. */ + tasklet_kill(&sp->task); + + /* Check if the device is Quiescent and then Reset the NIC */ + do { + val64 = readq(&bar0->adapter_status); + if (verify_xena_quiescence(val64, sp->device_enabled_once)) { + break; + } + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 20); + cnt++; + if (cnt == 10) { + DBG_PRINT(ERR_DBG, + "s2io_close:Device not Quiescent "); + DBG_PRINT(ERR_DBG, "adaper status reads 0x%llx\n", + (unsigned long long) val64); + break; + } + } while (1); + spin_lock_irqsave(&sp->tx_lock, flags); + s2io_reset(sp); + + /* Free all unused Tx and Rx buffers */ + free_tx_buffers(sp); + free_rx_buffers(sp); + + spin_unlock_irqrestore(&sp->tx_lock, flags); + clear_bit(0, &(sp->link_state)); +} + +static int s2io_card_up(nic_t * sp) +{ + int i, ret; + mac_info_t *mac_control; + struct config_param *config; + struct net_device *dev = (struct net_device *) sp->dev; + + /* Initialize the H/W I/O registers */ + if (init_nic(sp) != 0) { + DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n", + dev->name); + return -ENODEV; + } + + /* + * Initializing the Rx buffers. For now we are considering only 1 + * Rx ring and initializing buffers into 30 Rx blocks + */ + mac_control = &sp->mac_control; + config = &sp->config; + + for (i = 0; i < config->rx_ring_num; i++) { + if ((ret = fill_rx_buffers(sp, i))) { + DBG_PRINT(ERR_DBG, "%s: Out of memory in Open\n", + dev->name); + s2io_reset(sp); + free_rx_buffers(sp); + return -ENOMEM; + } + DBG_PRINT(INFO_DBG, "Buf in ring:%d is %d:\n", i, + atomic_read(&sp->rx_bufs_left[i])); + } + + /* Setting its receive mode */ + s2io_set_multicast(dev); + + /* Enable tasklet for the device */ + tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev); + + /* Enable Rx Traffic and interrupts on the NIC */ + if (start_nic(sp)) { + DBG_PRINT(ERR_DBG, "%s: Starting NIC failed\n", dev->name); + tasklet_kill(&sp->task); + s2io_reset(sp); + free_irq(dev->irq, dev); + free_rx_buffers(sp); + return -ENODEV; + } + + atomic_set(&sp->card_state, CARD_UP); + return 0; } -/* +/** + * s2io_restart_nic - Resets the NIC. + * @data : long pointer to the device private structure * Description: * This function is scheduled to be run by the s2io_tx_watchdog * function after 0.5 secs to reset the NIC. The idea is to reduce * the run time of the watch dog routine which is run holding a * spin lock. */ + static void s2io_restart_nic(unsigned long data) { struct net_device *dev = (struct net_device *) data; nic_t *sp = dev->priv; - s2io_close(dev); - sp->device_close_flag = TRUE; - s2io_open(dev); - DBG_PRINT(ERR_DBG, - "%s: was reset by Tx watchdog timer.\n", dev->name); + s2io_card_down(sp); + if (s2io_card_up(sp)) { + DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n", + dev->name); + } + netif_wake_queue(dev); + DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n", + dev->name); } -/* - * Input Argument/s: - * dev - device pointer. - * Return value: - * void +/** + * s2io_tx_watchdog - Watchdog for transmit side. + * @dev : Pointer to net device structure * Description: * This function is triggered if the Tx Queue is stopped * for a pre-defined amount of time when the Interface is still up. * If the Interface is jammed in such a situation, the hardware is * reset (by s2io_close) and restarted again (by s2io_open) to * overcome any problem that might have been caused in the hardware. + * Return value: + * void */ + static void s2io_tx_watchdog(struct net_device *dev) { nic_t *sp = dev->priv; @@ -3788,36 +4384,45 @@ static void s2io_tx_watchdog(struct net_device *dev) } } -/* - * Input Argument/s: - * sp - private member of the device structure, which is a pointer to the - * s2io_nic structure. - * skb - the socket buffer pointer. - * len - length of the packet - * cksum - FCS checksum of the frame. - * ring_no - the ring from which this RxD was extracted. - * Return value: - * SUCCESS on success and -1 on failure. - * Description: - * This function is called by the Tx interrupt serivce routine to perform +/** + * rx_osm_handler - To perform some OS related operations on SKB. + * @sp: private member of the device structure,pointer to s2io_nic structure. + * @skb : the socket buffer pointer. + * @len : length of the packet + * @cksum : FCS checksum of the frame. + * @ring_no : the ring from which this RxD was extracted. + * Description: + * This function is called by the Tx interrupt serivce routine to perform * some OS related operations on the SKB before passing it to the upper * layers. It mainly checks if the checksum is OK, if so adds it to the * SKBs cksum variable, increments the Rx packet count and passes the SKB * to the upper layer. If the checksum is wrong, it increments the Rx * packet error count, frees the SKB and returns error. + * Return value: + * SUCCESS on success and -1 on failure. */ -static int rxOsmHandler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no) +#ifndef CONFIG_2BUFF_MODE +static int rx_osm_handler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no) +#else +static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no, + buffAdd_t * ba) +#endif { struct net_device *dev = (struct net_device *) sp->dev; struct sk_buff *skb = (struct sk_buff *) ((unsigned long) rxdp->Host_Control); u16 l3_csum, l4_csum; +#ifdef CONFIG_2BUFF_MODE + int buf0_len, buf2_len; + unsigned char *buff; +#endif l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1); if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && (sp->rx_csum)) { l4_csum = RXD_GET_L4_CKSUM(rxdp->Control_1); if ((l3_csum == L3_CKSUM_OK) && (l4_csum == L4_CKSUM_OK)) { - /* NIC verifies if the Checksum of the received + /* + * NIC verifies if the Checksum of the received * frame is Ok or not and accordingly returns * a flag in the RxD. */ @@ -3833,9 +4438,26 @@ static int rxOsmHandler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no) skb->ip_summed = CHECKSUM_NONE; } + if (rxdp->Control_1 & RXD_T_CODE) { + unsigned long long err = rxdp->Control_1 & RXD_T_CODE; + DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n", + dev->name, err); + } +#ifdef CONFIG_2BUFF_MODE + buf0_len = RXD_GET_BUFFER0_SIZE(rxdp->Control_2); + buf2_len = RXD_GET_BUFFER2_SIZE(rxdp->Control_2); +#endif + skb->dev = dev; +#ifndef CONFIG_2BUFF_MODE skb_put(skb, len); skb->protocol = eth_type_trans(skb, dev); +#else + buff = skb_push(skb, buf0_len); + memcpy(buff, ba->ba_0, buf0_len); + skb_put(skb, buf2_len); + skb->protocol = eth_type_trans(skb, dev); +#endif #ifdef CONFIG_S2IO_NAPI netif_receive_skb(skb); @@ -3844,50 +4466,32 @@ static int rxOsmHandler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no) #endif dev->last_rx = jiffies; -#if DEBUG_ON - sp->rxpkt_cnt++; -#endif sp->rx_pkt_count++; sp->stats.rx_packets++; +#ifndef CONFIG_2BUFF_MODE sp->stats.rx_bytes += len; - sp->rxpkt_bytes += len; +#else + sp->stats.rx_bytes += buf0_len + buf2_len; +#endif atomic_dec(&sp->rx_bufs_left[ring_no]); rxdp->Host_Control = 0; return SUCCESS; } -int check_for_txSpace(nic_t * sp) -{ - u32 put_off, get_off, queue_len; - int ret = TRUE, i; - - for (i = 0; i < sp->config.TxFIFONum; i++) { - queue_len = sp->mac_control.tx_curr_put_info[i].fifo_len - + 1; - put_off = sp->mac_control.tx_curr_put_info[i].offset; - get_off = sp->mac_control.tx_curr_get_info[i].offset; - if (((put_off + 1) % queue_len) == get_off) { - ret = FALSE; - break; - } - } - - return ret; -} +/** + * s2io_link - stops/starts the Tx queue. + * @sp : private member of the device structure, which is a pointer to the + * s2io_nic structure. + * @link : inidicates whether link is UP/DOWN. + * Description: + * This function stops/starts the Tx queue depending on whether the link + * status of the NIC is is down or up. This is called by the Alarm + * interrupt handler whenever a link change interrupt comes up. + * Return value: + * void. + */ -/* -* Input Argument/s: -* sp - private member of the device structure, which is a pointer to the -* s2io_nic structure. -* link - inidicates whether link is UP/DOWN. -* Return value: -* void. -* Description: -* This function stops/starts the Tx queue depending on whether the link -* status of the NIC is is down or up. This is called by the Alarm interrupt -* handler whenever a link change interrupt comes up. -*/ void s2io_link(nic_t * sp, int link) { struct net_device *dev = (struct net_device *) sp->dev; @@ -3896,29 +4500,23 @@ void s2io_link(nic_t * sp, int link) if (link == LINK_DOWN) { DBG_PRINT(ERR_DBG, "%s: Link down\n", dev->name); netif_carrier_off(dev); - netif_stop_queue(dev); } else { DBG_PRINT(ERR_DBG, "%s: Link Up\n", dev->name); netif_carrier_on(dev); - if (check_for_txSpace(sp) == TRUE) { - /* Don't wake the queue, if we know there - * are no free TxDs available. - */ - netif_wake_queue(dev); - } } } sp->last_link_state = link; } -/* -* Input Argument/s: -* pdev - structure containing the PCI related information of the device. -* Return value: -* returns the revision ID of the device. -* Description: -* Function to identify the Revision ID of xena. -*/ +/** + * get_xena_rev_id - to identify revision ID of xena. + * @pdev : PCI Dev structure + * Description: + * Function to identify the Revision ID of xena. + * Return value: + * returns the revision ID of the device. + */ + int get_xena_rev_id(struct pci_dev *pdev) { u8 id = 0; @@ -3927,21 +4525,22 @@ int get_xena_rev_id(struct pci_dev *pdev) return id; } -/* -* Input Argument/s: -* sp - private member of the device structure, which is a pointer to the -* s2io_nic structure. -* Return value: -* void -* Description: -* This function initializes a few of the PCI and PCI-X configuration registers -* with recommended values. -*/ +/** + * s2io_init_pci -Initialization of PCI and PCI-X configuration registers . + * @sp : private member of the device structure, which is a pointer to the + * s2io_nic structure. + * Description: + * This function initializes a few of the PCI and PCI-X configuration registers + * with recommended values. + * Return value: + * void + */ + static void s2io_init_pci(nic_t * sp) { u16 pci_cmd = 0; -/* Enable Data Parity Error Recovery in PCI-X command register. */ + /* Enable Data Parity Error Recovery in PCI-X command register. */ pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(sp->pcix_cmd)); pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, @@ -3949,63 +4548,64 @@ static void s2io_init_pci(nic_t * sp) pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(sp->pcix_cmd)); -/* Set the PErr Response bit in PCI command register. */ + /* Set the PErr Response bit in PCI command register. */ pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd); pci_write_config_word(sp->pdev, PCI_COMMAND, (pci_cmd | PCI_COMMAND_PARITY)); pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd); -/* Set user specified value in Latency Timer */ - if (latency_timer) { - pci_write_config_byte(sp->pdev, PCI_LATENCY_TIMER, - latency_timer); - pci_read_config_byte(sp->pdev, PCI_LATENCY_TIMER, - &latency_timer); - } - -/* Set MMRB count to 4096 in PCI-X Command register. */ - pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, - (sp->pcix_cmd | 0x0C)); + /* Set MMRB count to 1024 in PCI-X Command register. */ + sp->pcix_cmd &= 0xFFF3; + pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, (sp->pcix_cmd | (0x1 << 2))); /* MMRBC 1K */ pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(sp->pcix_cmd)); -/* Setting Maximum outstanding splits to two for now. */ - sp->pcix_cmd &= 0xFF1F; + /* Setting Maximum outstanding splits based on system type. */ + sp->pcix_cmd &= 0xFF8F; - sp->pcix_cmd |= - XENA_MAX_OUTSTANDING_SPLITS(XENA_TWO_SPLIT_TRANSACTION); + sp->pcix_cmd |= XENA_MAX_OUTSTANDING_SPLITS(0x1); /* 2 splits. */ + pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, + sp->pcix_cmd); + pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, + &(sp->pcix_cmd)); + /* Forcibly disabling relaxed ordering capability of the card. */ + sp->pcix_cmd &= 0xfffd; pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, sp->pcix_cmd); pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(sp->pcix_cmd)); - } MODULE_AUTHOR("Raghavendra Koushik "); MODULE_LICENSE("GPL"); -MODULE_PARM(ring_num, "1-" __MODULE_STRING(1) "i"); -MODULE_PARM(frame_len, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(ring_len, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(fifo_num, "1-" __MODULE_STRING(1) "i"); -MODULE_PARM(fifo_len, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(rx_prio, "1-" __MODULE_STRING(1) "i"); -MODULE_PARM(tx_prio, "1-" __MODULE_STRING(1) "i"); -MODULE_PARM(latency_timer, "1-" __MODULE_STRING(1) "i"); - -/* -* Input Argument/s: -* pdev - structure containing the PCI related information of the device. -* pre - the List of PCI devices supported by the driver listed in s2io_tbl. -* Return value: -* returns '0' on success and negative on failure. -* Description: -* The function initializes an adapter identified by the pci_dec structure. -* All OS related initialization including memory and device structure and -* initlaization of the device private variable is done. Also the swapper -* control register is initialized to enable read and write into the I/O -* registers of the device. -* -*/ +module_param(tx_fifo_num, int, 0); +module_param_array(tx_fifo_len, int, NULL, 0); +module_param(rx_ring_num, int, 0); +module_param_array(rx_ring_sz, int, NULL, 0); +module_param(Stats_refresh_time, int, 0); +module_param(rmac_pause_time, int, 0); +module_param(mc_pause_threshold_q0q3, int, 0); +module_param(mc_pause_threshold_q4q7, int, 0); +module_param(shared_splits, int, 0); +module_param(tmac_util_period, int, 0); +module_param(rmac_util_period, int, 0); +#ifndef CONFIG_S2IO_NAPI +module_param(indicate_max_pkts, int, 0); +#endif +/** + * s2io_init_nic - Initialization of the adapter . + * @pdev : structure containing the PCI related information of the device. + * @pre: List of PCI devices supported by the driver listed in s2io_tbl. + * Description: + * The function initializes an adapter identified by the pci_dec structure. + * All OS related initialization including memory and device structure and + * initlaization of the device private variable is done. Also the swapper + * control register is initialized to enable read and write into the I/O + * registers of the device. + * Return value: + * returns 0 on success and negative on failure. + */ + static int __devinit s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) { @@ -4016,12 +4616,15 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) int dma_flag = FALSE; u32 mac_up, mac_down; u64 val64 = 0, tmp64 = 0; - XENA_dev_config_t *bar0 = NULL; + XENA_dev_config_t __iomem *bar0 = NULL; u16 subid; mac_info_t *mac_control; struct config_param *config; + DBG_PRINT(ERR_DBG, "Loading S2IO driver with %s\n", + s2io_driver_version); + if ((ret = pci_enable_device(pdev))) { DBG_PRINT(ERR_DBG, "s2io_init_nic: pci_enable_device failed\n"); @@ -4031,6 +4634,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) { DBG_PRINT(INIT_DBG, "s2io_init_nic: Using 64bit DMA\n"); dma_flag = TRUE; + if (pci_set_consistent_dma_mask (pdev, 0xffffffffffffffffULL)) { DBG_PRINT(ERR_DBG, @@ -4080,7 +4684,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) /* Initialize some PCI/PCI-X fields of the NIC. */ s2io_init_pci(sp); - /* Setting the device configuration parameters. + /* + * Setting the device configuration parameters. * Most of these parameters can be specified by the user during * module insertion as they are module loadable parameters. If * these parameters are not not specified during load time, they @@ -4090,104 +4695,72 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) config = &sp->config; /* Tx side parameters. */ - config->TxFIFONum = fifo_num ? fifo_num : 1; - - if (!fifo_len[0] && (fifo_num > 1)) { - printk(KERN_ERR "Fifo Lens not specified for all FIFOs\n"); - goto init_failed; - } - - if (fifo_len[0]) { - int cnt; - - for (cnt = 0; fifo_len[cnt]; cnt++); - if (fifo_num) { - if (cnt < fifo_num) { - printk(KERN_ERR - "Fifo Lens not specified for "); - printk(KERN_ERR "all FIFOs\n"); - goto init_failed; - } - } - for (cnt = 0; cnt < config->TxFIFONum; cnt++) { - config->TxCfg[cnt].FifoLen = fifo_len[cnt]; - config->TxCfg[cnt].FifoPriority = cnt; - } - } else { - config->TxCfg[0].FifoLen = DEFAULT_FIFO_LEN; - config->TxCfg[0].FifoPriority = 0; + tx_fifo_len[0] = DEFAULT_FIFO_LEN; /* Default value. */ + config->tx_fifo_num = tx_fifo_num; + for (i = 0; i < MAX_TX_FIFOS; i++) { + config->tx_cfg[i].fifo_len = tx_fifo_len[i]; + config->tx_cfg[i].fifo_priority = i; } - config->TxIntrType = TXD_INT_TYPE_UTILZ; - for (i = 0; i < config->TxFIFONum; i++) { - if (config->TxCfg[i].FifoLen < 65) { - config->TxIntrType = TXD_INT_TYPE_PER_LIST; + config->tx_intr_type = TXD_INT_TYPE_UTILZ; + for (i = 0; i < config->tx_fifo_num; i++) { + config->tx_cfg[i].f_no_snoop = + (NO_SNOOP_TXD | NO_SNOOP_TXD_BUFFER); + if (config->tx_cfg[i].fifo_len < 65) { + config->tx_intr_type = TXD_INT_TYPE_PER_LIST; break; } } - - config->TxCfg[0].fNoSnoop = (NO_SNOOP_TXD | NO_SNOOP_TXD_BUFFER); - config->MaxTxDs = MAX_SKB_FRAGS; - config->TxFlow = TRUE; + config->max_txds = MAX_SKB_FRAGS; /* Rx side parameters. */ - config->RxRingNum = ring_num ? ring_num : 1; - - if (ring_len[0]) { - int cnt; - for (cnt = 0; cnt < config->RxRingNum; cnt++) { - config->RxCfg[cnt].NumRxd = ring_len[cnt]; - config->RxCfg[cnt].RingPriority = cnt; - } - } else { - int id; - if ((id = get_xena_rev_id(pdev)) == 1) { - config->RxCfg[0].NumRxd = LARGE_RXD_CNT; - - } else { - config->RxCfg[0].NumRxd = SMALL_RXD_CNT; - } - config->RxCfg[0].RingPriority = 0; + rx_ring_sz[0] = SMALL_BLK_CNT; /* Default value. */ + config->rx_ring_num = rx_ring_num; + for (i = 0; i < MAX_RX_RINGS; i++) { + config->rx_cfg[i].num_rxd = rx_ring_sz[i] * + (MAX_RXDS_PER_BLOCK + 1); + config->rx_cfg[i].ring_priority = i; } - config->RxCfg[0].RingOrg = RING_ORG_BUFF1; - config->RxCfg[0].RxdThresh = DEFAULT_RXD_THRESHOLD; - config->RxCfg[0].fNoSnoop = (NO_SNOOP_RXD | NO_SNOOP_RXD_BUFFER); - config->RxCfg[0].RxD_BackOff_Interval = TBD; - config->RxFlow = TRUE; - /* Miscellaneous parameters. */ - config->RxVLANEnable = TRUE; - config->MTU = MAX_MTU_VLAN; - config->JumboEnable = FALSE; + for (i = 0; i < rx_ring_num; i++) { + config->rx_cfg[i].ring_org = RING_ORG_BUFF1; + config->rx_cfg[i].f_no_snoop = + (NO_SNOOP_RXD | NO_SNOOP_RXD_BUFFER); + } /* Setting Mac Control parameters */ - mac_control->txdl_len = MAX_SKB_FRAGS; - mac_control->rmac_pause_time = 0; + mac_control->rmac_pause_time = rmac_pause_time; + mac_control->mc_pause_threshold_q0q3 = mc_pause_threshold_q0q3; + mac_control->mc_pause_threshold_q4q7 = mc_pause_threshold_q4q7; + /* Initialize Ring buffer parameters. */ - for (i = 0; i < config->RxRingNum; i++) + for (i = 0; i < config->rx_ring_num; i++) atomic_set(&sp->rx_bufs_left[i], 0); /* initialize the shared memory used by the NIC and the host */ - if (initSharedMem(sp)) { + if (init_shared_mem(sp)) { DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", dev->name); + ret = -ENOMEM; goto mem_alloc_failed; } - sp->bar0 = (caddr_t) ioremap(pci_resource_start(pdev, 0), + sp->bar0 = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); if (!sp->bar0) { DBG_PRINT(ERR_DBG, "%s: S2IO: cannot remap io mem1\n", dev->name); + ret = -ENOMEM; goto bar0_remap_failed; } - sp->bar1 = (caddr_t) ioremap(pci_resource_start(pdev, 2), + sp->bar1 = ioremap(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); if (!sp->bar1) { DBG_PRINT(ERR_DBG, "%s: S2IO: cannot remap io mem2\n", dev->name); + ret = -ENOMEM; goto bar1_remap_failed; } @@ -4196,7 +4769,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) /* Initializing the BAR1 address as the start of the FIFO pointer. */ for (j = 0; j < MAX_TX_FIFOS; j++) { - mac_control->tx_FIFO_start[j] = (TxFIFO_element_t *) + mac_control->tx_FIFO_start[j] = (TxFIFO_element_t __iomem *) (sp->bar1 + (j * 0x00020000)); } @@ -4209,14 +4782,13 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) dev->do_ioctl = &s2io_ioctl; dev->change_mtu = &s2io_change_mtu; SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - /* * will use eth_mac_addr() for dev->set_mac_address * mac address will be set every time dev->open() is called */ #ifdef CONFIG_S2IO_NAPI dev->poll = s2io_poll; - dev->weight = 128; /* For now. */ + dev->weight = 90; #endif dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; @@ -4233,77 +4805,84 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) INIT_WORK(&sp->set_link_task, (void (*)(void *)) s2io_set_link, sp); - if (register_netdev(dev)) { - DBG_PRINT(ERR_DBG, "Device registration failed\n"); - goto register_failed; - } - - pci_save_state(sp->pdev, sp->config_space); + pci_save_state(sp->pdev); /* Setting swapper control on the NIC, for proper reset operation */ if (s2io_set_swapper(sp)) { DBG_PRINT(ERR_DBG, "%s:swapper settings are wrong\n", dev->name); + ret = -EAGAIN; goto set_swap_failed; } /* Fix for all "FFs" MAC address problems observed on Alpha platforms */ - FixMacAddress(sp); + fix_mac_address(sp); s2io_reset(sp); - /* Setting swapper control on the NIC, so the MAC address can be read. + /* + * Setting swapper control on the NIC, so the MAC address can be read. */ if (s2io_set_swapper(sp)) { DBG_PRINT(ERR_DBG, "%s: S2IO: swapper settings are wrong\n", dev->name); + ret = -EAGAIN; goto set_swap_failed; } - /* MAC address initialization. - * For now only one mac address will be read and used. + /* + * MAC address initialization. + * For now only one mac address will be read and used. */ - bar0 = (XENA_dev_config_t *) sp->bar0; + bar0 = sp->bar0; val64 = RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | RMAC_ADDR_CMD_MEM_OFFSET(0 + MAC_MAC_ADDR_START_OFFSET); writeq(val64, &bar0->rmac_addr_cmd_mem); - waitForCmdComplete(sp); + wait_for_cmd_complete(sp); tmp64 = readq(&bar0->rmac_addr_data0_mem); mac_down = (u32) tmp64; mac_up = (u32) (tmp64 >> 32); - memset(sp->defMacAddr[0].mac_addr, 0, sizeof(ETH_ALEN)); + memset(sp->def_mac_addr[0].mac_addr, 0, sizeof(ETH_ALEN)); - sp->defMacAddr[0].mac_addr[3] = (u8) (mac_up); - sp->defMacAddr[0].mac_addr[2] = (u8) (mac_up >> 8); - sp->defMacAddr[0].mac_addr[1] = (u8) (mac_up >> 16); - sp->defMacAddr[0].mac_addr[0] = (u8) (mac_up >> 24); - sp->defMacAddr[0].mac_addr[5] = (u8) (mac_down >> 16); - sp->defMacAddr[0].mac_addr[4] = (u8) (mac_down >> 24); + sp->def_mac_addr[0].mac_addr[3] = (u8) (mac_up); + sp->def_mac_addr[0].mac_addr[2] = (u8) (mac_up >> 8); + sp->def_mac_addr[0].mac_addr[1] = (u8) (mac_up >> 16); + sp->def_mac_addr[0].mac_addr[0] = (u8) (mac_up >> 24); + sp->def_mac_addr[0].mac_addr[5] = (u8) (mac_down >> 16); + sp->def_mac_addr[0].mac_addr[4] = (u8) (mac_down >> 24); DBG_PRINT(INIT_DBG, "DEFAULT MAC ADDR:0x%02x-%02x-%02x-%02x-%02x-%02x\n", - sp->defMacAddr[0].mac_addr[0], - sp->defMacAddr[0].mac_addr[1], - sp->defMacAddr[0].mac_addr[2], - sp->defMacAddr[0].mac_addr[3], - sp->defMacAddr[0].mac_addr[4], - sp->defMacAddr[0].mac_addr[5]); + sp->def_mac_addr[0].mac_addr[0], + sp->def_mac_addr[0].mac_addr[1], + sp->def_mac_addr[0].mac_addr[2], + sp->def_mac_addr[0].mac_addr[3], + sp->def_mac_addr[0].mac_addr[4], + sp->def_mac_addr[0].mac_addr[5]); /* Set the factory defined MAC address initially */ dev->addr_len = ETH_ALEN; - memcpy(dev->dev_addr, sp->defMacAddr, ETH_ALEN); + memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN); - /* Initialize the tasklet status flag */ - atomic_set(&(sp->tasklet_status), 0); + /* + * Initialize the tasklet status and link state flags + * and the card statte parameter + */ + atomic_set(&(sp->card_state), 0); + sp->tasklet_status = 0; + sp->link_state = 0; /* Initialize spinlocks */ - spin_lock_init(&sp->isr_lock); spin_lock_init(&sp->tx_lock); +#ifndef CONFIG_S2IO_NAPI + spin_lock_init(&sp->put_lock); +#endif - /* SXE-002: Configure link and activity LED to init state + /* + * SXE-002: Configure link and activity LED to init state * on driver load. */ subid = sp->pdev->subsystem_device; @@ -4312,49 +4891,53 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) val64 |= 0x0000800000000000ULL; writeq(val64, &bar0->gpio_control); val64 = 0x0411040400000000ULL; - writeq(val64, (u64 *) ((u8 *) bar0 + 0x2700)); + writeq(val64, (void __iomem *) bar0 + 0x2700); val64 = readq(&bar0->gpio_control); } - /* Make Link state as off at this point, when the Link change + sp->rx_csum = 1; /* Rx chksum verify enabled by default */ + + if (register_netdev(dev)) { + DBG_PRINT(ERR_DBG, "Device registration failed\n"); + ret = -ENODEV; + goto register_failed; + } + + /* + * Make Link state as off at this point, when the Link change * interrupt comes the state will be automatically changed to * the right state. */ netif_carrier_off(dev); sp->last_link_state = LINK_DOWN; - sp->rx_csum = 1; /* Rx chksum verify enabled by default */ - return 0; - set_swap_failed: - unregister_netdev(dev); register_failed: + set_swap_failed: iounmap(sp->bar1); bar1_remap_failed: iounmap(sp->bar0); bar0_remap_failed: mem_alloc_failed: - freeSharedMem(sp); - init_failed: + free_shared_mem(sp); pci_disable_device(pdev); pci_release_regions(pdev); pci_set_drvdata(pdev, NULL); free_netdev(dev); - return -ENODEV; + return ret; } -/* -* Input Argument/s: -* pdev - structure containing the PCI related information of the device. -* Return value: -* void -* Description: -* This function is called by the Pci subsystem to release a PCI device -* and free up all resource held up by the device. This could be in response -* to a Hot plug event or when the driver is to be removed from memory. -*/ +/** + * s2io_rem_nic - Free the PCI device + * @pdev: structure containing the PCI related information of the device. + * Description: This function is called by the Pci subsystem to release a + * PCI device and free up all resource held up by the device. This could + * be in response to a Hot plug event or when the driver is to be removed + * from memory. + */ + static void __devexit s2io_rem_nic(struct pci_dev *pdev) { struct net_device *dev = @@ -4365,24 +4948,36 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev) DBG_PRINT(ERR_DBG, "Driver Data is NULL!!\n"); return; } + sp = dev->priv; - freeSharedMem(sp); + unregister_netdev(dev); + + free_shared_mem(sp); iounmap(sp->bar0); iounmap(sp->bar1); pci_disable_device(pdev); pci_release_regions(pdev); pci_set_drvdata(pdev, NULL); - unregister_netdev(dev); - free_netdev(dev); } +/** + * s2io_starter - Entry point for the driver + * Description: This function is the entry point for the driver. It verifies + * the module loadable parameters and initializes PCI configuration space. + */ + int __init s2io_starter(void) { return pci_module_init(&s2io_driver); } +/** + * s2io_closer - Cleanup routine for the driver + * Description: This function is the cleanup routine for the driver. It unregist * ers the driver. + */ + void s2io_closer(void) { pci_unregister_driver(&s2io_driver);