Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 203545
b: refs/heads/master
c: 78e256c
h: refs/heads/master
i:
  203543: 94d40bf
v: v3
  • Loading branch information
Helmut Schaa authored and John W. Linville committed Jul 12, 2010
1 parent c4ba3c4 commit 57c97a2
Show file tree
Hide file tree
Showing 12 changed files with 202 additions and 71 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 50e888eae23dc062cb52a7538e85a5960ce1d91c
refs/heads/master: 78e256c9a3717bcae2e9ed05c9ec7bed7bf2c55d
54 changes: 38 additions & 16 deletions trunk/drivers/net/wireless/rt2x00/rt2400pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,8 @@ static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
int mask = (state == STATE_RADIO_IRQ_OFF);
int mask = (state == STATE_RADIO_IRQ_OFF) ||
(state == STATE_RADIO_IRQ_OFF_ISR);
u32 reg;

/*
Expand Down Expand Up @@ -980,7 +981,9 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
rt2400pci_toggle_rx(rt2x00dev, state);
break;
case STATE_RADIO_IRQ_ON:
case STATE_RADIO_IRQ_ON_ISR:
case STATE_RADIO_IRQ_OFF:
case STATE_RADIO_IRQ_OFF_ISR:
rt2400pci_toggle_irq(rt2x00dev, state);
break;
case STATE_DEEP_SLEEP:
Expand Down Expand Up @@ -1235,23 +1238,10 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
}
}

static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
static irqreturn_t rt2400pci_interrupt_thread(int irq, void *dev_instance)
{
struct rt2x00_dev *rt2x00dev = dev_instance;
u32 reg;

/*
* Get the interrupt sources & saved to local variable.
* Write register value back to clear pending interrupts.
*/
rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
rt2x00pci_register_write(rt2x00dev, CSR7, reg);

if (!reg)
return IRQ_NONE;

if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return IRQ_HANDLED;
u32 reg = rt2x00dev->irqvalue[0];

/*
* Handle interrupts, walk through all bits
Expand Down Expand Up @@ -1289,9 +1279,40 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
rt2400pci_txdone(rt2x00dev, QID_AC_BK);

/* Enable interrupts again. */
rt2x00dev->ops->lib->set_device_state(rt2x00dev,
STATE_RADIO_IRQ_ON_ISR);
return IRQ_HANDLED;
}

static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
{
struct rt2x00_dev *rt2x00dev = dev_instance;
u32 reg;

/*
* Get the interrupt sources & saved to local variable.
* Write register value back to clear pending interrupts.
*/
rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
rt2x00pci_register_write(rt2x00dev, CSR7, reg);

if (!reg)
return IRQ_NONE;

if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return IRQ_HANDLED;

/* Store irqvalues for use in the interrupt thread. */
rt2x00dev->irqvalue[0] = reg;

/* Disable interrupts, will be enabled again in the interrupt thread. */
rt2x00dev->ops->lib->set_device_state(rt2x00dev,
STATE_RADIO_IRQ_OFF_ISR);

return IRQ_WAKE_THREAD;
}

/*
* Device probe functions.
*/
Expand Down Expand Up @@ -1581,6 +1602,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {

static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.irq_handler = rt2400pci_interrupt,
.irq_handler_thread = rt2400pci_interrupt_thread,
.probe_hw = rt2400pci_probe_hw,
.initialize = rt2x00pci_initialize,
.uninitialize = rt2x00pci_uninitialize,
Expand Down
55 changes: 39 additions & 16 deletions trunk/drivers/net/wireless/rt2x00/rt2500pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1033,7 +1033,8 @@ static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
int mask = (state == STATE_RADIO_IRQ_OFF);
int mask = (state == STATE_RADIO_IRQ_OFF) ||
(state == STATE_RADIO_IRQ_OFF_ISR);
u32 reg;

/*
Expand Down Expand Up @@ -1134,7 +1135,9 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
rt2500pci_toggle_rx(rt2x00dev, state);
break;
case STATE_RADIO_IRQ_ON:
case STATE_RADIO_IRQ_ON_ISR:
case STATE_RADIO_IRQ_OFF:
case STATE_RADIO_IRQ_OFF_ISR:
rt2500pci_toggle_irq(rt2x00dev, state);
break;
case STATE_DEEP_SLEEP:
Expand Down Expand Up @@ -1367,23 +1370,10 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
}
}

static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
static irqreturn_t rt2500pci_interrupt_thread(int irq, void *dev_instance)
{
struct rt2x00_dev *rt2x00dev = dev_instance;
u32 reg;

/*
* Get the interrupt sources & saved to local variable.
* Write register value back to clear pending interrupts.
*/
rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
rt2x00pci_register_write(rt2x00dev, CSR7, reg);

if (!reg)
return IRQ_NONE;

if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return IRQ_HANDLED;
u32 reg = rt2x00dev->irqvalue[0];

/*
* Handle interrupts, walk through all bits
Expand Down Expand Up @@ -1421,9 +1411,41 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
rt2500pci_txdone(rt2x00dev, QID_AC_BK);

/* Enable interrupts again. */
rt2x00dev->ops->lib->set_device_state(rt2x00dev,
STATE_RADIO_IRQ_ON_ISR);

return IRQ_HANDLED;
}

static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
{
struct rt2x00_dev *rt2x00dev = dev_instance;
u32 reg;

/*
* Get the interrupt sources & saved to local variable.
* Write register value back to clear pending interrupts.
*/
rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
rt2x00pci_register_write(rt2x00dev, CSR7, reg);

if (!reg)
return IRQ_NONE;

if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return IRQ_HANDLED;

/* Store irqvalues for use in the interrupt thread. */
rt2x00dev->irqvalue[0] = reg;

/* Disable interrupts, will be enabled again in the interrupt thread. */
rt2x00dev->ops->lib->set_device_state(rt2x00dev,
STATE_RADIO_IRQ_OFF_ISR);

return IRQ_WAKE_THREAD;
}

/*
* Device probe functions.
*/
Expand Down Expand Up @@ -1874,6 +1896,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {

static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.irq_handler = rt2500pci_interrupt,
.irq_handler_thread = rt2500pci_interrupt_thread,
.probe_hw = rt2500pci_probe_hw,
.initialize = rt2x00pci_initialize,
.uninitialize = rt2x00pci_uninitialize,
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/net/wireless/rt2x00/rt2500usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1004,7 +1004,9 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
rt2500usb_toggle_rx(rt2x00dev, state);
break;
case STATE_RADIO_IRQ_ON:
case STATE_RADIO_IRQ_ON_ISR:
case STATE_RADIO_IRQ_OFF:
case STATE_RADIO_IRQ_OFF_ISR:
/* No support, but no error either */
break;
case STATE_DEEP_SLEEP:
Expand Down
50 changes: 37 additions & 13 deletions trunk/drivers/net/wireless/rt2x00/rt2800pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,8 @@ static void rt2800pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
int mask = (state == STATE_RADIO_IRQ_ON);
int mask = (state == STATE_RADIO_IRQ_ON) ||
(state == STATE_RADIO_IRQ_ON_ISR);
u32 reg;

/*
Expand Down Expand Up @@ -631,7 +632,9 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
rt2800pci_toggle_rx(rt2x00dev, state);
break;
case STATE_RADIO_IRQ_ON:
case STATE_RADIO_IRQ_ON_ISR:
case STATE_RADIO_IRQ_OFF:
case STATE_RADIO_IRQ_OFF_ISR:
rt2800pci_toggle_irq(rt2x00dev, state);
break;
case STATE_DEEP_SLEEP:
Expand Down Expand Up @@ -929,20 +932,10 @@ static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev)
rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
}

static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance)
{
struct rt2x00_dev *rt2x00dev = dev_instance;
u32 reg;

/* Read status and ACK all interrupts */
rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);

if (!reg)
return IRQ_NONE;

if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return IRQ_HANDLED;
u32 reg = rt2x00dev->irqvalue[0];

/*
* 1 - Rx ring done interrupt.
Expand All @@ -962,9 +955,39 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
rt2800pci_wakeup(rt2x00dev);

/* Enable interrupts again. */
rt2x00dev->ops->lib->set_device_state(rt2x00dev,
STATE_RADIO_IRQ_ON_ISR);

return IRQ_HANDLED;
}

static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
{
struct rt2x00_dev *rt2x00dev = dev_instance;
u32 reg;

/* Read status and ACK all interrupts */
rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);

if (!reg)
return IRQ_NONE;

if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return IRQ_HANDLED;

/* Store irqvalue for use in the interrupt thread. */
rt2x00dev->irqvalue[0] = reg;

/* Disable interrupts, will be enabled again in the interrupt thread. */
rt2x00dev->ops->lib->set_device_state(rt2x00dev,
STATE_RADIO_IRQ_OFF_ISR);


return IRQ_WAKE_THREAD;
}

/*
* Device probe functions.
*/
Expand Down Expand Up @@ -1049,6 +1072,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)

static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.irq_handler = rt2800pci_interrupt,
.irq_handler_thread = rt2800pci_interrupt_thread,
.probe_hw = rt2800pci_probe_hw,
.get_firmware_name = rt2800pci_get_firmware_name,
.check_firmware = rt2800pci_check_firmware,
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/net/wireless/rt2x00/rt2800usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,9 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
rt2800usb_toggle_rx(rt2x00dev, state);
break;
case STATE_RADIO_IRQ_ON:
case STATE_RADIO_IRQ_ON_ISR:
case STATE_RADIO_IRQ_OFF:
case STATE_RADIO_IRQ_OFF_ISR:
/* No support, but no error either */
break;
case STATE_DEEP_SLEEP:
Expand Down
11 changes: 11 additions & 0 deletions trunk/drivers/net/wireless/rt2x00/rt2x00.h
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,11 @@ struct rt2x00lib_ops {
*/
irq_handler_t irq_handler;

/*
* Threaded Interrupt handlers.
*/
irq_handler_t irq_handler_thread;

/*
* Device init handlers.
*/
Expand Down Expand Up @@ -870,6 +875,12 @@ struct rt2x00_dev {
*/
const struct firmware *fw;

/*
* Interrupt values, stored between interrupt service routine
* and interrupt thread routine.
*/
u32 irqvalue[2];

/*
* Driver specific data.
*/
Expand Down
23 changes: 20 additions & 3 deletions trunk/drivers/net/wireless/rt2x00/rt2x00dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,9 +340,17 @@ void rt2x00lib_txdone(struct queue_entry *entry,
* send the status report back.
*/
if (!(skbdesc_flags & SKBDESC_NOT_MAC80211))
ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb);
/*
* Only PCI and SOC devices process the tx status in process
* context. Hence use ieee80211_tx_status for PCI and SOC
* devices and stick to ieee80211_tx_status_irqsafe for USB.
*/
if (rt2x00_is_usb(rt2x00dev))
ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb);
else
ieee80211_tx_status(rt2x00dev->hw, entry->skb);
else
dev_kfree_skb_irq(entry->skb);
dev_kfree_skb_any(entry->skb);

/*
* Make this entry available for reuse.
Expand Down Expand Up @@ -489,7 +497,16 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
*/
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb);
memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status));
ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb);

/*
* Currently only PCI and SOC devices handle rx interrupts in process
* context. Hence, use ieee80211_rx_irqsafe for USB and ieee80211_rx_ni
* for PCI and SOC devices.
*/
if (rt2x00_is_usb(rt2x00dev))
ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb);
else
ieee80211_rx_ni(rt2x00dev->hw, entry->skb);

/*
* Replace the skb with the freshly allocated one.
Expand Down
6 changes: 4 additions & 2 deletions trunk/drivers/net/wireless/rt2x00/rt2x00pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,10 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
/*
* Register interrupt handler.
*/
status = request_irq(rt2x00dev->irq, rt2x00dev->ops->lib->irq_handler,
IRQF_SHARED, rt2x00dev->name, rt2x00dev);
status = request_threaded_irq(rt2x00dev->irq,
rt2x00dev->ops->lib->irq_handler,
rt2x00dev->ops->lib->irq_handler_thread,
IRQF_SHARED, rt2x00dev->name, rt2x00dev);
if (status) {
ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
rt2x00dev->irq, status);
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/net/wireless/rt2x00/rt2x00reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ enum dev_state {
STATE_RADIO_RX_OFF_LINK,
STATE_RADIO_IRQ_ON,
STATE_RADIO_IRQ_OFF,
STATE_RADIO_IRQ_ON_ISR,
STATE_RADIO_IRQ_OFF_ISR,
};

/*
Expand Down
Loading

0 comments on commit 57c97a2

Please sign in to comment.