Skip to content

Commit 0ce147d

Browse files
Subhash JadavaniChristoph Hellwig
authored andcommitted
ufs: introduce well known logical unit in ufs
UFS device may have standard LUs and LUN id could be from 0x00 to 0x7F. UFS device specification use "Peripheral Device Addressing Format" (SCSI SAM-5) for standard LUs. UFS device may also have the Well Known LUs (also referred as W-LU) which again could be from 0x00 to 0x7F. For W-LUs, UFS device specification only allows the "Extended Addressing Format" (SCSI SAM-5) which means the W-LUNs would start from 0xC100 onwards. This means max. LUN number reported from UFS device could be 0xC17F hence this patch advertise the "max_lun" as 0xC17F which will allow SCSI mid layer to detect the W-LUs as well. But once the W-LUs are detected, UFSHCD driver may get the commands with SCSI LUN id upto 0xC17F but UPIU LUN id field is only 8-bit wide so it requires the mapping of SCSI LUN id to UPIU LUN id. This patch also add support for this mapping. Signed-off-by: Subhash Jadavani <[email protected]> Signed-off-by: Dolev Raviv <[email protected]> Signed-off-by: Sujit Reddy Thumma <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]>
1 parent 2a8fa60 commit 0ce147d

File tree

3 files changed

+85
-22
lines changed

3 files changed

+85
-22
lines changed

drivers/scsi/ufs/ufs.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,28 @@
4949
#define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\
5050
cpu_to_be32((byte3 << 24) | (byte2 << 16) |\
5151
(byte1 << 8) | (byte0))
52-
52+
/*
53+
* UFS device may have standard LUs and LUN id could be from 0x00 to
54+
* 0x7F. Standard LUs use "Peripheral Device Addressing Format".
55+
* UFS device may also have the Well Known LUs (also referred as W-LU)
56+
* which again could be from 0x00 to 0x7F. For W-LUs, device only use
57+
* the "Extended Addressing Format" which means the W-LUNs would be
58+
* from 0xc100 (SCSI_W_LUN_BASE) onwards.
59+
* This means max. LUN number reported from UFS device could be 0xC17F.
60+
*/
61+
#define UFS_UPIU_MAX_UNIT_NUM_ID 0x7F
62+
#define UFS_MAX_LUNS (SCSI_W_LUN_BASE + UFS_UPIU_MAX_UNIT_NUM_ID)
63+
#define UFS_UPIU_WLUN_ID (1 << 7)
5364
#define UFS_UPIU_MAX_GENERAL_LUN 8
5465

66+
/* Well known logical unit id in LUN field of UPIU */
67+
enum {
68+
UFS_UPIU_REPORT_LUNS_WLUN = 0x81,
69+
UFS_UPIU_UFS_DEVICE_WLUN = 0xD0,
70+
UFS_UPIU_BOOT_WLUN = 0xB0,
71+
UFS_UPIU_RPMB_WLUN = 0xC4,
72+
};
73+
5574
/*
5675
* UFS Protocol Information Unit related definitions
5776
*/

drivers/scsi/ufs/ufshcd.c

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ static u32 ufs_query_desc_max_size[] = {
100100
enum {
101101
UFSHCD_MAX_CHANNEL = 0,
102102
UFSHCD_MAX_ID = 1,
103-
UFSHCD_MAX_LUNS = 8,
104103
UFSHCD_CMD_PER_LUN = 32,
105104
UFSHCD_CAN_QUEUE = 32,
106105
};
@@ -901,6 +900,21 @@ static int ufshcd_compose_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
901900
return ret;
902901
}
903902

903+
/*
904+
* ufshcd_scsi_to_upiu_lun - maps scsi LUN to UPIU LUN
905+
* @scsi_lun: scsi LUN id
906+
*
907+
* Returns UPIU LUN id
908+
*/
909+
static inline u8 ufshcd_scsi_to_upiu_lun(unsigned int scsi_lun)
910+
{
911+
if (scsi_is_wlun(scsi_lun))
912+
return (scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID)
913+
| UFS_UPIU_WLUN_ID;
914+
else
915+
return scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID;
916+
}
917+
904918
/**
905919
* ufshcd_upiu_wlun_to_scsi_wlun - maps UPIU W-LUN id to SCSI W-LUN ID
906920
* @scsi_lun: UPIU W-LUN id
@@ -970,7 +984,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
970984
lrbp->sense_bufflen = SCSI_SENSE_BUFFERSIZE;
971985
lrbp->sense_buffer = cmd->sense_buffer;
972986
lrbp->task_tag = tag;
973-
lrbp->lun = cmd->device->lun;
987+
lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun);
974988
lrbp->intr_cmd = false;
975989
lrbp->command_type = UTP_CMD_TYPE_SCSI;
976990

@@ -1524,7 +1538,7 @@ static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba,
15241538
* Unit descriptors are only available for general purpose LUs (LUN id
15251539
* from 0 to 7) and RPMB Well known LU.
15261540
*/
1527-
if (lun >= UFS_UPIU_MAX_GENERAL_LUN)
1541+
if (lun != UFS_UPIU_RPMB_WLUN && (lun >= UFS_UPIU_MAX_GENERAL_LUN))
15281542
return -EOPNOTSUPP;
15291543

15301544
return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun,
@@ -2154,6 +2168,44 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba)
21542168
return err;
21552169
}
21562170

2171+
/**
2172+
* ufshcd_set_queue_depth - set lun queue depth
2173+
* @sdev: pointer to SCSI device
2174+
*
2175+
* Read bLUQueueDepth value and activate scsi tagged command
2176+
* queueing. For WLUN, queue depth is set to 1. For best-effort
2177+
* cases (bLUQueueDepth = 0) the queue depth is set to a maximum
2178+
* value that host can queue.
2179+
*/
2180+
static void ufshcd_set_queue_depth(struct scsi_device *sdev)
2181+
{
2182+
int ret = 0;
2183+
u8 lun_qdepth;
2184+
struct ufs_hba *hba;
2185+
2186+
hba = shost_priv(sdev->host);
2187+
2188+
lun_qdepth = hba->nutrs;
2189+
ret = ufshcd_read_unit_desc_param(hba,
2190+
ufshcd_scsi_to_upiu_lun(sdev->lun),
2191+
UNIT_DESC_PARAM_LU_Q_DEPTH,
2192+
&lun_qdepth,
2193+
sizeof(lun_qdepth));
2194+
2195+
/* Some WLUN doesn't support unit descriptor */
2196+
if (ret == -EOPNOTSUPP)
2197+
lun_qdepth = 1;
2198+
else if (!lun_qdepth)
2199+
/* eventually, we can figure out the real queue depth */
2200+
lun_qdepth = hba->nutrs;
2201+
else
2202+
lun_qdepth = min_t(int, lun_qdepth, hba->nutrs);
2203+
2204+
dev_dbg(hba->dev, "%s: activate tcq with queue depth %d\n",
2205+
__func__, lun_qdepth);
2206+
scsi_activate_tcq(sdev, lun_qdepth);
2207+
}
2208+
21572209
/**
21582210
* ufshcd_slave_alloc - handle initial SCSI device configurations
21592211
* @sdev: pointer to SCSI device
@@ -2163,8 +2215,6 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba)
21632215
static int ufshcd_slave_alloc(struct scsi_device *sdev)
21642216
{
21652217
struct ufs_hba *hba;
2166-
u8 lun_qdepth;
2167-
int ret;
21682218

21692219
hba = shost_priv(sdev->host);
21702220
sdev->tagged_supported = 1;
@@ -2179,20 +2229,8 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev)
21792229
/* REPORT SUPPORTED OPERATION CODES is not supported */
21802230
sdev->no_report_opcodes = 1;
21812231

2182-
ret = ufshcd_read_unit_desc_param(hba,
2183-
sdev->lun,
2184-
UNIT_DESC_PARAM_LU_Q_DEPTH,
2185-
&lun_qdepth,
2186-
sizeof(lun_qdepth));
2187-
if (!ret || !lun_qdepth)
2188-
/* eventually, we can figure out the real queue depth */
2189-
lun_qdepth = hba->nutrs;
2190-
else
2191-
lun_qdepth = min_t(int, lun_qdepth, hba->nutrs);
21922232

2193-
dev_dbg(hba->dev, "%s: activate tcq with queue depth %d\n",
2194-
__func__, lun_qdepth);
2195-
scsi_activate_tcq(sdev, lun_qdepth);
2233+
ufshcd_set_queue_depth(sdev);
21962234

21972235
return 0;
21982236
}
@@ -2255,6 +2293,9 @@ static void ufshcd_slave_destroy(struct scsi_device *sdev)
22552293

22562294
hba = shost_priv(sdev->host);
22572295
scsi_deactivate_tcq(sdev, hba->nutrs);
2296+
/* Drop the reference as it won't be needed anymore */
2297+
if (ufshcd_scsi_to_upiu_lun(sdev->lun) == UFS_UPIU_UFS_DEVICE_WLUN)
2298+
hba->sdev_ufs_device = NULL;
22582299
}
22592300

22602301
/**
@@ -2972,7 +3013,10 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
29723013
lun_id, task_tag);
29733014
task_req_upiup->header.dword_1 =
29743015
UPIU_HEADER_DWORD(0, tm_function, 0, 0);
2975-
3016+
/*
3017+
* The host shall provide the same value for LUN field in the basic
3018+
* header and for Input Parameter.
3019+
*/
29763020
task_req_upiup->input_param1 = cpu_to_be32(lun_id);
29773021
task_req_upiup->input_param2 = cpu_to_be32(task_id);
29783022

@@ -4121,7 +4165,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
41214165
host->can_queue = hba->nutrs;
41224166
host->cmd_per_lun = hba->nutrs;
41234167
host->max_id = UFSHCD_MAX_ID;
4124-
host->max_lun = UFSHCD_MAX_LUNS;
4168+
host->max_lun = UFS_MAX_LUNS;
41254169
host->max_channel = UFSHCD_MAX_CHANNEL;
41264170
host->unique_id = host->host_no;
41274171
host->max_cmd_len = MAX_CDB_SIZE;

drivers/scsi/ufs/ufshcd.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ struct ufshcd_lrb {
124124

125125
int command_type;
126126
int task_tag;
127-
unsigned int lun;
127+
u8 lun; /* UPIU LUN id field is only 8-bit wide */
128128
bool intr_cmd;
129129
};
130130

0 commit comments

Comments
 (0)