S2io: Fixes to enable multiple transmit fifo support
Subsystems (2)
PATCH 1/2 S2io: Fixes to enable multiple transmit fifo support
Fixes to enable multiple transmit fifos (upto a maximum of eight).
- Moved single tx_lock from struct s2io_nic to struct fifo_info.
- Moved single ufo_in_band_v structure from struct s2io_nic to struct fifo_info.
- Assign the respective interrupt number for the transmitting fifo in the transmit descriptor (TXD).
- Added boundary checks for number of FIFOs enabled and FIFO length.
---
drivers/net/s2io.c +88 -48
@@ -84,7 +84,7 @@#include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "2.0.26.10" +#define DRV_VERSION "2.0.26.15-1"/* S2io Driver name & version. */ static char s2io_driver_name[] ="Neterion" ;
@@ -368,12 +368,19 @@ static void do_s2io_copy_mac_addr(structstatic void s2io_vlan_rx_register (struct net_device *dev,struct vlan_group *grp) { +int i;struct s2io_nic *nic = dev->priv; -unsigned long flags; +unsigned long flags[MAX_TX_FIFOS ]; +struct mac_info *mac_control = &nic->mac_control; +struct config_param *config = &nic->config; + +for (i =0 ; i < config->tx_fifo_num; i++) +spin_lock_irqsave (&mac_control->fifos[i].tx_lock, flags[i]); -spin_lock_irqsave (&nic->tx_lock, flags); nic->vlgrp = grp; -spin_unlock_irqrestore (&nic->tx_lock, flags); +for (i = config->tx_fifo_num -1 ; i >=0 ; i--) +spin_unlock_irqrestore (&mac_control->fifos[i].tx_lock, + flags[i]); }/* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */
@@ -565,6 +572,21 @@ static int init_shared_mem(struct s2io_nreturn -EINVAL ; } + size =0 ; +for (i =0 ; i < config->tx_fifo_num; i++) { + size = config->tx_cfg[i].fifo_len; +/* +* Legal values are from 2 to 8192 +*/ +if (size <2 ) { +DBG_PRINT (ERR_DBG ,"s2io: Invalid fifo len (%d)" , size); +DBG_PRINT (ERR_DBG ,"for fifo %d\n" , i); +DBG_PRINT (ERR_DBG ,"s2io: Legal values for fifo len" +"are 2 to 8192\n" ); +return -EINVAL ; + } + } + lst_size = (sizeof (struct TxD ) * config->max_txds); lst_per_page =PAGE_SIZE / lst_size;
@@ -639,10 +661,14 @@ static int init_shared_mem(struct s2io_n } } - nic->ufo_in_band_v =kcalloc (size,sizeof (u64),GFP_KERNEL ); -if (!nic->ufo_in_band_v) -return -ENOMEM ; - mem_allocated += (size *sizeof (u64)); +for (i =0 ; i < config->tx_fifo_num; i++) { + size = config->tx_cfg[i].fifo_len; + mac_control->fifos[i].ufo_in_band_v + =kcalloc (size,sizeof (u64),GFP_KERNEL ); +if (!mac_control->fifos[i].ufo_in_band_v) +return -ENOMEM ; + mem_allocated += (size *sizeof (u64)); + }/* Allocation and initialization of RXDs in Rings */ size =0 ;
@@ -829,7 +855,6 @@ static int init_shared_mem(struct s2io_nstatic void free_shared_mem (struct s2io_nic *nic) {int i, j, blk_cnt, size; -u32 ufo_size =0 ;void *tmp_v_addr;dma_addr_t tmp_p_addr;struct mac_info *mac_control;
@@ -850,7 +875,6 @@ static void free_shared_mem(struct s2io_ lst_per_page =PAGE_SIZE / lst_size;for (i =0 ; i < config->tx_fifo_num; i++) { - ufo_size += config->tx_cfg[i].fifo_len; page_num =TXD_MEM_PAGE_CNT (config->tx_cfg[i].fifo_len, lst_per_page);for (j =0 ; j < page_num; j++) {
@@ -940,18 +964,21 @@ static void free_shared_mem(struct s2io_ } } +for (i =0 ; i < nic->config.tx_fifo_num; i++) { +if (mac_control->fifos[i].ufo_in_band_v) { + nic->mac_control.stats_info->sw_stat.mem_freed + += (config->tx_cfg[i].fifo_len *sizeof (u64)); +kfree (mac_control->fifos[i].ufo_in_band_v); + } + } +if (mac_control->stats_mem) { + nic->mac_control.stats_info->sw_stat.mem_freed += + mac_control->stats_mem_sz;pci_free_consistent (nic->pdev, mac_control->stats_mem_sz, mac_control->stats_mem, mac_control->stats_mem_phy); - nic->mac_control.stats_info->sw_stat.mem_freed += - mac_control->stats_mem_sz; - } -if (nic->ufo_in_band_v) { -kfree (nic->ufo_in_band_v); - nic->mac_control.stats_info->sw_stat.mem_freed - += (ufo_size *sizeof (u64)); } }
@@ -2241,7 +2268,7 @@ static struct sk_buff *s2io_txdl_getskb(u16 j, frg_cnt; txds = txdlp; -if (txds->Host_Control == (u64 )(long )nic->ufo_in_band_v) { +if (txds->Host_Control == (u64 )(long )fifo_data->ufo_in_band_v) {pci_unmap_single (nic->pdev, (dma_addr_t ) txds->Buffer_Pointer,sizeof (u64),PCI_DMA_TODEVICE );
@@ -2296,6 +2323,8 @@ static void free_tx_buffers(struct s2io_ config = &nic->config;for (i =0 ; i < config->tx_fifo_num; i++) { +unsigned long flags; +spin_lock_irqsave (&mac_control->fifos[i].tx_lock, flags);for (j =0 ; j < config->tx_cfg[i].fifo_len -1 ; j++) { txdp = (struct TxD *) \ mac_control->fifos[i].list_info[j].list_virt_addr;
@@ -2312,6 +2341,7 @@ static void free_tx_buffers(struct s2io_ dev->name, cnt, i); mac_control->fifos[i].tx_curr_get_info.offset =0 ; mac_control->fifos[i].tx_curr_put_info.offset =0 ; +spin_unlock_irqrestore (&mac_control->fifos[i].tx_lock, flags); } }
@@ -2935,8 +2965,12 @@ static void tx_intr_handler(struct fifo_struct tx_curr_get_info get_info, put_info;struct sk_buff *skb;struct TxD *txdlp; +unsigned long flags =0 ;u8 err_mask; +if (!spin_trylock_irqsave (&fifo_data->tx_lock, flags)) +return ; + get_info = fifo_data->tx_curr_get_info;memcpy (&put_info, &fifo_data->tx_curr_put_info,sizeof (put_info)); txdlp = (struct TxD *) fifo_data->list_info[get_info.offset].
@@ -2985,6 +3019,7 @@ static void tx_intr_handler(struct fifo_ skb =s2io_txdl_getskb (fifo_data, txdlp, get_info.offset);if (skb ==NULL ) { +spin_unlock_irqrestore (&fifo_data->tx_lock, flags);DBG_PRINT (ERR_DBG ,"%s: Null skb " , __FUNCTION__);DBG_PRINT (ERR_DBG ,"in Tx Free Intr\n" );
@@ -3005,10 +3040,10 @@ static void tx_intr_handler(struct fifo_ get_info.offset; } -spin_lock (&nic->tx_lock);if (netif_queue_stopped (dev))netif_wake_queue (dev); -spin_unlock (&nic->tx_lock); + +spin_unlock_irqrestore (&fifo_data->tx_lock, flags); }/**
@@ -3972,9 +4007,10 @@ static int s2io_xmit(struct sk_buff *skb registeru64 val64;struct TxD *txdp;struct TxFIFO_element __iomem *tx_fifo; -unsigned long flags; +unsigned long flags =0 ;u16 vlan_tag =0 ;int vlan_priority =0 ; +struct fifo_info *fifo =NULL ;struct mac_info *mac_control;struct config_param *config;int offload_type;
@@ -3989,13 +4025,11 @@ static int s2io_xmit(struct sk_buff *skbDBG_PRINT (TX_DBG ,"%s:Buffer has no data..\n" , dev->name);dev_kfree_skb_any (skb);return 0 ; -} + } -spin_lock_irqsave (&sp->tx_lock, flags);if (!is_s2io_card_up (sp)) {DBG_PRINT (TX_DBG ,"%s: Card going down for reset\n" , dev->name); -spin_unlock_irqrestore (&sp->tx_lock, flags);dev_kfree_skb (skb);return 0 ; }
@@ -4008,19 +4042,20 @@ static int s2io_xmit(struct sk_buff *skb queue = config->fifo_mapping[vlan_priority]; } - put_off = (u16 ) mac_control->fifos[queue].tx_curr_put_info.offset; - get_off = (u16 ) mac_control->fifos[queue].tx_curr_get_info.offset; - txdp = (struct TxD *) mac_control->fifos[queue].list_info[put_off]. - list_virt_addr; + fifo = &mac_control->fifos[queue]; +spin_lock_irqsave (&fifo->tx_lock, flags); + put_off = (u16 ) fifo->tx_curr_put_info.offset; + get_off = (u16 ) fifo->tx_curr_get_info.offset; + txdp = (struct TxD *) fifo->list_info[put_off].list_virt_addr; - queue_len = mac_control->fifos[queue].tx_curr_put_info.fifo_len +1 ; + queue_len = fifo->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) {DBG_PRINT (TX_DBG ,"Error in xmit, No free TXDs.\n" );netif_stop_queue (dev);dev_kfree_skb (skb); -spin_unlock_irqrestore (&sp->tx_lock, flags); +spin_unlock_irqrestore (&fifo->tx_lock, flags);return 0 ; }
@@ -4036,7 +4071,7 @@ static int s2io_xmit(struct sk_buff *skb } txdp->Control_1 |=TXD_GATHER_CODE_FIRST ; txdp->Control_1 |=TXD_LIST_OWN_XENA ; - txdp->Control_2 |= config->tx_intr_type; + txdp->Control_2 |=TXD_INT_NUMBER (fifo->fifo_no);if (sp->vlgrp &&vlan_tx_tag_present (skb)) { txdp->Control_2 |=TXD_VLAN_ENABLE ;
@@ -4053,15 +4088,15 @@ static int s2io_xmit(struct sk_buff *skb txdp->Control_1 |=TXD_UFO_MSS (ufo_size); txdp->Control_1 |=TXD_BUFFER0_SIZE (8 );#ifdef __BIG_ENDIAN - sp->ufo_in_band_v[put_off] = + fifo->ufo_in_band_v[put_off] = (u64 )skb_shinfo (skb)->ip6_frag_id;#else - sp->ufo_in_band_v[put_off] = + fifo->ufo_in_band_v[put_off] = (u64 )skb_shinfo (skb)->ip6_frag_id <<32 ;#endif - txdp->Host_Control = (unsigned long )sp->ufo_in_band_v; + txdp->Host_Control = (unsigned long )fifo->ufo_in_band_v; txdp->Buffer_Pointer =pci_map_single (sp->pdev, - sp->ufo_in_band_v, + fifo->ufo_in_band_v,sizeof (u64),PCI_DMA_TODEVICE );if ((txdp->Buffer_Pointer ==0 ) || (txdp->Buffer_Pointer ==DMA_ERROR_CODE ))
@@ -4101,7 +4136,7 @@ static int s2io_xmit(struct sk_buff *skb frg_cnt++;/* as Txd0 was used for inband header */ tx_fifo = mac_control->tx_FIFO_start[queue]; - val64 = mac_control->fifos[queue].list_info[put_off].list_phy_addr; + val64 = fifo->list_info[put_off].list_phy_addr;writeq (val64, &tx_fifo->TxDL_Pointer); val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST |
@@ -4114,9 +4149,9 @@ static int s2io_xmit(struct sk_buff *skbmmiowb (); put_off++; -if (put_off == mac_control->fifos[queue].tx_curr_put_info.fifo_len +1 ) +if (put_off == fifo->tx_curr_put_info.fifo_len +1 ) put_off =0 ; - mac_control->fifos[queue].tx_curr_put_info.offset = put_off; + fifo->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) {
@@ -4128,7 +4163,7 @@ static int s2io_xmit(struct sk_buff *skb } mac_control->stats_info->sw_stat.mem_allocated += skb->truesize; dev->trans_start = jiffies; -spin_unlock_irqrestore (&sp->tx_lock, flags); +spin_unlock_irqrestore (&fifo->tx_lock, flags);return 0 ; pci_map_failed:
@@ -4136,7 +4171,7 @@ pci_map_failed:netif_stop_queue (dev); stats->mem_freed += skb->truesize;dev_kfree_skb (skb); -spin_unlock_irqrestore (&sp->tx_lock, flags); +spin_unlock_irqrestore (&fifo->tx_lock, flags);return 0 ; }
@@ -6996,10 +7031,8 @@ static void do_s2io_card_down(struct s2iif (do_io)s2io_reset (sp); -spin_lock_irqsave (&sp->tx_lock, flags);/* Free all Tx buffers */ free_tx_buffers (sp); -spin_unlock_irqrestore (&sp->tx_lock, flags);/* Free all Rx buffers */ spin_lock_irqsave (&sp->rx_lock, flags);
@@ -7458,12 +7491,18 @@ static void s2io_init_pci(struct s2io_nistatic 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 ((tx_fifo_num >MAX_TX_FIFOS ) || + (tx_fifo_num <FIFO_DEFAULT_NUM )) { +DBG_PRINT (ERR_DBG ,"s2io: Requested number of tx fifos " +"(%d) not supported\n" , tx_fifo_num); + tx_fifo_num = + ((tx_fifo_num >MAX_TX_FIFOS )?MAX_TX_FIFOS : + ((tx_fifo_num <FIFO_DEFAULT_NUM ) ?FIFO_DEFAULT_NUM : + tx_fifo_num)); +DBG_PRINT (ERR_DBG ,"s2io: Default to %d " , tx_fifo_num); +DBG_PRINT (ERR_DBG ,"tx fifos\n" ); } +if ( rx_ring_num >8 ) {DBG_PRINT (ERR_DBG ,"s2io: Requested number of Rx rings not " "supported\n" );
@@ -7842,7 +7881,8 @@ s2io_init_nic(struct pci_dev *pdev, cons sp->state =0 ;/* Initialize spinlocks */ -spin_lock_init (&sp->tx_lock); +for (i =0 ; i < sp->config.tx_fifo_num; i++) +spin_lock_init (&mac_control->fifos[i].tx_lock);if (!napi)spin_lock_init (&sp->put_lock);
drivers/net/s2io.h +9 -3
@@ -360,6 +360,8 @@ struct stat_block {#define MAX_TX_FIFOS 8#define MAX_RX_RINGS 8 +#define FIFO_DEFAULT_NUM 1 +#define MAX_RX_DESC_1 (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 127 )#define MAX_RX_DESC_2 (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 85 )#define MAX_RX_DESC_3 (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 85 )
@@ -719,8 +721,14 @@ struct fifo_info {*/ struct tx_curr_get_info tx_curr_get_info; +/* Per fifo lock */ +spinlock_t tx_lock; + +/* Per fifo UFO in band structure */ +u64 *ufo_in_band_v; +struct s2io_nic *nic; -}; +}____cacheline_aligned ;/* Information related to the Tx and Rx FIFOs and Rings of Xena * is maintained in this structure.
@@ -848,7 +856,6 @@ struct s2io_nic {atomic_t rx_bufs_left[MAX_RX_RINGS ]; -spinlock_t tx_lock;spinlock_t put_lock;#define PROMISC 1
@@ -915,7 +922,6 @@ struct s2io_nic {volatile unsigned long state;spinlock_t rx_lock;u64 general_int_mask; -u64 *ufo_in_band_v;#define VPD_STRING_LEN 80u8 product_name[VPD_STRING_LEN ];u8 serial_num[VPD_STRING_LEN ];
Quoted 11 lines · Ramkrishna Vepa
Fixes to enable multiple transmit fifos (upto a maximum of eight).
- Moved singletx_lockfrom structs2io_nicto structfifo_info.
- Moved singleufo_in_band_vstructure from structs2io_nicto structfifo_info.
- Assign the respective interrupt number for the transmitting fifo in the transmit descriptor (TXD).
- Added boundary checks for number of FIFOs enabled and FIFO length.Signed-off-by Surjit Reang <[email protected]>Signed-off-by Sreenivasa Honnur <[email protected]>Signed-off-by Ramkrishna Vepa <[email protected]>
applied 1-2 to #upstream