Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] s2io: UFO support

This patch implements the UFO support in S2io driver. This patch uses the UFO
interface available in linux-2.6.15 kernel.

Signed-off-by: Ananda Raju <ananda.raju@neterion.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>

authored by

Ananda Raju and committed by
Jeff Garzik
fed5eccd 1f8fc993

+112 -77
+109 -77
drivers/net/s2io.c
··· 66 66 #include "s2io.h" 67 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 71 /* S2io Driver name & version. */ 72 72 static char s2io_driver_name[] = "Neterion"; ··· 412 412 config->tx_cfg[i].fifo_len - 1; 413 413 mac_control->fifos[i].fifo_no = i; 414 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 417 for (j = 0; j < page_num; j++) { 418 418 int k = 0; ··· 458 458 } 459 459 } 460 460 } 461 + 462 + nic->ufo_in_band_v = kmalloc((sizeof(u64) * size), GFP_KERNEL); 463 + if (!nic->ufo_in_band_v) 464 + return -ENOMEM; 461 465 462 466 /* Allocation and initialization of RXDs in Rings */ 463 467 size = 0; ··· 735 731 mac_control->stats_mem, 736 732 mac_control->stats_mem_phy); 737 733 } 734 + if (nic->ufo_in_band_v) 735 + kfree(nic->ufo_in_band_v); 738 736 } 739 737 740 738 /** ··· 2009 2003 2010 2004 return SUCCESS; 2011 2005 } 2006 + /** 2007 + * s2io_txdl_getskb - Get the skb from txdl, unmap and return skb 2008 + */ 2009 + static struct sk_buff *s2io_txdl_getskb(fifo_info_t *fifo_data, TxD_t *txdlp, int get_off) 2010 + { 2011 + nic_t *nic = fifo_data->nic; 2012 + struct sk_buff *skb; 2013 + TxD_t *txds; 2014 + u16 j, frg_cnt; 2015 + 2016 + txds = txdlp; 2017 + if (txds->Host_Control == (u64) nic->ufo_in_band_v) { 2018 + pci_unmap_single(nic->pdev, (dma_addr_t) 2019 + txds->Buffer_Pointer, sizeof(u64), 2020 + PCI_DMA_TODEVICE); 2021 + txds++; 2022 + } 2023 + 2024 + skb = (struct sk_buff *) ((unsigned long) 2025 + txds->Host_Control); 2026 + if (!skb) { 2027 + memset(txdlp, 0, (sizeof(TxD_t) * fifo_data->max_txds)); 2028 + return NULL; 2029 + } 2030 + pci_unmap_single(nic->pdev, (dma_addr_t) 2031 + txds->Buffer_Pointer, 2032 + skb->len - skb->data_len, 2033 + PCI_DMA_TODEVICE); 2034 + frg_cnt = skb_shinfo(skb)->nr_frags; 2035 + if (frg_cnt) { 2036 + txds++; 2037 + for (j = 0; j < frg_cnt; j++, txds++) { 2038 + skb_frag_t *frag = &skb_shinfo(skb)->frags[j]; 2039 + if (!txds->Buffer_Pointer) 2040 + break; 2041 + pci_unmap_page(nic->pdev, (dma_addr_t) 2042 + txds->Buffer_Pointer, 2043 + frag->size, PCI_DMA_TODEVICE); 2044 + } 2045 + } 2046 + txdlp->Host_Control = 0; 2047 + return(skb); 2048 + } 2012 2049 2013 2050 /** 2014 2051 * free_tx_buffers - Free all queued Tx buffers ··· 2069 2020 int i, j; 2070 2021 mac_info_t *mac_control; 2071 2022 struct config_param *config; 2072 - int cnt = 0, frg_cnt; 2023 + int cnt = 0; 2073 2024 2074 2025 mac_control = &nic->mac_control; 2075 2026 config = &nic->config; ··· 2078 2029 for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) { 2079 2030 txdp = (TxD_t *) mac_control->fifos[i].list_info[j]. 2080 2031 list_virt_addr; 2081 - skb = 2082 - (struct sk_buff *) ((unsigned long) txdp-> 2083 - Host_Control); 2084 - if (skb == NULL) { 2085 - memset(txdp, 0, sizeof(TxD_t) * 2086 - config->max_txds); 2087 - continue; 2032 + skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j); 2033 + if (skb) { 2034 + dev_kfree_skb(skb); 2035 + cnt++; 2088 2036 } 2089 - frg_cnt = skb_shinfo(skb)->nr_frags; 2090 - pci_unmap_single(nic->pdev, (dma_addr_t) 2091 - txdp->Buffer_Pointer, 2092 - skb->len - skb->data_len, 2093 - PCI_DMA_TODEVICE); 2094 - if (frg_cnt) { 2095 - TxD_t *temp; 2096 - temp = txdp; 2097 - txdp++; 2098 - for (j = 0; j < frg_cnt; j++, txdp++) { 2099 - skb_frag_t *frag = 2100 - &skb_shinfo(skb)->frags[j]; 2101 - pci_unmap_page(nic->pdev, 2102 - (dma_addr_t) 2103 - txdp-> 2104 - Buffer_Pointer, 2105 - frag->size, 2106 - PCI_DMA_TODEVICE); 2107 - } 2108 - txdp = temp; 2109 - } 2110 - dev_kfree_skb(skb); 2111 - memset(txdp, 0, sizeof(TxD_t) * config->max_txds); 2112 - cnt++; 2113 2037 } 2114 2038 DBG_PRINT(INTR_DBG, 2115 2039 "%s:forcibly freeing %d skbs on FIFO%d\n", ··· 2683 2661 tx_curr_get_info_t get_info, put_info; 2684 2662 struct sk_buff *skb; 2685 2663 TxD_t *txdlp; 2686 - u16 j, frg_cnt; 2687 2664 2688 2665 get_info = fifo_data->tx_curr_get_info; 2689 2666 put_info = fifo_data->tx_curr_put_info; ··· 2705 2684 } 2706 2685 } 2707 2686 2708 - skb = (struct sk_buff *) ((unsigned long) 2709 - txdlp->Host_Control); 2687 + skb = s2io_txdl_getskb(fifo_data, txdlp, get_info.offset); 2710 2688 if (skb == NULL) { 2711 2689 DBG_PRINT(ERR_DBG, "%s: Null skb ", 2712 2690 __FUNCTION__); 2713 2691 DBG_PRINT(ERR_DBG, "in Tx Free Intr\n"); 2714 2692 return; 2715 2693 } 2716 - 2717 - frg_cnt = skb_shinfo(skb)->nr_frags; 2718 - nic->tx_pkt_count++; 2719 - 2720 - pci_unmap_single(nic->pdev, (dma_addr_t) 2721 - txdlp->Buffer_Pointer, 2722 - skb->len - skb->data_len, 2723 - PCI_DMA_TODEVICE); 2724 - if (frg_cnt) { 2725 - TxD_t *temp; 2726 - temp = txdlp; 2727 - txdlp++; 2728 - for (j = 0; j < frg_cnt; j++, txdlp++) { 2729 - skb_frag_t *frag = 2730 - &skb_shinfo(skb)->frags[j]; 2731 - if (!txdlp->Buffer_Pointer) 2732 - break; 2733 - pci_unmap_page(nic->pdev, 2734 - (dma_addr_t) 2735 - txdlp-> 2736 - Buffer_Pointer, 2737 - frag->size, 2738 - PCI_DMA_TODEVICE); 2739 - } 2740 - txdlp = temp; 2741 - } 2742 - memset(txdlp, 0, 2743 - (sizeof(TxD_t) * fifo_data->max_txds)); 2744 2694 2745 2695 /* Updating the statistics block */ 2746 2696 nic->stats.tx_bytes += skb->len; ··· 3519 3527 return 0; 3520 3528 } 3521 3529 3530 + txdp->Control_1 = 0; 3531 + txdp->Control_2 = 0; 3522 3532 #ifdef NETIF_F_TSO 3523 3533 mss = skb_shinfo(skb)->tso_size; 3524 3534 if (mss) { ··· 3528 3534 txdp->Control_1 |= TXD_TCP_LSO_MSS(mss); 3529 3535 } 3530 3536 #endif 3531 - 3532 - frg_cnt = skb_shinfo(skb)->nr_frags; 3533 - frg_len = skb->len - skb->data_len; 3534 - 3535 - txdp->Buffer_Pointer = pci_map_single 3536 - (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE); 3537 - txdp->Host_Control = (unsigned long) skb; 3538 3537 if (skb->ip_summed == CHECKSUM_HW) { 3539 3538 txdp->Control_2 |= 3540 3539 (TXD_TX_CKO_IPV4_EN | TXD_TX_CKO_TCP_EN | 3541 3540 TXD_TX_CKO_UDP_EN); 3542 3541 } 3543 - 3542 + txdp->Control_1 |= TXD_GATHER_CODE_FIRST; 3543 + txdp->Control_1 |= TXD_LIST_OWN_XENA; 3544 3544 txdp->Control_2 |= config->tx_intr_type; 3545 3545 3546 3546 if (sp->vlgrp && vlan_tx_tag_present(skb)) { ··· 3542 3554 txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag); 3543 3555 } 3544 3556 3545 - txdp->Control_1 |= (TXD_BUFFER0_SIZE(frg_len) | 3546 - TXD_GATHER_CODE_FIRST); 3547 - txdp->Control_1 |= TXD_LIST_OWN_XENA; 3557 + frg_len = skb->len - skb->data_len; 3558 + if (skb_shinfo(skb)->ufo_size) { 3559 + int ufo_size; 3548 3560 3561 + ufo_size = skb_shinfo(skb)->ufo_size; 3562 + ufo_size &= ~7; 3563 + txdp->Control_1 |= TXD_UFO_EN; 3564 + txdp->Control_1 |= TXD_UFO_MSS(ufo_size); 3565 + txdp->Control_1 |= TXD_BUFFER0_SIZE(8); 3566 + #ifdef __BIG_ENDIAN 3567 + sp->ufo_in_band_v[put_off] = 3568 + (u64)skb_shinfo(skb)->ip6_frag_id; 3569 + #else 3570 + sp->ufo_in_band_v[put_off] = 3571 + (u64)skb_shinfo(skb)->ip6_frag_id << 32; 3572 + #endif 3573 + txdp->Host_Control = (unsigned long)sp->ufo_in_band_v; 3574 + txdp->Buffer_Pointer = pci_map_single(sp->pdev, 3575 + sp->ufo_in_band_v, 3576 + sizeof(u64), PCI_DMA_TODEVICE); 3577 + txdp++; 3578 + txdp->Control_1 = 0; 3579 + txdp->Control_2 = 0; 3580 + } 3581 + 3582 + txdp->Buffer_Pointer = pci_map_single 3583 + (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE); 3584 + txdp->Host_Control = (unsigned long) skb; 3585 + txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len); 3586 + 3587 + if (skb_shinfo(skb)->ufo_size) 3588 + txdp->Control_1 |= TXD_UFO_EN; 3589 + 3590 + frg_cnt = skb_shinfo(skb)->nr_frags; 3549 3591 /* For fragmented SKB. */ 3550 3592 for (i = 0; i < frg_cnt; i++) { 3551 3593 skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ··· 3587 3569 (sp->pdev, frag->page, frag->page_offset, 3588 3570 frag->size, PCI_DMA_TODEVICE); 3589 3571 txdp->Control_1 |= TXD_BUFFER0_SIZE(frag->size); 3572 + if (skb_shinfo(skb)->ufo_size) 3573 + txdp->Control_1 |= TXD_UFO_EN; 3590 3574 } 3591 3575 txdp->Control_1 |= TXD_GATHER_CODE_LAST; 3576 + 3577 + if (skb_shinfo(skb)->ufo_size) 3578 + frg_cnt++; /* as Txd0 was used for inband header */ 3592 3579 3593 3580 tx_fifo = mac_control->tx_FIFO_start[queue]; 3594 3581 val64 = mac_control->fifos[queue].list_info[put_off].list_phy_addr; ··· 3606 3583 if (mss) 3607 3584 val64 |= TX_FIFO_SPECIAL_FUNC; 3608 3585 #endif 3586 + if (skb_shinfo(skb)->ufo_size) 3587 + val64 |= TX_FIFO_SPECIAL_FUNC; 3609 3588 writeq(val64, &tx_fifo->List_Control); 3610 3589 3611 3590 mmiowb(); ··· 5215 5190 .get_tso = ethtool_op_get_tso, 5216 5191 .set_tso = ethtool_op_set_tso, 5217 5192 #endif 5193 + .get_ufo = ethtool_op_get_ufo, 5194 + .set_ufo = ethtool_op_set_ufo, 5218 5195 .self_test_count = s2io_ethtool_self_test_count, 5219 5196 .self_test = s2io_ethtool_test, 5220 5197 .get_strings = s2io_ethtool_get_strings, ··· 5968 5941 break; 5969 5942 } 5970 5943 } 5971 - config->max_txds = MAX_SKB_FRAGS + 1; 5944 + /* + 2 because one Txd for skb->data and one Txd for UFO */ 5945 + config->max_txds = MAX_SKB_FRAGS + 2; 5972 5946 5973 5947 /* Rx side parameters. */ 5974 5948 if (rx_ring_sz[0] == 0) ··· 6063 6035 #ifdef NETIF_F_TSO 6064 6036 dev->features |= NETIF_F_TSO; 6065 6037 #endif 6038 + if (sp->device_type & XFRAME_II_DEVICE) { 6039 + dev->features |= NETIF_F_UFO; 6040 + dev->features |= NETIF_F_HW_CSUM; 6041 + } 6066 6042 6067 6043 dev->tx_timeout = &s2io_tx_watchdog; 6068 6044 dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
+3
drivers/net/s2io.h
··· 393 393 #define TXD_GATHER_CODE_LAST BIT(23) 394 394 #define TXD_TCP_LSO_EN BIT(30) 395 395 #define TXD_UDP_COF_EN BIT(31) 396 + #define TXD_UFO_EN BIT(31) | BIT(30) 396 397 #define TXD_TCP_LSO_MSS(val) vBIT(val,34,14) 398 + #define TXD_UFO_MSS(val) vBIT(val,34,14) 397 399 #define TXD_BUFFER0_SIZE(val) vBIT(val,48,16) 398 400 399 401 u64 Control_2; ··· 791 789 792 790 spinlock_t rx_lock; 793 791 atomic_t isr_cnt; 792 + u64 *ufo_in_band_v; 794 793 }; 795 794 796 795 #define RESET_ERROR 1;