Skip to contentSkip to conversation

scsi: ufs: add support for query requests

PATCH Superseded Dolev Raviv 1 participant 1 message Apr 9, 2013

Subsystems (2)

v1 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 scsi: ufs: add support for query requests

Add support for sending UFS query requests through tagged command queuing. This design allows queuing query requests in any open slot along with other SCSI commands. In this way there is no need to save a slot in the requests queue and decrease its size.

A query request is posing to a SCSI command to use native flow. But unlike normal SCSI command flow, the data and response fields are filled in UFS host data structure instead of passing as arguments while queuing into SCSI mlqueue (mid-layer SCSI queue, the requests from this queue are submitted to the device queue). As per specification only one query request is allowed to be processed by device. Hence a mutex lock for protecting data and response fields (hba->query.request and hba->query.response) needs to be held while query request is in progress.

The API for submitting a query request is ufs_query_request() in ufs_core.c. This function is responsible for:
1. Obtaining the SCSI device from the host
2. Keeping the query mutex to prevent multiple queries
3. Storing the required data for sending a query request in ufs_hba
4. Queuing a SCSI vendor specific command to trigger a query request in the UFS driver.

The callers of ufs_query_request() are expected to fill the query command data fields and are to provide an allocated response field for the driver to fill response fields after request completion.

The request and response upiu is extended in a union to enable using the same data structure, both for command upiu and query request upiu.

The query request flow is separated from the scsi command flow in:
1. Preparing the request
2. Validating response (error) codes
3. Copying data (only used for descriptor read/write query requests)
4. Copying response/sense

Data error can't be handled in the scsi command native flow. Hence, we pass the code as without a change back to the submitting layer.

UPIU (UFS Protocol Information Unit) size is increased to 512 bytes from 128. The UPIU header and the transaction specific fields (SCSI command or Query Request OSF - Op-code Specific Fields) are 32 bytes together, the rest is used to transfer extra request data (such as descriptor in query requests). In order to accommodate the largest descriptor in the UFS spec (256 bytes) we need to increase the UPIU size.

drivers/scsi/ufs/Makefile +1 -0
index 1e5bd48..1ca46ca 100644
@@ -1,4 +1,5 @@
 # UFSHCD makefile
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
+obj-$(CONFIG_SCSI_UFSHCD) += ufs_core.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
drivers/scsi/ufs/ufs.h +97 -8

166 lines not on this page · raw message

drivers/scsi/ufs/ufs_core.c new file +123 -0

123 lines not on this page · raw message

drivers/scsi/ufs/ufshcd.c +264 -79

428 lines not on this page · raw message

drivers/scsi/ufs/ufshcd.h +18 -2
index 6b99a42..54be260 100644
@@ -88,7 +88,7 @@ struct uic_command {
 /**
  * struct ufshcd_lrb - local reference block
  * @utr_descriptor_ptr: UTRD address of the command
- * @ucd_cmd_ptr: UCD address of the command
+ * @ucd_req_ptr: UCD address of the command
  * @ucd_rsp_ptr: Response UPIU address for this command
  * @ucd_prdt_ptr: PRDT address of the command
  * @cmd: pointer to SCSI command
@@ -101,7 +101,7 @@ struct uic_command {
  */
 struct ufshcd_lrb {
 	struct utp_transfer_req_desc *utr_descriptor_ptr;
-	struct utp_upiu_cmd *ucd_cmd_ptr;
+	struct utp_upiu_req *ucd_req_ptr;
 	struct utp_upiu_rsp *ucd_rsp_ptr;
 	struct ufshcd_sg_entry *ucd_prdt_ptr;
 
@@ -115,6 +115,19 @@ struct ufshcd_lrb {
 	unsigned int lun;
 };
 
+/**
+ * struct ufs_query - keeps the query request information
+ * @request: request upiu and function
+ * @descriptor: buffer for sending/receiving descriptor
+ * @response: response upiu and response
+ * @mutex: lock to allow one query at a time
+ */
+struct ufs_query {
+	struct ufs_query_req *request;
+	u8 *descriptor;
+	struct ufs_query_res *response;
+	struct mutex mutex;
+};
 
 /**
  * struct ufs_hba - per adapter private structure
@@ -184,6 +197,9 @@ struct ufs_hba {
 
 	/* HBA Errors */
 	u32 errors;
+
+	/* Query Request */
+	struct ufs_query query;
 };
 
 int ufshcd_init(struct device *, struct ufs_hba ** , void __iomem * ,
drivers/scsi/ufs/ufshci.h +16 -1
index 0c16484..cb53a79 100644
@@ -39,7 +39,7 @@
 enum {
 	TASK_REQ_UPIU_SIZE_DWORDS	= 8,
 	TASK_RSP_UPIU_SIZE_DWORDS	= 8,
-	ALIGNED_UPIU_SIZE		= 128,
+	ALIGNED_UPIU_SIZE		= 512,
 };
 
 /* UFSHCI Registers */
@@ -224,6 +224,21 @@ enum {
 	UIC_CMD_RESULT_DME_FAILURE		= 0x0A,
 };
 
+/* Query response result code */
+enum {
+	QUERY_RESULT_SUCCESS			= 0x00,
+	QUERY_RESULT_NOT_READABLE		= 0xF6,
+	QUERY_RESULT_NOT_WRITEABLE		= 0xF7,
+	QUERY_RESULT_ALREADY_WRITTEN		= 0xF8,
+	QUERY_RESULT_INVALID_LENGTH		= 0xF9,
+	QUERY_RESULT_INVALID_VALUE		= 0xFA,
+	QUERY_RESULT_INVALID_SELECTOR		= 0xFB,
+	QUERY_RESULT_INVALID_INDEX		= 0xFC,
+	QUERY_RESULT_INVALID_IDN		= 0xFD,
+	QUERY_RESULT_INVALID_OPCODE		= 0xFE,
+	QUERY_RESULT_GENERAL_FAILURE		= 0xFF,
+};
+
 #define MASK_UIC_COMMAND_RESULT			0xFF
 
 #define INT_AGGR_COUNTER_THRESHOLD_VALUE	(0x1F << 8)
Signature · 4 lines
1.7.6
-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation