/* mailbox recv message polling */ int ath6kl_hif_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd, int timeout) { struct ath6kl_irq_proc_registers *rg; int status = 0, i; u8 htc_mbox = 1 << HTC_MAILBOX; for (i = timeout / ATH6KL_TIME_QUANTUM; i > 0; i--) { /* this is the standard HIF way, load the reg table */ status = hif_read_write_sync(dev->ar, HOST_INT_STATUS_ADDRESS, (u8 *) &dev->irq_proc_reg, sizeof(dev->irq_proc_reg), HIF_RD_SYNC_BYTE_INC); if (status) { ath6kl_err("failed to read reg table\n"); return status; } /* check for MBOX data and valid lookahead */ if (dev->irq_proc_reg.host_int_status & htc_mbox) { if (dev->irq_proc_reg.rx_lkahd_valid & htc_mbox) { /* * Mailbox has a message and the look ahead * is valid. */ rg = &dev->irq_proc_reg; *lk_ahd = le32_to_cpu(rg->rx_lkahd[HTC_MAILBOX]); break; } } /* delay a little */ mdelay(ATH6KL_TIME_QUANTUM); ath6kl_dbg(ATH6KL_DBG_HIF, "hif retry mbox poll try %d\n", i); } if (i == 0) { ath6kl_err("timeout waiting for recv message\n"); status = -ETIME; /* check if the target asserted */ if (dev->irq_proc_reg.counter_int_status & ATH6KL_TARGET_DEBUG_INTR_MASK) /* * Target failure handler will be called in case of * an assert. */ ath6kl_hif_proc_dbg_intr(dev); } return status; }
int ath6kl_hif_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd, int timeout) { struct ath6kl_irq_proc_registers *rg; int status = 0, i; u8 htc_mbox = 1 << HTC_MAILBOX; for (i = timeout / ATH6KL_TIME_QUANTUM; i > 0; i--) { status = hif_read_write_sync(dev->ar, HOST_INT_STATUS_ADDRESS, (u8 *) &dev->irq_proc_reg, sizeof(dev->irq_proc_reg), HIF_RD_SYNC_BYTE_INC); if (status) { ath6kl_err("failed to read reg table\n"); return status; } if (dev->irq_proc_reg.host_int_status & htc_mbox) { if (dev->irq_proc_reg.rx_lkahd_valid & htc_mbox) { rg = &dev->irq_proc_reg; *lk_ahd = le32_to_cpu(rg->rx_lkahd[HTC_MAILBOX]); break; } } mdelay(ATH6KL_TIME_QUANTUM); ath6kl_dbg(ATH6KL_DBG_HIF, "hif retry mbox poll try %d\n", i); } if (i == 0) { ath6kl_err("timeout waiting for recv message\n"); status = -ETIME; if (dev->irq_proc_reg.counter_int_status & ATH6KL_TARGET_DEBUG_INTR_MASK) ath6kl_hif_proc_dbg_intr(dev); } return status; }
static int ath6kl_hif_proc_counter_intr(struct ath6kl_device *dev) { u8 counter_int_status; ath6kl_dbg(ATH6KL_DBG_IRQ, "counter interrupt\n"); counter_int_status = dev->irq_proc_reg.counter_int_status & dev->irq_en_reg.cntr_int_status_en; ath6kl_dbg(ATH6KL_DBG_IRQ, "valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n", counter_int_status); if (counter_int_status & ATH6KL_TARGET_DEBUG_INTR_MASK) return ath6kl_hif_proc_dbg_intr(dev); return 0; }
static int ath6kl_hif_proc_counter_intr(struct ath6kl_device *dev) { u8 counter_int_status; ath6kl_dbg(ATH6KL_DBG_IRQ, "counter interrupt\n"); counter_int_status = dev->irq_proc_reg.counter_int_status & dev->irq_en_reg.cntr_int_status_en; ath6kl_dbg(ATH6KL_DBG_IRQ, "valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n", counter_int_status); /* * NOTE: other modules like GMBOX may use the counter interrupt for * credit flow control on other counters, we only need to check for * the debug assertion counter interrupt. */ if (counter_int_status & ATH6KL_TARGET_DEBUG_INTR_MASK) return ath6kl_hif_proc_dbg_intr(dev); return 0; }