aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorHimanshu Madhani <himanshu.madhani@qlogic.com>2013-08-21 11:24:11 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-21 15:17:18 -0400
commitaa4a1f7df7cbb98797c9f4edfde3c726e2b3841f (patch)
tree0281089c4d1e9650bc5f558e8fd1dfb496ce6e2e /drivers/net/ethernet
parent012ec81223aa45d2b80aeafb77392fd1a19c7b10 (diff)
qlcnic: Enable Tx queue changes using ethtool for 82xx Series adapter.
o using ethtool {set|get}_channel option, user can change number of Tx queues for 82xx Series adapter. o updated ethtool -S <ethX> option to display stats from each Tx queue. Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h10
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c63
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h3
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c96
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c2
8 files changed, 145 insertions, 35 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 2f9985f2fbcb..101b538df8ab 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -1531,8 +1531,9 @@ int qlcnic_reset_context(struct qlcnic_adapter *);
1531void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings); 1531void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings);
1532int qlcnic_diag_alloc_res(struct net_device *netdev, int test); 1532int qlcnic_diag_alloc_res(struct net_device *netdev, int test);
1533netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev); 1533netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
1534int qlcnic_set_max_rss(struct qlcnic_adapter *, u8, size_t); 1534int qlcnic_set_max_rss(struct qlcnic_adapter *, u8, int);
1535int qlcnic_validate_max_rss(struct qlcnic_adapter *, __u32); 1535int qlcnic_validate_max_rss(struct qlcnic_adapter *, __u32);
1536int qlcnic_validate_max_tx_rings(struct qlcnic_adapter *, int);
1536void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter); 1537void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
1537void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *); 1538void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *);
1538int qlcnic_enable_msix(struct qlcnic_adapter *, u32); 1539int qlcnic_enable_msix(struct qlcnic_adapter *, u32);
@@ -1679,7 +1680,7 @@ struct qlcnic_hardware_ops {
1679 int (*write_reg) (struct qlcnic_adapter *, ulong, u32); 1680 int (*write_reg) (struct qlcnic_adapter *, ulong, u32);
1680 void (*get_ocm_win) (struct qlcnic_hardware_context *); 1681 void (*get_ocm_win) (struct qlcnic_hardware_context *);
1681 int (*get_mac_address) (struct qlcnic_adapter *, u8 *); 1682 int (*get_mac_address) (struct qlcnic_adapter *, u8 *);
1682 int (*setup_intr) (struct qlcnic_adapter *, u8); 1683 int (*setup_intr) (struct qlcnic_adapter *, u8, int);
1683 int (*alloc_mbx_args)(struct qlcnic_cmd_args *, 1684 int (*alloc_mbx_args)(struct qlcnic_cmd_args *,
1684 struct qlcnic_adapter *, u32); 1685 struct qlcnic_adapter *, u32);
1685 int (*mbx_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *); 1686 int (*mbx_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
@@ -1745,9 +1746,10 @@ static inline int qlcnic_get_mac_address(struct qlcnic_adapter *adapter,
1745 return adapter->ahw->hw_ops->get_mac_address(adapter, mac); 1746 return adapter->ahw->hw_ops->get_mac_address(adapter, mac);
1746} 1747}
1747 1748
1748static inline int qlcnic_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr) 1749static inline int qlcnic_setup_intr(struct qlcnic_adapter *adapter,
1750 u8 num_intr, int txq)
1749{ 1751{
1750 return adapter->ahw->hw_ops->setup_intr(adapter, num_intr); 1752 return adapter->ahw->hw_ops->setup_intr(adapter, num_intr, txq);
1751} 1753}
1752 1754
1753static inline int qlcnic_alloc_mbx_args(struct qlcnic_cmd_args *mbx, 1755static inline int qlcnic_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index f0dc5d438ed6..ea44828a546d 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -261,7 +261,7 @@ int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *adapter, ulong addr,
261 } 261 }
262} 262}
263 263
264int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr) 264int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr, int txq)
265{ 265{
266 int err, i, num_msix; 266 int err, i, num_msix;
267 struct qlcnic_hardware_context *ahw = adapter->ahw; 267 struct qlcnic_hardware_context *ahw = adapter->ahw;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
index d4c58c6a97d8..bfd2741d6c77 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -523,7 +523,7 @@ enum qlc_83xx_ext_regs {
523/* 83xx funcitons */ 523/* 83xx funcitons */
524int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *); 524int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *);
525int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *, struct qlcnic_cmd_args *); 525int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *, struct qlcnic_cmd_args *);
526int qlcnic_83xx_setup_intr(struct qlcnic_adapter *, u8); 526int qlcnic_83xx_setup_intr(struct qlcnic_adapter *, u8, int);
527void qlcnic_83xx_get_func_no(struct qlcnic_adapter *); 527void qlcnic_83xx_get_func_no(struct qlcnic_adapter *);
528int qlcnic_83xx_cam_lock(struct qlcnic_adapter *); 528int qlcnic_83xx_cam_lock(struct qlcnic_adapter *);
529void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *); 529void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index f23e66780e7a..fb0ef36b529b 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -2201,7 +2201,7 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
2201 if (err) 2201 if (err)
2202 goto detach_mbx; 2202 goto detach_mbx;
2203 2203
2204 err = qlcnic_setup_intr(adapter, 0); 2204 err = qlcnic_setup_intr(adapter, 0, 0);
2205 if (err) { 2205 if (err) {
2206 dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n"); 2206 dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");
2207 goto disable_intr; 2207 goto disable_intr;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index 79a5855f926c..583dc2b29a84 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -125,6 +125,14 @@ static const char qlcnic_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = {
125}; 125};
126 126
127#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats) 127#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
128
129static const char qlcnic_tx_ring_stats_strings[][ETH_GSTRING_LEN] = {
130 "xmit_on",
131 "xmit_off",
132 "xmit_called",
133 "xmit_finished",
134};
135
128static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = { 136static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = {
129 "ctx_rx_bytes", 137 "ctx_rx_bytes",
130 "ctx_rx_pkts", 138 "ctx_rx_pkts",
@@ -630,15 +638,15 @@ qlcnic_set_ringparam(struct net_device *dev,
630static void qlcnic_get_channels(struct net_device *dev, 638static void qlcnic_get_channels(struct net_device *dev,
631 struct ethtool_channels *channel) 639 struct ethtool_channels *channel)
632{ 640{
633 int min;
634 struct qlcnic_adapter *adapter = netdev_priv(dev); 641 struct qlcnic_adapter *adapter = netdev_priv(dev);
642 int min;
635 643
636 min = min_t(int, adapter->ahw->max_rx_ques, num_online_cpus()); 644 min = min_t(int, adapter->ahw->max_rx_ques, num_online_cpus());
637 channel->max_rx = rounddown_pow_of_two(min); 645 channel->max_rx = rounddown_pow_of_two(min);
638 channel->max_tx = adapter->ahw->max_tx_ques; 646 channel->max_tx = min_t(int, QLCNIC_MAX_TX_RINGS, num_online_cpus());
639 647
640 channel->rx_count = adapter->max_sds_rings; 648 channel->rx_count = adapter->max_sds_rings;
641 channel->tx_count = adapter->ahw->max_tx_ques; 649 channel->tx_count = adapter->max_drv_tx_rings;
642} 650}
643 651
644static int qlcnic_set_channels(struct net_device *dev, 652static int qlcnic_set_channels(struct net_device *dev,
@@ -646,18 +654,27 @@ static int qlcnic_set_channels(struct net_device *dev,
646{ 654{
647 struct qlcnic_adapter *adapter = netdev_priv(dev); 655 struct qlcnic_adapter *adapter = netdev_priv(dev);
648 int err; 656 int err;
657 int txq = 0;
649 658
650 if (channel->other_count || channel->combined_count || 659 if (channel->other_count || channel->combined_count)
651 channel->tx_count != channel->max_tx)
652 return -EINVAL; 660 return -EINVAL;
653 661
654 err = qlcnic_validate_max_rss(adapter, channel->rx_count); 662 if (channel->rx_count) {
655 if (err) 663 err = qlcnic_validate_max_rss(adapter, channel->rx_count);
656 return err; 664 if (err)
665 return err;
666 }
667
668 if (channel->tx_count) {
669 err = qlcnic_validate_max_tx_rings(adapter, channel->tx_count);
670 if (err)
671 return err;
672 txq = channel->tx_count;
673 }
657 674
658 err = qlcnic_set_max_rss(adapter, channel->rx_count, 0); 675 err = qlcnic_set_max_rss(adapter, channel->rx_count, txq);
659 netdev_info(dev, "allocated 0x%x sds rings\n", 676 netdev_info(dev, "allocated 0x%x sds rings and 0x%x tx rings\n",
660 adapter->max_sds_rings); 677 adapter->max_sds_rings, adapter->max_drv_tx_rings);
661 return err; 678 return err;
662} 679}
663 680
@@ -893,6 +910,7 @@ free_diag_res:
893clear_diag_irq: 910clear_diag_irq:
894 adapter->max_sds_rings = max_sds_rings; 911 adapter->max_sds_rings = max_sds_rings;
895 clear_bit(__QLCNIC_RESETTING, &adapter->state); 912 clear_bit(__QLCNIC_RESETTING, &adapter->state);
913
896 return ret; 914 return ret;
897} 915}
898 916
@@ -1077,11 +1095,21 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
1077 QLCNIC_TEST_LEN * ETH_GSTRING_LEN); 1095 QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
1078 break; 1096 break;
1079 case ETH_SS_STATS: 1097 case ETH_SS_STATS:
1098 num_stats = ARRAY_SIZE(qlcnic_tx_ring_stats_strings);
1099 for (i = 0; i < adapter->max_drv_tx_rings; i++) {
1100 for (index = 0; index < num_stats; index++) {
1101 sprintf(data, "tx_ring_%d %s", i,
1102 qlcnic_tx_ring_stats_strings[index]);
1103 data += ETH_GSTRING_LEN;
1104 }
1105 }
1106
1080 for (index = 0; index < QLCNIC_STATS_LEN; index++) { 1107 for (index = 0; index < QLCNIC_STATS_LEN; index++) {
1081 memcpy(data + index * ETH_GSTRING_LEN, 1108 memcpy(data + index * ETH_GSTRING_LEN,
1082 qlcnic_gstrings_stats[index].stat_string, 1109 qlcnic_gstrings_stats[index].stat_string,
1083 ETH_GSTRING_LEN); 1110 ETH_GSTRING_LEN);
1084 } 1111 }
1112
1085 if (qlcnic_83xx_check(adapter)) { 1113 if (qlcnic_83xx_check(adapter)) {
1086 num_stats = ARRAY_SIZE(qlcnic_83xx_tx_stats_strings); 1114 num_stats = ARRAY_SIZE(qlcnic_83xx_tx_stats_strings);
1087 for (i = 0; i < num_stats; i++, index++) 1115 for (i = 0; i < num_stats; i++, index++)
@@ -1173,11 +1201,22 @@ static void qlcnic_get_ethtool_stats(struct net_device *dev,
1173 struct ethtool_stats *stats, u64 *data) 1201 struct ethtool_stats *stats, u64 *data)
1174{ 1202{
1175 struct qlcnic_adapter *adapter = netdev_priv(dev); 1203 struct qlcnic_adapter *adapter = netdev_priv(dev);
1204 struct qlcnic_host_tx_ring *tx_ring;
1176 struct qlcnic_esw_statistics port_stats; 1205 struct qlcnic_esw_statistics port_stats;
1177 struct qlcnic_mac_statistics mac_stats; 1206 struct qlcnic_mac_statistics mac_stats;
1178 int index, ret, length, size; 1207 int index, ret, length, size, ring;
1179 char *p; 1208 char *p;
1180 1209
1210 memset(data, 0, adapter->max_drv_tx_rings * 4 * sizeof(u64));
1211 for (ring = 0, index = 0; ring < adapter->max_drv_tx_rings; ring++) {
1212 if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
1213 tx_ring = &adapter->tx_ring[ring];
1214 *data++ = tx_ring->xmit_on;
1215 *data++ = tx_ring->xmit_off;
1216 *data++ = tx_ring->xmit_called;
1217 *data++ = tx_ring->xmit_finished;
1218 }
1219 }
1181 memset(data, 0, stats->n_stats * sizeof(u64)); 1220 memset(data, 0, stats->n_stats * sizeof(u64));
1182 length = QLCNIC_STATS_LEN; 1221 length = QLCNIC_STATS_LEN;
1183 for (index = 0; index < length; index++) { 1222 for (index = 0; index < length; index++) {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
index e9a2225746a7..cf35220cbfad 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
@@ -150,7 +150,6 @@ struct ethtool_stats;
150struct pci_device_id; 150struct pci_device_id;
151struct qlcnic_host_sds_ring; 151struct qlcnic_host_sds_ring;
152struct qlcnic_host_tx_ring; 152struct qlcnic_host_tx_ring;
153struct qlcnic_host_tx_ring;
154struct qlcnic_hardware_context; 153struct qlcnic_hardware_context;
155struct qlcnic_adapter; 154struct qlcnic_adapter;
156 155
@@ -174,7 +173,7 @@ int qlcnic_82xx_set_lb_mode(struct qlcnic_adapter *, u8);
174void qlcnic_82xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t); 173void qlcnic_82xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
175void qlcnic_82xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t); 174void qlcnic_82xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
176void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *, u32); 175void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *, u32);
177int qlcnic_82xx_setup_intr(struct qlcnic_adapter *, u8); 176int qlcnic_82xx_setup_intr(struct qlcnic_adapter *, u8, int);
178irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *); 177irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *);
179int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter, 178int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter,
180 struct qlcnic_cmd_args *); 179 struct qlcnic_cmd_args *);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index af2b2e2bfceb..94b3e820f89e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -656,7 +656,7 @@ static int qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
656 return err; 656 return err;
657} 657}
658 658
659int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr) 659int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr, int txq)
660{ 660{
661 struct qlcnic_hardware_context *ahw = adapter->ahw; 661 struct qlcnic_hardware_context *ahw = adapter->ahw;
662 int num_msix, err = 0; 662 int num_msix, err = 0;
@@ -667,8 +667,11 @@ int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
667 if (ahw->msix_supported) { 667 if (ahw->msix_supported) {
668 num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(), 668 num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
669 num_intr)); 669 num_intr));
670 if (qlcnic_check_multi_tx(adapter)) 670 if (qlcnic_check_multi_tx(adapter)) {
671 if (txq)
672 adapter->max_drv_tx_rings = txq;
671 num_msix += adapter->max_drv_tx_rings; 673 num_msix += adapter->max_drv_tx_rings;
674 }
672 } else { 675 } else {
673 num_msix = 1; 676 num_msix = 1;
674 } 677 }
@@ -1990,11 +1993,9 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
1990 netdev->priv_flags |= IFF_UNICAST_FLT; 1993 netdev->priv_flags |= IFF_UNICAST_FLT;
1991 netdev->irq = adapter->msix_entries[0].vector; 1994 netdev->irq = adapter->msix_entries[0].vector;
1992 1995
1993 if (qlcnic_82xx_check(adapter) && qlcnic_check_multi_tx(adapter)) { 1996 err = qlcnic_set_real_num_queues(adapter, netdev);
1994 err = qlcnic_set_real_num_queues(adapter, netdev); 1997 if (err)
1995 if (err) 1998 return err;
1996 return err;
1997 }
1998 1999
1999 err = register_netdev(netdev); 2000 err = register_netdev(netdev);
2000 if (err) { 2001 if (err) {
@@ -2253,7 +2254,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2253 "Device does not support MSI interrupts\n"); 2254 "Device does not support MSI interrupts\n");
2254 2255
2255 if (qlcnic_82xx_check(adapter)) { 2256 if (qlcnic_82xx_check(adapter)) {
2256 err = qlcnic_setup_intr(adapter, 0); 2257 err = qlcnic_setup_intr(adapter, 0, 0);
2257 if (err) { 2258 if (err) {
2258 dev_err(&pdev->dev, "Failed to setup interrupt\n"); 2259 dev_err(&pdev->dev, "Failed to setup interrupt\n");
2259 goto err_out_disable_msi; 2260 goto err_out_disable_msi;
@@ -3371,7 +3372,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
3371 qlcnic_clr_drv_state(adapter); 3372 qlcnic_clr_drv_state(adapter);
3372 kfree(adapter->msix_entries); 3373 kfree(adapter->msix_entries);
3373 adapter->msix_entries = NULL; 3374 adapter->msix_entries = NULL;
3374 err = qlcnic_setup_intr(adapter, 0); 3375 err = qlcnic_setup_intr(adapter, 0, 0);
3375 3376
3376 if (err) { 3377 if (err) {
3377 kfree(adapter->msix_entries); 3378 kfree(adapter->msix_entries);
@@ -3496,6 +3497,49 @@ qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
3496 return err; 3497 return err;
3497} 3498}
3498 3499
3500int qlcnic_validate_max_tx_rings(struct qlcnic_adapter *adapter, int txq)
3501{
3502 struct net_device *netdev = adapter->netdev;
3503 u8 max_hw = QLCNIC_MAX_TX_RINGS;
3504 u32 max_allowed;
3505
3506 if (!qlcnic_82xx_check(adapter)) {
3507 netdev_err(netdev, "No Multi TX-Q support\n");
3508 return -EINVAL;
3509 }
3510
3511 if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
3512 netdev_err(netdev, "No Multi TX-Q support in INT-x mode\n");
3513 return -EINVAL;
3514 }
3515
3516 if (!qlcnic_check_multi_tx(adapter)) {
3517 netdev_err(netdev, "No Multi TX-Q support\n");
3518 return -EINVAL;
3519 }
3520
3521 if (txq > QLCNIC_MAX_TX_RINGS) {
3522 netdev_err(netdev, "Invalid ring count\n");
3523 return -EINVAL;
3524 }
3525
3526 max_allowed = rounddown_pow_of_two(min_t(int, max_hw,
3527 num_online_cpus()));
3528 if ((txq > max_allowed) || !is_power_of_2(txq)) {
3529 if (!is_power_of_2(txq))
3530 netdev_err(netdev,
3531 "TX queue should be a power of 2\n");
3532 if (txq > num_online_cpus())
3533 netdev_err(netdev,
3534 "Tx queue should not be higher than [%u], number of online CPUs in the system\n",
3535 num_online_cpus());
3536 netdev_err(netdev, "Unable to configure %u Tx rings\n", txq);
3537 return -EINVAL;
3538 }
3539
3540 return 0;
3541}
3542
3499int qlcnic_validate_max_rss(struct qlcnic_adapter *adapter, 3543int qlcnic_validate_max_rss(struct qlcnic_adapter *adapter,
3500 __u32 val) 3544 __u32 val)
3501{ 3545{
@@ -3503,6 +3547,12 @@ int qlcnic_validate_max_rss(struct qlcnic_adapter *adapter,
3503 u8 max_hw = adapter->ahw->max_rx_ques; 3547 u8 max_hw = adapter->ahw->max_rx_ques;
3504 u32 max_allowed; 3548 u32 max_allowed;
3505 3549
3550 if (qlcnic_82xx_check(adapter) && !qlcnic_use_msi_x &&
3551 !qlcnic_use_msi) {
3552 netdev_err(netdev, "No RSS support in INT-x mode\n");
3553 return -EINVAL;
3554 }
3555
3506 if (val > QLCNIC_MAX_SDS_RINGS) { 3556 if (val > QLCNIC_MAX_SDS_RINGS) {
3507 netdev_err(netdev, "RSS value should not be higher than %u\n", 3557 netdev_err(netdev, "RSS value should not be higher than %u\n",
3508 QLCNIC_MAX_SDS_RINGS); 3558 QLCNIC_MAX_SDS_RINGS);
@@ -3535,27 +3585,48 @@ int qlcnic_validate_max_rss(struct qlcnic_adapter *adapter,
3535 return 0; 3585 return 0;
3536} 3586}
3537 3587
3538int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, size_t len) 3588int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, int txq)
3539{ 3589{
3540 int err; 3590 int err;
3541 struct net_device *netdev = adapter->netdev; 3591 struct net_device *netdev = adapter->netdev;
3592 int num_msix;
3542 3593
3543 if (test_bit(__QLCNIC_RESETTING, &adapter->state)) 3594 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
3544 return -EBUSY; 3595 return -EBUSY;
3545 3596
3597 if (qlcnic_82xx_check(adapter) && !qlcnic_use_msi_x &&
3598 !qlcnic_use_msi) {
3599 netdev_err(netdev, "No RSS support in INT-x mode\n");
3600 return -EINVAL;
3601 }
3602
3546 netif_device_detach(netdev); 3603 netif_device_detach(netdev);
3547 if (netif_running(netdev)) 3604 if (netif_running(netdev))
3548 __qlcnic_down(adapter, netdev); 3605 __qlcnic_down(adapter, netdev);
3549 3606
3550 qlcnic_detach(adapter); 3607 qlcnic_detach(adapter);
3551 3608
3609 if (qlcnic_82xx_check(adapter)) {
3610 if (txq != 0)
3611 adapter->max_drv_tx_rings = txq;
3612
3613 if (qlcnic_check_multi_tx(adapter) &&
3614 (txq > adapter->max_drv_tx_rings))
3615 num_msix = adapter->max_drv_tx_rings;
3616 else
3617 num_msix = data;
3618 }
3619
3552 if (qlcnic_83xx_check(adapter)) { 3620 if (qlcnic_83xx_check(adapter)) {
3553 qlcnic_83xx_free_mbx_intr(adapter); 3621 qlcnic_83xx_free_mbx_intr(adapter);
3554 qlcnic_83xx_enable_mbx_poll(adapter); 3622 qlcnic_83xx_enable_mbx_poll(adapter);
3555 } 3623 }
3556 3624
3625 netif_set_real_num_tx_queues(netdev, adapter->max_drv_tx_rings);
3626
3557 qlcnic_teardown_intr(adapter); 3627 qlcnic_teardown_intr(adapter);
3558 err = qlcnic_setup_intr(adapter, data); 3628
3629 err = qlcnic_setup_intr(adapter, data, txq);
3559 if (err) { 3630 if (err) {
3560 kfree(adapter->msix_entries); 3631 kfree(adapter->msix_entries);
3561 netdev_err(netdev, "failed to setup interrupt\n"); 3632 netdev_err(netdev, "failed to setup interrupt\n");
@@ -3583,8 +3654,7 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, size_t len)
3583 goto done; 3654 goto done;
3584 qlcnic_restore_indev_addr(netdev, NETDEV_UP); 3655 qlcnic_restore_indev_addr(netdev, NETDEV_UP);
3585 } 3656 }
3586 err = len; 3657done:
3587 done:
3588 netif_device_attach(netdev); 3658 netif_device_attach(netdev);
3589 clear_bit(__QLCNIC_RESETTING, &adapter->state); 3659 clear_bit(__QLCNIC_RESETTING, &adapter->state);
3590 return err; 3660 return err;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
index b2fbefc0b73e..2f79ec5246dc 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
@@ -512,7 +512,7 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter,
512 dev_warn(&adapter->pdev->dev, 512 dev_warn(&adapter->pdev->dev,
513 "Device does not support MSI interrupts\n"); 513 "Device does not support MSI interrupts\n");
514 514
515 err = qlcnic_setup_intr(adapter, 1); 515 err = qlcnic_setup_intr(adapter, 1, 0);
516 if (err) { 516 if (err) {
517 dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n"); 517 dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");
518 goto err_out_disable_msi; 518 goto err_out_disable_msi;