rt2x00: Fix queue related oops in case of deselected mac80211 multi-queue feature.
authorGertjan van Wingerde <gwingerde@kpnplanet.nl>
Sat, 10 May 2008 11:43:33 +0000 (13:43 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 22 May 2008 01:47:32 +0000 (21:47 -0400)
With the integration of the mac80211 multiqueue patches it has become possible that the
mac80211 layer modifies the number of TX queues that is stored inside the ieee80211_hw
structure, especially when multi-queue is not selected.

The rt2x00 drivers are not well suited to handle that situation, as they allocate the
queue structures before mac80211 has modified the number of queues it is going to use,
and also expect the number of allocated queues to match the hardware implementation.

Hence, ensure that rt2x00 maintains by itself the number of queues that the hardware
supports, and, at the same time, making is not dependent on the preservation of contents
inside a mac80211 structure.

Signed-off-by: Gertjan van Wingerde <gwingerde@kpnplanet.nl>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
15 files changed:
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2400pci.h
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500pci.h
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2500usb.h
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rt2x00/rt2x00queue.c
drivers/net/wireless/rt2x00/rt2x00queue.h
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt61pci.h
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rt2x00/rt73usb.h

index fb02d118075b1c75a0e3bba5e2462fb812dfd65a..b4310d798f9466a228aa0cef19c8fb32358116f4 100644 (file)
@@ -1373,7 +1373,6 @@ static void rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
        rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
                               IEEE80211_HW_SIGNAL_DBM;
        rt2x00dev->hw->extra_tx_headroom = 0;
-       rt2x00dev->hw->queues = 2;
 
        SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -1620,6 +1619,7 @@ static const struct rt2x00_ops rt2400pci_ops = {
        .max_ap_intf    = 1,
        .eeprom_size    = EEPROM_SIZE,
        .rf_size        = RF_SIZE,
+       .tx_queues      = NUM_TX_QUEUES,
        .rx             = &rt2400pci_queue_rx,
        .tx             = &rt2400pci_queue_tx,
        .bcn            = &rt2400pci_queue_bcn,
index a5210f9a3360ba521f7ca6dc786351156f32dc18..e9aa326be9f69243c9937974c572566b027e3d9e 100644 (file)
 #define BBP_SIZE                       0x0020
 #define RF_SIZE                                0x0010
 
+/*
+ * Number of TX queues.
+ */
+#define NUM_TX_QUEUES                  2
+
 /*
  * Control/Status Registers(CSR).
  * Some values are set in TU, whereas 1 TU == 1024 us.
index 1724ce90f8b158f1f2db152b0276e8d654a3817c..54aaa8375a2c1f6e806112152cd6e72dac9c5c76 100644 (file)
@@ -1692,7 +1692,6 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
                               IEEE80211_HW_SIGNAL_DBM;
 
        rt2x00dev->hw->extra_tx_headroom = 0;
-       rt2x00dev->hw->queues = 2;
 
        SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -1933,6 +1932,7 @@ static const struct rt2x00_ops rt2500pci_ops = {
        .max_ap_intf    = 1,
        .eeprom_size    = EEPROM_SIZE,
        .rf_size        = RF_SIZE,
+       .tx_queues      = NUM_TX_QUEUES,
        .rx             = &rt2500pci_queue_rx,
        .tx             = &rt2500pci_queue_tx,
        .bcn            = &rt2500pci_queue_bcn,
index 13899550465acf5f402bd9c3c96d230235f7ac90..ea93b8f423a98a5ff2106340aae7fff5e0ba2c4f 100644 (file)
 #define BBP_SIZE                       0x0040
 #define RF_SIZE                                0x0014
 
+/*
+ * Number of TX queues.
+ */
+#define NUM_TX_QUEUES                  2
+
 /*
  * Control/Status Registers(CSR).
  * Some values are set in TU, whereas 1 TU == 1024 us.
index 7df06ece1b45331df40266569ccaf89032e57772..661cf3d7212a8a09aea06dfc60943786d50e770a 100644 (file)
@@ -1590,7 +1590,6 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
            IEEE80211_HW_SIGNAL_DBM;
 
        rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
-       rt2x00dev->hw->queues = 2;
 
        SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -1826,6 +1825,7 @@ static const struct rt2x00_ops rt2500usb_ops = {
        .max_ap_intf    = 1,
        .eeprom_size    = EEPROM_SIZE,
        .rf_size        = RF_SIZE,
+       .tx_queues      = NUM_TX_QUEUES,
        .rx             = &rt2500usb_queue_rx,
        .tx             = &rt2500usb_queue_tx,
        .bcn            = &rt2500usb_queue_bcn,
index a37a068d0c71d00bbf63a959e390aa1b1926744d..7d50098f0cc5d7affe871c840e63a1b6f3024875 100644 (file)
 #define BBP_SIZE                       0x0060
 #define RF_SIZE                                0x0014
 
+/*
+ * Number of TX queues.
+ */
+#define NUM_TX_QUEUES                  2
+
 /*
  * Control/Status Registers(CSR).
  * Some values are set in TU, whereas 1 TU == 1024 us.
index 65614841f748ebbdab733409b661a3f65e2ee12d..6f7b34fac16c275aa90b329253fc6580fd5117db 100644 (file)
@@ -591,6 +591,7 @@ struct rt2x00_ops {
        const unsigned int max_ap_intf;
        const unsigned int eeprom_size;
        const unsigned int rf_size;
+       const unsigned int tx_queues;
        const struct data_queue_desc *rx;
        const struct data_queue_desc *tx;
        const struct data_queue_desc *bcn;
index e1368f7098589398c5779df9769846ca5ca7b2ea..46c377873f163ac2af548213b5509008ae514904 100644 (file)
@@ -974,6 +974,11 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (status)
                return status;
 
+       /*
+        * Initialize HW fields.
+        */
+       rt2x00dev->hw->queues = rt2x00dev->ops->tx_queues;
+
        /*
         * Register HW.
         */
index 767e0ffce04e8d086712d7501fc99ebf3126648b..c5cedb29b87dcaf8f3c1f7bc8ddba01eb7696960 100644 (file)
@@ -456,7 +456,7 @@ int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
        struct rt2x00_dev *rt2x00dev = hw->priv;
        unsigned int i;
 
-       for (i = 0; i < hw->queues; i++) {
+       for (i = 0; i < rt2x00dev->ops->tx_queues; i++) {
                stats[i].len = rt2x00dev->tx[i].length;
                stats[i].limit = rt2x00dev->tx[i].limit;
                stats[i].count = rt2x00dev->tx[i].count;
index e5b861f8416d9db11b34563a8ee5d67a859080ee..95f8dd3462f6f9c191760c8ca721da767b7e8913 100644 (file)
@@ -34,7 +34,7 @@ struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
 {
        int atim = test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
 
-       if (queue < rt2x00dev->hw->queues && rt2x00dev->tx)
+       if (queue < rt2x00dev->ops->tx_queues && rt2x00dev->tx)
                return &rt2x00dev->tx[queue];
 
        if (!rt2x00dev->bcn)
@@ -255,11 +255,11 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
        /*
         * We need the following queues:
         * RX: 1
-        * TX: hw->queues
+        * TX: ops->tx_queues
         * Beacon: 1
         * Atim: 1 (if required)
         */
-       rt2x00dev->data_queues = 2 + rt2x00dev->hw->queues + req_atim;
+       rt2x00dev->data_queues = 2 + rt2x00dev->ops->tx_queues + req_atim;
 
        queue = kzalloc(rt2x00dev->data_queues * sizeof(*queue), GFP_KERNEL);
        if (!queue) {
@@ -272,7 +272,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
         */
        rt2x00dev->rx = queue;
        rt2x00dev->tx = &queue[1];
-       rt2x00dev->bcn = &queue[1 + rt2x00dev->hw->queues];
+       rt2x00dev->bcn = &queue[1 + rt2x00dev->ops->tx_queues];
 
        /*
         * Initialize queue parameters.
index 3f7cfa9b7da5a0cc6da300c39bd18d7608c95e3a..4bde98ba3c601889024355542e5942162fecdd49 100644 (file)
@@ -397,7 +397,7 @@ struct data_queue_desc {
  * the end of the TX queue array.
  */
 #define tx_queue_end(__dev) \
-       &(__dev)->tx[(__dev)->hw->queues]
+       &(__dev)->tx[(__dev)->ops->tx_queues]
 
 /**
  * queue_loop - Loop through the queues within a specific range (HELPER MACRO).
index 5d690ee1befaf6e2efb8dc8e2b9ead52ec848d7b..68d2216131b25a72628806135fc0f137f776f28d 100644 (file)
@@ -2257,7 +2257,6 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
            IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
            IEEE80211_HW_SIGNAL_DBM;
        rt2x00dev->hw->extra_tx_headroom = 0;
-       rt2x00dev->hw->queues = 4;
 
        SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -2489,6 +2488,7 @@ static const struct rt2x00_ops rt61pci_ops = {
        .max_ap_intf    = 4,
        .eeprom_size    = EEPROM_SIZE,
        .rf_size        = RF_SIZE,
+       .tx_queues      = NUM_TX_QUEUES,
        .rx             = &rt61pci_queue_rx,
        .tx             = &rt61pci_queue_tx,
        .bcn            = &rt61pci_queue_bcn,
index 3511bba7ff65479cdee3d2b3c158876929b89a36..c5a04b9329d2953f4957683bd633ff5a0afd56ba 100644 (file)
 #define BBP_SIZE                       0x0080
 #define RF_SIZE                                0x0014
 
+/*
+ * Number of TX queues.
+ */
+#define NUM_TX_QUEUES                  4
+
 /*
  * PCI registers.
  */
index d98002cfe091b750895e381a9453218701d57242..2191d8b94a894b4575ae47814ee84a01fbde039b 100644 (file)
@@ -1831,7 +1831,6 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
            IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
            IEEE80211_HW_SIGNAL_DBM;
        rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
-       rt2x00dev->hw->queues = 4;
 
        SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
        SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -2079,6 +2078,7 @@ static const struct rt2x00_ops rt73usb_ops = {
        .max_ap_intf    = 4,
        .eeprom_size    = EEPROM_SIZE,
        .rf_size        = RF_SIZE,
+       .tx_queues      = NUM_TX_QUEUES,
        .rx             = &rt73usb_queue_rx,
        .tx             = &rt73usb_queue_tx,
        .bcn            = &rt73usb_queue_bcn,
index 06d687425fefa069ea28f0bae2df6d118d437478..25cdcc9bf7c471b6170397f6afecb9065817cbf3 100644 (file)
 #define BBP_SIZE                       0x0080
 #define RF_SIZE                                0x0014
 
+/*
+ * Number of TX queues.
+ */
+#define NUM_TX_QUEUES                  4
+
 /*
  * USB registers.
  */