aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnilkumar Kolli <akolli@qti.qualcomm.com>2015-10-16 08:54:51 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2015-10-19 10:38:01 -0400
commit1aaf8efba0aeb25eb5858b19472badaa54a41a38 (patch)
tree1bc3ea6d0198f5cac8395a87a495843f49657651
parent400143e45d39fcedb5106c3aa212746a80a61f7c (diff)
ath10k: disable PCI PS for QCA988X and QCA99X0
This patch disables PCI PS for QCA988X and QCA99X0, Since PCI PS is validated for QCA6174, let it be enabled only for QCA6174. It would be better to execute PCI PS related functions only for the supported devices. PCI time out issue is observed with QCA99X0 on x86 platform, We will disable PCI PS for QCA988X and QCA99X0 until PCI PS is properly implemented. Taking and releasing ps_lock is causing higher CPU consumption. Michal Kazior suggested ps_lock overhead to be reworked so that ath10k_pci_wake/sleep functions are called less often, i.e. move the powersave logic up (only during irq handling, tx path, submitting fw commands) but that's a bigger change and can be implemented later. Signed-off-by: Anilkumar Kolli <akolli@qti.qualcomm.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c83
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.h6
2 files changed, 88 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index adcda2815b73..5c05b0cf54a1 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -479,12 +479,53 @@ static int ath10k_pci_wake_wait(struct ath10k *ar)
479 return -ETIMEDOUT; 479 return -ETIMEDOUT;
480} 480}
481 481
482static int ath10k_pci_force_wake(struct ath10k *ar)
483{
484 struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
485 unsigned long flags;
486 int ret = 0;
487
488 spin_lock_irqsave(&ar_pci->ps_lock, flags);
489
490 if (!ar_pci->ps_awake) {
491 iowrite32(PCIE_SOC_WAKE_V_MASK,
492 ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
493 PCIE_SOC_WAKE_ADDRESS);
494
495 ret = ath10k_pci_wake_wait(ar);
496 if (ret == 0)
497 ar_pci->ps_awake = true;
498 }
499
500 spin_unlock_irqrestore(&ar_pci->ps_lock, flags);
501
502 return ret;
503}
504
505static void ath10k_pci_force_sleep(struct ath10k *ar)
506{
507 struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
508 unsigned long flags;
509
510 spin_lock_irqsave(&ar_pci->ps_lock, flags);
511
512 iowrite32(PCIE_SOC_WAKE_RESET,
513 ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
514 PCIE_SOC_WAKE_ADDRESS);
515 ar_pci->ps_awake = false;
516
517 spin_unlock_irqrestore(&ar_pci->ps_lock, flags);
518}
519
482static int ath10k_pci_wake(struct ath10k *ar) 520static int ath10k_pci_wake(struct ath10k *ar)
483{ 521{
484 struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); 522 struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
485 unsigned long flags; 523 unsigned long flags;
486 int ret = 0; 524 int ret = 0;
487 525
526 if (ar_pci->pci_ps == 0)
527 return ret;
528
488 spin_lock_irqsave(&ar_pci->ps_lock, flags); 529 spin_lock_irqsave(&ar_pci->ps_lock, flags);
489 530
490 ath10k_dbg(ar, ATH10K_DBG_PCI_PS, "pci ps wake refcount %lu awake %d\n", 531 ath10k_dbg(ar, ATH10K_DBG_PCI_PS, "pci ps wake refcount %lu awake %d\n",
@@ -516,6 +557,9 @@ static void ath10k_pci_sleep(struct ath10k *ar)
516 struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); 557 struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
517 unsigned long flags; 558 unsigned long flags;
518 559
560 if (ar_pci->pci_ps == 0)
561 return;
562
519 spin_lock_irqsave(&ar_pci->ps_lock, flags); 563 spin_lock_irqsave(&ar_pci->ps_lock, flags);
520 564
521 ath10k_dbg(ar, ATH10K_DBG_PCI_PS, "pci ps sleep refcount %lu awake %d\n", 565 ath10k_dbg(ar, ATH10K_DBG_PCI_PS, "pci ps sleep refcount %lu awake %d\n",
@@ -558,6 +602,11 @@ static void ath10k_pci_sleep_sync(struct ath10k *ar)
558 struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); 602 struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
559 unsigned long flags; 603 unsigned long flags;
560 604
605 if (ar_pci->pci_ps == 0) {
606 ath10k_pci_force_sleep(ar);
607 return;
608 }
609
561 del_timer_sync(&ar_pci->ps_timer); 610 del_timer_sync(&ar_pci->ps_timer);
562 611
563 spin_lock_irqsave(&ar_pci->ps_lock, flags); 612 spin_lock_irqsave(&ar_pci->ps_lock, flags);
@@ -2417,6 +2466,15 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
2417 struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); 2466 struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
2418 struct pci_dev *pdev = ar_pci->pdev; 2467 struct pci_dev *pdev = ar_pci->pdev;
2419 u32 val; 2468 u32 val;
2469 int ret = 0;
2470
2471 if (ar_pci->pci_ps == 0) {
2472 ret = ath10k_pci_force_wake(ar);
2473 if (ret) {
2474 ath10k_err(ar, "failed to wake up target: %d\n", ret);
2475 return ret;
2476 }
2477 }
2420 2478
2421 /* Suspend/Resume resets the PCI configuration space, so we have to 2479 /* Suspend/Resume resets the PCI configuration space, so we have to
2422 * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries 2480 * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
@@ -2427,7 +2485,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
2427 if ((val & 0x0000ff00) != 0) 2485 if ((val & 0x0000ff00) != 0)
2428 pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); 2486 pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
2429 2487
2430 return 0; 2488 return ret;
2431} 2489}
2432#endif 2490#endif
2433 2491
@@ -2520,6 +2578,16 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg)
2520{ 2578{
2521 struct ath10k *ar = arg; 2579 struct ath10k *ar = arg;
2522 struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); 2580 struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
2581 int ret;
2582
2583 if (ar_pci->pci_ps == 0) {
2584 ret = ath10k_pci_force_wake(ar);
2585 if (ret) {
2586 ath10k_warn(ar, "failed to wake device up on irq: %d\n",
2587 ret);
2588 return IRQ_NONE;
2589 }
2590 }
2523 2591
2524 if (ar_pci->num_msi_intrs == 0) { 2592 if (ar_pci->num_msi_intrs == 0) {
2525 if (!ath10k_pci_irq_pending(ar)) 2593 if (!ath10k_pci_irq_pending(ar))
@@ -2919,17 +2987,21 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
2919 struct ath10k_pci *ar_pci; 2987 struct ath10k_pci *ar_pci;
2920 enum ath10k_hw_rev hw_rev; 2988 enum ath10k_hw_rev hw_rev;
2921 u32 chip_id; 2989 u32 chip_id;
2990 bool pci_ps;
2922 2991
2923 switch (pci_dev->device) { 2992 switch (pci_dev->device) {
2924 case QCA988X_2_0_DEVICE_ID: 2993 case QCA988X_2_0_DEVICE_ID:
2925 hw_rev = ATH10K_HW_QCA988X; 2994 hw_rev = ATH10K_HW_QCA988X;
2995 pci_ps = false;
2926 break; 2996 break;
2927 case QCA6164_2_1_DEVICE_ID: 2997 case QCA6164_2_1_DEVICE_ID:
2928 case QCA6174_2_1_DEVICE_ID: 2998 case QCA6174_2_1_DEVICE_ID:
2929 hw_rev = ATH10K_HW_QCA6174; 2999 hw_rev = ATH10K_HW_QCA6174;
3000 pci_ps = true;
2930 break; 3001 break;
2931 case QCA99X0_2_0_DEVICE_ID: 3002 case QCA99X0_2_0_DEVICE_ID:
2932 hw_rev = ATH10K_HW_QCA99X0; 3003 hw_rev = ATH10K_HW_QCA99X0;
3004 pci_ps = false;
2933 break; 3005 break;
2934 default: 3006 default:
2935 WARN_ON(1); 3007 WARN_ON(1);
@@ -2952,6 +3024,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
2952 ar_pci->dev = &pdev->dev; 3024 ar_pci->dev = &pdev->dev;
2953 ar_pci->ar = ar; 3025 ar_pci->ar = ar;
2954 ar->dev_id = pci_dev->device; 3026 ar->dev_id = pci_dev->device;
3027 ar_pci->pci_ps = pci_ps;
2955 3028
2956 ar->id.vendor = pdev->vendor; 3029 ar->id.vendor = pdev->vendor;
2957 ar->id.device = pdev->device; 3030 ar->id.device = pdev->device;
@@ -2982,6 +3055,14 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
2982 ath10k_pci_ce_deinit(ar); 3055 ath10k_pci_ce_deinit(ar);
2983 ath10k_pci_irq_disable(ar); 3056 ath10k_pci_irq_disable(ar);
2984 3057
3058 if (ar_pci->pci_ps == 0) {
3059 ret = ath10k_pci_force_wake(ar);
3060 if (ret) {
3061 ath10k_warn(ar, "failed to wake up device : %d\n", ret);
3062 goto err_free_pipes;
3063 }
3064 }
3065
2985 ret = ath10k_pci_init_irq(ar); 3066 ret = ath10k_pci_init_irq(ar);
2986 if (ret) { 3067 if (ret) {
2987 ath10k_err(ar, "failed to init irqs: %d\n", ret); 3068 ath10k_err(ar, "failed to init irqs: %d\n", ret);
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index 87216b844133..f91bf333cb75 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -219,6 +219,12 @@ struct ath10k_pci {
219 * powersave register state changes. 219 * powersave register state changes.
220 */ 220 */
221 bool ps_awake; 221 bool ps_awake;
222
223 /* pci power save, disable for QCA988X and QCA99X0.
224 * Writing 'false' to this variable avoids frequent locking
225 * on MMIO read/write.
226 */
227 bool pci_ps;
222}; 228};
223 229
224static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) 230static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar)