These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / net / wireless / ath / wil6210 / interrupt.c
index 28ffc18..50c136e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2015 Qualcomm Atheros, Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -61,13 +61,13 @@ static inline void wil_icr_clear(u32 x, void __iomem *addr)
 
 static inline void wil_icr_clear(u32 x, void __iomem *addr)
 {
-       iowrite32(x, addr);
+       writel(x, addr);
 }
 #endif /* defined(CONFIG_WIL6210_ISR_COR) */
 
 static inline u32 wil_ioread32_and_clear(void __iomem *addr)
 {
-       u32 x = ioread32(addr);
+       u32 x = readl(addr);
 
        wil_icr_clear(x, addr);
 
@@ -76,54 +76,47 @@ static inline u32 wil_ioread32_and_clear(void __iomem *addr)
 
 static void wil6210_mask_irq_tx(struct wil6210_priv *wil)
 {
-       iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
-                 HOSTADDR(RGF_DMA_EP_TX_ICR) +
-                 offsetof(struct RGF_ICR, IMS));
+       wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, IMS),
+             WIL6210_IRQ_DISABLE);
 }
 
 static void wil6210_mask_irq_rx(struct wil6210_priv *wil)
 {
-       iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
-                 HOSTADDR(RGF_DMA_EP_RX_ICR) +
-                 offsetof(struct RGF_ICR, IMS));
+       wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, IMS),
+             WIL6210_IRQ_DISABLE);
 }
 
 static void wil6210_mask_irq_misc(struct wil6210_priv *wil)
 {
-       iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
-                 HOSTADDR(RGF_DMA_EP_MISC_ICR) +
-                 offsetof(struct RGF_ICR, IMS));
+       wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMS),
+             WIL6210_IRQ_DISABLE);
 }
 
 static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil)
 {
        wil_dbg_irq(wil, "%s()\n", __func__);
 
-       iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
-                 HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
+       wil_w(wil, RGF_DMA_PSEUDO_CAUSE_MASK_SW, WIL6210_IRQ_DISABLE);
 
        clear_bit(wil_status_irqen, wil->status);
 }
 
 void wil6210_unmask_irq_tx(struct wil6210_priv *wil)
 {
-       iowrite32(WIL6210_IMC_TX, wil->csr +
-                 HOSTADDR(RGF_DMA_EP_TX_ICR) +
-                 offsetof(struct RGF_ICR, IMC));
+       wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, IMC),
+             WIL6210_IMC_TX);
 }
 
 void wil6210_unmask_irq_rx(struct wil6210_priv *wil)
 {
-       iowrite32(WIL6210_IMC_RX, wil->csr +
-                 HOSTADDR(RGF_DMA_EP_RX_ICR) +
-                 offsetof(struct RGF_ICR, IMC));
+       wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, IMC),
+             WIL6210_IMC_RX);
 }
 
 static void wil6210_unmask_irq_misc(struct wil6210_priv *wil)
 {
-       iowrite32(WIL6210_IMC_MISC, wil->csr +
-                 HOSTADDR(RGF_DMA_EP_MISC_ICR) +
-                 offsetof(struct RGF_ICR, IMC));
+       wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMC),
+             WIL6210_IMC_MISC);
 }
 
 static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil)
@@ -132,8 +125,7 @@ static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil)
 
        set_bit(wil_status_irqen, wil->status);
 
-       iowrite32(WIL6210_IRQ_PSEUDO_MASK, wil->csr +
-                 HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
+       wil_w(wil, RGF_DMA_PSEUDO_CAUSE_MASK_SW, WIL6210_IRQ_PSEUDO_MASK);
 }
 
 void wil_mask_irq(struct wil6210_priv *wil)
@@ -150,12 +142,12 @@ void wil_unmask_irq(struct wil6210_priv *wil)
 {
        wil_dbg_irq(wil, "%s()\n", __func__);
 
-       iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) +
-                 offsetof(struct RGF_ICR, ICC));
-       iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) +
-                 offsetof(struct RGF_ICR, ICC));
-       iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) +
-                 offsetof(struct RGF_ICR, ICC));
+       wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, ICC),
+             WIL_ICR_ICC_VALUE);
+       wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, ICC),
+             WIL_ICR_ICC_VALUE);
+       wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICC),
+             WIL_ICR_ICC_VALUE);
 
        wil6210_unmask_irq_pseudo(wil);
        wil6210_unmask_irq_tx(wil);
@@ -163,9 +155,6 @@ void wil_unmask_irq(struct wil6210_priv *wil)
        wil6210_unmask_irq_misc(wil);
 }
 
-/* target write operation */
-#define W(a, v) do { iowrite32(v, wil->csr + HOSTADDR(a)); wmb(); } while (0)
-
 void wil_configure_interrupt_moderation(struct wil6210_priv *wil)
 {
        wil_dbg_irq(wil, "%s()\n", __func__);
@@ -177,44 +166,42 @@ void wil_configure_interrupt_moderation(struct wil6210_priv *wil)
                return;
 
        /* Disable and clear tx counter before (re)configuration */
-       W(RGF_DMA_ITR_TX_CNT_CTL, BIT_DMA_ITR_TX_CNT_CTL_CLR);
-       W(RGF_DMA_ITR_TX_CNT_TRSH, wil->tx_max_burst_duration);
+       wil_w(wil, RGF_DMA_ITR_TX_CNT_CTL, BIT_DMA_ITR_TX_CNT_CTL_CLR);
+       wil_w(wil, RGF_DMA_ITR_TX_CNT_TRSH, wil->tx_max_burst_duration);
        wil_info(wil, "set ITR_TX_CNT_TRSH = %d usec\n",
                 wil->tx_max_burst_duration);
        /* Configure TX max burst duration timer to use usec units */
-       W(RGF_DMA_ITR_TX_CNT_CTL,
-         BIT_DMA_ITR_TX_CNT_CTL_EN | BIT_DMA_ITR_TX_CNT_CTL_EXT_TIC_SEL);
+       wil_w(wil, RGF_DMA_ITR_TX_CNT_CTL,
+             BIT_DMA_ITR_TX_CNT_CTL_EN | BIT_DMA_ITR_TX_CNT_CTL_EXT_TIC_SEL);
 
        /* Disable and clear tx idle counter before (re)configuration */
-       W(RGF_DMA_ITR_TX_IDL_CNT_CTL, BIT_DMA_ITR_TX_IDL_CNT_CTL_CLR);
-       W(RGF_DMA_ITR_TX_IDL_CNT_TRSH, wil->tx_interframe_timeout);
+       wil_w(wil, RGF_DMA_ITR_TX_IDL_CNT_CTL, BIT_DMA_ITR_TX_IDL_CNT_CTL_CLR);
+       wil_w(wil, RGF_DMA_ITR_TX_IDL_CNT_TRSH, wil->tx_interframe_timeout);
        wil_info(wil, "set ITR_TX_IDL_CNT_TRSH = %d usec\n",
                 wil->tx_interframe_timeout);
        /* Configure TX max burst duration timer to use usec units */
-       W(RGF_DMA_ITR_TX_IDL_CNT_CTL, BIT_DMA_ITR_TX_IDL_CNT_CTL_EN |
-                                     BIT_DMA_ITR_TX_IDL_CNT_CTL_EXT_TIC_SEL);
+       wil_w(wil, RGF_DMA_ITR_TX_IDL_CNT_CTL, BIT_DMA_ITR_TX_IDL_CNT_CTL_EN |
+             BIT_DMA_ITR_TX_IDL_CNT_CTL_EXT_TIC_SEL);
 
        /* Disable and clear rx counter before (re)configuration */
-       W(RGF_DMA_ITR_RX_CNT_CTL, BIT_DMA_ITR_RX_CNT_CTL_CLR);
-       W(RGF_DMA_ITR_RX_CNT_TRSH, wil->rx_max_burst_duration);
+       wil_w(wil, RGF_DMA_ITR_RX_CNT_CTL, BIT_DMA_ITR_RX_CNT_CTL_CLR);
+       wil_w(wil, RGF_DMA_ITR_RX_CNT_TRSH, wil->rx_max_burst_duration);
        wil_info(wil, "set ITR_RX_CNT_TRSH = %d usec\n",
                 wil->rx_max_burst_duration);
        /* Configure TX max burst duration timer to use usec units */
-       W(RGF_DMA_ITR_RX_CNT_CTL,
-         BIT_DMA_ITR_RX_CNT_CTL_EN | BIT_DMA_ITR_RX_CNT_CTL_EXT_TIC_SEL);
+       wil_w(wil, RGF_DMA_ITR_RX_CNT_CTL,
+             BIT_DMA_ITR_RX_CNT_CTL_EN | BIT_DMA_ITR_RX_CNT_CTL_EXT_TIC_SEL);
 
        /* Disable and clear rx idle counter before (re)configuration */
-       W(RGF_DMA_ITR_RX_IDL_CNT_CTL, BIT_DMA_ITR_RX_IDL_CNT_CTL_CLR);
-       W(RGF_DMA_ITR_RX_IDL_CNT_TRSH, wil->rx_interframe_timeout);
+       wil_w(wil, RGF_DMA_ITR_RX_IDL_CNT_CTL, BIT_DMA_ITR_RX_IDL_CNT_CTL_CLR);
+       wil_w(wil, RGF_DMA_ITR_RX_IDL_CNT_TRSH, wil->rx_interframe_timeout);
        wil_info(wil, "set ITR_RX_IDL_CNT_TRSH = %d usec\n",
                 wil->rx_interframe_timeout);
        /* Configure TX max burst duration timer to use usec units */
-       W(RGF_DMA_ITR_RX_IDL_CNT_CTL, BIT_DMA_ITR_RX_IDL_CNT_CTL_EN |
-                                     BIT_DMA_ITR_RX_IDL_CNT_CTL_EXT_TIC_SEL);
+       wil_w(wil, RGF_DMA_ITR_RX_IDL_CNT_CTL, BIT_DMA_ITR_RX_IDL_CNT_CTL_EN |
+             BIT_DMA_ITR_RX_IDL_CNT_CTL_EXT_TIC_SEL);
 }
 
-#undef W
-
 static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
 {
        struct wil6210_priv *wil = cookie;
@@ -249,7 +236,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
 
                isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE |
                         BIT_DMA_EP_RX_ICR_RX_HTRSH);
-               if (likely(test_bit(wil_status_reset_done, wil->status))) {
+               if (likely(test_bit(wil_status_fwready, wil->status))) {
                        if (likely(test_bit(wil_status_napi_en, wil->status))) {
                                wil_dbg_txrx(wil, "NAPI(Rx) schedule\n");
                                need_unmask = false;
@@ -299,7 +286,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
                isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE;
                /* clear also all VRING interrupts */
                isr &= ~(BIT(25) - 1UL);
-               if (likely(test_bit(wil_status_reset_done, wil->status))) {
+               if (likely(test_bit(wil_status_fwready, wil->status))) {
                        wil_dbg_txrx(wil, "NAPI(Tx) schedule\n");
                        need_unmask = false;
                        napi_schedule(&wil->napi_tx);
@@ -360,7 +347,12 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
        wil6210_mask_irq_misc(wil);
 
        if (isr & ISR_MISC_FW_ERROR) {
-               wil_err(wil, "Firmware error detected\n");
+               u32 fw_assert_code = wil_r(wil, RGF_FW_ASSERT_CODE);
+               u32 ucode_assert_code = wil_r(wil, RGF_UCODE_ASSERT_CODE);
+
+               wil_err(wil,
+                       "Firmware error detected, assert codes FW 0x%08x, UCODE 0x%08x\n",
+                       fw_assert_code, ucode_assert_code);
                clear_bit(wil_status_fwready, wil->status);
                /*
                 * do not clear @isr here - we do 2-nd part in thread
@@ -372,7 +364,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
        if (isr & ISR_MISC_FW_READY) {
                wil_dbg_irq(wil, "IRQ: FW ready\n");
                wil_cache_mbox_regs(wil);
-               set_bit(wil_status_reset_done, wil->status);
+               set_bit(wil_status_mbox_ready, wil->status);
                /**
                 * Actual FW ready indicated by the
                 * WMI_FW_READY_EVENTID
@@ -399,6 +391,7 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
        wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr);
 
        if (isr & ISR_MISC_FW_ERROR) {
+               wil_fw_core_dump(wil);
                wil_notify_fw_error(wil);
                isr &= ~ISR_MISC_FW_ERROR;
                wil_fw_error_recovery(wil);
@@ -452,27 +445,24 @@ static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause)
                u32 icr_rx = wil_ioread32_and_clear(wil->csr +
                                HOSTADDR(RGF_DMA_EP_RX_ICR) +
                                offsetof(struct RGF_ICR, ICR));
-               u32 imv_rx = ioread32(wil->csr +
-                               HOSTADDR(RGF_DMA_EP_RX_ICR) +
-                               offsetof(struct RGF_ICR, IMV));
+               u32 imv_rx = wil_r(wil, RGF_DMA_EP_RX_ICR +
+                                  offsetof(struct RGF_ICR, IMV));
                u32 icm_tx = wil_ioread32_and_clear(wil->csr +
                                HOSTADDR(RGF_DMA_EP_TX_ICR) +
                                offsetof(struct RGF_ICR, ICM));
                u32 icr_tx = wil_ioread32_and_clear(wil->csr +
                                HOSTADDR(RGF_DMA_EP_TX_ICR) +
                                offsetof(struct RGF_ICR, ICR));
-               u32 imv_tx = ioread32(wil->csr +
-                               HOSTADDR(RGF_DMA_EP_TX_ICR) +
-                               offsetof(struct RGF_ICR, IMV));
+               u32 imv_tx = wil_r(wil, RGF_DMA_EP_TX_ICR +
+                                  offsetof(struct RGF_ICR, IMV));
                u32 icm_misc = wil_ioread32_and_clear(wil->csr +
                                HOSTADDR(RGF_DMA_EP_MISC_ICR) +
                                offsetof(struct RGF_ICR, ICM));
                u32 icr_misc = wil_ioread32_and_clear(wil->csr +
                                HOSTADDR(RGF_DMA_EP_MISC_ICR) +
                                offsetof(struct RGF_ICR, ICR));
-               u32 imv_misc = ioread32(wil->csr +
-                               HOSTADDR(RGF_DMA_EP_MISC_ICR) +
-                               offsetof(struct RGF_ICR, IMV));
+               u32 imv_misc = wil_r(wil, RGF_DMA_EP_MISC_ICR +
+                                    offsetof(struct RGF_ICR, IMV));
                wil_err(wil, "IRQ when it should be masked: pseudo 0x%08x\n"
                                "Rx   icm:icr:imv 0x%08x 0x%08x 0x%08x\n"
                                "Tx   icm:icr:imv 0x%08x 0x%08x 0x%08x\n"
@@ -492,7 +482,7 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie)
 {
        irqreturn_t rc = IRQ_HANDLED;
        struct wil6210_priv *wil = cookie;
-       u32 pseudo_cause = ioread32(wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE));
+       u32 pseudo_cause = wil_r(wil, RGF_DMA_PSEUDO_CAUSE);
 
        /**
         * pseudo_cause is Clear-On-Read, no need to ACK
@@ -541,48 +531,12 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie)
        return rc;
 }
 
-static int wil6210_request_3msi(struct wil6210_priv *wil, int irq)
-{
-       int rc;
-       /*
-        * IRQ's are in the following order:
-        * - Tx
-        * - Rx
-        * - Misc
-        */
-
-       rc = request_irq(irq, wil6210_irq_tx, IRQF_SHARED,
-                        WIL_NAME"_tx", wil);
-       if (rc)
-               return rc;
-
-       rc = request_irq(irq + 1, wil6210_irq_rx, IRQF_SHARED,
-                        WIL_NAME"_rx", wil);
-       if (rc)
-               goto free0;
-
-       rc = request_threaded_irq(irq + 2, wil6210_irq_misc,
-                                 wil6210_irq_misc_thread,
-                                 IRQF_SHARED, WIL_NAME"_misc", wil);
-       if (rc)
-               goto free1;
-
-       return 0;
-       /* error branch */
-free1:
-       free_irq(irq + 1, wil);
-free0:
-       free_irq(irq, wil);
-
-       return rc;
-}
-
 /* can't use wil_ioread32_and_clear because ICC value is not set yet */
 static inline void wil_clear32(void __iomem *addr)
 {
-       u32 x = ioread32(addr);
+       u32 x = readl(addr);
 
-       iowrite32(x, addr);
+       writel(x, addr);
 }
 
 void wil6210_clear_irq(struct wil6210_priv *wil)
@@ -596,19 +550,16 @@ void wil6210_clear_irq(struct wil6210_priv *wil)
        wmb(); /* make sure write completed */
 }
 
-int wil6210_init_irq(struct wil6210_priv *wil, int irq)
+int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi)
 {
        int rc;
 
-       wil_dbg_misc(wil, "%s() n_msi=%d\n", __func__, wil->n_msi);
+       wil_dbg_misc(wil, "%s(%s)\n", __func__, use_msi ? "MSI" : "INTx");
 
-       if (wil->n_msi == 3)
-               rc = wil6210_request_3msi(wil, irq);
-       else
-               rc = request_threaded_irq(irq, wil6210_hardirq,
-                                         wil6210_thread_irq,
-                                         wil->n_msi ? 0 : IRQF_SHARED,
-                                         WIL_NAME, wil);
+       rc = request_threaded_irq(irq, wil6210_hardirq,
+                                 wil6210_thread_irq,
+                                 use_msi ? 0 : IRQF_SHARED,
+                                 WIL_NAME, wil);
        return rc;
 }
 
@@ -618,8 +569,4 @@ void wil6210_fini_irq(struct wil6210_priv *wil, int irq)
 
        wil_mask_irq(wil);
        free_irq(irq, wil);
-       if (wil->n_msi == 3) {
-               free_irq(irq + 1, wil);
-               free_irq(irq + 2, wil);
-       }
 }