diff options
author | Sathya Perla <sathya.perla@emulex.com> | 2011-06-12 16:01:58 -0400 |
---|---|---|
committer | David S. Miller <davem@conan.davemloft.net> | 2011-06-16 23:02:04 -0400 |
commit | 3c8def9776c3d4636291432522ea312f7a44be95 (patch) | |
tree | eec2cc837656dd9ee2a5e16dd7648d6a18e592d1 /drivers/net | |
parent | 15b4d93f0316caec44e07255c1d73bde4fac12e4 (diff) |
be2net: support multiple TX queues
This patch provides support for multiple TX queues.
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
Signed-off-by: David S. Miller <davem@conan.davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/benet/be.h | 13 | ||||
-rw-r--r-- | drivers/net/benet/be_ethtool.c | 50 | ||||
-rw-r--r-- | drivers/net/benet/be_main.c | 227 |
3 files changed, 171 insertions, 119 deletions
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index a7db870d1641..a36f5a6a8462 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h | |||
@@ -87,6 +87,7 @@ static inline char *nic_name(struct pci_dev *pdev) | |||
87 | 87 | ||
88 | #define MAX_RSS_QS 4 /* BE limit is 4 queues/port */ | 88 | #define MAX_RSS_QS 4 /* BE limit is 4 queues/port */ |
89 | #define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */ | 89 | #define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */ |
90 | #define MAX_TX_QS 8 | ||
90 | #define BE_MAX_MSIX_VECTORS (MAX_RX_QS + 1)/* RX + TX */ | 91 | #define BE_MAX_MSIX_VECTORS (MAX_RX_QS + 1)/* RX + TX */ |
91 | #define BE_NAPI_WEIGHT 64 | 92 | #define BE_NAPI_WEIGHT 64 |
92 | #define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ | 93 | #define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ |
@@ -170,7 +171,6 @@ struct be_tx_stats { | |||
170 | u32 be_tx_reqs; /* number of TX requests initiated */ | 171 | u32 be_tx_reqs; /* number of TX requests initiated */ |
171 | u32 be_tx_stops; /* number of times TX Q was stopped */ | 172 | u32 be_tx_stops; /* number of times TX Q was stopped */ |
172 | u32 be_tx_wrbs; /* number of tx WRBs used */ | 173 | u32 be_tx_wrbs; /* number of tx WRBs used */ |
173 | u32 be_tx_events; /* number of tx completion events */ | ||
174 | u32 be_tx_compl; /* number of tx completion entries processed */ | 174 | u32 be_tx_compl; /* number of tx completion entries processed */ |
175 | ulong be_tx_jiffies; | 175 | ulong be_tx_jiffies; |
176 | u64 be_tx_bytes; | 176 | u64 be_tx_bytes; |
@@ -184,6 +184,7 @@ struct be_tx_obj { | |||
184 | struct be_queue_info cq; | 184 | struct be_queue_info cq; |
185 | /* Remember the skbs that were transmitted */ | 185 | /* Remember the skbs that were transmitted */ |
186 | struct sk_buff *sent_skb_list[TX_Q_LEN]; | 186 | struct sk_buff *sent_skb_list[TX_Q_LEN]; |
187 | struct be_tx_stats stats; | ||
187 | }; | 188 | }; |
188 | 189 | ||
189 | /* Struct to remember the pages posted for rx frags */ | 190 | /* Struct to remember the pages posted for rx frags */ |
@@ -319,8 +320,8 @@ struct be_adapter { | |||
319 | 320 | ||
320 | /* TX Rings */ | 321 | /* TX Rings */ |
321 | struct be_eq_obj tx_eq; | 322 | struct be_eq_obj tx_eq; |
322 | struct be_tx_obj tx_obj; | 323 | struct be_tx_obj tx_obj[MAX_TX_QS]; |
323 | struct be_tx_stats tx_stats; | 324 | u8 num_tx_qs; |
324 | 325 | ||
325 | u32 cache_line_break[8]; | 326 | u32 cache_line_break[8]; |
326 | 327 | ||
@@ -391,7 +392,7 @@ struct be_adapter { | |||
391 | extern const struct ethtool_ops be_ethtool_ops; | 392 | extern const struct ethtool_ops be_ethtool_ops; |
392 | 393 | ||
393 | #define msix_enabled(adapter) (adapter->num_msix_vec > 0) | 394 | #define msix_enabled(adapter) (adapter->num_msix_vec > 0) |
394 | #define tx_stats(adapter) (&adapter->tx_stats) | 395 | #define tx_stats(txo) (&txo->stats) |
395 | #define rx_stats(rxo) (&rxo->stats) | 396 | #define rx_stats(rxo) (&rxo->stats) |
396 | 397 | ||
397 | #define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) | 398 | #define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) |
@@ -405,6 +406,10 @@ extern const struct ethtool_ops be_ethtool_ops; | |||
405 | for (i = 0, rxo = &adapter->rx_obj[i+1]; i < (adapter->num_rx_qs - 1);\ | 406 | for (i = 0, rxo = &adapter->rx_obj[i+1]; i < (adapter->num_rx_qs - 1);\ |
406 | i++, rxo++) | 407 | i++, rxo++) |
407 | 408 | ||
409 | #define for_all_tx_queues(adapter, txo, i) \ | ||
410 | for (i = 0, txo = &adapter->tx_obj[i]; i < adapter->num_tx_qs; \ | ||
411 | i++, txo++) | ||
412 | |||
408 | #define PAGE_SHIFT_4K 12 | 413 | #define PAGE_SHIFT_4K 12 |
409 | #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) | 414 | #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) |
410 | 415 | ||
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index facfe3ca5c40..84e03a747868 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c | |||
@@ -52,12 +52,7 @@ static const struct be_ethtool_stat et_stats[] = { | |||
52 | {NETSTAT_INFO(tx_errors)}, | 52 | {NETSTAT_INFO(tx_errors)}, |
53 | {NETSTAT_INFO(rx_dropped)}, | 53 | {NETSTAT_INFO(rx_dropped)}, |
54 | {NETSTAT_INFO(tx_dropped)}, | 54 | {NETSTAT_INFO(tx_dropped)}, |
55 | {DRVSTAT_TX_INFO(be_tx_rate)}, | 55 | {DRVSTAT_INFO(be_tx_events)}, |
56 | {DRVSTAT_TX_INFO(be_tx_reqs)}, | ||
57 | {DRVSTAT_TX_INFO(be_tx_wrbs)}, | ||
58 | {DRVSTAT_TX_INFO(be_tx_stops)}, | ||
59 | {DRVSTAT_TX_INFO(be_tx_events)}, | ||
60 | {DRVSTAT_TX_INFO(be_tx_compl)}, | ||
61 | {DRVSTAT_INFO(rx_crc_errors)}, | 56 | {DRVSTAT_INFO(rx_crc_errors)}, |
62 | {DRVSTAT_INFO(rx_alignment_symbol_errors)}, | 57 | {DRVSTAT_INFO(rx_alignment_symbol_errors)}, |
63 | {DRVSTAT_INFO(rx_pause_frames)}, | 58 | {DRVSTAT_INFO(rx_pause_frames)}, |
@@ -111,6 +106,16 @@ static const struct be_ethtool_stat et_rx_stats[] = { | |||
111 | }; | 106 | }; |
112 | #define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats)) | 107 | #define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats)) |
113 | 108 | ||
109 | /* Stats related to multi TX queues */ | ||
110 | static const struct be_ethtool_stat et_tx_stats[] = { | ||
111 | {DRVSTAT_TX_INFO(be_tx_rate)}, | ||
112 | {DRVSTAT_TX_INFO(be_tx_reqs)}, | ||
113 | {DRVSTAT_TX_INFO(be_tx_wrbs)}, | ||
114 | {DRVSTAT_TX_INFO(be_tx_stops)}, | ||
115 | {DRVSTAT_TX_INFO(be_tx_compl)} | ||
116 | }; | ||
117 | #define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats)) | ||
118 | |||
114 | static const char et_self_tests[][ETH_GSTRING_LEN] = { | 119 | static const char et_self_tests[][ETH_GSTRING_LEN] = { |
115 | "MAC Loopback test", | 120 | "MAC Loopback test", |
116 | "PHY Loopback test", | 121 | "PHY Loopback test", |
@@ -253,17 +258,15 @@ be_get_ethtool_stats(struct net_device *netdev, | |||
253 | { | 258 | { |
254 | struct be_adapter *adapter = netdev_priv(netdev); | 259 | struct be_adapter *adapter = netdev_priv(netdev); |
255 | struct be_rx_obj *rxo; | 260 | struct be_rx_obj *rxo; |
261 | struct be_tx_obj *txo; | ||
256 | void *p = NULL; | 262 | void *p = NULL; |
257 | int i, j; | 263 | int i, j, base; |
258 | 264 | ||
259 | for (i = 0; i < ETHTOOL_STATS_NUM; i++) { | 265 | for (i = 0; i < ETHTOOL_STATS_NUM; i++) { |
260 | switch (et_stats[i].type) { | 266 | switch (et_stats[i].type) { |
261 | case NETSTAT: | 267 | case NETSTAT: |
262 | p = &netdev->stats; | 268 | p = &netdev->stats; |
263 | break; | 269 | break; |
264 | case DRVSTAT_TX: | ||
265 | p = &adapter->tx_stats; | ||
266 | break; | ||
267 | case DRVSTAT: | 270 | case DRVSTAT: |
268 | p = &adapter->drv_stats; | 271 | p = &adapter->drv_stats; |
269 | break; | 272 | break; |
@@ -274,6 +277,7 @@ be_get_ethtool_stats(struct net_device *netdev, | |||
274 | *(u64 *)p: *(u32 *)p; | 277 | *(u64 *)p: *(u32 *)p; |
275 | } | 278 | } |
276 | 279 | ||
280 | base = ETHTOOL_STATS_NUM; | ||
277 | for_all_rx_queues(adapter, rxo, j) { | 281 | for_all_rx_queues(adapter, rxo, j) { |
278 | for (i = 0; i < ETHTOOL_RXSTATS_NUM; i++) { | 282 | for (i = 0; i < ETHTOOL_RXSTATS_NUM; i++) { |
279 | switch (et_rx_stats[i].type) { | 283 | switch (et_rx_stats[i].type) { |
@@ -285,11 +289,21 @@ be_get_ethtool_stats(struct net_device *netdev, | |||
285 | rxo->q.id; | 289 | rxo->q.id; |
286 | break; | 290 | break; |
287 | } | 291 | } |
288 | data[ETHTOOL_STATS_NUM + j * ETHTOOL_RXSTATS_NUM + i] = | 292 | data[base + j * ETHTOOL_RXSTATS_NUM + i] = |
289 | (et_rx_stats[i].size == sizeof(u64)) ? | 293 | (et_rx_stats[i].size == sizeof(u64)) ? |
290 | *(u64 *)p: *(u32 *)p; | 294 | *(u64 *)p: *(u32 *)p; |
291 | } | 295 | } |
292 | } | 296 | } |
297 | |||
298 | base = ETHTOOL_STATS_NUM + adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM; | ||
299 | for_all_tx_queues(adapter, txo, j) { | ||
300 | for (i = 0; i < ETHTOOL_TXSTATS_NUM; i++) { | ||
301 | p = (u8 *)&txo->stats + et_tx_stats[i].offset; | ||
302 | data[base + j * ETHTOOL_TXSTATS_NUM + i] = | ||
303 | (et_tx_stats[i].size == sizeof(u64)) ? | ||
304 | *(u64 *)p: *(u32 *)p; | ||
305 | } | ||
306 | } | ||
293 | } | 307 | } |
294 | 308 | ||
295 | static void | 309 | static void |
@@ -312,6 +326,13 @@ be_get_stat_strings(struct net_device *netdev, uint32_t stringset, | |||
312 | data += ETH_GSTRING_LEN; | 326 | data += ETH_GSTRING_LEN; |
313 | } | 327 | } |
314 | } | 328 | } |
329 | for (i = 0; i < adapter->num_tx_qs; i++) { | ||
330 | for (j = 0; j < ETHTOOL_TXSTATS_NUM; j++) { | ||
331 | sprintf(data, "txq%d: %s", i, | ||
332 | et_tx_stats[j].desc); | ||
333 | data += ETH_GSTRING_LEN; | ||
334 | } | ||
335 | } | ||
315 | break; | 336 | break; |
316 | case ETH_SS_TEST: | 337 | case ETH_SS_TEST: |
317 | for (i = 0; i < ETHTOOL_TESTS_NUM; i++) { | 338 | for (i = 0; i < ETHTOOL_TESTS_NUM; i++) { |
@@ -331,7 +352,8 @@ static int be_get_sset_count(struct net_device *netdev, int stringset) | |||
331 | return ETHTOOL_TESTS_NUM; | 352 | return ETHTOOL_TESTS_NUM; |
332 | case ETH_SS_STATS: | 353 | case ETH_SS_STATS: |
333 | return ETHTOOL_STATS_NUM + | 354 | return ETHTOOL_STATS_NUM + |
334 | adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM; | 355 | adapter->num_rx_qs * ETHTOOL_RXSTATS_NUM + |
356 | adapter->num_tx_qs * ETHTOOL_TXSTATS_NUM; | ||
335 | default: | 357 | default: |
336 | return -EINVAL; | 358 | return -EINVAL; |
337 | } | 359 | } |
@@ -457,10 +479,10 @@ be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) | |||
457 | struct be_adapter *adapter = netdev_priv(netdev); | 479 | struct be_adapter *adapter = netdev_priv(netdev); |
458 | 480 | ||
459 | ring->rx_max_pending = adapter->rx_obj[0].q.len; | 481 | ring->rx_max_pending = adapter->rx_obj[0].q.len; |
460 | ring->tx_max_pending = adapter->tx_obj.q.len; | 482 | ring->tx_max_pending = adapter->tx_obj[0].q.len; |
461 | 483 | ||
462 | ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used); | 484 | ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used); |
463 | ring->tx_pending = atomic_read(&adapter->tx_obj.q.used); | 485 | ring->tx_pending = atomic_read(&adapter->tx_obj[0].q.used); |
464 | } | 486 | } |
465 | 487 | ||
466 | static void | 488 | static void |
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 6ddaa34121e8..c4f564cd745b 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
@@ -427,6 +427,7 @@ void netdev_stats_update(struct be_adapter *adapter) | |||
427 | struct be_drv_stats *drvs = &adapter->drv_stats; | 427 | struct be_drv_stats *drvs = &adapter->drv_stats; |
428 | struct net_device_stats *dev_stats = &adapter->netdev->stats; | 428 | struct net_device_stats *dev_stats = &adapter->netdev->stats; |
429 | struct be_rx_obj *rxo; | 429 | struct be_rx_obj *rxo; |
430 | struct be_tx_obj *txo; | ||
430 | int i; | 431 | int i; |
431 | 432 | ||
432 | memset(dev_stats, 0, sizeof(*dev_stats)); | 433 | memset(dev_stats, 0, sizeof(*dev_stats)); |
@@ -450,8 +451,10 @@ void netdev_stats_update(struct be_adapter *adapter) | |||
450 | } | 451 | } |
451 | } | 452 | } |
452 | 453 | ||
453 | dev_stats->tx_packets = tx_stats(adapter)->be_tx_pkts; | 454 | for_all_tx_queues(adapter, txo, i) { |
454 | dev_stats->tx_bytes = tx_stats(adapter)->be_tx_bytes; | 455 | dev_stats->tx_packets += tx_stats(txo)->be_tx_pkts; |
456 | dev_stats->tx_bytes += tx_stats(txo)->be_tx_bytes; | ||
457 | } | ||
455 | 458 | ||
456 | /* bad pkts received */ | 459 | /* bad pkts received */ |
457 | dev_stats->rx_errors = drvs->rx_crc_errors + | 460 | dev_stats->rx_errors = drvs->rx_crc_errors + |
@@ -554,9 +557,9 @@ static u32 be_calc_rate(u64 bytes, unsigned long ticks) | |||
554 | return rate; | 557 | return rate; |
555 | } | 558 | } |
556 | 559 | ||
557 | static void be_tx_rate_update(struct be_adapter *adapter) | 560 | static void be_tx_rate_update(struct be_tx_obj *txo) |
558 | { | 561 | { |
559 | struct be_tx_stats *stats = tx_stats(adapter); | 562 | struct be_tx_stats *stats = tx_stats(txo); |
560 | ulong now = jiffies; | 563 | ulong now = jiffies; |
561 | 564 | ||
562 | /* Wrapped around? */ | 565 | /* Wrapped around? */ |
@@ -575,10 +578,11 @@ static void be_tx_rate_update(struct be_adapter *adapter) | |||
575 | } | 578 | } |
576 | } | 579 | } |
577 | 580 | ||
578 | static void be_tx_stats_update(struct be_adapter *adapter, | 581 | static void be_tx_stats_update(struct be_tx_obj *txo, |
579 | u32 wrb_cnt, u32 copied, u32 gso_segs, bool stopped) | 582 | u32 wrb_cnt, u32 copied, u32 gso_segs, bool stopped) |
580 | { | 583 | { |
581 | struct be_tx_stats *stats = tx_stats(adapter); | 584 | struct be_tx_stats *stats = tx_stats(txo); |
585 | |||
582 | stats->be_tx_reqs++; | 586 | stats->be_tx_reqs++; |
583 | stats->be_tx_wrbs += wrb_cnt; | 587 | stats->be_tx_wrbs += wrb_cnt; |
584 | stats->be_tx_bytes += copied; | 588 | stats->be_tx_bytes += copied; |
@@ -682,14 +686,13 @@ static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb, | |||
682 | } | 686 | } |
683 | } | 687 | } |
684 | 688 | ||
685 | static int make_tx_wrbs(struct be_adapter *adapter, | 689 | static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq, |
686 | struct sk_buff *skb, u32 wrb_cnt, bool dummy_wrb) | 690 | struct sk_buff *skb, u32 wrb_cnt, bool dummy_wrb) |
687 | { | 691 | { |
688 | dma_addr_t busaddr; | 692 | dma_addr_t busaddr; |
689 | int i, copied = 0; | 693 | int i, copied = 0; |
690 | struct device *dev = &adapter->pdev->dev; | 694 | struct device *dev = &adapter->pdev->dev; |
691 | struct sk_buff *first_skb = skb; | 695 | struct sk_buff *first_skb = skb; |
692 | struct be_queue_info *txq = &adapter->tx_obj.q; | ||
693 | struct be_eth_wrb *wrb; | 696 | struct be_eth_wrb *wrb; |
694 | struct be_eth_hdr_wrb *hdr; | 697 | struct be_eth_hdr_wrb *hdr; |
695 | bool map_single = false; | 698 | bool map_single = false; |
@@ -753,19 +756,19 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, | |||
753 | struct net_device *netdev) | 756 | struct net_device *netdev) |
754 | { | 757 | { |
755 | struct be_adapter *adapter = netdev_priv(netdev); | 758 | struct be_adapter *adapter = netdev_priv(netdev); |
756 | struct be_tx_obj *tx_obj = &adapter->tx_obj; | 759 | struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)]; |
757 | struct be_queue_info *txq = &tx_obj->q; | 760 | struct be_queue_info *txq = &txo->q; |
758 | u32 wrb_cnt = 0, copied = 0; | 761 | u32 wrb_cnt = 0, copied = 0; |
759 | u32 start = txq->head; | 762 | u32 start = txq->head; |
760 | bool dummy_wrb, stopped = false; | 763 | bool dummy_wrb, stopped = false; |
761 | 764 | ||
762 | wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb); | 765 | wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb); |
763 | 766 | ||
764 | copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb); | 767 | copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb); |
765 | if (copied) { | 768 | if (copied) { |
766 | /* record the sent skb in the sent_skb table */ | 769 | /* record the sent skb in the sent_skb table */ |
767 | BUG_ON(tx_obj->sent_skb_list[start]); | 770 | BUG_ON(txo->sent_skb_list[start]); |
768 | tx_obj->sent_skb_list[start] = skb; | 771 | txo->sent_skb_list[start] = skb; |
769 | 772 | ||
770 | /* Ensure txq has space for the next skb; Else stop the queue | 773 | /* Ensure txq has space for the next skb; Else stop the queue |
771 | * *BEFORE* ringing the tx doorbell, so that we serialze the | 774 | * *BEFORE* ringing the tx doorbell, so that we serialze the |
@@ -774,13 +777,13 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, | |||
774 | atomic_add(wrb_cnt, &txq->used); | 777 | atomic_add(wrb_cnt, &txq->used); |
775 | if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >= | 778 | if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >= |
776 | txq->len) { | 779 | txq->len) { |
777 | netif_stop_queue(netdev); | 780 | netif_stop_subqueue(netdev, skb_get_queue_mapping(skb)); |
778 | stopped = true; | 781 | stopped = true; |
779 | } | 782 | } |
780 | 783 | ||
781 | be_txq_notify(adapter, txq->id, wrb_cnt); | 784 | be_txq_notify(adapter, txq->id, wrb_cnt); |
782 | 785 | ||
783 | be_tx_stats_update(adapter, wrb_cnt, copied, | 786 | be_tx_stats_update(txo, wrb_cnt, copied, |
784 | skb_shinfo(skb)->gso_segs, stopped); | 787 | skb_shinfo(skb)->gso_segs, stopped); |
785 | } else { | 788 | } else { |
786 | txq->head = start; | 789 | txq->head = start; |
@@ -1459,11 +1462,12 @@ static struct be_eth_tx_compl *be_tx_compl_get(struct be_queue_info *tx_cq) | |||
1459 | return txcp; | 1462 | return txcp; |
1460 | } | 1463 | } |
1461 | 1464 | ||
1462 | static u16 be_tx_compl_process(struct be_adapter *adapter, u16 last_index) | 1465 | static u16 be_tx_compl_process(struct be_adapter *adapter, |
1466 | struct be_tx_obj *txo, u16 last_index) | ||
1463 | { | 1467 | { |
1464 | struct be_queue_info *txq = &adapter->tx_obj.q; | 1468 | struct be_queue_info *txq = &txo->q; |
1465 | struct be_eth_wrb *wrb; | 1469 | struct be_eth_wrb *wrb; |
1466 | struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; | 1470 | struct sk_buff **sent_skbs = txo->sent_skb_list; |
1467 | struct sk_buff *sent_skb; | 1471 | struct sk_buff *sent_skb; |
1468 | u16 cur_index, num_wrbs = 1; /* account for hdr wrb */ | 1472 | u16 cur_index, num_wrbs = 1; /* account for hdr wrb */ |
1469 | bool unmap_skb_hdr = true; | 1473 | bool unmap_skb_hdr = true; |
@@ -1504,7 +1508,8 @@ static inline struct be_eq_entry *event_get(struct be_eq_obj *eq_obj) | |||
1504 | } | 1508 | } |
1505 | 1509 | ||
1506 | static int event_handle(struct be_adapter *adapter, | 1510 | static int event_handle(struct be_adapter *adapter, |
1507 | struct be_eq_obj *eq_obj) | 1511 | struct be_eq_obj *eq_obj, |
1512 | bool rearm) | ||
1508 | { | 1513 | { |
1509 | struct be_eq_entry *eqe; | 1514 | struct be_eq_entry *eqe; |
1510 | u16 num = 0; | 1515 | u16 num = 0; |
@@ -1517,7 +1522,10 @@ static int event_handle(struct be_adapter *adapter, | |||
1517 | /* Deal with any spurious interrupts that come | 1522 | /* Deal with any spurious interrupts that come |
1518 | * without events | 1523 | * without events |
1519 | */ | 1524 | */ |
1520 | be_eq_notify(adapter, eq_obj->q.id, true, true, num); | 1525 | if (!num) |
1526 | rearm = true; | ||
1527 | |||
1528 | be_eq_notify(adapter, eq_obj->q.id, rearm, true, num); | ||
1521 | if (num) | 1529 | if (num) |
1522 | napi_schedule(&eq_obj->napi); | 1530 | napi_schedule(&eq_obj->napi); |
1523 | 1531 | ||
@@ -1565,13 +1573,14 @@ static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo) | |||
1565 | BUG_ON(atomic_read(&rxq->used)); | 1573 | BUG_ON(atomic_read(&rxq->used)); |
1566 | } | 1574 | } |
1567 | 1575 | ||
1568 | static void be_tx_compl_clean(struct be_adapter *adapter) | 1576 | static void be_tx_compl_clean(struct be_adapter *adapter, |
1577 | struct be_tx_obj *txo) | ||
1569 | { | 1578 | { |
1570 | struct be_queue_info *tx_cq = &adapter->tx_obj.cq; | 1579 | struct be_queue_info *tx_cq = &txo->cq; |
1571 | struct be_queue_info *txq = &adapter->tx_obj.q; | 1580 | struct be_queue_info *txq = &txo->q; |
1572 | struct be_eth_tx_compl *txcp; | 1581 | struct be_eth_tx_compl *txcp; |
1573 | u16 end_idx, cmpl = 0, timeo = 0, num_wrbs = 0; | 1582 | u16 end_idx, cmpl = 0, timeo = 0, num_wrbs = 0; |
1574 | struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; | 1583 | struct sk_buff **sent_skbs = txo->sent_skb_list; |
1575 | struct sk_buff *sent_skb; | 1584 | struct sk_buff *sent_skb; |
1576 | bool dummy_wrb; | 1585 | bool dummy_wrb; |
1577 | 1586 | ||
@@ -1580,7 +1589,7 @@ static void be_tx_compl_clean(struct be_adapter *adapter) | |||
1580 | while ((txcp = be_tx_compl_get(tx_cq))) { | 1589 | while ((txcp = be_tx_compl_get(tx_cq))) { |
1581 | end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, | 1590 | end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, |
1582 | wrb_index, txcp); | 1591 | wrb_index, txcp); |
1583 | num_wrbs += be_tx_compl_process(adapter, end_idx); | 1592 | num_wrbs += be_tx_compl_process(adapter, txo, end_idx); |
1584 | cmpl++; | 1593 | cmpl++; |
1585 | } | 1594 | } |
1586 | if (cmpl) { | 1595 | if (cmpl) { |
@@ -1607,7 +1616,7 @@ static void be_tx_compl_clean(struct be_adapter *adapter) | |||
1607 | index_adv(&end_idx, | 1616 | index_adv(&end_idx, |
1608 | wrb_cnt_for_skb(adapter, sent_skb, &dummy_wrb) - 1, | 1617 | wrb_cnt_for_skb(adapter, sent_skb, &dummy_wrb) - 1, |
1609 | txq->len); | 1618 | txq->len); |
1610 | num_wrbs = be_tx_compl_process(adapter, end_idx); | 1619 | num_wrbs = be_tx_compl_process(adapter, txo, end_idx); |
1611 | atomic_sub(num_wrbs, &txq->used); | 1620 | atomic_sub(num_wrbs, &txq->used); |
1612 | } | 1621 | } |
1613 | } | 1622 | } |
@@ -1666,16 +1675,20 @@ err: | |||
1666 | static void be_tx_queues_destroy(struct be_adapter *adapter) | 1675 | static void be_tx_queues_destroy(struct be_adapter *adapter) |
1667 | { | 1676 | { |
1668 | struct be_queue_info *q; | 1677 | struct be_queue_info *q; |
1678 | struct be_tx_obj *txo; | ||
1679 | u8 i; | ||
1669 | 1680 | ||
1670 | q = &adapter->tx_obj.q; | 1681 | for_all_tx_queues(adapter, txo, i) { |
1671 | if (q->created) | 1682 | q = &txo->q; |
1672 | be_cmd_q_destroy(adapter, q, QTYPE_TXQ); | 1683 | if (q->created) |
1673 | be_queue_free(adapter, q); | 1684 | be_cmd_q_destroy(adapter, q, QTYPE_TXQ); |
1685 | be_queue_free(adapter, q); | ||
1674 | 1686 | ||
1675 | q = &adapter->tx_obj.cq; | 1687 | q = &txo->cq; |
1676 | if (q->created) | 1688 | if (q->created) |
1677 | be_cmd_q_destroy(adapter, q, QTYPE_CQ); | 1689 | be_cmd_q_destroy(adapter, q, QTYPE_CQ); |
1678 | be_queue_free(adapter, q); | 1690 | be_queue_free(adapter, q); |
1691 | } | ||
1679 | 1692 | ||
1680 | /* Clear any residual events */ | 1693 | /* Clear any residual events */ |
1681 | be_eq_clean(adapter, &adapter->tx_eq); | 1694 | be_eq_clean(adapter, &adapter->tx_eq); |
@@ -1686,56 +1699,48 @@ static void be_tx_queues_destroy(struct be_adapter *adapter) | |||
1686 | be_queue_free(adapter, q); | 1699 | be_queue_free(adapter, q); |
1687 | } | 1700 | } |
1688 | 1701 | ||
1702 | /* One TX event queue is shared by all TX compl qs */ | ||
1689 | static int be_tx_queues_create(struct be_adapter *adapter) | 1703 | static int be_tx_queues_create(struct be_adapter *adapter) |
1690 | { | 1704 | { |
1691 | struct be_queue_info *eq, *q, *cq; | 1705 | struct be_queue_info *eq, *q, *cq; |
1706 | struct be_tx_obj *txo; | ||
1707 | u8 i; | ||
1692 | 1708 | ||
1693 | adapter->tx_eq.max_eqd = 0; | 1709 | adapter->tx_eq.max_eqd = 0; |
1694 | adapter->tx_eq.min_eqd = 0; | 1710 | adapter->tx_eq.min_eqd = 0; |
1695 | adapter->tx_eq.cur_eqd = 96; | 1711 | adapter->tx_eq.cur_eqd = 96; |
1696 | adapter->tx_eq.enable_aic = false; | 1712 | adapter->tx_eq.enable_aic = false; |
1697 | /* Alloc Tx Event queue */ | 1713 | |
1698 | eq = &adapter->tx_eq.q; | 1714 | eq = &adapter->tx_eq.q; |
1699 | if (be_queue_alloc(adapter, eq, EVNT_Q_LEN, sizeof(struct be_eq_entry))) | 1715 | if (be_queue_alloc(adapter, eq, EVNT_Q_LEN, |
1716 | sizeof(struct be_eq_entry))) | ||
1700 | return -1; | 1717 | return -1; |
1701 | 1718 | ||
1702 | /* Ask BE to create Tx Event queue */ | ||
1703 | if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd)) | 1719 | if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd)) |
1704 | goto tx_eq_free; | 1720 | goto err; |
1705 | |||
1706 | adapter->tx_eq.eq_idx = adapter->eq_next_idx++; | 1721 | adapter->tx_eq.eq_idx = adapter->eq_next_idx++; |
1707 | 1722 | ||
1708 | 1723 | for_all_tx_queues(adapter, txo, i) { | |
1709 | /* Alloc TX eth compl queue */ | 1724 | cq = &txo->cq; |
1710 | cq = &adapter->tx_obj.cq; | 1725 | if (be_queue_alloc(adapter, cq, TX_CQ_LEN, |
1711 | if (be_queue_alloc(adapter, cq, TX_CQ_LEN, | ||
1712 | sizeof(struct be_eth_tx_compl))) | 1726 | sizeof(struct be_eth_tx_compl))) |
1713 | goto tx_eq_destroy; | 1727 | goto err; |
1714 | 1728 | ||
1715 | /* Ask BE to create Tx eth compl queue */ | 1729 | if (be_cmd_cq_create(adapter, cq, eq, false, false, 3)) |
1716 | if (be_cmd_cq_create(adapter, cq, eq, false, false, 3)) | 1730 | goto err; |
1717 | goto tx_cq_free; | ||
1718 | 1731 | ||
1719 | /* Alloc TX eth queue */ | 1732 | q = &txo->q; |
1720 | q = &adapter->tx_obj.q; | 1733 | if (be_queue_alloc(adapter, q, TX_Q_LEN, |
1721 | if (be_queue_alloc(adapter, q, TX_Q_LEN, sizeof(struct be_eth_wrb))) | 1734 | sizeof(struct be_eth_wrb))) |
1722 | goto tx_cq_destroy; | 1735 | goto err; |
1723 | 1736 | ||
1724 | /* Ask BE to create Tx eth queue */ | 1737 | if (be_cmd_txq_create(adapter, q, cq)) |
1725 | if (be_cmd_txq_create(adapter, q, cq)) | 1738 | goto err; |
1726 | goto tx_q_free; | 1739 | } |
1727 | return 0; | 1740 | return 0; |
1728 | 1741 | ||
1729 | tx_q_free: | 1742 | err: |
1730 | be_queue_free(adapter, q); | 1743 | be_tx_queues_destroy(adapter); |
1731 | tx_cq_destroy: | ||
1732 | be_cmd_q_destroy(adapter, cq, QTYPE_CQ); | ||
1733 | tx_cq_free: | ||
1734 | be_queue_free(adapter, cq); | ||
1735 | tx_eq_destroy: | ||
1736 | be_cmd_q_destroy(adapter, eq, QTYPE_EQ); | ||
1737 | tx_eq_free: | ||
1738 | be_queue_free(adapter, eq); | ||
1739 | return -1; | 1744 | return -1; |
1740 | } | 1745 | } |
1741 | 1746 | ||
@@ -1876,10 +1881,10 @@ static irqreturn_t be_intx(int irq, void *dev) | |||
1876 | 1881 | ||
1877 | if (lancer_chip(adapter)) { | 1882 | if (lancer_chip(adapter)) { |
1878 | if (event_peek(&adapter->tx_eq)) | 1883 | if (event_peek(&adapter->tx_eq)) |
1879 | tx = event_handle(adapter, &adapter->tx_eq); | 1884 | tx = event_handle(adapter, &adapter->tx_eq, false); |
1880 | for_all_rx_queues(adapter, rxo, i) { | 1885 | for_all_rx_queues(adapter, rxo, i) { |
1881 | if (event_peek(&rxo->rx_eq)) | 1886 | if (event_peek(&rxo->rx_eq)) |
1882 | rx |= event_handle(adapter, &rxo->rx_eq); | 1887 | rx |= event_handle(adapter, &rxo->rx_eq, true); |
1883 | } | 1888 | } |
1884 | 1889 | ||
1885 | if (!(tx || rx)) | 1890 | if (!(tx || rx)) |
@@ -1892,11 +1897,11 @@ static irqreturn_t be_intx(int irq, void *dev) | |||
1892 | return IRQ_NONE; | 1897 | return IRQ_NONE; |
1893 | 1898 | ||
1894 | if ((1 << adapter->tx_eq.eq_idx & isr)) | 1899 | if ((1 << adapter->tx_eq.eq_idx & isr)) |
1895 | event_handle(adapter, &adapter->tx_eq); | 1900 | event_handle(adapter, &adapter->tx_eq, false); |
1896 | 1901 | ||
1897 | for_all_rx_queues(adapter, rxo, i) { | 1902 | for_all_rx_queues(adapter, rxo, i) { |
1898 | if ((1 << rxo->rx_eq.eq_idx & isr)) | 1903 | if ((1 << rxo->rx_eq.eq_idx & isr)) |
1899 | event_handle(adapter, &rxo->rx_eq); | 1904 | event_handle(adapter, &rxo->rx_eq, true); |
1900 | } | 1905 | } |
1901 | } | 1906 | } |
1902 | 1907 | ||
@@ -1908,7 +1913,7 @@ static irqreturn_t be_msix_rx(int irq, void *dev) | |||
1908 | struct be_rx_obj *rxo = dev; | 1913 | struct be_rx_obj *rxo = dev; |
1909 | struct be_adapter *adapter = rxo->adapter; | 1914 | struct be_adapter *adapter = rxo->adapter; |
1910 | 1915 | ||
1911 | event_handle(adapter, &rxo->rx_eq); | 1916 | event_handle(adapter, &rxo->rx_eq, true); |
1912 | 1917 | ||
1913 | return IRQ_HANDLED; | 1918 | return IRQ_HANDLED; |
1914 | } | 1919 | } |
@@ -1917,7 +1922,7 @@ static irqreturn_t be_msix_tx_mcc(int irq, void *dev) | |||
1917 | { | 1922 | { |
1918 | struct be_adapter *adapter = dev; | 1923 | struct be_adapter *adapter = dev; |
1919 | 1924 | ||
1920 | event_handle(adapter, &adapter->tx_eq); | 1925 | event_handle(adapter, &adapter->tx_eq, false); |
1921 | 1926 | ||
1922 | return IRQ_HANDLED; | 1927 | return IRQ_HANDLED; |
1923 | } | 1928 | } |
@@ -1978,45 +1983,48 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget) | |||
1978 | struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); | 1983 | struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); |
1979 | struct be_adapter *adapter = | 1984 | struct be_adapter *adapter = |
1980 | container_of(tx_eq, struct be_adapter, tx_eq); | 1985 | container_of(tx_eq, struct be_adapter, tx_eq); |
1981 | struct be_queue_info *txq = &adapter->tx_obj.q; | 1986 | struct be_tx_obj *txo; |
1982 | struct be_queue_info *tx_cq = &adapter->tx_obj.cq; | ||
1983 | struct be_eth_tx_compl *txcp; | 1987 | struct be_eth_tx_compl *txcp; |
1984 | int tx_compl = 0, mcc_compl, status = 0; | 1988 | int tx_compl, mcc_compl, status = 0; |
1985 | u16 end_idx, num_wrbs = 0; | 1989 | u8 i; |
1990 | u16 num_wrbs; | ||
1991 | |||
1992 | for_all_tx_queues(adapter, txo, i) { | ||
1993 | tx_compl = 0; | ||
1994 | num_wrbs = 0; | ||
1995 | while ((txcp = be_tx_compl_get(&txo->cq))) { | ||
1996 | num_wrbs += be_tx_compl_process(adapter, txo, | ||
1997 | AMAP_GET_BITS(struct amap_eth_tx_compl, | ||
1998 | wrb_index, txcp)); | ||
1999 | tx_compl++; | ||
2000 | } | ||
2001 | if (tx_compl) { | ||
2002 | be_cq_notify(adapter, txo->cq.id, true, tx_compl); | ||
2003 | |||
2004 | atomic_sub(num_wrbs, &txo->q.used); | ||
1986 | 2005 | ||
1987 | while ((txcp = be_tx_compl_get(tx_cq))) { | 2006 | /* As Tx wrbs have been freed up, wake up netdev queue |
1988 | end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, | 2007 | * if it was stopped due to lack of tx wrbs. */ |
1989 | wrb_index, txcp); | 2008 | if (__netif_subqueue_stopped(adapter->netdev, i) && |
1990 | num_wrbs += be_tx_compl_process(adapter, end_idx); | 2009 | atomic_read(&txo->q.used) < txo->q.len / 2) { |
1991 | tx_compl++; | 2010 | netif_wake_subqueue(adapter->netdev, i); |
2011 | } | ||
2012 | |||
2013 | adapter->drv_stats.be_tx_events++; | ||
2014 | txo->stats.be_tx_compl += tx_compl; | ||
2015 | } | ||
1992 | } | 2016 | } |
1993 | 2017 | ||
1994 | mcc_compl = be_process_mcc(adapter, &status); | 2018 | mcc_compl = be_process_mcc(adapter, &status); |
1995 | 2019 | ||
1996 | napi_complete(napi); | ||
1997 | |||
1998 | if (mcc_compl) { | 2020 | if (mcc_compl) { |
1999 | struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; | 2021 | struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; |
2000 | be_cq_notify(adapter, mcc_obj->cq.id, true, mcc_compl); | 2022 | be_cq_notify(adapter, mcc_obj->cq.id, true, mcc_compl); |
2001 | } | 2023 | } |
2002 | 2024 | ||
2003 | if (tx_compl) { | 2025 | napi_complete(napi); |
2004 | be_cq_notify(adapter, adapter->tx_obj.cq.id, true, tx_compl); | ||
2005 | |||
2006 | atomic_sub(num_wrbs, &txq->used); | ||
2007 | |||
2008 | /* As Tx wrbs have been freed up, wake up netdev queue if | ||
2009 | * it was stopped due to lack of tx wrbs. | ||
2010 | */ | ||
2011 | if (netif_queue_stopped(adapter->netdev) && | ||
2012 | atomic_read(&txq->used) < txq->len / 2) { | ||
2013 | netif_wake_queue(adapter->netdev); | ||
2014 | } | ||
2015 | |||
2016 | tx_stats(adapter)->be_tx_events++; | ||
2017 | tx_stats(adapter)->be_tx_compl += tx_compl; | ||
2018 | } | ||
2019 | 2026 | ||
2027 | be_eq_notify(adapter, tx_eq->q.id, true, false, 0); | ||
2020 | return 1; | 2028 | return 1; |
2021 | } | 2029 | } |
2022 | 2030 | ||
@@ -2065,6 +2073,7 @@ static void be_worker(struct work_struct *work) | |||
2065 | struct be_adapter *adapter = | 2073 | struct be_adapter *adapter = |
2066 | container_of(work, struct be_adapter, work.work); | 2074 | container_of(work, struct be_adapter, work.work); |
2067 | struct be_rx_obj *rxo; | 2075 | struct be_rx_obj *rxo; |
2076 | struct be_tx_obj *txo; | ||
2068 | int i; | 2077 | int i; |
2069 | 2078 | ||
2070 | if (!adapter->ue_detected && !lancer_chip(adapter)) | 2079 | if (!adapter->ue_detected && !lancer_chip(adapter)) |
@@ -2092,7 +2101,9 @@ static void be_worker(struct work_struct *work) | |||
2092 | else | 2101 | else |
2093 | be_cmd_get_stats(adapter, &adapter->stats_cmd); | 2102 | be_cmd_get_stats(adapter, &adapter->stats_cmd); |
2094 | } | 2103 | } |
2095 | be_tx_rate_update(adapter); | 2104 | |
2105 | for_all_tx_queues(adapter, txo, i) | ||
2106 | be_tx_rate_update(txo); | ||
2096 | 2107 | ||
2097 | for_all_rx_queues(adapter, rxo, i) { | 2108 | for_all_rx_queues(adapter, rxo, i) { |
2098 | be_rx_rate_update(rxo); | 2109 | be_rx_rate_update(rxo); |
@@ -2294,6 +2305,7 @@ static int be_close(struct net_device *netdev) | |||
2294 | { | 2305 | { |
2295 | struct be_adapter *adapter = netdev_priv(netdev); | 2306 | struct be_adapter *adapter = netdev_priv(netdev); |
2296 | struct be_rx_obj *rxo; | 2307 | struct be_rx_obj *rxo; |
2308 | struct be_tx_obj *txo; | ||
2297 | struct be_eq_obj *tx_eq = &adapter->tx_eq; | 2309 | struct be_eq_obj *tx_eq = &adapter->tx_eq; |
2298 | int vec, i; | 2310 | int vec, i; |
2299 | 2311 | ||
@@ -2311,10 +2323,11 @@ static int be_close(struct net_device *netdev) | |||
2311 | napi_disable(&tx_eq->napi); | 2323 | napi_disable(&tx_eq->napi); |
2312 | 2324 | ||
2313 | if (lancer_chip(adapter)) { | 2325 | if (lancer_chip(adapter)) { |
2314 | be_cq_notify(adapter, adapter->tx_obj.cq.id, false, 0); | ||
2315 | be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0); | 2326 | be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0); |
2316 | for_all_rx_queues(adapter, rxo, i) | 2327 | for_all_rx_queues(adapter, rxo, i) |
2317 | be_cq_notify(adapter, rxo->cq.id, false, 0); | 2328 | be_cq_notify(adapter, rxo->cq.id, false, 0); |
2329 | for_all_tx_queues(adapter, txo, i) | ||
2330 | be_cq_notify(adapter, txo->cq.id, false, 0); | ||
2318 | } | 2331 | } |
2319 | 2332 | ||
2320 | if (msix_enabled(adapter)) { | 2333 | if (msix_enabled(adapter)) { |
@@ -2333,7 +2346,8 @@ static int be_close(struct net_device *netdev) | |||
2333 | /* Wait for all pending tx completions to arrive so that | 2346 | /* Wait for all pending tx completions to arrive so that |
2334 | * all tx skbs are freed. | 2347 | * all tx skbs are freed. |
2335 | */ | 2348 | */ |
2336 | be_tx_compl_clean(adapter); | 2349 | for_all_tx_queues(adapter, txo, i) |
2350 | be_tx_compl_clean(adapter, txo); | ||
2337 | 2351 | ||
2338 | return 0; | 2352 | return 0; |
2339 | } | 2353 | } |
@@ -3183,6 +3197,17 @@ static int be_get_config(struct be_adapter *adapter) | |||
3183 | return status; | 3197 | return status; |
3184 | 3198 | ||
3185 | be_cmd_check_native_mode(adapter); | 3199 | be_cmd_check_native_mode(adapter); |
3200 | |||
3201 | if ((num_vfs && adapter->sriov_enabled) || | ||
3202 | (adapter->function_mode & 0x400) || | ||
3203 | lancer_chip(adapter) || !be_physfn(adapter)) { | ||
3204 | adapter->num_tx_qs = 1; | ||
3205 | netif_set_real_num_tx_queues(adapter->netdev, | ||
3206 | adapter->num_tx_qs); | ||
3207 | } else { | ||
3208 | adapter->num_tx_qs = MAX_TX_QS; | ||
3209 | } | ||
3210 | |||
3186 | return 0; | 3211 | return 0; |
3187 | } | 3212 | } |
3188 | 3213 | ||
@@ -3285,7 +3310,7 @@ static int __devinit be_probe(struct pci_dev *pdev, | |||
3285 | goto disable_dev; | 3310 | goto disable_dev; |
3286 | pci_set_master(pdev); | 3311 | pci_set_master(pdev); |
3287 | 3312 | ||
3288 | netdev = alloc_etherdev(sizeof(struct be_adapter)); | 3313 | netdev = alloc_etherdev_mq(sizeof(struct be_adapter), MAX_TX_QS); |
3289 | if (netdev == NULL) { | 3314 | if (netdev == NULL) { |
3290 | status = -ENOMEM; | 3315 | status = -ENOMEM; |
3291 | goto rel_reg; | 3316 | goto rel_reg; |