Loading drivers/net/s2io.c +173 −213 Original line number Diff line number Diff line Loading @@ -76,7 +76,7 @@ #include "s2io.h" #include "s2io-regs.h" #define DRV_VERSION "2.0.14.2" #define DRV_VERSION "2.0.15.2" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; Loading Loading @@ -370,38 +370,50 @@ static const u64 fix_mac[] = { END_SIGN }; MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); /* Module Loadable parameters. */ 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}; static unsigned int rx_ring_num = 1; static unsigned int rx_ring_sz[MAX_RX_RINGS] = {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT}; static unsigned int rts_frm_len[MAX_RX_RINGS] = {[0 ...(MAX_RX_RINGS - 1)] = 0 }; static unsigned int rx_ring_mode = 1; static unsigned int use_continuous_tx_intrs = 1; static unsigned int rmac_pause_time = 0x100; 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 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 */ static unsigned int rxsync_frequency = 3; S2IO_PARM_INT(rxsync_frequency, 3); /* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */ static unsigned int intr_type = 0; S2IO_PARM_INT(intr_type, 0); /* Large receive offload feature */ static unsigned int lro = 0; 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) */ static unsigned int lro_max_pkts = 0xFFFF; S2IO_PARM_INT(lro_max_pkts, 0xFFFF); #ifndef CONFIG_S2IO_NAPI S2IO_PARM_INT(indicate_max_pkts, 0); #endif static unsigned int tx_fifo_len[MAX_TX_FIFOS] = {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN}; static unsigned int rx_ring_sz[MAX_RX_RINGS] = {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT}; 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); /* * S2IO device table. Loading Loading @@ -464,10 +476,9 @@ 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, "%s: Requested TxDs too high, ", __FUNCTION__); DBG_PRINT(ERR_DBG, "s2io: Requested TxDs too high, "); DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size); return FAILURE; return -EINVAL; } lst_size = (sizeof(TxD_t) * config->max_txds); Loading Loading @@ -547,6 +558,7 @@ 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; Loading Loading @@ -1213,7 +1225,7 @@ static int init_nic(struct s2io_nic *nic) break; } /* Enable Tx FIFO partition 0. */ /* 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); Loading Loading @@ -1650,7 +1662,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 * disabled all PCIX, Flash, MDIO, IIC and GPIO * disable all PCIX, Flash, MDIO, IIC and GPIO * interrupts for now. * TODO */ Loading Loading @@ -2119,7 +2131,7 @@ static struct sk_buff *s2io_txdl_getskb(fifo_info_t *fifo_data, TxD_t *txdlp, in frag->size, PCI_DMA_TODEVICE); } } txdlp->Host_Control = 0; memset(txdlp,0, (sizeof(TxD_t) * fifo_data->max_txds)); return(skb); } Loading Loading @@ -2371,9 +2383,14 @@ 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, 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 */ Loading @@ -2386,10 +2403,13 @@ 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 */ /* 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_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); Loading Loading @@ -2614,23 +2634,23 @@ static int s2io_poll(struct net_device *dev, int *budget) } #endif #ifdef CONFIG_NET_POLL_CONTROLLER /** * s2io_netpoll - Rx interrupt service handler for netpoll support * s2io_netpoll - netpoll event handler entry point * @dev : pointer to the device structure. * Description: * Polling 'interrupt' - used by things like netconsole to send skbs * without having to re-enable interrupts. It's not called while * the interrupt routine is executing. * 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). */ #ifdef CONFIG_NET_POLL_CONTROLLER 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; u64 val64 = 0xFFFFFFFFFFFFFFFFULL; int i; disable_irq(dev->irq); Loading @@ -2639,9 +2659,17 @@ static void s2io_netpoll(struct net_device *dev) mac_control = &nic->mac_control; config = &nic->config; val64 = readq(&bar0->rx_traffic_int); 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]); Loading Loading @@ -2708,7 +2736,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(ERR_DBG, "%s: Ring Full\n",dev->name); DBG_PRINT(INTR_DBG, "%s: Ring Full\n",dev->name); break; } skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control); Loading @@ -2728,18 +2756,15 @@ 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_unmap_single(nic->pdev, (dma_addr_t) pci_dma_sync_single_for_cpu(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_unmap_single(nic->pdev, (dma_addr_t) pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(nic->pdev, (dma_addr_t) Loading Loading @@ -3327,7 +3352,7 @@ static void s2io_reset(nic_t * sp) /* Clear certain PCI/PCI-X fields after reset */ if (sp->device_type == XFRAME_II_DEVICE) { /* Clear parity err detect bit */ /* Clear "detected parity error" bit */ pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000); /* Clearing PCIX Ecc status register */ Loading Loading @@ -3528,7 +3553,7 @@ static void restore_xmsi_data(nic_t *nic) u64 val64; int i; for (i=0; i< nic->avail_msix_vectors; 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)); Loading @@ -3547,7 +3572,7 @@ static void store_xmsi_data(nic_t *nic) int i; /* Store and display */ for (i=0; i< nic->avail_msix_vectors; 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)) { Loading Loading @@ -3808,13 +3833,11 @@ 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; Loading Loading @@ -3862,13 +3885,11 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } txdp->Control_1 = 0; txdp->Control_2 = 0; offload_type = s2io_offload_type(skb); #ifdef NETIF_F_TSO mss = skb_shinfo(skb)->gso_size; if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { if (offload_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { txdp->Control_1 |= TXD_TCP_LSO_EN; txdp->Control_1 |= TXD_TCP_LSO_MSS(mss); txdp->Control_1 |= TXD_TCP_LSO_MSS(s2io_tcp_mss(skb)); } #endif if (skb->ip_summed == CHECKSUM_HW) { Loading @@ -3886,10 +3907,10 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) } frg_len = skb->len - skb->data_len; if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) { if (offload_type == SKB_GSO_UDP) { int ufo_size; ufo_size = skb_shinfo(skb)->gso_size; ufo_size = s2io_udp_mss(skb); ufo_size &= ~7; txdp->Control_1 |= TXD_UFO_EN; txdp->Control_1 |= TXD_UFO_MSS(ufo_size); Loading @@ -3906,16 +3927,13 @@ 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 (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) if (offload_type == SKB_GSO_UDP) txdp->Control_1 |= TXD_UFO_EN; frg_cnt = skb_shinfo(skb)->nr_frags; Loading @@ -3930,12 +3948,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 (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) if (offload_type == SKB_GSO_UDP) txdp->Control_1 |= TXD_UFO_EN; } txdp->Control_1 |= TXD_GATHER_CODE_LAST; if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) if (offload_type == SKB_GSO_UDP) frg_cnt++; /* as Txd0 was used for inband header */ tx_fifo = mac_control->tx_FIFO_start[queue]; Loading @@ -3944,13 +3962,9 @@ 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); #ifdef NETIF_F_TSO if (mss) val64 |= TX_FIFO_SPECIAL_FUNC; #endif if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) if (offload_type) val64 |= TX_FIFO_SPECIAL_FUNC; writeq(val64, &tx_fifo->List_Control); mmiowb(); Loading Loading @@ -3984,13 +3998,41 @@ 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; Loading @@ -4012,35 +4054,8 @@ 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++) { if (!sp->lro) { 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); } } else if (fill_rx_buffers(sp, i) == -ENOMEM) { DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name); DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); break; } } for (i = 0; i < config->rx_ring_num; i++) s2io_chk_rx_buffers(sp, i); atomic_dec(&sp->isr_cnt); return IRQ_HANDLED; Loading @@ -4051,39 +4066,13 @@ 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; struct net_device *dev = (struct net_device *) dev_id; int rxb_size, level, rng_n; atomic_inc(&sp->isr_cnt); rx_intr_handler(ring); rng_n = ring->ring_no; 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 IRQ_HANDLED; } 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", dev->name); DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); } rx_intr_handler(ring); s2io_chk_rx_buffers(sp, ring->ring_no); atomic_dec(&sp->isr_cnt); return IRQ_HANDLED; } Loading Loading @@ -4248,37 +4237,8 @@ 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++) { if (!sp->lro) { 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); writeq(org_mask, &bar0->general_int_mask); return IRQ_HANDLED; } clear_bit(0, (&sp->tasklet_status)); } else if (level == LOW) { tasklet_schedule(&sp->task); } } else if (fill_rx_buffers(sp, i) == -ENOMEM) { DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name); DBG_PRINT(ERR_DBG, " in Rx intr!!\n"); break; } } for (i = 0; i < config->rx_ring_num; i++) s2io_chk_rx_buffers(sp, i); #endif writeq(org_mask, &bar0->general_int_mask); atomic_dec(&sp->isr_cnt); Loading Loading @@ -4308,6 +4268,8 @@ 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)); } } Loading Loading @@ -4942,7 +4904,8 @@ static int write_eeprom(nic_t * sp, int off, u64 data, int cnt) } static void s2io_vpd_read(nic_t *nic) { u8 vpd_data[256],data; u8 *vpd_data; u8 data; int i=0, cnt, fail = 0; int vpd_addr = 0x80; Loading @@ -4955,6 +4918,10 @@ static void s2io_vpd_read(nic_t *nic) 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); Loading @@ -4977,6 +4944,7 @@ static void s2io_vpd_read(nic_t *nic) memset(nic->product_name, 0, vpd_data[1]); memcpy(nic->product_name, &vpd_data[3], vpd_data[1]); } kfree(vpd_data); } /** Loading Loading @@ -5295,7 +5263,7 @@ static int s2io_link_test(nic_t * sp, uint64_t * data) else *data = 0; return 0; return *data; } /** Loading Loading @@ -5753,6 +5721,19 @@ 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, Loading @@ -5773,8 +5754,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 = ethtool_op_get_tso, .set_tso = ethtool_op_set_tso, .get_tso = s2io_ethtool_op_get_tso, .set_tso = s2io_ethtool_op_set_tso, #endif .get_ufo = ethtool_op_get_ufo, .set_ufo = ethtool_op_set_ufo, Loading Loading @@ -6337,7 +6318,7 @@ static int s2io_card_up(nic_t * sp) s2io_set_multicast(dev); if (sp->lro) { /* Initialize max aggregatable pkts based on MTU */ /* 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) Loading Loading @@ -6438,7 +6419,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 Tx interrupt serivce routine to perform * This function is called by the Rx 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 Loading Loading @@ -6698,33 +6679,6 @@ static void s2io_init_pci(nic_t * sp) pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd); } MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>"); 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 module_param(rxsync_frequency, int, 0); module_param(intr_type, int, 0); module_param(lro, int, 0); module_param(lro_max_pkts, int, 0); static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type) { if ( tx_fifo_num > 8) { Loading Loading @@ -6832,7 +6786,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) } if (dev_intr_type != MSI_X) { if (pci_request_regions(pdev, s2io_driver_name)) { DBG_PRINT(ERR_DBG, "Request Regions failed\n"), DBG_PRINT(ERR_DBG, "Request Regions failed\n"); pci_disable_device(pdev); return -ENODEV; } Loading Loading @@ -6957,7 +6911,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", __FUNCTION__); dev->name); ret = -ENOMEM; goto mem_alloc_failed; } Loading Loading @@ -7094,6 +7048,9 @@ 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 Loading Loading @@ -7131,11 +7088,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) goto register_failed; } s2io_vpd_read(sp); DBG_PRINT(ERR_DBG, "%s: Neterion %s",dev->name, sp->product_name); DBG_PRINT(ERR_DBG, "(rev %d), Driver version %s\n", get_xena_rev_id(sp->pdev), s2io_driver_version); 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, sp->def_mac_addr[0].mac_addr[0], Loading Loading @@ -7436,8 +7393,13 @@ static int verify_l3_l4_lro_capable(lro_t *l_lro, struct iphdr *ip, 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->ack) { tcp->ece || tcp->cwr || !tcp->ack) { /* * Currently recognize only the ack control word and * any other control field being set would result in Loading Loading @@ -7591,18 +7553,16 @@ static void queue_rx_frame(struct sk_buff *skb) static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len) { struct sk_buff *tmp, *first = lro->parent; struct sk_buff *first = lro->parent; first->len += tcp_len; first->data_len = lro->frags_len; skb_pull(skb, (skb->len - tcp_len)); if ((tmp = skb_shinfo(first)->frag_list)) { while (tmp->next) tmp = tmp->next; tmp->next = skb; } 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; } drivers/net/s2io.h +10 −0 Original line number Diff line number Diff line Loading @@ -719,6 +719,7 @@ struct msix_info_st { /* Data structure to represent a LRO session */ typedef struct lro { struct sk_buff *parent; struct sk_buff *last_frag; u8 *l2h; struct iphdr *iph; struct tcphdr *tcph; Loading Loading @@ -1011,4 +1012,13 @@ static void clear_lro_session(lro_t *lro); static void queue_rx_frame(struct sk_buff *skb); static void update_L3L4_header(nic_t *sp, lro_t *lro); static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len); #define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size #define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size #define s2io_offload_type(skb) skb_shinfo(skb)->gso_type #define S2IO_PARM_INT(X, def_val) \ static unsigned int X = def_val;\ module_param(X , uint, 0); #endif /* _S2IO_H */ Loading
drivers/net/s2io.c +173 −213 Original line number Diff line number Diff line Loading @@ -76,7 +76,7 @@ #include "s2io.h" #include "s2io-regs.h" #define DRV_VERSION "2.0.14.2" #define DRV_VERSION "2.0.15.2" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; Loading Loading @@ -370,38 +370,50 @@ static const u64 fix_mac[] = { END_SIGN }; MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); /* Module Loadable parameters. */ 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}; static unsigned int rx_ring_num = 1; static unsigned int rx_ring_sz[MAX_RX_RINGS] = {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT}; static unsigned int rts_frm_len[MAX_RX_RINGS] = {[0 ...(MAX_RX_RINGS - 1)] = 0 }; static unsigned int rx_ring_mode = 1; static unsigned int use_continuous_tx_intrs = 1; static unsigned int rmac_pause_time = 0x100; 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 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 */ static unsigned int rxsync_frequency = 3; S2IO_PARM_INT(rxsync_frequency, 3); /* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */ static unsigned int intr_type = 0; S2IO_PARM_INT(intr_type, 0); /* Large receive offload feature */ static unsigned int lro = 0; 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) */ static unsigned int lro_max_pkts = 0xFFFF; S2IO_PARM_INT(lro_max_pkts, 0xFFFF); #ifndef CONFIG_S2IO_NAPI S2IO_PARM_INT(indicate_max_pkts, 0); #endif static unsigned int tx_fifo_len[MAX_TX_FIFOS] = {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN}; static unsigned int rx_ring_sz[MAX_RX_RINGS] = {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT}; 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); /* * S2IO device table. Loading Loading @@ -464,10 +476,9 @@ 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, "%s: Requested TxDs too high, ", __FUNCTION__); DBG_PRINT(ERR_DBG, "s2io: Requested TxDs too high, "); DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size); return FAILURE; return -EINVAL; } lst_size = (sizeof(TxD_t) * config->max_txds); Loading Loading @@ -547,6 +558,7 @@ 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; Loading Loading @@ -1213,7 +1225,7 @@ static int init_nic(struct s2io_nic *nic) break; } /* Enable Tx FIFO partition 0. */ /* 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); Loading Loading @@ -1650,7 +1662,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 * disabled all PCIX, Flash, MDIO, IIC and GPIO * disable all PCIX, Flash, MDIO, IIC and GPIO * interrupts for now. * TODO */ Loading Loading @@ -2119,7 +2131,7 @@ static struct sk_buff *s2io_txdl_getskb(fifo_info_t *fifo_data, TxD_t *txdlp, in frag->size, PCI_DMA_TODEVICE); } } txdlp->Host_Control = 0; memset(txdlp,0, (sizeof(TxD_t) * fifo_data->max_txds)); return(skb); } Loading Loading @@ -2371,9 +2383,14 @@ 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, 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 */ Loading @@ -2386,10 +2403,13 @@ 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 */ /* 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_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); Loading Loading @@ -2614,23 +2634,23 @@ static int s2io_poll(struct net_device *dev, int *budget) } #endif #ifdef CONFIG_NET_POLL_CONTROLLER /** * s2io_netpoll - Rx interrupt service handler for netpoll support * s2io_netpoll - netpoll event handler entry point * @dev : pointer to the device structure. * Description: * Polling 'interrupt' - used by things like netconsole to send skbs * without having to re-enable interrupts. It's not called while * the interrupt routine is executing. * 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). */ #ifdef CONFIG_NET_POLL_CONTROLLER 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; u64 val64 = 0xFFFFFFFFFFFFFFFFULL; int i; disable_irq(dev->irq); Loading @@ -2639,9 +2659,17 @@ static void s2io_netpoll(struct net_device *dev) mac_control = &nic->mac_control; config = &nic->config; val64 = readq(&bar0->rx_traffic_int); 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]); Loading Loading @@ -2708,7 +2736,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(ERR_DBG, "%s: Ring Full\n",dev->name); DBG_PRINT(INTR_DBG, "%s: Ring Full\n",dev->name); break; } skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control); Loading @@ -2728,18 +2756,15 @@ 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_unmap_single(nic->pdev, (dma_addr_t) pci_dma_sync_single_for_cpu(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_unmap_single(nic->pdev, (dma_addr_t) pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(nic->pdev, (dma_addr_t) Loading Loading @@ -3327,7 +3352,7 @@ static void s2io_reset(nic_t * sp) /* Clear certain PCI/PCI-X fields after reset */ if (sp->device_type == XFRAME_II_DEVICE) { /* Clear parity err detect bit */ /* Clear "detected parity error" bit */ pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000); /* Clearing PCIX Ecc status register */ Loading Loading @@ -3528,7 +3553,7 @@ static void restore_xmsi_data(nic_t *nic) u64 val64; int i; for (i=0; i< nic->avail_msix_vectors; 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)); Loading @@ -3547,7 +3572,7 @@ static void store_xmsi_data(nic_t *nic) int i; /* Store and display */ for (i=0; i< nic->avail_msix_vectors; 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)) { Loading Loading @@ -3808,13 +3833,11 @@ 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; Loading Loading @@ -3862,13 +3885,11 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } txdp->Control_1 = 0; txdp->Control_2 = 0; offload_type = s2io_offload_type(skb); #ifdef NETIF_F_TSO mss = skb_shinfo(skb)->gso_size; if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { if (offload_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { txdp->Control_1 |= TXD_TCP_LSO_EN; txdp->Control_1 |= TXD_TCP_LSO_MSS(mss); txdp->Control_1 |= TXD_TCP_LSO_MSS(s2io_tcp_mss(skb)); } #endif if (skb->ip_summed == CHECKSUM_HW) { Loading @@ -3886,10 +3907,10 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) } frg_len = skb->len - skb->data_len; if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) { if (offload_type == SKB_GSO_UDP) { int ufo_size; ufo_size = skb_shinfo(skb)->gso_size; ufo_size = s2io_udp_mss(skb); ufo_size &= ~7; txdp->Control_1 |= TXD_UFO_EN; txdp->Control_1 |= TXD_UFO_MSS(ufo_size); Loading @@ -3906,16 +3927,13 @@ 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 (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) if (offload_type == SKB_GSO_UDP) txdp->Control_1 |= TXD_UFO_EN; frg_cnt = skb_shinfo(skb)->nr_frags; Loading @@ -3930,12 +3948,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 (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) if (offload_type == SKB_GSO_UDP) txdp->Control_1 |= TXD_UFO_EN; } txdp->Control_1 |= TXD_GATHER_CODE_LAST; if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) if (offload_type == SKB_GSO_UDP) frg_cnt++; /* as Txd0 was used for inband header */ tx_fifo = mac_control->tx_FIFO_start[queue]; Loading @@ -3944,13 +3962,9 @@ 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); #ifdef NETIF_F_TSO if (mss) val64 |= TX_FIFO_SPECIAL_FUNC; #endif if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) if (offload_type) val64 |= TX_FIFO_SPECIAL_FUNC; writeq(val64, &tx_fifo->List_Control); mmiowb(); Loading Loading @@ -3984,13 +3998,41 @@ 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; Loading @@ -4012,35 +4054,8 @@ 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++) { if (!sp->lro) { 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); } } else if (fill_rx_buffers(sp, i) == -ENOMEM) { DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name); DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); break; } } for (i = 0; i < config->rx_ring_num; i++) s2io_chk_rx_buffers(sp, i); atomic_dec(&sp->isr_cnt); return IRQ_HANDLED; Loading @@ -4051,39 +4066,13 @@ 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; struct net_device *dev = (struct net_device *) dev_id; int rxb_size, level, rng_n; atomic_inc(&sp->isr_cnt); rx_intr_handler(ring); rng_n = ring->ring_no; 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 IRQ_HANDLED; } 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", dev->name); DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); } rx_intr_handler(ring); s2io_chk_rx_buffers(sp, ring->ring_no); atomic_dec(&sp->isr_cnt); return IRQ_HANDLED; } Loading Loading @@ -4248,37 +4237,8 @@ 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++) { if (!sp->lro) { 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); writeq(org_mask, &bar0->general_int_mask); return IRQ_HANDLED; } clear_bit(0, (&sp->tasklet_status)); } else if (level == LOW) { tasklet_schedule(&sp->task); } } else if (fill_rx_buffers(sp, i) == -ENOMEM) { DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name); DBG_PRINT(ERR_DBG, " in Rx intr!!\n"); break; } } for (i = 0; i < config->rx_ring_num; i++) s2io_chk_rx_buffers(sp, i); #endif writeq(org_mask, &bar0->general_int_mask); atomic_dec(&sp->isr_cnt); Loading Loading @@ -4308,6 +4268,8 @@ 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)); } } Loading Loading @@ -4942,7 +4904,8 @@ static int write_eeprom(nic_t * sp, int off, u64 data, int cnt) } static void s2io_vpd_read(nic_t *nic) { u8 vpd_data[256],data; u8 *vpd_data; u8 data; int i=0, cnt, fail = 0; int vpd_addr = 0x80; Loading @@ -4955,6 +4918,10 @@ static void s2io_vpd_read(nic_t *nic) 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); Loading @@ -4977,6 +4944,7 @@ static void s2io_vpd_read(nic_t *nic) memset(nic->product_name, 0, vpd_data[1]); memcpy(nic->product_name, &vpd_data[3], vpd_data[1]); } kfree(vpd_data); } /** Loading Loading @@ -5295,7 +5263,7 @@ static int s2io_link_test(nic_t * sp, uint64_t * data) else *data = 0; return 0; return *data; } /** Loading Loading @@ -5753,6 +5721,19 @@ 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, Loading @@ -5773,8 +5754,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 = ethtool_op_get_tso, .set_tso = ethtool_op_set_tso, .get_tso = s2io_ethtool_op_get_tso, .set_tso = s2io_ethtool_op_set_tso, #endif .get_ufo = ethtool_op_get_ufo, .set_ufo = ethtool_op_set_ufo, Loading Loading @@ -6337,7 +6318,7 @@ static int s2io_card_up(nic_t * sp) s2io_set_multicast(dev); if (sp->lro) { /* Initialize max aggregatable pkts based on MTU */ /* 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) Loading Loading @@ -6438,7 +6419,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 Tx interrupt serivce routine to perform * This function is called by the Rx 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 Loading Loading @@ -6698,33 +6679,6 @@ static void s2io_init_pci(nic_t * sp) pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd); } MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>"); 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 module_param(rxsync_frequency, int, 0); module_param(intr_type, int, 0); module_param(lro, int, 0); module_param(lro_max_pkts, int, 0); static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type) { if ( tx_fifo_num > 8) { Loading Loading @@ -6832,7 +6786,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) } if (dev_intr_type != MSI_X) { if (pci_request_regions(pdev, s2io_driver_name)) { DBG_PRINT(ERR_DBG, "Request Regions failed\n"), DBG_PRINT(ERR_DBG, "Request Regions failed\n"); pci_disable_device(pdev); return -ENODEV; } Loading Loading @@ -6957,7 +6911,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", __FUNCTION__); dev->name); ret = -ENOMEM; goto mem_alloc_failed; } Loading Loading @@ -7094,6 +7048,9 @@ 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 Loading Loading @@ -7131,11 +7088,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) goto register_failed; } s2io_vpd_read(sp); DBG_PRINT(ERR_DBG, "%s: Neterion %s",dev->name, sp->product_name); DBG_PRINT(ERR_DBG, "(rev %d), Driver version %s\n", get_xena_rev_id(sp->pdev), s2io_driver_version); 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, sp->def_mac_addr[0].mac_addr[0], Loading Loading @@ -7436,8 +7393,13 @@ static int verify_l3_l4_lro_capable(lro_t *l_lro, struct iphdr *ip, 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->ack) { tcp->ece || tcp->cwr || !tcp->ack) { /* * Currently recognize only the ack control word and * any other control field being set would result in Loading Loading @@ -7591,18 +7553,16 @@ static void queue_rx_frame(struct sk_buff *skb) static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len) { struct sk_buff *tmp, *first = lro->parent; struct sk_buff *first = lro->parent; first->len += tcp_len; first->data_len = lro->frags_len; skb_pull(skb, (skb->len - tcp_len)); if ((tmp = skb_shinfo(first)->frag_list)) { while (tmp->next) tmp = tmp->next; tmp->next = skb; } 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; }
drivers/net/s2io.h +10 −0 Original line number Diff line number Diff line Loading @@ -719,6 +719,7 @@ struct msix_info_st { /* Data structure to represent a LRO session */ typedef struct lro { struct sk_buff *parent; struct sk_buff *last_frag; u8 *l2h; struct iphdr *iph; struct tcphdr *tcph; Loading Loading @@ -1011,4 +1012,13 @@ static void clear_lro_session(lro_t *lro); static void queue_rx_frame(struct sk_buff *skb); static void update_L3L4_header(nic_t *sp, lro_t *lro); static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len); #define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size #define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size #define s2io_offload_type(skb) skb_shinfo(skb)->gso_type #define S2IO_PARM_INT(X, def_val) \ static unsigned int X = def_val;\ module_param(X , uint, 0); #endif /* _S2IO_H */