scsi: ufs: add support for query requests
Subsystems (2)
PATCH v4 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 ufshcd.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.
---
changes for v4:
- Removed un-necessary inline modifiers
- Fixed return values to SCSI layer on completion changes for v3:
- Reworked validating response UPIU
- Removed redundant NULL pointer checks
changes for v2:
- Moved ufs_query_request to ufshcd.c and removed ufs_core.c
- Addressed Santosh's comments
drivers/scsi/ufs/Kconfig +1 -0
@@ -35,6 +35,7 @@ config SCSI_UFSHCD tristate "Universal Flash Storage Controller Driver Core" depends on SCSI + default y ---help--- This selects the support for UFS devices in Linux, say Y and make sure that you know the name of your UFS host adapter (the card
drivers/scsi/ufs/ufs.h +114 -8
195 lines not on this page · raw message
drivers/scsi/ufs/ufshcd.c +357 -91
539 lines not on this page · raw message
drivers/scsi/ufs/ufshcd.h +20 -2
@@ -60,6 +60,7 @@#include <scsi/scsi_tcq.h> #include <scsi/scsi_dbg.h> #include <scsi/scsi_eh.h> +#include <scsi/scsi_device.h> #include "ufs.h" #include "ufshci.h"
@@ -88,7 +89,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 +102,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 +116,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 lock_ufs_query; +};/** * struct ufs_hba - per adapter private structure
@@ -143,6 +157,7 @@ struct ufshcd_lrb {* @uic_workq: Work queue for UIC completion handling * @feh_workq: Work queue for fatal controller error handling * @errors: HBA errors +* @query: query request information */ struct ufs_hba {void __iomem *mmio_base;
@@ -184,6 +199,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 +1 -1
@@ -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 */
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
Quoted 7 lines
drivers/scsi/ufs/ufshcd.c +7
-0+ +/** +* ufshcd_compose_upiu - form UFS Protocol Information Unit(UPIU) +* @hba - UFS hba +* @lrb - pointer to local reference block +*/ +static int ufshcd_compose_upiu (struct ufs_hba *hba,struct ufshcd_lrb *lrbp)
drivers/scsi/ufs/ufshcd.c static void ufshcd_int_config(struct ufs_hba *hba, u32 option) · line 606
Quoted 10 lines
drivers/scsi/ufs/ufshcd.c +8
-1+{ +u32 upiu_flags; +int ret =0 ; + +switch (lrbp->command_type) { +case UTP_CMD_TYPE_SCSI :case UTP_CMD_TYPE_DEV_MANAGE : -/* For query function implementation */ +ufshcd_prepare_req_desc (lrbp, &upiu_flags); +if (lrbp->cmd && lrbp->command_type ==UTP_CMD_TYPE_SCSI )
Sorry, probably missed it in the initial review. Here no need to check for 'lrbp->cmd'.
drivers/scsi/ufs/ufshcd.c static void ufshcd_int_config(struct ufs_hba *hba, u32 option) · line 608
Quoted 2 lines
drivers/scsi/ufs/ufshcd.c +2
-0+ufshcd_prepare_utp_scsi_cmd_upiu (lrbp, upiu_flags); + else if (lrbp->cmd)
no need to check here also
drivers/scsi/ufs/ufshcd.c static void ufshcd_int_config(struct ufs_hba *hba, u32 option) · line 615
Quoted 7 lines
drivers/scsi/ufs/ufshcd.c +7
-0+ufshcd_prepare_utp_query_req_upiu (hba, lrbp, + upiu_flags); + else { +dev_err (hba->dev,"%s: Invalid UPIU request\n" , + __func__); + ret = -EINVAL ; + }
remove this else part, this condition will never be true.
Quoted 17 lines
break; case UTP_CMD_TYPE_UFS: /* For UFS native command implementation */drivers/scsi/ufs/ufshcd.c +10
-0+dev_err (hba->dev,"%s: UFS native command are not supported\n" , + __func__); + ret = -ENOTSUPP ; +break ; +default : + ret = -ENOTSUPP ; +dev_err (hba->dev,"%s: unknown command type: 0x%x\n" , + __func__, lrbp->command_type);break ; }/* end of switch */ + +return ret; }
Signature · 1 line
~Santosh