Re: [PATCH V5 12/12] pm80xx: thermal, sas controller config and error handling update

2013-05-06 Thread James Bottomley
On Mon, 2013-05-06 at 09:36 -0700, Anand wrote:
> diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h 
> b/drivers/scsi/pm8001/pm80xx_hwi.h
> index 0c15627..ea127b6 100644
> --- a/drivers/scsi/pm8001/pm80xx_hwi.h
> +++ b/drivers/scsi/pm8001/pm80xx_hwi.h
[...]
> @@ -996,6 +1020,23 @@ struct ssp_coalesced_comp_resp {
>  
>  /* new outbound structure for spcv - ends */
>  
> +/* brief data structure for SAS protocol timer configuration page.
> + *
> + */
> +struct SASProtocolTimerConfig{
> +__le32 pageCode;/* 0 */
> +__le32 MST_MSI; /* 1 */
> +__le32 STP_SSP_MCT_TMO; /* 2 */
> +__le32 STP_FRM_TMO; /* 3 */
> +__le32 STP_IDLE_TMO;/* 4 */
> +__le32 OPNRJT_RTRY_INTVL;   /* 5 */
> +__le32 Data_Cmd_OPNRJT_RTRY_TMO;/* 6 */
> +__le32 Data_Cmd_OPNRJT_RTRY_THR;/* 7 */
> +__le32 MAX_AIP; /* 8 */
> +} __attribute__((packed, aligned(4)));

This is wrongly aligned using spaces instead of tabs ... since the rest
of the file is OK, you cut and pasted this from somewhere.
checkpatch.pl warns about this stuff, please use it.

James


--
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 V5 11/12] pm80xx: NCQ error handling changes

2013-05-06 Thread James Bottomley
On Mon, 2013-05-06 at 09:35 -0700, Anand wrote:
> >From 2738e0b59fe103a363b0ea600b3eccc687a7fa3c Mon Sep 17 00:00:00 2001
> From: Sakthivel K 
> Date: Tue, 19 Mar 2013 18:08:08 +0530
> Subject: [PATCH V5 11/12] pm80xx: NCQ error handling changes
> 
> Handled NCQ errors in the low level driver as the FW
> is not providing the faulty tag for NCQ errors for libsas
> to recover.
> 
> Signed-off-by: Anand Kumar S 
> Acked-by: Jack Wang 
> Reviewed-by: Hannes Reinecke  
> ---
>  drivers/scsi/pm8001/pm8001_hwi.c |  270 
> --
>  drivers/scsi/pm8001/pm8001_sas.c |   22 +++-
>  drivers/scsi/pm8001/pm8001_sas.h |   15 ++-
>  drivers/scsi/pm8001/pm80xx_hwi.c |  262 +++--
>  drivers/scsi/pm8001/pm80xx_hwi.h |1 +
>  5 files changed, 543 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/scsi/pm8001/pm8001_hwi.c 
> b/drivers/scsi/pm8001/pm8001_hwi.c
> index 265dbf4..a90c002 100644
> --- a/drivers/scsi/pm8001/pm8001_hwi.c
> +++ b/drivers/scsi/pm8001/pm8001_hwi.c
> @@ -1707,6 +1707,123 @@ int pm8001_handle_event(struct pm8001_hba_info 
> *pm8001_ha, void *data,
>   return ret;
>  }
>  
> +static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
> + struct pm8001_device *pm8001_ha_dev)
> +{
> + int res;
> + u32 ccb_tag;
> + struct pm8001_ccb_info *ccb;
> + struct sas_task *task = NULL;
> + struct task_abort_req task_abort;
> + struct inbound_queue_table *circularQ;
> + u32 opc = OPC_INB_SATA_ABORT;
> + int ret;
> +
> + if (!pm8001_ha_dev) {
> + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("dev is null \n"));

This space before a \n is quite a pattern with you.  Please don't do it
because it can lead to odd problems with logging.  I fixed it up this
time.

Thanks,

James


--
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 v3 1/6] scsi: ufs: wrap the i/o access operations

2013-05-06 Thread Seungwon Jeon
On Tuesday, May 07, 2013, Santosh Y wrote:
> On Mon, May 6, 2013 at 11:07 AM, 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 = ufs

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

2013-05-06 Thread Seungwon Jeon
On Tuesday, May 07, 2013, Santosh Y wrote:
> >  /**
> > + * ufshcd_dme_power_xxx - 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_xxx(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_xxx);
> > +
> > +/**
> > + * ufshcd_dme_hibern8_xxx - 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_xxx(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:%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_xxx);
> > +
> 
> 
> power/hibernate functions can also be renamed as
> ufshcd_dme_power/hibernate_config(struct ufs_hba *hba, bool
> enable/enter) or similar instead of xxx.
Ok, I'll change the names including dme_get/set.
If you have further views, please let me know.

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 v3 0/4] Patchset to use PCLMULQDQ to accelerate CRC-T10DIF checksum computation

2013-05-06 Thread Tim Chen
On Wed, 2013-05-01 at 12:52 -0700, Tim Chen wrote:
> Currently the CRC-T10DIF checksum is computed using a generic table lookup
> algorithm.  By switching the checksum to PCLMULQDQ based computation,
> we can speedup the computation by 8x for checksumming 512 bytes and
> even more for larger buffer size.  This will improve performance of SCSI
> drivers turning on the CRC-T10IDF checksum.  In our SSD based experiments,
> we have seen increase disk throughput by 3.5x with T10DIF for 512 byte
> block size.
> 
> This patch set provides the x86_64 routine using PCLMULQDQ instruction
> and switches the crc_t10dif library function to use the faster PCLMULQDQ
> based routine when available.
> 
> Tim
> 
> v3
> 1. Update the crct10dif crypto transform used in the crct10dif library in a 
> safe way.
> 2. Load the accelerated t10dif transform for the x86_64 cpus that support it.
> 3. Added generic crct10dif crypto transform.
> 

Herbert,

Any feedback on this updated patchset?  Thanks.

Tim

--
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


PING^6 Re: [PATCH v2 00/14] Corrections and customization of the SG_IO command whitelist (CVE-2012-4542)

2013-05-06 Thread Paolo Bonzini
Il 20/02/2013 17:12, Paolo Bonzini ha scritto:
> Il 06/02/2013 16:15, Paolo Bonzini ha scritto:
>> This series regards the whitelist that is used for the SG_IO ioctl.  This
>> whitelist has three problems:
>>
>> * the bitmap of allowed commands is designed for MMC devices (roughly,
>>   "play/burn CDs without requiring root") but some opcodes overlap across 
>> SCSI
>>   device classes and have different meanings for different classes.
>>
>> * also because the bitmap of allowed commands is designed for MMC devices
>>   only, some commands are missing even though they are generally useful and
>>   not insecure.  At least not more insecure than anything else you can
>>   do if you have access to /dev/sdX or /dev/stX nodes.
>>
>> * the whitelist can be disabled per-process but not per-disk.  In addition,
>>   the required capability (CAP_SYS_RAWIO) gives access to a range of other 
>>   resources, enough to make it insecure.
>>
>> The series corrects these problems.  Patches 1-4 solve the first problem,
>> which also has an assigned CVE, by using different bitmaps for the various
>> device classes.  Patches 5-11 solve the second by adding more commands
>> to the bitmaps.  Patches 12 and 13 solve the third, and were already
>> posted but ignored by the maintainers despite multiple pings.
>>
>> Note: checkpatch hates the formatting of the command table.  I know about 
>> this,
>> and ensured that there are no errors in the rest of the code.  The current
>> formatting is IMHO quite handy, and roughly based on the files available
>> from the SCSI standard body.
>>
>> Ok for the next merge window?
>>
>> Paolo
>>
>> v1->v2: remove 2 MMC commands and 6 SBC commands (see patches 6 and 9
>> for details).  Added patch 14 and added a few more scanner
>> commands based on SANE (scanners are not whitelisted by default,
>> also were not in v1, but this makes it possible to opt into the
>> whitelist out of paranoia).  Removed C++ comments.  Removed the
>> large #if 0'd list of commands that the kernel does not pass
>> though.  Marked blk_set_cmd_filter_defaults as __init.
> 
> Ping...
> 
> Jens/James, is anyone going to pick this up for 3.9?
> 
> Paolo
> 
>>
>> Paolo Bonzini (14):
>>   sg_io: pass request_queue to blk_verify_command
>>   sg_io: reorganize list of allowed commands
>>   sg_io: use different default filters for each device class
>>   sg_io: resolve conflicts between commands assigned to multiple
>> classes (CVE-2012-4542)
>>   sg_io: whitelist a few more commands for rare & obsolete device types
>>   sg_io: whitelist another command for multimedia devices
>>   sg_io: whitelist a few more commands for media changers
>>   sg_io: whitelist a few more commands for tapes
>>   sg_io: whitelist a few more commands for disks
>>   sg_io: whitelist a few obsolete commands
>>   sg_io: mark blk_set_cmd_filter_defaults as __init
>>   sg_io: remove remnants of sysfs SG_IO filters
>>   sg_io: introduce unpriv_sgio queue flag
>>   sg_io: use unpriv_sgio to disable whitelisting for scanners
>>
>>  Documentation/block/queue-sysfs.txt |8 +
>>  block/blk-sysfs.c   |   33 +++
>>  block/bsg.c |2 +-
>>  block/scsi_ioctl.c  |  369 
>> ++-
>>  drivers/scsi/scsi_scan.c|   14 ++-
>>  drivers/scsi/sg.c   |6 +-
>>  include/linux/blkdev.h  |8 +-
>>  include/linux/genhd.h   |9 -
>>  include/scsi/scsi.h |3 +
>>  9 files changed, 344 insertions(+), 108 deletions(-)
>>
> 

--
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 v3 6/6] scsi: ufs: add dme control primitives

2013-05-06 Thread Santosh Y
>  /**
> + * ufshcd_dme_power_xxx - 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_xxx(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_xxx);
> +
> +/**
> + * ufshcd_dme_hibern8_xxx - 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_xxx(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:%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_xxx);
> +


power/hibernate functions can also be renamed as
ufshcd_dme_power/hibernate_config(struct ufs_hba *hba, bool
enable/enter) or similar instead of xxx.


-- 
~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: notify userspace of offline -> running transitions

2013-05-06 Thread Ewan Milne
http://marc.info/?l=linux-scsi&m=133769378525796&w=2

Did anything ever happen with this?  I don't see that it did.

There seems to be a problem with udev processing an event
for a device at a time when the device can't be accessed.
Mike's original fix was to generate another KOBJ_CHANGE
event when the device comes back online, so that subsequent
udev rule processing would succeed.  Even so, the device
could become inaccessible again by the time the event was
actually processed by udev (if udevd was overloaded...)

-Ewan




--
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 v3 5/6] scsi: ufs: add dme configuration primitives

2013-05-06 Thread Santosh Y
>
>  /**
> + * ufshcd_dme_xxx_set - 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_xxx_set(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);
> +
> +   dev_dbg(hba->dev, "%s: error code %d\n", set, ret);
> +
> +   return ret;
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_dme_xxx_set);
> +
> +/**
> + * ufshcd_dme_xxx_get - 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_xxx_get(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 (mib_val)
> +   *mib_val = uic_cmd.argument3;
> +
> +   dev_dbg(hba->dev, "%s: error code %d\n", get, ret);
> +
> +   return ret;
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_dme_xxx_get);
> +
> +/**
>   * ufshcd_make_hba_operational - Make UFS controller operational
>   * @hba: per adapter instance
>   *
> @@ -1531,6 +1613,8 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba)
>  {
> 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..93965b9 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_xxx_set(struct ufs_hba *hba, u32 attr_sel,
> + u8 attr_set, u32 mib_val, u8 peer);
> +extern int ufshcd_dme_xxx_get(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_DISABLE,  REG_CONTROLLER_ENABLE);
>  }
>
> +/* UIC command interfaces for DME primitives */
> +static inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel,
> +u8 attr_set, u32 mib_val)
> +{
> +   return ufshcd_dme_xxx_set(hba, attr_sel, attr_set, mib_val, 0);
> +}
> +
> +static inline int ufshcd_dme_peer_set(struct ufs_hba *hba, u32 attr_sel,
> + u8 attr_set, u32 mib_val)
> +{
> +   return ufshcd_dme_xxx_set(hba, attr_sel, attr_set, mib_val, 1);
> +}
> +
> +static inline int ufshcd_dme_get(struct ufs_hba *hba,
> +u32 attr_sel, u32 *mib_val)
> +{
> +   return ufshcd_dme_xxx_get(hba, attr_sel, mib_val, 0);
> +}
> +
> +static inline int ufshcd_dme_peer_get(struct ufs_hba *hba,
> + u32 attr_sel, u32 *mib_val)
> +{
> +   return ufshcd_dme_xxx_get(hba, attr_sel, mib_val, 1);
> +}
> +

ufshcd_dme_xxx_get/set() are being used to configure attributes. So it
is better to rename them as ufshcd_dme_attr_get/set().

-- 
~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 v3 1/6] scsi: ufs: wrap the i/o access operations

2013-05-06 Thread Santosh Y
On Mon, May 6, 2013 at 11:07 AM, 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)
>  {
>  

Re: 32-byte CDB support in Libsas?

2013-05-06 Thread James Bottomley
On Mon, 2013-05-06 at 11:41 -0700, Kamaljit Singh wrote:
> Are there any plans to add 32-byte CDB support in Libsas?

I don't understand the question ... it should just work; is it broken?

James


--
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


32-byte CDB support in Libsas?

2013-05-06 Thread Kamaljit Singh
Hello,

Are there any plans to add 32-byte CDB support in Libsas?

Thanks,

Kamaljit Singh


--
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/12] pm80xx: Added SPCv/ve specific ids, variables and modify for SPC

2013-05-06 Thread James Bottomley
On Mon, 2013-05-06 at 09:48 -0700, Anand Kumar Santhanam wrote:
> Hi James,
> 
> I have resubmitted the patchset after fixing the array out of bounds
> issue. Pls pull the same.
> 
> I guess I did not make myself clear with my earlier mail. I compiled my
> earlier patchset using the 
> Kernel Makefile and I did not get the array out of bounds warning even I
> had -Wall -O2 flags enabled.
> So I was just wondering whether you are using any special settings such
> that you are able to see the 
> warning.

Oh, OK, that's not what I read in the email, so sorry for being brusque.
What -Wall actually does is highly gcc version dependent.  What I did
was simply a standard kernel compile (no extra flags), but with
gcc-4.7.2

James


--
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 1/1] scsi: ufs: Set fDeviceInit flag to initiate device initialization

2013-05-06 Thread merez
Tested-by: Maya Erez 

> 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|   10 -
>  drivers/scsi/ufs/ufshcd.c |  102
> +
>  drivers/scsi/ufs/ufshcd.h |7 +++
>  3 files changed, 118 insertions(+), 1 deletions(-)
>
> 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 4090f6c..21aa0b4 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -52,6 +52,15 @@
>  /* Reserved tag for internal commands */
>  #define INTERNAL_CMD_TAG   0
>
> +/* Query request standard 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,
> @@ -952,6 +961,57 @@ int ufshcd_query_request(struct ufs_hba *hba,
>  }
>
>  /**
> + * 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
>   *
> @@ -1384,6 +1444,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_validate_device_init(struct ufs_hba *hba)
> +{
> + int i, err;
> + bool flag_res = 0;
> +
> + err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_SET_FLAG,
> + QUERY_FLAG_IDN_FDEVICEINIT, &flag_res);
> + if (err) {
> + dev_err(hba->dev,
> + "%s setting fDeviceInit flag failed with error %d\n",
> + __func__, err);
> + goto out;
> + }
> +
> + for (i = 0; i < QUERY_REQ_RETRIES && !err && flag_res; i++) {
> + err

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

2013-05-06 Thread merez

> On Monday, May 06, 2013, Sujit Reddy Thumma wrote:
>> On 5/6/2013 11:07 AM, 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.
>> We have seen a kernel crash when the timeout happens in our internal
>> testing. This is basically because the the UIC_CMD_TIMEOUT of 500msec is
>> less for our platform. We see UIC_COMMAND_COMPL interrupt after this
>> timeout and since uic_cmd is freed we see a kernel crash.
>>
>> [6.026094] ufshcd :01:00.0: link startup: error code -110
>> [6.030886] ufshcd :01:00.0: link startup failed -110
>> ...
>>
>> [6.487288] BUG: spinlock bad magic on CPU#0, swapper/0/0
>> [6.491683] Unable to handle kernel paging request at virtual address
>> 612b
>> ...
>> [7.625270] [] (spin_dump+0x4c/0x88) from []
>> (do_raw_spin_lock+0x20/0x154)
>> [7.633877] [] (do_raw_spin_lock+0x20/0x154) from
>> [] (_raw_spin_lock_irqsave+0x28/0x30)
>> [7.643583] [] (_raw_spin_lock_irqsave+0x28/0x30) from
>> [] (complete+0x1c/0x58)
>> [7.652525] [] (complete+0x1c/0x58) from []
>> (ufshcd_intr+0x1a8/0x498)
>> [7.660705] [] (ufshcd_intr+0x1a8/0x498) from []
>> (handle_irq_event_percpu+0xb0/0x290)
>> [7.670227] [] (handle_irq_event_percpu+0xb0/0x290) from
>> [] (handle_irq_event+0x3c/0x5c)
>> [7.680054] [] (handle_irq_event+0x3c/0x5c) from
>> [] (handle_fasteoi_irq+0xdc/0x148)
>> [7.689424] [] (handle_fasteoi_irq+0xdc/0x148) from
>> [] (generic_handle_irq+0x30/0x44)
>> [7.698977] [] (generic_handle_irq+0x30/0x44) from
>> [] (handle_IRQ+0x7c/0xc0)
>> [7.707736] [] (handle_IRQ+0x7c/0xc0) from []
>> (gic_handle_irq+0x94/0x110)
>> [7.716252] [] (gic_handle_irq+0x94/0x110) from
>> [] (__irq_svc+0x40/0x70)
>>
>>
>> Following would fix this. Please check. Also, we need to increase the
>> timeout to say 5 secs to avoid such races.
> Thank you for test.
> I have seen the completion of link startup within current timeout ever.
> It should be fixed for that case.
> By the way, I feel 5 seconds looks like a little too long.
> Currently, is your platform situation with UFS in normal stage?
> The UNIPRO spec. mentions the 100 ms as timeout internally for link
> startup.
> Anyway, do you mean that you want to change timeout value to 5 seconds?
> I think it has a strong dependency with your platform.
> 1 sec seems proper though the worst case is considered.
>
> Thanks,
> Seungwon Jeon

I agree, you can keep a timeout of 500ms. I got the timeout due to a
unipro issue and not due to low timeout value.

Thanks,
Maya
>
>>
>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>> index ecbae40..ae22a8e 100644
>> --- a/drivers/scsi/ufs/ufshcd.c
>> +++ b/drivers/scsi/ufs/ufshcd.c
>> @@ -485,6 +485,7 @@ 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)))
>> @@ -492,6 +493,10 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct
>> uic_command *uic_cmd)
>>  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;
>>  }
>>
>> @@ -1842,7 +1847,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,
>> struct ufshcd_lrb *lrbp)
>>   */
>>  static void ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
>>  {
>> -if (intr_status & UIC_COMMAND_COMPL) {
>> +if (hba->active_uic_cmd && (intr_status & UIC_COMMAND_COMPL)) {
>>  hba->active_uic_cmd->argument2 |=
>>  ufshcd_get_uic_cmd_result(hba);
>>  hba->active_uic_cmd->argument3 =
>>
>>
>> > 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 
>> > ---
>> >   drivers/scsi/ufs/ufshcd.c |  287
>> ++---
>> >   drivers/scsi/ufs/ufshcd.h |   10 +-
>> >   2 files changed, 200 insertions(+), 97 deletions(-)
>> >
>> > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>> > index e04c74e..118f104 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 |\
>> >

Re: linux-next: Tree for May 6 (lpfc)

2013-05-06 Thread Randy Dunlap
On 05/06/13 09:49, James Bottomley wrote:
> On Mon, 2013-05-06 at 09:14 -0700, Randy Dunlap wrote:
>> On 05/05/13 21:42, Stephen Rothwell wrote:
>>> Hi all,
>>>
>>> Please do not add any v3.11 destined work to your linux-next included
>>> branches until after v3.10-rc1 is released.
>>>
>>> I am receiving a (un)reasonable number of conflicts from there being
>>> multiple copies of some commits in various trees.   Please clean this up
>>> and resist the temptataion to rebase your trees on the way to your
>>> upstream ...
>>>
>>> Changes since 20130506:
>>>
>>
>> on i386:
>> # CONFIG_CRC_T10DIF is not set
>>
>>
>> drivers/built-in.o: In function `lpfc_bg_crc':
>> (.text+0x3cb3c9): undefined reference to `crc_t10dif'
> 
> That's the usual minor config cockup, isn't it?  lpfc apparently also
> needs the generic checksum, so the fix would seem to be this.
> 
> James
> 

Thanks, that works.

for your S-O-B patch:
Acked-by: Randy Dunlap 


> ---
> diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
> index db95c54..86af29f 100644
> --- a/drivers/scsi/Kconfig
> +++ b/drivers/scsi/Kconfig
> @@ -1353,6 +1353,8 @@ config SCSI_LPFC
>   tristate "Emulex LightPulse Fibre Channel Support"
>   depends on PCI && SCSI
>   select SCSI_FC_ATTRS
> + select GENERIC_CSUM
> + select CRC_T10DIF
>   help
>This lpfc driver supports the Emulex LightPulse
>Family of Fibre Channel PCI host adapters.
> 
> 
> --


-- 
~Randy
--
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: linux-next: Tree for May 6 (lpfc)

2013-05-06 Thread Martin K. Petersen
> "James" == James Bottomley  writes:

>> drivers/built-in.o: In function `lpfc_bg_crc': (.text+0x3cb3c9):
>> undefined reference to `crc_t10dif'

James> That's the usual minor config cockup, isn't it?  lpfc apparently
James> also needs the generic checksum, so the fix would seem to be
James> this.

Patch ok as a short term fix.

Longer term I'd like to provide a helper function that HBAs can call to
validate the data and PI scatterlists.

-- 
Martin K. Petersen  Oracle Linux Engineering
--
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-06 Thread Mike Christie
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.

iscsi class, qla4xxx: fix sess/conn refcounting when find fns are used

This fixes a bug where the iscsi class/driver did not do a put_device
when a sess/conn device was found. This also simplifies the interface
by not having to pass in some arguments that were duplicated and did
not need to be exported.

Signed-off-by: Mike Christie 

diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index d777332..4d231c1 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;
}
 
@@ -6112,8 +6113,7 @@ qla4xxx_sysfs_ddb_get_param(struct 
iscsi_bus_flash_session *fnode_sess,
int parent_type, parent_index = 0x;
int rc = 0;
 
-   dev = iscsi_find_flashnode_conn(fnode_sess, NULL,
-   iscsi_is_flashnode_conn_dev);
+   dev = iscsi_find_flashnode_conn(fnode_sess);
if (!dev)
return -EIO;
 
@@ -6347,6 +6347,8 @@ qla4xxx_sysfs_ddb_get_param(struct 
iscsi_bus_flash_session *fnode_sess,
rc = -ENOSYS;
break;
}
+
+   put_device(dev);
return rc;
 }
 
diff --git a/drivers/scsi/scsi_transport_iscsi.c 
b/drivers/scsi/scsi_transport_iscsi.c
index 475265a..133926b 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1019,8 +1019,7 @@ exit_match_index:
 /**
  * iscsi_get_flashnode_by_index -finds flashnode session entry by index
  * @shost: pointer to host data
- * @data: pointer to data containing value to use for comparison
- * @fn: function pointer that does actual comparison
+ * @idx: index to match
  *
  * Finds the flashnode session object for the passed index
  *
@@ -1029,13 +1028,13 @@ exit_match_index:
  *  %NULL on failure
  */
 static struct iscsi_bus_flash_session *
-iscsi_get_flashnode_by_index(struct Scsi_Host *shost, void *data,
-int (*fn)(struct device *dev, void *data))
+iscsi_get_flashnode_by_index(struct Scsi_Host *shost, uint32_t idx)
 {
struct iscsi_bus_flash_session *fnode_sess = NULL;
struct device *dev;
 
-   dev = device_find_child(&shost->shost_gendev, data, fn);
+   dev = device_find_child(&shost->shost_gendev, &idx,
+   flashnode_match_index);
if (dev)
fnode_sess = iscsi_dev_to_flash_session(dev);
 
@@ -1059,18 +1058,13 @@ struct device *
 iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data,
  int (*fn)(struct device *dev, void *data))
 {
-   struct device *dev;
-
-   dev = device_find_child(&shost->shost_gendev, data, fn);
-   return dev;
+   return device_find_child(&shost->shost_gendev, data, fn);
 }
 EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess);
 
 /**
  * iscsi_find_flashnode_conn - finds flashnode connection entry
  * @fnode_sess: pointer to parent flashnode session entry
- * @data: pointer to data containing value to use for comparison
- * @fn: function pointer that does actual comparison
  *
  * Finds the flashnode connection object comparing the data passed using logic
  * defined in passed function pointer
@@ -1080,14 +1074,10 @@ EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess);
  *  %NULL on failure
  */
 struct device *
-iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess,
- void *data,
- int (*fn)(struct device *dev, void *data))
+iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess)
 {
-   struct device *dev;
-
- 

Re: linux-next: Tree for May 6 (lpfc)

2013-05-06 Thread James Bottomley
On Mon, 2013-05-06 at 09:14 -0700, Randy Dunlap wrote:
> On 05/05/13 21:42, Stephen Rothwell wrote:
> > Hi all,
> > 
> > Please do not add any v3.11 destined work to your linux-next included
> > branches until after v3.10-rc1 is released.
> > 
> > I am receiving a (un)reasonable number of conflicts from there being
> > multiple copies of some commits in various trees.   Please clean this up
> > and resist the temptataion to rebase your trees on the way to your
> > upstream ...
> > 
> > Changes since 20130506:
> > 
> 
> on i386:
> # CONFIG_CRC_T10DIF is not set
> 
> 
> drivers/built-in.o: In function `lpfc_bg_crc':
> (.text+0x3cb3c9): undefined reference to `crc_t10dif'

That's the usual minor config cockup, isn't it?  lpfc apparently also
needs the generic checksum, so the fix would seem to be this.

James

---
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index db95c54..86af29f 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1353,6 +1353,8 @@ config SCSI_LPFC
tristate "Emulex LightPulse Fibre Channel Support"
depends on PCI && SCSI
select SCSI_FC_ATTRS
+   select GENERIC_CSUM
+   select CRC_T10DIF
help
   This lpfc driver supports the Emulex LightPulse
   Family of Fibre Channel PCI host adapters.


--
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/12] pm80xx: Added SPCv/ve specific ids, variables and modify for SPC

2013-05-06 Thread Anand Kumar Santhanam
Hi James,

I have resubmitted the patchset after fixing the array out of bounds
issue. Pls pull the same.

I guess I did not make myself clear with my earlier mail. I compiled my
earlier patchset using the 
Kernel Makefile and I did not get the array out of bounds warning even I
had -Wall -O2 flags enabled.
So I was just wondering whether you are using any special settings such
that you are able to see the 
warning.

Regards
Anand

-Original Message-
From: James Bottomley [mailto:james.bottom...@hansenpartnership.com] 
Sent: Friday, May 03, 2013 11:29 AM
To: Anand Kumar Santhanam
Cc: linux-scsi@vger.kernel.org; Harry Yang; Vishwanath Maram;
sakthivel...@hcl.com; Rich Bono; Sangeetha Gnanasekaran
Subject: Re: [PATCH V4 2/12] pm80xx: Added SPCv/ve specific ids,
variables and modify for SPC

On Thu, 2013-05-02 at 19:26 -0700, Anand Kumar Santhanam wrote:
> James,
>  
> Can you pls let us know the warning flags you are including in your 
> makefile such that we can check from our end.
> Obviously it looks like we did not use -Warray-bounds in this case.

Oh good grief, please stop wasting my time.  You have the definition
here in your patch:

> + u32 rsvd1[2];

And then you use it as:

> + pm8001_ha->gs_tbl.pm8001_tbl.rsvd1[0]   =
> + pm8001_mr32(address, 0x38);
> + pm8001_ha->gs_tbl.pm8001_tbl.rsvd1[1]   =
> + pm8001_mr32(address, 0x3C);
> + pm8001_ha->gs_tbl.pm8001_tbl.rsvd1[2]   =
> + pm8001_mr32(address, 0x40);

That last one goes over the array bounds because an array declared as
rsvdl1[2] only has two elements: 0 and 1 ... this isn't rocket science
or esoteric compiler flags, this is basic C.

Stop quibbling and fix it, please.

James


--
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 1/1] Create megaraid ioctl device node

2013-05-06 Thread Patrick Monnerat
On 05/06/2013 04:23 PM, Bjørn Mork wrote:
> "Patrick Monnerat"  writes:
>>Create ioctl device node for megaraid_sas driver. Let this node be
>> managed by udev. Fix a typo.
>
> Or maybe just simplify it all and use a misc device instead?  See how
> this is done in e.g. drivers/scsi/mpt3sas/mpt3sas_ctl.c or
> drivers/message/fusion/mptctl.c

Yes, could be done that way, but I want to retain compatibility with 
existing shell scripts doing things like:


DEVICE=/dev/megaraid_sas_ioctl_node
DEVICENAME=megaraid_sas_ioctl
DEVICEPERM=400
MAJOR=`grep "$DEVICENAME" /proc/devices | awk '{print $1}'`

if [ -n "$MAJOR" -a ! -e "$DEVICE" ]; then
 mknod "$DEVICE" c "$MAJOR" 0
 chmod "$DEVICEPERM" "$DEVICE"
fi



[PATCH V5 12/12] pm80xx: thermal, sas controller config and error handling update

2013-05-06 Thread Anand
>From ffe82b1efc42510239046909a7ac0aff10bb4162 Mon Sep 17 00:00:00 2001
From: Sakthivel K 
Date: Tue, 19 Mar 2013 18:08:40 +0530
Subject: [PATCH V5 12/12] pm80xx: thermal, sas controller config and error 
handling update

Modified thermal configuration to happen after interrupt registration
Added SAS controller configuration during initialization
Added error handling logic to handle I_T_Nexus errors and variants

Signed-off-by: Anand Kumar S 
Acked-by: Jack Wang 
Reviewed-by: Hannes Reinecke  
---
 drivers/scsi/pm8001/pm8001_hwi.c  |2 +-
 drivers/scsi/pm8001/pm8001_init.c |2 +
 drivers/scsi/pm8001/pm8001_sas.c  |   66 
 drivers/scsi/pm8001/pm8001_sas.h  |2 +
 drivers/scsi/pm8001/pm80xx_hwi.c  |  150 +
 drivers/scsi/pm8001/pm80xx_hwi.h  |   44 +++-
 6 files changed, 249 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index a90c002..d18f421 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1670,7 +1670,7 @@ void pm8001_work_fn(struct work_struct *work)
}   break;
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
dev = pm8001_dev->sas_device;
-   pm8001_I_T_nexus_reset(dev);
+   pm8001_I_T_nexus_event_handler(dev);
break;
case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
dev = pm8001_dev->sas_device;
diff --git a/drivers/scsi/pm8001/pm8001_init.c 
b/drivers/scsi/pm8001/pm8001_init.c
index 055f7d0..1c71852 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -838,6 +838,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
if (pm8001_ha->chip_id != chip_8001) {
for (i = 1; i < pm8001_ha->number_of_intr; i++)
PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i);
+   /* setup thermal configuration. */
+   pm80xx_set_thermal_config(pm8001_ha);
}
 
pm8001_init_sas_add(pm8001_ha);
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index c720917..9af9585 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -1018,6 +1018,72 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)
return rc;
 }
 
+/*
+* This function handle the IT_NEXUS_XXX event or completion
+* status code for SSP/SATA/SMP I/O request.
+*/
+int pm8001_I_T_nexus_event_handler(struct domain_device *dev)
+{
+   int rc = TMF_RESP_FUNC_FAILED;
+   struct pm8001_device *pm8001_dev;
+   struct pm8001_hba_info *pm8001_ha;
+   struct sas_phy *phy;
+   u32 device_id = 0;
+
+   if (!dev || !dev->lldd_dev)
+   return -1;
+
+   pm8001_dev = dev->lldd_dev;
+   device_id = pm8001_dev->device_id;
+   pm8001_ha = pm8001_find_ha_by_dev(dev);
+
+   PM8001_EH_DBG(pm8001_ha,
+   pm8001_printk("I_T_Nexus handler invoked !!"));
+
+   phy = sas_get_local_phy(dev);
+
+   if (dev_is_sata(dev)) {
+   DECLARE_COMPLETION_ONSTACK(completion_setstate);
+   if (scsi_is_sas_phy_local(phy)) {
+   rc = 0;
+   goto out;
+   }
+   /* send internal ssp/sata/smp abort command to FW */
+   rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
+   dev, 1, 0);
+   msleep(100);
+
+   /* deregister the target device */
+   pm8001_dev_gone_notify(dev);
+   msleep(200);
+
+   /*send phy reset to hard reset target */
+   rc = sas_phy_reset(phy, 1);
+   msleep(2000);
+   pm8001_dev->setds_completion = &completion_setstate;
+
+   wait_for_completion(&completion_setstate);
+   } else {
+   /* send internal ssp/sata/smp abort command to FW */
+   rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
+   dev, 1, 0);
+   msleep(100);
+
+   /* deregister the target device */
+   pm8001_dev_gone_notify(dev);
+   msleep(200);
+
+   /*send phy reset to hard reset target */
+   rc = sas_phy_reset(phy, 1);
+   msleep(2000);
+   }
+   PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n",
+   pm8001_dev->device_id, rc));
+out:
+   sas_put_local_phy(phy);
+
+   return rc;
+}
 /* mandatory SAM-3, the task reset the specified LUN*/
 int pm8001_lu_reset(struct domain_device *dev, u8 *lun)
 {
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index ab30193..72d46ea 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -563,6 +563,7 @@ int pm8001_dev_found(struc

[PATCH V5 11/12] pm80xx: NCQ error handling changes

2013-05-06 Thread Anand
>From 2738e0b59fe103a363b0ea600b3eccc687a7fa3c Mon Sep 17 00:00:00 2001
From: Sakthivel K 
Date: Tue, 19 Mar 2013 18:08:08 +0530
Subject: [PATCH V5 11/12] pm80xx: NCQ error handling changes

Handled NCQ errors in the low level driver as the FW
is not providing the faulty tag for NCQ errors for libsas
to recover.

Signed-off-by: Anand Kumar S 
Acked-by: Jack Wang 
Reviewed-by: Hannes Reinecke  
---
 drivers/scsi/pm8001/pm8001_hwi.c |  270 --
 drivers/scsi/pm8001/pm8001_sas.c |   22 +++-
 drivers/scsi/pm8001/pm8001_sas.h |   15 ++-
 drivers/scsi/pm8001/pm80xx_hwi.c |  262 +++--
 drivers/scsi/pm8001/pm80xx_hwi.h |1 +
 5 files changed, 543 insertions(+), 27 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 265dbf4..a90c002 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1707,6 +1707,123 @@ int pm8001_handle_event(struct pm8001_hba_info 
*pm8001_ha, void *data,
return ret;
 }
 
+static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha,
+   struct pm8001_device *pm8001_ha_dev)
+{
+   int res;
+   u32 ccb_tag;
+   struct pm8001_ccb_info *ccb;
+   struct sas_task *task = NULL;
+   struct task_abort_req task_abort;
+   struct inbound_queue_table *circularQ;
+   u32 opc = OPC_INB_SATA_ABORT;
+   int ret;
+
+   if (!pm8001_ha_dev) {
+   PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("dev is null \n"));
+   return;
+   }
+
+   task = sas_alloc_slow_task(GFP_ATOMIC);
+
+   if (!task) {
+   PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot "
+   "allocate task \n"));
+   return;
+   }
+
+   task->task_done = pm8001_task_done;
+
+   res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
+   if (res)
+   return;
+
+   ccb = &pm8001_ha->ccb_info[ccb_tag];
+   ccb->device = pm8001_ha_dev;
+   ccb->ccb_tag = ccb_tag;
+   ccb->task = task;
+
+   circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+   memset(&task_abort, 0, sizeof(task_abort));
+   task_abort.abort_all = cpu_to_le32(1);
+   task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
+   task_abort.tag = cpu_to_le32(ccb_tag);
+
+   ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
+
+}
+
+static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha,
+   struct pm8001_device *pm8001_ha_dev)
+{
+   struct sata_start_req sata_cmd;
+   int res;
+   u32 ccb_tag;
+   struct pm8001_ccb_info *ccb;
+   struct sas_task *task = NULL;
+   struct host_to_dev_fis fis;
+   struct domain_device *dev;
+   struct inbound_queue_table *circularQ;
+   u32 opc = OPC_INB_SATA_HOST_OPSTART;
+
+   task = sas_alloc_slow_task(GFP_ATOMIC);
+
+   if (!task) {
+   PM8001_FAIL_DBG(pm8001_ha,
+   pm8001_printk("cannot allocate task !!!\n"));
+   return;
+   }
+   task->task_done = pm8001_task_done;
+
+   res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
+   if (res) {
+   PM8001_FAIL_DBG(pm8001_ha,
+   pm8001_printk("cannot allocate tag !!!\n"));
+   return;
+   }
+
+   /* allocate domain device by ourselves as libsas
+* is not going to provide any
+   */
+   dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC);
+   if (!dev) {
+   PM8001_FAIL_DBG(pm8001_ha,
+   pm8001_printk("Domain device cannot be allocated \n"));
+   sas_free_task(task);
+   return;
+   } else {
+   task->dev = dev;
+   task->dev->lldd_dev = pm8001_ha_dev;
+   }
+
+   ccb = &pm8001_ha->ccb_info[ccb_tag];
+   ccb->device = pm8001_ha_dev;
+   ccb->ccb_tag = ccb_tag;
+   ccb->task = task;
+   pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
+   pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
+
+   memset(&sata_cmd, 0, sizeof(sata_cmd));
+   circularQ = &pm8001_ha->inbnd_q_tbl[0];
+
+   /* construct read log FIS */
+   memset(&fis, 0, sizeof(struct host_to_dev_fis));
+   fis.fis_type = 0x27;
+   fis.flags = 0x80;
+   fis.command = ATA_CMD_READ_LOG_EXT;
+   fis.lbal = 0x10;
+   fis.sector_count = 0x1;
+
+   sata_cmd.tag = cpu_to_le32(ccb_tag);
+   sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
+   sata_cmd.ncqtag_atap_dir_m |= ((0x1 << 7) | (0x5 << 9));
+   memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
+
+   res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
+
+}
+
 /**
  * mpi_ssp_completion- process the event that FW response to the SSP request.
  * @pm8001_ha: our hba card information
@@ -2170,16 +2287,44 @@ mpi_sata_completion(struct pm8001_hba_i

[PATCH V5 10/12] pm80xx: WWN Modification for PM8081/88/89 controllers

2013-05-06 Thread Anand
>From 6fb08e45a7272daecc4b8bdce643e40fd2062542 Mon Sep 17 00:00:00 2001
From: Sakthivel K 
Date: Tue, 19 Mar 2013 18:07:35 +0530
Subject: [PATCH V5 10/12] pm80xx: WWN Modification for PM8081/88/89 controllers

Individual WWN read operations based on controller.
PM8081 - Read WWN from Flash VPD.
PM8088/89 - Read WWN from EEPROM.
PM8001 - Read WWN from NVM.

Signed-off-by: Sakthivel K 
Signed-off-by: Anand Kumar S 
Acked-by: Jack Wang 
Reviewed-by: Hannes Reinecke  
---
 drivers/scsi/pm8001/pm8001_init.c |   43 +++--
 1 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_init.c 
b/drivers/scsi/pm8001/pm8001_init.c
index 0c14dc0..055f7d0 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -605,21 +605,50 @@ static void  pm8001_post_sas_ha_init(struct Scsi_Host 
*shost,
  */
 static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
 {
-   u8 i;
+   u8 i, j;
 #ifdef PM8001_READ_VPD
+   /* For new SPC controllers WWN is stored in flash vpd
+   *  For SPC/SPCve controllers WWN is stored in EEPROM
+   *  For Older SPC WWN is stored in NVMD
+   */
DECLARE_COMPLETION_ONSTACK(completion);
struct pm8001_ioctl_payload payload;
+   u16 deviceid;
+   pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
pm8001_ha->nvmd_completion = &completion;
-   payload.minor_function = 0;
-   payload.length = 128;
-   payload.func_specific = kzalloc(128, GFP_KERNEL);
+
+   if (pm8001_ha->chip_id == chip_8001) {
+   if (deviceid == 0x8081) {
+   payload.minor_function = 4;
+   payload.length = 4096;
+   } else {
+   payload.minor_function = 0;
+   payload.length = 128;
+   }
+   } else {
+   payload.minor_function = 1;
+   payload.length = 4096;
+   }
+   payload.offset = 0;
+   payload.func_specific = kzalloc(payload.length, GFP_KERNEL);
PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
wait_for_completion(&completion);
+
+   for (i = 0, j = 0; i <= 7; i++, j++) {
+   if (pm8001_ha->chip_id == chip_8001) {
+   if (deviceid == 0x8081)
+   pm8001_ha->sas_addr[j] =
+   payload.func_specific[0x704 + i];
+   } else
+   pm8001_ha->sas_addr[j] =
+   payload.func_specific[0x804 + i];
+   }
+
for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
-   memcpy(&pm8001_ha->phy[i].dev_sas_addr, pm8001_ha->sas_addr,
-   SAS_ADDR_SIZE);
+   memcpy(&pm8001_ha->phy[i].dev_sas_addr,
+   pm8001_ha->sas_addr, SAS_ADDR_SIZE);
PM8001_INIT_DBG(pm8001_ha,
-   pm8001_printk("phy %d sas_addr = %016llx \n", i,
+   pm8001_printk("phy %d sas_addr = %016llx\n", i,
pm8001_ha->phy[i].dev_sas_addr));
}
 #else
-- 
1.7.1

--
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 V5 09/12] pm80xx: Changed module name and debug messages update

2013-05-06 Thread Anand
>From 8d5db4d3d00604c8dc3db6e616ed21e0c46bcbaf Mon Sep 17 00:00:00 2001
From: Sakthivel K 
Date: Tue, 19 Mar 2013 18:07:09 +0530
Subject: [PATCH V5 09/12] pm80xx: Changed module name and debug messages update

Changed name in driver to pm80xx. Updated debug messages.

Signed-off-by: Sakthivel K 
Signed-off-by: Anand Kumar S 
Acked-by: Jack Wang 
Reviewed-by: Hannes Reinecke  
---
 drivers/scsi/pm8001/pm8001_hwi.c  |   11 ++-
 drivers/scsi/pm8001/pm8001_init.c |   14 ++
 drivers/scsi/pm8001/pm8001_sas.h  |8 
 3 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index c124fc6..265dbf4 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -2506,9 +2506,9 @@ static void mpi_sata_event(struct pm8001_hba_info 
*pm8001_ha , void *piomb)
if (unlikely(!t || !t->lldd_task || !t->dev))
return;
ts = &t->task_status;
-   PM8001_IO_DBG(pm8001_ha,
-   pm8001_printk("port_id = %x,device_id = %x\n",
-   port_id, dev_id));
+   PM8001_IO_DBG(pm8001_ha, pm8001_printk(
+   "port_id:0x%x, device_id:0x%x, tag:0x%x, event:0x%x\n",
+   port_id, dev_id, tag, event));
switch (event) {
case IO_OVERFLOW:
PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n"));
@@ -4409,8 +4409,9 @@ int pm8001_chip_abort_task(struct pm8001_hba_info 
*pm8001_ha,
 {
u32 opc, device_id;
int rc = TMF_RESP_FUNC_FAILED;
-   PM8001_EH_DBG(pm8001_ha, pm8001_printk("cmd_tag = %x, abort task tag"
-   " = %x", cmd_tag, task_tag));
+   PM8001_EH_DBG(pm8001_ha,
+   pm8001_printk("cmd_tag = %x, abort task tag = 0x%x",
+   cmd_tag, task_tag));
if (pm8001_dev->dev_type == SAS_END_DEV)
opc = OPC_INB_SSP_ABORT;
else if (pm8001_dev->dev_type == SATA_DEV)
diff --git a/drivers/scsi/pm8001/pm8001_init.c 
b/drivers/scsi/pm8001/pm8001_init.c
index 64168eb..0c14dc0 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -741,7 +741,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
const struct pm8001_chip_info *chip;
 
dev_printk(KERN_INFO, &pdev->dev,
-   "pm8001: driver version %s\n", DRV_VERSION);
+   "pm80xx: driver version %s\n", DRV_VERSION);
rc = pci_enable_device(pdev);
if (rc)
goto err_out_enable;
@@ -789,15 +789,21 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
list_add_tail(&pm8001_ha->list, &hba_list);
PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
-   if (rc)
+   if (rc) {
+   PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+   "chip_init failed [ret: %d]\n", rc));
goto err_out_ha_free;
+   }
 
rc = scsi_add_host(shost, &pdev->dev);
if (rc)
goto err_out_ha_free;
rc = pm8001_request_irq(pm8001_ha);
-   if (rc)
+   if (rc) {
+   PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+   "pm8001_request_irq failed [ret: %d]\n", rc));
goto err_out_shost;
+   }
 
PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
if (pm8001_ha->chip_id != chip_8001) {
@@ -1039,7 +1045,7 @@ static int __init pm8001_init(void)
 {
int rc = -ENOMEM;
 
-   pm8001_wq = alloc_workqueue("pm8001", 0, 0);
+   pm8001_wq = alloc_workqueue("pm80xx", 0, 0);
if (!pm8001_wq)
goto err;
 
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index c6fd99a..89dc227 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -57,8 +57,8 @@
 #include 
 #include "pm8001_defs.h"
 
-#define DRV_NAME   "pm8001"
-#define DRV_VERSION"0.1.36"
+#define DRV_NAME   "pm80xx"
+#define DRV_VERSION"0.1.37"
 #define PM8001_FAIL_LOGGING0x01 /* Error message logging */
 #define PM8001_INIT_LOGGING0x02 /* driver init logging */
 #define PM8001_DISC_LOGGING0x04 /* discovery layer logging */
@@ -66,8 +66,8 @@
 #define PM8001_EH_LOGGING  0x10 /* libsas EH function logging*/
 #define PM8001_IOCTL_LOGGING   0x20 /* IOCTL message logging */
 #define PM8001_MSG_LOGGING 0x40 /* misc message logging */
-#define pm8001_printk(format, arg...)  printk(KERN_INFO "%s %d:" format,\
-   __func__, __LINE__, ## arg)
+#define pm8001_printk(format, arg...)  printk(KERN_INFO "pm80xx %s %d:" \
+   format, __func__, __LINE__, ## arg)
 #define PM8001_CHECK_LOGGING(HBA, LEVEL, CMD)  \
 do {   \
if (unlikely(HBA->logging_level & LEVEL))   \
-- 
1.7.1

--
To unsubscribe from this list: send the line

[PATCH V5 08/12] pm80xx: Firmware flash memory free fix, with addition of new memory region for it

2013-05-06 Thread Anand
>From 4043d1eb8813a2fc0656815fe2e6d21d4df0da66 Mon Sep 17 00:00:00 2001
From: Sakthivel K 
Date: Tue, 19 Mar 2013 18:06:40 +0530
Subject: [PATCH V5 08/12] pm80xx: Firmware flash memory free fix, with addition 
of new memory region for it

Performing pci_free_consistent in tasklet had result in a core dump. So
allocated a new memory region for it. Fix for passing proper address
and operation in firmware flash update.

Signed-off-by: Sakthivel K 
Signed-off-by: Anand Kumar S 
Acked-by: Jack Wang 
Reviewed-by: Hannes Reinecke  
---
 drivers/scsi/pm8001/pm8001_ctl.c  |5 +++--
 drivers/scsi/pm8001/pm8001_defs.h |3 ++-
 drivers/scsi/pm8001/pm8001_hwi.c  |   30 ++
 drivers/scsi/pm8001/pm8001_init.c |3 +++
 4 files changed, 14 insertions(+), 27 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index ae2b124..d99f41c 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -400,10 +400,11 @@ static int pm8001_set_nvmd(struct pm8001_hba_info 
*pm8001_ha)
goto out;
}
payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
-   memcpy((u8 *)payload->func_specific, (u8 *)pm8001_ha->fw_image->data,
+   memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data,
pm8001_ha->fw_image->size);
payload->length = pm8001_ha->fw_image->size;
payload->id = 0;
+   payload->minor_function = 0x1;
pm8001_ha->nvmd_completion = &completion;
ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload);
wait_for_completion(&completion);
@@ -450,7 +451,7 @@ static int pm8001_update_flash(struct pm8001_hba_info 
*pm8001_ha)
payload->length = 1024*16;
payload->id = 0;
fwControl =
- (struct fw_control_info *)payload->func_specific;
+ (struct fw_control_info *)&payload->func_specific;
fwControl->len = IOCTL_BUF_SIZE;   /* IN */
fwControl->size = partitionSize + HEADER_LEN;/* IN */
fwControl->retcode = 0;/* OUT */
diff --git a/drivers/scsi/pm8001/pm8001_defs.h 
b/drivers/scsi/pm8001/pm8001_defs.h
index 26a2ee6..479c5a7 100644
--- a/drivers/scsi/pm8001/pm8001_defs.h
+++ b/drivers/scsi/pm8001/pm8001_defs.h
@@ -86,7 +86,7 @@ enum port_type {
 #definePM8001_MAX_DEVICES   2048   /* max supported device */
 #definePM8001_MAX_MSIX_VEC  64 /* max msi-x int for spcv/ve */
 
-#define USI_MAX_MEMCNT_BASE4
+#define USI_MAX_MEMCNT_BASE5
 #define IB (USI_MAX_MEMCNT_BASE + 1)
 #define CI (IB + PM8001_MAX_SPCV_INB_NUM)
 #define OB (CI + PM8001_MAX_SPCV_INB_NUM)
@@ -99,6 +99,7 @@ enum memory_region_num {
NVMD,   /* NVM device */
DEV_MEM,/* memory for devices */
CCB_MEM,/* memory for command control block */
+   FW_FLASH/* memory for fw flash update */
 };
 #definePM8001_EVENT_LOG_SIZE(128 * 1024)
 
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 3adf499..c124fc6 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3481,10 +3481,6 @@ int pm8001_mpi_fw_flash_update_resp(struct 
pm8001_hba_info *pm8001_ha,
break;
}
ccb->fw_control_context->fw_control->retcode = status;
-   pci_free_consistent(pm8001_ha->pdev,
-   fw_control_context.len,
-   fw_control_context.virtAddr,
-   fw_control_context.phys_addr);
complete(pm8001_ha->nvmd_completion);
ccb->task = NULL;
ccb->ccb_tag = 0x;
@@ -4474,7 +4470,7 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info 
*pm8001_ha,
fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL);
if (!fw_control_context)
return -ENOMEM;
-   fw_control_context->usrAddr = (u8 *)&ioctl_payload->func_specific[0];
+   fw_control_context->usrAddr = (u8 *)ioctl_payload->func_specific;
fw_control_context->len = ioctl_payload->length;
circularQ = &pm8001_ha->inbnd_q_tbl[0];
memset(&nvmd_req, 0, sizeof(nvmd_req));
@@ -4556,7 +4552,7 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info 
*pm8001_ha,
return -ENOMEM;
circularQ = &pm8001_ha->inbnd_q_tbl[0];
memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr,
-   ioctl_payload->func_specific,
+   &ioctl_payload->func_specific,
ioctl_payload->length);
memset(&nvmd_req, 0, sizeof(nvmd_req));
rc = pm8001_tag_alloc(pm8001_ha, &tag);
@@ -4658,29 +4654,14 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info 
*pm8001_ha,
int rc;
u32 tag;
struct 

[PATCH V5 07/12] pm80xx: SPC new firmware changes for device id 0x8081 alone

2013-05-06 Thread Anand
>From 2ce3ecb52358fcd358e1ea93a02522084fc7f968 Mon Sep 17 00:00:00 2001
From: Sakthivel K 
Date: Tue, 19 Mar 2013 18:05:55 +0530
Subject: [PATCH V5 07/12] pm80xx: SPC new firmware changes for device id 0x8081 
alone

Additional bar shift for new SPC firmware, applicable to device
id 0x8081 only.

Signed-off-by: Sakthivel K 
Signed-off-by: Anand Kumar S 
Acked-by: Jack Wang 
Reviewed-by: Hannes Reinecke  
---
 drivers/scsi/pm8001/pm8001_hwi.c |   31 ---
 drivers/scsi/pm8001/pm8001_hwi.h |2 ++
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index c335ae8..3adf499 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -640,6 +640,18 @@ static void init_pci_device_addresses(struct 
pm8001_hba_info *pm8001_ha)
 static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha)
 {
u8 i = 0;
+   u16 deviceid;
+   pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
+   /* 8081 controllers need BAR shift to access MPI space
+   * as this is shared with BIOS data */
+   if (deviceid == 0x8081) {
+   if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_SM_BASE)) {
+   PM8001_FAIL_DBG(pm8001_ha,
+   pm8001_printk("Shift Bar4 to 0x%x failed\n",
+   GSM_SM_BASE));
+   return -1;
+   }
+   }
/* check the firmware status */
if (-1 == check_fw_ready(pm8001_ha)) {
PM8001_FAIL_DBG(pm8001_ha,
@@ -660,9 +672,12 @@ static int pm8001_chip_init(struct pm8001_hba_info 
*pm8001_ha)
update_inbnd_queue_table(pm8001_ha, i);
for (i = 0; i < PM8001_MAX_OUTB_NUM; i++)
update_outbnd_queue_table(pm8001_ha, i);
-   mpi_set_phys_g3_with_ssc(pm8001_ha, 0);
-   /* 7->130ms, 34->500ms, 119->1.5s */
-   mpi_set_open_retry_interval_reg(pm8001_ha, 119);
+   /* 8081 controller donot require these operations */
+   if (deviceid != 0x8081) {
+   mpi_set_phys_g3_with_ssc(pm8001_ha, 0);
+   /* 7->130ms, 34->500ms, 119->1.5s */
+   mpi_set_open_retry_interval_reg(pm8001_ha, 119);
+   }
/* notify firmware update finished and check initialization status */
if (0 == mpi_init_check(pm8001_ha)) {
PM8001_INIT_DBG(pm8001_ha,
@@ -684,6 +699,16 @@ static int mpi_uninit_check(struct pm8001_hba_info 
*pm8001_ha)
u32 max_wait_count;
u32 value;
u32 gst_len_mpistate;
+   u16 deviceid;
+   pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
+   if (deviceid == 0x8081) {
+   if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_SM_BASE)) {
+   PM8001_FAIL_DBG(pm8001_ha,
+   pm8001_printk("Shift Bar4 to 0x%x failed\n",
+   GSM_SM_BASE));
+   return -1;
+   }
+   }
init_pci_device_addresses(pm8001_ha);
/* Write bit1=1 to Inbound DoorBell Register to tell the SPC FW the
table is stop */
diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h
index 2399aab..d7c1e20 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.h
+++ b/drivers/scsi/pm8001/pm8001_hwi.h
@@ -131,6 +131,8 @@
 #define LINKRATE_30(0x02 << 8)
 #define LINKRATE_60(0x04 << 8)
 
+/* for new SPC controllers MEMBASE III is shared between BIOS and DATA */
+#define GSM_SM_BASE0x4F
 struct mpi_msg_hdr{
__le32  header; /* Bits [11:0]  - Message operation code */
/* Bits [15:12] - Message Category */
-- 
1.7.1

--
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 V5 5/12] pm80xx: MSI-X implementation for using 64 interrupts

2013-05-06 Thread Anand
>From c9ef2f3de75ccd7d33ac26ab3e40745ce3134a2b Mon Sep 17 00:00:00 2001
From: Sakthivel K 
Date: Tue, 19 Mar 2013 17:56:17 +0530
Subject: [PATCH V5 5/12] pm80xx: MSI-X implementation for using 64 interrupts

Implementation of interrupt handlers and tasklets to support
upto 64 interrupt for the device.

Signed-off-by: Sakthivel K 
Signed-off-by: Anand Kumar S 
Acked-by: Jack Wang 
Reviewed-by: Hannes Reinecke 
---
 drivers/scsi/pm8001/pm8001_init.c |  141 +
 drivers/scsi/pm8001/pm8001_sas.h  |2 +
 2 files changed, 113 insertions(+), 30 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_init.c 
b/drivers/scsi/pm8001/pm8001_init.c
index 19fbd03..75270ee 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -159,33 +159,71 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
 }
 
 #ifdef PM8001_USE_TASKLET
+
+/**
+ * tasklet for 64 msi-x interrupt handler
+ * @opaque: the passed general host adapter struct
+ * Note: pm8001_tasklet is common for pm8001 & pm80xx
+ */
 static void pm8001_tasklet(unsigned long opaque)
 {
struct pm8001_hba_info *pm8001_ha;
+   u32 vec;
pm8001_ha = (struct pm8001_hba_info *)opaque;
if (unlikely(!pm8001_ha))
BUG_ON(1);
-   PM8001_CHIP_DISP->isr(pm8001_ha, 0);
+   vec = pm8001_ha->int_vector;
+   PM8001_CHIP_DISP->isr(pm8001_ha, vec);
+}
+#endif
+
+static struct  pm8001_hba_info *outq_to_hba(u8 *outq)
+{
+   return container_of((outq - *outq), struct pm8001_hba_info, outq[0]);
 }
+
+/**
+ * pm8001_interrupt_handler_msix - main MSIX interrupt handler.
+ * It obtains the vector number and calls the equivalent bottom
+ * half or services directly.
+ * @opaque: the passed outbound queue/vector. Host structure is
+ * retrieved from the same.
+ */
+static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque)
+{
+   struct pm8001_hba_info *pm8001_ha = outq_to_hba(opaque);
+   u8 outq = *(u8 *)opaque;
+   irqreturn_t ret = IRQ_HANDLED;
+   if (unlikely(!pm8001_ha))
+   return IRQ_NONE;
+   if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
+   return IRQ_NONE;
+   pm8001_ha->int_vector = outq;
+#ifdef PM8001_USE_TASKLET
+   tasklet_schedule(&pm8001_ha->tasklet);
+#else
+   ret = PM8001_CHIP_DISP->isr(pm8001_ha, outq);
 #endif
+   return ret;
+}
 
+/**
+ * pm8001_interrupt_handler_intx - main INTx interrupt handler.
+ * @dev_id: sas_ha structure. The HBA is retrieved from sas_has structure.
+ */
 
- /**
-  * pm8001_interrupt - when HBA originate a interrupt,we should invoke this
-  * dispatcher to handle each case.
-  * @irq: irq number.
-  * @opaque: the passed general host adapter struct
-  */
-static irqreturn_t pm8001_interrupt(int irq, void *opaque)
+static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id)
 {
struct pm8001_hba_info *pm8001_ha;
irqreturn_t ret = IRQ_HANDLED;
-   struct sas_ha_struct *sha = opaque;
+   struct sas_ha_struct *sha = dev_id;
pm8001_ha = sha->lldd_ha;
if (unlikely(!pm8001_ha))
return IRQ_NONE;
if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
return IRQ_NONE;
+
+   pm8001_ha->int_vector = 0;
 #ifdef PM8001_USE_TASKLET
tasklet_schedule(&pm8001_ha->tasklet);
 #else
@@ -427,8 +465,12 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct 
pci_dev *pdev,
pm8001_ha->iomb_size = IOMB_SIZE_SPC;
 
 #ifdef PM8001_USE_TASKLET
+   /**
+   * default tasklet for non msi-x interrupt handler/first msi-x
+   * interrupt handler
+   **/
tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet,
-   (unsigned long)pm8001_ha);
+   (unsigned long)pm8001_ha);
 #endif
pm8001_ioremap(pm8001_ha);
if (!pm8001_alloc(pm8001_ha, ent))
@@ -591,31 +633,50 @@ static void pm8001_init_sas_add(struct pm8001_hba_info 
*pm8001_ha)
  * @chip_info: our ha struct.
  * @irq_handler: irq_handler
  */
-static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha,
-   irq_handler_t irq_handler)
+static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
 {
u32 i = 0, j = 0;
-   u32 number_of_intr = 1;
+   u32 number_of_intr;
int flag = 0;
u32 max_entry;
int rc;
+   static char intr_drvname[PM8001_MAX_MSIX_VEC][sizeof(DRV_NAME)+3];
+
+   /* SPCv controllers supports 64 msi-x */
+   if (pm8001_ha->chip_id == chip_8001) {
+   number_of_intr = 1;
+   flag |= IRQF_DISABLED;
+   } else {
+   number_of_intr = PM8001_MAX_MSIX_VEC;
+   flag &= ~IRQF_SHARED;
+   flag |= IRQF_DISABLED;
+   }
+
max_entry = sizeof(pm8001_ha->msix_entries) /
sizeof(pm8001_ha->msix_entries[0]);
-   flag |= IRQF_DISABLED;
for (i = 0; i < max_entry ; i++)
p

[PATCH V5 4/12] pm80xx: Updated common functions common for SPC and SPCv/ve

2013-05-06 Thread Anand
>From c5a2c7eff684b5ece5320f070855e3c9321f9b94 Mon Sep 17 00:00:00 2001
From: Sakthivel K 
Date: Wed, 27 Feb 2013 20:27:43 +0530
Subject: [PATCH V5 4/12] pm80xx: Updated common functions common for SPC and 
SPCv/ve

Update of function prototype for common function to SPC and SPCv/ve.
Multiple queues implementation for IO.

Signed-off-by: Sakthivel K 
Signed-off-by: Anand Kumar S 
Acked-by: Jack Wang 
Reviewed-by: Hannes Reinecke 
---
 drivers/scsi/pm8001/pm8001_hwi.c  |  193 +++--
 drivers/scsi/pm8001/pm8001_init.c |   20 +++--
 drivers/scsi/pm8001/pm8001_sas.h  |   60 +++-
 3 files changed, 168 insertions(+), 105 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 6a1b45b..33ebfea 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1158,7 +1158,7 @@ static void pm8001_hw_chip_rst(struct pm8001_hba_info 
*pm8001_ha)
  * pm8001_chip_iounmap - which maped when initialized.
  * @pm8001_ha: our hba card information
  */
-static void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha)
+void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha)
 {
s8 bar, logical = 0;
for (bar = 0; bar < 6; bar++) {
@@ -1237,7 +1237,7 @@ pm8001_chip_msix_interrupt_disable(struct pm8001_hba_info 
*pm8001_ha,
  * @pm8001_ha: our hba card information
  */
 static void
-pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha)
+pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec)
 {
 #ifdef PM8001_USE_MSIX
pm8001_chip_msix_interrupt_enable(pm8001_ha, 0);
@@ -1252,7 +1252,7 @@ pm8001_chip_interrupt_enable(struct pm8001_hba_info 
*pm8001_ha)
  * @pm8001_ha: our hba card information
  */
 static void
-pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha)
+pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec)
 {
 #ifdef PM8001_USE_MSIX
pm8001_chip_msix_interrupt_disable(pm8001_ha, 0);
@@ -1263,12 +1263,13 @@ pm8001_chip_interrupt_disable(struct pm8001_hba_info 
*pm8001_ha)
 }
 
 /**
- * mpi_msg_free_get- get the free message buffer for transfer inbound queue.
+ * pm8001_mpi_msg_free_get - get the free message buffer for transfer
+ * inbound queue.
  * @circularQ: the inbound queue  we want to transfer to HBA.
  * @messageSize: the message size of this transfer, normally it is 64 bytes
  * @messagePtr: the pointer to message.
  */
-static int mpi_msg_free_get(struct inbound_queue_table *circularQ,
+int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ,
u16 messageSize, void **messagePtr)
 {
u32 offset, consumer_index;
@@ -1276,7 +1277,7 @@ static int mpi_msg_free_get(struct inbound_queue_table 
*circularQ,
u8 bcCount = 1; /* only support single buffer */
 
/* Checks is the requested message size can be allocated in this queue*/
-   if (messageSize > 64) {
+   if (messageSize > IOMB_SIZE_SPCV) {
*messagePtr = NULL;
return -1;
}
@@ -1290,7 +1291,7 @@ static int mpi_msg_free_get(struct inbound_queue_table 
*circularQ,
return -1;
}
/* get memory IOMB buffer address */
-   offset = circularQ->producer_idx * 64;
+   offset = circularQ->producer_idx * messageSize;
/* increment to next bcCount element */
circularQ->producer_idx = (circularQ->producer_idx + bcCount)
% PM8001_MPI_QUEUE;
@@ -1302,29 +1303,30 @@ static int mpi_msg_free_get(struct inbound_queue_table 
*circularQ,
 }
 
 /**
- * mpi_build_cmd- build the message queue for transfer, update the PI to FW
- * to tell the fw to get this message from IOMB.
+ * pm8001_mpi_build_cmd- build the message queue for transfer, update the PI to
+ * FW to tell the fw to get this message from IOMB.
  * @pm8001_ha: our hba card information
  * @circularQ: the inbound queue we want to transfer to HBA.
  * @opCode: the operation code represents commands which LLDD and fw 
recognized.
  * @payload: the command payload of each operation command.
  */
-static int mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
+int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
 struct inbound_queue_table *circularQ,
-u32 opCode, void *payload)
+u32 opCode, void *payload, u32 responseQueue)
 {
u32 Header = 0, hpriority = 0, bc = 1, category = 0x02;
-   u32 responseQueue = 0;
void *pMessage;
 
-   if (mpi_msg_free_get(circularQ, 64, &pMessage) < 0) {
+   if (pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size,
+   &pMessage) < 0) {
PM8001_IO_DBG(pm8001_ha,
pm8001_printk("No free mpi buffer\n"));
return -1;
}
BUG_ON(!payload);
/*Copy to the payload*/
-   memcpy(pMessage, payload, (64 - sizeof(struct mpi_msg_hdr))

[PATCH V5 3/12] pm80xx: Multiple inbound/outbound queue configuration

2013-05-06 Thread Anand
>From 6218dd8466f6771ff46dfcd0a820f853c62cde32 Mon Sep 17 00:00:00 2001
From: Sakthivel K 
Date: Wed, 27 Feb 2013 20:25:25 +0530
Subject: [PATCH V5 3/12] pm80xx: Multiple inbound/outbound queue configuration

Memory allocation and configuration of multiple inbound and
outbound queues.

Signed-off-by: Sakthivel K 
Signed-off-by: Anand Kumar S 
Acked-by: Jack Wang 
Reviewed-by: Hannes Reinecke 
---
 drivers/scsi/pm8001/pm8001_defs.h |   14 +++--
 drivers/scsi/pm8001/pm8001_hwi.c  |   43 
 drivers/scsi/pm8001/pm8001_init.c |  101 +
 3 files changed, 98 insertions(+), 60 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_defs.h 
b/drivers/scsi/pm8001/pm8001_defs.h
index b25f87c..26a2ee6 100644
--- a/drivers/scsi/pm8001/pm8001_defs.h
+++ b/drivers/scsi/pm8001/pm8001_defs.h
@@ -48,8 +48,7 @@ enum chip_flavors {
chip_8018,
chip_8019
 };
-#define USI_MAX_MEMCNT 9
-#define PM8001_MAX_DMA_SG  SG_ALL
+
 enum phy_speed {
PHY_SPEED_15 = 0x01,
PHY_SPEED_30 = 0x02,
@@ -87,13 +86,16 @@ enum port_type {
 #definePM8001_MAX_DEVICES   2048   /* max supported device */
 #definePM8001_MAX_MSIX_VEC  64 /* max msi-x int for spcv/ve */
 
+#define USI_MAX_MEMCNT_BASE4
+#define IB (USI_MAX_MEMCNT_BASE + 1)
+#define CI (IB + PM8001_MAX_SPCV_INB_NUM)
+#define OB (CI + PM8001_MAX_SPCV_INB_NUM)
+#define PI (OB + PM8001_MAX_SPCV_OUTB_NUM)
+#define USI_MAX_MEMCNT (PI + PM8001_MAX_SPCV_OUTB_NUM)
+#define PM8001_MAX_DMA_SG  SG_ALL
 enum memory_region_num {
AAP1 = 0x0, /* application acceleration processor */
IOP,/* IO processor */
-   CI, /* consumer index */
-   PI, /* producer index */
-   IB, /* inbound queue */
-   OB, /* outbound queue */
NVMD,   /* NVM device */
DEV_MEM,/* memory for devices */
CCB_MEM,/* memory for command control block */
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index dc45fdc..6a1b45b 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -151,10 +151,9 @@ static void read_general_status_table(struct 
pm8001_hba_info *pm8001_ha)
  */
 static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
 {
-   int inbQ_num = 1;
int i;
void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;
-   for (i = 0; i < inbQ_num; i++) {
+   for (i = 0; i < PM8001_MAX_INB_NUM; i++) {
u32 offset = i * 0x20;
pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =
  get_pci_bar_index(pm8001_mr32(address, (offset + 0x14)));
@@ -169,10 +168,9 @@ static void read_inbnd_queue_table(struct pm8001_hba_info 
*pm8001_ha)
  */
 static void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
 {
-   int outbQ_num = 1;
int i;
void __iomem *address = pm8001_ha->outbnd_q_tbl_addr;
-   for (i = 0; i < outbQ_num; i++) {
+   for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) {
u32 offset = i * 0x24;
pm8001_ha->outbnd_q_tbl[i].ci_pci_bar =
  get_pci_bar_index(pm8001_mr32(address, (offset + 0x14)));
@@ -225,19 +223,19 @@ static void init_default_table_values(struct 
pm8001_hba_info *pm8001_ha)
pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt  =
PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30);
pm8001_ha->inbnd_q_tbl[i].upper_base_addr   =
-   pm8001_ha->memoryMap.region[IB].phys_addr_hi;
+   pm8001_ha->memoryMap.region[IB + i].phys_addr_hi;
pm8001_ha->inbnd_q_tbl[i].lower_base_addr   =
-   pm8001_ha->memoryMap.region[IB].phys_addr_lo;
+   pm8001_ha->memoryMap.region[IB + i].phys_addr_lo;
pm8001_ha->inbnd_q_tbl[i].base_virt =
-   (u8 *)pm8001_ha->memoryMap.region[IB].virt_ptr;
+   (u8 *)pm8001_ha->memoryMap.region[IB + i].virt_ptr;
pm8001_ha->inbnd_q_tbl[i].total_length  =
-   pm8001_ha->memoryMap.region[IB].total_len;
+   pm8001_ha->memoryMap.region[IB + i].total_len;
pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr=
-   pm8001_ha->memoryMap.region[CI].phys_addr_hi;
+   pm8001_ha->memoryMap.region[CI + i].phys_addr_hi;
pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr=
-   pm8001_ha->memoryMap.region[CI].phys_addr_lo;
+   pm8001_ha->memoryMap.region[CI + i].phys_addr_lo;
pm8001_ha->inbnd_q_tbl[i].ci_virt   =
-   pm8001_ha->memoryMap.region[CI].virt_ptr;
+   pm8001

[PATCH V5 02/12] pm80xx: Added SPCv/ve specific ids, variables and modify for SPC

2013-05-06 Thread Anand
>From a33eba8de80389b80fd3a16437e475598854eed7 Mon Sep 17 00:00:00 2001
From: Sakthivel K 
Date: Wed, 17 Apr 2013 16:26:36 +0530
Subject: [PATCH V5 02/12] pm80xx: Added SPCv/ve specific ids, variables and 
modify for SPC

Updated pci id table with device, vendor, subdevice and subvendor ids
for 8081, 8088, 8089 SAS/SATA controllers. Added SPCv/ve related macros.
Updated macros, hba info structure and other structures for SPCv/ve.
Update of structure and variable names for SPC hardware functionalities.

Signed-off-by: Sakthivel K 
Signed-off-by: Anand Kumar S 
Acked-by: Jack Wang 
Reviewed-by:  Hannes Reinecke 
---
 drivers/scsi/pm8001/pm8001_ctl.c  |   69 ++---
 drivers/scsi/pm8001/pm8001_defs.h |   19 +++-
 drivers/scsi/pm8001/pm8001_hwi.c  |  213 ++---
 drivers/scsi/pm8001/pm8001_init.c |   48 +++-
 drivers/scsi/pm8001/pm8001_sas.h  |   92 ++--
 5 files changed, 320 insertions(+), 121 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 45bc197..ae2b124 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -1,5 +1,5 @@
 /*
- * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver
+ * PMC-Sierra 8001/8081/8088/8089 SAS/SATA based host adapters driver
  *
  * Copyright (c) 2008-2009 USI Co., Ltd.
  * All rights reserved.
@@ -58,8 +58,13 @@ static ssize_t pm8001_ctl_mpi_interface_rev_show(struct 
device *cdev,
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
 
-   return snprintf(buf, PAGE_SIZE, "%d\n",
-   pm8001_ha->main_cfg_tbl.interface_rev);
+   if (pm8001_ha->chip_id == chip_8001) {
+   return snprintf(buf, PAGE_SIZE, "%d\n",
+   pm8001_ha->main_cfg_tbl.pm8001_tbl.interface_rev);
+   } else {
+   return snprintf(buf, PAGE_SIZE, "%d\n",
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev);
+   }
 }
 static
 DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL);
@@ -78,11 +83,19 @@ static ssize_t pm8001_ctl_fw_version_show(struct device 
*cdev,
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
 
-   return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
-  (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 24),
-  (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 16),
-  (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 8),
-  (u8)(pm8001_ha->main_cfg_tbl.firmware_rev));
+   if (pm8001_ha->chip_id == chip_8001) {
+   return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
+   (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 24),
+   (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 16),
+   (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 8),
+   (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev));
+   } else {
+   return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 24),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 16),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 8),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev));
+   }
 }
 static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL);
 /**
@@ -99,8 +112,13 @@ static ssize_t pm8001_ctl_max_out_io_show(struct device 
*cdev,
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
 
-   return snprintf(buf, PAGE_SIZE, "%d\n",
-   pm8001_ha->main_cfg_tbl.max_out_io);
+   if (pm8001_ha->chip_id == chip_8001) {
+   return snprintf(buf, PAGE_SIZE, "%d\n",
+   pm8001_ha->main_cfg_tbl.pm8001_tbl.max_out_io);
+   } else {
+   return snprintf(buf, PAGE_SIZE, "%d\n",
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io);
+   }
 }
 static DEVICE_ATTR(max_out_io, S_IRUGO, pm8001_ctl_max_out_io_show, NULL);
 /**
@@ -117,8 +135,15 @@ static ssize_t pm8001_ctl_max_devices_show(struct device 
*cdev,
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
 
-   return snprintf(buf, PAGE_SIZE, "%04d\n",
-   (u16)(pm8001_ha->main_cfg_tbl.max_sgl >> 16));
+   if (pm8001_ha->chip_id == chip_8001) {
+   return snprintf(buf, PAGE_SIZE, "%04d\n",
+   (u16)(pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl >> 16)
+   );
+   } else {
+   return snprintf(buf, PAGE_SIZE, "%04d\n",
+   (u16)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl >

[PATCH V5 1/12] pm80xx: fix for memory region free

2013-05-06 Thread Anand
>From 8464bcd3b7789798a1f34826fe51eb833ae0578d Mon Sep 17 00:00:00 2001
From: Sakthivel K 
Date: Mon, 4 Feb 2013 12:10:02 +0530
Subject: [PATCH V5 1/12] pm80xx: fix for memory region free

All memory regions are allocated based on variables total_len
and alignment but free was based on element_size.

Signed-off-by: Sakthivel K 
Signed-off-by: Anand Kumar S 
Acked-by: Jack Wang 
Reviewed-by: Hannes Reinecke 
---
 drivers/scsi/pm8001/pm8001_init.c |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_init.c 
b/drivers/scsi/pm8001/pm8001_init.c
index 4c9fe73..3d5e522 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -140,7 +140,8 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
for (i = 0; i < USI_MAX_MEMCNT; i++) {
if (pm8001_ha->memoryMap.region[i].virt_ptr != NULL) {
pci_free_consistent(pm8001_ha->pdev,
-   pm8001_ha->memoryMap.region[i].element_size,
+   (pm8001_ha->memoryMap.region[i].total_len +
+   pm8001_ha->memoryMap.region[i].alignment),
pm8001_ha->memoryMap.region[i].virt_ptr,
pm8001_ha->memoryMap.region[i].phys_addr);
}
-- 
1.7.1

--
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 V5 00/12] Support for PMC 8081/8088/8089 controllers

2013-05-06 Thread Anand
>From ffe82b1efc42510239046909a7ac0aff10bb4162 Mon Sep 17 00:00:00 2001
From: Sakthivel K 
Date: Tue, 19 Mar 2013 18:32:55 +0530
Subject: [PATCH V5 00/12] Support for PMC 8081/8088/8089 controllers

V5

Resubmission of patchset to fix the array out of bounds
error reported by James.

V4

Resubmission of patchset to handle patch apply issue
reported by James.
Fixed dependencies in patch 2 and 6.

V3

Resubmission of patchset addressing Hannes comment
on usage of multiple interrupt handlers for handling
MSI-X.

V2

Resubmission of patchset addressing Hannes comment
on usage of multiple tasklets for handling MSI-X.

1. Patch5 - Implemented a single tasklet to handle all MSI-x
interrupts

V1

Resubmission of pm8001 patchset based on James Bottomley comments

1. The patch permission level corrected to 644.
2. Patches 2 3 and 4 of the original patchset have been merged to a
   single patch (patch 2) to fix compilation error and ensure
   individual functionality.
3. Email id's changed to resolvable ids.

Sakthivel K (12):
  pm80xx: fix for memory region free
  pm80xx: Added SPCv/ve specific ids, variables and modify for SPC
  pm80xx: Multiple inbound/outbound queue configuration
  pm80xx: Updated common functions common for SPC and SPCv/ve
  pm80xx: MSI-X implementation for using 64 interrupts
  pm80xx: Added SPCv/ve specific hardware functionalities and  
relavent changes in common files
  pm80xx: SPC new firmware changes for device id 0x8081 alone
  pm80xx: Firmware flash memory free fix, with addition of new memory
region for it
  pm80xx: Changed module name and debug messages update
  pm80xx: WWN Modification for PM8081/88/89 controllers
  pm80xx: NCQ error handling changes
  pm80xx: thermal, sas controller config and error handling update

 drivers/scsi/pm8001/Makefile  |7 +-
 drivers/scsi/pm8001/pm8001_ctl.c  |   74 +-
 drivers/scsi/pm8001/pm8001_defs.h |   34 +-
 drivers/scsi/pm8001/pm8001_hwi.c  |  796 +---
 drivers/scsi/pm8001/pm8001_hwi.h  |4 +-
 drivers/scsi/pm8001/pm8001_init.c |  384 +++-
 drivers/scsi/pm8001/pm8001_sas.c  |  105 +-
 drivers/scsi/pm8001/pm8001_sas.h  |  177 ++-
 drivers/scsi/pm8001/pm80xx_hwi.c  | 4131 +
 drivers/scsi/pm8001/pm80xx_hwi.h  | 1524 ++
 10 files changed, 6845 insertions(+), 391 deletions(-)
 create mode 100644 drivers/scsi/pm8001/pm80xx_hwi.c
 create mode 100644 drivers/scsi/pm8001/pm80xx_hwi.h

--
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: linux-next: Tree for May 6 (lpfc)

2013-05-06 Thread Randy Dunlap
On 05/05/13 21:42, Stephen Rothwell wrote:
> Hi all,
> 
> Please do not add any v3.11 destined work to your linux-next included
> branches until after v3.10-rc1 is released.
> 
> I am receiving a (un)reasonable number of conflicts from there being
> multiple copies of some commits in various trees.   Please clean this up
> and resist the temptataion to rebase your trees on the way to your
> upstream ...
> 
> Changes since 20130506:
> 

on i386:
# CONFIG_CRC_T10DIF is not set


drivers/built-in.o: In function `lpfc_bg_crc':
(.text+0x3cb3c9): undefined reference to `crc_t10dif'




-- 
~Randy
--
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 1/1] Create megaraid ioctl device node

2013-05-06 Thread Patrick Monnerat

On 05/06/2013 04:23 PM, Bjørn Mork wrote:

"Patrick Monnerat"  writes:

   Create ioctl device node for megaraid_sas driver. Let this node be
managed by udev. Fix a typo.


Or maybe just simplify it all and use a misc device instead?  See how
this is done in e.g. drivers/scsi/mpt3sas/mpt3sas_ctl.c or
drivers/message/fusion/mptctl.c


Yes, could be done that way, But I want to retain compatibility with 
existing shell scripts doing things like:


DEVICE=/dev/megaraid_sas_ioctl_node
DEVICENAME=megaraid_sas_ioctl
DEVICEPERM=400
MAJOR=`grep "$DEVICENAME" /proc/devices | awk '{print $1}'`

if [ -n "$MAJOR" -a ! -e "$DEVICE" ]; then
mknod "$DEVICE" c "$MAJOR" 0
chmod "$DEVICEPERM" "$DEVICE"
fi

Snippets like this one appear both in open-source projects and Dell scripts.

Patrick
--
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] hpsa: fix memory leak in hpsa_big_passthru_ioctl

2013-05-06 Thread Stephen M. Cameron
From: Stephen M. Cameron 

In the event of a dma mapping error, we forgot to free
the command we had allocated.

Signed-off-by: Stephen M. Cameron 
---
 drivers/scsi/hpsa.c |   11 +--
 1 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 7f4f790..97351b4 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -3149,7 +3149,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, 
void __user *argp)
hpsa_pci_unmap(h->pdev, c, i,
PCI_DMA_BIDIRECTIONAL);
status = -ENOMEM;
-   goto cleanup1;
+   goto cleanup0;
}
c->SG[i].Addr.lower = temp64.val32.lower;
c->SG[i].Addr.upper = temp64.val32.upper;
@@ -3165,24 +3165,23 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, 
void __user *argp)
/* Copy the error information out */
memcpy(&ioc->error_info, c->err_info, sizeof(ioc->error_info));
if (copy_to_user(argp, ioc, sizeof(*ioc))) {
-   cmd_special_free(h, c);
status = -EFAULT;
-   goto cleanup1;
+   goto cleanup0;
}
if (ioc->Request.Type.Direction == XFER_READ && ioc->buf_size > 0) {
/* Copy the data out of the buffer we created */
BYTE __user *ptr = ioc->buf;
for (i = 0; i < sg_used; i++) {
if (copy_to_user(ptr, buff[i], buff_size[i])) {
-   cmd_special_free(h, c);
status = -EFAULT;
-   goto cleanup1;
+   goto cleanup0;
}
ptr += buff_size[i];
}
}
-   cmd_special_free(h, c);
status = 0;
+cleanup0:
+   cmd_special_free(h, c);
 cleanup1:
if (buff) {
for (i = 0; i < sg_used; i++)

--
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 1/1] Create megaraid ioctl device node

2013-05-06 Thread Bjørn Mork
"Patrick Monnerat"  writes:

> From: Patrick Monnerat 
>
>   Create ioctl device node for megaraid_sas driver. Let this node be
> managed by udev. Fix a typo.

Or maybe just simplify it all and use a misc device instead?  See how
this is done in e.g. drivers/scsi/mpt3sas/mpt3sas_ctl.c or
drivers/message/fusion/mptctl.c



Bjørn
--
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 3/7] scsi: ufs: amend interrupt configuration

2013-05-06 Thread James Bottomley
On Mon, 2013-05-06 at 03:40 -0700, me...@codeaurora.org wrote:
> Hi James,
> 
> Can you please merge this patch?

Well, no.  a) because it's part of a series which still seems to be
under development and b) because it needs a maintainer ack.

James

--
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 1/1] Create megaraid ioctl device node

2013-05-06 Thread Patrick Monnerat
From: Patrick Monnerat 

  Create ioctl device node for megaraid_sas driver. Let this node be
managed by udev. Fix a typo.

Reported-by: p...@datasphere.ch
To: Neela Syam Kolli 
Cc: "James E.J. Bottomley" 
Cc: linux-scsi@vger.kernel.org
Cc: linux-ker...@vger.kernel.org
Signed-off-by: Patrick Monnerat 
---
diff -uprN
linux-3.8.11-200.1pm.fc18.x86_64.orig/drivers/scsi/megaraid/megaraid_sas
_base.c
linux-3.8.11-200.1pm.fc18.x86_64.new/drivers/scsi/megaraid/megaraid_sas_
base.c
---
linux-3.8.11-200.1pm.fc18.x86_64.orig/drivers/scsi/megaraid/megaraid_sas
_base.c 2013-02-19 00:58:34.0 +0100
+++
linux-3.8.11-200.1pm.fc18.x86_64.new/drivers/scsi/megaraid/megaraid_sas_
base.c  2013-05-06 13:39:27.903234426 +0200
@@ -49,6 +49,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -127,6 +128,8 @@ static struct pci_device_id megasas_pci_
 
 MODULE_DEVICE_TABLE(pci, megasas_pci_table);
 
+static struct class *megasas_mgmt_class;
+static struct device *megasas_mgmt_device;
 static int megasas_mgmt_majorno;
 static struct megasas_mgmt_info megasas_mgmt_info;
 static struct fasync_struct *megasas_async_queue;
@@ -5450,7 +5453,7 @@ static int __init megasas_init(void)
rval = pci_register_driver(&megasas_pci_driver);
 
if (rval) {
-   printk(KERN_DEBUG "megasas: PCI hotplug regisration
failed \n");
+   printk(KERN_DEBUG "megasas: PCI hotplug registration
failed\n");
goto err_pcidrv;
}
 
@@ -5477,8 +5480,28 @@ static int __init megasas_init(void)
if (rval)
goto err_dcf_support_device_change;
 
-   return rval;
+   /*
+* Register as an udev-controlled device.
+*/
+   megasas_mgmt_class = class_create(THIS_MODULE, "megaraid");
+   rval = PTR_ERR(megasas_mgmt_class);
+   if (IS_ERR(megasas_mgmt_class))
+   goto err_class;
+
+   megasas_mgmt_device = device_create(megasas_mgmt_class, NULL,
+   MKDEV(megasas_mgmt_majorno,
0),
+   NULL, "megaraid_sas_ioctl");
+   rval = PTR_ERR(megasas_mgmt_device);
+   if (IS_ERR(megasas_mgmt_device))
+   goto err_create_device;
 
+   return 0;
+
+err_create_device:
+   class_destroy(megasas_mgmt_class);
+err_class:
+   driver_remove_file(&megasas_pci_driver.driver,
+  &driver_attr_support_device_change);
 err_dcf_support_device_change:
driver_remove_file(&megasas_pci_driver.driver,
   &driver_attr_dbg_lvl);
@@ -5504,6 +5527,9 @@ err_pcidrv:
  */
 static void __exit megasas_exit(void)
 {
+   device_destroy(megasas_mgmt_class, MKDEV(megasas_mgmt_majorno,
0));
+   class_destroy(megasas_mgmt_class);
+
driver_remove_file(&megasas_pci_driver.driver,
   &driver_attr_dbg_lvl);
driver_remove_file(&megasas_pci_driver.driver,
--
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: add put_device() after device_find_child()

2013-05-06 Thread Zhao Hongjiang
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;
}
 
-- 
1.7.1

--
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 v3 4/6] scsi: ufs: rework link start-up process

2013-05-06 Thread Seungwon Jeon
On Monday, May 06, 2013, Sujit Reddy Thumma wrote:
> On 5/6/2013 11:07 AM, 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.
> We have seen a kernel crash when the timeout happens in our internal
> testing. This is basically because the the UIC_CMD_TIMEOUT of 500msec is
> less for our platform. We see UIC_COMMAND_COMPL interrupt after this
> timeout and since uic_cmd is freed we see a kernel crash.
> 
> [6.026094] ufshcd :01:00.0: link startup: error code -110
> [6.030886] ufshcd :01:00.0: link startup failed -110
> ...
> 
> [6.487288] BUG: spinlock bad magic on CPU#0, swapper/0/0
> [6.491683] Unable to handle kernel paging request at virtual address
> 612b
> ...
> [7.625270] [] (spin_dump+0x4c/0x88) from []
> (do_raw_spin_lock+0x20/0x154)
> [7.633877] [] (do_raw_spin_lock+0x20/0x154) from
> [] (_raw_spin_lock_irqsave+0x28/0x30)
> [7.643583] [] (_raw_spin_lock_irqsave+0x28/0x30) from
> [] (complete+0x1c/0x58)
> [7.652525] [] (complete+0x1c/0x58) from []
> (ufshcd_intr+0x1a8/0x498)
> [7.660705] [] (ufshcd_intr+0x1a8/0x498) from []
> (handle_irq_event_percpu+0xb0/0x290)
> [7.670227] [] (handle_irq_event_percpu+0xb0/0x290) from
> [] (handle_irq_event+0x3c/0x5c)
> [7.680054] [] (handle_irq_event+0x3c/0x5c) from
> [] (handle_fasteoi_irq+0xdc/0x148)
> [7.689424] [] (handle_fasteoi_irq+0xdc/0x148) from
> [] (generic_handle_irq+0x30/0x44)
> [7.698977] [] (generic_handle_irq+0x30/0x44) from
> [] (handle_IRQ+0x7c/0xc0)
> [7.707736] [] (handle_IRQ+0x7c/0xc0) from []
> (gic_handle_irq+0x94/0x110)
> [7.716252] [] (gic_handle_irq+0x94/0x110) from
> [] (__irq_svc+0x40/0x70)
> 
> 
> Following would fix this. Please check. Also, we need to increase the
> timeout to say 5 secs to avoid such races.
Thank you for test.
I have seen the completion of link startup within current timeout ever.
It should be fixed for that case.
By the way, I feel 5 seconds looks like a little too long.
Currently, is your platform situation with UFS in normal stage?
The UNIPRO spec. mentions the 100 ms as timeout internally for link startup.
Anyway, do you mean that you want to change timeout value to 5 seconds?
I think it has a strong dependency with your platform.
1 sec seems proper though the worst case is considered.

Thanks,
Seungwon Jeon

> 
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index ecbae40..ae22a8e 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -485,6 +485,7 @@ 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)))
> @@ -492,6 +493,10 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct
> uic_command *uic_cmd)
>   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;
>  }
> 
> @@ -1842,7 +1847,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,
> struct ufshcd_lrb *lrbp)
>   */
>  static void ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
>  {
> - if (intr_status & UIC_COMMAND_COMPL) {
> + if (hba->active_uic_cmd && (intr_status & UIC_COMMAND_COMPL)) {
>   hba->active_uic_cmd->argument2 |=
>   ufshcd_get_uic_cmd_result(hba);
>   hba->active_uic_cmd->argument3 =
> 
> 
> > 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 
> > ---
> >   drivers/scsi/ufs/ufshcd.c |  287 
> > ++---
> >   drivers/scsi/ufs/ufshcd.h |   10 +-
> >   2 files changed, 200 insertions(+), 97 deletions(-)
> >
> > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> > index e04c74e..118f104 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,115 @@ static inl

[PATCH 1/1] scsi: ufs: Set fDeviceInit flag to initiate device initialization

2013-05-06 Thread Sujit Reddy Thumma
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|   10 -
 drivers/scsi/ufs/ufshcd.c |  102 +
 drivers/scsi/ufs/ufshcd.h |7 +++
 3 files changed, 118 insertions(+), 1 deletions(-)

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 4090f6c..21aa0b4 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -52,6 +52,15 @@
 /* Reserved tag for internal commands */
 #define INTERNAL_CMD_TAG   0
 
+/* Query request standard 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,
@@ -952,6 +961,57 @@ int ufshcd_query_request(struct ufs_hba *hba,
 }
 
 /**
+ * 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
  *
@@ -1384,6 +1444,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_validate_device_init(struct ufs_hba *hba)
+{
+   int i, err;
+   bool flag_res = 0;
+
+   err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_SET_FLAG,
+   QUERY_FLAG_IDN_FDEVICEINIT, &flag_res);
+   if (err) {
+   dev_err(hba->dev,
+   "%s setting fDeviceInit flag failed with error %d\n",
+   __func__, err);
+   goto out;
+   }
+
+   for (i = 0; i < QUERY_REQ_RETRIES && !err && flag_res; i++) {
+   err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG,
+   QUERY_FLAG_IDN_FDEVICEINIT, &flag_res);
+   }
+   if (err)
+   dev_err(hba->dev,
+ 

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

2013-05-06 Thread merez
Tested-by: Maya Erez 

> 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 
> ---
>  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
>


-- 
Maya Erez
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


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

2013-05-06 Thread merez
Tested-by: Maya Erez 

> 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 
>
> ---
> 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 |  161
> ++---
>  drivers/scsi/ufs/ufshcd.h |4 +
>  2 files changed, 156 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 3607ffb..ecbae40 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -34,6 +34,7 @@
>   */
>
>  #include 
> +#include 
>
>  #include "ufshcd.h"
>
> @@ -44,6 +45,13 @@
>  /* 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 */
> +/* Reserved tag for internal commands */
> +#define INTERNAL_CMD_TAG   0
> +
>  enum {
>   UFSHCD_MAX_CHANNEL  = 0,
>   UFSHCD_MAX_ID   = 1,
> @@ -630,7 +638,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 +655,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 +745,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 +771,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 +826,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host,
> struct scsi_cmnd *cmd)
>   lrbp->sense_buffer = cmd->sense_buffer;
>   lrbp->task_tag = tag;
>   lrbp->lun = cmd->device->lun;
> + lrbp->intr_cmd = false;
>
>   if (ufshcd_is_query_req(lrbp))
>   lrbp->command_type = UTP_CMD_TYPE_DEV_MANAGE;
> @@ -1261,6 +1286,101 @@ int ufshcd_dme_endpt_reset(struct ufs_hba *hba)
>  }
>  EXPORT_SYMBOL_GPL(ufshcd_dme_endpt_reset);
>
> +static int
> +ufshcd_compose_nop_out_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
> +{
> + lrbp->cmd = NULL;
> + lrbp->sense_bufflen = 0;
> + lrbp->sense_buffer = NULL;
> + lrbp->task_tag = INTERNAL_CMD_TAG;
> + lrbp->lun = 0; /* NOP OUT is not specific to any LUN */
> + lrbp->command_type = UTP_CMD_TYPE_DEV_MANAGE;
> + lrbp->intr_cmd = true; /* No interrupt aggregation */
> +
> + return ufshcd_compose_upiu(hba, lrbp);
> +}
> +
> +static int ufshcd_wait_for_nop_cmd(struct ufs_hba *hba, struct ufshcd_lrb
> *lrbp)
> +{
> + int err = 0;
> + unsigned long timeout;
> + unsigned long flags;
> +
> + timeout = wait_for_completion_timeout(
> +  

Re: [PATCH 3/3] scsi: ufs: add support for query requests

2013-05-06 Thread merez
Tested-by: Maya Erez 

>>> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
>>> index 35faf24..82417d6 100644
>>> --- a/drivers/scsi/ufs/Kconfig
>>> +++ b/drivers/scsi/ufs/Kconfig
>>> @@ -35,6 +35,7 @@
>>>  config SCSI_UFSHCD
>>>   tristate "Universal Flash Storage Controller Driver Core"
>>>   depends on SCSI
>>> + default y
>>>   ---help---
>>>   This selects the support for UFS devices in Linux, say Y and make
>>> sure that you know the name of your UFS host adapter (the card
>>
>> I don't think you want to force this on in every configuration since
>> it's only appropriate to non server/desktop.  I stripped this hunk.
>>
>
> Hi James,
>
> Please apply the patch without the particular change or you can apply
> the latest patch sent by Dolev -
> http://marc.info/?l=linux-scsi&m=136774922024179&w=1.
>
> Thanks,
> 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
>


-- 
Maya Erez
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


Re: [PATCH v2 7/7] scsi: ufs: add dme control primitives

2013-05-06 Thread merez
Tested-by: Maya Erez 

> 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 
> ---
>  drivers/scsi/ufs/ufshcd.c |  133
> ++---
>  drivers/scsi/ufs/ufshcd.h |   26 +
>  drivers/scsi/ufs/ufshci.h |   15 +
>  3 files changed, 166 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 956041c..54cd61a 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_TIMEOUT  500
> @@ -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
> @@ -1161,6 +1174,104 @@ int ufshcd_dme_xxx_get(struct ufs_hba *hba, u32
> attr_sel,
>  EXPORT_SYMBOL_GPL(ufshcd_dme_xxx_get);
>
>  /**
> + * ufshcd_dme_power_xxx - 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_xxx(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_xxx);
> +
> +/**
> + * ufshcd_dme_hibern8_xxx - 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_xxx(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);
> + ret = __ufshcd_send_uic_cmd(hba, &uic_cmd);
> + if (ret) {
> + dev_err(hba->dev, "%s: error code %d\n", hibern8, ret);
> + goto out;
> + }
> +
> + init_completion(&hba->hibern8_done);
> +
> + 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:%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_xxx);
> +
> +/**
> + * ufshcd_dme_endpt_reset - UIC command for DME_ENDPOINTRESET
> + * @hba: per adapter instance
> + *
> + * Returns 0 on success, non-zero value on failure
> + */
> +int ufshcd_dme_endpt_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, "endpoint reset: error code %d\n", ret);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_dme_endpt_reset);
> +
> +/**
>   * ufshcd_make_hba_operational - Make UFS controller operational
>   * @hba: per adapter instance
>   *
> @@ -1617,14 +1728,20 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,
> s

Re: [PATCH v2 6/7] scsi: ufs: add dme configuration primitives

2013-05-06 Thread merez
Tested-by: Maya Erez 

> Implements to support Get and Set operation of the DME.
> And along with these operations, IDs of Attribute are added.
> It is used to configure the behavior of the UNIPRO.
>
> Signed-off-by: Seungwon Jeon 
> ---
>  drivers/scsi/ufs/ufshcd.c |   84 +
>  drivers/scsi/ufs/ufshcd.h |   29 ++
>  drivers/scsi/ufs/ufshci.h |4 ++
>  drivers/scsi/ufs/unipro.h |  129
> +
>  4 files changed, 246 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/scsi/ufs/unipro.h
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 9c94d42..956041c 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
> @@ -1079,6 +1091,76 @@ static int ufshcd_dme_link_startup(struct ufs_hba
> *hba)
>  }
>
>  /**
> + * ufshcd_dme_xxx_set - 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_xxx_set(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);
> +
> + dev_dbg(hba->dev, "%s: error code %d\n", set, ret);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_dme_xxx_set);
> +
> +/**
> + * ufshcd_dme_xxx_get - 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_xxx_get(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 (mib_val)
> + *mib_val = uic_cmd.argument3;
> +
> + dev_dbg(hba->dev, "%s: error code %d\n", get, ret);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_dme_xxx_get);
> +
> +/**
>   * ufshcd_make_hba_operational - Make UFS controller operational
>   * @hba: per adapter instance
>   *
> @@ -1540,6 +1622,8 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba
> *hba)
>  {
>   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 6095b3b..b47de70 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -217,4 +217,33 @@ int ufshcd_init(struct device *, struct ufs_hba ** ,
> void __iomem * ,
>   unsigned int);
>  void ufshcd_remove(struct ufs_hba *);
>
> +extern int ufshcd_dme_xxx_set(struct ufs_hba *hba, u32 attr_sel,
> +   u8 attr_set, u32 mib_val, u8 peer);
> +extern int ufshcd_dme_xxx_get(struct ufs_hba *hba, u32 attr_sel,
> +   u32 *mib_val, u8 peer);
> +
> +static inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel,
> +  u8 attr_set, u32 mib_val)
> +{
> + return ufshcd_dme_xxx_set(hba, attr_sel, attr_set, mib_val, 0);
> +}
> +
> +static inline int ufshcd_dme_peer_set(struct ufs_hba *hba, u32 attr_sel,
> +

Re: [PATCH v2 3/7] scsi: ufs: amend interrupt configuration

2013-05-06 Thread merez
Hi James,

Can you please merge this patch?

Thanks,
Maya
> 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 af7b81b..bc956e8 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
>   *
> @@ -450,25 +468,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);
>  }
>
>  /**
> @@ -955,8 +993,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);
> @@ -1003,13 +1040,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);
> @@ -1837,7 +1868,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);
> @@ -1895,6 +1926,9 @@ int ufshcd_init(struct device *dev, struct uf

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

2013-05-06 Thread merez
Hi James,

Can you please merge this patch?

Thanks,
Maya
> 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

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

2013-05-06 Thread merez
Hi James,

Can you please merge this patch on top of the query requests patch?

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,
> - 

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

2013-05-06 Thread merez
Hi,

The proposed fix fixes the timeout crash.
In normal operation the patch works, so after applying the fix you can add
my Tested-By.

One additional minor fix that is required:
In ufshcd_link_startup the following print-out is printed in success as well:
dev_err(hba->dev, "link startup failed %d\n", ret);

Please move it to the error cases only.

Thanks,
Maya

> On 5/6/2013 11:07 AM, 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.
> We have seen a kernel crash when the timeout happens in our internal
> testing. This is basically because the the UIC_CMD_TIMEOUT of 500msec is
> less for our platform. We see UIC_COMMAND_COMPL interrupt after this
> timeout and since uic_cmd is freed we see a kernel crash.
>
> [6.026094] ufshcd :01:00.0: link startup: error code -110
> [6.030886] ufshcd :01:00.0: link startup failed -110
> ...
>
> [6.487288] BUG: spinlock bad magic on CPU#0, swapper/0/0
> [6.491683] Unable to handle kernel paging request at virtual address
> 612b
> ...
> [7.625270] [] (spin_dump+0x4c/0x88) from []
> (do_raw_spin_lock+0x20/0x154)
> [7.633877] [] (do_raw_spin_lock+0x20/0x154) from
> [] (_raw_spin_lock_irqsave+0x28/0x30)
> [7.643583] [] (_raw_spin_lock_irqsave+0x28/0x30) from
> [] (complete+0x1c/0x58)
> [7.652525] [] (complete+0x1c/0x58) from []
> (ufshcd_intr+0x1a8/0x498)
> [7.660705] [] (ufshcd_intr+0x1a8/0x498) from []
> (handle_irq_event_percpu+0xb0/0x290)
> [7.670227] [] (handle_irq_event_percpu+0xb0/0x290) from
> [] (handle_irq_event+0x3c/0x5c)
> [7.680054] [] (handle_irq_event+0x3c/0x5c) from
> [] (handle_fasteoi_irq+0xdc/0x148)
> [7.689424] [] (handle_fasteoi_irq+0xdc/0x148) from
> [] (generic_handle_irq+0x30/0x44)
> [7.698977] [] (generic_handle_irq+0x30/0x44) from
> [] (handle_IRQ+0x7c/0xc0)
> [7.707736] [] (handle_IRQ+0x7c/0xc0) from []
> (gic_handle_irq+0x94/0x110)
> [7.716252] [] (gic_handle_irq+0x94/0x110) from
> [] (__irq_svc+0x40/0x70)
>
>
> Following would fix this. Please check. Also, we need to increase the
> timeout to say 5 secs to avoid such races.
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index ecbae40..ae22a8e 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -485,6 +485,7 @@ 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)))
> @@ -492,6 +493,10 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct
> uic_command *uic_cmd)
>   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;
>  }
>
> @@ -1842,7 +1847,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,
> struct ufshcd_lrb *lrbp)
>   */
>  static void ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
>  {
> - if (intr_status & UIC_COMMAND_COMPL) {
> + if (hba->active_uic_cmd && (intr_status & UIC_COMMAND_COMPL)) {
>   hba->active_uic_cmd->argument2 |=
>   ufshcd_get_uic_cmd_result(hba);
>   hba->active_uic_cmd->argument3 =
>
>
>> 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 
>> ---
>>   drivers/scsi/ufs/ufshcd.c |  287
>> ++---
>>   drivers/scsi/ufs/ufshcd.h |   10 +-
>>   2 files changed, 200 insertions(+), 97 deletions(-)
>>
>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>> index e04c74e..118f104 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_TIMEOUT 500
>>
>>   enum {
>>  UFSHCD_MAX_CHANNEL  = 0,
>> @@ -401,24 +405,115 @@ 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

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

2013-05-06 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 

---
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 |  163 ++---
 drivers/scsi/ufs/ufshcd.h |4 +
 2 files changed, 158 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3607ffb..4090f6c 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -34,6 +34,7 @@
  */
 
 #include 
+#include 
 
 #include "ufshcd.h"
 
@@ -44,6 +45,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,
@@ -630,7 +638,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 +655,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 +745,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 +771,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 +826,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, 
struct scsi_cmnd *cmd)
lrbp->sense_buffer = cmd->sense_buffer;
lrbp->task_tag = tag;
lrbp->lun = cmd->device->lun;
+   lrbp->intr_cmd = false;
 
if (ufshcd_is_query_req(lrbp))
lrbp->command_type = UTP_CMD_TYPE_DEV_MANAGE;
@@ -1261,6 +1286,103 @@ int ufshcd_dme_endpt_reset(struct ufs_hba *hba)
 }
 EXPORT_SYMBOL_GPL(ufshcd_dme_endpt_reset);
 
+static int
+ufshcd_compose_nop_out_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
+{
+   lrbp->cmd = NULL;
+   lrbp->sense_bufflen = 0;
+   lrbp->sense_buffer = NULL;
+   lrbp->task_tag = INTERNAL_CMD_TAG;
+   lrbp->lun = 0; /* NOP OUT is not specific to any LUN */
+   lrbp->command_type = UTP_CMD_TYPE_DEV_MANAGE;
+   lrbp->intr_cmd = true; /* No interrupt aggregation */
+
+   return ufshcd_compose_upiu(hba, lrbp);
+}
+
+static int ufshcd_wait_for_nop_cmd(struct ufs_hba *hba, struct ufshcd_lrb 
*lrbp)
+{
+   int err = 0;
+   unsigned long timeout;
+   unsigned long flags;
+
+   timeout = wait_for_completion_timeout(
+   lrbp->completion, msecs_to_jiffies(NOP_OUT_TIMEOUT));
+
+   if (timeout) {
+   spin_lock

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

2013-05-06 Thread Sujit Reddy Thumma
On 5/6/2013 11:07 AM, 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.
We have seen a kernel crash when the timeout happens in our internal
testing. This is basically because the the UIC_CMD_TIMEOUT of 500msec is
less for our platform. We see UIC_COMMAND_COMPL interrupt after this
timeout and since uic_cmd is freed we see a kernel crash.

[6.026094] ufshcd :01:00.0: link startup: error code -110
[6.030886] ufshcd :01:00.0: link startup failed -110
...

[6.487288] BUG: spinlock bad magic on CPU#0, swapper/0/0
[6.491683] Unable to handle kernel paging request at virtual address
612b
...
[7.625270] [] (spin_dump+0x4c/0x88) from []
(do_raw_spin_lock+0x20/0x154)
[7.633877] [] (do_raw_spin_lock+0x20/0x154) from
[] (_raw_spin_lock_irqsave+0x28/0x30)
[7.643583] [] (_raw_spin_lock_irqsave+0x28/0x30) from
[] (complete+0x1c/0x58)
[7.652525] [] (complete+0x1c/0x58) from []
(ufshcd_intr+0x1a8/0x498)
[7.660705] [] (ufshcd_intr+0x1a8/0x498) from []
(handle_irq_event_percpu+0xb0/0x290)
[7.670227] [] (handle_irq_event_percpu+0xb0/0x290) from
[] (handle_irq_event+0x3c/0x5c)
[7.680054] [] (handle_irq_event+0x3c/0x5c) from
[] (handle_fasteoi_irq+0xdc/0x148)
[7.689424] [] (handle_fasteoi_irq+0xdc/0x148) from
[] (generic_handle_irq+0x30/0x44)
[7.698977] [] (generic_handle_irq+0x30/0x44) from
[] (handle_IRQ+0x7c/0xc0)
[7.707736] [] (handle_IRQ+0x7c/0xc0) from []
(gic_handle_irq+0x94/0x110)
[7.716252] [] (gic_handle_irq+0x94/0x110) from
[] (__irq_svc+0x40/0x70)


Following would fix this. Please check. Also, we need to increase the
timeout to say 5 secs to avoid such races.

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index ecbae40..ae22a8e 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -485,6 +485,7 @@ 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)))
@@ -492,6 +493,10 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct
uic_command *uic_cmd)
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;
 }

@@ -1842,7 +1847,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,
struct ufshcd_lrb *lrbp)
  */
 static void ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
 {
-   if (intr_status & UIC_COMMAND_COMPL) {
+   if (hba->active_uic_cmd && (intr_status & UIC_COMMAND_COMPL)) {
hba->active_uic_cmd->argument2 |=
ufshcd_get_uic_cmd_result(hba);
hba->active_uic_cmd->argument3 =


> 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 
> ---
>   drivers/scsi/ufs/ufshcd.c |  287 
> ++---
>   drivers/scsi/ufs/ufshcd.h |   10 +-
>   2 files changed, 200 insertions(+), 97 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index e04c74e..118f104 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_TIMEOUT  500
>   
>   enum {
>   UFSHCD_MAX_CHANNEL  = 0,
> @@ -401,24 +405,115 @@ 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.

[PATCH 5/5] scsi: Remove 'last_reset' for struct Scsi_Host

2013-05-06 Thread Hannes Reinecke
Field is now unused, so remove it.

Signed-off-by: Hannes Reinecke 
---
 include/scsi/scsi_host.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index af7ad0e..dcf17dc 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -596,9 +596,8 @@ struct Scsi_Host {
unsigned int host_busy;/* commands actually active on 
low-level */
unsigned int host_failed;  /* commands that failed. */
unsigned int host_eh_scheduled;/* EH scheduled without command */
-
+
unsigned int host_no;  /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
-   unsigned long last_reset;
 
/*
 * These three parameters can be used to allow for wide scsi,
-- 
1.7.12.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 3/5] dc395: Move 'last_reset' into internal host structure

2013-05-06 Thread Hannes Reinecke
'last_reset' is only used internally, so move it into the
internal host structure.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/dc395x.c | 24 +---
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 694e13c..42e8624 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -308,6 +308,8 @@ struct AdapterCtlBlk {
struct timer_list waiting_timer;
struct timer_list selto_timer;
 
+   unsigned long last_reset;
+
u16 srb_count;
 
u8 sel_timeout;
@@ -860,9 +862,9 @@ static void waiting_set_timer(struct AdapterCtlBlk *acb, 
unsigned long to)
init_timer(&acb->waiting_timer);
acb->waiting_timer.function = waiting_timeout;
acb->waiting_timer.data = (unsigned long) acb;
-   if (time_before(jiffies + to, acb->scsi_host->last_reset - HZ / 2))
+   if (time_before(jiffies + to, acb->last_reset - HZ / 2))
acb->waiting_timer.expires =
-   acb->scsi_host->last_reset - HZ / 2 + 1;
+   acb->last_reset - HZ / 2 + 1;
else
acb->waiting_timer.expires = jiffies + to + 1;
add_timer(&acb->waiting_timer);
@@ -1319,7 +1321,7 @@ static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
udelay(500);
 
/* We may be in serious trouble. Wait some seconds */
-   acb->scsi_host->last_reset =
+   acb->last_reset =
jiffies + 3 * HZ / 2 +
HZ * acb->eeprom.delay_time;
 
@@ -1462,9 +1464,9 @@ static void selto_timer(struct AdapterCtlBlk *acb)
acb->selto_timer.function = selection_timeout_missed;
acb->selto_timer.data = (unsigned long) acb;
if (time_before
-   (jiffies + HZ, acb->scsi_host->last_reset + HZ / 2))
+   (jiffies + HZ, acb->last_reset + HZ / 2))
acb->selto_timer.expires =
-   acb->scsi_host->last_reset + HZ / 2 + 1;
+   acb->last_reset + HZ / 2 + 1;
else
acb->selto_timer.expires = jiffies + HZ + 1;
add_timer(&acb->selto_timer);
@@ -1535,7 +1537,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct 
DeviceCtlBlk* dcb,
}
/* Allow starting of SCSI commands half a second before we allow the 
mid-level
 * to queue them again after a reset */
-   if (time_before(jiffies, acb->scsi_host->last_reset - HZ / 2)) {
+   if (time_before(jiffies, acb->last_reset - HZ / 2)) {
dprintkdbg(DBG_KG, "start_scsi: Refuse cmds (reset wait)\n");
return 1;
}
@@ -3031,7 +3033,7 @@ static void disconnect(struct AdapterCtlBlk *acb)
dprintkl(KERN_ERR, "disconnect: No such device\n");
udelay(500);
/* Suspend queue for a while */
-   acb->scsi_host->last_reset =
+   acb->last_reset =
jiffies + HZ / 2 +
HZ * acb->eeprom.delay_time;
clear_fifo(acb, "disconnectEx");
@@ -3053,7 +3055,7 @@ static void disconnect(struct AdapterCtlBlk *acb)
waiting_process_next(acb);
} else if (srb->state & SRB_ABORT_SENT) {
dcb->flag &= ~ABORT_DEV_;
-   acb->scsi_host->last_reset = jiffies + HZ / 2 + 1;
+   acb->last_reset = jiffies + HZ / 2 + 1;
dprintkl(KERN_ERR, "disconnect: SRB_ABORT_SENT\n");
doing_srb_done(acb, DID_ABORT, srb->cmd, 1);
waiting_process_next(acb);
@@ -3649,7 +3651,7 @@ static void scsi_reset_detect(struct AdapterCtlBlk *acb)
/*DC395x_write8(acb, TRM_S1040_DMA_CONTROL,STOPDMAXFER); */
udelay(500);
/* Maybe we locked up the bus? Then lets wait even longer ... */
-   acb->scsi_host->last_reset =
+   acb->last_reset =
jiffies + 5 * HZ / 2 +
HZ * acb->eeprom.delay_time;
 
@@ -4426,7 +4428,7 @@ static void adapter_init_scsi_host(struct Scsi_Host *host)
host->dma_channel = -1;
host->unique_id = acb->io_port_base;
host->irq = acb->irq_level;
-   host->last_reset = jiffies;
+   acb->last_reset = jiffies;
 
host->max_id = 16;
if (host->max_id - 1 == eeprom->scsi_id)
@@ -4484,7 +4486,7 @@ static void adapter_init_chip(struct AdapterCtlBlk *acb)
/*spin_unlock_irq (&io_request_lock); */
udelay(500);
 
-   acb->scsi_host->last_reset =
+   acb->last_reset =
jiffies + HZ / 2 +
HZ * acb->eeprom.delay_time;
 
-- 
1.7.12.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 1/5] scsi: remove 'resetting' field from struct Scsi_Host

2013-05-06 Thread Hannes Reinecke
struct Scsi_Host has a field 'resetting' which is only ever used
in dpt_i2o. And even there the usage is questionable.
So remove the field and have dpt_i2o use the standard mechanism
for delaying I/O.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/dpt_i2o.c   | 22 +++---
 drivers/scsi/scsi.c  | 25 +
 include/scsi/scsi_host.h |  1 -
 3 files changed, 4 insertions(+), 44 deletions(-)

diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 19e1b42..943d9c0 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -448,18 +448,8 @@ static int adpt_queue_lck(struct scsi_cmnd * cmd, void 
(*done) (struct scsi_cmnd
}
 
rmb();
-   /*
-* TODO: I need to block here if I am processing ioctl cmds
-* but if the outstanding cmds all finish before the ioctl,
-* the scsi-core will not know to start sending cmds to me again.
-* I need to a way to restart the scsi-cores queues or should I block
-* calling scsi_done on the outstanding cmds instead
-* for now we don't set the IOCTL state
-*/
-   if(((pHba->state) & DPTI_STATE_IOCTL) || ((pHba->state) & 
DPTI_STATE_RESET)) {
-   pHba->host->last_reset = jiffies;
-   pHba->host->resetting = 1;
-   return 1;
+   if(((pHba->state) & DPTI_STATE_RESET)) {
+   return SCSI_MLQUEUE_HOST_BUSY;
}
 
// TODO if the cmd->device if offline then I may need to issue a bus 
rescan
@@ -1813,19 +1803,13 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user 
*arg)
do {
if(pHba->host)
spin_lock_irqsave(pHba->host->host_lock, flags);
-   // This state stops any new commands from enterring the
-   // controller while processing the ioctl
-// pHba->state |= DPTI_STATE_IOCTL;
-// We can't set this now - The scsi subsystem sets host_blocked and
-// the queue empties and stops.  We need a way to restart the queue
rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER);
if (rcode != 0)
printk("adpt_i2o_passthru: post wait failed %d %p\n",
rcode, reply);
-// pHba->state &= ~DPTI_STATE_IOCTL;
if(pHba->host)
spin_unlock_irqrestore(pHba->host->host_lock, flags);
-   } while(rcode == -ETIMEDOUT);  
+   } while(rcode == -ETIMEDOUT);
 
if(rcode){
goto cleanup;
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 2c0d0ec..173c6bc 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -658,7 +658,6 @@ EXPORT_SYMBOL(scsi_cmd_get_serial);
 int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 {
struct Scsi_Host *host = cmd->device->host;
-   unsigned long timeout;
int rtn = 0;
 
atomic_inc(&cmd->device->iorequest_cnt);
@@ -695,7 +694,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
goto out;
}
 
-   /* 
+   /*
 * If SCSI-2 or lower, store the LUN value in cmnd.
 */
if (cmd->device->scsi_level <= SCSI_2 &&
@@ -704,28 +703,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
   (cmd->device->lun << 5 & 0xe0);
}
 
-   /*
-* We will wait MIN_RESET_DELAY clock ticks after the last reset so
-* we can avoid the drive not being ready.
-*/
-   timeout = host->last_reset + MIN_RESET_DELAY;
-
-   if (host->resetting && time_before(jiffies, timeout)) {
-   int ticks_remaining = timeout - jiffies;
-   /*
-* NOTE: This may be executed from within an interrupt
-* handler!  This is bad, but for now, it'll do.  The irq
-* level of the interrupt handler has been masked out by the
-* platform dependent interrupt handling code already, so the
-* sti() here will not cause another call to the SCSI host's
-* interrupt handler (assuming there is one irq-level per
-* host).
-*/
-   while (--ticks_remaining >= 0)
-   mdelay(1 + 999 / HZ);
-   host->resetting = 0;
-   }
-
scsi_log_send(cmd);
 
/*
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 7552435..af7ad0e 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -598,7 +598,6 @@ struct Scsi_Host {
unsigned int host_eh_scheduled;/* EH scheduled without command */
 
unsigned int host_no;  /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
-   int resetting; /* if set, it means that last_reset is a valid value */
unsigned long last_reset;
 
/*
-- 
1.7.12.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of

[PATCH 2/5] tmscsim: Move 'last_reset' into host structure

2013-05-06 Thread Hannes Reinecke
The 'last_reset' value is only used internally, so move it into
the internal host structure.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/tmscsim.c | 12 ++--
 drivers/scsi/tmscsim.h |  1 +
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index 9327f5f..ec74087 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -521,7 +521,7 @@ dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* 
pDCB, struct dc390_sr
pACB->SelConn++;
return 1;
 }
-if (time_before (jiffies, pACB->pScsiHost->last_reset))
+if (time_before (jiffies, pACB->last_reset))
 {
DEBUG0(printk ("DC390: We were just reset and don't accept commands 
yet!\n"));
return 1;
@@ -1863,7 +1863,7 @@ dc390_ScsiRstDetect( struct dc390_acb* pACB )
 /* delay half a second */
 udelay (1000);
 DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-pACB->pScsiHost->last_reset = jiffies + 5*HZ/2
+pACB->last_reset = jiffies + 5*HZ/2
+ HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
 pACB->Connected = 0;
 
@@ -2048,7 +2048,7 @@ static int DC390_bus_reset (struct scsi_cmnd *cmd)
 
dc390_ResetDevParam(pACB);
mdelay(1);
-   pACB->pScsiHost->last_reset = jiffies + 3*HZ/2 
+   pACB->last_reset = jiffies + 3*HZ/2 
+ HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
 
DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
@@ -2383,7 +2383,7 @@ static void dc390_init_hw(struct dc390_acb *pACB, u8 
index)
if (pACB->Gmode2 & RST_SCSI_BUS) {
dc390_ResetSCSIBus(pACB);
udelay(1000);
-   shost->last_reset = jiffies + HZ/2 +
+   pACB->last_reset = jiffies + HZ/2 +
HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
}
 
@@ -2455,8 +2455,8 @@ static int dc390_probe_one(struct pci_dev *pdev, const 
struct pci_device_id *id)
shost->irq = pdev->irq;
shost->base = io_port;
shost->unique_id = io_port;
-   shost->last_reset = jiffies;
-   
+
+   pACB->last_reset = jiffies;
pACB->pScsiHost = shost;
pACB->IOPortBase = (u16) io_port;
pACB->IRQLevel = pdev->irq;
diff --git a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h
index 77adc54..3d1bb4a 100644
--- a/drivers/scsi/tmscsim.h
+++ b/drivers/scsi/tmscsim.h
@@ -143,6 +143,7 @@ u8  Ignore_IRQ; /* Not used */
 
 struct pci_dev *pdev;
 
+unsigned long   last_reset;
 unsigned long  Cmds;
 u32SelLost;
 u32SelConn;
-- 
1.7.12.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 4/5] advansys: Remove references to 'last_reset'

2013-05-06 Thread Hannes Reinecke
The 'last_reset' field is only displayed in logging messages but
never actually used. Remove references to it.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/advansys.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index c67e401..d814588 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -2511,8 +2511,8 @@ static void asc_prt_scsi_host(struct Scsi_Host *s)
struct asc_board *boardp = shost_priv(s);
 
printk("Scsi_Host at addr 0x%p, device %s\n", s, dev_name(boardp->dev));
-   printk(" host_busy %u, host_no %d, last_reset %d,\n",
-  s->host_busy, s->host_no, (unsigned)s->last_reset);
+   printk(" host_busy %u, host_no %d,\n",
+  s->host_busy, s->host_no);
 
printk(" base 0x%lx, io_port 0x%lx, irq %d,\n",
   (ulong)s->base, (ulong)s->io_port, boardp->irq);
@@ -3345,8 +3345,8 @@ static void asc_prt_driver_conf(struct seq_file *m, 
struct Scsi_Host *shost)
shost->host_no);
 
seq_printf(m,
-  " host_busy %u, last_reset %lu, max_id %u, max_lun %u, 
max_channel %u\n",
-  shost->host_busy, shost->last_reset, shost->max_id,
+  " host_busy %u, max_id %u, max_lun %u, max_channel %u\n",
+  shost->host_busy, shost->max_id,
   shost->max_lun, shost->max_channel);
 
seq_printf(m,
-- 
1.7.12.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 0/5] Cleanup struct Scsi_Host

2013-05-06 Thread Hannes Reinecke
The 'Scsi_Host' structure has two fields 'resetting' and
'last_reset' which are basically unused. There are only
4 drivers referencing 'last_reset' (dpt_i2o, tmscsim, dc395, and advansys),
and only dpt_i2o makes usage of both fields.
However, dpt_i2o does _not_ require a delay after reset,
so even there the usage is questionable.

So move the 'last_reset' field into the internal host
structure where needed and remove both fields from
struct Scsi_Host.

Hannes Reinecke (5):
  scsi: remove 'resetting' field from struct Scsi_Host
  tmscsim: Move 'last_reset' into host structure
  dc395: Move 'last_reset' into internal host structure
  advansys: Remove references to 'last_reset'
  scsi: Remove 'last_reset' for struct Scsi_Host

 drivers/scsi/advansys.c  |  8 
 drivers/scsi/dc395x.c| 24 +---
 drivers/scsi/dpt_i2o.c   | 22 +++---
 drivers/scsi/scsi.c  | 25 +
 drivers/scsi/tmscsim.c   | 12 ++--
 drivers/scsi/tmscsim.h   |  1 +
 include/scsi/scsi_host.h |  4 +---
 7 files changed, 29 insertions(+), 67 deletions(-)

-- 
1.7.12.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