Commit 906ad3c9 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 't7xx-pm-fixes'



Kornel Dulęba says:

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

d10b3a69 ("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: default avatarDavid S. Miller <davem@davemloft.net>
parents 60bd1d90 e3d6d152
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -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);
+20 −9
Original line number Diff line number Diff line
@@ -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,14 +875,13 @@ 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);
	} 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);
		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);
	}

	return work_done;
}
@@ -891,7 +889,8 @@ int t7xx_dpmaif_napi_rx_poll(struct napi_struct *napi, const int budget)
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);
}

+15 −1
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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);
}