ath10k: allow loading device specific board files
[deliverable/linux.git] / drivers / net / wireless / ath / ath10k / pci.c
index 7abb8367119a872f0de5063d9ff1f75025abcebd..9dc0079a8ea6dba482191c3110dd987825d227ff 100644 (file)
@@ -58,12 +58,27 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)");
 #define ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS 3
 
 #define QCA988X_2_0_DEVICE_ID  (0x003c)
+#define QCA6174_2_1_DEVICE_ID  (0x003e)
 
 static const struct pci_device_id ath10k_pci_id_table[] = {
        { PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */
+       { PCI_VDEVICE(ATHEROS, QCA6174_2_1_DEVICE_ID) }, /* PCI-E QCA6174 V2.1 */
        {0}
 };
 
+static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = {
+       /* QCA988X pre 2.0 chips are not supported because they need some nasty
+        * hacks. ath10k doesn't have them and these devices crash horribly
+        * because of that.
+        */
+       { QCA988X_2_0_DEVICE_ID, QCA988X_HW_2_0_CHIP_ID_REV },
+       { QCA6174_2_1_DEVICE_ID, QCA6174_HW_2_1_CHIP_ID_REV },
+       { QCA6174_2_1_DEVICE_ID, QCA6174_HW_2_2_CHIP_ID_REV },
+       { QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_0_CHIP_ID_REV },
+       { QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_1_CHIP_ID_REV },
+       { QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_2_CHIP_ID_REV },
+};
+
 static void ath10k_pci_buffer_cleanup(struct ath10k *ar);
 static int ath10k_pci_cold_reset(struct ath10k *ar);
 static int ath10k_pci_warm_reset(struct ath10k *ar);
@@ -89,7 +104,7 @@ static const struct ce_attr host_ce_config_wlan[] = {
        {
                .flags = CE_ATTR_FLAGS,
                .src_nentries = 0,
-               .src_sz_max = 512,
+               .src_sz_max = 2048,
                .dest_nentries = 512,
        },
 
@@ -98,7 +113,7 @@ static const struct ce_attr host_ce_config_wlan[] = {
                .flags = CE_ATTR_FLAGS,
                .src_nentries = 0,
                .src_sz_max = 2048,
-               .dest_nentries = 32,
+               .dest_nentries = 128,
        },
 
        /* CE3: host->target WMI */
@@ -159,7 +174,7 @@ static const struct ce_pipe_config target_ce_config_wlan[] = {
                .pipenum = __cpu_to_le32(1),
                .pipedir = __cpu_to_le32(PIPEDIR_IN),
                .nentries = __cpu_to_le32(32),
-               .nbytes_max = __cpu_to_le32(512),
+               .nbytes_max = __cpu_to_le32(2048),
                .flags = __cpu_to_le32(CE_ATTR_FLAGS),
                .reserved = __cpu_to_le32(0),
        },
@@ -168,7 +183,7 @@ static const struct ce_pipe_config target_ce_config_wlan[] = {
        {
                .pipenum = __cpu_to_le32(2),
                .pipedir = __cpu_to_le32(PIPEDIR_IN),
-               .nentries = __cpu_to_le32(32),
+               .nentries = __cpu_to_le32(64),
                .nbytes_max = __cpu_to_le32(2048),
                .flags = __cpu_to_le32(CE_ATTR_FLAGS),
                .reserved = __cpu_to_le32(0),
@@ -395,7 +410,7 @@ static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe)
                return -EIO;
        }
 
-       ATH10K_SKB_CB(skb)->paddr = paddr;
+       ATH10K_SKB_RXCB(skb)->paddr = paddr;
 
        ret = __ath10k_ce_rx_post_buf(ce_pipe, skb, paddr);
        if (ret) {
@@ -804,6 +819,21 @@ static int ath10k_pci_wake_wait(struct ath10k *ar)
        return -ETIMEDOUT;
 }
 
+/* The rule is host is forbidden from accessing device registers while it's
+ * asleep. Currently ath10k_pci_wake() and ath10k_pci_sleep() calls aren't
+ * balanced and the device is kept awake all the time. This is intended for a
+ * simpler solution for the following problems:
+ *
+ *   * device can enter sleep during s2ram without the host knowing,
+ *
+ *   * irq handlers access registers which is a problem if other device asserts
+ *     a shared irq line when ath10k is between hif_power_down() and
+ *     hif_power_up().
+ *
+ * FIXME: If power consumption is a concern (and there are *real* gains) then a
+ * refcounted wake/sleep needs to be implemented.
+ */
+
 static int ath10k_pci_wake(struct ath10k *ar)
 {
        ath10k_pci_reg_write32(ar, PCIE_SOC_WAKE_ADDRESS,
@@ -864,7 +894,7 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state)
                                             &flags) == 0) {
                skb = transfer_context;
                max_nbytes = skb->len + skb_tailroom(skb);
-               dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr,
+               dma_unmap_single(ar->dev, ATH10K_SKB_RXCB(skb)->paddr,
                                 max_nbytes, DMA_FROM_DEVICE);
 
                if (unlikely(max_nbytes < nbytes)) {
@@ -1230,7 +1260,7 @@ static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
 
                ce_ring->per_transfer_context[i] = NULL;
 
-               dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr,
+               dma_unmap_single(ar->dev, ATH10K_SKB_RXCB(skb)->paddr,
                                 skb->len + skb_tailroom(skb),
                                 DMA_FROM_DEVICE);
                dev_kfree_skb_any(skb);
@@ -1498,6 +1528,35 @@ static int ath10k_pci_wake_target_cpu(struct ath10k *ar)
        return 0;
 }
 
+static int ath10k_pci_get_num_banks(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+       switch (ar_pci->pdev->device) {
+       case QCA988X_2_0_DEVICE_ID:
+               return 1;
+       case QCA6174_2_1_DEVICE_ID:
+               switch (MS(ar->chip_id, SOC_CHIP_ID_REV)) {
+               case QCA6174_HW_1_0_CHIP_ID_REV:
+               case QCA6174_HW_1_1_CHIP_ID_REV:
+                       return 3;
+               case QCA6174_HW_1_3_CHIP_ID_REV:
+                       return 2;
+               case QCA6174_HW_2_1_CHIP_ID_REV:
+               case QCA6174_HW_2_2_CHIP_ID_REV:
+                       return 6;
+               case QCA6174_HW_3_0_CHIP_ID_REV:
+               case QCA6174_HW_3_1_CHIP_ID_REV:
+               case QCA6174_HW_3_2_CHIP_ID_REV:
+                       return 9;
+               }
+               break;
+       }
+
+       ath10k_warn(ar, "unknown number of banks, assuming 1\n");
+       return 1;
+}
+
 static int ath10k_pci_init_config(struct ath10k *ar)
 {
        u32 interconnect_targ_addr;
@@ -1608,7 +1667,8 @@ static int ath10k_pci_init_config(struct ath10k *ar)
        /* first bank is switched to IRAM */
        ealloc_value |= ((HI_EARLY_ALLOC_MAGIC << HI_EARLY_ALLOC_MAGIC_SHIFT) &
                         HI_EARLY_ALLOC_MAGIC_MASK);
-       ealloc_value |= ((1 << HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) &
+       ealloc_value |= ((ath10k_pci_get_num_banks(ar) <<
+                         HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) &
                         HI_EARLY_ALLOC_IRAM_BANKS_MASK);
 
        ret = ath10k_pci_diag_write32(ar, ealloc_targ_addr, ealloc_value);
@@ -1804,12 +1864,12 @@ static int ath10k_pci_warm_reset(struct ath10k *ar)
        return 0;
 }
 
-static int ath10k_pci_chip_reset(struct ath10k *ar)
+static int ath10k_pci_qca988x_chip_reset(struct ath10k *ar)
 {
        int i, ret;
        u32 val;
 
-       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset\n");
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot 988x chip reset\n");
 
        /* Some hardware revisions (e.g. CUS223v2) has issues with cold reset.
         * It is thus preferred to use warm reset which is safer but may not be
@@ -1873,11 +1933,53 @@ static int ath10k_pci_chip_reset(struct ath10k *ar)
                return ret;
        }
 
-       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset complete (cold)\n");
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot qca988x chip reset complete (cold)\n");
+
+       return 0;
+}
+
+static int ath10k_pci_qca6174_chip_reset(struct ath10k *ar)
+{
+       int ret;
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot qca6174 chip reset\n");
+
+       /* FIXME: QCA6174 requires cold + warm reset to work. */
+
+       ret = ath10k_pci_cold_reset(ar);
+       if (ret) {
+               ath10k_warn(ar, "failed to cold reset: %d\n", ret);
+               return ret;
+       }
+
+       ret = ath10k_pci_wait_for_target_init(ar);
+       if (ret) {
+               ath10k_warn(ar, "failed to wait for target after cold reset: %d\n",
+                               ret);
+               return ret;
+       }
+
+       ret = ath10k_pci_warm_reset(ar);
+       if (ret) {
+               ath10k_warn(ar, "failed to warm reset: %d\n", ret);
+               return ret;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot qca6174 chip reset complete (cold)\n");
 
        return 0;
 }
 
+static int ath10k_pci_chip_reset(struct ath10k *ar)
+{
+       if (QCA_REV_988X(ar))
+               return ath10k_pci_qca988x_chip_reset(ar);
+       else if (QCA_REV_6174(ar))
+               return ath10k_pci_qca6174_chip_reset(ar);
+       else
+               return -ENOTSUPP;
+}
+
 static int ath10k_pci_hif_power_up(struct ath10k *ar)
 {
        int ret;
@@ -1902,6 +2004,12 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
         */
        ret = ath10k_pci_chip_reset(ar);
        if (ret) {
+               if (ath10k_pci_has_fw_crashed(ar)) {
+                       ath10k_warn(ar, "firmware crashed during chip reset\n");
+                       ath10k_pci_fw_crashed_clear(ar);
+                       ath10k_pci_fw_crashed_dump(ar);
+               }
+
                ath10k_err(ar, "failed to reset chip: %d\n", ret);
                goto err_sleep;
        }
@@ -1941,28 +2049,13 @@ static void ath10k_pci_hif_power_down(struct ath10k *ar)
        /* Currently hif_power_up performs effectively a reset and hif_stop
         * resets the chip as well so there's no point in resetting here.
         */
-
-       ath10k_pci_sleep(ar);
 }
 
 #ifdef CONFIG_PM
 
-#define ATH10K_PCI_PM_CONTROL 0x44
-
 static int ath10k_pci_hif_suspend(struct ath10k *ar)
 {
-       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       struct pci_dev *pdev = ar_pci->pdev;
-       u32 val;
-
-       pci_read_config_dword(pdev, ATH10K_PCI_PM_CONTROL, &val);
-
-       if ((val & 0x000000ff) != 0x3) {
-               pci_save_state(pdev);
-               pci_disable_device(pdev);
-               pci_write_config_dword(pdev, ATH10K_PCI_PM_CONTROL,
-                                      (val & 0xffffff00) | 0x03);
-       }
+       ath10k_pci_sleep(ar);
 
        return 0;
 }
@@ -1972,25 +2065,24 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        struct pci_dev *pdev = ar_pci->pdev;
        u32 val;
+       int ret;
 
-       pci_read_config_dword(pdev, ATH10K_PCI_PM_CONTROL, &val);
-
-       if ((val & 0x000000ff) != 0) {
-               pci_restore_state(pdev);
-               pci_write_config_dword(pdev, ATH10K_PCI_PM_CONTROL,
-                                      val & 0xffffff00);
-               /*
-                * Suspend/Resume resets the PCI configuration space,
-                * so we have to re-disable the RETRY_TIMEOUT register (0x41)
-                * to keep PCI Tx retries from interfering with C3 CPU state
-                */
-               pci_read_config_dword(pdev, 0x40, &val);
-
-               if ((val & 0x0000ff00) != 0)
-                       pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+       ret = ath10k_pci_wake(ar);
+       if (ret) {
+               ath10k_err(ar, "failed to wake device up on resume: %d\n", ret);
+               return ret;
        }
 
-       return 0;
+       /* Suspend/Resume resets the PCI configuration space, so we have to
+        * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
+        * from interfering with C3 CPU state. pci_restore_state won't help
+        * here since it only restores the first 64 bytes pci config header.
+        */
+       pci_read_config_dword(pdev, 0x40, &val);
+       if ((val & 0x0000ff00) != 0)
+               pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+       return ret;
 }
 #endif
 
@@ -2033,6 +2125,7 @@ static void ath10k_msi_err_tasklet(unsigned long data)
                return;
        }
 
+       ath10k_pci_irq_disable(ar);
        ath10k_pci_fw_crashed_clear(ar);
        ath10k_pci_fw_crashed_dump(ar);
 }
@@ -2083,6 +2176,13 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg)
 {
        struct ath10k *ar = arg;
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       int ret;
+
+       ret = ath10k_pci_wake(ar);
+       if (ret) {
+               ath10k_warn(ar, "failed to wake device up on irq: %d\n", ret);
+               return IRQ_NONE;
+       }
 
        if (ar_pci->num_msi_intrs == 0) {
                if (!ath10k_pci_irq_pending(ar))
@@ -2102,6 +2202,7 @@ static void ath10k_pci_tasklet(unsigned long data)
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 
        if (ath10k_pci_has_fw_crashed(ar)) {
+               ath10k_pci_irq_disable(ar);
                ath10k_pci_fw_crashed_clear(ar);
                ath10k_pci_fw_crashed_dump(ar);
                return;
@@ -2344,8 +2445,6 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar)
 
        if (val & FW_IND_EVENT_PENDING) {
                ath10k_warn(ar, "device has crashed during init\n");
-               ath10k_pci_fw_crashed_clear(ar);
-               ath10k_pci_fw_crashed_dump(ar);
                return -ECOMM;
        }
 
@@ -2476,17 +2575,46 @@ static void ath10k_pci_release(struct ath10k *ar)
        pci_disable_device(pdev);
 }
 
+static bool ath10k_pci_chip_is_supported(u32 dev_id, u32 chip_id)
+{
+       const struct ath10k_pci_supp_chip *supp_chip;
+       int i;
+       u32 rev_id = MS(chip_id, SOC_CHIP_ID_REV);
+
+       for (i = 0; i < ARRAY_SIZE(ath10k_pci_supp_chips); i++) {
+               supp_chip = &ath10k_pci_supp_chips[i];
+
+               if (supp_chip->dev_id == dev_id &&
+                   supp_chip->rev_id == rev_id)
+                       return true;
+       }
+
+       return false;
+}
+
 static int ath10k_pci_probe(struct pci_dev *pdev,
                            const struct pci_device_id *pci_dev)
 {
        int ret = 0;
        struct ath10k *ar;
        struct ath10k_pci *ar_pci;
+       enum ath10k_hw_rev hw_rev;
        u32 chip_id;
 
-       ar = ath10k_core_create(sizeof(*ar_pci), &pdev->dev,
-                               ATH10K_BUS_PCI,
-                               &ath10k_pci_hif_ops);
+       switch (pci_dev->device) {
+       case QCA988X_2_0_DEVICE_ID:
+               hw_rev = ATH10K_HW_QCA988X;
+               break;
+       case QCA6174_2_1_DEVICE_ID:
+               hw_rev = ATH10K_HW_QCA6174;
+               break;
+       default:
+               WARN_ON(1);
+               return -ENOTSUPP;
+       }
+
+       ar = ath10k_core_create(sizeof(*ar_pci), &pdev->dev, ATH10K_BUS_PCI,
+                               hw_rev, &ath10k_pci_hif_ops);
        if (!ar) {
                dev_err(&pdev->dev, "failed to allocate core\n");
                return -ENOMEM;
@@ -2499,6 +2627,12 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
        ar_pci->dev = &pdev->dev;
        ar_pci->ar = ar;
 
+       if (pdev->subsystem_vendor || pdev->subsystem_device)
+               scnprintf(ar->spec_board_id, sizeof(ar->spec_board_id),
+                         "%04x:%04x:%04x:%04x",
+                         pdev->vendor, pdev->device,
+                         pdev->subsystem_vendor, pdev->subsystem_device);
+
        spin_lock_init(&ar_pci->ce_lock);
        setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry,
                    (unsigned long)ar);
@@ -2515,12 +2649,6 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
                goto err_release;
        }
 
-       chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
-       if (chip_id == 0xffffffff) {
-               ath10k_err(ar, "failed to get chip id\n");
-               goto err_sleep;
-       }
-
        ret = ath10k_pci_alloc_pipes(ar);
        if (ret) {
                ath10k_err(ar, "failed to allocate copy engine pipes: %d\n",
@@ -2547,7 +2675,23 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
                goto err_deinit_irq;
        }
 
-       ath10k_pci_sleep(ar);
+       ret = ath10k_pci_chip_reset(ar);
+       if (ret) {
+               ath10k_err(ar, "failed to reset chip: %d\n", ret);
+               goto err_free_irq;
+       }
+
+       chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
+       if (chip_id == 0xffffffff) {
+               ath10k_err(ar, "failed to get chip id\n");
+               goto err_free_irq;
+       }
+
+       if (!ath10k_pci_chip_is_supported(pdev->device, chip_id)) {
+               ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n",
+                          pdev->device, chip_id);
+               goto err_free_irq;
+       }
 
        ret = ath10k_core_register(ar, chip_id);
        if (ret) {
@@ -2636,7 +2780,19 @@ module_exit(ath10k_pci_exit);
 MODULE_AUTHOR("Qualcomm Atheros");
 MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices");
 MODULE_LICENSE("Dual BSD/GPL");
+
+/* QCA988x 2.0 firmware files */
 MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_FILE);
 MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API2_FILE);
 MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API3_FILE);
+MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API4_FILE);
+MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API5_FILE);
 MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE);
+
+/* QCA6174 2.1 firmware files */
+MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API4_FILE);
+MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" QCA6174_HW_2_1_BOARD_DATA_FILE);
+
+/* QCA6174 3.1 firmware files */
+MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API4_FILE);
+MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" QCA6174_HW_3_0_BOARD_DATA_FILE);
This page took 0.046926 seconds and 5 git commands to generate.