Skip to content

Commit

Permalink
Merge branch 't7xx-pm-fixes'
Browse files Browse the repository at this point in the history
Kornel Dulęba says:

====================
net: wwan: t7xx: Fix Runtime PM implementation

d10b3a6 ("net: wwan: t7xx: Runtime PM") introduced support for
Runtime PM for this driver, but due to a bug in the initialization logic
the usage refcount would never reach 0, leaving the feature unused.
This patchset addresses that, together with a bug found after runtime
suspend was enabled.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jan 28, 2023
2 parents 60bd1d9 + e3d6d15 commit 906ad3c
Showing 4 changed files with 47 additions and 11 deletions.
11 changes: 10 additions & 1 deletion drivers/net/wwan/t7xx/t7xx_hif_dpmaif.c
Original file line number Diff line number Diff line change
@@ -152,6 +152,15 @@ static irqreturn_t t7xx_dpmaif_isr_handler(int irq, void *data)
}

t7xx_pcie_mac_clear_int(dpmaif_ctrl->t7xx_dev, isr_para->pcie_int);

return IRQ_WAKE_THREAD;
}

static irqreturn_t t7xx_dpmaif_isr_thread(int irq, void *data)
{
struct dpmaif_isr_para *isr_para = data;
struct dpmaif_ctrl *dpmaif_ctrl = isr_para->dpmaif_ctrl;

t7xx_dpmaif_irq_cb(isr_para);
t7xx_pcie_mac_set_int(dpmaif_ctrl->t7xx_dev, isr_para->pcie_int);
return IRQ_HANDLED;
@@ -188,7 +197,7 @@ static void t7xx_dpmaif_register_pcie_irq(struct dpmaif_ctrl *dpmaif_ctrl)
t7xx_pcie_mac_clear_int(t7xx_dev, int_type);

t7xx_dev->intr_handler[int_type] = t7xx_dpmaif_isr_handler;
t7xx_dev->intr_thread[int_type] = NULL;
t7xx_dev->intr_thread[int_type] = t7xx_dpmaif_isr_thread;
t7xx_dev->callback_param[int_type] = isr_para;

t7xx_pcie_mac_clear_int_status(t7xx_dev, int_type);
29 changes: 20 additions & 9 deletions drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c
Original file line number Diff line number Diff line change
@@ -840,14 +840,13 @@ int t7xx_dpmaif_napi_rx_poll(struct napi_struct *napi, const int budget)

if (!rxq->que_started) {
atomic_set(&rxq->rx_processing, 0);
pm_runtime_put_autosuspend(rxq->dpmaif_ctrl->dev);
dev_err(rxq->dpmaif_ctrl->dev, "Work RXQ: %d has not been started\n", rxq->index);
return work_done;
}

if (!rxq->sleep_lock_pending) {
pm_runtime_get_noresume(rxq->dpmaif_ctrl->dev);
if (!rxq->sleep_lock_pending)
t7xx_pci_disable_sleep(t7xx_dev);
}

ret = try_wait_for_completion(&t7xx_dev->sleep_lock_acquire);
if (!ret) {
@@ -876,22 +875,22 @@ int t7xx_dpmaif_napi_rx_poll(struct napi_struct *napi, const int budget)
napi_complete_done(napi, work_done);
t7xx_dpmaif_clr_ip_busy_sts(&rxq->dpmaif_ctrl->hw_info);
t7xx_dpmaif_dlq_unmask_rx_done(&rxq->dpmaif_ctrl->hw_info, rxq->index);
t7xx_pci_enable_sleep(rxq->dpmaif_ctrl->t7xx_dev);
pm_runtime_mark_last_busy(rxq->dpmaif_ctrl->dev);
pm_runtime_put_autosuspend(rxq->dpmaif_ctrl->dev);
atomic_set(&rxq->rx_processing, 0);
} else {
t7xx_dpmaif_clr_ip_busy_sts(&rxq->dpmaif_ctrl->hw_info);
}

t7xx_pci_enable_sleep(rxq->dpmaif_ctrl->t7xx_dev);
pm_runtime_mark_last_busy(rxq->dpmaif_ctrl->dev);
pm_runtime_put_noidle(rxq->dpmaif_ctrl->dev);
atomic_set(&rxq->rx_processing, 0);

return work_done;
}

void t7xx_dpmaif_irq_rx_done(struct dpmaif_ctrl *dpmaif_ctrl, const unsigned int que_mask)
{
struct dpmaif_rx_queue *rxq;
int qno;
struct dpmaif_ctrl *ctrl;
int qno, ret;

qno = ffs(que_mask) - 1;
if (qno < 0 || qno > DPMAIF_RXQ_NUM - 1) {
@@ -900,6 +899,18 @@ void t7xx_dpmaif_irq_rx_done(struct dpmaif_ctrl *dpmaif_ctrl, const unsigned int
}

rxq = &dpmaif_ctrl->rxq[qno];
ctrl = rxq->dpmaif_ctrl;
/* We need to make sure that the modem has been resumed before
* calling napi. This can't be done inside the polling function
* as we could be blocked waiting for device to be resumed,
* which can't be done from softirq context the poll function
* is running in.
*/
ret = pm_runtime_resume_and_get(ctrl->dev);
if (ret < 0 && ret != -EACCES) {
dev_err(ctrl->dev, "Failed to resume device: %d\n", ret);
return;
}
napi_schedule(&rxq->napi);
}

16 changes: 15 additions & 1 deletion drivers/net/wwan/t7xx/t7xx_netdev.c
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@
#include <linux/list.h>
#include <linux/netdev_features.h>
#include <linux/netdevice.h>
#include <linux/pm_runtime.h>
#include <linux/skbuff.h>
#include <linux/types.h>
#include <linux/wwan.h>
@@ -45,12 +46,25 @@

static void t7xx_ccmni_enable_napi(struct t7xx_ccmni_ctrl *ctlb)
{
int i;
struct dpmaif_ctrl *ctrl;
int i, ret;

ctrl = ctlb->hif_ctrl;

if (ctlb->is_napi_en)
return;

for (i = 0; i < RXQ_NUM; i++) {
/* The usage count has to be bumped every time before calling
* napi_schedule. It will be decresed in the poll routine,
* right after napi_complete_done is called.
*/
ret = pm_runtime_resume_and_get(ctrl->dev);
if (ret < 0) {
dev_err(ctrl->dev, "Failed to resume device: %d\n",
ret);
return;
}
napi_enable(ctlb->napi[i]);
napi_schedule(ctlb->napi[i]);
}
2 changes: 2 additions & 0 deletions drivers/net/wwan/t7xx/t7xx_pci.c
Original file line number Diff line number Diff line change
@@ -121,6 +121,8 @@ void t7xx_pci_pm_init_late(struct t7xx_pci_dev *t7xx_dev)
iowrite32(T7XX_L1_BIT(0), IREG_BASE(t7xx_dev) + ENABLE_ASPM_LOWPWR);
atomic_set(&t7xx_dev->md_pm_state, MTK_PM_RESUMED);

pm_runtime_mark_last_busy(&t7xx_dev->pdev->dev);
pm_runtime_allow(&t7xx_dev->pdev->dev);
pm_runtime_put_noidle(&t7xx_dev->pdev->dev);
}

0 comments on commit 906ad3c

Please sign in to comment.