Commit 5a0b0cb9 authored by Sujit Reddy Thumma's avatar Sujit Reddy Thumma Committed by James Bottomley

[SCSI] ufs: Add support for sending NOP OUT UPIU

As part of device initialization sequence, sending NOP OUT UPIU and
waiting for NOP IN UPIU response is mandatory. This confirms that the
device UFS Transport (UTP) layer is functional and the host can configure
the device with further commands. Add support for sending NOP OUT UPIU to
check the device connection path and test whether the UTP layer on the
device side is functional during initialization.

A tag is acquired from the SCSI tag map space in order to send the device
management command. When the tag is acquired by internal command the scsi
command is rejected with host busy flag in order to requeue the request.
To avoid frequent collisions between internal commands and scsi commands
the device management command tag is allocated in the opposite direction
w.r.t block layer tag allocation.
Signed-off-by: default avatarSujit Reddy Thumma <sthumma@codeaurora.org>
Signed-off-by: default avatarDolev Raviv <draviv@codeaurora.org>
Signed-off-by: default avatarSantosh Y <santoshsy@gmail.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 5f09e1f3
...@@ -36,10 +36,13 @@ ...@@ -36,10 +36,13 @@
#ifndef _UFS_H #ifndef _UFS_H
#define _UFS_H #define _UFS_H
#include <linux/mutex.h>
#include <linux/types.h>
#define MAX_CDB_SIZE 16 #define MAX_CDB_SIZE 16
#define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\ #define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\
((byte3 << 24) | (byte2 << 16) |\ cpu_to_be32((byte3 << 24) | (byte2 << 16) |\
(byte1 << 8) | (byte0)) (byte1 << 8) | (byte0))
/* /*
...@@ -73,6 +76,7 @@ enum { ...@@ -73,6 +76,7 @@ enum {
UPIU_TRANSACTION_TASK_RSP = 0x24, UPIU_TRANSACTION_TASK_RSP = 0x24,
UPIU_TRANSACTION_READY_XFER = 0x31, UPIU_TRANSACTION_READY_XFER = 0x31,
UPIU_TRANSACTION_QUERY_RSP = 0x36, UPIU_TRANSACTION_QUERY_RSP = 0x36,
UPIU_TRANSACTION_REJECT_UPIU = 0x3F,
}; };
/* UPIU Read/Write flags */ /* UPIU Read/Write flags */
...@@ -110,6 +114,12 @@ enum { ...@@ -110,6 +114,12 @@ enum {
UPIU_COMMAND_SET_TYPE_QUERY = 0x2, UPIU_COMMAND_SET_TYPE_QUERY = 0x2,
}; };
/* UTP Transfer Request Command Offset */
#define UPIU_COMMAND_TYPE_OFFSET 28
/* Offset of the response code in the UPIU header */
#define UPIU_RSP_CODE_OFFSET 8
enum { enum {
MASK_SCSI_STATUS = 0xFF, MASK_SCSI_STATUS = 0xFF,
MASK_TASK_RESPONSE = 0xFF00, MASK_TASK_RESPONSE = 0xFF00,
...@@ -138,32 +148,48 @@ struct utp_upiu_header { ...@@ -138,32 +148,48 @@ struct utp_upiu_header {
/** /**
* struct utp_upiu_cmd - Command UPIU structure * struct utp_upiu_cmd - Command UPIU structure
* @header: UPIU header structure DW-0 to DW-2
* @data_transfer_len: Data Transfer Length DW-3 * @data_transfer_len: Data Transfer Length DW-3
* @cdb: Command Descriptor Block CDB DW-4 to DW-7 * @cdb: Command Descriptor Block CDB DW-4 to DW-7
*/ */
struct utp_upiu_cmd { struct utp_upiu_cmd {
struct utp_upiu_header header;
u32 exp_data_transfer_len; u32 exp_data_transfer_len;
u8 cdb[MAX_CDB_SIZE]; u8 cdb[MAX_CDB_SIZE];
}; };
/** /**
* struct utp_upiu_rsp - Response UPIU structure * struct utp_upiu_req - general upiu request structure
* @header: UPIU header DW-0 to DW-2 * @header:UPIU header structure DW-0 to DW-2
* @sc: fields structure for scsi command DW-3 to DW-7
*/
struct utp_upiu_req {
struct utp_upiu_header header;
struct utp_upiu_cmd sc;
};
/**
* struct utp_cmd_rsp - Response UPIU structure
* @residual_transfer_count: Residual transfer count DW-3 * @residual_transfer_count: Residual transfer count DW-3
* @reserved: Reserved double words DW-4 to DW-7 * @reserved: Reserved double words DW-4 to DW-7
* @sense_data_len: Sense data length DW-8 U16 * @sense_data_len: Sense data length DW-8 U16
* @sense_data: Sense data field DW-8 to DW-12 * @sense_data: Sense data field DW-8 to DW-12
*/ */
struct utp_upiu_rsp { struct utp_cmd_rsp {
struct utp_upiu_header header;
u32 residual_transfer_count; u32 residual_transfer_count;
u32 reserved[4]; u32 reserved[4];
u16 sense_data_len; u16 sense_data_len;
u8 sense_data[18]; u8 sense_data[18];
}; };
/**
* struct utp_upiu_rsp - general upiu response structure
* @header: UPIU header structure DW-0 to DW-2
* @sr: fields structure for scsi command DW-3 to DW-12
*/
struct utp_upiu_rsp {
struct utp_upiu_header header;
struct utp_cmd_rsp sr;
};
/** /**
* struct utp_upiu_task_req - Task request UPIU structure * struct utp_upiu_task_req - Task request UPIU structure
* @header - UPIU header structure DW0 to DW-2 * @header - UPIU header structure DW0 to DW-2
......
This diff is collapsed.
...@@ -68,6 +68,10 @@ ...@@ -68,6 +68,10 @@
#define UFSHCD "ufshcd" #define UFSHCD "ufshcd"
#define UFSHCD_DRIVER_VERSION "0.2" #define UFSHCD_DRIVER_VERSION "0.2"
enum dev_cmd_type {
DEV_CMD_TYPE_NOP = 0x0,
};
/** /**
* struct uic_command - UIC command structure * struct uic_command - UIC command structure
* @command: UIC command * @command: UIC command
...@@ -91,7 +95,7 @@ struct uic_command { ...@@ -91,7 +95,7 @@ struct uic_command {
/** /**
* struct ufshcd_lrb - local reference block * struct ufshcd_lrb - local reference block
* @utr_descriptor_ptr: UTRD address of the command * @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_rsp_ptr: Response UPIU address for this command
* @ucd_prdt_ptr: PRDT address of the command * @ucd_prdt_ptr: PRDT address of the command
* @cmd: pointer to SCSI command * @cmd: pointer to SCSI command
...@@ -101,10 +105,11 @@ struct uic_command { ...@@ -101,10 +105,11 @@ struct uic_command {
* @command_type: SCSI, UFS, Query. * @command_type: SCSI, UFS, Query.
* @task_tag: Task tag of the command * @task_tag: Task tag of the command
* @lun: LUN of the command * @lun: LUN of the command
* @intr_cmd: Interrupt command (doesn't participate in interrupt aggregation)
*/ */
struct ufshcd_lrb { struct ufshcd_lrb {
struct utp_transfer_req_desc *utr_descriptor_ptr; 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 utp_upiu_rsp *ucd_rsp_ptr;
struct ufshcd_sg_entry *ucd_prdt_ptr; struct ufshcd_sg_entry *ucd_prdt_ptr;
...@@ -116,8 +121,22 @@ struct ufshcd_lrb { ...@@ -116,8 +121,22 @@ struct ufshcd_lrb {
int command_type; int command_type;
int task_tag; int task_tag;
unsigned int lun; unsigned int lun;
bool intr_cmd;
}; };
/**
* struct ufs_dev_cmd - all assosiated fields with device management commands
* @type: device management command type - Query, NOP OUT
* @lock: lock to allow one command at a time
* @complete: internal commands completion
* @tag_wq: wait queue until free command slot is available
*/
struct ufs_dev_cmd {
enum dev_cmd_type type;
struct mutex lock;
struct completion *complete;
wait_queue_head_t tag_wq;
};
/** /**
* struct ufs_hba - per adapter private structure * struct ufs_hba - per adapter private structure
...@@ -131,6 +150,7 @@ struct ufshcd_lrb { ...@@ -131,6 +150,7 @@ struct ufshcd_lrb {
* @host: Scsi_Host instance of the driver * @host: Scsi_Host instance of the driver
* @dev: device handle * @dev: device handle
* @lrb: local reference block * @lrb: local reference block
* @lrb_in_use: lrb in use
* @outstanding_tasks: Bits representing outstanding task requests * @outstanding_tasks: Bits representing outstanding task requests
* @outstanding_reqs: Bits representing outstanding transfer requests * @outstanding_reqs: Bits representing outstanding transfer requests
* @capabilities: UFS Controller Capabilities * @capabilities: UFS Controller Capabilities
...@@ -146,6 +166,7 @@ struct ufshcd_lrb { ...@@ -146,6 +166,7 @@ struct ufshcd_lrb {
* @intr_mask: Interrupt Mask Bits * @intr_mask: Interrupt Mask Bits
* @feh_workq: Work queue for fatal controller error handling * @feh_workq: Work queue for fatal controller error handling
* @errors: HBA errors * @errors: HBA errors
* @dev_cmd: ufs device management command information
*/ */
struct ufs_hba { struct ufs_hba {
void __iomem *mmio_base; void __iomem *mmio_base;
...@@ -164,6 +185,7 @@ struct ufs_hba { ...@@ -164,6 +185,7 @@ struct ufs_hba {
struct device *dev; struct device *dev;
struct ufshcd_lrb *lrb; struct ufshcd_lrb *lrb;
unsigned long lrb_in_use;
unsigned long outstanding_tasks; unsigned long outstanding_tasks;
unsigned long outstanding_reqs; unsigned long outstanding_reqs;
...@@ -188,6 +210,9 @@ struct ufs_hba { ...@@ -188,6 +210,9 @@ struct ufs_hba {
/* HBA Errors */ /* HBA Errors */
u32 errors; u32 errors;
/* Device management request data */
struct ufs_dev_cmd dev_cmd;
}; };
#define ufshcd_writel(hba, val, reg) \ #define ufshcd_writel(hba, val, reg) \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment