diff options
author | Sreenivasa Honnur <Sreenivasa.Honnur@neterion.com> | 2008-02-20 17:07:51 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-03-17 07:49:26 -0400 |
commit | 6cfc482b4b1c512d81712eba41fa324b24e5e7b2 (patch) | |
tree | d288e4f8a08b22507a86e67826c87a0070e98789 /drivers | |
parent | 3a3d5756ac552ee2d2cca6ba0912f0ff328e8357 (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')
-rw-r--r-- | drivers/net/s2io.c | 135 | ||||
-rw-r--r-- | drivers/net/s2io.h | 34 |
2 files changed, 150 insertions, 19 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. */ |
461 | S2IO_PARM_INT(tx_fifo_num, 1); | 461 | S2IO_PARM_INT(tx_fifo_num, FIFO_DEFAULT_NUM); |
462 | S2IO_PARM_INT(rx_ring_num, 1); | 462 | S2IO_PARM_INT(rx_ring_num, 1); |
463 | S2IO_PARM_INT(multiq, 0); | 463 | S2IO_PARM_INT(multiq, 0); |
464 | S2IO_PARM_INT(rx_ring_mode, 1); | 464 | S2IO_PARM_INT(rx_ring_mode, 1); |
@@ -470,6 +470,8 @@ S2IO_PARM_INT(shared_splits, 0); | |||
470 | S2IO_PARM_INT(tmac_util_period, 5); | 470 | S2IO_PARM_INT(tmac_util_period, 5); |
471 | S2IO_PARM_INT(rmac_util_period, 5); | 471 | S2IO_PARM_INT(rmac_util_period, 5); |
472 | S2IO_PARM_INT(l3l4hdr_size, 128); | 472 | S2IO_PARM_INT(l3l4hdr_size, 128); |
473 | /* 0 is no steering, 1 is Priority steering, 2 is Default steering */ | ||
474 | S2IO_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 */ |
474 | S2IO_PARM_INT(rxsync_frequency, 3); | 476 | S2IO_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); |
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index fdc0a94d0a89..5e351c0879fa 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h | |||
@@ -360,7 +360,10 @@ struct stat_block { | |||
360 | #define MAX_TX_FIFOS 8 | 360 | #define MAX_TX_FIFOS 8 |
361 | #define MAX_RX_RINGS 8 | 361 | #define MAX_RX_RINGS 8 |
362 | 362 | ||
363 | #define FIFO_DEFAULT_NUM 1 | 363 | #define FIFO_DEFAULT_NUM 5 |
364 | #define FIFO_UDP_MAX_NUM 2 /* 0 - even, 1 -odd ports */ | ||
365 | #define FIFO_OTHER_MAX_NUM 1 | ||
366 | |||
364 | 367 | ||
365 | #define MAX_RX_DESC_1 (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 127 ) | 368 | #define MAX_RX_DESC_1 (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 127 ) |
366 | #define MAX_RX_DESC_2 (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 85 ) | 369 | #define MAX_RX_DESC_2 (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 85 ) |
@@ -379,6 +382,8 @@ static int fifo_map[][MAX_TX_FIFOS] = { | |||
379 | {0, 1, 2, 3, 4, 5, 6, 7}, | 382 | {0, 1, 2, 3, 4, 5, 6, 7}, |
380 | }; | 383 | }; |
381 | 384 | ||
385 | static u16 fifo_selector[MAX_TX_FIFOS] = {0, 1, 3, 3, 7, 7, 7, 7}; | ||
386 | |||
382 | /* Maintains Per FIFO related information. */ | 387 | /* Maintains Per FIFO related information. */ |
383 | struct tx_fifo_config { | 388 | struct tx_fifo_config { |
384 | #define MAX_AVAILABLE_TXDS 8192 | 389 | #define MAX_AVAILABLE_TXDS 8192 |
@@ -431,6 +436,12 @@ struct config_param { | |||
431 | /* Tx Side */ | 436 | /* Tx Side */ |
432 | u32 tx_fifo_num; /*Number of Tx FIFOs */ | 437 | u32 tx_fifo_num; /*Number of Tx FIFOs */ |
433 | 438 | ||
439 | /* 0-No steering, 1-Priority steering, 2-Default fifo map */ | ||
440 | #define NO_STEERING 0 | ||
441 | #define TX_PRIORITY_STEERING 0x1 | ||
442 | #define TX_DEFAULT_STEERING 0x2 | ||
443 | u8 tx_steering_type; | ||
444 | |||
434 | u8 fifo_mapping[MAX_TX_FIFOS]; | 445 | u8 fifo_mapping[MAX_TX_FIFOS]; |
435 | struct tx_fifo_config tx_cfg[MAX_TX_FIFOS]; /*Per-Tx FIFO config */ | 446 | struct tx_fifo_config tx_cfg[MAX_TX_FIFOS]; /*Per-Tx FIFO config */ |
436 | u32 max_txds; /*Max no. of Tx buffer descriptor per TxDL */ | 447 | u32 max_txds; /*Max no. of Tx buffer descriptor per TxDL */ |
@@ -895,6 +906,27 @@ struct s2io_nic { | |||
895 | */ | 906 | */ |
896 | int rx_csum; | 907 | int rx_csum; |
897 | 908 | ||
909 | /* Below variables are used for fifo selection to transmit a packet */ | ||
910 | u16 fifo_selector[MAX_TX_FIFOS]; | ||
911 | |||
912 | /* Total fifos for tcp packets */ | ||
913 | u8 total_tcp_fifos; | ||
914 | |||
915 | /* | ||
916 | * Beginning index of udp for udp packets | ||
917 | * Value will be equal to | ||
918 | * (tx_fifo_num - FIFO_UDP_MAX_NUM - FIFO_OTHER_MAX_NUM) | ||
919 | */ | ||
920 | u8 udp_fifo_idx; | ||
921 | |||
922 | u8 total_udp_fifos; | ||
923 | |||
924 | /* | ||
925 | * Beginning index of fifo for all other packets | ||
926 | * Value will be equal to (tx_fifo_num - FIFO_OTHER_MAX_NUM) | ||
927 | */ | ||
928 | u8 other_fifo_idx; | ||
929 | |||
898 | /* after blink, the adapter must be restored with original | 930 | /* after blink, the adapter must be restored with original |
899 | * values. | 931 | * values. |
900 | */ | 932 | */ |