public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
From: James Bottomley <James.Bottomley@HansenPartnership.com>
To: Thomas Gleixner <tglx@linutronix.de>,
	LKML <linux-kernel@vger.kernel.org>
Cc: Marc Zyngier <maz@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	 Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>,
	"Martin K. Petersen" <martin.petersen@oracle.com>,
	 linux-scsi@vger.kernel.org,
	Jonathan Cameron <Jonathan.Cameron@huawei.com>,
	 Nishanth Menon <nm@ti.com>, Dhruva Gole <d-gole@ti.com>,
	Tero Kristo <kristo@kernel.org>,
	 Santosh Shilimkar <ssantosh@kernel.org>,
	Logan Gunthorpe <logang@deltatee.com>,
	Dave Jiang <dave.jiang@intel.com>,  Jon Mason <jdmason@kudzu.us>,
	Allen Hubbe <allenbh@gmail.com>,
	ntb@lists.linux.dev, Bjorn Helgaas <bhelgaas@google.com>,
	linux-pci@vger.kernel.org, Michael Kelley <mhklinux@outlook.com>,
	Wei Liu <wei.liu@kernel.org>,
	Haiyang Zhang <haiyangz@microsoft.com>,
	linux-hyperv@vger.kernel.org, Wei Huang <wei.huang2@amd.com>,
	Jonathan Cameron <Jonathan.Cameron@huawei.com>
Subject: Re: [patch V3 09/10] scsi: ufs: qcom: Remove the MSI descriptor abuse
Date: Mon, 17 Mar 2025 12:26:29 -0400	[thread overview]
Message-ID: <609eeb873fdef6171c71f3beda289d799cb7172c.camel@HansenPartnership.com> (raw)
In-Reply-To: <20250317092946.265146293@linutronix.de>

On Mon, 2025-03-17 at 14:29 +0100, Thomas Gleixner wrote:
> The driver abuses the MSI descriptors for internal purposes. Aside of
> core code and MSI providers nothing has to care about their
> existence. They have been encapsulated with a lot of effort because
> this kind of abuse caused all sorts of issues including a
> maintainability nightmare.
> 
> Rewrite the code so it uses dedicated storage to hand the required
> information to the interrupt handler.
> 
> No functional change intended.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
> Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
> Cc: "Martin K. Petersen" <martin.petersen@oracle.com>
> Cc: linux-scsi@vger.kernel.org
> 
> 
> ---
>  drivers/ufs/host/ufs-qcom.c |   77 ++++++++++++++++++++++-----------
> -----------
>  1 file changed, 40 insertions(+), 37 deletions(-)
> 
> --- a/drivers/ufs/host/ufs-qcom.c
> +++ b/drivers/ufs/host/ufs-qcom.c
> @@ -1782,15 +1782,19 @@ static void ufs_qcom_write_msi_msg(struc
>  	ufshcd_mcq_config_esi(hba, msg);
>  }
>  
> +struct ufs_qcom_irq {
> +	unsigned int		irq;
> +	unsigned int		idx;
> +	struct ufs_hba		*hba;
> +};
> +
>  static irqreturn_t ufs_qcom_mcq_esi_handler(int irq, void *data)
>  {
> -	struct msi_desc *desc = data;
> -	struct device *dev = msi_desc_to_dev(desc);
> -	struct ufs_hba *hba = dev_get_drvdata(dev);
> -	u32 id = desc->msi_index;
> -	struct ufs_hw_queue *hwq = &hba->uhq[id];
> +	struct ufs_qcom_irq *qi = data;
> +	struct ufs_hba *hba = qi->hba;
> +	struct ufs_hw_queue *hwq = &hba->uhq[qi->idx];
>  
> -	ufshcd_mcq_write_cqis(hba, 0x1, id);
> +	ufshcd_mcq_write_cqis(hba, 0x1, qi->idx);
>  	ufshcd_mcq_poll_cqe_lock(hba, hwq);
>  
>  	return IRQ_HANDLED;
> @@ -1799,8 +1803,7 @@ static irqreturn_t ufs_qcom_mcq_esi_hand
>  static int ufs_qcom_config_esi(struct ufs_hba *hba)
>  {
>  	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
> -	struct msi_desc *desc;
> -	struct msi_desc *failed_desc = NULL;
> +	struct ufs_qcom_irq *qi;
>  	int nr_irqs, ret;
>  
>  	if (host->esi_enabled)
> @@ -1811,47 +1814,47 @@ static int ufs_qcom_config_esi(struct uf
>  	 * 2. Poll queues do not need ESI.
>  	 */
>  	nr_irqs = hba->nr_hw_queues - hba-
> >nr_queues[HCTX_TYPE_POLL];
> +	qi = devm_kcalloc(hba->dev, nr_irqs, sizeof(*qi),
> GFP_KERNEL);
> +	if (qi)

Typo causing logic inversion: should be !qi here (you need a more
responsive ! key).

> +		return -ENOMEM;
> +
>  	ret = platform_device_msi_init_and_alloc_irqs(hba->dev,
> nr_irqs,
>  						     
> ufs_qcom_write_msi_msg);
>  	if (ret) {
>  		dev_err(hba->dev, "Failed to request Platform MSI
> %d\n", ret);
> -		return ret;
> +		goto cleanup;
>  	}
>  
> -	msi_lock_descs(hba->dev);
> -	msi_for_each_desc(desc, hba->dev, MSI_DESC_ALL) {
> -		ret = devm_request_irq(hba->dev, desc->irq,
> -				       ufs_qcom_mcq_esi_handler,
> -				       IRQF_SHARED, "qcom-mcq-esi",
> desc);
> +	for (int idx = 0; idx < nr_irqs; idx++) {
> +		qi[idx].irq = msi_get_virq(hba->dev, idx);
> +		qi[idx].idx = idx;
> +		qi[idx].hba = hba;
> +
> +		ret = devm_request_irq(hba->dev, qi[idx].irq,
> ufs_qcom_mcq_esi_handler,
> +				       IRQF_SHARED, "qcom-mcq-esi",
> qi + idx);
>  		if (ret) {
>  			dev_err(hba->dev, "%s: Fail to request IRQ
> for %d, err = %d\n",
> -				__func__, desc->irq, ret);
> -			failed_desc = desc;
> -			break;
> +				__func__, qi[idx].irq, ret);
> +			qi[idx].irq = 0;
> +			goto cleanup;
>  		}
>  	}
> -	msi_unlock_descs(hba->dev);
>  
> -	if (ret) {
> -		/* Rewind */
> -		msi_lock_descs(hba->dev);
> -		msi_for_each_desc(desc, hba->dev, MSI_DESC_ALL) {
> -			if (desc == failed_desc)
> -				break;
> -			devm_free_irq(hba->dev, desc->irq, hba);
> -		}
> -		msi_unlock_descs(hba->dev);
> -		platform_device_msi_free_irqs_all(hba->dev);
> -	} else {
> -		if (host->hw_ver.major == 6 && host->hw_ver.minor ==
> 0 &&
> -		    host->hw_ver.step == 0)
> -			ufshcd_rmwl(hba, ESI_VEC_MASK,
> -				    FIELD_PREP(ESI_VEC_MASK,
> MAX_ESI_VEC - 1),
> -				    REG_UFS_CFG3);
> -		ufshcd_mcq_enable_esi(hba);
> -		host->esi_enabled = true;
> +	if (host->hw_ver.major == 6 && host->hw_ver.minor == 0 &&
> +	    host->hw_ver.step == 0) {
> +		ufshcd_rmwl(hba, ESI_VEC_MASK,
> +			    FIELD_PREP(ESI_VEC_MASK, MAX_ESI_VEC -
> 1),
> +			    REG_UFS_CFG3);
>  	}
> -
> +	ufshcd_mcq_enable_esi(hba);
> +	host->esi_enabled = true;
> +	return 0;
> +
> +cleanup:
> +	for (int idx = 0; qi[idx].irq; idx++)
> +		devm_free_irq(hba->dev, qi[idx].irq, hba);
> +	platform_device_msi_free_irqs_all(hba->dev);
> +	devm_kfree(hba->dev, qi);
>  	return ret;
>  }

This does seem to be exactly the pattern you describe in 1/10, although
I'm not entirely convinced that something like the below is more
readable and safe.

Regards,

James

---

diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index 23b9f6efa047..26b0c665c3b7 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -1782,25 +1782,37 @@ static void ufs_qcom_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
 	ufshcd_mcq_config_esi(hba, msg);
 }
 
+struct ufs_qcom_irq {
+	unsigned int		irq;
+	unsigned int		idx;
+	struct ufs_hba		*hba;
+};
+
 static irqreturn_t ufs_qcom_mcq_esi_handler(int irq, void *data)
 {
-	struct msi_desc *desc = data;
-	struct device *dev = msi_desc_to_dev(desc);
-	struct ufs_hba *hba = dev_get_drvdata(dev);
-	u32 id = desc->msi_index;
-	struct ufs_hw_queue *hwq = &hba->uhq[id];
+	struct ufs_qcom_irq *qi = data;
+	struct ufs_hba *hba = qi->hba;
+	struct ufs_hw_queue *hwq = &hba->uhq[qi->idx];
 
-	ufshcd_mcq_write_cqis(hba, 0x1, id);
+	ufshcd_mcq_write_cqis(hba, 0x1, qi->idx);
 	ufshcd_mcq_poll_cqe_lock(hba, hwq);
 
 	return IRQ_HANDLED;
 }
 
+DEFINE_FREE(ufs_qcom_irq, struct ufs_qcom_irq *,
+	    if (_T) {							\
+		    for (int idx = 0; _T[idx].irq; idx++)		\
+			    devm_free_irq(_T[idx].hba->dev, _T[idx].irq, \
+					  _T[idx].hba);			\
+		    platform_device_msi_free_irqs_all(_T[0].hba->dev);	\
+		    devm_kfree(_T[0].hba->dev, _T);			\
+	    })
+
 static int ufs_qcom_config_esi(struct ufs_hba *hba)
 {
 	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
-	struct msi_desc *desc;
-	struct msi_desc *failed_desc = NULL;
+	struct ufs_qcom_irq *qi __free(ufs_qcom_irq);
 	int nr_irqs, ret;
 
 	if (host->esi_enabled)
@@ -1811,6 +1823,11 @@ static int ufs_qcom_config_esi(struct ufs_hba *hba)
 	 * 2. Poll queues do not need ESI.
 	 */
 	nr_irqs = hba->nr_hw_queues - hba->nr_queues[HCTX_TYPE_POLL];
+	qi = devm_kcalloc(hba->dev, nr_irqs, sizeof(*qi), GFP_KERNEL);
+	if (!qi)
+		return -ENOMEM;
+	qi[0].hba = hba;	/* required by __free() */
+
 	ret = platform_device_msi_init_and_alloc_irqs(hba->dev, nr_irqs,
 						      ufs_qcom_write_msi_msg);
 	if (ret) {
@@ -1818,41 +1835,31 @@ static int ufs_qcom_config_esi(struct ufs_hba *hba)
 		return ret;
 	}
 
-	msi_lock_descs(hba->dev);
-	msi_for_each_desc(desc, hba->dev, MSI_DESC_ALL) {
-		ret = devm_request_irq(hba->dev, desc->irq,
-				       ufs_qcom_mcq_esi_handler,
-				       IRQF_SHARED, "qcom-mcq-esi", desc);
+	for (int idx = 0; idx < nr_irqs; idx++) {
+		qi[idx].irq = msi_get_virq(hba->dev, idx);
+		qi[idx].idx = idx;
+		qi[idx].hba = hba;
+
+		ret = devm_request_irq(hba->dev, qi[idx].irq, ufs_qcom_mcq_esi_handler,
+				       IRQF_SHARED, "qcom-mcq-esi", qi + idx);
 		if (ret) {
 			dev_err(hba->dev, "%s: Fail to request IRQ for %d, err = %d\n",
-				__func__, desc->irq, ret);
-			failed_desc = desc;
-			break;
+				__func__, qi[idx].irq, ret);
+			qi[idx].irq = 0;
+			return ret;
 		}
 	}
-	msi_unlock_descs(hba->dev);
+	retain_ptr(qi);
 
-	if (ret) {
-		/* Rewind */
-		msi_lock_descs(hba->dev);
-		msi_for_each_desc(desc, hba->dev, MSI_DESC_ALL) {
-			if (desc == failed_desc)
-				break;
-			devm_free_irq(hba->dev, desc->irq, hba);
-		}
-		msi_unlock_descs(hba->dev);
-		platform_device_msi_free_irqs_all(hba->dev);
-	} else {
-		if (host->hw_ver.major == 6 && host->hw_ver.minor == 0 &&
-		    host->hw_ver.step == 0)
-			ufshcd_rmwl(hba, ESI_VEC_MASK,
-				    FIELD_PREP(ESI_VEC_MASK, MAX_ESI_VEC - 1),
-				    REG_UFS_CFG3);
-		ufshcd_mcq_enable_esi(hba);
-		host->esi_enabled = true;
+	if (host->hw_ver.major == 6 && host->hw_ver.minor == 0 &&
+	    host->hw_ver.step == 0) {
+		ufshcd_rmwl(hba, ESI_VEC_MASK,
+			    FIELD_PREP(ESI_VEC_MASK, MAX_ESI_VEC - 1),
+			    REG_UFS_CFG3);
 	}
-
-	return ret;
+	ufshcd_mcq_enable_esi(hba);
+	host->esi_enabled = true;
+	return 0;
 }
 
 /*


  reply	other threads:[~2025-03-17 16:26 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-17 13:29 [patch V3 00/10] genirq/msi: Spring cleaning Thomas Gleixner
2025-03-17 13:29 ` [patch V3 01/10] cleanup: Provide retain_ptr() Thomas Gleixner
2025-03-17 13:57   ` James Bottomley
2025-03-18  8:37     ` Thomas Gleixner
2025-03-17 13:29 ` [patch V3 02/10] genirq/msi: Use lock guards for MSI descriptor locking Thomas Gleixner
2025-03-17 13:29 ` [patch V3 03/10] soc: ti: ti_sci_inta_msi: Switch MSI descriptor locking to guard() Thomas Gleixner
2025-03-17 13:29 ` [patch V3 04/10] NTB/msi: Switch MSI descriptor locking to lock guard() Thomas Gleixner
2025-03-17 13:29 ` [patch V3 05/10] PCI/MSI: Switch to MSI descriptor locking to guard() Thomas Gleixner
2025-03-18 20:24   ` Bjorn Helgaas
2025-03-17 13:29 ` [patch V3 06/10] PCI: hv: Switch " Thomas Gleixner
2025-03-17 13:29 ` [patch V3 07/10] PCI/MSI: Provide a sane mechanism for TPH Thomas Gleixner
2025-03-17 13:29 ` [patch V3 08/10] PCI/TPH: Replace the broken MSI-X control word update Thomas Gleixner
2025-03-17 13:29 ` [patch V3 09/10] scsi: ufs: qcom: Remove the MSI descriptor abuse Thomas Gleixner
2025-03-17 16:26   ` James Bottomley [this message]
2025-03-18  8:40     ` Thomas Gleixner
2025-03-17 13:29 ` [patch V3 10/10] genirq/msi: Rename msi_[un]lock_descs() Thomas Gleixner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=609eeb873fdef6171c71f3beda289d799cb7172c.camel@HansenPartnership.com \
    --to=james.bottomley@hansenpartnership.com \
    --cc=Jonathan.Cameron@huawei.com \
    --cc=allenbh@gmail.com \
    --cc=bhelgaas@google.com \
    --cc=d-gole@ti.com \
    --cc=dave.jiang@intel.com \
    --cc=haiyangz@microsoft.com \
    --cc=jdmason@kudzu.us \
    --cc=kristo@kernel.org \
    --cc=linux-hyperv@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=logang@deltatee.com \
    --cc=manivannan.sadhasivam@linaro.org \
    --cc=martin.petersen@oracle.com \
    --cc=maz@kernel.org \
    --cc=mhklinux@outlook.com \
    --cc=nm@ti.com \
    --cc=ntb@lists.linux.dev \
    --cc=peterz@infradead.org \
    --cc=ssantosh@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=wei.huang2@amd.com \
    --cc=wei.liu@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox