wl1271: Update interrupt handling by removing an extra SPI read
Remove separate interrupt register reading from the interrupt handling routine. This will slightly improve interrupt performance. Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com> Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com> Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
committed by
John W. Linville
parent
284134eb6f
commit
c15f63bffa
@@ -76,20 +76,14 @@ static void wl1271_power_on(struct wl1271 *wl)
|
|||||||
wl->set_power(true);
|
wl->set_power(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status)
|
static void wl1271_fw_status(struct wl1271 *wl,
|
||||||
|
struct wl1271_fw_status *status)
|
||||||
{
|
{
|
||||||
u32 total = 0;
|
u32 total = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
wl1271_spi_reg_read(wl, FW_STATUS_ADDR, status,
|
||||||
* FIXME: Reading the FW status directly from the registers seems to
|
sizeof(*status), false);
|
||||||
* be the right thing to do, but it doesn't work. And in the
|
|
||||||
* reference driver, there is a workaround called
|
|
||||||
* USE_SDIO_24M_WORKAROUND, which reads the status from memory
|
|
||||||
* instead, so we do the same here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
wl1271_spi_mem_read(wl, STATUS_MEM_ADDRESS, status, sizeof(*status));
|
|
||||||
|
|
||||||
wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
|
wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
|
||||||
"drv_rx_counter = %d, tx_results_counter = %d)",
|
"drv_rx_counter = %d, tx_results_counter = %d)",
|
||||||
@@ -114,11 +108,10 @@ static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status)
|
|||||||
wl->time_offset = jiffies_to_usecs(jiffies) - status->fw_localtime;
|
wl->time_offset = jiffies_to_usecs(jiffies) - status->fw_localtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WL1271_IRQ_MAX_LOOPS 10
|
|
||||||
static void wl1271_irq_work(struct work_struct *work)
|
static void wl1271_irq_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
u32 intr, ctr = WL1271_IRQ_MAX_LOOPS;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
u32 intr;
|
||||||
struct wl1271 *wl =
|
struct wl1271 *wl =
|
||||||
container_of(work, struct wl1271, irq_work);
|
container_of(work, struct wl1271, irq_work);
|
||||||
|
|
||||||
@@ -135,7 +128,8 @@ static void wl1271_irq_work(struct work_struct *work)
|
|||||||
|
|
||||||
wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
|
wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
|
||||||
|
|
||||||
intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
|
wl1271_fw_status(wl, wl->fw_status);
|
||||||
|
intr = wl->fw_status->intr;
|
||||||
if (!intr) {
|
if (!intr) {
|
||||||
wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
|
wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
|
||||||
goto out_sleep;
|
goto out_sleep;
|
||||||
@@ -143,43 +137,35 @@ static void wl1271_irq_work(struct work_struct *work)
|
|||||||
|
|
||||||
intr &= WL1271_INTR_MASK;
|
intr &= WL1271_INTR_MASK;
|
||||||
|
|
||||||
do {
|
if (intr & (WL1271_ACX_INTR_EVENT_A |
|
||||||
wl1271_fw_status(wl, wl->fw_status);
|
WL1271_ACX_INTR_EVENT_B)) {
|
||||||
|
wl1271_debug(DEBUG_IRQ,
|
||||||
|
"WL1271_ACX_INTR_EVENT (0x%x)", intr);
|
||||||
|
if (intr & WL1271_ACX_INTR_EVENT_A)
|
||||||
|
wl1271_event_handle(wl, 0);
|
||||||
|
else
|
||||||
|
wl1271_event_handle(wl, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
|
||||||
|
wl1271_debug(DEBUG_IRQ,
|
||||||
|
"WL1271_ACX_INTR_INIT_COMPLETE");
|
||||||
|
|
||||||
if (intr & (WL1271_ACX_INTR_EVENT_A |
|
if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
|
||||||
WL1271_ACX_INTR_EVENT_B)) {
|
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
|
||||||
wl1271_debug(DEBUG_IRQ,
|
|
||||||
"WL1271_ACX_INTR_EVENT (0x%x)", intr);
|
|
||||||
if (intr & WL1271_ACX_INTR_EVENT_A)
|
|
||||||
wl1271_event_handle(wl, 0);
|
|
||||||
else
|
|
||||||
wl1271_event_handle(wl, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
|
if (intr & WL1271_ACX_INTR_DATA) {
|
||||||
wl1271_debug(DEBUG_IRQ,
|
u8 tx_res_cnt = wl->fw_status->tx_results_counter -
|
||||||
"WL1271_ACX_INTR_INIT_COMPLETE");
|
wl->tx_results_count;
|
||||||
|
|
||||||
if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
|
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
|
||||||
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
|
|
||||||
|
|
||||||
if (intr & WL1271_ACX_INTR_DATA) {
|
/* check for tx results */
|
||||||
u8 tx_res_cnt = wl->fw_status->tx_results_counter -
|
if (tx_res_cnt)
|
||||||
wl->tx_results_count;
|
wl1271_tx_complete(wl, tx_res_cnt);
|
||||||
|
|
||||||
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
|
wl1271_rx(wl, wl->fw_status);
|
||||||
|
}
|
||||||
/* check for tx results */
|
|
||||||
if (tx_res_cnt)
|
|
||||||
wl1271_tx_complete(wl, tx_res_cnt);
|
|
||||||
|
|
||||||
wl1271_rx(wl, wl->fw_status);
|
|
||||||
}
|
|
||||||
|
|
||||||
intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
|
|
||||||
intr &= WL1271_INTR_MASK;
|
|
||||||
} while (intr && --ctr);
|
|
||||||
|
|
||||||
out_sleep:
|
out_sleep:
|
||||||
wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
|
wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
|
||||||
|
@@ -34,7 +34,7 @@
|
|||||||
#define REGISTERS_WORK_SIZE 0x0000b000
|
#define REGISTERS_WORK_SIZE 0x0000b000
|
||||||
|
|
||||||
#define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC
|
#define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC
|
||||||
#define STATUS_MEM_ADDRESS 0x40400
|
#define FW_STATUS_ADDR (0x14FC0 + 0xA000)
|
||||||
|
|
||||||
/* ELP register commands */
|
/* ELP register commands */
|
||||||
#define ELPCTRL_WAKE_UP 0x1
|
#define ELPCTRL_WAKE_UP 0x1
|
||||||
|
Reference in New Issue
Block a user