]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
scsi: ufs: core: Check LSDBS cap when !mcq
authorKyoungrul Kim <k831.kim@samsung.com>
Tue, 9 Jul 2024 23:25:20 +0000 (08:25 +0900)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 16 Jul 2024 02:51:06 +0000 (22:51 -0400)
If the user sets use_mcq_mode to 0, the host will try to activate the LSDB
mode unconditionally even when the LSDBS of device HCI cap is 1. This makes
commands time out and causes device probing to fail.

To prevent that problem, check the LSDBS cap when MCQ is not supported.

Signed-off-by: Kyoungrul Kim <k831.kim@samsung.com>
Link: https://lore.kernel.org/r/20240709232520epcms2p8ebdb5c4fccc30a6221390566589bf122@epcms2p8
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/ufs/core/ufshcd.c
include/ufs/ufshcd.h
include/ufs/ufshci.h

index bea00e069e9a0f80d849970a2a11909ca56ad258..480be64acf2474ec3a0a7cd538cc583692526341 100644 (file)
@@ -2416,7 +2416,17 @@ static inline int ufshcd_hba_capabilities(struct ufs_hba *hba)
                return err;
        }
 
+       /*
+        * The UFSHCI 3.0 specification does not define MCQ_SUPPORT and
+        * LSDB_SUPPORT, but [31:29] as reserved bits with reset value 0s, which
+        * means we can simply read values regardless of version.
+        */
        hba->mcq_sup = FIELD_GET(MASK_MCQ_SUPPORT, hba->capabilities);
+       /*
+        * 0h: legacy single doorbell support is available
+        * 1h: indicate that legacy single doorbell support has been removed
+        */
+       hba->lsdb_sup = !FIELD_GET(MASK_LSDB_SUPPORT, hba->capabilities);
        if (!hba->mcq_sup)
                return 0;
 
@@ -10494,6 +10504,12 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
        }
 
        if (!is_mcq_supported(hba)) {
+               if (!hba->lsdb_sup) {
+                       dev_err(hba->dev, "%s: failed to initialize (legacy doorbell mode not supported)\n",
+                               __func__);
+                       err = -EINVAL;
+                       goto out_disable;
+               }
                err = scsi_add_host(host, hba->dev);
                if (err) {
                        dev_err(hba->dev, "scsi_add_host failed\n");
index a43b14276bc33dd5ca04dc94249578a3177a9b6f..cac0cdb9a916c733f6dd8f6622b3c57bccd3abe3 100644 (file)
@@ -1109,6 +1109,7 @@ struct ufs_hba {
        bool ext_iid_sup;
        bool scsi_host_added;
        bool mcq_sup;
+       bool lsdb_sup;
        bool mcq_enabled;
        struct ufshcd_res_info res[RES_MAX];
        void __iomem *mcq_base;
index 38fe97971a65facdd67a62cfa32fbf48f8a7dbd7..9917c7743d808c49a67a5008793a44273862f176 100644 (file)
@@ -77,6 +77,7 @@ enum {
        MASK_OUT_OF_ORDER_DATA_DELIVERY_SUPPORT = 0x02000000,
        MASK_UIC_DME_TEST_MODE_SUPPORT          = 0x04000000,
        MASK_CRYPTO_SUPPORT                     = 0x10000000,
+       MASK_LSDB_SUPPORT                       = 0x20000000,
        MASK_MCQ_SUPPORT                        = 0x40000000,
 };