Commit dcea4dbe authored by Janne Ylalehto's avatar Janne Ylalehto Committed by John W. Linville
Browse files

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: default avatarJanne Ylalehto <janne.ylalehto@nokia.com>
Reviewed-by: default avatarJuuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: default avatarLuciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: default avatarKalle Valo <kalle.valo@nokia.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 33d51fac
Loading
Loading
Loading
Loading
+67 −60
Original line number Diff line number Diff line
@@ -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: