RE: [PATCH V3 2/2] scsi: ufs: Set fDeviceInit flag to initiate device initialization
> On Tuesday, July 09, 2013, Sujit Reddy Thumma wrote: >> From: Dolev Raviv >> Allow UFS device to complete its initialization and accept >> SCSI commands by setting fDeviceInit flag. The device may take >> time for this operation and hence the host should poll until >> fDeviceInit flag is toggled to zero. This step is mandated by >> UFS device specification for device initialization completion. >> Signed-off-by: Dolev Raviv >> Signed-off-by: Sujit Reddy Thumma >> --- >> drivers/scsi/ufs/ufs.h| 88 +- >> drivers/scsi/ufs/ufshcd.c | 292 >> - >> drivers/scsi/ufs/ufshcd.h | 14 ++ >> drivers/scsi/ufs/ufshci.h |2 +- >> 4 files changed, 390 insertions(+), 6 deletions(-) >> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h >> index 14c0a4e..db5bde4 100644 >> --- a/drivers/scsi/ufs/ufs.h >> +++ b/drivers/scsi/ufs/ufs.h >> @@ -43,6 +43,8 @@ >> #define GENERAL_UPIU_REQUEST_SIZE 32 >> #define UPIU_HEADER_DATA_SEGMENT_MAX_SIZE ((ALIGNED_UPIU_SIZE) - \ >> (GENERAL_UPIU_REQUEST_SIZE)) >> +#define QUERY_OSF_SIZE ((GENERAL_UPIU_REQUEST_SIZE) - \ >> +(sizeof(struct utp_upiu_header))) >> #define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\ >> cpu_to_be32((byte3 << 24) | (byte2 << 16) |\ >> @@ -68,7 +70,7 @@ enum { >> UPIU_TRANSACTION_COMMAND= 0x01, >> UPIU_TRANSACTION_DATA_OUT = 0x02, >> UPIU_TRANSACTION_TASK_REQ = 0x04, >> -UPIU_TRANSACTION_QUERY_REQ = 0x26, >> +UPIU_TRANSACTION_QUERY_REQ = 0x16, >> }; >> /* UTP UPIU Transaction Codes Target to Initiator */ >> @@ -97,8 +99,19 @@ enum { >> UPIU_TASK_ATTR_ACA = 0x03, >> }; >> -/* UTP QUERY Transaction Specific Fields OpCode */ >> +/* UPIU Query request function */ >> enum { >> +UPIU_QUERY_FUNC_STANDARD_READ_REQUEST = 0x01, >> +UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST = 0x81, >> +}; >> + >> +/* Flag idn for Query Requests*/ >> +enum flag_idn { >> +QUERY_FLAG_IDN_FDEVICEINIT = 0x01, >> +}; >> + >> +/* UTP QUERY Transaction Specific Fields OpCode */ >> +enum query_opcode { >> UPIU_QUERY_OPCODE_NOP = 0x0, >> UPIU_QUERY_OPCODE_READ_DESC = 0x1, >> UPIU_QUERY_OPCODE_WRITE_DESC= 0x2, >> @@ -110,6 +123,21 @@ enum { >> UPIU_QUERY_OPCODE_TOGGLE_FLAG = 0x8, >> }; >> +/* 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, >> +}; >> + >> /* UTP Transfer Request Command Type (CT) */ >> enum { >> UPIU_COMMAND_SET_TYPE_SCSI = 0x0, >> @@ -127,6 +155,7 @@ enum { >> MASK_SCSI_STATUS= 0xFF, >> MASK_TASK_RESPONSE = 0xFF00, >> MASK_RSP_UPIU_RESULT= 0x, >> +MASK_QUERY_DATA_SEG_LEN = 0x, >> }; >> /* Task management service response */ >> @@ -160,13 +189,40 @@ struct utp_upiu_cmd { >> }; >> /** >> + * struct utp_upiu_query - upiu request buffer structure for >> + * query request. >> + * @opcode: command to perform B-0 >> + * @idn: a value that indicates the particular type of data B-1 + * @index: Index to further identify data B-2 >> + * @selector: Index to further identify data B-3 >> + * @reserved_osf: spec reserved field B-4,5 >> + * @length: number of descriptor bytes to read/write B-6,7 >> + * @value: Attribute value to be written DW-5 >> + * @reserved: spec reserved DW-6,7 >> + */ >> +struct utp_upiu_query { >> +u8 opcode; >> +u8 idn; >> +u8 index; >> +u8 selector; >> +u16 reserved_osf; >> +u16 length; >> +u32 value; >> +u32 reserved[2]; >> +}; >> + >> +/** >> * struct utp_upiu_req - general upiu request structure >> * @header:UPIU header structure DW-0 to DW-2 >> * @sc: fields structure for scsi command DW-3 to DW-7 >> + * @qr: fields structure for query request DW-3 to DW-7 >> */ >> struct utp_upiu_req { >> struct utp_upiu_header header; >> -struct utp_upiu_cmd sc; >> +union { >> +struct utp_upiu_cmd sc; >> +struct utp_upiu_query qr; >> +}; >> }; >> /** >> @@ -187,10 +243,14 @@ struct utp_cmd_rsp { >> * 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 >> + * @qr: fields structure for query request DW-3 to DW-7 >> */ >>
RE: [PATCH V3 2/2] scsi: ufs: Add runtime PM support for UFS host controller driver
On Tue, July 09, 2013, Sujit Reddy Thumma wrote: > Add runtime PM helpers to suspend/resume UFS controller at runtime. > Enable runtime PM by default for pci and platform drivers as the > initialized hardware can suspend if it is not used after bootup. > > Signed-off-by: Sujit Reddy Thumma > --- > drivers/scsi/ufs/ufshcd-pci.c| 65 ++--- > drivers/scsi/ufs/ufshcd-pltfrm.c | 51 +- > drivers/scsi/ufs/ufshcd.c|8 + > 3 files changed, 117 insertions(+), 7 deletions(-) > > diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c > index 48be39a..7bd8faa 100644 > --- a/drivers/scsi/ufs/ufshcd-pci.c > +++ b/drivers/scsi/ufs/ufshcd-pci.c > @@ -35,6 +35,7 @@ > > #include "ufshcd.h" > #include > +#include > > #ifdef CONFIG_PM > /** > @@ -44,7 +45,7 @@ > * > * Returns -ENOSYS > */ > -static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state) > +static int ufshcd_pci_suspend(struct device *dev) > { > /* >* TODO: > @@ -61,7 +62,7 @@ static int ufshcd_pci_suspend(struct pci_dev *pdev, > pm_message_t state) > * > * Returns -ENOSYS > */ > -static int ufshcd_pci_resume(struct pci_dev *pdev) > +static int ufshcd_pci_resume(struct device *dev) > { > /* >* TODO: > @@ -71,8 +72,48 @@ static int ufshcd_pci_resume(struct pci_dev *pdev) > > return -ENOSYS; > } > +#else > +#define ufshcd_pci_suspend NULL > +#define ufshcd_pci_resumeNULL > #endif /* CONFIG_PM */ > > +#ifdef CONFIG_PM_RUNTIME > +static int ufshcd_pci_runtime_suspend(struct device *dev) > +{ > + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); > + struct ufs_hba *hba = pci_get_drvdata(pdev); Can be replaced: struct ufs_hba *hba = dev_get_drvdata(dev); > + > + if (!hba) > + return 0; > + > + return ufshcd_runtime_suspend(hba); > +} > +static int ufshcd_pci_runtime_resume(struct device *dev) > +{ > + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); > + struct ufs_hba *hba = pci_get_drvdata(pdev); Same as above. > + > + if (!hba) > + return 0; > + > + return ufshcd_runtime_resume(hba); > +} > +static int ufshcd_pci_runtime_idle(struct device *dev) > +{ > + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); > + struct ufs_hba *hba = pci_get_drvdata(pdev); Same as above. > + > + if (!hba) > + return 0; > + > + return ufshcd_runtime_idle(hba); > +} > +#else /* !CONFIG_PM_RUNTIME */ > +#define ufshcd_pci_runtime_suspend NULL > +#define ufshcd_pci_runtime_resumeNULL > +#define ufshcd_pci_runtime_idle NULL > +#endif /* CONFIG_PM_RUNTIME */ > + > /** > * ufshcd_pci_shutdown - main function to put the controller in reset state > * @pdev: pointer to PCI device handle > @@ -91,6 +132,9 @@ static void ufshcd_pci_remove(struct pci_dev *pdev) > { > struct ufs_hba *hba = pci_get_drvdata(pdev); > > + pm_runtime_forbid(&pdev->dev); > + pm_runtime_get_noresume(&pdev->dev); > + > disable_irq(pdev->irq); > ufshcd_remove(hba); > pci_release_regions(pdev); > @@ -168,6 +212,8 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct > pci_device_id *id) > } > > pci_set_drvdata(pdev, hba); > + pm_runtime_put_noidle(&pdev->dev); > + pm_runtime_allow(&pdev->dev); > > return 0; > > @@ -182,6 +228,14 @@ out_error: > return err; > } > > +static const struct dev_pm_ops ufshcd_pci_pm_ops = { > + .suspend= ufshcd_pci_suspend, > + .resume = ufshcd_pci_resume, > + .runtime_suspend = ufshcd_pci_runtime_suspend, > + .runtime_resume = ufshcd_pci_runtime_resume, > + .runtime_idle= ufshcd_pci_runtime_idle, > +}; > + > static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = { > { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, > { } /* terminate list */ > @@ -195,10 +249,9 @@ static struct pci_driver ufshcd_pci_driver = { > .probe = ufshcd_pci_probe, > .remove = ufshcd_pci_remove, > .shutdown = ufshcd_pci_shutdown, > -#ifdef CONFIG_PM > - .suspend = ufshcd_pci_suspend, > - .resume = ufshcd_pci_resume, > -#endif > + .driver = { > + .pm = &ufshcd_pci_pm_ops > + }, > }; > > module_pci_driver(ufshcd_pci_driver); > diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c > b/drivers/scsi/ufs/ufshcd-pltfrm.c > index c42db40..b1f2605 100644 > --- a/drivers/scsi/ufs/ufshcd-pltfrm.c > +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c > @@ -34,6 +34,7 @@ > */ > > #include > +#include > > #include "ufshcd.h" > > @@ -87,6 +88,43 @@ static int ufshcd_pltfrm_resume(struct device *dev) > #define ufshcd_pltfrm_resume NULL > #endif > > +#ifdef CONFIG_PM_RUNTIME > +static int ufshcd_pltfrm_runtime_suspend(struct device *dev) > +{ > + struct platform_device *pdev = to_platform_device(dev); > + struct ufs_hba *hb
RE: [PATCH V3 1/2] scsi: ufs: Add support for host assisted background operations
I'm not sure that BKOPS with runtime-pm associates. Do you think it's helpful for power management? How about hibernation scheme for runtime-pm? I'm testing and I can introduce soon. On Tue, July 09, 2013, Sujit Reddy Thumma wrote: > Background operations in the UFS device can be disabled by > the host to reduce the response latency of transfer requests. > Add support for enabling/disabling the background operations > during runtime suspend/resume of the device. > > If the device is in critical need of BKOPS it will raise an > URGENT_BKOPS exception which should be handled by the host to > make sure the device performs as expected. > > During bootup, the BKOPS is enabled in the device by default. > The disable of BKOPS is supported only when the driver supports > runtime suspend/resume operations as the runtime PM framework > provides a way to determine the device idleness and hence BKOPS > can be managed effectively. During runtime resume the BKOPS is > disabled to reduce latency and during runtime suspend the BKOPS > is enabled to allow device to carry out idle time BKOPS. > > In some cases where the BKOPS is disabled during runtime resume > and due to continuous data transfers the runtime suspend is not > triggered, the BKOPS is enabled when the device raises a level-2 > exception (outstanding operations - performance impact). > > Signed-off-by: Sujit Reddy Thumma > --- > drivers/scsi/ufs/ufs.h| 25 - > drivers/scsi/ufs/ufshcd.c | 338 > + > drivers/scsi/ufs/ufshcd.h | 10 ++ > 3 files changed, 372 insertions(+), 1 deletions(-) > > diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h > index db5bde4..549a652 100644 > --- a/drivers/scsi/ufs/ufs.h > +++ b/drivers/scsi/ufs/ufs.h > @@ -107,7 +107,29 @@ enum { > > /* Flag idn for Query Requests*/ > enum flag_idn { > - QUERY_FLAG_IDN_FDEVICEINIT = 0x01, > + QUERY_FLAG_IDN_FDEVICEINIT = 0x01, > + QUERY_FLAG_IDN_BKOPS_EN = 0x04, > +}; > + > +/* Attribute idn for Query requests */ > +enum attr_idn { > + QUERY_ATTR_IDN_BKOPS_STATUS = 0x05, > + QUERY_ATTR_IDN_EE_CONTROL = 0x0D, > + QUERY_ATTR_IDN_EE_STATUS= 0x0E, > +}; > + > +/* Exception event mask values */ > +enum { > + MASK_EE_STATUS = 0x, > + MASK_EE_URGENT_BKOPS= (1 << 2), > +}; > + > +/* Background operation status */ > +enum { > + BKOPS_STATUS_NO_OP = 0x0, > + BKOPS_STATUS_NON_CRITICAL= 0x1, > + BKOPS_STATUS_PERF_IMPACT = 0x2, > + BKOPS_STATUS_CRITICAL= 0x3, > }; > > /* UTP QUERY Transaction Specific Fields OpCode */ > @@ -156,6 +178,7 @@ enum { > MASK_TASK_RESPONSE = 0xFF00, > MASK_RSP_UPIU_RESULT= 0x, > MASK_QUERY_DATA_SEG_LEN = 0x, > + MASK_RSP_EXCEPTION_EVENT = 0x1, > }; > > /* Task management service response */ > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c > index 96ccb28..a25de66 100644 > --- a/drivers/scsi/ufs/ufshcd.c > +++ b/drivers/scsi/ufs/ufshcd.c > @@ -268,6 +268,21 @@ ufshcd_get_rsp_upiu_result(struct utp_upiu_rsp > *ucd_rsp_ptr) > } > > /** > + * ufshcd_is_exception_event - Check if the device raised an exception event > + * @ucd_rsp_ptr: pointer to response UPIU > + * > + * The function checks if the device raised an exception event indicated in > + * the Device Information field of response UPIU. > + * > + * Returns true if exception is raised, false otherwise. > + */ > +static inline bool ufshcd_is_exception_event(struct utp_upiu_rsp > *ucd_rsp_ptr) > +{ > + return be32_to_cpu(ucd_rsp_ptr->header.dword_2) & > + MASK_RSP_EXCEPTION_EVENT ? true : false; > +} > + > +/** > * ufshcd_config_int_aggr - Configure interrupt aggregation values. > * Currently there is no use case where we want to configure > * interrupt aggregation dynamically. So to configure interrupt > @@ -1174,6 +1189,86 @@ out_no_mem: > } > > /** > + * ufshcd_query_attr - Helper function for composing attribute requests > + * hba: per-adapter instance > + * opcode: attribute opcode > + * idn: attribute idn to access > + * index: index field > + * selector: selector field > + * attr_val: the attribute value after the query request completes > + * > + * Returns 0 for success, non-zero in case of failure > +*/ > +int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, > + enum attr_idn idn, u8 index, u8 selector, u32 *attr_val) > +{ > + struct ufs_query_req *query; > + struct ufs_query_res *response; > + int err = -ENOMEM; > + > + if (!attr_val) { > + dev_err(hba->dev, "%s: attribute value required for write > request\n", It's trivial, but message is only focused on write. attr_val is also needed in case read request. Thanks, Seungwon Jeon > + __func__); > + err = -EINVAL; > +
RE: [PATCH V3 2/2] scsi: ufs: Set fDeviceInit flag to initiate device initialization
On Tuesday, July 09, 2013, Sujit Reddy Thumma wrote: > From: Dolev Raviv > > Allow UFS device to complete its initialization and accept > SCSI commands by setting fDeviceInit flag. The device may take > time for this operation and hence the host should poll until > fDeviceInit flag is toggled to zero. This step is mandated by > UFS device specification for device initialization completion. > > Signed-off-by: Dolev Raviv > Signed-off-by: Sujit Reddy Thumma > --- > drivers/scsi/ufs/ufs.h| 88 +- > drivers/scsi/ufs/ufshcd.c | 292 > - > drivers/scsi/ufs/ufshcd.h | 14 ++ > drivers/scsi/ufs/ufshci.h |2 +- > 4 files changed, 390 insertions(+), 6 deletions(-) > > diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h > index 14c0a4e..db5bde4 100644 > --- a/drivers/scsi/ufs/ufs.h > +++ b/drivers/scsi/ufs/ufs.h > @@ -43,6 +43,8 @@ > #define GENERAL_UPIU_REQUEST_SIZE 32 > #define UPIU_HEADER_DATA_SEGMENT_MAX_SIZE((ALIGNED_UPIU_SIZE) - \ > (GENERAL_UPIU_REQUEST_SIZE)) > +#define QUERY_OSF_SIZE ((GENERAL_UPIU_REQUEST_SIZE) - \ > + (sizeof(struct utp_upiu_header))) > > #define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\ > cpu_to_be32((byte3 << 24) | (byte2 << 16) |\ > @@ -68,7 +70,7 @@ enum { > UPIU_TRANSACTION_COMMAND= 0x01, > UPIU_TRANSACTION_DATA_OUT = 0x02, > UPIU_TRANSACTION_TASK_REQ = 0x04, > - UPIU_TRANSACTION_QUERY_REQ = 0x26, > + UPIU_TRANSACTION_QUERY_REQ = 0x16, > }; > > /* UTP UPIU Transaction Codes Target to Initiator */ > @@ -97,8 +99,19 @@ enum { > UPIU_TASK_ATTR_ACA = 0x03, > }; > > -/* UTP QUERY Transaction Specific Fields OpCode */ > +/* UPIU Query request function */ > enum { > + UPIU_QUERY_FUNC_STANDARD_READ_REQUEST = 0x01, > + UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST = 0x81, > +}; > + > +/* Flag idn for Query Requests*/ > +enum flag_idn { > + QUERY_FLAG_IDN_FDEVICEINIT = 0x01, > +}; > + > +/* UTP QUERY Transaction Specific Fields OpCode */ > +enum query_opcode { > UPIU_QUERY_OPCODE_NOP = 0x0, > UPIU_QUERY_OPCODE_READ_DESC = 0x1, > UPIU_QUERY_OPCODE_WRITE_DESC= 0x2, > @@ -110,6 +123,21 @@ enum { > UPIU_QUERY_OPCODE_TOGGLE_FLAG = 0x8, > }; > > +/* 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, > +}; > + > /* UTP Transfer Request Command Type (CT) */ > enum { > UPIU_COMMAND_SET_TYPE_SCSI = 0x0, > @@ -127,6 +155,7 @@ enum { > MASK_SCSI_STATUS= 0xFF, > MASK_TASK_RESPONSE = 0xFF00, > MASK_RSP_UPIU_RESULT= 0x, > + MASK_QUERY_DATA_SEG_LEN = 0x, > }; > > /* Task management service response */ > @@ -160,13 +189,40 @@ struct utp_upiu_cmd { > }; > > /** > + * struct utp_upiu_query - upiu request buffer structure for > + * query request. > + * @opcode: command to perform B-0 > + * @idn: a value that indicates the particular type of data B-1 > + * @index: Index to further identify data B-2 > + * @selector: Index to further identify data B-3 > + * @reserved_osf: spec reserved field B-4,5 > + * @length: number of descriptor bytes to read/write B-6,7 > + * @value: Attribute value to be written DW-5 > + * @reserved: spec reserved DW-6,7 > + */ > +struct utp_upiu_query { > + u8 opcode; > + u8 idn; > + u8 index; > + u8 selector; > + u16 reserved_osf; > + u16 length; > + u32 value; > + u32 reserved[2]; > +}; > + > +/** > * struct utp_upiu_req - general upiu request structure > * @header:UPIU header structure DW-0 to DW-2 > * @sc: fields structure for scsi command DW-3 to DW-7 > + * @qr: fields structure for query request DW-3 to DW-7 > */ > struct utp_upiu_req { > struct utp_upiu_header header; > - struct utp_upiu_cmd sc; > + union { > + struct utp_upiu_cmd sc; > + struct utp_upiu_query qr; > + }; > }; > > /** > @@ -187,10 +243,14 @@ struct utp_cmd_rsp { > * 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 > + * @qr: fields structure for query request DW-3 to DW-7 > */ > struct utp_upiu_rsp { > struct utp_upiu_hea
RE: [PATCH V3 1/2] scsi: ufs: Add support for sending NOP OUT UPIU
On Tue, July 09, 2013, Sujit Reddy Thumma wrote: > 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: Sujit Reddy Thumma > Signed-off-by: Dolev Raviv > --- > drivers/scsi/ufs/ufs.h| 43 +++- > drivers/scsi/ufs/ufshcd.c | 596 > + > drivers/scsi/ufs/ufshcd.h | 29 ++- > 3 files changed, 552 insertions(+), 116 deletions(-) > > diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h > index 139bc06..14c0a4e 100644 > --- a/drivers/scsi/ufs/ufs.h > +++ b/drivers/scsi/ufs/ufs.h > @@ -36,10 +36,16 @@ > #ifndef _UFS_H > #define _UFS_H > > +#include > +#include > + > #define MAX_CDB_SIZE 16 > +#define GENERAL_UPIU_REQUEST_SIZE 32 > +#define UPIU_HEADER_DATA_SEGMENT_MAX_SIZE((ALIGNED_UPIU_SIZE) - \ > + (GENERAL_UPIU_REQUEST_SIZE)) > > #define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\ > - ((byte3 << 24) | (byte2 << 16) |\ > + cpu_to_be32((byte3 << 24) | (byte2 << 16) |\ >(byte1 << 8) | (byte0)) > > /* > @@ -73,6 +79,7 @@ enum { > UPIU_TRANSACTION_TASK_RSP = 0x24, > UPIU_TRANSACTION_READY_XFER = 0x31, > UPIU_TRANSACTION_QUERY_RSP = 0x36, > + UPIU_TRANSACTION_REJECT_UPIU= 0x3F, > }; > > /* UPIU Read/Write flags */ > @@ -110,6 +117,12 @@ enum { > 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 { > MASK_SCSI_STATUS= 0xFF, > MASK_TASK_RESPONSE = 0xFF00, > @@ -138,26 +151,32 @@ struct utp_upiu_header { > > /** > * struct utp_upiu_cmd - Command UPIU structure > - * @header: UPIU header structure DW-0 to DW-2 > * @data_transfer_len: Data Transfer Length DW-3 > * @cdb: Command Descriptor Block CDB DW-4 to DW-7 > */ > struct utp_upiu_cmd { > - struct utp_upiu_header header; > u32 exp_data_transfer_len; > u8 cdb[MAX_CDB_SIZE]; > }; > > /** > - * struct utp_upiu_rsp - Response UPIU structure > - * @header: UPIU header DW-0 to DW-2 > + * struct utp_upiu_req - general upiu request structure > + * @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 > * @reserved: Reserved double words DW-4 to DW-7 > * @sense_data_len: Sense data length DW-8 U16 > * @sense_data: Sense data field DW-8 to DW-12 > */ > -struct utp_upiu_rsp { > - struct utp_upiu_header header; > +struct utp_cmd_rsp { > u32 residual_transfer_count; > u32 reserved[4]; > u16 sense_data_len; > @@ -165,6 +184,16 @@ struct utp_upiu_rsp { > }; > > /** > + * 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 > * @header - UPIU header structure DW0 to DW-2 > * @input_param1: Input parameter 1 DW-3 > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c > index b743bd6..3f482b6 100644 > --- a/drivers/scsi/ufs/ufshcd.c > +++ b/drivers/scsi/ufs/ufshcd.c > @@ -43,6 +43,11 @@ > /* UIC command timeout, unit: ms */ > #define UIC_CMD_TIMEOUT 500 > > +/* NOP OUT retries waiting for NOP IN response */ > +#define NOP_OUT_RETRIES10 > +/* Timeout after 30 msecs if NOP OUT hangs without response */ > +#define NOP_OUT_TIMEOUT30 /* msecs */ > + > enum { > UFSHCD_MAX_CHANNEL = 0, > UFSHCD_MAX_ID = 1, > @@ -71,6 +76,47 @@ enum { > INT_AGGR_CONFIG, > }; > > +/* > + * ufshcd_wait_for_register - wait for register value to change > + * @hba - per-adapter interface > + * @re