diff options
author | David S. Miller <davem@davemloft.net> | 2014-11-10 14:34:59 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-11-10 14:34:59 -0500 |
commit | b92172661e63c1f3528015bb378954c1a9e5bf4a (patch) | |
tree | 5794874cfe80a3bfc4c1038faafdbec14d412ee1 /drivers/net/wireless/ath/ath10k/pci.c | |
parent | e344458fc011bf4bea52a090895c38c4634ab402 (diff) | |
parent | bf515fb11ab539c76d04f0e3c5216ed41f41d81f (diff) | |
download | linux-b92172661e63c1f3528015bb378954c1a9e5bf4a.tar.gz linux-b92172661e63c1f3528015bb378954c1a9e5bf4a.tar.bz2 linux-b92172661e63c1f3528015bb378954c1a9e5bf4a.zip |
Merge tag 'master-2014-11-04' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
John W. Linville says:
====================
pull request: wireless-next 2014-11-07
Please pull this batch of updates intended for the 3.19 stream!
For the mac80211 bits, Johannes says:
"This relatively large batch of changes is comprised of the following:
* large mac80211-hwsim changes from Ben, Jukka and a bit myself
* OCB/WAVE/11p support from Rostislav on behalf of the Czech Technical
University in Prague and Volkswagen Group Research
* minstrel VHT work from Karl
* more CSA work from Luca
* WMM admission control support in mac80211 (myself)
* various smaller fixes, spelling corrections, and minor API additions"
For the Bluetooth bits, Johan says:
"Here's the first bluetooth-next pull request for 3.19. The vast majority
of patches are for ieee802154 from Alexander Aring with various fixes
and cleanups. There are also several LE/SMP fixes as well as improved
support for handling LE devices that have lost their pairing information
(the patches from Alfonso). Jukka provides a couple of stability fixes
for 6lowpan and Szymon conformance fixes for RFCOMM. For the HCI drivers
we have one new USB ID for an Acer controller as well as a reset
handling fix for H5."
For the Atheros bits, Kalle says:
"Major changes are:
o ethtool support (Ben)
o print dev string prefix with debug hex buffers dump (Michal)
o debugfs file to read calibration data from the firmware verification
purposes (me)
o fix fw_stats debugfs file, now results are more reliable (Michal)
o firmware crash counters via debugfs (Ben&me)
o various tracing points to debug firmware (Rajkumar)
o make it possible to provide firmware calibration data via a file (me)
And we have quite a lot of smaller fixes and clean up."
For the iwlwifi bits, Emmanuel says:
"The big new thing here is netdetect which allows the
firmware to wake up the platform when a specific network
is detected. Along with that I have fixes for d3 operation.
The usual amount of rate scaling stuff - we now support STBC.
The other commit that stands out is Johannes's work on
devcoredump. He basically starts to use the standard
infrastructure he built."
Along with that are the usual sort of updates and such for ath9k,
brcmfmac, wil6210, and a handful of other bits here and there...
Please let me know if there are problems!
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/pci.c')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/pci.c | 203 |
1 files changed, 122 insertions, 81 deletions
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 59e0ea83be50..4a4740b4bdc0 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -485,6 +485,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, void *data_buf = NULL; int i; + spin_lock_bh(&ar_pci->ce_lock); + ce_diag = ar_pci->ce_diag; /* @@ -511,7 +513,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, nbytes = min_t(unsigned int, remaining_bytes, DIAG_TRANSFER_LIMIT); - ret = ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data); + ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data); if (ret != 0) goto done; @@ -527,15 +529,15 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem, address); - ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0, - 0); + ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0, + 0); if (ret) goto done; i = 0; - while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf, - &completed_nbytes, - &id) != 0) { + while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf, + &completed_nbytes, + &id) != 0) { mdelay(1); if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { ret = -EBUSY; @@ -554,9 +556,9 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, } i = 0; - while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf, - &completed_nbytes, - &id, &flags) != 0) { + while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, + &completed_nbytes, + &id, &flags) != 0) { mdelay(1); if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { @@ -591,6 +593,8 @@ done: dma_free_coherent(ar->dev, orig_nbytes, data_buf, ce_data_base); + spin_unlock_bh(&ar_pci->ce_lock); + return ret; } @@ -648,6 +652,8 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, dma_addr_t ce_data_base = 0; int i; + spin_lock_bh(&ar_pci->ce_lock); + ce_diag = ar_pci->ce_diag; /* @@ -688,7 +694,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT); /* Set up to receive directly into Target(!) address */ - ret = ath10k_ce_rx_post_buf(ce_diag, NULL, address); + ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, address); if (ret != 0) goto done; @@ -696,15 +702,15 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, * Request CE to send caller-supplied data that * was copied to bounce buffer to Target(!) address. */ - ret = ath10k_ce_send(ce_diag, NULL, (u32)ce_data, - nbytes, 0, 0); + ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)ce_data, + nbytes, 0, 0); if (ret != 0) goto done; i = 0; - while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf, - &completed_nbytes, - &id) != 0) { + while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf, + &completed_nbytes, + &id) != 0) { mdelay(1); if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { @@ -724,9 +730,9 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, } i = 0; - while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf, - &completed_nbytes, - &id, &flags) != 0) { + while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, + &completed_nbytes, + &id, &flags) != 0) { mdelay(1); if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { @@ -760,6 +766,8 @@ done: ath10k_warn(ar, "failed to write diag value at 0x%x: %d\n", address, ret); + spin_unlock_bh(&ar_pci->ce_lock); + return ret; } @@ -861,6 +869,12 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state) } skb_put(skb, nbytes); + + ath10k_dbg(ar, ATH10K_DBG_PCI, "pci rx ce pipe %d len %d\n", + ce_state->id, skb->len); + ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ", + skb->data, skb->len); + cb->rx_completion(ar, skb, pipe_info->pipe_num); } @@ -936,6 +950,12 @@ err: return err; } +static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf, + size_t buf_len) +{ + return ath10k_pci_diag_read_mem(ar, address, buf, buf_len); +} + static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -986,6 +1006,8 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar) spin_lock_bh(&ar->data_lock); + ar->stats.fw_crash_counter++; + crash_data = ath10k_debug_get_new_fw_crash_data(ar); if (crash_data) @@ -1121,14 +1143,37 @@ static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, &dl_is_polled); } -static void ath10k_pci_irq_disable(struct ath10k *ar) +static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - int i; + u32 val; + val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS); + val &= ~CORE_CTRL_PCIE_REG_31_MASK; + + ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val); +} + +static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar) +{ + u32 val; + + val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS); + val |= CORE_CTRL_PCIE_REG_31_MASK; + + ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val); +} + +static void ath10k_pci_irq_disable(struct ath10k *ar) +{ ath10k_ce_disable_interrupts(ar); ath10k_pci_disable_and_clear_legacy_irq(ar); - /* FIXME: How to mask all MSI interrupts? */ + ath10k_pci_irq_msi_fw_mask(ar); +} + +static void ath10k_pci_irq_sync(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int i; for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++) synchronize_irq(ar_pci->pdev->irq + i); @@ -1138,7 +1183,7 @@ static void ath10k_pci_irq_enable(struct ath10k *ar) { ath10k_ce_enable_interrupts(ar); ath10k_pci_enable_legacy_irq(ar); - /* FIXME: How to unmask all MSI interrupts? */ + ath10k_pci_irq_msi_fw_unmask(ar); } static int ath10k_pci_hif_start(struct ath10k *ar) @@ -1266,6 +1311,7 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) ath10k_pci_warm_reset(ar); ath10k_pci_irq_disable(ar); + ath10k_pci_irq_sync(ar); ath10k_pci_flush(ar); } @@ -1569,23 +1615,40 @@ static int ath10k_pci_init_config(struct ath10k *ar) return 0; } -static int ath10k_pci_alloc_ce(struct ath10k *ar) +static int ath10k_pci_alloc_pipes(struct ath10k *ar) { + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_pci_pipe *pipe; int i, ret; for (i = 0; i < CE_COUNT; i++) { - ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i]); + pipe = &ar_pci->pipe_info[i]; + pipe->ce_hdl = &ar_pci->ce_states[i]; + pipe->pipe_num = i; + pipe->hif_ce_state = ar; + + ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i], + ath10k_pci_ce_send_done, + ath10k_pci_ce_recv_data); if (ret) { ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n", i, ret); return ret; } + + /* Last CE is Diagnostic Window */ + if (i == CE_COUNT - 1) { + ar_pci->ce_diag = pipe->ce_hdl; + continue; + } + + pipe->buf_sz = (size_t)(host_ce_config_wlan[i].src_sz_max); } return 0; } -static void ath10k_pci_free_ce(struct ath10k *ar) +static void ath10k_pci_free_pipes(struct ath10k *ar) { int i; @@ -1593,39 +1656,17 @@ static void ath10k_pci_free_ce(struct ath10k *ar) ath10k_ce_free_pipe(ar, i); } -static int ath10k_pci_ce_init(struct ath10k *ar) +static int ath10k_pci_init_pipes(struct ath10k *ar) { - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_pci_pipe *pipe_info; - const struct ce_attr *attr; - int pipe_num, ret; + int i, ret; - for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) { - pipe_info = &ar_pci->pipe_info[pipe_num]; - pipe_info->ce_hdl = &ar_pci->ce_states[pipe_num]; - pipe_info->pipe_num = pipe_num; - pipe_info->hif_ce_state = ar; - attr = &host_ce_config_wlan[pipe_num]; - - ret = ath10k_ce_init_pipe(ar, pipe_num, attr, - ath10k_pci_ce_send_done, - ath10k_pci_ce_recv_data); + for (i = 0; i < CE_COUNT; i++) { + ret = ath10k_ce_init_pipe(ar, i, &host_ce_config_wlan[i]); if (ret) { ath10k_err(ar, "failed to initialize copy engine pipe %d: %d\n", - pipe_num, ret); + i, ret); return ret; } - - if (pipe_num == CE_COUNT - 1) { - /* - * Reserve the ultimate CE for - * diagnostic Window support - */ - ar_pci->ce_diag = pipe_info->ce_hdl; - continue; - } - - pipe_info->buf_sz = (size_t)(attr->src_sz_max); } return 0; @@ -1672,6 +1713,12 @@ static int ath10k_pci_warm_reset(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n"); + spin_lock_bh(&ar->data_lock); + + ar->stats.fw_warm_reset_counter++; + + spin_unlock_bh(&ar->data_lock); + /* debug */ val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_CAUSE_ADDRESS); @@ -1773,7 +1820,7 @@ static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset) goto err; } - ret = ath10k_pci_ce_init(ar); + ret = ath10k_pci_init_pipes(ar); if (ret) { ath10k_err(ar, "failed to initialize CE: %d\n", ret); goto err; @@ -1921,6 +1968,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar) static const struct ath10k_hif_ops ath10k_pci_hif_ops = { .tx_sg = ath10k_pci_hif_tx_sg, + .diag_read = ath10k_pci_hif_diag_read, .exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg, .start = ath10k_pci_hif_start, .stop = ath10k_pci_hif_stop, @@ -2250,14 +2298,14 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar) if (ar_pci->num_msi_intrs == 0) /* Fix potential race by repeating CORE_BASE writes */ - ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + - PCIE_INTR_ENABLE_ADDRESS, - PCIE_INTR_FIRMWARE_MASK | - PCIE_INTR_CE_MASK_ALL); + ath10k_pci_enable_legacy_irq(ar); mdelay(10); } while (time_before(jiffies, timeout)); + ath10k_pci_disable_and_clear_legacy_irq(ar); + ath10k_pci_irq_msi_fw_mask(ar); + if (val == 0xffffffff) { ath10k_err(ar, "failed to read device register, device is gone\n"); return -EIO; @@ -2287,6 +2335,12 @@ static int ath10k_pci_cold_reset(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n"); + spin_lock_bh(&ar->data_lock); + + ar->stats.fw_cold_reset_counter++; + + spin_unlock_bh(&ar->data_lock); + /* Put Target, including PCIe, into RESET. */ val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS); val |= 1; @@ -2400,6 +2454,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, u32 chip_id; ar = ath10k_core_create(sizeof(*ar_pci), &pdev->dev, + ATH10K_BUS_PCI, &ath10k_pci_hif_ops); if (!ar) { dev_err(&pdev->dev, "failed to allocate core\n"); @@ -2435,7 +2490,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, goto err_sleep; } - ret = ath10k_pci_alloc_ce(ar); + ret = ath10k_pci_alloc_pipes(ar); if (ret) { ath10k_err(ar, "failed to allocate copy engine pipes: %d\n", ret); @@ -2443,25 +2498,12 @@ static int ath10k_pci_probe(struct pci_dev *pdev, } ath10k_pci_ce_deinit(ar); - - ret = ath10k_ce_disable_interrupts(ar); - if (ret) { - ath10k_err(ar, "failed to disable copy engine interrupts: %d\n", - ret); - goto err_free_ce; - } - - /* Workaround: There's no known way to mask all possible interrupts via - * device CSR. The only way to make sure device doesn't assert - * interrupts is to reset it. Interrupts are then disabled on host - * after handlers are registered. - */ - ath10k_pci_warm_reset(ar); + ath10k_pci_irq_disable(ar); ret = ath10k_pci_init_irq(ar); if (ret) { ath10k_err(ar, "failed to init irqs: %d\n", ret); - goto err_free_ce; + goto err_free_pipes; } ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n", @@ -2474,9 +2516,6 @@ static int ath10k_pci_probe(struct pci_dev *pdev, goto err_deinit_irq; } - /* This shouldn't race as the device has been reset above. */ - ath10k_pci_irq_disable(ar); - ret = ath10k_core_register(ar, chip_id); if (ret) { ath10k_err(ar, "failed to register driver core: %d\n", ret); @@ -2492,8 +2531,8 @@ err_free_irq: err_deinit_irq: ath10k_pci_deinit_irq(ar); -err_free_ce: - ath10k_pci_free_ce(ar); +err_free_pipes: + ath10k_pci_free_pipes(ar); err_sleep: ath10k_pci_sleep(ar); @@ -2527,7 +2566,7 @@ static void ath10k_pci_remove(struct pci_dev *pdev) ath10k_pci_kill_tasklet(ar); ath10k_pci_deinit_irq(ar); ath10k_pci_ce_deinit(ar); - ath10k_pci_free_ce(ar); + ath10k_pci_free_pipes(ar); ath10k_pci_sleep(ar); ath10k_pci_release(ar); ath10k_core_destroy(ar); @@ -2565,5 +2604,7 @@ module_exit(ath10k_pci_exit); MODULE_AUTHOR("Qualcomm Atheros"); MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices"); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_3_FILE); +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 "/" QCA988X_HW_2_0_BOARD_DATA_FILE); |