diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/s2io.c | 186 | ||||
-rw-r--r-- | drivers/net/s2io.h | 3 |
2 files changed, 112 insertions, 77 deletions
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index e57df8dfe6b4..5303a96b4327 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c | |||
@@ -66,7 +66,7 @@ | |||
66 | #include "s2io.h" | 66 | #include "s2io.h" |
67 | #include "s2io-regs.h" | 67 | #include "s2io-regs.h" |
68 | 68 | ||
69 | #define DRV_VERSION "Version 2.0.9.3" | 69 | #define DRV_VERSION "Version 2.0.9.4" |
70 | 70 | ||
71 | /* S2io Driver name & version. */ | 71 | /* S2io Driver name & version. */ |
72 | static char s2io_driver_name[] = "Neterion"; | 72 | static char s2io_driver_name[] = "Neterion"; |
@@ -412,7 +412,7 @@ static int init_shared_mem(struct s2io_nic *nic) | |||
412 | config->tx_cfg[i].fifo_len - 1; | 412 | config->tx_cfg[i].fifo_len - 1; |
413 | mac_control->fifos[i].fifo_no = i; | 413 | mac_control->fifos[i].fifo_no = i; |
414 | mac_control->fifos[i].nic = nic; | 414 | mac_control->fifos[i].nic = nic; |
415 | mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 1; | 415 | mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 2; |
416 | 416 | ||
417 | for (j = 0; j < page_num; j++) { | 417 | for (j = 0; j < page_num; j++) { |
418 | int k = 0; | 418 | int k = 0; |
@@ -459,6 +459,10 @@ static int init_shared_mem(struct s2io_nic *nic) | |||
459 | } | 459 | } |
460 | } | 460 | } |
461 | 461 | ||
462 | nic->ufo_in_band_v = kmalloc((sizeof(u64) * size), GFP_KERNEL); | ||
463 | if (!nic->ufo_in_band_v) | ||
464 | return -ENOMEM; | ||
465 | |||
462 | /* Allocation and initialization of RXDs in Rings */ | 466 | /* Allocation and initialization of RXDs in Rings */ |
463 | size = 0; | 467 | size = 0; |
464 | for (i = 0; i < config->rx_ring_num; i++) { | 468 | for (i = 0; i < config->rx_ring_num; i++) { |
@@ -731,6 +735,8 @@ static void free_shared_mem(struct s2io_nic *nic) | |||
731 | mac_control->stats_mem, | 735 | mac_control->stats_mem, |
732 | mac_control->stats_mem_phy); | 736 | mac_control->stats_mem_phy); |
733 | } | 737 | } |
738 | if (nic->ufo_in_band_v) | ||
739 | kfree(nic->ufo_in_band_v); | ||
734 | } | 740 | } |
735 | 741 | ||
736 | /** | 742 | /** |
@@ -2003,6 +2009,49 @@ static int start_nic(struct s2io_nic *nic) | |||
2003 | 2009 | ||
2004 | return SUCCESS; | 2010 | return SUCCESS; |
2005 | } | 2011 | } |
2012 | /** | ||
2013 | * s2io_txdl_getskb - Get the skb from txdl, unmap and return skb | ||
2014 | */ | ||
2015 | static struct sk_buff *s2io_txdl_getskb(fifo_info_t *fifo_data, TxD_t *txdlp, int get_off) | ||
2016 | { | ||
2017 | nic_t *nic = fifo_data->nic; | ||
2018 | struct sk_buff *skb; | ||
2019 | TxD_t *txds; | ||
2020 | u16 j, frg_cnt; | ||
2021 | |||
2022 | txds = txdlp; | ||
2023 | if (txds->Host_Control == (u64) nic->ufo_in_band_v) { | ||
2024 | pci_unmap_single(nic->pdev, (dma_addr_t) | ||
2025 | txds->Buffer_Pointer, sizeof(u64), | ||
2026 | PCI_DMA_TODEVICE); | ||
2027 | txds++; | ||
2028 | } | ||
2029 | |||
2030 | skb = (struct sk_buff *) ((unsigned long) | ||
2031 | txds->Host_Control); | ||
2032 | if (!skb) { | ||
2033 | memset(txdlp, 0, (sizeof(TxD_t) * fifo_data->max_txds)); | ||
2034 | return NULL; | ||
2035 | } | ||
2036 | pci_unmap_single(nic->pdev, (dma_addr_t) | ||
2037 | txds->Buffer_Pointer, | ||
2038 | skb->len - skb->data_len, | ||
2039 | PCI_DMA_TODEVICE); | ||
2040 | frg_cnt = skb_shinfo(skb)->nr_frags; | ||
2041 | if (frg_cnt) { | ||
2042 | txds++; | ||
2043 | for (j = 0; j < frg_cnt; j++, txds++) { | ||
2044 | skb_frag_t *frag = &skb_shinfo(skb)->frags[j]; | ||
2045 | if (!txds->Buffer_Pointer) | ||
2046 | break; | ||
2047 | pci_unmap_page(nic->pdev, (dma_addr_t) | ||
2048 | txds->Buffer_Pointer, | ||
2049 | frag->size, PCI_DMA_TODEVICE); | ||
2050 | } | ||
2051 | } | ||
2052 | txdlp->Host_Control = 0; | ||
2053 | return(skb); | ||
2054 | } | ||
2006 | 2055 | ||
2007 | /** | 2056 | /** |
2008 | * free_tx_buffers - Free all queued Tx buffers | 2057 | * free_tx_buffers - Free all queued Tx buffers |
@@ -2020,7 +2069,7 @@ static void free_tx_buffers(struct s2io_nic *nic) | |||
2020 | int i, j; | 2069 | int i, j; |
2021 | mac_info_t *mac_control; | 2070 | mac_info_t *mac_control; |
2022 | struct config_param *config; | 2071 | struct config_param *config; |
2023 | int cnt = 0, frg_cnt; | 2072 | int cnt = 0; |
2024 | 2073 | ||
2025 | mac_control = &nic->mac_control; | 2074 | mac_control = &nic->mac_control; |
2026 | config = &nic->config; | 2075 | config = &nic->config; |
@@ -2029,38 +2078,11 @@ static void free_tx_buffers(struct s2io_nic *nic) | |||
2029 | for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) { | 2078 | for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) { |
2030 | txdp = (TxD_t *) mac_control->fifos[i].list_info[j]. | 2079 | txdp = (TxD_t *) mac_control->fifos[i].list_info[j]. |
2031 | list_virt_addr; | 2080 | list_virt_addr; |
2032 | skb = | 2081 | skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j); |
2033 | (struct sk_buff *) ((unsigned long) txdp-> | 2082 | if (skb) { |
2034 | Host_Control); | 2083 | dev_kfree_skb(skb); |
2035 | if (skb == NULL) { | 2084 | cnt++; |
2036 | memset(txdp, 0, sizeof(TxD_t) * | ||
2037 | config->max_txds); | ||
2038 | continue; | ||
2039 | } | ||
2040 | frg_cnt = skb_shinfo(skb)->nr_frags; | ||
2041 | pci_unmap_single(nic->pdev, (dma_addr_t) | ||
2042 | txdp->Buffer_Pointer, | ||
2043 | skb->len - skb->data_len, | ||
2044 | PCI_DMA_TODEVICE); | ||
2045 | if (frg_cnt) { | ||
2046 | TxD_t *temp; | ||
2047 | temp = txdp; | ||
2048 | txdp++; | ||
2049 | for (j = 0; j < frg_cnt; j++, txdp++) { | ||
2050 | skb_frag_t *frag = | ||
2051 | &skb_shinfo(skb)->frags[j]; | ||
2052 | pci_unmap_page(nic->pdev, | ||
2053 | (dma_addr_t) | ||
2054 | txdp-> | ||
2055 | Buffer_Pointer, | ||
2056 | frag->size, | ||
2057 | PCI_DMA_TODEVICE); | ||
2058 | } | ||
2059 | txdp = temp; | ||
2060 | } | 2085 | } |
2061 | dev_kfree_skb(skb); | ||
2062 | memset(txdp, 0, sizeof(TxD_t) * config->max_txds); | ||
2063 | cnt++; | ||
2064 | } | 2086 | } |
2065 | DBG_PRINT(INTR_DBG, | 2087 | DBG_PRINT(INTR_DBG, |
2066 | "%s:forcibly freeing %d skbs on FIFO%d\n", | 2088 | "%s:forcibly freeing %d skbs on FIFO%d\n", |
@@ -2661,7 +2683,6 @@ static void tx_intr_handler(fifo_info_t *fifo_data) | |||
2661 | tx_curr_get_info_t get_info, put_info; | 2683 | tx_curr_get_info_t get_info, put_info; |
2662 | struct sk_buff *skb; | 2684 | struct sk_buff *skb; |
2663 | TxD_t *txdlp; | 2685 | TxD_t *txdlp; |
2664 | u16 j, frg_cnt; | ||
2665 | 2686 | ||
2666 | get_info = fifo_data->tx_curr_get_info; | 2687 | get_info = fifo_data->tx_curr_get_info; |
2667 | put_info = fifo_data->tx_curr_put_info; | 2688 | put_info = fifo_data->tx_curr_put_info; |
@@ -2684,8 +2705,7 @@ to loss of link\n"); | |||
2684 | } | 2705 | } |
2685 | } | 2706 | } |
2686 | 2707 | ||
2687 | skb = (struct sk_buff *) ((unsigned long) | 2708 | skb = s2io_txdl_getskb(fifo_data, txdlp, get_info.offset); |
2688 | txdlp->Host_Control); | ||
2689 | if (skb == NULL) { | 2709 | if (skb == NULL) { |
2690 | DBG_PRINT(ERR_DBG, "%s: Null skb ", | 2710 | DBG_PRINT(ERR_DBG, "%s: Null skb ", |
2691 | __FUNCTION__); | 2711 | __FUNCTION__); |
@@ -2693,34 +2713,6 @@ to loss of link\n"); | |||
2693 | return; | 2713 | return; |
2694 | } | 2714 | } |
2695 | 2715 | ||
2696 | frg_cnt = skb_shinfo(skb)->nr_frags; | ||
2697 | nic->tx_pkt_count++; | ||
2698 | |||
2699 | pci_unmap_single(nic->pdev, (dma_addr_t) | ||
2700 | txdlp->Buffer_Pointer, | ||
2701 | skb->len - skb->data_len, | ||
2702 | PCI_DMA_TODEVICE); | ||
2703 | if (frg_cnt) { | ||
2704 | TxD_t *temp; | ||
2705 | temp = txdlp; | ||
2706 | txdlp++; | ||
2707 | for (j = 0; j < frg_cnt; j++, txdlp++) { | ||
2708 | skb_frag_t *frag = | ||
2709 | &skb_shinfo(skb)->frags[j]; | ||
2710 | if (!txdlp->Buffer_Pointer) | ||
2711 | break; | ||
2712 | pci_unmap_page(nic->pdev, | ||
2713 | (dma_addr_t) | ||
2714 | txdlp-> | ||
2715 | Buffer_Pointer, | ||
2716 | frag->size, | ||
2717 | PCI_DMA_TODEVICE); | ||
2718 | } | ||
2719 | txdlp = temp; | ||
2720 | } | ||
2721 | memset(txdlp, 0, | ||
2722 | (sizeof(TxD_t) * fifo_data->max_txds)); | ||
2723 | |||
2724 | /* Updating the statistics block */ | 2716 | /* Updating the statistics block */ |
2725 | nic->stats.tx_bytes += skb->len; | 2717 | nic->stats.tx_bytes += skb->len; |
2726 | dev_kfree_skb_irq(skb); | 2718 | dev_kfree_skb_irq(skb); |
@@ -3527,6 +3519,8 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3527 | return 0; | 3519 | return 0; |
3528 | } | 3520 | } |
3529 | 3521 | ||
3522 | txdp->Control_1 = 0; | ||
3523 | txdp->Control_2 = 0; | ||
3530 | #ifdef NETIF_F_TSO | 3524 | #ifdef NETIF_F_TSO |
3531 | mss = skb_shinfo(skb)->tso_size; | 3525 | mss = skb_shinfo(skb)->tso_size; |
3532 | if (mss) { | 3526 | if (mss) { |
@@ -3534,19 +3528,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3534 | txdp->Control_1 |= TXD_TCP_LSO_MSS(mss); | 3528 | txdp->Control_1 |= TXD_TCP_LSO_MSS(mss); |
3535 | } | 3529 | } |
3536 | #endif | 3530 | #endif |
3537 | |||
3538 | frg_cnt = skb_shinfo(skb)->nr_frags; | ||
3539 | frg_len = skb->len - skb->data_len; | ||
3540 | |||
3541 | txdp->Buffer_Pointer = pci_map_single | ||
3542 | (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE); | ||
3543 | txdp->Host_Control = (unsigned long) skb; | ||
3544 | if (skb->ip_summed == CHECKSUM_HW) { | 3531 | if (skb->ip_summed == CHECKSUM_HW) { |
3545 | txdp->Control_2 |= | 3532 | txdp->Control_2 |= |
3546 | (TXD_TX_CKO_IPV4_EN | TXD_TX_CKO_TCP_EN | | 3533 | (TXD_TX_CKO_IPV4_EN | TXD_TX_CKO_TCP_EN | |
3547 | TXD_TX_CKO_UDP_EN); | 3534 | TXD_TX_CKO_UDP_EN); |
3548 | } | 3535 | } |
3549 | 3536 | txdp->Control_1 |= TXD_GATHER_CODE_FIRST; | |
3537 | txdp->Control_1 |= TXD_LIST_OWN_XENA; | ||
3550 | txdp->Control_2 |= config->tx_intr_type; | 3538 | txdp->Control_2 |= config->tx_intr_type; |
3551 | 3539 | ||
3552 | if (sp->vlgrp && vlan_tx_tag_present(skb)) { | 3540 | if (sp->vlgrp && vlan_tx_tag_present(skb)) { |
@@ -3554,10 +3542,40 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3554 | txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag); | 3542 | txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag); |
3555 | } | 3543 | } |
3556 | 3544 | ||
3557 | txdp->Control_1 |= (TXD_BUFFER0_SIZE(frg_len) | | 3545 | frg_len = skb->len - skb->data_len; |
3558 | TXD_GATHER_CODE_FIRST); | 3546 | if (skb_shinfo(skb)->ufo_size) { |
3559 | txdp->Control_1 |= TXD_LIST_OWN_XENA; | 3547 | int ufo_size; |
3548 | |||
3549 | ufo_size = skb_shinfo(skb)->ufo_size; | ||
3550 | ufo_size &= ~7; | ||
3551 | txdp->Control_1 |= TXD_UFO_EN; | ||
3552 | txdp->Control_1 |= TXD_UFO_MSS(ufo_size); | ||
3553 | txdp->Control_1 |= TXD_BUFFER0_SIZE(8); | ||
3554 | #ifdef __BIG_ENDIAN | ||
3555 | sp->ufo_in_band_v[put_off] = | ||
3556 | (u64)skb_shinfo(skb)->ip6_frag_id; | ||
3557 | #else | ||
3558 | sp->ufo_in_band_v[put_off] = | ||
3559 | (u64)skb_shinfo(skb)->ip6_frag_id << 32; | ||
3560 | #endif | ||
3561 | txdp->Host_Control = (unsigned long)sp->ufo_in_band_v; | ||
3562 | txdp->Buffer_Pointer = pci_map_single(sp->pdev, | ||
3563 | sp->ufo_in_band_v, | ||
3564 | sizeof(u64), PCI_DMA_TODEVICE); | ||
3565 | txdp++; | ||
3566 | txdp->Control_1 = 0; | ||
3567 | txdp->Control_2 = 0; | ||
3568 | } | ||
3569 | |||
3570 | txdp->Buffer_Pointer = pci_map_single | ||
3571 | (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE); | ||
3572 | txdp->Host_Control = (unsigned long) skb; | ||
3573 | txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len); | ||
3560 | 3574 | ||
3575 | if (skb_shinfo(skb)->ufo_size) | ||
3576 | txdp->Control_1 |= TXD_UFO_EN; | ||
3577 | |||
3578 | frg_cnt = skb_shinfo(skb)->nr_frags; | ||
3561 | /* For fragmented SKB. */ | 3579 | /* For fragmented SKB. */ |
3562 | for (i = 0; i < frg_cnt; i++) { | 3580 | for (i = 0; i < frg_cnt; i++) { |
3563 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; | 3581 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; |
@@ -3569,9 +3587,14 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3569 | (sp->pdev, frag->page, frag->page_offset, | 3587 | (sp->pdev, frag->page, frag->page_offset, |
3570 | frag->size, PCI_DMA_TODEVICE); | 3588 | frag->size, PCI_DMA_TODEVICE); |
3571 | txdp->Control_1 |= TXD_BUFFER0_SIZE(frag->size); | 3589 | txdp->Control_1 |= TXD_BUFFER0_SIZE(frag->size); |
3590 | if (skb_shinfo(skb)->ufo_size) | ||
3591 | txdp->Control_1 |= TXD_UFO_EN; | ||
3572 | } | 3592 | } |
3573 | txdp->Control_1 |= TXD_GATHER_CODE_LAST; | 3593 | txdp->Control_1 |= TXD_GATHER_CODE_LAST; |
3574 | 3594 | ||
3595 | if (skb_shinfo(skb)->ufo_size) | ||
3596 | frg_cnt++; /* as Txd0 was used for inband header */ | ||
3597 | |||
3575 | tx_fifo = mac_control->tx_FIFO_start[queue]; | 3598 | tx_fifo = mac_control->tx_FIFO_start[queue]; |
3576 | val64 = mac_control->fifos[queue].list_info[put_off].list_phy_addr; | 3599 | val64 = mac_control->fifos[queue].list_info[put_off].list_phy_addr; |
3577 | writeq(val64, &tx_fifo->TxDL_Pointer); | 3600 | writeq(val64, &tx_fifo->TxDL_Pointer); |
@@ -3583,6 +3606,8 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3583 | if (mss) | 3606 | if (mss) |
3584 | val64 |= TX_FIFO_SPECIAL_FUNC; | 3607 | val64 |= TX_FIFO_SPECIAL_FUNC; |
3585 | #endif | 3608 | #endif |
3609 | if (skb_shinfo(skb)->ufo_size) | ||
3610 | val64 |= TX_FIFO_SPECIAL_FUNC; | ||
3586 | writeq(val64, &tx_fifo->List_Control); | 3611 | writeq(val64, &tx_fifo->List_Control); |
3587 | 3612 | ||
3588 | mmiowb(); | 3613 | mmiowb(); |
@@ -5190,6 +5215,8 @@ static struct ethtool_ops netdev_ethtool_ops = { | |||
5190 | .get_tso = ethtool_op_get_tso, | 5215 | .get_tso = ethtool_op_get_tso, |
5191 | .set_tso = ethtool_op_set_tso, | 5216 | .set_tso = ethtool_op_set_tso, |
5192 | #endif | 5217 | #endif |
5218 | .get_ufo = ethtool_op_get_ufo, | ||
5219 | .set_ufo = ethtool_op_set_ufo, | ||
5193 | .self_test_count = s2io_ethtool_self_test_count, | 5220 | .self_test_count = s2io_ethtool_self_test_count, |
5194 | .self_test = s2io_ethtool_test, | 5221 | .self_test = s2io_ethtool_test, |
5195 | .get_strings = s2io_ethtool_get_strings, | 5222 | .get_strings = s2io_ethtool_get_strings, |
@@ -5941,7 +5968,8 @@ Defaulting to INTA\n"); | |||
5941 | break; | 5968 | break; |
5942 | } | 5969 | } |
5943 | } | 5970 | } |
5944 | config->max_txds = MAX_SKB_FRAGS + 1; | 5971 | /* + 2 because one Txd for skb->data and one Txd for UFO */ |
5972 | config->max_txds = MAX_SKB_FRAGS + 2; | ||
5945 | 5973 | ||
5946 | /* Rx side parameters. */ | 5974 | /* Rx side parameters. */ |
5947 | if (rx_ring_sz[0] == 0) | 5975 | if (rx_ring_sz[0] == 0) |
@@ -6035,6 +6063,10 @@ Defaulting to INTA\n"); | |||
6035 | #ifdef NETIF_F_TSO | 6063 | #ifdef NETIF_F_TSO |
6036 | dev->features |= NETIF_F_TSO; | 6064 | dev->features |= NETIF_F_TSO; |
6037 | #endif | 6065 | #endif |
6066 | if (sp->device_type & XFRAME_II_DEVICE) { | ||
6067 | dev->features |= NETIF_F_UFO; | ||
6068 | dev->features |= NETIF_F_HW_CSUM; | ||
6069 | } | ||
6038 | 6070 | ||
6039 | dev->tx_timeout = &s2io_tx_watchdog; | 6071 | dev->tx_timeout = &s2io_tx_watchdog; |
6040 | dev->watchdog_timeo = WATCH_DOG_TIMEOUT; | 6072 | dev->watchdog_timeo = WATCH_DOG_TIMEOUT; |
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 419aad7f10e7..852a6a899d07 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h | |||
@@ -393,7 +393,9 @@ typedef struct _TxD { | |||
393 | #define TXD_GATHER_CODE_LAST BIT(23) | 393 | #define TXD_GATHER_CODE_LAST BIT(23) |
394 | #define TXD_TCP_LSO_EN BIT(30) | 394 | #define TXD_TCP_LSO_EN BIT(30) |
395 | #define TXD_UDP_COF_EN BIT(31) | 395 | #define TXD_UDP_COF_EN BIT(31) |
396 | #define TXD_UFO_EN BIT(31) | BIT(30) | ||
396 | #define TXD_TCP_LSO_MSS(val) vBIT(val,34,14) | 397 | #define TXD_TCP_LSO_MSS(val) vBIT(val,34,14) |
398 | #define TXD_UFO_MSS(val) vBIT(val,34,14) | ||
397 | #define TXD_BUFFER0_SIZE(val) vBIT(val,48,16) | 399 | #define TXD_BUFFER0_SIZE(val) vBIT(val,48,16) |
398 | 400 | ||
399 | u64 Control_2; | 401 | u64 Control_2; |
@@ -789,6 +791,7 @@ struct s2io_nic { | |||
789 | 791 | ||
790 | spinlock_t rx_lock; | 792 | spinlock_t rx_lock; |
791 | atomic_t isr_cnt; | 793 | atomic_t isr_cnt; |
794 | u64 *ufo_in_band_v; | ||
792 | }; | 795 | }; |
793 | 796 | ||
794 | #define RESET_ERROR 1; | 797 | #define RESET_ERROR 1; |