ixgbe: Introduce Multiqueue TX
authorAyyappan Veeraiyan <ayyappan.veeraiyan@intel.com>
Mon, 3 Mar 2008 23:03:52 +0000 (15:03 -0800)
committerJeff Garzik <jeff@garzik.org>
Mon, 17 Mar 2008 11:49:28 +0000 (07:49 -0400)
Now that the irq vector code is in place, we can add the conditional
multiqueue TX code in the driver. This requires the optional
CONFIG_NETDEVICES_MULTIQUEUE=y and will not be enabled without
it.

Signed-off-by: Ayyappan Veeraiyan <ayyappan.veeraiyan@intel.com>
Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>
Acked-by: Waskiewicz Jr, Peter P <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/net/ixgbe/ixgbe_ethtool.c
drivers/net/ixgbe/ixgbe_main.c

index a119cbd8dbb8b2aad03186d12a8e2150f3752a1b..85b7d15e12171bc0cfc7038461d24c676154d022 100644 (file)
@@ -246,13 +246,26 @@ static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data)
 
 static int ixgbe_set_tso(struct net_device *netdev, u32 data)
 {
-
        if (data) {
                netdev->features |= NETIF_F_TSO;
                netdev->features |= NETIF_F_TSO6;
        } else {
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+               struct ixgbe_adapter *adapter = netdev_priv(netdev);
+               int i;
+#endif
+               netif_stop_queue(netdev);
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+               for (i = 0; i < adapter->num_tx_queues; i++)
+                       netif_stop_subqueue(netdev, i);
+#endif
                netdev->features &= ~NETIF_F_TSO;
                netdev->features &= ~NETIF_F_TSO6;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+               for (i = 0; i < adapter->num_tx_queues; i++)
+                       netif_start_subqueue(netdev, i);
+#endif
+               netif_start_queue(netdev);
        }
        return 0;
 }
index fecc8ea79e9d683e8a01ba55b3295b005742df29..fc1c226f5751cdd5dba220b0dcfe5767b9a8fdac 100644 (file)
@@ -256,16 +256,28 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter,
                 * sees the new next_to_clean.
                 */
                smp_mb();
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+               if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) &&
+                   !test_bit(__IXGBE_DOWN, &adapter->state)) {
+                       netif_wake_subqueue(netdev, tx_ring->queue_index);
+                       adapter->restart_queue++;
+               }
+#else
                if (netif_queue_stopped(netdev) &&
                    !test_bit(__IXGBE_DOWN, &adapter->state)) {
                        netif_wake_queue(netdev);
                        adapter->restart_queue++;
                }
+#endif
        }
 
        if (adapter->detect_tx_hung)
                if (ixgbe_check_tx_hang(adapter, tx_ring, eop, eop_desc))
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+                       netif_stop_subqueue(netdev, tx_ring->queue_index);
+#else
                        netif_stop_queue(netdev);
+#endif
 
        if (total_tx_packets >= tx_ring->work_limit)
                IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->eims_value);
@@ -1812,7 +1824,11 @@ static void __devinit ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
                case (IXGBE_FLAG_RSS_ENABLED):
                        rss_m = 0xF;
                        nrq = rss_i;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+                       ntq = rss_i;
+#else
                        ntq = 1;
+#endif
                        break;
                case 0:
                default:
@@ -1986,6 +2002,10 @@ try_msi:
        }
 
 out:
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+       /* Notify the stack of the (possibly) reduced Tx Queue count. */
+       adapter->netdev->egress_subqueue_count = adapter->num_tx_queues;
+#endif
 
        return err;
 }
@@ -2504,6 +2524,9 @@ static void ixgbe_watchdog(unsigned long data)
        struct net_device *netdev = adapter->netdev;
        bool link_up;
        u32 link_speed = 0;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+       int i;
+#endif
 
        adapter->hw.mac.ops.check_link(&adapter->hw, &(link_speed), &link_up);
 
@@ -2525,6 +2548,10 @@ static void ixgbe_watchdog(unsigned long data)
 
                        netif_carrier_on(netdev);
                        netif_wake_queue(netdev);
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+                       for (i = 0; i < adapter->num_tx_queues; i++)
+                               netif_wake_subqueue(netdev, i);
+#endif
                } else {
                        /* Force detection of hung controller */
                        adapter->detect_tx_hung = true;
@@ -2568,7 +2595,6 @@ static int ixgbe_tso(struct ixgbe_adapter *adapter,
        struct ixgbe_tx_buffer *tx_buffer_info;
        u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
        u32 mss_l4len_idx = 0, l4len;
-       *hdr_len = 0;
 
        if (skb_is_gso(skb)) {
                if (skb_header_cloned(skb)) {
@@ -2852,7 +2878,11 @@ static int __ixgbe_maybe_stop_tx(struct net_device *netdev,
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+       netif_stop_subqueue(netdev, tx_ring->queue_index);
+#else
        netif_stop_queue(netdev);
+#endif
        /* Herbert's original patch had:
         *  smp_mb__after_netif_stop_queue();
         * but since that doesn't exist yet, just open code it. */
@@ -2864,7 +2894,11 @@ static int __ixgbe_maybe_stop_tx(struct net_device *netdev,
                return -EBUSY;
 
        /* A reprieve! - use start_queue because it doesn't call schedule */
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+       netif_wake_subqueue(netdev, tx_ring->queue_index);
+#else
        netif_wake_queue(netdev);
+#endif
        ++adapter->restart_queue;
        return 0;
 }
@@ -2885,15 +2919,18 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        unsigned int len = skb->len;
        unsigned int first;
        unsigned int tx_flags = 0;
-       u8 hdr_len;
-       int tso;
+       u8 hdr_len = 0;
+       int r_idx = 0, tso;
        unsigned int mss = 0;
        int count = 0;
        unsigned int f;
        unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
        len -= skb->data_len;
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+       r_idx = (adapter->num_tx_queues - 1) & skb->queue_mapping;
+#endif
+       tx_ring = &adapter->tx_ring[r_idx];
 
-       tx_ring = adapter->tx_ring;
 
        if (skb->len <= 0) {
                dev_kfree_skb(skb);
@@ -3078,7 +3115,11 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 
        pci_set_master(pdev);
 
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+       netdev = alloc_etherdev_mq(sizeof(struct ixgbe_adapter), MAX_TX_QUEUES);
+#else
        netdev = alloc_etherdev(sizeof(struct ixgbe_adapter));
+#endif
        if (!netdev) {
                err = -ENOMEM;
                goto err_alloc_etherdev;
@@ -3164,6 +3205,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
        if (pci_using_dac)
                netdev->features |= NETIF_F_HIGHDMA;
 
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+       netdev->features |= NETIF_F_MULTI_QUEUE;
+#endif
 
        /* make sure the EEPROM is good */
        if (ixgbe_validate_eeprom_checksum(hw, NULL) < 0) {
@@ -3231,6 +3275,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 
        netif_carrier_off(netdev);
        netif_stop_queue(netdev);
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+       for (i = 0; i < adapter->num_tx_queues; i++)
+               netif_stop_subqueue(netdev, i);
+#endif
 
        ixgbe_napi_add_all(adapter);