wl1251: Add IRQ looping support

Add support for IRQ looping. Helps in the case that we have e.g. multiple
packets coming from the network when we wake up from the ELP.

Signed-off-by: Janne Ylalehto <janne.ylalehto@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Kalle Valo <kalle.valo@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Janne Ylalehto 2009-11-17 18:49:31 +02:00 committed by John W. Linville
parent 33d51facad
commit dcea4dbe54

View File

@ -212,9 +212,10 @@ out:
return ret;
}
#define WL1251_IRQ_LOOP_COUNT 10
static void wl1251_irq_work(struct work_struct *work)
{
u32 intr;
u32 intr, ctr = WL1251_IRQ_LOOP_COUNT;
struct wl1251 *wl =
container_of(work, struct wl1251, irq_work);
int ret;
@ -235,14 +236,16 @@ static void wl1251_irq_work(struct work_struct *work)
intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
wl1251_debug(DEBUG_IRQ, "intr: 0x%x", intr);
do {
if (wl->data_path) {
wl->rx_counter =
wl1251_mem_read32(wl, wl->data_path->rx_control_addr);
wl->rx_counter = wl1251_mem_read32(
wl, wl->data_path->rx_control_addr);
/* We handle a frmware bug here */
switch ((wl->rx_counter - wl->rx_handled) & 0xf) {
case 0:
wl1251_debug(DEBUG_IRQ, "RX: FW and host in sync");
wl1251_debug(DEBUG_IRQ,
"RX: FW and host in sync");
intr &= ~WL1251_ACX_INTR_RX0_DATA;
intr &= ~WL1251_ACX_INTR_RX1_DATA;
break;
@ -257,24 +260,22 @@ static void wl1251_irq_work(struct work_struct *work)
intr |= WL1251_ACX_INTR_RX1_DATA;
break;
default:
wl1251_warning("RX: FW and host out of sync: %d",
wl1251_warning(
"RX: FW and host out of sync: %d",
wl->rx_counter - wl->rx_handled);
break;
}
wl->rx_handled = wl->rx_counter;
wl1251_debug(DEBUG_IRQ, "RX counter: %d", wl->rx_counter);
wl1251_debug(DEBUG_IRQ, "RX counter: %d",
wl->rx_counter);
}
intr &= wl->intr_mask;
if (intr == 0) {
wl1251_debug(DEBUG_IRQ, "INTR is 0");
wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
~(wl->intr_mask));
goto out_sleep;
}
@ -293,8 +294,10 @@ static void wl1251_irq_work(struct work_struct *work)
wl1251_tx_complete(wl);
}
if (intr & (WL1251_ACX_INTR_EVENT_A | WL1251_ACX_INTR_EVENT_B)) {
wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", intr);
if (intr & (WL1251_ACX_INTR_EVENT_A |
WL1251_ACX_INTR_EVENT_B)) {
wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)",
intr);
if (intr & WL1251_ACX_INTR_EVENT_A)
wl1251_event_handle(wl, 0);
else
@ -302,11 +305,15 @@ static void wl1251_irq_work(struct work_struct *work)
}
if (intr & WL1251_ACX_INTR_INIT_COMPLETE)
wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_INIT_COMPLETE");
wl1251_debug(DEBUG_IRQ,
"WL1251_ACX_INTR_INIT_COMPLETE");
wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
} while (intr && --ctr);
out_sleep:
wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
wl1251_ps_elp_sleep(wl);
out: