X-Git-Url: http://git.onelab.eu/?p=linux-2.6.git;a=blobdiff_plain;f=drivers%2Fnet%2Fs2io.c;fp=drivers%2Fnet%2Fs2io.c;h=b7f00d6eb6a6a49bd3b34f4729806cf77d867702;hp=e72e0e099060f6386f22e3800dfdef76aa326e1e;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index e72e0e099..b7f00d6eb 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -26,24 +26,18 @@ * * The module loadable parameters that are supported by the driver and a brief * explaination of all the variables. - * * rx_ring_num : This can be used to program the number of receive rings used * in the driver. - * rx_ring_sz: This defines the number of receive blocks each ring can have. - * This is also an array of size 8. + * rx_ring_sz: This defines the number of descriptors each ring can have. This + * is also an array of size 8. * rx_ring_mode: This defines the operation mode of all 8 rings. The valid * values are 1, 2 and 3. * 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. - * intr_type: This defines the type of interrupt. The values can be 0(INTA), - * 1(MSI), 2(MSI_X). Default value is '0(INTA)' - * lro: Specifies whether to enable Large Receive Offload (LRO) or not. - * Possible values '1' for enable '0' for disable. Default is '0' - * lro_max_pkts: This parameter defines maximum number of packets can be - * aggregated as a single large packet ************************************************************************/ +#include #include #include #include @@ -63,28 +57,23 @@ #include #include #include -#include -#include -#include #include #include #include -#include -#include /* local include */ #include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "2.0.15.2" +#define DRV_VERSION "Version 2.0.9.4" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; static char s2io_driver_version[] = DRV_VERSION; -static int rxd_size[4] = {32,48,48,64}; -static int rxd_count[4] = {127,85,85,63}; +int rxd_size[4] = {32,48,48,64}; +int rxd_count[4] = {127,85,85,63}; static inline int RXD_IS_UP2DT(RxD_t *rxdp) { @@ -113,14 +102,18 @@ static inline int RXD_IS_UP2DT(RxD_t *rxdp) #define LOW 2 static inline int rx_buffer_level(nic_t * sp, int rxb_size, int ring) { + int level = 0; mac_info_t *mac_control; mac_control = &sp->mac_control; - if (rxb_size <= rxd_count[sp->rxd_mode]) - return PANIC; - else if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16) - return LOW; - return 0; + if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16) { + level = LOW; + if (rxb_size <= rxd_count[sp->rxd_mode]) { + level = PANIC; + } + } + + return level; } /* Ethtool related variables and Macros. */ @@ -139,11 +132,7 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = { {"tmac_mcst_frms"}, {"tmac_bcst_frms"}, {"tmac_pause_ctrl_frms"}, - {"tmac_ttl_octets"}, - {"tmac_ucst_frms"}, - {"tmac_nucst_frms"}, {"tmac_any_err_frms"}, - {"tmac_ttl_less_fb_octets"}, {"tmac_vld_ip_octets"}, {"tmac_vld_ip"}, {"tmac_drop_ip"}, @@ -158,27 +147,13 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = { {"rmac_vld_mcst_frms"}, {"rmac_vld_bcst_frms"}, {"rmac_in_rng_len_err_frms"}, - {"rmac_out_rng_len_err_frms"}, {"rmac_long_frms"}, {"rmac_pause_ctrl_frms"}, - {"rmac_unsup_ctrl_frms"}, - {"rmac_ttl_octets"}, - {"rmac_accepted_ucst_frms"}, - {"rmac_accepted_nucst_frms"}, {"rmac_discarded_frms"}, - {"rmac_drop_events"}, - {"rmac_ttl_less_fb_octets"}, - {"rmac_ttl_frms"}, {"rmac_usized_frms"}, {"rmac_osized_frms"}, {"rmac_frag_frms"}, {"rmac_jabber_frms"}, - {"rmac_ttl_64_frms"}, - {"rmac_ttl_65_127_frms"}, - {"rmac_ttl_128_255_frms"}, - {"rmac_ttl_256_511_frms"}, - {"rmac_ttl_512_1023_frms"}, - {"rmac_ttl_1024_1518_frms"}, {"rmac_ip"}, {"rmac_ip_octets"}, {"rmac_hdr_err_ip"}, @@ -187,87 +162,12 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = { {"rmac_tcp"}, {"rmac_udp"}, {"rmac_err_drp_udp"}, - {"rmac_xgmii_err_sym"}, - {"rmac_frms_q0"}, - {"rmac_frms_q1"}, - {"rmac_frms_q2"}, - {"rmac_frms_q3"}, - {"rmac_frms_q4"}, - {"rmac_frms_q5"}, - {"rmac_frms_q6"}, - {"rmac_frms_q7"}, - {"rmac_full_q0"}, - {"rmac_full_q1"}, - {"rmac_full_q2"}, - {"rmac_full_q3"}, - {"rmac_full_q4"}, - {"rmac_full_q5"}, - {"rmac_full_q6"}, - {"rmac_full_q7"}, {"rmac_pause_cnt"}, - {"rmac_xgmii_data_err_cnt"}, - {"rmac_xgmii_ctrl_err_cnt"}, {"rmac_accepted_ip"}, {"rmac_err_tcp"}, - {"rd_req_cnt"}, - {"new_rd_req_cnt"}, - {"new_rd_req_rtry_cnt"}, - {"rd_rtry_cnt"}, - {"wr_rtry_rd_ack_cnt"}, - {"wr_req_cnt"}, - {"new_wr_req_cnt"}, - {"new_wr_req_rtry_cnt"}, - {"wr_rtry_cnt"}, - {"wr_disc_cnt"}, - {"rd_rtry_wr_ack_cnt"}, - {"txp_wr_cnt"}, - {"txd_rd_cnt"}, - {"txd_wr_cnt"}, - {"rxd_rd_cnt"}, - {"rxd_wr_cnt"}, - {"txf_rd_cnt"}, - {"rxf_wr_cnt"}, - {"rmac_ttl_1519_4095_frms"}, - {"rmac_ttl_4096_8191_frms"}, - {"rmac_ttl_8192_max_frms"}, - {"rmac_ttl_gt_max_frms"}, - {"rmac_osized_alt_frms"}, - {"rmac_jabber_alt_frms"}, - {"rmac_gt_max_alt_frms"}, - {"rmac_vlan_frms"}, - {"rmac_len_discard"}, - {"rmac_fcs_discard"}, - {"rmac_pf_discard"}, - {"rmac_da_discard"}, - {"rmac_red_discard"}, - {"rmac_rts_discard"}, - {"rmac_ingm_full_discard"}, - {"link_fault_cnt"}, {"\n DRIVER STATISTICS"}, {"single_bit_ecc_errs"}, {"double_bit_ecc_errs"}, - {"parity_err_cnt"}, - {"serious_err_cnt"}, - {"soft_reset_cnt"}, - {"fifo_full_cnt"}, - {"ring_full_cnt"}, - ("alarm_transceiver_temp_high"), - ("alarm_transceiver_temp_low"), - ("alarm_laser_bias_current_high"), - ("alarm_laser_bias_current_low"), - ("alarm_laser_output_power_high"), - ("alarm_laser_output_power_low"), - ("warn_transceiver_temp_high"), - ("warn_transceiver_temp_low"), - ("warn_laser_bias_current_high"), - ("warn_laser_bias_current_low"), - ("warn_laser_output_power_high"), - ("warn_laser_output_power_low"), - ("lro_aggregated_pkts"), - ("lro_flush_both_count"), - ("lro_out_of_sequence_pkts"), - ("lro_flush_due_to_max_pkts"), - ("lro_avg_aggr_pkts"), }; #define S2IO_STAT_LEN sizeof(ethtool_stats_keys)/ ETH_GSTRING_LEN @@ -311,8 +211,10 @@ static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid) * the XAUI. */ +#define SWITCH_SIGN 0xA5A5A5A5A5A5A5A5ULL #define END_SIGN 0x0 -static const u64 herc_act_dtx_cfg[] = { + +static u64 herc_act_dtx_cfg[] = { /* Set address */ 0x8000051536750000ULL, 0x80000515367500E0ULL, /* Write data */ @@ -333,19 +235,37 @@ static const u64 herc_act_dtx_cfg[] = { END_SIGN }; -static const u64 xena_dtx_cfg[] = { - /* Set address */ +static u64 xena_mdio_cfg[] = { + /* Reset PMA PLL */ + 0xC001010000000000ULL, 0xC0010100000000E0ULL, + 0xC0010100008000E4ULL, + /* Remove Reset from PMA PLL */ + 0xC001010000000000ULL, 0xC0010100000000E0ULL, + 0xC0010100000000E4ULL, + END_SIGN +}; + +static u64 xena_dtx_cfg[] = { 0x8000051500000000ULL, 0x80000515000000E0ULL, - /* Write data */ - 0x80000515D9350004ULL, 0x80000515D93500E4ULL, - /* Set address */ - 0x8001051500000000ULL, 0x80010515000000E0ULL, - /* Write data */ - 0x80010515001E0004ULL, 0x80010515001E00E4ULL, - /* Set address */ + 0x80000515D93500E4ULL, 0x8001051500000000ULL, + 0x80010515000000E0ULL, 0x80010515001E00E4ULL, 0x8002051500000000ULL, 0x80020515000000E0ULL, - /* Write data */ - 0x80020515F2100004ULL, 0x80020515F21000E4ULL, + 0x80020515F21000E4ULL, + /* Set PADLOOPBACKN */ + 0x8002051500000000ULL, 0x80020515000000E0ULL, + 0x80020515B20000E4ULL, 0x8003051500000000ULL, + 0x80030515000000E0ULL, 0x80030515B20000E4ULL, + 0x8004051500000000ULL, 0x80040515000000E0ULL, + 0x80040515B20000E4ULL, 0x8005051500000000ULL, + 0x80050515000000E0ULL, 0x80050515B20000E4ULL, + SWITCH_SIGN, + /* Remove PADLOOPBACKN */ + 0x8002051500000000ULL, 0x80020515000000E0ULL, + 0x80020515F20000E4ULL, 0x8003051500000000ULL, + 0x80030515000000E0ULL, 0x80030515F20000E4ULL, + 0x8004051500000000ULL, 0x80040515000000E0ULL, + 0x80040515F20000E4ULL, 0x8005051500000000ULL, + 0x80050515000000E0ULL, 0x80050515F20000E4ULL, END_SIGN }; @@ -353,7 +273,7 @@ static const u64 xena_dtx_cfg[] = { * Constants for Fixing the MacAddress problem seen mostly on * Alpha machines. */ -static const u64 fix_mac[] = { +static u64 fix_mac[] = { 0x0060000000000000ULL, 0x0060600000000000ULL, 0x0040600000000000ULL, 0x0000600000000000ULL, 0x0020600000000000ULL, 0x0060600000000000ULL, @@ -371,50 +291,32 @@ static const u64 fix_mac[] = { END_SIGN }; -MODULE_AUTHOR("Raghavendra Koushik "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - - /* Module Loadable parameters. */ -S2IO_PARM_INT(tx_fifo_num, 1); -S2IO_PARM_INT(rx_ring_num, 1); - - -S2IO_PARM_INT(rx_ring_mode, 1); -S2IO_PARM_INT(use_continuous_tx_intrs, 1); -S2IO_PARM_INT(rmac_pause_time, 0x100); -S2IO_PARM_INT(mc_pause_threshold_q0q3, 187); -S2IO_PARM_INT(mc_pause_threshold_q4q7, 187); -S2IO_PARM_INT(shared_splits, 0); -S2IO_PARM_INT(tmac_util_period, 5); -S2IO_PARM_INT(rmac_util_period, 5); -S2IO_PARM_INT(bimodal, 0); -S2IO_PARM_INT(l3l4hdr_size, 128); -/* Frequency of Rx desc syncs expressed as power of 2 */ -S2IO_PARM_INT(rxsync_frequency, 3); -/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */ -S2IO_PARM_INT(intr_type, 0); -/* Large receive offload feature */ -S2IO_PARM_INT(lro, 0); -/* Max pkts to be aggregated by LRO at one time. If not specified, - * aggregation happens until we hit max IP pkt size(64K) - */ -S2IO_PARM_INT(lro_max_pkts, 0xFFFF); -#ifndef CONFIG_S2IO_NAPI -S2IO_PARM_INT(indicate_max_pkts, 0); -#endif - +static unsigned int tx_fifo_num = 1; static unsigned int tx_fifo_len[MAX_TX_FIFOS] = - {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN}; + {[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)] = SMALL_BLK_CNT}; + {[0 ...(MAX_RX_RINGS - 1)] = 0 }; static unsigned int rts_frm_len[MAX_RX_RINGS] = {[0 ...(MAX_RX_RINGS - 1)] = 0 }; - -module_param_array(tx_fifo_len, uint, NULL, 0); -module_param_array(rx_ring_sz, uint, NULL, 0); -module_param_array(rts_frm_len, uint, NULL, 0); +static unsigned int rx_ring_mode = 1; +static unsigned int use_continuous_tx_intrs = 1; +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; +static unsigned int bimodal = 0; +static unsigned int l3l4hdr_size = 128; +#ifndef CONFIG_S2IO_NAPI +static unsigned int indicate_max_pkts; +#endif +/* Frequency of Rx desc syncs expressed as power of 2 */ +static unsigned int rxsync_frequency = 3; +/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */ +static unsigned int intr_type = 0; /* * S2IO device table. @@ -477,9 +379,10 @@ static int init_shared_mem(struct s2io_nic *nic) size += config->tx_cfg[i].fifo_len; } if (size > MAX_AVAILABLE_TXDS) { - DBG_PRINT(ERR_DBG, "s2io: Requested TxDs too high, "); + DBG_PRINT(ERR_DBG, "%s: Requested TxDs too high, ", + __FUNCTION__); DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size); - return -EINVAL; + return FAILURE; } lst_size = (sizeof(TxD_t) * config->max_txds); @@ -559,7 +462,6 @@ static int init_shared_mem(struct s2io_nic *nic) nic->ufo_in_band_v = kmalloc((sizeof(u64) * size), GFP_KERNEL); if (!nic->ufo_in_band_v) return -ENOMEM; - memset(nic->ufo_in_band_v, 0, size); /* Allocation and initialization of RXDs in Rings */ size = 0; @@ -632,6 +534,11 @@ static int init_shared_mem(struct s2io_nic *nic) rx_blocks->block_dma_addr + (rxd_size[nic->rxd_mode] * l); } + + mac_control->rings[i].rx_blocks[j].block_virt_addr = + tmp_v_addr; + mac_control->rings[i].rx_blocks[j].block_dma_addr = + tmp_p_addr; } /* Interlinking all Rx Blocks */ for (j = 0; j < blk_cnt; j++) { @@ -850,21 +757,7 @@ static int s2io_verify_pci_mode(nic_t *nic) return mode; } -#define NEC_VENID 0x1033 -#define NEC_DEVID 0x0125 -static int s2io_on_nec_bridge(struct pci_dev *s2io_pdev) -{ - struct pci_dev *tdev = NULL; - while ((tdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, tdev)) != NULL) { - if ((tdev->vendor == NEC_VENID) && (tdev->device == NEC_DEVID)){ - if (tdev->bus == s2io_pdev->bus->parent) - return 1; - } - } - return 0; -} -static int bus_speed[8] = {33, 133, 133, 200, 266, 133, 200, 266}; /** * s2io_print_pci_mode - */ @@ -881,14 +774,6 @@ static int s2io_print_pci_mode(nic_t *nic) if ( val64 & PCI_MODE_UNKNOWN_MODE) return -1; /* Unknown PCI mode */ - config->bus_speed = bus_speed[mode]; - - if (s2io_on_nec_bridge(nic->pdev)) { - DBG_PRINT(ERR_DBG, "%s: Device is on PCI-E bus\n", - nic->dev->name); - return mode; - } - if (val64 & PCI_MODE_32_BITS) { DBG_PRINT(ERR_DBG, "%s: Device is on 32 bit ", nic->dev->name); } else { @@ -898,27 +783,35 @@ static int s2io_print_pci_mode(nic_t *nic) switch(mode) { case PCI_MODE_PCI_33: DBG_PRINT(ERR_DBG, "33MHz PCI bus\n"); + config->bus_speed = 33; break; case PCI_MODE_PCI_66: DBG_PRINT(ERR_DBG, "66MHz PCI bus\n"); + config->bus_speed = 133; break; case PCI_MODE_PCIX_M1_66: DBG_PRINT(ERR_DBG, "66MHz PCIX(M1) bus\n"); + config->bus_speed = 133; /* Herc doubles the clock rate */ break; case PCI_MODE_PCIX_M1_100: DBG_PRINT(ERR_DBG, "100MHz PCIX(M1) bus\n"); + config->bus_speed = 200; break; case PCI_MODE_PCIX_M1_133: DBG_PRINT(ERR_DBG, "133MHz PCIX(M1) bus\n"); + config->bus_speed = 266; break; case PCI_MODE_PCIX_M2_66: DBG_PRINT(ERR_DBG, "133MHz PCIX(M2) bus\n"); + config->bus_speed = 133; break; case PCI_MODE_PCIX_M2_100: DBG_PRINT(ERR_DBG, "200MHz PCIX(M2) bus\n"); + config->bus_speed = 200; break; case PCI_MODE_PCIX_M2_133: DBG_PRINT(ERR_DBG, "266MHz PCIX(M2) bus\n"); + config->bus_speed = 266; break; default: return -1; /* Unsupported bus speed */ @@ -946,7 +839,7 @@ static int init_nic(struct s2io_nic *nic) int i, j; mac_info_t *mac_control; struct config_param *config; - int dtx_cnt = 0; + int mdio_cnt = 0, dtx_cnt = 0; unsigned long long mem_share; int mem_size; @@ -993,6 +886,20 @@ static int init_nic(struct s2io_nic *nic) val64 = dev->mtu; writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len); + /* + * 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 + * which will be defined in the array of configuration values + * (xena_dtx_cfg & xena_mdio_cfg) at appropriate places + * to switch writing from one regsiter to another. We continue + * writing these values until we encounter the 'END_SIGN' macro. + * For example, After making a series of 21 writes into + * dtx_control register the 'SWITCH_SIGN' appears and hence we + * start writing into mdio_control until we encounter END_SIGN. + */ if (nic->device_type & XFRAME_II_DEVICE) { while (herc_act_dtx_cfg[dtx_cnt] != END_SIGN) { SPECIAL_REG_WRITE(herc_act_dtx_cfg[dtx_cnt], @@ -1002,11 +909,35 @@ static int init_nic(struct s2io_nic *nic) dtx_cnt++; } } else { - while (xena_dtx_cfg[dtx_cnt] != END_SIGN) { - SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt], - &bar0->dtx_control, UF); - val64 = readq(&bar0->dtx_control); - dtx_cnt++; + while (1) { + dtx_cfg: + while (xena_dtx_cfg[dtx_cnt] != END_SIGN) { + if (xena_dtx_cfg[dtx_cnt] == SWITCH_SIGN) { + dtx_cnt++; + goto mdio_cfg; + } + SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt], + &bar0->dtx_control, UF); + val64 = readq(&bar0->dtx_control); + dtx_cnt++; + } + mdio_cfg: + while (xena_mdio_cfg[mdio_cnt] != END_SIGN) { + if (xena_mdio_cfg[mdio_cnt] == SWITCH_SIGN) { + mdio_cnt++; + goto dtx_cfg; + } + SPECIAL_REG_WRITE(xena_mdio_cfg[mdio_cnt], + &bar0->mdio_control, UF); + val64 = readq(&bar0->mdio_control); + mdio_cnt++; + } + if ((xena_dtx_cfg[dtx_cnt] == END_SIGN) && + (xena_mdio_cfg[mdio_cnt] == END_SIGN)) { + break; + } else { + goto dtx_cfg; + } } } @@ -1048,6 +979,11 @@ static int init_nic(struct s2io_nic *nic) } } + /* Enable Tx FIFO partition 0. */ + val64 = readq(&bar0->tx_fifo_partition_0); + val64 |= BIT(0); /* To enable the FIFO partition. */ + writeq(val64, &bar0->tx_fifo_partition_0); + /* * Disable 4 PCCs for Xena1, 2 and 3 as per H/W bug * SXE-008 TRANSMIT DMA ARBITRATION ISSUE. @@ -1226,11 +1162,6 @@ static int init_nic(struct s2io_nic *nic) break; } - /* Enable all configured Tx FIFO partitions */ - val64 = readq(&bar0->tx_fifo_partition_0); - val64 |= (TX_FIFO_PARTITION_EN); - writeq(val64, &bar0->tx_fifo_partition_0); - /* Filling the Rx round robin registers as per the * number of Rings and steering based on QoS. */ @@ -1545,19 +1476,6 @@ static int init_nic(struct s2io_nic *nic) writel((u32) (val64 >> 32), (add + 4)); val64 = readq(&bar0->mac_cfg); - /* Enable FCS stripping by adapter */ - add = &bar0->mac_cfg; - val64 = readq(&bar0->mac_cfg); - val64 |= MAC_CFG_RMAC_STRIP_FCS; - if (nic->device_type == XFRAME_II_DEVICE) - writeq(val64, &bar0->mac_cfg); - else { - writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); - writel((u32) (val64), add); - writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); - writel((u32) (val64 >> 32), (add + 4)); - } - /* * Set the time value to be inserted in the pause frame * generated by xena. @@ -1599,26 +1517,19 @@ static int init_nic(struct s2io_nic *nic) val64 |= PIC_CNTL_SHARED_SPLITS(shared_splits); writeq(val64, &bar0->pic_control); - if (nic->config.bus_speed == 266) { - writeq(TXREQTO_VAL(0x7f) | TXREQTO_EN, &bar0->txreqtimeout); - writeq(0x0, &bar0->read_retry_delay); - writeq(0x0, &bar0->write_retry_delay); - } - /* * Programming the Herc to split every write transaction * that does not start on an ADB to reduce disconnects. */ if (nic->device_type == XFRAME_II_DEVICE) { - val64 = EXT_REQ_EN | MISC_LINK_STABILITY_PRD(3); - writeq(val64, &bar0->misc_control); - val64 = readq(&bar0->pic_control2); - val64 &= ~(BIT(13)|BIT(14)|BIT(15)); - writeq(val64, &bar0->pic_control2); + val64 = WREQ_SPLIT_MASK_SET_MASK(255); + writeq(val64, &bar0->wreq_split_mask); } - if (strstr(nic->product_name, "CX4")) { - val64 = TMAC_AVG_IPG(0x17); - writeq(val64, &bar0->tmac_avg_ipg); + + /* Setting Link stability period to 64 ms */ + if (nic->device_type == XFRAME_II_DEVICE) { + val64 = MISC_LINK_STABILITY_PRD(3); + writeq(val64, &bar0->misc_control); } return SUCCESS; @@ -1663,7 +1574,7 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag) writeq(temp64, &bar0->general_int_mask); /* * If Hercules adapter enable GPIO otherwise - * disable all PCIX, Flash, MDIO, IIC and GPIO + * disabled all PCIX, Flash, MDIO, IIC and GPIO * interrupts for now. * TODO */ @@ -1989,6 +1900,7 @@ static int start_nic(struct s2io_nic *nic) XENA_dev_config_t __iomem *bar0 = nic->bar0; struct net_device *dev = nic->dev; register u64 val64 = 0; + u16 interruptible; u16 subid, i; mac_info_t *mac_control; struct config_param *config; @@ -2008,10 +1920,6 @@ static int start_nic(struct s2io_nic *nic) val64 |= PRC_CTRL_RC_ENABLED; else val64 |= PRC_CTRL_RC_ENABLED | PRC_CTRL_RING_MODE_3; - if (nic->device_type == XFRAME_II_DEVICE) - val64 |= PRC_CTRL_GROUP_READS; - val64 &= ~PRC_CTRL_RXD_BACKOFF_INTERVAL(0xFFFFFF); - val64 |= PRC_CTRL_RXD_BACKOFF_INTERVAL(0x1000); writeq(val64, &bar0->prc_ctrl_n[i]); } @@ -2059,6 +1967,16 @@ static int start_nic(struct s2io_nic *nic) return FAILURE; } + /* Enable select interrupts */ + if (nic->intr_type != INTA) + en_dis_able_nic_intrs(nic, ENA_ALL_INTRS, DISABLE_INTRS); + else { + interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR; + interruptible |= TX_PIC_INTR | RX_PIC_INTR; + interruptible |= TX_MAC_INTR | RX_MAC_INTR; + en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS); + } + /* * With some switches, link might be already up at this point. * Because of this weird behavior, when we enable laser, @@ -2072,13 +1990,6 @@ static int start_nic(struct s2io_nic *nic) val64 |= ADAPTER_EOI_TX_ON; writeq(val64, &bar0->adapter_control); - if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) { - /* - * Dont see link state interrupts initally on some switches, - * so directly scheduling the link state task here. - */ - schedule_work(&nic->set_link_task); - } /* SXE-002: Initialize link and activity LED */ subid = nic->pdev->subsystem_device; if (((subid & 0xFF) >= 0x07) && @@ -2090,6 +2001,12 @@ static int start_nic(struct s2io_nic *nic) 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); + return SUCCESS; } /** @@ -2132,7 +2049,7 @@ static struct sk_buff *s2io_txdl_getskb(fifo_info_t *fifo_data, TxD_t *txdlp, in frag->size, PCI_DMA_TODEVICE); } } - memset(txdlp,0, (sizeof(TxD_t) * fifo_data->max_txds)); + txdlp->Host_Control = 0; return(skb); } @@ -2189,7 +2106,7 @@ static void stop_nic(struct s2io_nic *nic) { XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64 = 0; - u16 interruptible; + u16 interruptible, i; mac_info_t *mac_control; struct config_param *config; @@ -2202,13 +2119,15 @@ static void stop_nic(struct s2io_nic *nic) interruptible |= TX_MAC_INTR | RX_MAC_INTR; en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS); - /* Clearing Adapter_En bit of ADAPTER_CONTROL Register */ - val64 = readq(&bar0->adapter_control); - val64 &= ~(ADAPTER_CNTL_EN); - writeq(val64, &bar0->adapter_control); + /* 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]); + } } -static int fill_rxd_3buf(nic_t *nic, RxD_t *rxdp, struct sk_buff *skb) +int fill_rxd_3buf(nic_t *nic, RxD_t *rxdp, struct sk_buff *skb) { struct net_device *dev = nic->dev; struct sk_buff *frag_list; @@ -2284,12 +2203,13 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) alloc_cnt = mac_control->rings[ring_no].pkt_cnt - atomic_read(&nic->rx_bufs_left[ring_no]); - block_no1 = mac_control->rings[ring_no].rx_curr_get_info.block_index; - off1 = mac_control->rings[ring_no].rx_curr_get_info.offset; while (alloc_tab < alloc_cnt) { block_no = mac_control->rings[ring_no].rx_curr_put_info. block_index; + block_no1 = mac_control->rings[ring_no].rx_curr_get_info. + block_index; off = mac_control->rings[ring_no].rx_curr_put_info.offset; + off1 = mac_control->rings[ring_no].rx_curr_get_info.offset; rxdp = mac_control->rings[ring_no]. rx_blocks[block_no].rxds[off].virt_addr; @@ -2359,9 +2279,9 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) memset(rxdp, 0, sizeof(RxD1_t)); skb_reserve(skb, NET_IP_ALIGN); ((RxD1_t*)rxdp)->Buffer0_ptr = pci_map_single - (nic->pdev, skb->data, size - NET_IP_ALIGN, - PCI_DMA_FROMDEVICE); - rxdp->Control_2 = SET_BUFFER0_SIZE_1(size - NET_IP_ALIGN); + (nic->pdev, skb->data, size, PCI_DMA_FROMDEVICE); + rxdp->Control_2 &= (~MASK_BUFFER0_SIZE_1); + rxdp->Control_2 |= SET_BUFFER0_SIZE_1(size); } else if (nic->rxd_mode >= RXD_MODE_3A) { /* @@ -2384,14 +2304,9 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) skb->data = (void *) (unsigned long)tmp; skb->tail = (void *) (unsigned long)tmp; - if (!(((RxD3_t*)rxdp)->Buffer0_ptr)) - ((RxD3_t*)rxdp)->Buffer0_ptr = - pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN, + ((RxD3_t*)rxdp)->Buffer0_ptr = + pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN, PCI_DMA_FROMDEVICE); - else - pci_dma_sync_single_for_device(nic->pdev, - (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr, - BUF0_LEN, PCI_DMA_FROMDEVICE); rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); if (nic->rxd_mode == RXD_MODE_3B) { /* Two buffer mode */ @@ -2404,13 +2319,10 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) (nic->pdev, skb->data, dev->mtu + 4, PCI_DMA_FROMDEVICE); - /* Buffer-1 will be dummy buffer. Not used */ - if (!(((RxD3_t*)rxdp)->Buffer1_ptr)) { - ((RxD3_t*)rxdp)->Buffer1_ptr = - pci_map_single(nic->pdev, - ba->ba_1, BUF1_LEN, - PCI_DMA_FROMDEVICE); - } + /* Buffer-1 will be dummy buffer not used */ + ((RxD3_t*)rxdp)->Buffer1_ptr = + pci_map_single(nic->pdev, ba->ba_1, BUF1_LEN, + PCI_DMA_FROMDEVICE); rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1); rxdp->Control_2 |= SET_BUFFER2_SIZE_3 (dev->mtu + 4); @@ -2576,7 +2488,7 @@ static int s2io_poll(struct net_device *dev, int *budget) mac_info_t *mac_control; struct config_param *config; XENA_dev_config_t __iomem *bar0 = nic->bar0; - u64 val64 = 0xFFFFFFFFFFFFFFFFULL; + u64 val64; int i; atomic_inc(&nic->isr_cnt); @@ -2588,8 +2500,8 @@ static int s2io_poll(struct net_device *dev, int *budget) nic->pkts_to_process = dev->quota; org_pkts_to_process = nic->pkts_to_process; + val64 = readq(&bar0->rx_traffic_int); writeq(val64, &bar0->rx_traffic_int); - val64 = readl(&bar0->rx_traffic_int); for (i = 0; i < config->rx_ring_num; i++) { rx_intr_handler(&mac_control->rings[i]); @@ -2614,8 +2526,7 @@ static int s2io_poll(struct net_device *dev, int *budget) } } /* Re enable the Rx interrupts. */ - writeq(0x0, &bar0->rx_traffic_mask); - val64 = readl(&bar0->rx_traffic_mask); + en_dis_able_nic_intrs(nic, RX_TRAFFIC_INTR, ENABLE_INTRS); atomic_dec(&nic->isr_cnt); return 0; @@ -2635,58 +2546,6 @@ no_rx: } #endif -#ifdef CONFIG_NET_POLL_CONTROLLER -/** - * s2io_netpoll - netpoll event handler entry point - * @dev : pointer to the device structure. - * Description: - * This function will be called by upper layer to check for events on the - * interface in situations where interrupts are disabled. It is used for - * specific in-kernel networking tasks, such as remote consoles and kernel - * debugging over the network (example netdump in RedHat). - */ -static void s2io_netpoll(struct net_device *dev) -{ - nic_t *nic = dev->priv; - mac_info_t *mac_control; - struct config_param *config; - XENA_dev_config_t __iomem *bar0 = nic->bar0; - u64 val64 = 0xFFFFFFFFFFFFFFFFULL; - int i; - - disable_irq(dev->irq); - - atomic_inc(&nic->isr_cnt); - mac_control = &nic->mac_control; - config = &nic->config; - - writeq(val64, &bar0->rx_traffic_int); - writeq(val64, &bar0->tx_traffic_int); - - /* we need to free up the transmitted skbufs or else netpoll will - * run out of skbs and will fail and eventually netpoll application such - * as netdump will fail. - */ - for (i = 0; i < config->tx_fifo_num; i++) - tx_intr_handler(&mac_control->fifos[i]); - - /* check for received packet and indicate up to network */ - for (i = 0; i < config->rx_ring_num; i++) - rx_intr_handler(&mac_control->rings[i]); - - 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 Netpoll!!\n"); - break; - } - } - atomic_dec(&nic->isr_cnt); - enable_irq(dev->irq); - return; -} -#endif - /** * rx_intr_handler - Rx interrupt handler * @nic: device private variable. @@ -2710,8 +2569,6 @@ static void rx_intr_handler(ring_info_t *ring_data) #ifndef CONFIG_S2IO_NAPI int pkt_cnt = 0; #endif - int i; - spin_lock(&nic->rx_lock); if (atomic_read(&nic->card_state) == CARD_DOWN) { DBG_PRINT(INTR_DBG, "%s: %s going down for reset\n", @@ -2737,7 +2594,7 @@ static void rx_intr_handler(ring_info_t *ring_data) /* If your are next to put index then it's FIFO full condition */ if ((get_block == put_block) && (get_info.offset + 1) == put_info.offset) { - DBG_PRINT(INTR_DBG, "%s: Ring Full\n",dev->name); + DBG_PRINT(ERR_DBG, "%s: Ring Full\n",dev->name); break; } skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control); @@ -2757,15 +2614,18 @@ static void rx_intr_handler(ring_info_t *ring_data) HEADER_SNAP_SIZE, PCI_DMA_FROMDEVICE); } else if (nic->rxd_mode == RXD_MODE_3B) { - pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) + pci_unmap_single(nic->pdev, (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); + pci_unmap_single(nic->pdev, (dma_addr_t) + ((RxD3_t*)rxdp)->Buffer1_ptr, + BUF1_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(nic->pdev, (dma_addr_t) ((RxD3_t*)rxdp)->Buffer2_ptr, dev->mtu + 4, PCI_DMA_FROMDEVICE); } else { - pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) + pci_unmap_single(nic->pdev, (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(nic->pdev, (dma_addr_t) @@ -2776,7 +2636,6 @@ static void rx_intr_handler(ring_info_t *ring_data) ((RxD3_t*)rxdp)->Buffer2_ptr, dev->mtu, PCI_DMA_FROMDEVICE); } - prefetch(skb->data); rx_osm_handler(ring_data, rxdp); get_info.offset++; ring_data->rx_curr_get_info.offset = get_info.offset; @@ -2802,18 +2661,6 @@ static void rx_intr_handler(ring_info_t *ring_data) break; #endif } - if (nic->lro) { - /* Clear all LRO sessions before exiting */ - for (i=0; ilro0_n[i]; - if (lro->in_use) { - update_L3L4_header(nic, lro); - queue_rx_frame(lro->parent); - clear_lro_session(lro); - } - } - } - spin_unlock(&nic->rx_lock); } @@ -2848,10 +2695,6 @@ static void tx_intr_handler(fifo_info_t *fifo_data) if (txdlp->Control_1 & TXD_T_CODE) { unsigned long long err; err = txdlp->Control_1 & TXD_T_CODE; - if (err & 0x1) { - nic->mac_control.stats_info->sw_stat. - parity_err_cnt++; - } if ((err >> 48) == 0xA) { DBG_PRINT(TX_DBG, "TxD returned due \ to loss of link\n"); @@ -2875,8 +2718,7 @@ to loss of link\n"); dev_kfree_skb_irq(skb); get_info.offset++; - if (get_info.offset == get_info.fifo_len + 1) - get_info.offset = 0; + get_info.offset %= get_info.fifo_len + 1; txdlp = (TxD_t *) fifo_data->list_info [get_info.offset].list_virt_addr; fifo_data->tx_curr_get_info.offset = @@ -2889,256 +2731,6 @@ to loss of link\n"); spin_unlock(&nic->tx_lock); } -/** - * s2io_mdio_write - Function to write in to MDIO registers - * @mmd_type : MMD type value (PMA/PMD/WIS/PCS/PHYXS) - * @addr : address value - * @value : data value - * @dev : pointer to net_device structure - * Description: - * This function is used to write values to the MDIO registers - * NONE - */ -static void s2io_mdio_write(u32 mmd_type, u64 addr, u16 value, struct net_device *dev) -{ - u64 val64 = 0x0; - nic_t *sp = dev->priv; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0; - - //address transaction - val64 = val64 | MDIO_MMD_INDX_ADDR(addr) - | MDIO_MMD_DEV_ADDR(mmd_type) - | MDIO_MMS_PRT_ADDR(0x0); - writeq(val64, &bar0->mdio_control); - val64 = val64 | MDIO_CTRL_START_TRANS(0xE); - writeq(val64, &bar0->mdio_control); - udelay(100); - - //Data transaction - val64 = 0x0; - val64 = val64 | MDIO_MMD_INDX_ADDR(addr) - | MDIO_MMD_DEV_ADDR(mmd_type) - | MDIO_MMS_PRT_ADDR(0x0) - | MDIO_MDIO_DATA(value) - | MDIO_OP(MDIO_OP_WRITE_TRANS); - writeq(val64, &bar0->mdio_control); - val64 = val64 | MDIO_CTRL_START_TRANS(0xE); - writeq(val64, &bar0->mdio_control); - udelay(100); - - val64 = 0x0; - val64 = val64 | MDIO_MMD_INDX_ADDR(addr) - | MDIO_MMD_DEV_ADDR(mmd_type) - | MDIO_MMS_PRT_ADDR(0x0) - | MDIO_OP(MDIO_OP_READ_TRANS); - writeq(val64, &bar0->mdio_control); - val64 = val64 | MDIO_CTRL_START_TRANS(0xE); - writeq(val64, &bar0->mdio_control); - udelay(100); - -} - -/** - * s2io_mdio_read - Function to write in to MDIO registers - * @mmd_type : MMD type value (PMA/PMD/WIS/PCS/PHYXS) - * @addr : address value - * @dev : pointer to net_device structure - * Description: - * This function is used to read values to the MDIO registers - * NONE - */ -static u64 s2io_mdio_read(u32 mmd_type, u64 addr, struct net_device *dev) -{ - u64 val64 = 0x0; - u64 rval64 = 0x0; - nic_t *sp = dev->priv; - XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0; - - /* address transaction */ - val64 = val64 | MDIO_MMD_INDX_ADDR(addr) - | MDIO_MMD_DEV_ADDR(mmd_type) - | MDIO_MMS_PRT_ADDR(0x0); - writeq(val64, &bar0->mdio_control); - val64 = val64 | MDIO_CTRL_START_TRANS(0xE); - writeq(val64, &bar0->mdio_control); - udelay(100); - - /* Data transaction */ - val64 = 0x0; - val64 = val64 | MDIO_MMD_INDX_ADDR(addr) - | MDIO_MMD_DEV_ADDR(mmd_type) - | MDIO_MMS_PRT_ADDR(0x0) - | MDIO_OP(MDIO_OP_READ_TRANS); - writeq(val64, &bar0->mdio_control); - val64 = val64 | MDIO_CTRL_START_TRANS(0xE); - writeq(val64, &bar0->mdio_control); - udelay(100); - - /* Read the value from regs */ - rval64 = readq(&bar0->mdio_control); - rval64 = rval64 & 0xFFFF0000; - rval64 = rval64 >> 16; - return rval64; -} -/** - * s2io_chk_xpak_counter - Function to check the status of the xpak counters - * @counter : couter value to be updated - * @flag : flag to indicate the status - * @type : counter type - * Description: - * This function is to check the status of the xpak counters value - * NONE - */ - -static void s2io_chk_xpak_counter(u64 *counter, u64 * regs_stat, u32 index, u16 flag, u16 type) -{ - u64 mask = 0x3; - u64 val64; - int i; - for(i = 0; i 0) - { - *counter = *counter + 1; - val64 = *regs_stat & mask; - val64 = val64 >> (index * 0x2); - val64 = val64 + 1; - if(val64 == 3) - { - switch(type) - { - case 1: - DBG_PRINT(ERR_DBG, "Take Xframe NIC out of " - "service. Excessive temperatures may " - "result in premature transceiver " - "failure \n"); - break; - case 2: - DBG_PRINT(ERR_DBG, "Take Xframe NIC out of " - "service Excessive bias currents may " - "indicate imminent laser diode " - "failure \n"); - break; - case 3: - DBG_PRINT(ERR_DBG, "Take Xframe NIC out of " - "service Excessive laser output " - "power may saturate far-end " - "receiver\n"); - break; - default: - DBG_PRINT(ERR_DBG, "Incorrect XPAK Alarm " - "type \n"); - } - val64 = 0x0; - } - val64 = val64 << (index * 0x2); - *regs_stat = (*regs_stat & (~mask)) | (val64); - - } else { - *regs_stat = *regs_stat & (~mask); - } -} - -/** - * s2io_updt_xpak_counter - Function to update the xpak counters - * @dev : pointer to net_device struct - * Description: - * This function is to upate the status of the xpak counters value - * NONE - */ -static void s2io_updt_xpak_counter(struct net_device *dev) -{ - u16 flag = 0x0; - u16 type = 0x0; - u16 val16 = 0x0; - u64 val64 = 0x0; - u64 addr = 0x0; - - nic_t *sp = dev->priv; - StatInfo_t *stat_info = sp->mac_control.stats_info; - - /* Check the communication with the MDIO slave */ - addr = 0x0000; - val64 = 0x0; - val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); - if((val64 == 0xFFFF) || (val64 == 0x0000)) - { - DBG_PRINT(ERR_DBG, "ERR: MDIO slave access failed - " - "Returned %llx\n", (unsigned long long)val64); - return; - } - - /* Check for the expecte value of 2040 at PMA address 0x0000 */ - if(val64 != 0x2040) - { - DBG_PRINT(ERR_DBG, "Incorrect value at PMA address 0x0000 - "); - DBG_PRINT(ERR_DBG, "Returned: %llx- Expected: 0x2040\n", - (unsigned long long)val64); - return; - } - - /* Loading the DOM register to MDIO register */ - addr = 0xA100; - s2io_mdio_write(MDIO_MMD_PMA_DEV_ADDR, addr, val16, dev); - val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); - - /* Reading the Alarm flags */ - addr = 0xA070; - val64 = 0x0; - val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); - - flag = CHECKBIT(val64, 0x7); - type = 1; - s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_transceiver_temp_high, - &stat_info->xpak_stat.xpak_regs_stat, - 0x0, flag, type); - - if(CHECKBIT(val64, 0x6)) - stat_info->xpak_stat.alarm_transceiver_temp_low++; - - flag = CHECKBIT(val64, 0x3); - type = 2; - s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_bias_current_high, - &stat_info->xpak_stat.xpak_regs_stat, - 0x2, flag, type); - - if(CHECKBIT(val64, 0x2)) - stat_info->xpak_stat.alarm_laser_bias_current_low++; - - flag = CHECKBIT(val64, 0x1); - type = 3; - s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_output_power_high, - &stat_info->xpak_stat.xpak_regs_stat, - 0x4, flag, type); - - if(CHECKBIT(val64, 0x0)) - stat_info->xpak_stat.alarm_laser_output_power_low++; - - /* Reading the Warning flags */ - addr = 0xA074; - val64 = 0x0; - val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev); - - if(CHECKBIT(val64, 0x7)) - stat_info->xpak_stat.warn_transceiver_temp_high++; - - if(CHECKBIT(val64, 0x6)) - stat_info->xpak_stat.warn_transceiver_temp_low++; - - if(CHECKBIT(val64, 0x3)) - stat_info->xpak_stat.warn_laser_bias_current_high++; - - if(CHECKBIT(val64, 0x2)) - stat_info->xpak_stat.warn_laser_bias_current_low++; - - if(CHECKBIT(val64, 0x1)) - stat_info->xpak_stat.warn_laser_output_power_high++; - - if(CHECKBIT(val64, 0x0)) - stat_info->xpak_stat.warn_laser_output_power_low++; -} - /** * alarm_intr_handler - Alarm Interrrupt handler * @nic: device private variable @@ -3156,18 +2748,6 @@ static void alarm_intr_handler(struct s2io_nic *nic) struct net_device *dev = (struct net_device *) nic->dev; XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64 = 0, err_reg = 0; - u64 cnt; - int i; - nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0; - /* Handling the XPAK counters update */ - if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) { - /* waiting for an hour */ - nic->mac_control.stats_info->xpak_stat.xpak_timer_count++; - } else { - s2io_updt_xpak_counter(dev); - /* reset the count to zero */ - nic->mac_control.stats_info->xpak_stat.xpak_timer_count = 0; - } /* Handling link status change error Intr */ if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) { @@ -3194,8 +2774,6 @@ static void alarm_intr_handler(struct s2io_nic *nic) MC_ERR_REG_MIRI_ECC_DB_ERR_1)) { netif_stop_queue(dev); schedule_work(&nic->rst_timer_task); - nic->mac_control.stats_info->sw_stat. - soft_reset_cnt++; } } } else { @@ -3207,13 +2785,11 @@ static void alarm_intr_handler(struct s2io_nic *nic) /* In case of a serious error, the device will be Reset. */ val64 = readq(&bar0->serr_source); if (val64 & SERR_SOURCE_ANY) { - nic->mac_control.stats_info->sw_stat.serious_err_cnt++; DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name); DBG_PRINT(ERR_DBG, "serious error %llx!!\n", (unsigned long long)val64); netif_stop_queue(dev); schedule_work(&nic->rst_timer_task); - nic->mac_control.stats_info->sw_stat.soft_reset_cnt++; } /* @@ -3231,35 +2807,6 @@ static void alarm_intr_handler(struct s2io_nic *nic) ac = readq(&bar0->adapter_control); schedule_work(&nic->set_link_task); } - /* Check for data parity error */ - val64 = readq(&bar0->pic_int_status); - if (val64 & PIC_INT_GPIO) { - val64 = readq(&bar0->gpio_int_reg); - if (val64 & GPIO_INT_REG_DP_ERR_INT) { - nic->mac_control.stats_info->sw_stat.parity_err_cnt++; - schedule_work(&nic->rst_timer_task); - nic->mac_control.stats_info->sw_stat.soft_reset_cnt++; - } - } - - /* Check for ring full counter */ - if (nic->device_type & XFRAME_II_DEVICE) { - val64 = readq(&bar0->ring_bump_counter1); - for (i=0; i<4; i++) { - cnt = ( val64 & vBIT(0xFFFF,(i*16),16)); - cnt >>= 64 - ((i+1)*16); - nic->mac_control.stats_info->sw_stat.ring_full_cnt - += cnt; - } - - val64 = readq(&bar0->ring_bump_counter2); - for (i=0; i<4; i++) { - cnt = ( val64 & vBIT(0xFFFF,(i*16),16)); - cnt >>= 64 - ((i+1)*16); - nic->mac_control.stats_info->sw_stat.ring_full_cnt - += cnt; - } - } /* Other type of interrupts are not being handled now, TODO */ } @@ -3275,26 +2822,23 @@ static void alarm_intr_handler(struct s2io_nic *nic) * SUCCESS on success and FAILURE on failure. */ -static int wait_for_cmd_complete(void *addr, u64 busy_bit) +static int wait_for_cmd_complete(nic_t * sp) { + XENA_dev_config_t __iomem *bar0 = sp->bar0; int ret = FAILURE, cnt = 0; u64 val64; while (TRUE) { - val64 = readq(addr); - if (!(val64 & busy_bit)) { + val64 = readq(&bar0->rmac_addr_cmd_mem); + if (!(val64 & RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) { ret = SUCCESS; break; } - - if(in_interrupt()) - mdelay(50); - else - msleep(50); - + msleep(50); if (cnt++ > 10) break; } + return ret; } @@ -3308,7 +2852,7 @@ static int wait_for_cmd_complete(void *addr, u64 busy_bit) * void. */ -static void s2io_reset(nic_t * sp) +void s2io_reset(nic_t * sp) { XENA_dev_config_t __iomem *bar0 = sp->bar0; u64 val64; @@ -3333,9 +2877,6 @@ static void s2io_reset(nic_t * sp) * PCI write to sw_reset register is done by this time. */ msleep(250); - if (strstr(sp->product_name, "CX4")) { - msleep(750); - } /* Restore the PCI state saved during initialization. */ pci_restore_state(sp->pdev); @@ -3353,7 +2894,7 @@ static void s2io_reset(nic_t * sp) /* Clear certain PCI/PCI-X fields after reset */ if (sp->device_type == XFRAME_II_DEVICE) { - /* Clear "detected parity error" bit */ + /* Clear parity err detect bit */ pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000); /* Clearing PCIX Ecc status register */ @@ -3399,7 +2940,7 @@ static void s2io_reset(nic_t * sp) * SUCCESS on success and FAILURE on failure. */ -static int s2io_set_swapper(nic_t * sp) +int s2io_set_swapper(nic_t * sp) { struct net_device *dev = sp->dev; XENA_dev_config_t __iomem *bar0 = sp->bar0; @@ -3548,13 +3089,13 @@ static int wait_for_msix_trans(nic_t *nic, int i) return ret; } -static void restore_xmsi_data(nic_t *nic) +void restore_xmsi_data(nic_t *nic) { XENA_dev_config_t __iomem *bar0 = nic->bar0; u64 val64; int i; - for (i=0; i < MAX_REQUESTED_MSI_X; i++) { + for (i=0; i< MAX_REQUESTED_MSI_X; i++) { writeq(nic->msix_info[i].addr, &bar0->xmsi_address); writeq(nic->msix_info[i].data, &bar0->xmsi_data); val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6)); @@ -3573,7 +3114,7 @@ static void store_xmsi_data(nic_t *nic) int i; /* Store and display */ - for (i=0; i < MAX_REQUESTED_MSI_X; i++) { + for (i=0; i< MAX_REQUESTED_MSI_X; i++) { val64 = (BIT(15) | vBIT(i, 26, 6)); writeq(val64, &bar0->xmsi_access); if (wait_for_msix_trans(nic, i)) { @@ -3639,7 +3180,7 @@ int s2io_enable_msi(nic_t *nic) return 0; } -static int s2io_enable_msi_x(nic_t *nic) +int s2io_enable_msi_x(nic_t *nic) { XENA_dev_config_t __iomem *bar0 = nic->bar0; u64 tx_mat, rx_mat; @@ -3701,24 +3242,15 @@ static int s2io_enable_msi_x(nic_t *nic) writeq(tx_mat, &bar0->tx_mat0_n[7]); } - nic->avail_msix_vectors = 0; ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X); - /* We fail init if error or we get less vectors than min required */ - if (ret >= (nic->config.tx_fifo_num + nic->config.rx_ring_num + 1)) { - nic->avail_msix_vectors = ret; - ret = pci_enable_msix(nic->pdev, nic->entries, ret); - } if (ret) { DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name); kfree(nic->entries); kfree(nic->s2io_entries); nic->entries = NULL; nic->s2io_entries = NULL; - nic->avail_msix_vectors = 0; return -ENOMEM; } - if (!nic->avail_msix_vectors) - nic->avail_msix_vectors = MAX_REQUESTED_MSI_X; /* * To enable MSI-X, MSI also needs to be enabled, due to a bug @@ -3751,6 +3283,8 @@ static int s2io_open(struct net_device *dev) { nic_t *sp = dev->priv; int err = 0; + int i; + u16 msi_control; /* Temp variable */ /* * Make sure you have link off by default every time @@ -3760,23 +3294,98 @@ static int s2io_open(struct net_device *dev) sp->last_link_state = 0; /* Initialize H/W and enable interrupts */ - err = s2io_card_up(sp); - if (err) { + if (s2io_card_up(sp)) { DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n", dev->name); + err = -ENODEV; goto hw_init_failed; } - if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) { + /* Store the values of the MSIX table in the nic_t structure */ + store_xmsi_data(sp); + + /* After proper initialization of H/W, register ISR */ + if (sp->intr_type == MSI) { + err = request_irq((int) sp->pdev->irq, s2io_msi_handle, + SA_SHIRQ, sp->name, dev); + if (err) { + DBG_PRINT(ERR_DBG, "%s: MSI registration \ +failed\n", dev->name); + goto isr_registration_failed; + } + } + if (sp->intr_type == MSI_X) { + for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) { + if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) { + sprintf(sp->desc1, "%s:MSI-X-%d-TX", + dev->name, i); + err = request_irq(sp->entries[i].vector, + s2io_msix_fifo_handle, 0, sp->desc1, + sp->s2io_entries[i].arg); + DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc1, + (unsigned long long)sp->msix_info[i].addr); + } else { + sprintf(sp->desc2, "%s:MSI-X-%d-RX", + dev->name, i); + err = request_irq(sp->entries[i].vector, + s2io_msix_ring_handle, 0, sp->desc2, + sp->s2io_entries[i].arg); + DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc2, + (unsigned long long)sp->msix_info[i].addr); + } + if (err) { + DBG_PRINT(ERR_DBG, "%s: MSI-X-%d registration \ +failed\n", dev->name, i); + DBG_PRINT(ERR_DBG, "Returned: %d\n", err); + goto isr_registration_failed; + } + sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS; + } + } + if (sp->intr_type == INTA) { + err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ, + sp->name, dev); + if (err) { + DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n", + dev->name); + goto isr_registration_failed; + } + } + + if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) { DBG_PRINT(ERR_DBG, "Set Mac Address Failed\n"); - s2io_card_down(sp); err = -ENODEV; - goto hw_init_failed; + goto setting_mac_address_failed; } netif_start_queue(dev); return 0; +setting_mac_address_failed: + if (sp->intr_type != MSI_X) + free_irq(sp->pdev->irq, dev); +isr_registration_failed: + del_timer_sync(&sp->alarm_timer); + if (sp->intr_type == MSI_X) { + if (sp->device_type == XFRAME_II_DEVICE) { + for (i=1; (sp->s2io_entries[i].in_use == + MSIX_REGISTERED_SUCCESS); i++) { + int vector = sp->entries[i].vector; + void *arg = sp->s2io_entries[i].arg; + + free_irq(vector, arg); + } + pci_disable_msix(sp->pdev); + + /* Temp */ + pci_read_config_word(sp->pdev, 0x42, &msi_control); + msi_control &= 0xFFFE; /* Disable MSI */ + pci_write_config_word(sp->pdev, 0x42, msi_control); + } + } + else if (sp->intr_type == MSI) + pci_disable_msi(sp->pdev); + s2io_reset(sp); hw_init_failed: if (sp->intr_type == MSI_X) { if (sp->entries) @@ -3803,12 +3412,35 @@ hw_init_failed: static int s2io_close(struct net_device *dev) { nic_t *sp = dev->priv; + int i; + u16 msi_control; flush_scheduled_work(); netif_stop_queue(dev); /* Reset card, kill tasklet and free Tx and Rx buffers. */ s2io_card_down(sp); + if (sp->intr_type == MSI_X) { + if (sp->device_type == XFRAME_II_DEVICE) { + for (i=1; (sp->s2io_entries[i].in_use == + MSIX_REGISTERED_SUCCESS); i++) { + int vector = sp->entries[i].vector; + void *arg = sp->s2io_entries[i].arg; + + free_irq(vector, arg); + } + pci_read_config_word(sp->pdev, 0x42, &msi_control); + msi_control &= 0xFFFE; /* Disable MSI */ + pci_write_config_word(sp->pdev, 0x42, msi_control); + + pci_disable_msix(sp->pdev); + } + } + else { + free_irq(sp->pdev->irq, dev); + if (sp->intr_type == MSI) + pci_disable_msi(sp->pdev); + } sp->device_close_flag = TRUE; /* Device is shut down. */ return 0; } @@ -3834,11 +3466,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) TxD_t *txdp; TxFIFO_element_t __iomem *tx_fifo; unsigned long flags; +#ifdef NETIF_F_TSO + int mss; +#endif u16 vlan_tag = 0; int vlan_priority = 0; mac_info_t *mac_control; struct config_param *config; - int offload_type; mac_control = &sp->mac_control; config = &sp->config; @@ -3869,8 +3503,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) queue_len = mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1; /* Avoid "put" pointer going beyond "get" pointer */ - if (txdp->Host_Control || - ((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) { + if (txdp->Host_Control || (((put_off + 1) % queue_len) == get_off)) { DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n"); netif_stop_queue(dev); dev_kfree_skb(skb); @@ -3886,11 +3519,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } - offload_type = s2io_offload_type(skb); + txdp->Control_1 = 0; + txdp->Control_2 = 0; #ifdef NETIF_F_TSO - if (offload_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { + mss = skb_shinfo(skb)->tso_size; + if (mss) { txdp->Control_1 |= TXD_TCP_LSO_EN; - txdp->Control_1 |= TXD_TCP_LSO_MSS(s2io_tcp_mss(skb)); + txdp->Control_1 |= TXD_TCP_LSO_MSS(mss); } #endif if (skb->ip_summed == CHECKSUM_HW) { @@ -3908,10 +3543,10 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) } frg_len = skb->len - skb->data_len; - if (offload_type == SKB_GSO_UDP) { + if (skb_shinfo(skb)->ufo_size) { int ufo_size; - ufo_size = s2io_udp_mss(skb); + ufo_size = skb_shinfo(skb)->ufo_size; ufo_size &= ~7; txdp->Control_1 |= TXD_UFO_EN; txdp->Control_1 |= TXD_UFO_MSS(ufo_size); @@ -3928,13 +3563,16 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) sp->ufo_in_band_v, sizeof(u64), PCI_DMA_TODEVICE); txdp++; + txdp->Control_1 = 0; + txdp->Control_2 = 0; } txdp->Buffer_Pointer = pci_map_single (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE); txdp->Host_Control = (unsigned long) skb; txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len); - if (offload_type == SKB_GSO_UDP) + + if (skb_shinfo(skb)->ufo_size) txdp->Control_1 |= TXD_UFO_EN; frg_cnt = skb_shinfo(skb)->nr_frags; @@ -3949,12 +3587,12 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) (sp->pdev, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE); txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size); - if (offload_type == SKB_GSO_UDP) + if (skb_shinfo(skb)->ufo_size) txdp->Control_1 |= TXD_UFO_EN; } txdp->Control_1 |= TXD_GATHER_CODE_LAST; - if (offload_type == SKB_GSO_UDP) + if (skb_shinfo(skb)->ufo_size) frg_cnt++; /* as Txd0 was used for inband header */ tx_fifo = mac_control->tx_FIFO_start[queue]; @@ -3963,21 +3601,23 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST | TX_FIFO_LAST_LIST); - if (offload_type) - val64 |= TX_FIFO_SPECIAL_FUNC; +#ifdef NETIF_F_TSO + if (mss) + val64 |= TX_FIFO_SPECIAL_FUNC; +#endif + if (skb_shinfo(skb)->ufo_size) + val64 |= TX_FIFO_SPECIAL_FUNC; writeq(val64, &tx_fifo->List_Control); mmiowb(); put_off++; - if (put_off == mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1) - put_off = 0; + put_off %= mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1; mac_control->fifos[queue].tx_curr_put_info.offset = put_off; /* Avoid "put" pointer going beyond "get" pointer */ - if (((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) { - sp->mac_control.stats_info->sw_stat.fifo_full_cnt++; + 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); @@ -3999,41 +3639,13 @@ s2io_alarm_handle(unsigned long data) mod_timer(&sp->alarm_timer, jiffies + HZ / 2); } -static int s2io_chk_rx_buffers(nic_t *sp, int rng_n) -{ - int rxb_size, level; - - if (!sp->lro) { - rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]); - level = rx_buffer_level(sp, rxb_size, rng_n); - - if ((level == PANIC) && (!TASKLET_IN_USE)) { - int ret; - DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__); - DBG_PRINT(INTR_DBG, "PANIC levels\n"); - if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "Out of memory in %s", - __FUNCTION__); - clear_bit(0, (&sp->tasklet_status)); - return -1; - } - clear_bit(0, (&sp->tasklet_status)); - } else if (level == LOW) - tasklet_schedule(&sp->task); - - } else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "%s:Out of memory", sp->dev->name); - DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); - } - return 0; -} - static irqreturn_t s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; nic_t *sp = dev->priv; int i; + int ret; mac_info_t *mac_control; struct config_param *config; @@ -4055,8 +3667,26 @@ s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs) * reallocate the buffers from the interrupt handler itself, * else schedule a tasklet to reallocate the buffers. */ - for (i = 0; i < config->rx_ring_num; i++) - s2io_chk_rx_buffers(sp, i); + 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)) { + 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"); + clear_bit(0, (&sp->tasklet_status)); + atomic_dec(&sp->isr_cnt); + return IRQ_HANDLED; + } + clear_bit(0, (&sp->tasklet_status)); + } else if (level == LOW) { + tasklet_schedule(&sp->task); + } + } atomic_dec(&sp->isr_cnt); return IRQ_HANDLED; @@ -4067,13 +3697,31 @@ s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs) { ring_info_t *ring = (ring_info_t *)dev_id; nic_t *sp = ring->nic; + int rxb_size, level, rng_n; atomic_inc(&sp->isr_cnt); - rx_intr_handler(ring); - s2io_chk_rx_buffers(sp, ring->ring_no); + rng_n = ring->ring_no; + rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]); + level = rx_buffer_level(sp, rxb_size, rng_n); + + if ((level == PANIC) && (!TASKLET_IN_USE)) { + int ret; + DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__); + DBG_PRINT(INTR_DBG, "PANIC levels\n"); + if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "Out of memory in %s", + __FUNCTION__); + clear_bit(0, (&sp->tasklet_status)); + return IRQ_HANDLED; + } + clear_bit(0, (&sp->tasklet_status)); + } else if (level == LOW) { + tasklet_schedule(&sp->task); + } atomic_dec(&sp->isr_cnt); + return IRQ_HANDLED; } @@ -4088,6 +3736,7 @@ s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs) atomic_dec(&sp->isr_cnt); return IRQ_HANDLED; } + static void s2io_txpic_intr_handle(nic_t *sp) { XENA_dev_config_t __iomem *bar0 = sp->bar0; @@ -4098,56 +3747,41 @@ static void s2io_txpic_intr_handle(nic_t *sp) val64 = readq(&bar0->gpio_int_reg); if ((val64 & GPIO_INT_REG_LINK_DOWN) && (val64 & GPIO_INT_REG_LINK_UP)) { - /* - * This is unstable state so clear both up/down - * interrupt and adapter to re-evaluate the link state. - */ val64 |= GPIO_INT_REG_LINK_DOWN; val64 |= GPIO_INT_REG_LINK_UP; writeq(val64, &bar0->gpio_int_reg); + goto masking; + } + + if (((sp->last_link_state == LINK_UP) && + (val64 & GPIO_INT_REG_LINK_DOWN)) || + ((sp->last_link_state == LINK_DOWN) && + (val64 & GPIO_INT_REG_LINK_UP))) { val64 = readq(&bar0->gpio_int_mask); - val64 &= ~(GPIO_INT_MASK_LINK_UP | - GPIO_INT_MASK_LINK_DOWN); + val64 |= GPIO_INT_MASK_LINK_DOWN; + val64 |= GPIO_INT_MASK_LINK_UP; writeq(val64, &bar0->gpio_int_mask); + s2io_set_link((unsigned long)sp); } - else if (val64 & GPIO_INT_REG_LINK_UP) { - val64 = readq(&bar0->adapter_status); - if (verify_xena_quiescence(sp, val64, - sp->device_enabled_once)) { - /* Enable Adapter */ - val64 = readq(&bar0->adapter_control); - val64 |= ADAPTER_CNTL_EN; - writeq(val64, &bar0->adapter_control); - val64 |= ADAPTER_LED_ON; - writeq(val64, &bar0->adapter_control); - if (!sp->device_enabled_once) - sp->device_enabled_once = 1; - - s2io_link(sp, LINK_UP); - /* - * unmask link down interrupt and mask link-up - * intr - */ - val64 = readq(&bar0->gpio_int_mask); - val64 &= ~GPIO_INT_MASK_LINK_DOWN; - val64 |= GPIO_INT_MASK_LINK_UP; - writeq(val64, &bar0->gpio_int_mask); - - } - }else if (val64 & GPIO_INT_REG_LINK_DOWN) { - val64 = readq(&bar0->adapter_status); - if (verify_xena_quiescence(sp, val64, - sp->device_enabled_once)) { - s2io_link(sp, LINK_DOWN); - /* Link is down so unmaks link up interrupt */ - val64 = readq(&bar0->gpio_int_mask); - val64 &= ~GPIO_INT_MASK_LINK_UP; - val64 |= GPIO_INT_MASK_LINK_DOWN; - writeq(val64, &bar0->gpio_int_mask); - } +masking: + if (sp->last_link_state == LINK_UP) { + /*enable down interrupt */ + val64 = readq(&bar0->gpio_int_mask); + /* unmasks link down intr */ + val64 &= ~GPIO_INT_MASK_LINK_DOWN; + /* masks link up intr */ + val64 |= GPIO_INT_MASK_LINK_UP; + writeq(val64, &bar0->gpio_int_mask); + } else { + /*enable UP Interrupt */ + val64 = readq(&bar0->gpio_int_mask); + /* unmasks link up interrupt */ + val64 &= ~GPIO_INT_MASK_LINK_UP; + /* masks link down interrupt */ + val64 |= GPIO_INT_MASK_LINK_DOWN; + writeq(val64, &bar0->gpio_int_mask); } } - val64 = readq(&bar0->gpio_int_mask); } /** @@ -4170,7 +3804,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs) nic_t *sp = dev->priv; XENA_dev_config_t __iomem *bar0 = sp->bar0; int i; - u64 reason = 0, val64, org_mask; + u64 reason = 0, val64; mac_info_t *mac_control; struct config_param *config; @@ -4194,41 +3828,43 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs) return IRQ_NONE; } - val64 = 0xFFFFFFFFFFFFFFFFULL; - /* Store current mask before masking all interrupts */ - org_mask = readq(&bar0->general_int_mask); - writeq(val64, &bar0->general_int_mask); - #ifdef CONFIG_S2IO_NAPI if (reason & GEN_INTR_RXTRAFFIC) { if (netif_rx_schedule_prep(dev)) { - writeq(val64, &bar0->rx_traffic_mask); + en_dis_able_nic_intrs(sp, RX_TRAFFIC_INTR, + DISABLE_INTRS); __netif_rx_schedule(dev); } } #else - /* - * Rx handler is called by default, without checking for the - * cause of interrupt. - * rx_traffic_int reg is an R1 register, writing all 1's - * will ensure that the actual interrupt causing bit get's - * cleared and hence a read can be avoided. - */ - writeq(val64, &bar0->rx_traffic_int); - for (i = 0; i < config->rx_ring_num; i++) { - rx_intr_handler(&mac_control->rings[i]); + /* If Intr is because of Rx Traffic */ + if (reason & GEN_INTR_RXTRAFFIC) { + /* + * rx_traffic_int reg is an R1 register, writing all 1's + * will ensure that the actual interrupt causing bit get's + * cleared and hence a read can be avoided. + */ + val64 = 0xFFFFFFFFFFFFFFFFULL; + writeq(val64, &bar0->rx_traffic_int); + for (i = 0; i < config->rx_ring_num; i++) { + rx_intr_handler(&mac_control->rings[i]); + } } #endif - /* - * tx_traffic_int reg is an R1 register, writing all 1's - * will ensure that the actual interrupt causing bit get's - * cleared and hence a read can be avoided. - */ - writeq(val64, &bar0->tx_traffic_int); + /* If Intr is because of Tx Traffic */ + if (reason & GEN_INTR_TXTRAFFIC) { + /* + * tx_traffic_int reg is an R1 register, writing all 1's + * will ensure that the actual interrupt causing bit get's + * cleared and hence a read can be avoided. + */ + val64 = 0xFFFFFFFFFFFFFFFFULL; + writeq(val64, &bar0->tx_traffic_int); - for (i = 0; i < config->tx_fifo_num; i++) - tx_intr_handler(&mac_control->fifos[i]); + for (i = 0; i < config->tx_fifo_num; i++) + tx_intr_handler(&mac_control->fifos[i]); + } if (reason & GEN_INTR_TXPIC) s2io_txpic_intr_handle(sp); @@ -4238,10 +3874,29 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs) * else schedule a tasklet to reallocate the buffers. */ #ifndef CONFIG_S2IO_NAPI - for (i = 0; i < config->rx_ring_num; i++) - s2io_chk_rx_buffers(sp, i); + for (i = 0; i < config->rx_ring_num; i++) { + int ret; + 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)) { + 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"); + clear_bit(0, (&sp->tasklet_status)); + atomic_dec(&sp->isr_cnt); + return IRQ_HANDLED; + } + clear_bit(0, (&sp->tasklet_status)); + } else if (level == LOW) { + tasklet_schedule(&sp->task); + } + } #endif - writeq(org_mask, &bar0->general_int_mask); + atomic_dec(&sp->isr_cnt); return IRQ_HANDLED; } @@ -4269,8 +3924,6 @@ static void s2io_updt_stats(nic_t *sp) if (cnt == 5) break; /* Updt failed */ } while(1); - } else { - memset(sp->mac_control.stats_info, 0, sizeof(StatInfo_t)); } } @@ -4346,8 +3999,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 */ - wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, - RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING); + wait_for_cmd_complete(sp); sp->m_cast_flg = 1; sp->all_multi_pos = MAC_MC_ALL_MC_ADDR_OFFSET; @@ -4362,8 +4014,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 */ - wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, - RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING); + wait_for_cmd_complete(sp); sp->m_cast_flg = 0; sp->all_multi_pos = 0; @@ -4428,8 +4079,7 @@ static void s2io_set_multicast(struct net_device *dev) writeq(val64, &bar0->rmac_addr_cmd_mem); /* Wait for command completes */ - if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, - RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) { + if (wait_for_cmd_complete(sp)) { DBG_PRINT(ERR_DBG, "%s: Adding ", dev->name); DBG_PRINT(ERR_DBG, "Multicasts failed\n"); @@ -4459,8 +4109,7 @@ static void s2io_set_multicast(struct net_device *dev) writeq(val64, &bar0->rmac_addr_cmd_mem); /* Wait for command completes */ - if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, - RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) { + if (wait_for_cmd_complete(sp)) { DBG_PRINT(ERR_DBG, "%s: Adding ", dev->name); DBG_PRINT(ERR_DBG, "Multicasts failed\n"); @@ -4480,7 +4129,7 @@ static void s2io_set_multicast(struct net_device *dev) * as defined in errno.h file on failure. */ -static int s2io_set_mac_addr(struct net_device *dev, u8 * addr) +int s2io_set_mac_addr(struct net_device *dev, u8 * addr) { nic_t *sp = dev->priv; XENA_dev_config_t __iomem *bar0 = sp->bar0; @@ -4505,8 +4154,7 @@ static 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 (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, - RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) { + if (wait_for_cmd_complete(sp)) { DBG_PRINT(ERR_DBG, "%s: set_mac_addr failed\n", dev->name); return FAILURE; } @@ -4903,50 +4551,6 @@ static int write_eeprom(nic_t * sp, int off, u64 data, int cnt) } return ret; } -static void s2io_vpd_read(nic_t *nic) -{ - u8 *vpd_data; - u8 data; - int i=0, cnt, fail = 0; - int vpd_addr = 0x80; - - if (nic->device_type == XFRAME_II_DEVICE) { - strcpy(nic->product_name, "Xframe II 10GbE network adapter"); - vpd_addr = 0x80; - } - else { - strcpy(nic->product_name, "Xframe I 10GbE network adapter"); - vpd_addr = 0x50; - } - - vpd_data = kmalloc(256, GFP_KERNEL); - if (!vpd_data) - return; - - for (i = 0; i < 256; i +=4 ) { - pci_write_config_byte(nic->pdev, (vpd_addr + 2), i); - pci_read_config_byte(nic->pdev, (vpd_addr + 2), &data); - pci_write_config_byte(nic->pdev, (vpd_addr + 3), 0); - for (cnt = 0; cnt <5; cnt++) { - msleep(2); - pci_read_config_byte(nic->pdev, (vpd_addr + 3), &data); - if (data == 0x80) - break; - } - if (cnt >= 5) { - DBG_PRINT(ERR_DBG, "Read of VPD data failed\n"); - fail = 1; - break; - } - pci_read_config_dword(nic->pdev, (vpd_addr + 4), - (u32 *)&vpd_data[i]); - } - if ((!fail) && (vpd_data[1] < VPD_PRODUCT_NAME_LEN)) { - memset(nic->product_name, 0, vpd_data[1]); - memcpy(nic->product_name, &vpd_data[3], vpd_data[1]); - } - kfree(vpd_data); -} /** * s2io_ethtool_geeprom - reads the value stored in the Eeprom. @@ -5259,12 +4863,10 @@ static int s2io_link_test(nic_t * sp, uint64_t * data) u64 val64; val64 = readq(&bar0->adapter_status); - if(!(LINK_IS_UP(val64))) + if (val64 & ADAPTER_STATUS_RMAC_LOCAL_FAULT) *data = 1; - else - *data = 0; - return *data; + return 0; } /** @@ -5458,19 +5060,9 @@ static void s2io_get_ethtool_stats(struct net_device *dev, (u64)le32_to_cpu(stat_info->tmac_bcst_frms_oflow) << 32 | le32_to_cpu(stat_info->tmac_bcst_frms); tmp_stats[i++] = le64_to_cpu(stat_info->tmac_pause_ctrl_frms); - tmp_stats[i++] = - (u64)le32_to_cpu(stat_info->tmac_ttl_octets_oflow) << 32 | - le32_to_cpu(stat_info->tmac_ttl_octets); - tmp_stats[i++] = - (u64)le32_to_cpu(stat_info->tmac_ucst_frms_oflow) << 32 | - le32_to_cpu(stat_info->tmac_ucst_frms); - tmp_stats[i++] = - (u64)le32_to_cpu(stat_info->tmac_nucst_frms_oflow) << 32 | - le32_to_cpu(stat_info->tmac_nucst_frms); tmp_stats[i++] = (u64)le32_to_cpu(stat_info->tmac_any_err_frms_oflow) << 32 | le32_to_cpu(stat_info->tmac_any_err_frms); - tmp_stats[i++] = le64_to_cpu(stat_info->tmac_ttl_less_fb_octets); tmp_stats[i++] = le64_to_cpu(stat_info->tmac_vld_ip_octets); tmp_stats[i++] = (u64)le32_to_cpu(stat_info->tmac_vld_ip_oflow) << 32 | @@ -5502,27 +5094,11 @@ static void s2io_get_ethtool_stats(struct net_device *dev, (u64)le32_to_cpu(stat_info->rmac_vld_bcst_frms_oflow) << 32 | le32_to_cpu(stat_info->rmac_vld_bcst_frms); tmp_stats[i++] = le32_to_cpu(stat_info->rmac_in_rng_len_err_frms); - tmp_stats[i++] = le32_to_cpu(stat_info->rmac_out_rng_len_err_frms); tmp_stats[i++] = le64_to_cpu(stat_info->rmac_long_frms); tmp_stats[i++] = le64_to_cpu(stat_info->rmac_pause_ctrl_frms); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_unsup_ctrl_frms); - tmp_stats[i++] = - (u64)le32_to_cpu(stat_info->rmac_ttl_octets_oflow) << 32 | - le32_to_cpu(stat_info->rmac_ttl_octets); - tmp_stats[i++] = - (u64)le32_to_cpu(stat_info->rmac_accepted_ucst_frms_oflow) - << 32 | le32_to_cpu(stat_info->rmac_accepted_ucst_frms); - tmp_stats[i++] = - (u64)le32_to_cpu(stat_info->rmac_accepted_nucst_frms_oflow) - << 32 | le32_to_cpu(stat_info->rmac_accepted_nucst_frms); tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_discarded_frms_oflow) << 32 | le32_to_cpu(stat_info->rmac_discarded_frms); - tmp_stats[i++] = - (u64)le32_to_cpu(stat_info->rmac_drop_events_oflow) - << 32 | le32_to_cpu(stat_info->rmac_drop_events); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_less_fb_octets); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_frms); tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_usized_frms_oflow) << 32 | le32_to_cpu(stat_info->rmac_usized_frms); @@ -5535,129 +5111,30 @@ static void s2io_get_ethtool_stats(struct net_device *dev, tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_jabber_frms_oflow) << 32 | le32_to_cpu(stat_info->rmac_jabber_frms); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_64_frms); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_65_127_frms); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_128_255_frms); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_256_511_frms); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_512_1023_frms); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_1024_1518_frms); - tmp_stats[i++] = - (u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 | + tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 | le32_to_cpu(stat_info->rmac_ip); tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ip_octets); tmp_stats[i++] = le32_to_cpu(stat_info->rmac_hdr_err_ip); - tmp_stats[i++] = - (u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 | + tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 | le32_to_cpu(stat_info->rmac_drop_ip); - tmp_stats[i++] = - (u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 | + tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 | le32_to_cpu(stat_info->rmac_icmp); tmp_stats[i++] = le64_to_cpu(stat_info->rmac_tcp); - tmp_stats[i++] = - (u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 | + tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 | le32_to_cpu(stat_info->rmac_udp); tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_err_drp_udp_oflow) << 32 | le32_to_cpu(stat_info->rmac_err_drp_udp); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_err_sym); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q0); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q1); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q2); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q3); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q4); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q5); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q6); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q7); - tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q0); - tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q1); - tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q2); - tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q3); - tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q4); - tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q5); - tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q6); - tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q7); tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_pause_cnt_oflow) << 32 | le32_to_cpu(stat_info->rmac_pause_cnt); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_data_err_cnt); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_ctrl_err_cnt); tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_accepted_ip_oflow) << 32 | le32_to_cpu(stat_info->rmac_accepted_ip); tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_tcp); - tmp_stats[i++] = le32_to_cpu(stat_info->rd_req_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->new_rd_req_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->new_rd_req_rtry_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->rd_rtry_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->wr_rtry_rd_ack_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->wr_req_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->new_wr_req_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->new_wr_req_rtry_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->wr_rtry_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->wr_disc_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->rd_rtry_wr_ack_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->txp_wr_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->txd_rd_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->txd_wr_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->rxd_rd_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->rxd_wr_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->txf_rd_cnt); - tmp_stats[i++] = le32_to_cpu(stat_info->rxf_wr_cnt); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_1519_4095_frms); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_4096_8191_frms); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_8192_max_frms); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_gt_max_frms); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_osized_alt_frms); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_jabber_alt_frms); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_gt_max_alt_frms); - tmp_stats[i++] = le64_to_cpu(stat_info->rmac_vlan_frms); - tmp_stats[i++] = le32_to_cpu(stat_info->rmac_len_discard); - tmp_stats[i++] = le32_to_cpu(stat_info->rmac_fcs_discard); - tmp_stats[i++] = le32_to_cpu(stat_info->rmac_pf_discard); - tmp_stats[i++] = le32_to_cpu(stat_info->rmac_da_discard); - tmp_stats[i++] = le32_to_cpu(stat_info->rmac_red_discard); - tmp_stats[i++] = le32_to_cpu(stat_info->rmac_rts_discard); - tmp_stats[i++] = le32_to_cpu(stat_info->rmac_ingm_full_discard); - tmp_stats[i++] = le32_to_cpu(stat_info->link_fault_cnt); tmp_stats[i++] = 0; tmp_stats[i++] = stat_info->sw_stat.single_ecc_errs; tmp_stats[i++] = stat_info->sw_stat.double_ecc_errs; - tmp_stats[i++] = stat_info->sw_stat.parity_err_cnt; - tmp_stats[i++] = stat_info->sw_stat.serious_err_cnt; - tmp_stats[i++] = stat_info->sw_stat.soft_reset_cnt; - tmp_stats[i++] = stat_info->sw_stat.fifo_full_cnt; - tmp_stats[i++] = stat_info->sw_stat.ring_full_cnt; - tmp_stats[i++] = stat_info->xpak_stat.alarm_transceiver_temp_high; - tmp_stats[i++] = stat_info->xpak_stat.alarm_transceiver_temp_low; - tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_bias_current_high; - tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_bias_current_low; - tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_output_power_high; - tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_output_power_low; - tmp_stats[i++] = stat_info->xpak_stat.warn_transceiver_temp_high; - tmp_stats[i++] = stat_info->xpak_stat.warn_transceiver_temp_low; - tmp_stats[i++] = stat_info->xpak_stat.warn_laser_bias_current_high; - tmp_stats[i++] = stat_info->xpak_stat.warn_laser_bias_current_low; - tmp_stats[i++] = stat_info->xpak_stat.warn_laser_output_power_high; - tmp_stats[i++] = stat_info->xpak_stat.warn_laser_output_power_low; - tmp_stats[i++] = stat_info->sw_stat.clubbed_frms_cnt; - tmp_stats[i++] = stat_info->sw_stat.sending_both; - tmp_stats[i++] = stat_info->sw_stat.outof_sequence_pkts; - tmp_stats[i++] = stat_info->sw_stat.flush_max_pkts; - if (stat_info->sw_stat.num_aggregations) { - u64 tmp = stat_info->sw_stat.sum_avg_pkts_aggregated; - int count = 0; - /* - * Since 64-bit divide does not work on all platforms, - * do repeated subtraction. - */ - while (tmp >= stat_info->sw_stat.num_aggregations) { - tmp -= stat_info->sw_stat.num_aggregations; - count++; - } - tmp_stats[i++] = count; - } - else - tmp_stats[i++] = 0; } static int s2io_ethtool_get_regs_len(struct net_device *dev) @@ -5722,19 +5199,6 @@ static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data) return 0; } -static u32 s2io_ethtool_op_get_tso(struct net_device *dev) -{ - return (dev->features & NETIF_F_TSO) != 0; -} -static int s2io_ethtool_op_set_tso(struct net_device *dev, u32 data) -{ - if (data) - dev->features |= (NETIF_F_TSO | NETIF_F_TSO6); - else - dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); - - return 0; -} static struct ethtool_ops netdev_ethtool_ops = { .get_settings = s2io_ethtool_gset, @@ -5755,8 +5219,8 @@ static struct ethtool_ops netdev_ethtool_ops = { .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, #ifdef NETIF_F_TSO - .get_tso = s2io_ethtool_op_get_tso, - .set_tso = s2io_ethtool_op_set_tso, + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, #endif .get_ufo = ethtool_op_get_ufo, .set_ufo = ethtool_op_set_ufo, @@ -5946,313 +5410,31 @@ static void s2io_set_link(unsigned long data) clear_bit(0, &(nic->link_state)); } -static int set_rxd_buffer_pointer(nic_t *sp, RxD_t *rxdp, buffAdd_t *ba, - struct sk_buff **skb, u64 *temp0, u64 *temp1, - u64 *temp2, int size) +static void s2io_card_down(nic_t * sp) { - struct net_device *dev = sp->dev; - struct sk_buff *frag_list; - - if ((sp->rxd_mode == RXD_MODE_1) && (rxdp->Host_Control == 0)) { - /* allocate skb */ - if (*skb) { - DBG_PRINT(INFO_DBG, "SKB is not NULL\n"); - /* - * As Rx frame are not going to be processed, - * using same mapped address for the Rxd - * buffer pointer - */ - ((RxD1_t*)rxdp)->Buffer0_ptr = *temp0; - } else { - *skb = dev_alloc_skb(size); - if (!(*skb)) { - DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name); - DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n"); - return -ENOMEM ; - } - /* storing the mapped addr in a temp variable - * such it will be used for next rxd whose - * Host Control is NULL - */ - ((RxD1_t*)rxdp)->Buffer0_ptr = *temp0 = - pci_map_single( sp->pdev, (*skb)->data, - size - NET_IP_ALIGN, - PCI_DMA_FROMDEVICE); - rxdp->Host_Control = (unsigned long) (*skb); - } - } else if ((sp->rxd_mode == RXD_MODE_3B) && (rxdp->Host_Control == 0)) { - /* Two buffer Mode */ - if (*skb) { - ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2; - ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0; - ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1; - } else { - *skb = dev_alloc_skb(size); - ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 = - pci_map_single(sp->pdev, (*skb)->data, - dev->mtu + 4, - PCI_DMA_FROMDEVICE); - ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0 = - pci_map_single( sp->pdev, ba->ba_0, BUF0_LEN, - PCI_DMA_FROMDEVICE); - rxdp->Host_Control = (unsigned long) (*skb); + int cnt = 0; + XENA_dev_config_t __iomem *bar0 = sp->bar0; + unsigned long flags; + register u64 val64 = 0; - /* Buffer-1 will be dummy buffer not used */ - ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1 = - pci_map_single(sp->pdev, ba->ba_1, BUF1_LEN, - PCI_DMA_FROMDEVICE); - } - } else if ((rxdp->Host_Control == 0)) { - /* Three buffer mode */ - if (*skb) { - ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0; - ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1; - ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2; - } else { - *skb = dev_alloc_skb(size); - - ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0 = - pci_map_single(sp->pdev, ba->ba_0, BUF0_LEN, - PCI_DMA_FROMDEVICE); - /* Buffer-1 receives L3/L4 headers */ - ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1 = - pci_map_single( sp->pdev, (*skb)->data, - l3l4hdr_size + 4, - PCI_DMA_FROMDEVICE); - /* - * skb_shinfo(skb)->frag_list will have L4 - * data payload - */ - skb_shinfo(*skb)->frag_list = dev_alloc_skb(dev->mtu + - ALIGN_SIZE); - if (skb_shinfo(*skb)->frag_list == NULL) { - DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb \ - failed\n ", dev->name); - return -ENOMEM ; - } - frag_list = skb_shinfo(*skb)->frag_list; - frag_list->next = NULL; - /* - * Buffer-2 receives L4 data payload - */ - ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 = - pci_map_single( sp->pdev, frag_list->data, - dev->mtu, PCI_DMA_FROMDEVICE); - } - } - return 0; -} -static void set_rxd_buffer_size(nic_t *sp, RxD_t *rxdp, int size) -{ - struct net_device *dev = sp->dev; - if (sp->rxd_mode == RXD_MODE_1) { - rxdp->Control_2 = SET_BUFFER0_SIZE_1( size - NET_IP_ALIGN); - } else if (sp->rxd_mode == RXD_MODE_3B) { - rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); - rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1); - rxdp->Control_2 |= SET_BUFFER2_SIZE_3( dev->mtu + 4); - } else { - rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); - rxdp->Control_2 |= SET_BUFFER1_SIZE_3(l3l4hdr_size + 4); - rxdp->Control_2 |= SET_BUFFER2_SIZE_3(dev->mtu); + del_timer_sync(&sp->alarm_timer); + /* If s2io_set_link task is executing, wait till it completes. */ + while (test_and_set_bit(0, &(sp->link_state))) { + msleep(50); } -} - -static int rxd_owner_bit_reset(nic_t *sp) -{ - int i, j, k, blk_cnt = 0, size; - mac_info_t * mac_control = &sp->mac_control; - struct config_param *config = &sp->config; - struct net_device *dev = sp->dev; - RxD_t *rxdp = NULL; - struct sk_buff *skb = NULL; - buffAdd_t *ba = NULL; - u64 temp0_64 = 0, temp1_64 = 0, temp2_64 = 0; - - /* Calculate the size based on ring mode */ - size = dev->mtu + HEADER_ETHERNET_II_802_3_SIZE + - HEADER_802_2_SIZE + HEADER_SNAP_SIZE; - if (sp->rxd_mode == RXD_MODE_1) - size += NET_IP_ALIGN; - else if (sp->rxd_mode == RXD_MODE_3B) - size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4; - else - size = l3l4hdr_size + ALIGN_SIZE + BUF0_LEN + 4; + atomic_set(&sp->card_state, CARD_DOWN); - for (i = 0; i < config->rx_ring_num; i++) { - blk_cnt = config->rx_cfg[i].num_rxd / - (rxd_count[sp->rxd_mode] +1); + /* disable Tx and Rx traffic on the NIC */ + stop_nic(sp); - for (j = 0; j < blk_cnt; j++) { - for (k = 0; k < rxd_count[sp->rxd_mode]; k++) { - rxdp = mac_control->rings[i]. - rx_blocks[j].rxds[k].virt_addr; - if(sp->rxd_mode >= RXD_MODE_3A) - ba = &mac_control->rings[i].ba[j][k]; - set_rxd_buffer_pointer(sp, rxdp, ba, - &skb,(u64 *)&temp0_64, - (u64 *)&temp1_64, - (u64 *)&temp2_64, size); + /* Kill tasklet. */ + tasklet_kill(&sp->task); - set_rxd_buffer_size(sp, rxdp, size); - wmb(); - /* flip the Ownership bit to Hardware */ - rxdp->Control_1 |= RXD_OWN_XENA; - } - } - } - return 0; - -} - -static int s2io_add_isr(nic_t * sp) -{ - int ret = 0; - struct net_device *dev = sp->dev; - int err = 0; - - if (sp->intr_type == MSI) - ret = s2io_enable_msi(sp); - else if (sp->intr_type == MSI_X) - ret = s2io_enable_msi_x(sp); - if (ret) { - DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name); - sp->intr_type = INTA; - } - - /* Store the values of the MSIX table in the nic_t structure */ - store_xmsi_data(sp); - - /* After proper initialization of H/W, register ISR */ - if (sp->intr_type == MSI) { - err = request_irq((int) sp->pdev->irq, s2io_msi_handle, - IRQF_SHARED, sp->name, dev); - if (err) { - pci_disable_msi(sp->pdev); - DBG_PRINT(ERR_DBG, "%s: MSI registration failed\n", - dev->name); - return -1; - } - } - if (sp->intr_type == MSI_X) { - int i; - - for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) { - if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) { - sprintf(sp->desc[i], "%s:MSI-X-%d-TX", - dev->name, i); - err = request_irq(sp->entries[i].vector, - s2io_msix_fifo_handle, 0, sp->desc[i], - sp->s2io_entries[i].arg); - DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc[i], - (unsigned long long)sp->msix_info[i].addr); - } else { - sprintf(sp->desc[i], "%s:MSI-X-%d-RX", - dev->name, i); - err = request_irq(sp->entries[i].vector, - s2io_msix_ring_handle, 0, sp->desc[i], - sp->s2io_entries[i].arg); - DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc[i], - (unsigned long long)sp->msix_info[i].addr); - } - if (err) { - DBG_PRINT(ERR_DBG,"%s:MSI-X-%d registration " - "failed\n", dev->name, i); - DBG_PRINT(ERR_DBG, "Returned: %d\n", err); - return -1; - } - sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS; - } - } - if (sp->intr_type == INTA) { - err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED, - sp->name, dev); - if (err) { - DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n", - dev->name); - return -1; - } - } - return 0; -} -static void s2io_rem_isr(nic_t * sp) -{ - int cnt = 0; - struct net_device *dev = sp->dev; - - if (sp->intr_type == MSI_X) { - int i; - u16 msi_control; - - for (i=1; (sp->s2io_entries[i].in_use == - MSIX_REGISTERED_SUCCESS); i++) { - int vector = sp->entries[i].vector; - void *arg = sp->s2io_entries[i].arg; - - free_irq(vector, arg); - } - pci_read_config_word(sp->pdev, 0x42, &msi_control); - msi_control &= 0xFFFE; /* Disable MSI */ - pci_write_config_word(sp->pdev, 0x42, msi_control); - - pci_disable_msix(sp->pdev); - } else { - free_irq(sp->pdev->irq, dev); - if (sp->intr_type == MSI) { - u16 val; - - pci_disable_msi(sp->pdev); - pci_read_config_word(sp->pdev, 0x4c, &val); - val ^= 0x1; - pci_write_config_word(sp->pdev, 0x4c, val); - } - } - /* Waiting till all Interrupt handlers are complete */ - cnt = 0; - do { - msleep(10); - if (!atomic_read(&sp->isr_cnt)) - break; - cnt++; - } while(cnt < 5); -} - -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; - - del_timer_sync(&sp->alarm_timer); - /* If s2io_set_link task is executing, wait till it completes. */ - while (test_and_set_bit(0, &(sp->link_state))) { - msleep(50); - } - atomic_set(&sp->card_state, CARD_DOWN); - - /* disable Tx and Rx traffic on the NIC */ - stop_nic(sp); - - s2io_rem_isr(sp); - - /* Kill tasklet. */ - tasklet_kill(&sp->task); - - /* Check if the device is Quiescent and then Reset the NIC */ - do { - /* As per the HW requirement we need to replenish the - * receive buffer to avoid the ring bump. Since there is - * no intention of processing the Rx frame at this pointwe are - * just settting the ownership bit of rxd in Each Rx - * ring to HW and set the appropriate buffer size - * based on the ring mode - */ - rxd_owner_bit_reset(sp); - - val64 = readq(&bar0->adapter_status); - if (verify_xena_quiescence(sp, val64, sp->device_enabled_once)) { - break; + /* Check if the device is Quiescent and then Reset the NIC */ + do { + val64 = readq(&bar0->adapter_status); + if (verify_xena_quiescence(sp, val64, sp->device_enabled_once)) { + break; } msleep(50); @@ -6267,6 +5449,15 @@ static void s2io_card_down(nic_t * sp) } while (1); s2io_reset(sp); + /* Waiting till all Interrupt handlers are complete */ + cnt = 0; + do { + msleep(10); + if (!atomic_read(&sp->isr_cnt)) + break; + cnt++; + } while(cnt < 5); + spin_lock_irqsave(&sp->tx_lock, flags); /* Free all Tx buffers */ free_tx_buffers(sp); @@ -6286,16 +5477,23 @@ static int s2io_card_up(nic_t * sp) mac_info_t *mac_control; struct config_param *config; struct net_device *dev = (struct net_device *) sp->dev; - u16 interruptible; /* Initialize the H/W I/O registers */ if (init_nic(sp) != 0) { DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n", dev->name); - s2io_reset(sp); return -ENODEV; } + if (sp->intr_type == MSI) + ret = s2io_enable_msi(sp); + else if (sp->intr_type == MSI_X) + ret = s2io_enable_msi_x(sp); + if (ret) { + DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name); + sp->intr_type = INTA; + } + /* * Initializing the Rx buffers. For now we are considering only 1 * Rx ring and initializing buffers into 30 Rx blocks @@ -6318,47 +5516,21 @@ static int s2io_card_up(nic_t * sp) /* Setting its receive mode */ s2io_set_multicast(dev); - if (sp->lro) { - /* Initialize max aggregatable pkts per session based on MTU */ - sp->lro_max_aggr_per_sess = ((1<<16) - 1) / dev->mtu; - /* Check if we can use(if specified) user provided value */ - if (lro_max_pkts < sp->lro_max_aggr_per_sess) - sp->lro_max_aggr_per_sess = lro_max_pkts; - } + /* 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_rx_buffers(sp); - return -ENODEV; - } - - /* Add interrupt service routine */ - if (s2io_add_isr(sp) != 0) { - if (sp->intr_type == MSI_X) - s2io_rem_isr(sp); - s2io_reset(sp); + free_irq(dev->irq, dev); free_rx_buffers(sp); return -ENODEV; } S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2)); - /* Enable tasklet for the device */ - tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev); - - /* Enable select interrupts */ - if (sp->intr_type != INTA) - en_dis_able_nic_intrs(sp, ENA_ALL_INTRS, DISABLE_INTRS); - else { - interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR; - interruptible |= TX_PIC_INTR | RX_PIC_INTR; - interruptible |= TX_MAC_INTR | RX_MAC_INTR; - en_dis_able_nic_intrs(sp, interruptible, ENABLE_INTRS); - } - - atomic_set(&sp->card_state, CARD_UP); return 0; } @@ -6408,7 +5580,6 @@ static void s2io_tx_watchdog(struct net_device *dev) if (netif_carrier_ok(dev)) { schedule_work(&sp->rst_timer_task); - sp->mac_control.stats_info->sw_stat.soft_reset_cnt++; } } @@ -6420,7 +5591,7 @@ static void s2io_tx_watchdog(struct net_device *dev) * @cksum : FCS checksum of the frame. * @ring_no : the ring from which this RxD was extracted. * Description: - * This function is called by the Rx interrupt serivce routine to perform + * 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 @@ -6437,33 +5608,17 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp) ((unsigned long) rxdp->Host_Control); int ring_no = ring_data->ring_no; u16 l3_csum, l4_csum; - unsigned long long err = rxdp->Control_1 & RXD_T_CODE; - lro_t *lro; skb->dev = dev; - - if (err) { - /* Check for parity error */ - if (err & 0x1) { - sp->mac_control.stats_info->sw_stat.parity_err_cnt++; - } - - /* - * Drop the packet if bad transfer code. Exception being - * 0x5, which could be due to unsupported IPv6 extension header. - * In this case, we let stack handle the packet. - * Note that in this case, since checksum will be incorrect, - * stack will validate the same. - */ - if (err && ((err >> 48) != 0x5)) { - DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n", - dev->name, err); - sp->stats.rx_crc_errors++; - dev_kfree_skb(skb); - atomic_dec(&sp->rx_bufs_left[ring_no]); - rxdp->Host_Control = 0; - return 0; - } + 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); + dev_kfree_skb(skb); + sp->stats.rx_crc_errors++; + atomic_dec(&sp->rx_bufs_left[ring_no]); + rxdp->Host_Control = 0; + return 0; } /* Updating statistics */ @@ -6501,8 +5656,7 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp) skb_put(skb, buf2_len); } - if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && ((!sp->lro) || - (sp->lro && (!(rxdp->Control_1 & RXD_FRAME_IP_FRAG)))) && + if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && (sp->rx_csum)) { l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1); l4_csum = RXD_GET_L4_CKSUM(rxdp->Control_1); @@ -6513,57 +5667,6 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp) * a flag in the RxD. */ skb->ip_summed = CHECKSUM_UNNECESSARY; - if (sp->lro) { - u32 tcp_len; - u8 *tcp; - int ret = 0; - - ret = s2io_club_tcp_session(skb->data, &tcp, - &tcp_len, &lro, rxdp, sp); - switch (ret) { - case 3: /* Begin anew */ - lro->parent = skb; - goto aggregate; - case 1: /* Aggregate */ - { - lro_append_pkt(sp, lro, - skb, tcp_len); - goto aggregate; - } - case 4: /* Flush session */ - { - lro_append_pkt(sp, lro, - skb, tcp_len); - queue_rx_frame(lro->parent); - clear_lro_session(lro); - sp->mac_control.stats_info-> - sw_stat.flush_max_pkts++; - goto aggregate; - } - case 2: /* Flush both */ - lro->parent->data_len = - lro->frags_len; - sp->mac_control.stats_info-> - sw_stat.sending_both++; - queue_rx_frame(lro->parent); - clear_lro_session(lro); - goto send_up; - case 0: /* sessions exceeded */ - case -1: /* non-TCP or not - * L2 aggregatable - */ - case 5: /* - * First pkt in session not - * L3/L4 aggregatable - */ - break; - default: - DBG_PRINT(ERR_DBG, - "%s: Samadhana!!\n", - __FUNCTION__); - BUG(); - } - } } else { /* * Packet with erroneous checksum, let the @@ -6575,31 +5678,25 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp) skb->ip_summed = CHECKSUM_NONE; } - if (!sp->lro) { - skb->protocol = eth_type_trans(skb, dev); + skb->protocol = eth_type_trans(skb, dev); #ifdef CONFIG_S2IO_NAPI - if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) { - /* Queueing the vlan frame to the upper layer */ - vlan_hwaccel_receive_skb(skb, sp->vlgrp, - RXD_GET_VLAN_TAG(rxdp->Control_2)); - } else { - netif_receive_skb(skb); - } + if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) { + /* Queueing the vlan frame to the upper layer */ + vlan_hwaccel_receive_skb(skb, sp->vlgrp, + RXD_GET_VLAN_TAG(rxdp->Control_2)); + } else { + netif_receive_skb(skb); + } #else - if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) { - /* Queueing the vlan frame to the upper layer */ - vlan_hwaccel_rx(skb, sp->vlgrp, - RXD_GET_VLAN_TAG(rxdp->Control_2)); - } else { - netif_rx(skb); - } -#endif + if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) { + /* Queueing the vlan frame to the upper layer */ + vlan_hwaccel_rx(skb, sp->vlgrp, + RXD_GET_VLAN_TAG(rxdp->Control_2)); } else { -send_up: - queue_rx_frame(skb); - } + netif_rx(skb); + } +#endif dev->last_rx = jiffies; -aggregate: atomic_dec(&sp->rx_bufs_left[ring_no]); return SUCCESS; } @@ -6617,7 +5714,7 @@ aggregate: * void. */ -static void s2io_link(nic_t * sp, int link) +void s2io_link(nic_t * sp, int link) { struct net_device *dev = (struct net_device *) sp->dev; @@ -6642,7 +5739,7 @@ static void s2io_link(nic_t * sp, int link) * returns the revision ID of the device. */ -static int get_xena_rev_id(struct pci_dev *pdev) +int get_xena_rev_id(struct pci_dev *pdev) { u8 id = 0; int ret; @@ -6678,56 +5775,39 @@ static void s2io_init_pci(nic_t * sp) pci_write_config_word(sp->pdev, PCI_COMMAND, (pci_cmd | PCI_COMMAND_PARITY)); pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd); + + /* Forcibly disabling relaxed ordering capability of the card. */ + pcix_cmd &= 0xfffd; + pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, + pcix_cmd); + pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, + &(pcix_cmd)); } -static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type) -{ - if ( tx_fifo_num > 8) { - DBG_PRINT(ERR_DBG, "s2io: Requested number of Tx fifos not " - "supported\n"); - DBG_PRINT(ERR_DBG, "s2io: Default to 8 Tx fifos\n"); - tx_fifo_num = 8; - } - if ( rx_ring_num > 8) { - DBG_PRINT(ERR_DBG, "s2io: Requested number of Rx rings not " - "supported\n"); - DBG_PRINT(ERR_DBG, "s2io: Default to 8 Rx rings\n"); - rx_ring_num = 8; - } -#ifdef CONFIG_S2IO_NAPI - if (*dev_intr_type != INTA) { - DBG_PRINT(ERR_DBG, "s2io: NAPI cannot be enabled when " - "MSI/MSI-X is enabled. Defaulting to INTA\n"); - *dev_intr_type = INTA; - } -#endif -#ifndef CONFIG_PCI_MSI - if (*dev_intr_type != INTA) { - DBG_PRINT(ERR_DBG, "s2io: This kernel does not support" - "MSI/MSI-X. Defaulting to INTA\n"); - *dev_intr_type = INTA; - } -#else - if (*dev_intr_type > MSI_X) { - DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. " - "Defaulting to INTA\n"); - *dev_intr_type = INTA; - } +MODULE_AUTHOR("Raghavendra Koushik "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +module_param(tx_fifo_num, int, 0); +module_param(rx_ring_num, int, 0); +module_param(rx_ring_mode, int, 0); +module_param_array(tx_fifo_len, uint, NULL, 0); +module_param_array(rx_ring_sz, uint, NULL, 0); +module_param_array(rts_frm_len, uint, NULL, 0); +module_param(use_continuous_tx_intrs, int, 1); +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); +module_param(bimodal, bool, 0); +module_param(l3l4hdr_size, int , 0); +#ifndef CONFIG_S2IO_NAPI +module_param(indicate_max_pkts, int, 0); #endif - if ((*dev_intr_type == MSI_X) && - ((pdev->device != PCI_DEVICE_ID_HERC_WIN) && - (pdev->device != PCI_DEVICE_ID_HERC_UNI))) { - DBG_PRINT(ERR_DBG, "s2io: Xframe I does not support MSI_X. " - "Defaulting to INTA\n"); - *dev_intr_type = INTA; - } - if (rx_ring_mode > 3) { - DBG_PRINT(ERR_DBG, "s2io: Requested ring mode not supported\n"); - DBG_PRINT(ERR_DBG, "s2io: Defaulting to 3-buffer mode\n"); - rx_ring_mode = 3; - } - return SUCCESS; -} +module_param(rxsync_frequency, int, 0); +module_param(intr_type, int, 0); /** * s2io_init_nic - Initialization of the adapter . @@ -6759,8 +5839,15 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) int mode; u8 dev_intr_type = intr_type; - if ((ret = s2io_verify_parm(pdev, &dev_intr_type))) - return ret; +#ifdef CONFIG_S2IO_NAPI + if (dev_intr_type != INTA) { + DBG_PRINT(ERR_DBG, "NAPI cannot be enabled when MSI/MSI-X \ +is enabled. Defaulting to INTA\n"); + dev_intr_type = INTA; + } + else + DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n"); +#endif if ((ret = pci_enable_device(pdev))) { DBG_PRINT(ERR_DBG, @@ -6785,10 +5872,18 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) pci_disable_device(pdev); return -ENOMEM; } + + if ((dev_intr_type == MSI_X) && + ((pdev->device != PCI_DEVICE_ID_HERC_WIN) && + (pdev->device != PCI_DEVICE_ID_HERC_UNI))) { + DBG_PRINT(ERR_DBG, "Xframe I does not support MSI_X. \ +Defaulting to INTA\n"); + dev_intr_type = INTA; + } if (dev_intr_type != MSI_X) { if (pci_request_regions(pdev, s2io_driver_name)) { - DBG_PRINT(ERR_DBG, "Request Regions failed\n"); - pci_disable_device(pdev); + DBG_PRINT(ERR_DBG, "Request Regions failed\n"), + pci_disable_device(pdev); return -ENODEV; } } @@ -6844,7 +5939,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) else sp->device_type = XFRAME_I_DEVICE; - sp->lro = lro; /* Initialize some PCI/PCI-X fields of the NIC. */ s2io_init_pci(sp); @@ -6860,6 +5954,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) config = &sp->config; /* Tx side parameters. */ + if (tx_fifo_len[0] == 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]; @@ -6883,6 +5979,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) config->max_txds = MAX_SKB_FRAGS + 2; /* Rx side parameters. */ + if (rx_ring_sz[0] == 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] * @@ -6912,7 +6010,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) /* initialize the shared memory used by the NIC and the host */ if (init_shared_mem(sp)) { DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", - dev->name); + __FUNCTION__); ret = -ENOMEM; goto mem_alloc_failed; } @@ -6966,18 +6064,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) dev->weight = 32; #endif -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = s2io_netpoll; -#endif - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; if (sp->high_dma_flag == TRUE) dev->features |= NETIF_F_HIGHDMA; #ifdef NETIF_F_TSO dev->features |= NETIF_F_TSO; -#endif -#ifdef NETIF_F_TSO6 - dev->features |= NETIF_F_TSO6; #endif if (sp->device_type & XFRAME_II_DEVICE) { dev->features |= NETIF_F_UFO; @@ -7030,8 +6121,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) 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); - wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, - RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING); + wait_for_cmd_complete(sp); + tmp64 = readq(&bar0->rmac_addr_data0_mem); mac_down = (u32) tmp64; mac_up = (u32) (tmp64 >> 32); @@ -7049,9 +6140,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) dev->addr_len = ETH_ALEN; memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN); - /* reset Nic and bring it to known state */ - s2io_reset(sp); - /* * Initialize the tasklet status and link state flags * and the card state parameter @@ -7088,63 +6176,78 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) ret = -ENODEV; goto register_failed; } - s2io_vpd_read(sp); - DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2005 Neterion Inc.\n"); - DBG_PRINT(ERR_DBG, "%s: Neterion %s (rev %d)\n",dev->name, - sp->product_name, get_xena_rev_id(sp->pdev)); - DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name, - s2io_driver_version); - DBG_PRINT(ERR_DBG, "%s: MAC ADDR: " - "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, + + if (sp->device_type & XFRAME_II_DEVICE) { + DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ", + dev->name); + DBG_PRINT(ERR_DBG, "(rev %d), Version %s", + get_xena_rev_id(sp->pdev), + s2io_driver_version); + switch(sp->intr_type) { + case INTA: + DBG_PRINT(ERR_DBG, ", Intr type INTA"); + break; + case MSI: + DBG_PRINT(ERR_DBG, ", Intr type MSI"); + break; + case MSI_X: + DBG_PRINT(ERR_DBG, ", Intr type MSI-X"); + break; + } + + DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n"); + DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", 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]); - if (sp->device_type & XFRAME_II_DEVICE) { mode = s2io_print_pci_mode(sp); if (mode < 0) { - DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode\n"); + DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode "); ret = -EBADSLT; - unregister_netdev(dev); goto set_swap_failed; } - } - switch(sp->rxd_mode) { - case RXD_MODE_1: - DBG_PRINT(ERR_DBG, "%s: 1-Buffer receive mode enabled\n", - dev->name); - break; - case RXD_MODE_3B: - DBG_PRINT(ERR_DBG, "%s: 2-Buffer receive mode enabled\n", - dev->name); - break; - case RXD_MODE_3A: - DBG_PRINT(ERR_DBG, "%s: 3-Buffer receive mode enabled\n", - dev->name); - break; - } -#ifdef CONFIG_S2IO_NAPI - DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name); -#endif - switch(sp->intr_type) { - case INTA: - DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name); - break; - case MSI: - DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI\n", dev->name); - break; - case MSI_X: - DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI-X\n", dev->name); - break; - } - if (sp->lro) - DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n", + } else { + DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ", dev->name); + DBG_PRINT(ERR_DBG, "(rev %d), Version %s", + get_xena_rev_id(sp->pdev), + s2io_driver_version); + switch(sp->intr_type) { + case INTA: + DBG_PRINT(ERR_DBG, ", Intr type INTA"); + break; + case MSI: + DBG_PRINT(ERR_DBG, ", Intr type MSI"); + break; + case MSI_X: + DBG_PRINT(ERR_DBG, ", Intr type MSI-X"); + break; + } + DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n"); + DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", + 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]); + } + if (sp->rxd_mode == RXD_MODE_3B) + DBG_PRINT(ERR_DBG, "%s: 2-Buffer mode support has been " + "enabled\n",dev->name); + if (sp->rxd_mode == RXD_MODE_3A) + DBG_PRINT(ERR_DBG, "%s: 3-Buffer mode support has been " + "enabled\n",dev->name); /* Initialize device name */ - sprintf(sp->name, "%s Neterion %s", dev->name, sp->product_name); + strcpy(sp->name, dev->name); + if (sp->device_type & XFRAME_II_DEVICE) + strcat(sp->name, ": Neterion Xframe II 10GbE adapter"); + else + strcat(sp->name, ": Neterion Xframe I 10GbE adapter"); /* Initialize bimodal Interrupts */ sp->config.bimodal = bimodal; @@ -7241,7 +6344,7 @@ int __init s2io_starter(void) * Description: This function is the cleanup routine for the driver. It unregist * ers the driver. */ -static void s2io_closer(void) +void s2io_closer(void) { pci_unregister_driver(&s2io_driver); DBG_PRINT(INIT_DBG, "cleanup done\n"); @@ -7249,321 +6352,3 @@ static void s2io_closer(void) module_init(s2io_starter); module_exit(s2io_closer); - -static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip, - struct tcphdr **tcp, RxD_t *rxdp) -{ - int ip_off; - u8 l2_type = (u8)((rxdp->Control_1 >> 37) & 0x7), ip_len; - - if (!(rxdp->Control_1 & RXD_FRAME_PROTO_TCP)) { - DBG_PRINT(INIT_DBG,"%s: Non-TCP frames not supported for LRO\n", - __FUNCTION__); - return -1; - } - - /* TODO: - * By default the VLAN field in the MAC is stripped by the card, if this - * feature is turned off in rx_pa_cfg register, then the ip_off field - * has to be shifted by a further 2 bytes - */ - switch (l2_type) { - case 0: /* DIX type */ - case 4: /* DIX type with VLAN */ - ip_off = HEADER_ETHERNET_II_802_3_SIZE; - break; - /* LLC, SNAP etc are considered non-mergeable */ - default: - return -1; - } - - *ip = (struct iphdr *)((u8 *)buffer + ip_off); - ip_len = (u8)((*ip)->ihl); - ip_len <<= 2; - *tcp = (struct tcphdr *)((unsigned long)*ip + ip_len); - - return 0; -} - -static int check_for_socket_match(lro_t *lro, struct iphdr *ip, - struct tcphdr *tcp) -{ - DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); - if ((lro->iph->saddr != ip->saddr) || (lro->iph->daddr != ip->daddr) || - (lro->tcph->source != tcp->source) || (lro->tcph->dest != tcp->dest)) - return -1; - return 0; -} - -static inline int get_l4_pyld_length(struct iphdr *ip, struct tcphdr *tcp) -{ - return(ntohs(ip->tot_len) - (ip->ihl << 2) - (tcp->doff << 2)); -} - -static void initiate_new_session(lro_t *lro, u8 *l2h, - struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len) -{ - DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); - lro->l2h = l2h; - lro->iph = ip; - lro->tcph = tcp; - lro->tcp_next_seq = tcp_pyld_len + ntohl(tcp->seq); - lro->tcp_ack = ntohl(tcp->ack_seq); - lro->sg_num = 1; - lro->total_len = ntohs(ip->tot_len); - lro->frags_len = 0; - /* - * check if we saw TCP timestamp. Other consistency checks have - * already been done. - */ - if (tcp->doff == 8) { - u32 *ptr; - ptr = (u32 *)(tcp+1); - lro->saw_ts = 1; - lro->cur_tsval = *(ptr+1); - lro->cur_tsecr = *(ptr+2); - } - lro->in_use = 1; -} - -static void update_L3L4_header(nic_t *sp, lro_t *lro) -{ - struct iphdr *ip = lro->iph; - struct tcphdr *tcp = lro->tcph; - u16 nchk; - StatInfo_t *statinfo = sp->mac_control.stats_info; - DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); - - /* Update L3 header */ - ip->tot_len = htons(lro->total_len); - ip->check = 0; - nchk = ip_fast_csum((u8 *)lro->iph, ip->ihl); - ip->check = nchk; - - /* Update L4 header */ - tcp->ack_seq = lro->tcp_ack; - tcp->window = lro->window; - - /* Update tsecr field if this session has timestamps enabled */ - if (lro->saw_ts) { - u32 *ptr = (u32 *)(tcp + 1); - *(ptr+2) = lro->cur_tsecr; - } - - /* Update counters required for calculation of - * average no. of packets aggregated. - */ - statinfo->sw_stat.sum_avg_pkts_aggregated += lro->sg_num; - statinfo->sw_stat.num_aggregations++; -} - -static void aggregate_new_rx(lro_t *lro, struct iphdr *ip, - struct tcphdr *tcp, u32 l4_pyld) -{ - DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); - lro->total_len += l4_pyld; - lro->frags_len += l4_pyld; - lro->tcp_next_seq += l4_pyld; - lro->sg_num++; - - /* Update ack seq no. and window ad(from this pkt) in LRO object */ - lro->tcp_ack = tcp->ack_seq; - lro->window = tcp->window; - - if (lro->saw_ts) { - u32 *ptr; - /* Update tsecr and tsval from this packet */ - ptr = (u32 *) (tcp + 1); - lro->cur_tsval = *(ptr + 1); - lro->cur_tsecr = *(ptr + 2); - } -} - -static int verify_l3_l4_lro_capable(lro_t *l_lro, struct iphdr *ip, - struct tcphdr *tcp, u32 tcp_pyld_len) -{ - u8 *ptr; - - DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__); - - if (!tcp_pyld_len) { - /* Runt frame or a pure ack */ - return -1; - } - - if (ip->ihl != 5) /* IP has options */ - return -1; - - /* If we see CE codepoint in IP header, packet is not mergeable */ - if (INET_ECN_is_ce(ipv4_get_dsfield(ip))) - return -1; - - /* If we see ECE or CWR flags in TCP header, packet is not mergeable */ - if (tcp->urg || tcp->psh || tcp->rst || tcp->syn || tcp->fin || - tcp->ece || tcp->cwr || !tcp->ack) { - /* - * Currently recognize only the ack control word and - * any other control field being set would result in - * flushing the LRO session - */ - return -1; - } - - /* - * Allow only one TCP timestamp option. Don't aggregate if - * any other options are detected. - */ - if (tcp->doff != 5 && tcp->doff != 8) - return -1; - - if (tcp->doff == 8) { - ptr = (u8 *)(tcp + 1); - while (*ptr == TCPOPT_NOP) - ptr++; - if (*ptr != TCPOPT_TIMESTAMP || *(ptr+1) != TCPOLEN_TIMESTAMP) - return -1; - - /* Ensure timestamp value increases monotonically */ - if (l_lro) - if (l_lro->cur_tsval > *((u32 *)(ptr+2))) - return -1; - - /* timestamp echo reply should be non-zero */ - if (*((u32 *)(ptr+6)) == 0) - return -1; - } - - return 0; -} - -static int -s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, lro_t **lro, - RxD_t *rxdp, nic_t *sp) -{ - struct iphdr *ip; - struct tcphdr *tcph; - int ret = 0, i; - - if (!(ret = check_L2_lro_capable(buffer, &ip, (struct tcphdr **)tcp, - rxdp))) { - DBG_PRINT(INFO_DBG,"IP Saddr: %x Daddr: %x\n", - ip->saddr, ip->daddr); - } else { - return ret; - } - - tcph = (struct tcphdr *)*tcp; - *tcp_len = get_l4_pyld_length(ip, tcph); - for (i=0; ilro0_n[i]; - if (l_lro->in_use) { - if (check_for_socket_match(l_lro, ip, tcph)) - continue; - /* Sock pair matched */ - *lro = l_lro; - - if ((*lro)->tcp_next_seq != ntohl(tcph->seq)) { - DBG_PRINT(INFO_DBG, "%s:Out of order. expected " - "0x%x, actual 0x%x\n", __FUNCTION__, - (*lro)->tcp_next_seq, - ntohl(tcph->seq)); - - sp->mac_control.stats_info-> - sw_stat.outof_sequence_pkts++; - ret = 2; - break; - } - - if (!verify_l3_l4_lro_capable(l_lro, ip, tcph,*tcp_len)) - ret = 1; /* Aggregate */ - else - ret = 2; /* Flush both */ - break; - } - } - - if (ret == 0) { - /* Before searching for available LRO objects, - * check if the pkt is L3/L4 aggregatable. If not - * don't create new LRO session. Just send this - * packet up. - */ - if (verify_l3_l4_lro_capable(NULL, ip, tcph, *tcp_len)) { - return 5; - } - - for (i=0; ilro0_n[i]; - if (!(l_lro->in_use)) { - *lro = l_lro; - ret = 3; /* Begin anew */ - break; - } - } - } - - if (ret == 0) { /* sessions exceeded */ - DBG_PRINT(INFO_DBG,"%s:All LRO sessions already in use\n", - __FUNCTION__); - *lro = NULL; - return ret; - } - - switch (ret) { - case 3: - initiate_new_session(*lro, buffer, ip, tcph, *tcp_len); - break; - case 2: - update_L3L4_header(sp, *lro); - break; - case 1: - aggregate_new_rx(*lro, ip, tcph, *tcp_len); - if ((*lro)->sg_num == sp->lro_max_aggr_per_sess) { - update_L3L4_header(sp, *lro); - ret = 4; /* Flush the LRO */ - } - break; - default: - DBG_PRINT(ERR_DBG,"%s:Dont know, can't say!!\n", - __FUNCTION__); - break; - } - - return ret; -} - -static void clear_lro_session(lro_t *lro) -{ - static u16 lro_struct_size = sizeof(lro_t); - - memset(lro, 0, lro_struct_size); -} - -static void queue_rx_frame(struct sk_buff *skb) -{ - struct net_device *dev = skb->dev; - - skb->protocol = eth_type_trans(skb, dev); -#ifdef CONFIG_S2IO_NAPI - netif_receive_skb(skb); -#else - netif_rx(skb); -#endif -} - -static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, - u32 tcp_len) -{ - struct sk_buff *first = lro->parent; - - first->len += tcp_len; - first->data_len = lro->frags_len; - skb_pull(skb, (skb->len - tcp_len)); - if (skb_shinfo(first)->frag_list) - lro->last_frag->next = skb; - else - skb_shinfo(first)->frag_list = skb; - lro->last_frag = skb; - sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++; - return; -}