Re: [PATCH v4 6/6] scsi: ufs: add dme control primitives

2013-05-08 Thread Santosh Y
On Wed, May 8, 2013 at 2:13 PM, Seungwon Jeon  wrote:
> Implements to support the following operations.
> Currently, this patch doesn't introduce DME_ENABLE and DME_RESET
> because host controller's HCE enable contains these roles.
>
> DME_POWERON{OFF}, DME_HIBERNATE_ENTER{EXIT}, DME_ENDPOINTRESET.
>
> Signed-off-by: Seungwon Jeon 
> Tested-by: Maya Erez 
> ---
> Change in v4:
> - Changed function names.
>
>  drivers/scsi/ufs/ufshcd.c |  123 
> +++--
>  drivers/scsi/ufs/ufshcd.h |   26 ++
>  drivers/scsi/ufs/ufshci.h |   15 ++
>  3 files changed, 160 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index e05eedb..45123b4 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -39,6 +39,7 @@
>
>  #define UFSHCD_ENABLE_INTRS(UTP_TRANSFER_REQ_COMPL |\
>  UTP_TASK_REQ_COMPL |\
> +UFSHCD_HIBERNATE_MASK |\
>  UFSHCD_ERROR_MASK)
>  /* UIC command timeout, unit: ms */
>  #define UIC_CMD_TIMEOUT500
> @@ -203,6 +204,18 @@ static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba 
> *hba)
>  }
>
>  /**
> + * ufshcd_get_upmcrs - Get the power mode change request status
> + * @hba: Pointer to adapter instance
> + *
> + * This function gets the UPMCRS field of HCS register
> + * Returns value of UPMCRS field
> + */
> +static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba)
> +{
> +   return (ufshcd_readl(hba, REG_CONTROLLER_STATUS) >> 8) & 0x7;
> +}
> +
> +/**
>   * ufshcd_free_hba_memory - Free allocated memory for LRB, request
>   * and task lists
>   * @hba: Pointer to adapter instance
> @@ -1163,6 +1176,103 @@ out:
>  EXPORT_SYMBOL_GPL(ufshcd_dme_get_attr);
>
>  /**
> + * ufshcd_dme_power_ctrl - UIC command for DME_POWERON, DME_POWEROFF
> + * @hba: per adapter instance
> + * @on: indicate wherter power_on or power_off
> + *
> + * Returns 0 on success, non-zero value on failure
> + */
> +int ufshcd_dme_power_ctrl(struct ufs_hba *hba, u8 on)
> +{
> +   struct uic_command uic_cmd = {0};
> +   static const char *const action[] = {
> +   "dme-power-off",
> +   "dme-power-on"
> +   };
> +   const char *power = action[!!on];
> +   int ret;
> +
> +   uic_cmd.command = on ?
> +   UIC_CMD_DME_POWERON : UIC_CMD_DME_POWEROFF;
> +
> +   ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
> +   if (ret)
> +   dev_err(hba->dev, "%s: error code %d\n", power, ret);
> +
> +   return ret;
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_dme_power_ctrl);
> +
> +/**
> + * ufshcd_dme_hibern8_ctrl - UIC command for DME_HIBERNATE_ENTER,
> + *  DME_HIBERNATE_EXIT
> + * @hba: per adapter instance
> + * @enter: indicate wherter hibernation enter or exit
> + *
> + * Returns 0 on success, non-zero value on failure
> + */
> +int ufshcd_dme_hibern8_ctrl(struct ufs_hba *hba, u8 enter)
> +{
> +   struct uic_command uic_cmd = {0};
> +   static const char *const action[] = {
> +   "dme-hibernate-exit",
> +   "dme-hibernate-enter"
> +   };
> +   const char *hibern8 = action[!!enter];
> +   u8 status;
> +   int ret;
> +
> +   uic_cmd.command = enter ?
> +   UIC_CMD_DME_HIBER_ENTER : UIC_CMD_DME_HIBER_EXIT;
> +
> +   mutex_lock(&hba->uic_cmd_mutex);
> +   init_completion(&hba->hibern8_done);
> +   ret = __ufshcd_send_uic_cmd(hba, &uic_cmd);
> +   if (ret) {
> +   dev_err(hba->dev, "%s: error code %d\n", hibern8, ret);
> +   goto out;
> +   }
> +
> +   if (wait_for_completion_timeout(&hba->hibern8_done,
> +   msecs_to_jiffies(UIC_CMD_TIMEOUT))) {
> +   status = ufshcd_get_upmcrs(hba);
> +   if (status != PWR_LOCAL) {
> +   dev_err(hba->dev, "%s: failed, host upmcrs:0x%x\n",
> +   hibern8, status);
> +   ret = status;
> +   }
> +   } else {
> +   dev_err(hba->dev, "%s: timeout\n", hibern8);
> +   ret = -ETIMEDOUT;
> +   }
> +out:
> +   mutex_unlock(&hba->uic_cmd_mutex);
> +   return ret;
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_dme_hibern8_ctrl);
> +
> +/**
> + * ufshcd_dme_endpoint_reset - UIC command for DME_ENDPOINTRESET
> + * @hba: per adapter instance
> + *
> + * Returns 0 on success, non-zero value on failure
> + */
> +int ufshcd_dme_endpoint_reset(struct ufs_hba *hba)
> +{
> +   struct uic_command uic_cmd = {0};
> +   int ret;
> +
> +   uic_cmd.command = UIC_CMD_DME_END_PT_RST;
> +
> +   ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
> +   if (ret)
> +   dev_err(hba->dev, "dme-endpoint-reset: error code %d\n", ret);
> +
> +   return ret;
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_dme_endpoint_reset);
> +
> +/

Re: [PATCH v4 5/6] scsi: ufs: add dme configuration primitives

2013-05-08 Thread Santosh Y
On Wed, May 8, 2013 at 2:12 PM, Seungwon Jeon  wrote:
> Implements to support Get and Set operation of the DME.
> These operations are used to configure the behavior of
> the UNIPRO.
>
> Signed-off-by: Seungwon Jeon 
> Tested-by: Maya Erez 
> ---
> Change in v4:
> - Removed unipro.h header file. It will be introduced in next.
> - Changed function names and error message.
>
>  drivers/scsi/ufs/ufshcd.c |   88 
> +
>  drivers/scsi/ufs/ufshcd.h |   30 +++
>  drivers/scsi/ufs/ufshci.h |5 +++
>  3 files changed, 123 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 8363b92..e05eedb 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -191,6 +191,18 @@ static inline int ufshcd_get_uic_cmd_result(struct 
> ufs_hba *hba)
>  }
>
>  /**
> + * ufshcd_get_dme_attr_val - Get the value of attribute returned by UIC 
> command
> + * @hba: Pointer to adapter instance
> + *
> + * This function gets UIC command argument3
> + * Returns 0 on success, non zero value on error
> + */
> +static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba)
> +{
> +   return ufshcd_readl(hba, REG_UIC_COMMAND_ARG_3);
> +}
> +
> +/**
>   * ufshcd_free_hba_memory - Free allocated memory for LRB, request
>   * and task lists
>   * @hba: Pointer to adapter instance
> @@ -1077,6 +1089,80 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
>  }
>
>  /**
> + * ufshcd_dme_set_attr - UIC command for DME_SET, DME_PEER_SET
> + * @hba: per adapter instance
> + * @attr_sel: uic command argument1
> + * @attr_set: attribute set type as uic command argument2
> + * @mib_val: setting value as uic command argument3
> + * @peer: indicate wherter peer or non-peer
> + *
> + * Returns 0 on success, non-zero value on failure
> + */
> +int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
> +   u8 attr_set, u32 mib_val, u8 peer)
> +{
> +   struct uic_command uic_cmd = {0};
> +   static const char *const action[] = {
> +   "dme-set",
> +   "dme-peer-set"
> +   };
> +   const char *set = action[!!peer];
> +   int ret;
> +
> +   uic_cmd.command = peer ?
> +   UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET;
> +   uic_cmd.argument1 = attr_sel;
> +   uic_cmd.argument2 = UIC_ARG_ATTR_SET(attr_set);
> +   uic_cmd.argument3 = mib_val;
> +
> +   ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
> +   if (ret)
> +   dev_err(hba->dev, "%s: attr-id 0x%x error code %d\n",
> +   set, GET_UIC_ATTR_ID(attr_sel), ret);
> +
> +   return ret;
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_dme_set_attr);
> +
> +/**
> + * ufshcd_dme_get_attr - UIC command for DME_GET, DME_PEER_GET
> + * @hba: per adapter instance
> + * @attr_sel: uic command argument1
> + * @mib_val: the value of the attribute as returned by the UIC command
> + * @peer: indicate wherter peer or non-peer
> + *
> + * Returns 0 on success, non-zero value on failure
> + */
> +int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
> +   u32 *mib_val, u8 peer)
> +{
> +   struct uic_command uic_cmd = {0};
> +   static const char *const action[] = {
> +   "dme-get",
> +   "dme-peer-get"
> +   };
> +   const char *get = action[!!peer];
> +   int ret;
> +
> +   uic_cmd.command = peer ?
> +   UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET;
> +   uic_cmd.argument1 = attr_sel;
> +
> +   ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
> +   if (ret) {
> +   dev_err(hba->dev, "%s: attr-id 0x%x error code %d\n",
> +   get, GET_UIC_ATTR_ID(attr_sel), ret);
> +   goto out;
> +   }
> +
> +   if (mib_val)
> +   *mib_val = uic_cmd.argument3;
> +out:
> +   return ret;
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_dme_get_attr);
> +
> +/**
>   * ufshcd_make_hba_operational - Make UFS controller operational
>   * @hba: per adapter instance
>   *
> @@ -1538,6 +1624,8 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba)
> if (hba->active_uic_cmd) {
> hba->active_uic_cmd->argument2 |=
> ufshcd_get_uic_cmd_result(hba);
> +   hba->active_uic_cmd->argument3 =
> +   ufshcd_get_dme_attr_val(hba);
> complete(&hba->active_uic_cmd->done);
> }
>  }
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 974bd07..dabd29c 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -217,6 +217,11 @@ int ufshcd_init(struct device *, struct ufs_hba ** , 
> void __iomem * ,
> unsigned int);
>  void ufshcd_remove(struct ufs_hba *);
>
> +extern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
> +  u8 attr_set, u32 mib_val, u8 peer);
>

Re: [PATCH v4 1/6] scsi: ufs: wrap the i/o access operations

2013-05-08 Thread Santosh Y
On Thu, May 9, 2013 at 12:09 PM, Seungwon Jeon  wrote:
> On Thursday, May 09, 2013 Santosh wrote:
>> > There are two patches remained. These are applied with your final comments.
>> > Do you have any idea?
>> > [PATCH v4 5/6] scsi: ufs: add dme configuration primitives
>> > [PATCH v4 6/6] scsi: ufs: add dme control primitives
>> >
>>
>> Since there is no use case for these implementations yet, except for
>> ufshcd_get_dme_attr_val(), as per James's suggestion
>> [http://www.mail-archive.com/linux-scsi@vger.kernel.org/msg20207.html]
>> I did not ACK the patches.
>> The same patches can be used to implement related features and resubmit 
>> later.
> I respect your decision. But I have another opinion.
> The remained patches are basic operations which should be supported by ufshcd.
> Especially, dme_set/set will be used in vender specific part of host 
> controller rather than in ufshcd itself.
> And above all, Maya Erez completed to test and reported working fine.
> If these patches are merged this time, it would be helpful to various hosts.
>

I'm ok with merging these patches if James is fine with it. I will ACK
the patches.

-- 
~Santosh
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH v4 1/6] scsi: ufs: wrap the i/o access operations

2013-05-08 Thread Seungwon Jeon
On Thursday, May 09, 2013 Santosh wrote:
> > There are two patches remained. These are applied with your final comments.
> > Do you have any idea?
> > [PATCH v4 5/6] scsi: ufs: add dme configuration primitives
> > [PATCH v4 6/6] scsi: ufs: add dme control primitives
> >
> 
> Since there is no use case for these implementations yet, except for
> ufshcd_get_dme_attr_val(), as per James's suggestion
> [http://www.mail-archive.com/linux-scsi@vger.kernel.org/msg20207.html]
> I did not ACK the patches.
> The same patches can be used to implement related features and resubmit later.
I respect your decision. But I have another opinion.
The remained patches are basic operations which should be supported by ufshcd.
Especially, dme_set/set will be used in vender specific part of host controller 
rather than in ufshcd itself.
And above all, Maya Erez completed to test and reported working fine.
If these patches are merged this time, it would be helpful to various hosts.

Thanks,
Seungwon Jeon
> 
> --
> ~Santosh
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH V2] scsi: ufs: Add fDeviceInit set flag during initialization

2013-05-08 Thread Dolev Raviv
>> + */
>> +int ufshcd_query_request(struct ufs_hba *hba,
>> +   struct ufs_query_req *query,
>> +   u8 *descriptor,
>> +   struct ufs_query_res *response,
>> +   int timeout,
>> +   int retries)
>> +{
>> +   struct scsi_device *sdev;
>> +   u8 cmd[UFS_QUERY_CMD_SIZE] = {0};
>> +   int result;
>> +   bool sdev_lookup = true;
>> +
>> +   if (!hba || !query || !response) {
>> +   dev_err(hba->dev,
>
> Please fix the static checker warnings mentioned by Dan in the previous
> mail.
> Re-base it on Seungwon's V4 patch series and you can add my Acked-by:
> Santosh Y 
>

The fix is ready.
I have to base it on top of Sujit's patch since it is inserted in the flow
he introduced.

>
>
> --
> ~Santosh
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

-- 
Dolev
-- 
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation



--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[ANNOUNCE] lsscsi version 0.27 released

2013-05-08 Thread Douglas Gilbert

lsscsi is a command line utility that probes sysfs in Linux
2.6 and 3 series kernels in order to list information about
SCSI devices and SCSI hosts. Both a compact format which is
one line per device and a "classic" format (like the output
of 'cat /proc/scsi/scsi') are supported.

Version 0.27 is available at:
http://sg.danny.cz/scsi/lsscsi.html
More information can be found on that page including examples
plus a Download and Build information section containing
tarballs, rpm and deb packages.


ChangeLog:
Version 0.27 2013/05/08 [svn: r111]
  - rework buffer handling for systems with many disks
  - add --lunhex option for displaying LUNs in hex
  - accept LUNs from sysfs as large as a 64 bit unsigned
decimal number (largest was signed 32 bit decimal)
  - accept LSSCSI_LUNHEX_OPT environment variable
  - add --scsi_id option for /dev/disk/by-id/scsi*

Version 0.26 2012/01/31 [svn: r97]


Doug Gilbert
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 1/6] scsi: ufs: wrap the i/o access operations

2013-05-08 Thread Santosh Y
> There are two patches remained. These are applied with your final comments.
> Do you have any idea?
> [PATCH v4 5/6] scsi: ufs: add dme configuration primitives
> [PATCH v4 6/6] scsi: ufs: add dme control primitives
>

Since there is no use case for these implementations yet, except for
ufshcd_get_dme_attr_val(), as per James's suggestion
[http://www.mail-archive.com/linux-scsi@vger.kernel.org/msg20207.html]
I did not ACK the patches.
The same patches can be used to implement related features and resubmit later.

-- 
~Santosh
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] [SCSI] fnic: fix error return code in fnic_probe()

2013-05-08 Thread Wei Yongjun
From: Wei Yongjun 

Fix to return -ENOMEM in the mempool_create_slab_pool() error handling
case instead of 0, as done elsewhere in this function.

Signed-off-by: Wei Yongjun 
---
 drivers/scsi/fnic/fnic_main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 5f09d18..0523322 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -605,6 +605,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct 
pci_device_id *ent)
for (i = 0; i < FNIC_IO_LOCKS; i++)
spin_lock_init(&fnic->io_req_lock[i]);
 
+   err = -ENOMEM;
fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache);
if (!fnic->io_req_pool)
goto err_out_free_resources;

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] [SCSI] sd: fix error return code in sd_probe()

2013-05-08 Thread Wei Yongjun
From: Wei Yongjun 

Fix to return a negative error code in the device add error handling
case instead of 0, as done elsewhere in this function.

Signed-off-by: Wei Yongjun 
---
 drivers/scsi/sd.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 82910cc..99f07e92 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2944,7 +2944,8 @@ static int sd_probe(struct device *dev)
sdkp->dev.class = &sd_disk_class;
dev_set_name(&sdkp->dev, dev_name(dev));
 
-   if (device_add(&sdkp->dev))
+   error = device_add(&sdkp->dev);
+   if (error)
goto out_free_index;
 
get_device(dev);

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH v4 1/6] scsi: ufs: wrap the i/o access operations

2013-05-08 Thread Seungwon Jeon
On Thursday, May 09, 2013, Santosh Y wrote:
> On Wed, May 8, 2013 at 2:11 PM, Seungwon Jeon  wrote:
> > Simplify operations with hiding mmio_base.
> >
> > Signed-off-by: Seungwon Jeon 
> > Tested-by: Maya Erez 
> > ---
> >  drivers/scsi/ufs/ufshcd.c |  105 
> > +++--
> >  drivers/scsi/ufs/ufshcd.h |7 +++-
> >  2 files changed, 50 insertions(+), 62 deletions(-)
> >
> Hi Seungwon,
> I could apply your test patch without any issues but I still get
> "fatal: cannot convert from ks_c_5601-1987 to UTF-8" with V4 patch
> series.
> At this point I'm confused :-| not sure if the problem is the
> character set or something else...
Hi Santosh,
You got a pass with my test one before v4. It's strange.

Hi James,
Please let me know, if you have a same problem.
I guess I should change mail sender.

> 
> 
> Hi James,
> Please consider Acked-by: Santosh Y , if you are
> able to apply the patches.
Thank you for your ack.
There are two patches remained. These are applied with your final comments.
Do you have any idea?
[PATCH v4 5/6] scsi: ufs: add dme configuration primitives
[PATCH v4 6/6] scsi: ufs: add dme control primitives

Thanks,
Seungwon Jeon

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[patch] [SCSI] pm80xx: missing break statement in mpi_sata_completion()

2013-05-08 Thread Dan Carpenter
Smatch discovered a missing break statement here.

Signed-off-by: Dan Carpenter 

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 670998a..6c0470e 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -2021,6 +2021,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+   break;
default:
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("Unknown status 0x%x\n", status));
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


re: [SCSI] pm80xx: NCQ error handling changes

2013-05-08 Thread Dan Carpenter
Hello Sakthivel K,

This is a semi-automatic email about new static checker warnings.

The patch 1cde970c1025: "[SCSI] pm80xx: NCQ error handling changes"
from Mar 19, 2013, leads to the following Smatch complaint:

drivers/scsi/pm8001/pm8001_hwi.c:4393 pm8001_chip_sata_req()
 warn: variable dereferenced before check 'pm8001_ha_dev' (see line 
4362)

drivers/scsi/pm8001/pm8001_hwi.c
  4361  sata_cmd.tag = cpu_to_le32(tag);
  4362  sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
 ^
Old dereference.

  4363  sata_cmd.data_len = cpu_to_le32(task->total_xfer_len);
  4364  sata_cmd.ncqtag_atap_dir_m =
  4365  cpu_to_le32(((ncg_tag & 0xff)<<16)|((ATAP & 0x3f) << 
10) | dir);
  4366  sata_cmd.sata_fis = task->ata_task.fis;
  4367  if (likely(!task->ata_task.device_control_reg_update))
  4368  sata_cmd.sata_fis.flags |= 0x80;/* C=1: update ATA cmd 
reg */
  4369  sata_cmd.sata_fis.flags &= 0xF0;/* PM_PORT field shall be 0 */
  4370  /* fill in PRD (scatter/gather) table, if any */
  4371  if (task->num_scatter > 1) {
  4372  pm8001_chip_make_sg(task->scatter, ccb->n_elem, 
ccb->buf_prd);
  4373  phys_addr = ccb->ccb_dma_handle +
  4374  offsetof(struct pm8001_ccb_info, 
buf_prd[0]);
  4375  sata_cmd.addr_low = lower_32_bits(phys_addr);
  4376  sata_cmd.addr_high = upper_32_bits(phys_addr);
  4377  sata_cmd.esgl = cpu_to_le32(1 << 31);
  4378  } else if (task->num_scatter == 1) {
  4379  u64 dma_addr = sg_dma_address(task->scatter);
  4380  sata_cmd.addr_low = lower_32_bits(dma_addr);
  4381  sata_cmd.addr_high = upper_32_bits(dma_addr);
  4382  sata_cmd.len = cpu_to_le32(task->total_xfer_len);
  4383  sata_cmd.esgl = 0;
  4384  } else if (task->num_scatter == 0) {
  4385  sata_cmd.addr_low = 0;
  4386  sata_cmd.addr_high = 0;
  4387  sata_cmd.len = cpu_to_le32(task->total_xfer_len);
  4388  sata_cmd.esgl = 0;
  4389  }
  4390  
  4391  /* Check for read log for failed drive and return */
  4392  if (sata_cmd.sata_fis.command == 0x2f) {
  4393  if (pm8001_ha_dev && ((pm8001_ha_dev->id & 
NCQ_READ_LOG_FLAG) ||
^
New check.  Probably this check is unneeded and can be removed.

  4394  (pm8001_ha_dev->id & NCQ_ABORT_ALL_FLAG) ||
  4395  (pm8001_ha_dev->id & NCQ_2ND_RLE_FLAG))) {

regards,
dan carpenter
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH V4 1/1] scsi: ufs: Add support for sending NOP OUT UPIU

2013-05-08 Thread Santosh Y
On Wed, May 8, 2013 at 3:20 PM, 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.
>
> Signed-off-by: Sujit Reddy Thumma 
>
> ---
> v4:
>- Removed readl_poll_timeout and replaced with wait logic
>- additional checks for completion
> v3:
>- minor bug fix in error path
> v2:
>- fixed INTERNAL_CMD_TAG check in readl_poll_timeout
>- minor cleanup from v1
>- rebased on Seungwon Jeon's UFS V3 patchset
> ---
>  drivers/scsi/ufs/ufshcd.c |  197 ++--
>  drivers/scsi/ufs/ufshcd.h |4 +
>  2 files changed, 192 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 3607ffb..ded770d 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -44,6 +44,13 @@
>  /* UIC command timeout, unit: ms */
>  #define UIC_CMD_TIMEOUT500
>
> +/* 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 */
> +/* Reserved tag for internal commands */
> +#define INTERNAL_CMD_TAG   0
> +
>  enum {
> UFSHCD_MAX_CHANNEL  = 0,
> UFSHCD_MAX_ID   = 1,
> @@ -72,6 +79,39 @@ enum {
> INT_AGGR_CONFIG,
>  };
>
> +/*
> + * ufshcd_wait_for_register - wait for register value to change
> + * @hba - per-adapter interface
> + * @reg - mmio register offset
> + * @mask - mask to apply to read register value
> + * @val - wait condition
> + * @interval_us - polling interval in microsecs
> + * @timeout_ms - timeout in millisecs
> + *
> + * Returns final register value after iteration
> + */
> +static u32 ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
> +   u32 val, unsigned long interval_us, unsigned long timeout_ms)
> +{
> +   u32 tmp;
> +   ktime_t start;
> +   unsigned long diff;
> +
> +   tmp = ufshcd_readl(hba, reg);
> +
> +   start = ktime_get();
> +   while ((tmp & mask) == val) {
> +   /* wakeup within 50us of expiry */
> +   usleep_range(interval_us, interval_us + 50);
> +   tmp = ufshcd_readl(hba, reg);
> +   diff = ktime_to_ms(ktime_sub(ktime_get(), start));
> +   if (diff > timeout_ms)
> +   break;
> +   }
> +
> +   return tmp;
> +}
> +
>  /**
>   * ufshcd_get_intr_mask - Get the interrupt bit mask
>   * @hba - Pointer to adapter instance
> @@ -630,7 +670,7 @@ static void ufshcd_prepare_req_desc(struct ufshcd_lrb 
> *lrbp, u32 *upiu_flags)
>  {
> struct utp_transfer_req_desc *req_desc = lrbp->utr_descriptor_ptr;
> enum dma_data_direction cmd_dir =
> -   lrbp->cmd->sc_data_direction;
> +   lrbp->cmd ? lrbp->cmd->sc_data_direction : DMA_NONE;
> u32 data_direction;
> u32 dword_0;
>
> @@ -647,6 +687,8 @@ static void ufshcd_prepare_req_desc(struct ufshcd_lrb 
> *lrbp, u32 *upiu_flags)
>
> dword_0 = data_direction | (lrbp->command_type
> << UPIU_COMMAND_TYPE_OFFSET);
> +   if (lrbp->intr_cmd)
> +   dword_0 |= UTP_REQ_DESC_INT_CMD;
>
> /* Transfer request descriptor header fields */
> req_desc->header.dword_0 = cpu_to_le32(dword_0);
> @@ -735,6 +777,18 @@ static void ufshcd_prepare_utp_query_req_upiu(struct 
> ufs_hba *hba,
>
>  }
>
> +static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp)
> +{
> +   struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
> +
> +   memset(ucd_req_ptr, 0, sizeof(struct utp_upiu_req));
> +
> +   /* command descriptor fields */
> +   ucd_req_ptr->header.dword_0 =
> +   UPIU_HEADER_DWORD(
> +   UPIU_TRANSACTION_NOP_OUT, 0, 0, lrbp->task_tag);
> +}
> +
>  /**
>   * ufshcd_compose_upiu - form UFS Protocol Information Unit(UPIU)
>   * @hba - UFS hba
> @@ -749,11 +803,13 @@ static int ufshcd_compose_upiu(struct ufs_hba *hba, 
> struct ufshcd_lrb *lrbp)
> case UTP_CMD_TYPE_SCSI:
> case UTP_CMD_TYPE_DEV_MANAGE:
> ufshcd_prepare_req_desc(lrbp, &upiu_flags);
> -   if (lrbp->command_type == UTP_CMD_TYPE_SCSI)
> +   if (lrbp->cmd && lrbp->command_type == UTP_CMD_TYPE_SCSI)
> ufshcd_prepare_utp_scsi_cmd_upiu(lrbp, upiu_flags);
> -   else
> +   else if (lrbp->cmd && ufshcd_is_query_req(lrbp))
> ufshcd_prepare_utp_query_req_upiu(hba, lrbp,
>   

Re: [PATCH V2] scsi: ufs: Add fDeviceInit set flag during initialization

2013-05-08 Thread Santosh Y
> + */
> +int ufshcd_query_request(struct ufs_hba *hba,
> +   struct ufs_query_req *query,
> +   u8 *descriptor,
> +   struct ufs_query_res *response,
> +   int timeout,
> +   int retries)
> +{
> +   struct scsi_device *sdev;
> +   u8 cmd[UFS_QUERY_CMD_SIZE] = {0};
> +   int result;
> +   bool sdev_lookup = true;
> +
> +   if (!hba || !query || !response) {
> +   dev_err(hba->dev,

Please fix the static checker warnings mentioned by Dan in the previous mail.
Re-base it on Seungwon's V4 patch series and you can add my Acked-by:
Santosh Y 

> +   "%s: NULL pointer hba = %p, query = %p response = 
> %p\n",
> +   __func__, hba, query, response);
> +   return -EINVAL;
> +   }
> +
> +   /*
> +* A SCSI command structure is composed from opcode at the
> +* begining and 0 at the end.
> +*/
> +   cmd[0] = UFS_QUERY_RESERVED_SCSI_CMD;
> +
> +   /* extracting the SCSI Device */
> +   sdev = scsi_device_lookup(hba->host, 0, 0, 0);
> +   if (!sdev) {
> +   /**
> +* There are some Query Requests that are sent during device
> +* initialization, this happens before the scsi device was
> +* initialized. If there is no scsi device, we generate a
> +* temporary device to allow the Query Request flow.
> +*/
> +   sdev_lookup = false;
> +   sdev = scsi_get_host_dev(hba->host);
> +   }
> +
> +   if (!sdev) {
> +   dev_err(hba->dev, "%s: Could not fetch scsi device\n",
> +   __func__);
> +   return -ENODEV;
> +   }
> +
> +   mutex_lock(&hba->query.lock_ufs_query);
> +   hba->query.request = query;
> +   hba->query.descriptor = descriptor;
> +   hba->query.response = response;
> +
> +   /* wait until request is completed */
> +   result = scsi_execute(sdev, cmd, DMA_NONE, NULL, 0, NULL,
> +   timeout, retries, 0, NULL);
> +   if (result) {
> +   dev_err(hba->dev,
> +   "%s: Query with opcode 0x%x, failed with result %d\n",
> +   __func__, query->upiu_req.opcode, result);
> +   result = -EIO;
> +   }
> +
> +   hba->query.request = NULL;
> +   hba->query.descriptor = NULL;
> +   hba->query.response = NULL;
> +   mutex_unlock(&hba->query.lock_ufs_query);
> +
> +   /* Releasing scsi device resource */
> +   if (sdev_lookup)
> +   scsi_device_put(sdev);
> +   else
> +   scsi_free_host_dev(sdev);
> +
> +   return result;
> +}
> +
> +/**
> + * ufshcd_query_flag() - Helper function for composing flag query requests
> + * hba: per-adapter instance
> + * query_opcode: flag query to perform
> + * idn: flag idn to access
> + * flag_res: the flag value after the query request completes
> + *
> + * Returns 0 for success, non-zero in case of failure
> + */
> +int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
> +   enum flag_idn idn, bool *flag_res)
> +{
> +   struct ufs_query_req query = {0};
> +   struct ufs_query_res response = {0};
> +   int err;
> +
> +   switch (opcode) {
> +   case UPIU_QUERY_OPCODE_SET_FLAG:
> +   case UPIU_QUERY_OPCODE_CLEAR_FLAG:
> +   case UPIU_QUERY_OPCODE_TOGGLE_FLAG:
> +   query.query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST;
> +   break;
> +   case UPIU_QUERY_OPCODE_READ_FLAG:
> +   query.query_func = UPIU_QUERY_FUNC_STANDARD_READ_REQUEST;
> +   break;
> +   default:
> +   dev_err(hba->dev,
> +   "%s: Expected query flag opcode but got = %d\n",
> +   __func__, opcode);
> +   err = -EINVAL;
> +   goto out;
> +   }
> +   query.upiu_req.opcode = opcode;
> +   query.upiu_req.idn = idn;
> +
> +   /* Send query request */
> +   err = send_query_request(hba, &query, NULL, &response);
> +
> +   if (err) {
> +   dev_err(hba->dev,
> +   "%s: Sending flag query for idn %d failed, err = 
> %d\n",
> +   __func__, idn, err);
> +   goto out;
> +   }
> +
> +   *flag_res = (response.upiu_res.value & MASK_QUERY_UPIU_FLAG_LOC) & 
> 0x1;
> +
> +out:
> +   return err;
> +}
> +
> +/**
>   * ufshcd_memory_alloc - allocate memory for host memory space data 
> structures
>   * @hba: per adapter instance
>   *
> @@ -1324,6 +1488,44 @@ out:
>  }
>
>  /**
> + * ufshcd_validate_device_init() - checks device readines
> + * hba: per-adapter instance
> + *
> + * Set fDeviceInit flag, than, query the flag untill the device clears the
> + * flag.
> + */
> +static int ufshcd_val

Re: [PATCH v4 4/6] scsi: ufs: rework link start-up process

2013-05-08 Thread Santosh Y
On Wed, May 8, 2013 at 2:12 PM, Seungwon Jeon  wrote:
> Link start-up requires long time with multiphase handshakes
> between UFS host and device. This affects driver's probe time.
> This patch let link start-up run asynchronously. Link start-up
> will be executed at the end of prove separately.
> Along with this change, the following is worked.
>
> Defined completion time of uic command to avoid a permanent wait.
> Added mutex to guarantee of uic command at a time.
> Adapted some sequence of controller initialization after link statup
> according to HCI standard.
>
> Signed-off-by: Seungwon Jeon 
> Signed-off-by: Sujit Reddy Thumma 
> Tested-by: Maya Erez 
> ---
> Change in v4:
> - Addressed late interrupt case (Sujit).
> - Move print message in link startup (Maya).
>
>  drivers/scsi/ufs/ufshcd.c |  295 ++--
>  drivers/scsi/ufs/ufshcd.h |   10 +-
>  2 files changed, 208 insertions(+), 97 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index e04c74e..8363b92 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -33,11 +33,15 @@
>   * this program.
>   */
>
> +#include 
> +
>  #include "ufshcd.h"
>
>  #define UFSHCD_ENABLE_INTRS(UTP_TRANSFER_REQ_COMPL |\
>  UTP_TASK_REQ_COMPL |\
>  UFSHCD_ERROR_MASK)
> +/* UIC command timeout, unit: ms */
> +#define UIC_CMD_TIMEOUT500
>
>  enum {
> UFSHCD_MAX_CHANNEL  = 0,
> @@ -401,24 +405,122 @@ static inline void ufshcd_hba_capabilities(struct 
> ufs_hba *hba)
>  }
>
>  /**
> - * ufshcd_send_uic_command - Send UIC commands to unipro layers
> + * ufshcd_ready_for_uic_cmd - Check if controller is ready
> + *to accept UIC commands
>   * @hba: per adapter instance
> - * @uic_command: UIC command
> + * Return true on success, else false
> + */
> +static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba)
> +{
> +   if (ufshcd_readl(hba, REG_CONTROLLER_STATUS) & UIC_COMMAND_READY)
> +   return true;
> +   else
> +   return false;
> +}
> +
> +/**
> + * ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers
> + * @hba: per adapter instance
> + * @uic_cmd: UIC command
> + *
> + * Mutex must be held.
>   */
>  static inline void
> -ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd)
> +ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
>  {
> +   WARN_ON(hba->active_uic_cmd);
> +
> +   hba->active_uic_cmd = uic_cmd;
> +
> /* Write Args */
> -   ufshcd_writel(hba, uic_cmnd->argument1, REG_UIC_COMMAND_ARG_1);
> -   ufshcd_writel(hba, uic_cmnd->argument2, REG_UIC_COMMAND_ARG_2);
> -   ufshcd_writel(hba, uic_cmnd->argument3, REG_UIC_COMMAND_ARG_3);
> +   ufshcd_writel(hba, uic_cmd->argument1, REG_UIC_COMMAND_ARG_1);
> +   ufshcd_writel(hba, uic_cmd->argument2, REG_UIC_COMMAND_ARG_2);
> +   ufshcd_writel(hba, uic_cmd->argument3, REG_UIC_COMMAND_ARG_3);
>
> /* Write UIC Cmd */
> -   ufshcd_writel(hba, uic_cmnd->command & COMMAND_OPCODE_MASK,
> +   ufshcd_writel(hba, uic_cmd->command & COMMAND_OPCODE_MASK,
>   REG_UIC_COMMAND);
>  }
>
>  /**
> + * ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command
> + * @hba: per adapter instance
> + * @uic_command: UIC command
> + *
> + * Must be called with mutex held.
> + * Returns 0 only if success.
> + */
> +static int
> +ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
> +{
> +   int ret;
> +   unsigned long flags;
> +
> +   if (wait_for_completion_timeout(&uic_cmd->done,
> +   msecs_to_jiffies(UIC_CMD_TIMEOUT)))
> +   ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
> +   else
> +   ret = -ETIMEDOUT;
> +
> +   spin_lock_irqsave(hba->host->host_lock, flags);
> +   hba->active_uic_cmd = NULL;
> +   spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> +   return ret;
> +}
> +
> +/**
> + * __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
> + * @hba: per adapter instance
> + * @uic_cmd: UIC command
> + *
> + * Identical to ufshcd_send_uic_cmd() expect mutex. Must be called
> + * with mutex held.
> + * Returns 0 only if success.
> + */
> +static int
> +__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
> +{
> +   int ret;
> +   unsigned long flags;
> +
> +   if (!ufshcd_ready_for_uic_cmd(hba)) {
> +   dev_err(hba->dev,
> +   "Controller not ready to accept UIC commands\n");
> +   return -EIO;
> +   }
> +
> +   init_completion(&uic_cmd->done);
> +
> +   spin_lock_irqsave(hba->host->host_lock, flags);
> +   ufshcd_dispatch_uic_cmd(hba, uic_cmd);
> +   spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> +   ret = ufshcd

Re: [PATCH v4 3/6] scsi: ufs: fix interrupt status clears

2013-05-08 Thread Santosh Y
On Wed, May 8, 2013 at 2:11 PM, Seungwon Jeon  wrote:
> There is no need to check the version to clear
> the interrupt status. And the order is changed
> prior to actual handling.
>
> Signed-off-by: Seungwon Jeon 
> Tested-by: Maya Erez 
> ---
>  drivers/scsi/ufs/ufshcd.c |5 +
>  1 files changed, 1 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index feaf221..e04c74e 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -1582,11 +1582,8 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)
> intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
>
> if (intr_status) {
> +   ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
> ufshcd_sl_intr(hba, intr_status);
> -
> -   /* If UFSHCI 1.0 then clear interrupt status register */
> -   if (hba->ufs_version == UFSHCI_VERSION_10)
> -   ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
> retval = IRQ_HANDLED;
> }
> spin_unlock(hba->host->host_lock);
> --
> 1.7.0.4
>
>

Acked-by: Santosh Y 


-- 
~Santosh
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 2/6] scsi: ufs: amend interrupt configuration

2013-05-08 Thread Santosh Y
On Wed, May 8, 2013 at 2:11 PM, Seungwon Jeon  wrote:
> It makes interrupt setting more flexible especially
> for disabling. And wrong bit mask is fixed for ver 1.0.
> [17:16] is added for mask.
>
> Signed-off-by: Seungwon Jeon 
> Tested-by: Maya Erez 
> ---
>  drivers/scsi/ufs/ufshcd.c |   84 +++-
>  drivers/scsi/ufs/ufshcd.h |4 +-
>  drivers/scsi/ufs/ufshci.h |5 ++-
>  3 files changed, 64 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index cf7c8e4..feaf221 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -35,6 +35,10 @@
>
>  #include "ufshcd.h"
>
> +#define UFSHCD_ENABLE_INTRS(UTP_TRANSFER_REQ_COMPL |\
> +UTP_TASK_REQ_COMPL |\
> +UFSHCD_ERROR_MASK)
> +
>  enum {
> UFSHCD_MAX_CHANNEL  = 0,
> UFSHCD_MAX_ID   = 1,
> @@ -64,6 +68,20 @@ enum {
>  };
>
>  /**
> + * ufshcd_get_intr_mask - Get the interrupt bit mask
> + * @hba - Pointer to adapter instance
> + *
> + * Returns interrupt bit mask per version
> + */
> +static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba)
> +{
> +   if (hba->ufs_version == UFSHCI_VERSION_10)
> +   return INTERRUPT_MASK_ALL_VER_10;
> +   else
> +   return INTERRUPT_MASK_ALL_VER_11;
> +}
> +
> +/**
>   * ufshcd_get_ufs_version - Get the UFS version supported by the HBA
>   * @hba - Pointer to adapter instance
>   *
> @@ -441,25 +459,45 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp)
>  }
>
>  /**
> - * ufshcd_int_config - enable/disable interrupts
> + * ufshcd_enable_intr - enable interrupts
>   * @hba: per adapter instance
> - * @option: interrupt option
> + * @intrs: interrupt bits
>   */
> -static void ufshcd_int_config(struct ufs_hba *hba, u32 option)
> +static void ufshcd_enable_intr(struct ufs_hba *hba, u32 intrs)
>  {
> -   switch (option) {
> -   case UFSHCD_INT_ENABLE:
> -   ufshcd_writel(hba, hba->int_enable_mask, 
> REG_INTERRUPT_ENABLE);
> -   break;
> -   case UFSHCD_INT_DISABLE:
> -   if (hba->ufs_version == UFSHCI_VERSION_10)
> -   ufshcd_writel(hba, INTERRUPT_DISABLE_MASK_10,
> - REG_INTERRUPT_ENABLE);
> -   else
> -   ufshcd_writel(hba, INTERRUPT_DISABLE_MASK_11,
> - REG_INTERRUPT_ENABLE);
> -   break;
> +   u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
> +
> +   if (hba->ufs_version == UFSHCI_VERSION_10) {
> +   u32 rw;
> +   rw = set & INTERRUPT_MASK_RW_VER_10;
> +   set = rw | ((set ^ intrs) & intrs);
> +   } else {
> +   set |= intrs;
> +   }
> +
> +   ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
> +}
> +
> +/**
> + * ufshcd_disable_intr - disable interrupts
> + * @hba: per adapter instance
> + * @intrs: interrupt bits
> + */
> +static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs)
> +{
> +   u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
> +
> +   if (hba->ufs_version == UFSHCI_VERSION_10) {
> +   u32 rw;
> +   rw = (set & INTERRUPT_MASK_RW_VER_10) &
> +   ~(intrs & INTERRUPT_MASK_RW_VER_10);
> +   set = rw | ((set & intrs) & ~INTERRUPT_MASK_RW_VER_10);
> +
> +   } else {
> +   set &= ~intrs;
> }
> +
> +   ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
>  }
>
>  /**
> @@ -946,8 +984,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
> uic_cmd->argument3 = 0;
>
> /* enable UIC related interrupts */
> -   hba->int_enable_mask |= UIC_COMMAND_COMPL;
> -   ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
> +   ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
>
> /* sending UIC commands to controller */
> ufshcd_send_uic_command(hba, uic_cmd);
> @@ -994,13 +1031,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba 
> *hba)
> }
>
> /* Enable required interrupts */
> -   hba->int_enable_mask |= (UTP_TRANSFER_REQ_COMPL |
> -UIC_ERROR |
> -UTP_TASK_REQ_COMPL |
> -DEVICE_FATAL_ERROR |
> -CONTROLLER_FATAL_ERROR |
> -SYSTEM_BUS_FATAL_ERROR);
> -   ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
> +   ufshcd_enable_intr(hba, UFSHCD_ENABLE_INTRS);
>
> /* Configure interrupt aggregation */
> ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG);
> @@ -1828,7 +1859,7 @@ static void ufshcd_hba_free(struct ufs_hba *hba)
>  void ufshcd_remove(struct ufs_hba *hba)
>  {
> /* disable interrupts */
> -   ufshcd_int_config(hba, UFSHCD_INT_DISABLE);
> +   ufshcd_disable_intr(hba, hba->intr_mask);
>
> 

Re: [PATCH v4 1/6] scsi: ufs: wrap the i/o access operations

2013-05-08 Thread Santosh Y
On Wed, May 8, 2013 at 2:11 PM, Seungwon Jeon  wrote:
> Simplify operations with hiding mmio_base.
>
> Signed-off-by: Seungwon Jeon 
> Tested-by: Maya Erez 
> ---
>  drivers/scsi/ufs/ufshcd.c |  105 
> +++--
>  drivers/scsi/ufs/ufshcd.h |7 +++-
>  2 files changed, 50 insertions(+), 62 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index f244812..cf7c8e4 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -71,7 +71,7 @@ enum {
>   */
>  static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba)
>  {
> -   return readl(hba->mmio_base + REG_UFS_VERSION);
> +   return ufshcd_readl(hba, REG_UFS_VERSION);
>  }
>
>  /**
> @@ -130,8 +130,7 @@ static inline int ufshcd_get_tm_free_slot(struct ufs_hba 
> *hba)
>   */
>  static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos)
>  {
> -   writel(~(1 << pos),
> -   (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_CLEAR));
> +   ufshcd_writel(hba, ~(1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR);
>  }
>
>  /**
> @@ -165,7 +164,7 @@ static inline int ufshcd_get_lists_status(u32 reg)
>   */
>  static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba)
>  {
> -   return readl(hba->mmio_base + REG_UIC_COMMAND_ARG_2) &
> +   return ufshcd_readl(hba, REG_UIC_COMMAND_ARG_2) &
>MASK_UIC_COMMAND_RESULT;
>  }
>
> @@ -238,18 +237,15 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option)
>  {
> switch (option) {
> case INT_AGGR_RESET:
> -   writel((INT_AGGR_ENABLE |
> -   INT_AGGR_COUNTER_AND_TIMER_RESET),
> -   (hba->mmio_base +
> -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL));
> +   ufshcd_writel(hba, INT_AGGR_ENABLE |
> + INT_AGGR_COUNTER_AND_TIMER_RESET,
> + REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL);
> break;
> case INT_AGGR_CONFIG:
> -   writel((INT_AGGR_ENABLE |
> -   INT_AGGR_PARAM_WRITE |
> -   INT_AGGR_COUNTER_THRESHOLD_VALUE |
> -   INT_AGGR_TIMEOUT_VALUE),
> -   (hba->mmio_base +
> -REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL));
> +   ufshcd_writel(hba, INT_AGGR_ENABLE | INT_AGGR_PARAM_WRITE |
> + INT_AGGR_COUNTER_THRESHOLD_VALUE |
> + INT_AGGR_TIMEOUT_VALUE,
> + REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL);
> break;
> }
>  }
> @@ -262,12 +258,10 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option)
>   */
>  static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)
>  {
> -   writel(UTP_TASK_REQ_LIST_RUN_STOP_BIT,
> -  (hba->mmio_base +
> -   REG_UTP_TASK_REQ_LIST_RUN_STOP));
> -   writel(UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT,
> -  (hba->mmio_base +
> -   REG_UTP_TRANSFER_REQ_LIST_RUN_STOP));
> +   ufshcd_writel(hba, UTP_TASK_REQ_LIST_RUN_STOP_BIT,
> + REG_UTP_TASK_REQ_LIST_RUN_STOP);
> +   ufshcd_writel(hba, UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT,
> + REG_UTP_TRANSFER_REQ_LIST_RUN_STOP);
>  }
>
>  /**
> @@ -276,7 +270,7 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba 
> *hba)
>   */
>  static inline void ufshcd_hba_start(struct ufs_hba *hba)
>  {
> -   writel(CONTROLLER_ENABLE , (hba->mmio_base + REG_CONTROLLER_ENABLE));
> +   ufshcd_writel(hba, CONTROLLER_ENABLE, REG_CONTROLLER_ENABLE);
>  }
>
>  /**
> @@ -287,7 +281,7 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba)
>   */
>  static inline int ufshcd_is_hba_active(struct ufs_hba *hba)
>  {
> -   return (readl(hba->mmio_base + REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
> +   return (ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
>  }
>
>  /**
> @@ -299,8 +293,7 @@ static inline
>  void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
>  {
> __set_bit(task_tag, &hba->outstanding_reqs);
> -   writel((1 << task_tag),
> -  (hba->mmio_base + REG_UTP_TRANSFER_REQ_DOOR_BELL));
> +   ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
>  }
>
>  /**
> @@ -381,8 +374,7 @@ void ufshcd_copy_query_response(struct ufs_hba *hba, 
> struct ufshcd_lrb *lrbp)
>   */
>  static inline void ufshcd_hba_capabilities(struct ufs_hba *hba)
>  {
> -   hba->capabilities =
> -   readl(hba->mmio_base + REG_CONTROLLER_CAPABILITIES);
> +   hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES);
>
> /* nutrs and nutmrs are 0 based values */
> hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1;
> @@ -399,16 +391,13 @@ static inline void
>  ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd)
>  {
>   

[PATCH RESEND] qla2xxx: Update firmware link in Kconfig file.

2013-05-08 Thread Chad Dupuis
Hi James,

Can you apply this for inclusion in 3.10-rc?

Thanks,
Chad

Signed-off-by: Giridhar Malavali 
Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qla2xxx/Kconfig |4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
index 317a7fd..23d6072 100644
--- a/drivers/scsi/qla2xxx/Kconfig
+++ b/drivers/scsi/qla2xxx/Kconfig
@@ -24,7 +24,9 @@ config SCSI_QLA_FC
 
Firmware images can be retrieved from:
 
-   ftp://ftp.qlogic.com/outgoing/linux/firmware/
+   http://ldriver.qlogic.com/firmware/
+
+   They are also included in the linux-firmware tree as well.
 
 config TCM_QLA2XXX
tristate "TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode 
HBAs"
-- 
1.7.7


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH V2] scsi: ufs: Add fDeviceInit set flag during initialization

2013-05-08 Thread Dolev Raviv
Send fDeviceInit flag during device initialization. Than poll until the
device clears the flag. This step is required during the device
initialization process.
The flag set is used to communicate to the UFS device that it can complete
its initialization. The UFS device will then move from Boot W-LU READY
state to Device Initialization IN PROGRESS state. When the initialization
is complete the device will reset the fDeviceInit flag.

Signed-off-by: Dolev Raviv 
Signed-off-by: Sujit Reddy Thumma 

--- 
Changes for V2:
- Add the query sending api via SCSI from the original query patch

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 086ff03..742363d 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -107,8 +107,13 @@ enum {
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 {
+enum query_opcode {
UPIU_QUERY_OPCODE_NOP   = 0x0,
UPIU_QUERY_OPCODE_READ_DESC = 0x1,
UPIU_QUERY_OPCODE_WRITE_DESC= 0x2,
@@ -208,6 +213,9 @@ struct utp_upiu_query {
u32 reserved[2];
 };
 
+/* Expose the flag value from utp_upiu_query.value */
+#define MASK_QUERY_UPIU_FLAG_LOC 0xFF
+
 /**
  * struct utp_upiu_req - general upiu request structure
  * @header:UPIU header structure DW-0 to DW-2
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index bcdc576..7036550 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -51,6 +51,15 @@
 /* Reserved tag for internal commands */
 #define INTERNAL_CMD_TAG   0
 
+/* Query request standart retries */
+#define QUERY_REQ_RETRIES 10
+/* Query request standart timeout  in seconds */
+#define QUERY_REQ_TIMEOUT 5
+/* Send Query Requst with default parameters */
+#define send_query_request(ARG1, ARG2, ARG3, ARG4) \
+   ufshcd_query_request(ARG1, ARG2, ARG3, ARG4,\
+   QUERY_REQ_TIMEOUT, QUERY_REQ_RETRIES)
+
 enum {
UFSHCD_MAX_CHANNEL  = 0,
UFSHCD_MAX_ID   = 1,
@@ -887,6 +896,161 @@ out:
 }
 
 /**
+ *  ufshcd_query_request() - Entry point for issuing query request to a
+ *  ufs device.
+ *  @hba: ufs driver context
+ *  @query: params for query request
+ *  @descriptor: buffer for sending/receiving descriptor
+ *  @response: pointer to a buffer that will contain the response code and
+ *   response upiu
+ *  @timeout: time limit for the command in seconds
+ *  @retries: number of times to try executing the command
+ *
+ *  The query request is submitted to the same request queue as the rest of
+ *  the scsi commands passed to the UFS controller. In order to use this
+ *  queue, we need to receive a tag, same as all other commands. The tags
+ *  are issued from the block layer. To simulate a request from the block
+ *  layer, we use the same interface as the SCSI layer does when it issues
+ *  commands not generated by users. To distinguish a query request from
+ *  the SCSI commands, we use a vendor specific unused SCSI command
+ *  op-code. This op-code is not part of the SCSI command subset used in
+ *  UFS. In such way it is easy to check the command in the driver and
+ *  handle it appropriately.
+ *
+ *  All necessary fields for issuing a query and receiving its response are
+ *  stored in the UFS hba struct. We can use this method since we know
+ *  there is only one active query request at all times.
+ *
+ *  The request that will pass to the device is stored in "query" argument
+ *  passed to this function, while the "response" argument (which is output
+ *  field) will hold the query response from the device along with the
+ *  response code.
+ */
+int ufshcd_query_request(struct ufs_hba *hba,
+   struct ufs_query_req *query,
+   u8 *descriptor,
+   struct ufs_query_res *response,
+   int timeout,
+   int retries)
+{
+   struct scsi_device *sdev;
+   u8 cmd[UFS_QUERY_CMD_SIZE] = {0};
+   int result;
+   bool sdev_lookup = true;
+
+   if (!hba || !query || !response) {
+   dev_err(hba->dev,
+   "%s: NULL pointer hba = %p, query = %p response = %p\n",
+   __func__, hba, query, response);
+   return -EINVAL;
+   }
+
+   /*
+* A SCSI command structure is composed from opcode at the
+* begining and 0 at the end.
+*/
+   cmd[0] = UFS_QUERY_RESERVED_SCSI_CMD;
+
+   /* extracting the SCSI Device */
+   sdev = scsi_device_lookup(hba->host, 0, 0, 0);
+   if (!sdev) {
+   /**
+* There are some Query Requests that are sent during device
+* initialization, this happens before the scsi device was
+* initialized. If there is no scsi device, we generate a
+* t

Re: [PATCH v10 0/9] More device removal fixes

2013-05-08 Thread Joe Lawrence
On Sun, 07 Apr 2013 16:55:33 +0200
Bart Van Assche  wrote:

> Fix a few issues that can be triggered by removing a device:
> - Fix a race between starved list processing and device removal.
> - Avoid that a SCSI LLD callback can get invoked after
>scsi_remove_host() finished.
> - Speed up device removal by stopping error handling as soon as
>the SHOST_DEL or SHOST_DEL_RECOVERY state has been reached.
> - Save and restore the host_scribble field during error handling.
> 
> These patches have been tested on top of kernel v3.9-rc5.

Hi Bart,

I tested the patchset against 3.9 and ran surprise HBA device removals
during device initialization (3sec, 6sec, 12sec) while running IO out
to a multipath LUN and an MD RAID1 SAS pair.  No warnings in the logs
and everything looks consistent this morning.

Regards,

-- Joe
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH trivial] mvsas: fix build warning about enum comparisons

2013-05-08 Thread Kyle McMartin
On Tue, May 07, 2013 at 02:20:37PM -0700, James Bottomley wrote:
> On Tue, 2013-05-07 at 12:57 -0400, Kyle McMartin wrote:
> > device_type is a sas_device_type, not a sas_dev_type.
> 
> Heh, months ago, someone who submitted the same trivial but insufficient
> fix was asked to go and see if they could unify sas_device_type and
> sas_dev_type, which is the correct fix.  They were never heard from
> again.  I suppose that shows that if you want something doing properly,
> you should do it yourself.
> 

Woops, sorry James, I only looked at the last two months of archives for
mvsas patches.

Thanks for fixing this.

regards, Kyle
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] scsi: add put_device() after device_find_child()

2013-05-08 Thread Vikas Chaudhary

-Original Message-
From: Mike Christie 
Date: Monday 6 May 2013 10:36 PM
To: Zhao Hongjiang 
Cc: "jbottom...@parallels.com" , Ravi Anand
, Vikas , scsi

Subject: Re: [PATCH] scsi: add put_device() after device_find_child()

>On 05/06/2013 06:55 AM, Zhao Hongjiang wrote:
>> The qla4xxx_sysfs_ddb_add() function uses device_find_child() but it
>>does not drop
>> the reference of the retrieved child.
>> 
>> Signed-off-by: Zhao Hongjiang 
>> ---
>>  drivers/scsi/qla4xxx/ql4_os.c |1 +
>>  1 files changed, 1 insertions(+), 0 deletions(-)
>> 
>> diff --git a/drivers/scsi/qla4xxx/ql4_os.c
>>b/drivers/scsi/qla4xxx/ql4_os.c
>> index a47f999..b378d9e 100644
>> --- a/drivers/scsi/qla4xxx/ql4_os.c
>> +++ b/drivers/scsi/qla4xxx/ql4_os.c
>> @@ -5605,6 +5605,7 @@ static int qla4xxx_sysfs_ddb_add(struct Scsi_Host
>>*shost, const char *buf,
>>  ql4_printk(KERN_ERR, ha,
>> "%s: A non-persistent entry %s found\n",
>> __func__, dev->kobj.name);
>> +put_device(dev);
>>  goto exit_ddb_add;
>>  }
>>  
>> 
>
>Thanks for catching this. I messed up when reviewing it. For some dumb
>reason I thought it was not doing refcounting.
>
>I think there are a couple bugs from other similar functions. What about
>the attached patch? It is only compile tested. If it is ok, Vikas,
>please test.

We have tested this patch and it looks good in our testing.
I am resending this patch for inclusion with our next patch-set which I am
sending in next email.
Thanks for fixing this.

Acked-by: Vikas Chaudhary 

<>

Re: [PATCH v4 1/6] scsi: ufs: wrap the i/o access operations

2013-05-08 Thread merez
Hi,

I tested the new set of patches (v4 1-6) and it works.

Thanks,
Maya
> Simplify operations with hiding mmio_base.
>
> Signed-off-by: Seungwon Jeon 
> Tested-by: Maya Erez 
> ---
>  drivers/scsi/ufs/ufshcd.c |  105
> +++--
>  drivers/scsi/ufs/ufshcd.h |7 +++-
>  2 files changed, 50 insertions(+), 62 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index f244812..cf7c8e4 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -71,7 +71,7 @@ enum {
>   */
>  static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba)
>  {
> - return readl(hba->mmio_base + REG_UFS_VERSION);
> + return ufshcd_readl(hba, REG_UFS_VERSION);
>  }
>
>  /**
> @@ -130,8 +130,7 @@ static inline int ufshcd_get_tm_free_slot(struct
> ufs_hba *hba)
>   */
>  static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos)
>  {
> - writel(~(1 << pos),
> - (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_CLEAR));
> + ufshcd_writel(hba, ~(1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR);
>  }
>
>  /**
> @@ -165,7 +164,7 @@ static inline int ufshcd_get_lists_status(u32 reg)
>   */
>  static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba)
>  {
> - return readl(hba->mmio_base + REG_UIC_COMMAND_ARG_2) &
> + return ufshcd_readl(hba, REG_UIC_COMMAND_ARG_2) &
>  MASK_UIC_COMMAND_RESULT;
>  }
>
> @@ -238,18 +237,15 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int
> option)
>  {
>   switch (option) {
>   case INT_AGGR_RESET:
> - writel((INT_AGGR_ENABLE |
> - INT_AGGR_COUNTER_AND_TIMER_RESET),
> - (hba->mmio_base +
> -  REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL));
> + ufshcd_writel(hba, INT_AGGR_ENABLE |
> +   INT_AGGR_COUNTER_AND_TIMER_RESET,
> +   REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL);
>   break;
>   case INT_AGGR_CONFIG:
> - writel((INT_AGGR_ENABLE |
> - INT_AGGR_PARAM_WRITE |
> - INT_AGGR_COUNTER_THRESHOLD_VALUE |
> - INT_AGGR_TIMEOUT_VALUE),
> - (hba->mmio_base +
> -  REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL));
> + ufshcd_writel(hba, INT_AGGR_ENABLE | INT_AGGR_PARAM_WRITE |
> +   INT_AGGR_COUNTER_THRESHOLD_VALUE |
> +   INT_AGGR_TIMEOUT_VALUE,
> +   REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL);
>   break;
>   }
>  }
> @@ -262,12 +258,10 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int
> option)
>   */
>  static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)
>  {
> - writel(UTP_TASK_REQ_LIST_RUN_STOP_BIT,
> -(hba->mmio_base +
> - REG_UTP_TASK_REQ_LIST_RUN_STOP));
> - writel(UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT,
> -(hba->mmio_base +
> - REG_UTP_TRANSFER_REQ_LIST_RUN_STOP));
> + ufshcd_writel(hba, UTP_TASK_REQ_LIST_RUN_STOP_BIT,
> +   REG_UTP_TASK_REQ_LIST_RUN_STOP);
> + ufshcd_writel(hba, UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT,
> +   REG_UTP_TRANSFER_REQ_LIST_RUN_STOP);
>  }
>
>  /**
> @@ -276,7 +270,7 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba
> *hba)
>   */
>  static inline void ufshcd_hba_start(struct ufs_hba *hba)
>  {
> - writel(CONTROLLER_ENABLE , (hba->mmio_base + REG_CONTROLLER_ENABLE));
> + ufshcd_writel(hba, CONTROLLER_ENABLE, REG_CONTROLLER_ENABLE);
>  }
>
>  /**
> @@ -287,7 +281,7 @@ static inline void ufshcd_hba_start(struct ufs_hba
> *hba)
>   */
>  static inline int ufshcd_is_hba_active(struct ufs_hba *hba)
>  {
> - return (readl(hba->mmio_base + REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
> + return (ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
>  }
>
>  /**
> @@ -299,8 +293,7 @@ static inline
>  void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
>  {
>   __set_bit(task_tag, &hba->outstanding_reqs);
> - writel((1 << task_tag),
> -(hba->mmio_base + REG_UTP_TRANSFER_REQ_DOOR_BELL));
> + ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
>  }
>
>  /**
> @@ -381,8 +374,7 @@ void ufshcd_copy_query_response(struct ufs_hba *hba,
> struct ufshcd_lrb *lrbp)
>   */
>  static inline void ufshcd_hba_capabilities(struct ufs_hba *hba)
>  {
> - hba->capabilities =
> - readl(hba->mmio_base + REG_CONTROLLER_CAPABILITIES);
> + hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES);
>
>   /* nutrs and nutmrs are 0 based values */
>   hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1;
> @@ -399,16 +391,13 @@ static inline void
>  ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command
> *uic_cmnd)
>  {
>   /* Write Args */
> - writel(uic_cmnd->argument1,
> -   (hba->mmio_base +

[PATCH V4 1/1] scsi: ufs: Add support for sending NOP OUT UPIU

2013-05-08 Thread Sujit Reddy Thumma
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.

Signed-off-by: Sujit Reddy Thumma 

---
v4:
   - Removed readl_poll_timeout and replaced with wait logic
   - additional checks for completion
v3:
   - minor bug fix in error path
v2:
   - fixed INTERNAL_CMD_TAG check in readl_poll_timeout
   - minor cleanup from v1
   - rebased on Seungwon Jeon's UFS V3 patchset
---
 drivers/scsi/ufs/ufshcd.c |  197 ++--
 drivers/scsi/ufs/ufshcd.h |4 +
 2 files changed, 192 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3607ffb..ded770d 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -44,6 +44,13 @@
 /* UIC command timeout, unit: ms */
 #define UIC_CMD_TIMEOUT500
 
+/* 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 */
+/* Reserved tag for internal commands */
+#define INTERNAL_CMD_TAG   0
+
 enum {
UFSHCD_MAX_CHANNEL  = 0,
UFSHCD_MAX_ID   = 1,
@@ -72,6 +79,39 @@ enum {
INT_AGGR_CONFIG,
 };
 
+/*
+ * ufshcd_wait_for_register - wait for register value to change
+ * @hba - per-adapter interface
+ * @reg - mmio register offset
+ * @mask - mask to apply to read register value
+ * @val - wait condition
+ * @interval_us - polling interval in microsecs
+ * @timeout_ms - timeout in millisecs
+ *
+ * Returns final register value after iteration
+ */
+static u32 ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
+   u32 val, unsigned long interval_us, unsigned long timeout_ms)
+{
+   u32 tmp;
+   ktime_t start;
+   unsigned long diff;
+
+   tmp = ufshcd_readl(hba, reg);
+
+   start = ktime_get();
+   while ((tmp & mask) == val) {
+   /* wakeup within 50us of expiry */
+   usleep_range(interval_us, interval_us + 50);
+   tmp = ufshcd_readl(hba, reg);
+   diff = ktime_to_ms(ktime_sub(ktime_get(), start));
+   if (diff > timeout_ms)
+   break;
+   }
+
+   return tmp;
+}
+
 /**
  * ufshcd_get_intr_mask - Get the interrupt bit mask
  * @hba - Pointer to adapter instance
@@ -630,7 +670,7 @@ static void ufshcd_prepare_req_desc(struct ufshcd_lrb 
*lrbp, u32 *upiu_flags)
 {
struct utp_transfer_req_desc *req_desc = lrbp->utr_descriptor_ptr;
enum dma_data_direction cmd_dir =
-   lrbp->cmd->sc_data_direction;
+   lrbp->cmd ? lrbp->cmd->sc_data_direction : DMA_NONE;
u32 data_direction;
u32 dword_0;
 
@@ -647,6 +687,8 @@ static void ufshcd_prepare_req_desc(struct ufshcd_lrb 
*lrbp, u32 *upiu_flags)
 
dword_0 = data_direction | (lrbp->command_type
<< UPIU_COMMAND_TYPE_OFFSET);
+   if (lrbp->intr_cmd)
+   dword_0 |= UTP_REQ_DESC_INT_CMD;
 
/* Transfer request descriptor header fields */
req_desc->header.dword_0 = cpu_to_le32(dword_0);
@@ -735,6 +777,18 @@ static void ufshcd_prepare_utp_query_req_upiu(struct 
ufs_hba *hba,
 
 }
 
+static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp)
+{
+   struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
+
+   memset(ucd_req_ptr, 0, sizeof(struct utp_upiu_req));
+
+   /* command descriptor fields */
+   ucd_req_ptr->header.dword_0 =
+   UPIU_HEADER_DWORD(
+   UPIU_TRANSACTION_NOP_OUT, 0, 0, lrbp->task_tag);
+}
+
 /**
  * ufshcd_compose_upiu - form UFS Protocol Information Unit(UPIU)
  * @hba - UFS hba
@@ -749,11 +803,13 @@ static int ufshcd_compose_upiu(struct ufs_hba *hba, 
struct ufshcd_lrb *lrbp)
case UTP_CMD_TYPE_SCSI:
case UTP_CMD_TYPE_DEV_MANAGE:
ufshcd_prepare_req_desc(lrbp, &upiu_flags);
-   if (lrbp->command_type == UTP_CMD_TYPE_SCSI)
+   if (lrbp->cmd && lrbp->command_type == UTP_CMD_TYPE_SCSI)
ufshcd_prepare_utp_scsi_cmd_upiu(lrbp, upiu_flags);
-   else
+   else if (lrbp->cmd && ufshcd_is_query_req(lrbp))
ufshcd_prepare_utp_query_req_upiu(hba, lrbp,
upiu_flags);
+   else if (!lrbp->cmd)
+   ufshcd_prepare_utp_nop_upiu(lrbp);
break;
case UTP_CMD_TYPE_UFS:
/* For UFS native command implementation */
@@ -802,6 +858,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *

[PATCH v4 6/6] scsi: ufs: add dme control primitives

2013-05-08 Thread Seungwon Jeon
Implements to support the following operations.
Currently, this patch doesn't introduce DME_ENABLE and DME_RESET
because host controller's HCE enable contains these roles.

DME_POWERON{OFF}, DME_HIBERNATE_ENTER{EXIT}, DME_ENDPOINTRESET.

Signed-off-by: Seungwon Jeon 
Tested-by: Maya Erez 
---
Change in v4:
- Changed function names.

 drivers/scsi/ufs/ufshcd.c |  123 +++--
 drivers/scsi/ufs/ufshcd.h |   26 ++
 drivers/scsi/ufs/ufshci.h |   15 ++
 3 files changed, 160 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index e05eedb..45123b4 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -39,6 +39,7 @@
 
 #define UFSHCD_ENABLE_INTRS(UTP_TRANSFER_REQ_COMPL |\
 UTP_TASK_REQ_COMPL |\
+UFSHCD_HIBERNATE_MASK |\
 UFSHCD_ERROR_MASK)
 /* UIC command timeout, unit: ms */
 #define UIC_CMD_TIMEOUT500
@@ -203,6 +204,18 @@ static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba 
*hba)
 }
 
 /**
+ * ufshcd_get_upmcrs - Get the power mode change request status
+ * @hba: Pointer to adapter instance
+ *
+ * This function gets the UPMCRS field of HCS register
+ * Returns value of UPMCRS field
+ */
+static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba)
+{
+   return (ufshcd_readl(hba, REG_CONTROLLER_STATUS) >> 8) & 0x7;
+}
+
+/**
  * ufshcd_free_hba_memory - Free allocated memory for LRB, request
  * and task lists
  * @hba: Pointer to adapter instance
@@ -1163,6 +1176,103 @@ out:
 EXPORT_SYMBOL_GPL(ufshcd_dme_get_attr);
 
 /**
+ * ufshcd_dme_power_ctrl - UIC command for DME_POWERON, DME_POWEROFF
+ * @hba: per adapter instance
+ * @on: indicate wherter power_on or power_off
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+int ufshcd_dme_power_ctrl(struct ufs_hba *hba, u8 on)
+{
+   struct uic_command uic_cmd = {0};
+   static const char *const action[] = {
+   "dme-power-off",
+   "dme-power-on"
+   };
+   const char *power = action[!!on];
+   int ret;
+
+   uic_cmd.command = on ?
+   UIC_CMD_DME_POWERON : UIC_CMD_DME_POWEROFF;
+
+   ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
+   if (ret)
+   dev_err(hba->dev, "%s: error code %d\n", power, ret);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(ufshcd_dme_power_ctrl);
+
+/**
+ * ufshcd_dme_hibern8_ctrl - UIC command for DME_HIBERNATE_ENTER,
+ *  DME_HIBERNATE_EXIT
+ * @hba: per adapter instance
+ * @enter: indicate wherter hibernation enter or exit
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+int ufshcd_dme_hibern8_ctrl(struct ufs_hba *hba, u8 enter)
+{
+   struct uic_command uic_cmd = {0};
+   static const char *const action[] = {
+   "dme-hibernate-exit",
+   "dme-hibernate-enter"
+   };
+   const char *hibern8 = action[!!enter];
+   u8 status;
+   int ret;
+
+   uic_cmd.command = enter ?
+   UIC_CMD_DME_HIBER_ENTER : UIC_CMD_DME_HIBER_EXIT;
+
+   mutex_lock(&hba->uic_cmd_mutex);
+   init_completion(&hba->hibern8_done);
+   ret = __ufshcd_send_uic_cmd(hba, &uic_cmd);
+   if (ret) {
+   dev_err(hba->dev, "%s: error code %d\n", hibern8, ret);
+   goto out;
+   }
+
+   if (wait_for_completion_timeout(&hba->hibern8_done,
+   msecs_to_jiffies(UIC_CMD_TIMEOUT))) {
+   status = ufshcd_get_upmcrs(hba);
+   if (status != PWR_LOCAL) {
+   dev_err(hba->dev, "%s: failed, host upmcrs:0x%x\n",
+   hibern8, status);
+   ret = status;
+   }
+   } else {
+   dev_err(hba->dev, "%s: timeout\n", hibern8);
+   ret = -ETIMEDOUT;
+   }
+out:
+   mutex_unlock(&hba->uic_cmd_mutex);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(ufshcd_dme_hibern8_ctrl);
+
+/**
+ * ufshcd_dme_endpoint_reset - UIC command for DME_ENDPOINTRESET
+ * @hba: per adapter instance
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+int ufshcd_dme_endpoint_reset(struct ufs_hba *hba)
+{
+   struct uic_command uic_cmd = {0};
+   int ret;
+
+   uic_cmd.command = UIC_CMD_DME_END_PT_RST;
+
+   ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
+   if (ret)
+   dev_err(hba->dev, "dme-endpoint-reset: error code %d\n", ret);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(ufshcd_dme_endpoint_reset);
+
+/**
  * ufshcd_make_hba_operational - Make UFS controller operational
  * @hba: per adapter instance
  *
@@ -1618,16 +1728,21 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct 
ufshcd_lrb *lrbp)
 /**
  * ufshcd_uic_cmd_compl - handle completion of uic command
  * @hba: per adapter instance
+ * @intr_status: interrupt status generated by t

[PATCH v4 4/6] scsi: ufs: rework link start-up process

2013-05-08 Thread Seungwon Jeon
Link start-up requires long time with multiphase handshakes
between UFS host and device. This affects driver's probe time.
This patch let link start-up run asynchronously. Link start-up
will be executed at the end of prove separately.
Along with this change, the following is worked.

Defined completion time of uic command to avoid a permanent wait.
Added mutex to guarantee of uic command at a time.
Adapted some sequence of controller initialization after link statup
according to HCI standard.

Signed-off-by: Seungwon Jeon 
Signed-off-by: Sujit Reddy Thumma 
Tested-by: Maya Erez 
---
Change in v4:
- Addressed late interrupt case (Sujit).
- Move print message in link startup (Maya).

 drivers/scsi/ufs/ufshcd.c |  295 ++--
 drivers/scsi/ufs/ufshcd.h |   10 +-
 2 files changed, 208 insertions(+), 97 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index e04c74e..8363b92 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -33,11 +33,15 @@
  * this program.
  */
 
+#include 
+
 #include "ufshcd.h"
 
 #define UFSHCD_ENABLE_INTRS(UTP_TRANSFER_REQ_COMPL |\
 UTP_TASK_REQ_COMPL |\
 UFSHCD_ERROR_MASK)
+/* UIC command timeout, unit: ms */
+#define UIC_CMD_TIMEOUT500
 
 enum {
UFSHCD_MAX_CHANNEL  = 0,
@@ -401,24 +405,122 @@ static inline void ufshcd_hba_capabilities(struct 
ufs_hba *hba)
 }
 
 /**
- * ufshcd_send_uic_command - Send UIC commands to unipro layers
+ * ufshcd_ready_for_uic_cmd - Check if controller is ready
+ *to accept UIC commands
  * @hba: per adapter instance
- * @uic_command: UIC command
+ * Return true on success, else false
+ */
+static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba)
+{
+   if (ufshcd_readl(hba, REG_CONTROLLER_STATUS) & UIC_COMMAND_READY)
+   return true;
+   else
+   return false;
+}
+
+/**
+ * ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Mutex must be held.
  */
 static inline void
-ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd)
+ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
 {
+   WARN_ON(hba->active_uic_cmd);
+
+   hba->active_uic_cmd = uic_cmd;
+
/* Write Args */
-   ufshcd_writel(hba, uic_cmnd->argument1, REG_UIC_COMMAND_ARG_1);
-   ufshcd_writel(hba, uic_cmnd->argument2, REG_UIC_COMMAND_ARG_2);
-   ufshcd_writel(hba, uic_cmnd->argument3, REG_UIC_COMMAND_ARG_3);
+   ufshcd_writel(hba, uic_cmd->argument1, REG_UIC_COMMAND_ARG_1);
+   ufshcd_writel(hba, uic_cmd->argument2, REG_UIC_COMMAND_ARG_2);
+   ufshcd_writel(hba, uic_cmd->argument3, REG_UIC_COMMAND_ARG_3);
 
/* Write UIC Cmd */
-   ufshcd_writel(hba, uic_cmnd->command & COMMAND_OPCODE_MASK,
+   ufshcd_writel(hba, uic_cmd->command & COMMAND_OPCODE_MASK,
  REG_UIC_COMMAND);
 }
 
 /**
+ * ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command
+ * @hba: per adapter instance
+ * @uic_command: UIC command
+ *
+ * Must be called with mutex held.
+ * Returns 0 only if success.
+ */
+static int
+ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+   int ret;
+   unsigned long flags;
+
+   if (wait_for_completion_timeout(&uic_cmd->done,
+   msecs_to_jiffies(UIC_CMD_TIMEOUT)))
+   ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
+   else
+   ret = -ETIMEDOUT;
+
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   hba->active_uic_cmd = NULL;
+   spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+   return ret;
+}
+
+/**
+ * __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Identical to ufshcd_send_uic_cmd() expect mutex. Must be called
+ * with mutex held.
+ * Returns 0 only if success.
+ */
+static int
+__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+   int ret;
+   unsigned long flags;
+
+   if (!ufshcd_ready_for_uic_cmd(hba)) {
+   dev_err(hba->dev,
+   "Controller not ready to accept UIC commands\n");
+   return -EIO;
+   }
+
+   init_completion(&uic_cmd->done);
+
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   ufshcd_dispatch_uic_cmd(hba, uic_cmd);
+   spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+   ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);
+
+   return ret;
+}
+
+/**
+ * ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Returns 0 only if success.
+ */
+static int
+ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+   int ret;

[PATCH v4 5/6] scsi: ufs: add dme configuration primitives

2013-05-08 Thread Seungwon Jeon
Implements to support Get and Set operation of the DME.
These operations are used to configure the behavior of
the UNIPRO.

Signed-off-by: Seungwon Jeon 
Tested-by: Maya Erez 
---
Change in v4:
- Removed unipro.h header file. It will be introduced in next.
- Changed function names and error message.

 drivers/scsi/ufs/ufshcd.c |   88 +
 drivers/scsi/ufs/ufshcd.h |   30 +++
 drivers/scsi/ufs/ufshci.h |5 +++
 3 files changed, 123 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 8363b92..e05eedb 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -191,6 +191,18 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba 
*hba)
 }
 
 /**
+ * ufshcd_get_dme_attr_val - Get the value of attribute returned by UIC command
+ * @hba: Pointer to adapter instance
+ *
+ * This function gets UIC command argument3
+ * Returns 0 on success, non zero value on error
+ */
+static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba)
+{
+   return ufshcd_readl(hba, REG_UIC_COMMAND_ARG_3);
+}
+
+/**
  * ufshcd_free_hba_memory - Free allocated memory for LRB, request
  * and task lists
  * @hba: Pointer to adapter instance
@@ -1077,6 +1089,80 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
 }
 
 /**
+ * ufshcd_dme_set_attr - UIC command for DME_SET, DME_PEER_SET
+ * @hba: per adapter instance
+ * @attr_sel: uic command argument1
+ * @attr_set: attribute set type as uic command argument2
+ * @mib_val: setting value as uic command argument3
+ * @peer: indicate wherter peer or non-peer
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
+   u8 attr_set, u32 mib_val, u8 peer)
+{
+   struct uic_command uic_cmd = {0};
+   static const char *const action[] = {
+   "dme-set",
+   "dme-peer-set"
+   };
+   const char *set = action[!!peer];
+   int ret;
+
+   uic_cmd.command = peer ?
+   UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET;
+   uic_cmd.argument1 = attr_sel;
+   uic_cmd.argument2 = UIC_ARG_ATTR_SET(attr_set);
+   uic_cmd.argument3 = mib_val;
+
+   ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
+   if (ret)
+   dev_err(hba->dev, "%s: attr-id 0x%x error code %d\n",
+   set, GET_UIC_ATTR_ID(attr_sel), ret);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(ufshcd_dme_set_attr);
+
+/**
+ * ufshcd_dme_get_attr - UIC command for DME_GET, DME_PEER_GET
+ * @hba: per adapter instance
+ * @attr_sel: uic command argument1
+ * @mib_val: the value of the attribute as returned by the UIC command
+ * @peer: indicate wherter peer or non-peer
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
+   u32 *mib_val, u8 peer)
+{
+   struct uic_command uic_cmd = {0};
+   static const char *const action[] = {
+   "dme-get",
+   "dme-peer-get"
+   };
+   const char *get = action[!!peer];
+   int ret;
+
+   uic_cmd.command = peer ?
+   UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET;
+   uic_cmd.argument1 = attr_sel;
+
+   ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
+   if (ret) {
+   dev_err(hba->dev, "%s: attr-id 0x%x error code %d\n",
+   get, GET_UIC_ATTR_ID(attr_sel), ret);
+   goto out;
+   }
+
+   if (mib_val)
+   *mib_val = uic_cmd.argument3;
+out:
+   return ret;
+}
+EXPORT_SYMBOL_GPL(ufshcd_dme_get_attr);
+
+/**
  * ufshcd_make_hba_operational - Make UFS controller operational
  * @hba: per adapter instance
  *
@@ -1538,6 +1624,8 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba)
if (hba->active_uic_cmd) {
hba->active_uic_cmd->argument2 |=
ufshcd_get_uic_cmd_result(hba);
+   hba->active_uic_cmd->argument3 =
+   ufshcd_get_dme_attr_val(hba);
complete(&hba->active_uic_cmd->done);
}
 }
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 974bd07..dabd29c 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -217,6 +217,11 @@ int ufshcd_init(struct device *, struct ufs_hba ** , void 
__iomem * ,
unsigned int);
 void ufshcd_remove(struct ufs_hba *);
 
+extern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
+  u8 attr_set, u32 mib_val, u8 peer);
+extern int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
+  u32 *mib_val, u8 peer);
+
 /**
  * ufshcd_hba_stop - Send controller to reset state
  * @hba: per adapter instance
@@ -226,4 +231,29 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba)
ufshcd_writel(hba, CONTROLLER_DISABL

[PATCH v4 3/6] scsi: ufs: fix interrupt status clears

2013-05-08 Thread Seungwon Jeon
There is no need to check the version to clear
the interrupt status. And the order is changed
prior to actual handling.

Signed-off-by: Seungwon Jeon 
Tested-by: Maya Erez 
---
 drivers/scsi/ufs/ufshcd.c |5 +
 1 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index feaf221..e04c74e 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1582,11 +1582,8 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)
intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
 
if (intr_status) {
+   ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
ufshcd_sl_intr(hba, intr_status);
-
-   /* If UFSHCI 1.0 then clear interrupt status register */
-   if (hba->ufs_version == UFSHCI_VERSION_10)
-   ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
retval = IRQ_HANDLED;
}
spin_unlock(hba->host->host_lock);
-- 
1.7.0.4


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 2/6] scsi: ufs: amend interrupt configuration

2013-05-08 Thread Seungwon Jeon
It makes interrupt setting more flexible especially
for disabling. And wrong bit mask is fixed for ver 1.0.
[17:16] is added for mask.

Signed-off-by: Seungwon Jeon 
Tested-by: Maya Erez 
---
 drivers/scsi/ufs/ufshcd.c |   84 +++-
 drivers/scsi/ufs/ufshcd.h |4 +-
 drivers/scsi/ufs/ufshci.h |5 ++-
 3 files changed, 64 insertions(+), 29 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index cf7c8e4..feaf221 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -35,6 +35,10 @@
 
 #include "ufshcd.h"
 
+#define UFSHCD_ENABLE_INTRS(UTP_TRANSFER_REQ_COMPL |\
+UTP_TASK_REQ_COMPL |\
+UFSHCD_ERROR_MASK)
+
 enum {
UFSHCD_MAX_CHANNEL  = 0,
UFSHCD_MAX_ID   = 1,
@@ -64,6 +68,20 @@ enum {
 };
 
 /**
+ * ufshcd_get_intr_mask - Get the interrupt bit mask
+ * @hba - Pointer to adapter instance
+ *
+ * Returns interrupt bit mask per version
+ */
+static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba)
+{
+   if (hba->ufs_version == UFSHCI_VERSION_10)
+   return INTERRUPT_MASK_ALL_VER_10;
+   else
+   return INTERRUPT_MASK_ALL_VER_11;
+}
+
+/**
  * ufshcd_get_ufs_version - Get the UFS version supported by the HBA
  * @hba - Pointer to adapter instance
  *
@@ -441,25 +459,45 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp)
 }
 
 /**
- * ufshcd_int_config - enable/disable interrupts
+ * ufshcd_enable_intr - enable interrupts
  * @hba: per adapter instance
- * @option: interrupt option
+ * @intrs: interrupt bits
  */
-static void ufshcd_int_config(struct ufs_hba *hba, u32 option)
+static void ufshcd_enable_intr(struct ufs_hba *hba, u32 intrs)
 {
-   switch (option) {
-   case UFSHCD_INT_ENABLE:
-   ufshcd_writel(hba, hba->int_enable_mask, REG_INTERRUPT_ENABLE);
-   break;
-   case UFSHCD_INT_DISABLE:
-   if (hba->ufs_version == UFSHCI_VERSION_10)
-   ufshcd_writel(hba, INTERRUPT_DISABLE_MASK_10,
- REG_INTERRUPT_ENABLE);
-   else
-   ufshcd_writel(hba, INTERRUPT_DISABLE_MASK_11,
- REG_INTERRUPT_ENABLE);
-   break;
+   u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
+
+   if (hba->ufs_version == UFSHCI_VERSION_10) {
+   u32 rw;
+   rw = set & INTERRUPT_MASK_RW_VER_10;
+   set = rw | ((set ^ intrs) & intrs);
+   } else {
+   set |= intrs;
+   }
+
+   ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
+}
+
+/**
+ * ufshcd_disable_intr - disable interrupts
+ * @hba: per adapter instance
+ * @intrs: interrupt bits
+ */
+static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs)
+{
+   u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
+
+   if (hba->ufs_version == UFSHCI_VERSION_10) {
+   u32 rw;
+   rw = (set & INTERRUPT_MASK_RW_VER_10) &
+   ~(intrs & INTERRUPT_MASK_RW_VER_10);
+   set = rw | ((set & intrs) & ~INTERRUPT_MASK_RW_VER_10);
+
+   } else {
+   set &= ~intrs;
}
+
+   ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
 }
 
 /**
@@ -946,8 +984,7 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
uic_cmd->argument3 = 0;
 
/* enable UIC related interrupts */
-   hba->int_enable_mask |= UIC_COMMAND_COMPL;
-   ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
+   ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
 
/* sending UIC commands to controller */
ufshcd_send_uic_command(hba, uic_cmd);
@@ -994,13 +1031,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba 
*hba)
}
 
/* Enable required interrupts */
-   hba->int_enable_mask |= (UTP_TRANSFER_REQ_COMPL |
-UIC_ERROR |
-UTP_TASK_REQ_COMPL |
-DEVICE_FATAL_ERROR |
-CONTROLLER_FATAL_ERROR |
-SYSTEM_BUS_FATAL_ERROR);
-   ufshcd_int_config(hba, UFSHCD_INT_ENABLE);
+   ufshcd_enable_intr(hba, UFSHCD_ENABLE_INTRS);
 
/* Configure interrupt aggregation */
ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG);
@@ -1828,7 +1859,7 @@ static void ufshcd_hba_free(struct ufs_hba *hba)
 void ufshcd_remove(struct ufs_hba *hba)
 {
/* disable interrupts */
-   ufshcd_int_config(hba, UFSHCD_INT_DISABLE);
+   ufshcd_disable_intr(hba, hba->intr_mask);
 
ufshcd_hba_stop(hba);
ufshcd_hba_free(hba);
@@ -1886,6 +1917,9 @@ int ufshcd_init(struct device *dev, struct ufs_hba 
**hba_handle,
/* Get UFS version supported by the controller */
hba->ufs_version = ufshcd_get_ufs_version(hba);
 
+   /* Get Interrupt bit mask per version */
+   hba->int

[PATCH v4 1/6] scsi: ufs: wrap the i/o access operations

2013-05-08 Thread Seungwon Jeon
Simplify operations with hiding mmio_base.

Signed-off-by: Seungwon Jeon 
Tested-by: Maya Erez 
---
 drivers/scsi/ufs/ufshcd.c |  105 +++--
 drivers/scsi/ufs/ufshcd.h |7 +++-
 2 files changed, 50 insertions(+), 62 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f244812..cf7c8e4 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -71,7 +71,7 @@ enum {
  */
 static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba)
 {
-   return readl(hba->mmio_base + REG_UFS_VERSION);
+   return ufshcd_readl(hba, REG_UFS_VERSION);
 }
 
 /**
@@ -130,8 +130,7 @@ static inline int ufshcd_get_tm_free_slot(struct ufs_hba 
*hba)
  */
 static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos)
 {
-   writel(~(1 << pos),
-   (hba->mmio_base + REG_UTP_TRANSFER_REQ_LIST_CLEAR));
+   ufshcd_writel(hba, ~(1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR);
 }
 
 /**
@@ -165,7 +164,7 @@ static inline int ufshcd_get_lists_status(u32 reg)
  */
 static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba)
 {
-   return readl(hba->mmio_base + REG_UIC_COMMAND_ARG_2) &
+   return ufshcd_readl(hba, REG_UIC_COMMAND_ARG_2) &
   MASK_UIC_COMMAND_RESULT;
 }
 
@@ -238,18 +237,15 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option)
 {
switch (option) {
case INT_AGGR_RESET:
-   writel((INT_AGGR_ENABLE |
-   INT_AGGR_COUNTER_AND_TIMER_RESET),
-   (hba->mmio_base +
-REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL));
+   ufshcd_writel(hba, INT_AGGR_ENABLE |
+ INT_AGGR_COUNTER_AND_TIMER_RESET,
+ REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL);
break;
case INT_AGGR_CONFIG:
-   writel((INT_AGGR_ENABLE |
-   INT_AGGR_PARAM_WRITE |
-   INT_AGGR_COUNTER_THRESHOLD_VALUE |
-   INT_AGGR_TIMEOUT_VALUE),
-   (hba->mmio_base +
-REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL));
+   ufshcd_writel(hba, INT_AGGR_ENABLE | INT_AGGR_PARAM_WRITE |
+ INT_AGGR_COUNTER_THRESHOLD_VALUE |
+ INT_AGGR_TIMEOUT_VALUE,
+ REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL);
break;
}
 }
@@ -262,12 +258,10 @@ ufshcd_config_int_aggr(struct ufs_hba *hba, int option)
  */
 static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)
 {
-   writel(UTP_TASK_REQ_LIST_RUN_STOP_BIT,
-  (hba->mmio_base +
-   REG_UTP_TASK_REQ_LIST_RUN_STOP));
-   writel(UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT,
-  (hba->mmio_base +
-   REG_UTP_TRANSFER_REQ_LIST_RUN_STOP));
+   ufshcd_writel(hba, UTP_TASK_REQ_LIST_RUN_STOP_BIT,
+ REG_UTP_TASK_REQ_LIST_RUN_STOP);
+   ufshcd_writel(hba, UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT,
+ REG_UTP_TRANSFER_REQ_LIST_RUN_STOP);
 }
 
 /**
@@ -276,7 +270,7 @@ static void ufshcd_enable_run_stop_reg(struct ufs_hba *hba)
  */
 static inline void ufshcd_hba_start(struct ufs_hba *hba)
 {
-   writel(CONTROLLER_ENABLE , (hba->mmio_base + REG_CONTROLLER_ENABLE));
+   ufshcd_writel(hba, CONTROLLER_ENABLE, REG_CONTROLLER_ENABLE);
 }
 
 /**
@@ -287,7 +281,7 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba)
  */
 static inline int ufshcd_is_hba_active(struct ufs_hba *hba)
 {
-   return (readl(hba->mmio_base + REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
+   return (ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & 0x1) ? 0 : 1;
 }
 
 /**
@@ -299,8 +293,7 @@ static inline
 void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
 {
__set_bit(task_tag, &hba->outstanding_reqs);
-   writel((1 << task_tag),
-  (hba->mmio_base + REG_UTP_TRANSFER_REQ_DOOR_BELL));
+   ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
 }
 
 /**
@@ -381,8 +374,7 @@ void ufshcd_copy_query_response(struct ufs_hba *hba, struct 
ufshcd_lrb *lrbp)
  */
 static inline void ufshcd_hba_capabilities(struct ufs_hba *hba)
 {
-   hba->capabilities =
-   readl(hba->mmio_base + REG_CONTROLLER_CAPABILITIES);
+   hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES);
 
/* nutrs and nutmrs are 0 based values */
hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1;
@@ -399,16 +391,13 @@ static inline void
 ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd)
 {
/* Write Args */
-   writel(uic_cmnd->argument1,
- (hba->mmio_base + REG_UIC_COMMAND_ARG_1));
-   writel(uic_cmnd->argument2,
- (hba->mmio_base + REG_UIC_COMMAND_ARG_2));
-   writel(uic_cmnd->argument3,
- (hba->mmio_base + REG_UIC_COMMAND_ARG_3));

[SCSI] mvsas: Fix the kernel panic due to unaligned data access

2013-05-08 Thread Paul Guo
It's easy to find the address and symbol that causes the unalignd data
access according to the stack dump information. The following small
patch will fix it.

This change is harmless for platforms (like x86/x64) which support
unaligned data access but is critical for platforms those do not support
unaligned data access (like our platform: arch/tile).

I sent the patch but did not ping the status. I sync-up the workspace
and re-generate the patch again. Feel free to give me any feedback. It's
really annoying to maintain the change internally.

Thanks,
Paul


Signed-off-by: Paul Guo 
---
 drivers/scsi/mvsas/mv_sas.c |5 +++--
 drivers/scsi/mvsas/mv_sas.h |1 +
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index fd3b283..18e133e 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -1852,10 +1852,11 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 
rx_desc, u32 flags)
}
 
/* error info record present */
-   if (unlikely((rx_desc & RXQ_ERR) && (*(u64 *) slot->response))) {
+   if (unlikely((rx_desc & RXQ_ERR) &&
+ get_unaligned_le64((u64 *) slot->response))) {
mv_dprintk("port %d slot %d rx_desc %X has error info"
"%016llX.\n", slot->port->sas_port.id, slot_idx,
-rx_desc, (u64)(*(u64 *)slot->response));
+rx_desc, get_unaligned_le64((u64 *) slot->response));
tstat->stat = mvs_slot_err(mvi, task, slot_idx);
tstat->resp = SAS_TASK_COMPLETE;
goto out;
diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h
index c04a4f5..c89c145 100644
--- a/drivers/scsi/mvsas/mv_sas.h
+++ b/drivers/scsi/mvsas/mv_sas.h
@@ -39,6 +39,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
-- 
1.7.10.3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html