From: Dolev Raviv <draviv@codeaurora.org>
To: James.Bottomley@HansenPartnership.com, hch@infradead.org
Cc: linux-scsi@vger.kernel.org, linux-scsi-owner@vger.kernel.org,
linux-arm-msm@vger.kernel.org, santoshsy@gmail.com,
Subhash Jadavani <subhashj@codeaurora.org>,
Dolev Raviv <draviv@codeaurora.org>,
Sujit Reddy Thumma <sthumma@codeaurora.org>
Subject: [PATCH/RFC V2 08/16] scsi: ufs: introduce well known logical unit in ufs
Date: Thu, 14 Aug 2014 16:30:59 +0300 [thread overview]
Message-ID: <1408023067-26103-9-git-send-email-draviv@codeaurora.org> (raw)
In-Reply-To: <1408023067-26103-1-git-send-email-draviv@codeaurora.org>
From: Subhash Jadavani <subhashj@codeaurora.org>
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 <subhashj@codeaurora.org>
Signed-off-by: Dolev Raviv <draviv@codeaurora.org>
Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org>
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index b0e1f62..bcc3a7f 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -49,9 +49,28 @@
#define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\
cpu_to_be32((byte3 << 24) | (byte2 << 16) |\
(byte1 << 8) | (byte0))
-
+/*
+ * UFS device may have standard LUs and LUN id could be from 0x00 to
+ * 0x7F. Standard LUs use "Peripheral Device Addressing Format".
+ * 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, device only use
+ * the "Extended Addressing Format" which means the W-LUNs would be
+ * from 0xc100 (SCSI_W_LUN_BASE) onwards.
+ * This means max. LUN number reported from UFS device could be 0xC17F.
+ */
+#define UFS_UPIU_MAX_UNIT_NUM_ID 0x7F
+#define UFS_MAX_LUNS (SCSI_W_LUN_BASE + UFS_UPIU_MAX_UNIT_NUM_ID)
+#define UFS_UPIU_WLUN_ID (1 << 7)
#define UFS_UPIU_MAX_GENERAL_LUN 8
+/* Well known logical unit id in LUN field of UPIU */
+enum {
+ UFS_UPIU_REPORT_LUNS_WLUN = 0x81,
+ UFS_UPIU_UFS_DEVICE_WLUN = 0xD0,
+ UFS_UPIU_BOOT_WLUN = 0xB0,
+ UFS_UPIU_RPMB_WLUN = 0xC4,
+};
+
/*
* UFS Protocol Information Unit related definitions
*/
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index a851323..876d210 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -100,7 +100,6 @@ static u32 ufs_query_desc_max_size[] = {
enum {
UFSHCD_MAX_CHANNEL = 0,
UFSHCD_MAX_ID = 1,
- UFSHCD_MAX_LUNS = 8,
UFSHCD_CMD_PER_LUN = 32,
UFSHCD_CAN_QUEUE = 32,
};
@@ -902,6 +901,21 @@ static int ufshcd_compose_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
}
/**
+ * ufshcd_scsi_to_upiu_lun - maps scsi LUN to UPIU LUN
+ * @scsi_lun: scsi LUN id
+ *
+ * Returns UPIU LUN id
+ */
+static inline u8 ufshcd_scsi_to_upiu_lun(unsigned int scsi_lun)
+{
+ if (scsi_is_wlun(scsi_lun))
+ return (scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID)
+ | UFS_UPIU_WLUN_ID;
+ else
+ return scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID;
+}
+
+/**
* ufshcd_queuecommand - main entry point for SCSI requests
* @cmd: command from SCSI Midlayer
* @done: call back function
@@ -959,7 +973,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
lrbp->sense_bufflen = SCSI_SENSE_BUFFERSIZE;
lrbp->sense_buffer = cmd->sense_buffer;
lrbp->task_tag = tag;
- lrbp->lun = cmd->device->lun;
+ lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun);
lrbp->intr_cmd = false;
lrbp->command_type = UTP_CMD_TYPE_SCSI;
@@ -1513,7 +1527,7 @@ static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba,
* Unit descriptors are only available for general purpose LUs (LUN id
* from 0 to 7) and RPMB Well known LU.
*/
- if (lun >= UFS_UPIU_MAX_GENERAL_LUN)
+ if (lun != UFS_UPIU_RPMB_WLUN && (lun >= UFS_UPIU_MAX_GENERAL_LUN))
return -EOPNOTSUPP;
return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun,
@@ -2144,6 +2158,44 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba)
}
/**
+ * ufshcd_set_queue_depth - set lun queue depth
+ * @sdev: pointer to SCSI device
+ *
+ * Read bLUQueueDepth value and activate scsi tagged command
+ * queueing. For WLUN, queue depth is set to 1. For best-effort
+ * cases (bLUQueueDepth = 0) the queue depth is set to a maximum
+ * value that host can queue.
+ */
+static void ufshcd_set_queue_depth(struct scsi_device *sdev)
+{
+ int ret = 0;
+ u8 lun_qdepth;
+ struct ufs_hba *hba;
+
+ hba = shost_priv(sdev->host);
+
+ lun_qdepth = hba->nutrs;
+ ret = ufshcd_read_unit_desc_param(hba,
+ ufshcd_scsi_to_upiu_lun(sdev->lun),
+ UNIT_DESC_PARAM_LU_Q_DEPTH,
+ &lun_qdepth,
+ sizeof(lun_qdepth));
+
+ /* Some WLUN doesn't support unit descriptor */
+ if (ret == -EOPNOTSUPP)
+ lun_qdepth = 1;
+ else if (!lun_qdepth)
+ /* eventually, we can figure out the real queue depth */
+ lun_qdepth = hba->nutrs;
+ else
+ lun_qdepth = min_t(int, lun_qdepth, hba->nutrs);
+
+ dev_dbg(hba->dev, "%s: activate tcq with queue depth %d\n",
+ __func__, lun_qdepth);
+ scsi_activate_tcq(sdev, lun_qdepth);
+}
+
+/**
* ufshcd_slave_alloc - handle initial SCSI device configurations
* @sdev: pointer to SCSI device
*
@@ -2152,8 +2204,6 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba)
static int ufshcd_slave_alloc(struct scsi_device *sdev)
{
struct ufs_hba *hba;
- u8 lun_qdepth;
- int ret;
hba = shost_priv(sdev->host);
sdev->tagged_supported = 1;
@@ -2168,20 +2218,8 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev)
/* REPORT SUPPORTED OPERATION CODES is not supported */
sdev->no_report_opcodes = 1;
- ret = ufshcd_read_unit_desc_param(hba,
- sdev->lun,
- UNIT_DESC_PARAM_LU_Q_DEPTH,
- &lun_qdepth,
- sizeof(lun_qdepth));
- if (!ret || !lun_qdepth)
- /* eventually, we can figure out the real queue depth */
- lun_qdepth = hba->nutrs;
- else
- lun_qdepth = min_t(int, lun_qdepth, hba->nutrs);
- dev_dbg(hba->dev, "%s: activate tcq with queue depth %d\n",
- __func__, lun_qdepth);
- scsi_activate_tcq(sdev, lun_qdepth);
+ ufshcd_set_queue_depth(sdev);
return 0;
}
@@ -2244,6 +2282,9 @@ static void ufshcd_slave_destroy(struct scsi_device *sdev)
hba = shost_priv(sdev->host);
scsi_deactivate_tcq(sdev, hba->nutrs);
+ /* Drop the reference as it won't be needed anymore */
+ if (ufshcd_scsi_to_upiu_lun(sdev->lun) == UFS_UPIU_UFS_DEVICE_WLUN)
+ hba->sdev_ufs_device = NULL;
}
/**
@@ -2961,7 +3002,10 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
lun_id, task_tag);
task_req_upiup->header.dword_1 =
UPIU_HEADER_DWORD(0, tm_function, 0, 0);
-
+ /*
+ * The host shall provide the same value for LUN field in the basic
+ * header and for Input Parameter.
+ */
task_req_upiup->input_param1 = cpu_to_be32(lun_id);
task_req_upiup->input_param2 = cpu_to_be32(task_id);
@@ -3980,10 +4024,11 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
host->can_queue = hba->nutrs;
host->cmd_per_lun = hba->nutrs;
host->max_id = UFSHCD_MAX_ID;
- host->max_lun = UFSHCD_MAX_LUNS;
+ host->max_lun = UFS_MAX_LUNS;
host->max_channel = UFSHCD_MAX_CHANNEL;
host->unique_id = host->host_no;
host->max_cmd_len = MAX_CDB_SIZE;
+ host->report_wlus = 1;
/* Initailize wait queue for task management */
init_waitqueue_head(&hba->tm_wq);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 8365ad4..9b5f77f 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -124,7 +124,7 @@ struct ufshcd_lrb {
int command_type;
int task_tag;
- unsigned int lun;
+ u8 lun; /* UPIU LUN id field is only 8-bit wide */
bool intr_cmd;
};
@@ -266,6 +266,11 @@ struct ufs_hba {
struct Scsi_Host *host;
struct device *dev;
+ /*
+ * This field is to keep a reference to "scsi_device" corresponding to
+ * "UFS device" W-LU.
+ */
+ struct scsi_device *sdev_ufs_device;
struct ufshcd_lrb *lrb;
unsigned long lrb_in_use;
--
1.8.5.2
--
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation
next prev parent reply other threads:[~2014-08-14 13:31 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-14 13:30 [PATCH/RFC V2 00/16] UFS: Power managment support Dolev Raviv
2014-08-14 13:30 ` [PATCH/RFC V2 01/16] scsi: ufs: Allow vendor specific initialization Dolev Raviv
2014-08-14 13:30 ` [PATCH/RFC V2 02/16] scsi: ufs: Add regulator enable support Dolev Raviv
2014-08-14 13:30 ` [PATCH/RFC V2 03/16] scsi: ufs: Add clock initialization support Dolev Raviv
2014-08-14 13:30 ` [PATCH/RFC V2 04/16] scsi: ufs: refactor query descriptor API support Dolev Raviv
2014-08-14 13:30 ` [PATCH/RFC V2 05/16] scsi: ufs: improve init sequence Dolev Raviv
2014-08-14 13:30 ` [PATCH/RFC V2 06/16] scsi: ufs: Active Power Mode - configuring bActiveICCLevel Dolev Raviv
2014-08-14 13:30 ` [PATCH/RFC V2 07/16] scsi: support well known logical units Dolev Raviv
2014-08-19 17:22 ` Christoph Hellwig
2014-08-21 21:18 ` Martin K. Petersen
2014-08-14 13:30 ` Dolev Raviv [this message]
2014-08-14 13:31 ` [PATCH/RFC V2 09/16] scsi: sd: Avoid sending medium write commands if device is write protected Dolev Raviv
2014-08-14 13:31 ` [PATCH/RFC V2 10/16] scsi: ufs: add UFS power management support Dolev Raviv
2014-08-20 7:20 ` Dong, Chuanxiao
2014-08-21 8:59 ` Dong, Chuanxiao
2014-08-21 13:01 ` hch
2014-09-03 13:04 ` Dolev Raviv
2014-09-03 11:43 ` Dolev Raviv
2014-08-14 13:31 ` [PATCH/RFC V2 11/16] scsi: ufs: refactor configuring power mode Dolev Raviv
2014-08-14 13:31 ` [PATCH/RFC V2 12/16] scsi: ufs: Add support for clock gating Dolev Raviv
2014-08-14 13:31 ` [PATCH/RFC V2 13/16] scsi: ufs: Add freq-table-hz property for UFS device Dolev Raviv
2014-08-14 13:31 ` [PATCH/RFC V2 14/16] scsi: ufs: Add support for clock scaling using devfreq framework Dolev Raviv
2014-08-14 13:31 ` [PATCH/RFC V2 15/16] scsi: ufs: add capability to control the auto bkops during suspend Dolev Raviv
2014-08-14 13:31 ` [PATCH/RFC V2 16/16] scsi: ufs: definitions for phy interface Dolev Raviv
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=1408023067-26103-9-git-send-email-draviv@codeaurora.org \
--to=draviv@codeaurora.org \
--cc=James.Bottomley@HansenPartnership.com \
--cc=hch@infradead.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-scsi-owner@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=santoshsy@gmail.com \
--cc=sthumma@codeaurora.org \
--cc=subhashj@codeaurora.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;
as well as URLs for NNTP newsgroup(s).