diff options
author | Kalle Valo <kvalo@qca.qualcomm.com> | 2013-10-17 04:36:15 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2013-10-21 10:16:36 -0400 |
commit | f3782744c9b50edf94d28e37a937ff84f267dfab (patch) | |
tree | 4cb69ccd0ac2d3f8594971282a8acc4b9177ba4a /drivers/net/wireless/ath/ath10k/pci.c | |
parent | 60f85bea25d5e9915da8b0c87275143b317cec3b (diff) |
ath10k: add error handling to ath10k_pci_wait()
ath10k_pci_wait() didn't notify any errors to callers, it
just printed a warning so add proper error handling. This fixes
a crash Ben reported:
ath10k: MSI-X interrupt handling (8 intrs)
ath10k: Unable to wakeup target
ath10k: target took longer 5000 us to wake up (awake count 1)
ath10k: Failed to get pcie state addr: -16
ath10k: early firmware event indicated
BUG: unable to handle kernel NULL pointer dereference at 0000000000000004
IP: [<ffffffffa06ae46c>] ath10k_ce_completed_send_next+0x47/0x122 [ath10k_pci]
Reported-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/pci.c')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/pci.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 5c7838398e9a..42d2473b56ba 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c | |||
@@ -526,15 +526,19 @@ static bool ath10k_pci_target_is_awake(struct ath10k *ar) | |||
526 | return (RTC_STATE_V_GET(val) == RTC_STATE_V_ON); | 526 | return (RTC_STATE_V_GET(val) == RTC_STATE_V_ON); |
527 | } | 527 | } |
528 | 528 | ||
529 | static void ath10k_pci_wait(struct ath10k *ar) | 529 | static int ath10k_pci_wait(struct ath10k *ar) |
530 | { | 530 | { |
531 | int n = 100; | 531 | int n = 100; |
532 | 532 | ||
533 | while (n-- && !ath10k_pci_target_is_awake(ar)) | 533 | while (n-- && !ath10k_pci_target_is_awake(ar)) |
534 | msleep(10); | 534 | msleep(10); |
535 | 535 | ||
536 | if (n < 0) | 536 | if (n < 0) { |
537 | ath10k_warn("Unable to wakeup target\n"); | 537 | ath10k_warn("Unable to wakeup target\n"); |
538 | return -ETIMEDOUT; | ||
539 | } | ||
540 | |||
541 | return 0; | ||
538 | } | 542 | } |
539 | 543 | ||
540 | int ath10k_do_pci_wake(struct ath10k *ar) | 544 | int ath10k_do_pci_wake(struct ath10k *ar) |
@@ -2155,7 +2159,13 @@ static int ath10k_pci_start_intr_legacy(struct ath10k *ar) | |||
2155 | ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + | 2159 | ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + |
2156 | PCIE_SOC_WAKE_ADDRESS); | 2160 | PCIE_SOC_WAKE_ADDRESS); |
2157 | 2161 | ||
2158 | ath10k_pci_wait(ar); | 2162 | ret = ath10k_pci_wait(ar); |
2163 | if (ret) { | ||
2164 | ath10k_warn("Failed to enable legacy interrupt, target did not wake up: %d\n", | ||
2165 | ret); | ||
2166 | free_irq(ar_pci->pdev->irq, ar); | ||
2167 | return ret; | ||
2168 | } | ||
2159 | 2169 | ||
2160 | /* | 2170 | /* |
2161 | * A potential race occurs here: The CORE_BASE write | 2171 | * A potential race occurs here: The CORE_BASE write |
@@ -2218,6 +2228,10 @@ static int ath10k_pci_start_intr(struct ath10k *ar) | |||
2218 | } | 2228 | } |
2219 | 2229 | ||
2220 | ret = ath10k_pci_start_intr_legacy(ar); | 2230 | ret = ath10k_pci_start_intr_legacy(ar); |
2231 | if (ret) { | ||
2232 | ath10k_warn("Failed to start legacy interrupts: %d\n", ret); | ||
2233 | return ret; | ||
2234 | } | ||
2221 | 2235 | ||
2222 | exit: | 2236 | exit: |
2223 | ar_pci->num_msi_intrs = num; | 2237 | ar_pci->num_msi_intrs = num; |
@@ -2243,13 +2257,19 @@ static int ath10k_pci_reset_target(struct ath10k *ar) | |||
2243 | { | 2257 | { |
2244 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 2258 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
2245 | int wait_limit = 300; /* 3 sec */ | 2259 | int wait_limit = 300; /* 3 sec */ |
2260 | int ret; | ||
2246 | 2261 | ||
2247 | /* Wait for Target to finish initialization before we proceed. */ | 2262 | /* Wait for Target to finish initialization before we proceed. */ |
2248 | iowrite32(PCIE_SOC_WAKE_V_MASK, | 2263 | iowrite32(PCIE_SOC_WAKE_V_MASK, |
2249 | ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + | 2264 | ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + |
2250 | PCIE_SOC_WAKE_ADDRESS); | 2265 | PCIE_SOC_WAKE_ADDRESS); |
2251 | 2266 | ||
2252 | ath10k_pci_wait(ar); | 2267 | ret = ath10k_pci_wait(ar); |
2268 | if (ret) { | ||
2269 | ath10k_warn("Failed to reset target, target did not wake up: %d\n", | ||
2270 | ret); | ||
2271 | return ret; | ||
2272 | } | ||
2253 | 2273 | ||
2254 | while (wait_limit-- && | 2274 | while (wait_limit-- && |
2255 | !(ioread32(ar_pci->mem + FW_INDICATOR_ADDRESS) & | 2275 | !(ioread32(ar_pci->mem + FW_INDICATOR_ADDRESS) & |