diff options
Diffstat (limited to 'drivers/net/benet/be_main.c')
-rw-r--r-- | drivers/net/benet/be_main.c | 227 |
1 files changed, 126 insertions, 101 deletions
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; |