Skip to content

Commit

Permalink
rt2x00: Fix queue related oops in case of deselected mac80211 multi-q…
Browse files Browse the repository at this point in the history
…ueue feature.

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>
  • Loading branch information
Gertjan van Wingerde authored and John W. Linville committed May 22, 2008
1 parent 61486e0 commit 61448f8
Show file tree
Hide file tree
Showing 15 changed files with 42 additions and 11 deletions.
2 changes: 1 addition & 1 deletion drivers/net/wireless/rt2x00/rt2400pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/wireless/rt2x00/rt2400pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@
#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.
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/rt2x00/rt2500pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/wireless/rt2x00/rt2500pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@
#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.
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/rt2x00/rt2500usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/wireless/rt2x00/rt2500usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@
#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.
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/rt2x00/rt2x00.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/wireless/rt2x00/rt2x00dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/rt2x00/rt2x00mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions drivers/net/wireless/rt2x00/rt2x00queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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) {
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/rt2x00/rt2x00queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/rt2x00/rt61pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/wireless/rt2x00/rt61pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@
#define BBP_SIZE 0x0080
#define RF_SIZE 0x0014

/*
* Number of TX queues.
*/
#define NUM_TX_QUEUES 4

/*
* PCI registers.
*/
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/rt2x00/rt73usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/wireless/rt2x00/rt73usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@
#define BBP_SIZE 0x0080
#define RF_SIZE 0x0014

/*
* Number of TX queues.
*/
#define NUM_TX_QUEUES 4

/*
* USB registers.
*/
Expand Down

0 comments on commit 61448f8

Please sign in to comment.