RE: [PATCH V3 2/2] scsi: ufs: Set fDeviceInit flag to initiate device initialization

2013-07-10 Thread Dolev Raviv
> 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

2013-07-10 Thread Seungwon Jeon
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

2013-07-10 Thread Seungwon Jeon
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

2013-07-10 Thread Seungwon Jeon
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

2013-07-10 Thread Seungwon Jeon
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