aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/s2io.c
diff options
context:
space:
mode:
authorSreenivasa Honnur <Sreenivasa.Honnur@neterion.com>2008-02-20 17:07:51 -0500
committerJeff Garzik <jeff@garzik.org>2008-03-17 07:49:26 -0400
commit6cfc482b4b1c512d81712eba41fa324b24e5e7b2 (patch)
treed288e4f8a08b22507a86e67826c87a0070e98789 /drivers/net/s2io.c
parent3a3d5756ac552ee2d2cca6ba0912f0ff328e8357 (diff)
S2io: Multiqueue network device support - FIFO selection based on L4 ports
- Resubmit #2 - Transmit fifo selection based on TCP/UDP ports. - Added tx_steering_type loadable parameter for transmit fifo selection. 0x0 NO_STEERING: Default FIFO is selected. 0x1 TX_PRIORITY_STEERING: FIFO is selected based on skb->priority. 0x2 TX_DEFAULT_STEERING: FIFO is selected based on L4 Ports. Signed-off-by: Surjit Reang <surjit.reang@neterion.com> Signed-off-by: Ramkrishna Vepa <ram.vepa@neterion.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/s2io.c')
-rw-r--r--drivers/net/s2io.c135
1 files changed, 117 insertions, 18 deletions
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 3ddc0aae60b6..9786de9c0248 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -458,7 +458,7 @@ MODULE_VERSION(DRV_VERSION);
458 458
459 459
460/* Module Loadable parameters. */ 460/* Module Loadable parameters. */
461S2IO_PARM_INT(tx_fifo_num, 1); 461S2IO_PARM_INT(tx_fifo_num, FIFO_DEFAULT_NUM);
462S2IO_PARM_INT(rx_ring_num, 1); 462S2IO_PARM_INT(rx_ring_num, 1);
463S2IO_PARM_INT(multiq, 0); 463S2IO_PARM_INT(multiq, 0);
464S2IO_PARM_INT(rx_ring_mode, 1); 464S2IO_PARM_INT(rx_ring_mode, 1);
@@ -470,6 +470,8 @@ S2IO_PARM_INT(shared_splits, 0);
470S2IO_PARM_INT(tmac_util_period, 5); 470S2IO_PARM_INT(tmac_util_period, 5);
471S2IO_PARM_INT(rmac_util_period, 5); 471S2IO_PARM_INT(rmac_util_period, 5);
472S2IO_PARM_INT(l3l4hdr_size, 128); 472S2IO_PARM_INT(l3l4hdr_size, 128);
473/* 0 is no steering, 1 is Priority steering, 2 is Default steering */
474S2IO_PARM_INT(tx_steering_type, TX_DEFAULT_STEERING);
473/* Frequency of Rx desc syncs expressed as power of 2 */ 475/* Frequency of Rx desc syncs expressed as power of 2 */
474S2IO_PARM_INT(rxsync_frequency, 3); 476S2IO_PARM_INT(rxsync_frequency, 3);
475/* Interrupt type. Values can be 0(INTA), 2(MSI_X) */ 477/* Interrupt type. Values can be 0(INTA), 2(MSI_X) */
@@ -4114,7 +4116,9 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
4114 struct fifo_info *fifo = NULL; 4116 struct fifo_info *fifo = NULL;
4115 struct mac_info *mac_control; 4117 struct mac_info *mac_control;
4116 struct config_param *config; 4118 struct config_param *config;
4119 int do_spin_lock = 1;
4117 int offload_type; 4120 int offload_type;
4121 int enable_per_list_interrupt = 0;
4118 struct swStat *stats = &sp->mac_control.stats_info->sw_stat; 4122 struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
4119 4123
4120 mac_control = &sp->mac_control; 4124 mac_control = &sp->mac_control;
@@ -4136,15 +4140,52 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
4136 } 4140 }
4137 4141
4138 queue = 0; 4142 queue = 0;
4139 /* Get Fifo number to Transmit based on vlan priority */
4140 if (sp->vlgrp && vlan_tx_tag_present(skb)) 4143 if (sp->vlgrp && vlan_tx_tag_present(skb))
4141 vlan_tag = vlan_tx_tag_get(skb); 4144 vlan_tag = vlan_tx_tag_get(skb);
4145 if (sp->config.tx_steering_type == TX_DEFAULT_STEERING) {
4146 if (skb->protocol == htons(ETH_P_IP)) {
4147 struct iphdr *ip;
4148 struct tcphdr *th;
4149 ip = ip_hdr(skb);
4150
4151 if ((ip->frag_off & htons(IP_OFFSET|IP_MF)) == 0) {
4152 th = (struct tcphdr *)(((unsigned char *)ip) +
4153 ip->ihl*4);
4154
4155 if (ip->protocol == IPPROTO_TCP) {
4156 queue_len = sp->total_tcp_fifos;
4157 queue = (ntohs(th->source) +
4158 ntohs(th->dest)) &
4159 sp->fifo_selector[queue_len - 1];
4160 if (queue >= queue_len)
4161 queue = queue_len - 1;
4162 } else if (ip->protocol == IPPROTO_UDP) {
4163 queue_len = sp->total_udp_fifos;
4164 queue = (ntohs(th->source) +
4165 ntohs(th->dest)) &
4166 sp->fifo_selector[queue_len - 1];
4167 if (queue >= queue_len)
4168 queue = queue_len - 1;
4169 queue += sp->udp_fifo_idx;
4170 if (skb->len > 1024)
4171 enable_per_list_interrupt = 1;
4172 do_spin_lock = 0;
4173 }
4174 }
4175 }
4176 } else if (sp->config.tx_steering_type == TX_PRIORITY_STEERING)
4177 /* get fifo number based on skb->priority value */
4178 queue = config->fifo_mapping
4179 [skb->priority & (MAX_TX_FIFOS - 1)];
4180 fifo = &mac_control->fifos[queue];
4142 4181
4143 /* get fifo number based on skb->priority value */ 4182 if (do_spin_lock)
4144 queue = config->fifo_mapping[skb->priority & (MAX_TX_FIFOS - 1)]; 4183 spin_lock_irqsave(&fifo->tx_lock, flags);
4184 else {
4185 if (unlikely(!spin_trylock_irqsave(&fifo->tx_lock, flags)))
4186 return NETDEV_TX_LOCKED;
4187 }
4145 4188
4146 fifo = &mac_control->fifos[queue];
4147 spin_lock_irqsave(&fifo->tx_lock, flags);
4148#ifdef CONFIG_NETDEVICES_MULTIQUEUE 4189#ifdef CONFIG_NETDEVICES_MULTIQUEUE
4149 if (sp->config.multiq) { 4190 if (sp->config.multiq) {
4150 if (__netif_subqueue_stopped(dev, fifo->fifo_no)) { 4191 if (__netif_subqueue_stopped(dev, fifo->fifo_no)) {
@@ -4188,7 +4229,9 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
4188 txdp->Control_1 |= TXD_GATHER_CODE_FIRST; 4229 txdp->Control_1 |= TXD_GATHER_CODE_FIRST;
4189 txdp->Control_1 |= TXD_LIST_OWN_XENA; 4230 txdp->Control_1 |= TXD_LIST_OWN_XENA;
4190 txdp->Control_2 |= TXD_INT_NUMBER(fifo->fifo_no); 4231 txdp->Control_2 |= TXD_INT_NUMBER(fifo->fifo_no);
4191 4232 if (enable_per_list_interrupt)
4233 if (put_off & (queue_len >> 5))
4234 txdp->Control_2 |= TXD_INT_TYPE_PER_LIST;
4192 if (vlan_tag) { 4235 if (vlan_tag) {
4193 txdp->Control_2 |= TXD_VLAN_ENABLE; 4236 txdp->Control_2 |= TXD_VLAN_ENABLE;
4194 txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag); 4237 txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag);
@@ -7622,13 +7665,15 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type,
7622 u8 *dev_multiq) 7665 u8 *dev_multiq)
7623{ 7666{
7624 if ((tx_fifo_num > MAX_TX_FIFOS) || 7667 if ((tx_fifo_num > MAX_TX_FIFOS) ||
7625 (tx_fifo_num < FIFO_DEFAULT_NUM)) { 7668 (tx_fifo_num < 1)) {
7626 DBG_PRINT(ERR_DBG, "s2io: Requested number of tx fifos " 7669 DBG_PRINT(ERR_DBG, "s2io: Requested number of tx fifos "
7627 "(%d) not supported\n", tx_fifo_num); 7670 "(%d) not supported\n", tx_fifo_num);
7628 tx_fifo_num = 7671
7629 ((tx_fifo_num > MAX_TX_FIFOS)? MAX_TX_FIFOS : 7672 if (tx_fifo_num < 1)
7630 ((tx_fifo_num < FIFO_DEFAULT_NUM) ? FIFO_DEFAULT_NUM : 7673 tx_fifo_num = 1;
7631 tx_fifo_num)); 7674 else
7675 tx_fifo_num = MAX_TX_FIFOS;
7676
7632 DBG_PRINT(ERR_DBG, "s2io: Default to %d ", tx_fifo_num); 7677 DBG_PRINT(ERR_DBG, "s2io: Default to %d ", tx_fifo_num);
7633 DBG_PRINT(ERR_DBG, "tx fifos\n"); 7678 DBG_PRINT(ERR_DBG, "tx fifos\n");
7634 } 7679 }
@@ -7639,10 +7684,23 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type,
7639 multiq = 0; 7684 multiq = 0;
7640 } 7685 }
7641#endif 7686#endif
7642 /* if multiqueue is enabled configure all fifos */ 7687 if (multiq)
7643 if (multiq) {
7644 tx_fifo_num = MAX_TX_FIFOS;
7645 *dev_multiq = multiq; 7688 *dev_multiq = multiq;
7689
7690 if (tx_steering_type && (1 == tx_fifo_num)) {
7691 if (tx_steering_type != TX_DEFAULT_STEERING)
7692 DBG_PRINT(ERR_DBG,
7693 "s2io: Tx steering is not supported with "
7694 "one fifo. Disabling Tx steering.\n");
7695 tx_steering_type = NO_STEERING;
7696 }
7697
7698 if ((tx_steering_type < NO_STEERING) ||
7699 (tx_steering_type > TX_DEFAULT_STEERING)) {
7700 DBG_PRINT(ERR_DBG, "s2io: Requested transmit steering not "
7701 "supported\n");
7702 DBG_PRINT(ERR_DBG, "s2io: Disabling transmit steering\n");
7703 tx_steering_type = NO_STEERING;
7646 } 7704 }
7647 7705
7648 if ( rx_ring_num > 8) { 7706 if ( rx_ring_num > 8) {
@@ -7773,7 +7831,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
7773 } 7831 }
7774#ifdef CONFIG_NETDEVICES_MULTIQUEUE 7832#ifdef CONFIG_NETDEVICES_MULTIQUEUE
7775 if (dev_multiq) 7833 if (dev_multiq)
7776 dev = alloc_etherdev_mq(sizeof(struct s2io_nic), MAX_TX_FIFOS); 7834 dev = alloc_etherdev_mq(sizeof(struct s2io_nic), tx_fifo_num);
7777 else 7835 else
7778#endif 7836#endif
7779 dev = alloc_etherdev(sizeof(struct s2io_nic)); 7837 dev = alloc_etherdev(sizeof(struct s2io_nic));
@@ -7824,11 +7882,33 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
7824 config = &sp->config; 7882 config = &sp->config;
7825 7883
7826 config->napi = napi; 7884 config->napi = napi;
7885 config->tx_steering_type = tx_steering_type;
7827 7886
7828 /* Tx side parameters. */ 7887 /* Tx side parameters. */
7829 config->tx_fifo_num = tx_fifo_num; 7888 if (config->tx_steering_type == TX_PRIORITY_STEERING)
7889 config->tx_fifo_num = MAX_TX_FIFOS;
7890 else
7891 config->tx_fifo_num = tx_fifo_num;
7892
7893 /* Initialize the fifos used for tx steering */
7894 if (config->tx_fifo_num < 5) {
7895 if (config->tx_fifo_num == 1)
7896 sp->total_tcp_fifos = 1;
7897 else
7898 sp->total_tcp_fifos = config->tx_fifo_num - 1;
7899 sp->udp_fifo_idx = config->tx_fifo_num - 1;
7900 sp->total_udp_fifos = 1;
7901 sp->other_fifo_idx = sp->total_tcp_fifos - 1;
7902 } else {
7903 sp->total_tcp_fifos = (tx_fifo_num - FIFO_UDP_MAX_NUM -
7904 FIFO_OTHER_MAX_NUM);
7905 sp->udp_fifo_idx = sp->total_tcp_fifos;
7906 sp->total_udp_fifos = FIFO_UDP_MAX_NUM;
7907 sp->other_fifo_idx = sp->udp_fifo_idx + FIFO_UDP_MAX_NUM;
7908 }
7909
7830 config->multiq = dev_multiq; 7910 config->multiq = dev_multiq;
7831 for (i = 0; i < MAX_TX_FIFOS; i++) { 7911 for (i = 0; i < config->tx_fifo_num; i++) {
7832 config->tx_cfg[i].fifo_len = tx_fifo_len[i]; 7912 config->tx_cfg[i].fifo_len = tx_fifo_len[i];
7833 config->tx_cfg[i].fifo_priority = i; 7913 config->tx_cfg[i].fifo_priority = i;
7834 } 7914 }
@@ -7837,6 +7917,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
7837 for (i = 0; i < MAX_TX_FIFOS; i++) 7917 for (i = 0; i < MAX_TX_FIFOS; i++)
7838 config->fifo_mapping[i] = fifo_map[config->tx_fifo_num - 1][i]; 7918 config->fifo_mapping[i] = fifo_map[config->tx_fifo_num - 1][i];
7839 7919
7920 /* map the hashing selector table to the configured fifos */
7921 for (i = 0; i < config->tx_fifo_num; i++)
7922 sp->fifo_selector[i] = fifo_selector[i];
7923
7924
7840 config->tx_intr_type = TXD_INT_TYPE_UTILZ; 7925 config->tx_intr_type = TXD_INT_TYPE_UTILZ;
7841 for (i = 0; i < config->tx_fifo_num; i++) { 7926 for (i = 0; i < config->tx_fifo_num; i++) {
7842 config->tx_cfg[i].f_no_snoop = 7927 config->tx_cfg[i].f_no_snoop =
@@ -8113,6 +8198,20 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
8113 DBG_PRINT(ERR_DBG, "%s: Multiqueue support disabled\n", 8198 DBG_PRINT(ERR_DBG, "%s: Multiqueue support disabled\n",
8114 dev->name); 8199 dev->name);
8115 8200
8201 switch (sp->config.tx_steering_type) {
8202 case NO_STEERING:
8203 DBG_PRINT(ERR_DBG, "%s: No steering enabled for"
8204 " transmit\n", dev->name);
8205 break;
8206 case TX_PRIORITY_STEERING:
8207 DBG_PRINT(ERR_DBG, "%s: Priority steering enabled for"
8208 " transmit\n", dev->name);
8209 break;
8210 case TX_DEFAULT_STEERING:
8211 DBG_PRINT(ERR_DBG, "%s: Default steering enabled for"
8212 " transmit\n", dev->name);
8213 }
8214
8116 if (sp->lro) 8215 if (sp->lro)
8117 DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n", 8216 DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
8118 dev->name); 8217 dev->name);