Re: [PATCH 7/7] scsi: Add 'eh_deadline' to limit SCSI EH runtime

2013-06-28 Thread Hannes Reinecke
On 06/28/2013 09:29 AM, Bart Van Assche wrote:
 On 06/10/13 13:11, Hannes Reinecke wrote:
 +static int sdev_eh_deadline(struct Scsi_Host *shost,
 +   unsigned long eh_start)
 +{
 +if (!shost-eh_deadline)
 +return 0;
 +
 +if (shost-last_reset != 0 
 +time_before(shost-last_reset, eh_start))
 +eh_start = shost-last_reset;
 +
 +if (time_before(jiffies,
 +eh_start + shost-eh_deadline))
 +return 0;
 +
 +return 1;
 +}
 +
 +static int scsi_host_eh_deadline(struct Scsi_Host *shost)
 +{
 +if (!shost-last_reset)
 +return 0;
 +
 +return sdev_eh_deadline(shost, shost-last_reset);
 +}
 
 Hello Hannes,
 
 I would appreciate if you would choose other names for these two
 functions and also for shost-eh_deadline. To me a deadline is a
 time instant. As far as I can see the two functions above check
 whether a deadline has been passed, and shost-eh_deadline is a time
 interval. How about the following names: sdev_eh_past_deadline(),
 shost_eh_past_deadline() and shost-max_eh_jiffies ?
 
Sure. I changed the naming once already, so I don't have any issues
with that.
And yes, the suggested naming does make more sense.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke   zSeries  Storage
h...@suse.de  +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
--
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] mpt3sas: Description patch

2013-06-28 Thread Sreekanth Reddy

Please consider this patch set fot next kernel release.

Signed-off-by: Sreekanth Reddy sreekanth.re...@lsi.com
---

[PATCH 1/7][SCSI] mpt3sas: 2013 source code copyright.
[PATCH 2/7][SCSI] mpt3sas: Updated the Hardware timing requirements.
[PATCH 3/7][SCSI] mpt3sas: fix for kernel panic when driver loads with HBA 
conected to non LUN 0 configured expander.
[PATCH 4/7][SCSI] mpt3sas: Infinite loops can occur if 
MPI2_IOCSTATUS_CONFIG_INVALID_PAGE is not returned.
[PATCH 5/7][SCSI] mpt3sas: MPI2.5 Rev F v2.5.1.1 specification.
[PATCH 6/7][SCSI] mpt3sas: when async scanning is enabled then while scanning, 
devices are removed but their transport layer entries are not removed.
[PATCH 7/7][SCSI] mpt3sas: Bump driver version to v02.100.00.00.

--
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/7][SCSI] mpt3sas: Infinite loops can occur if MPI2_IOCSTATUS_CONFIG_INVALID_PAGE is not returned

2013-06-28 Thread Sreekanth Reddy

Infinite loop can occur if IOCStatus is not equal to
MPI2_IOCSTATUS_CONFIG_INVALID_PAGE value in the while loops in functions 
_scsih_search_responding_sas_devices,
_scsih_search_responding_raid_devices and
_scsih_search_responding_expanders

So, Instead of checking for MPI2_IOCSTATUS_CONFIG_INVALID_PAGE value,
in this patch code is modified to check for IOCStatus not equals to 
MPI2_IOCSTATUS_SUCCESS to break the while loop.

Signed-off-by: Sreekanth Reddy sreekanth.re...@lsi.com
Cc: sta...@vger.kernel.org
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c |   16 
 1 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 9ebc9dc..632eba7 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -6406,7 +6406,7 @@ _scsih_search_responding_sas_devices(struct 
MPT3SAS_ADAPTER *ioc)
handle))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) 
MPI2_IOCSTATUS_MASK;
-   if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+   if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
break;
handle = le16_to_cpu(sas_device_pg0.DevHandle);
device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
@@ -6508,7 +6508,7 @@ _scsih_search_responding_raid_devices(struct 
MPT3SAS_ADAPTER *ioc)
volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) 
MPI2_IOCSTATUS_MASK;
-   if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+   if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
break;
handle = le16_to_cpu(volume_pg1.DevHandle);
 
@@ -6532,7 +6532,7 @@ _scsih_search_responding_raid_devices(struct 
MPT3SAS_ADAPTER *ioc)
phys_disk_num))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) 
MPI2_IOCSTATUS_MASK;
-   if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+   if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
break;
phys_disk_num = pd_pg0.PhysDiskNum;
handle = le16_to_cpu(pd_pg0.DevHandle);
@@ -6611,7 +6611,7 @@ _scsih_search_responding_expanders(struct MPT3SAS_ADAPTER 
*ioc)
 
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) 
MPI2_IOCSTATUS_MASK;
-   if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+   if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
break;
 
handle = le16_to_cpu(expander_pg0.DevHandle);
@@ -6756,8 +6756,6 @@ _scsih_scan_for_devices_after_reset(struct 
MPT3SAS_ADAPTER *ioc)
MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) 
MPI2_IOCSTATUS_MASK;
-   if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
-   break;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
pr_info(MPT3SAS_FMT \tbreak from expander scan:  \
ioc_status(0x%04x), loginfo(0x%08x)\n,
@@ -6801,8 +6799,6 @@ _scsih_scan_for_devices_after_reset(struct 
MPT3SAS_ADAPTER *ioc)
phys_disk_num))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) 
MPI2_IOCSTATUS_MASK;
-   if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
-   break;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
pr_info(MPT3SAS_FMT \tbreak from phys disk scan: \
ioc_status(0x%04x), loginfo(0x%08x)\n,
@@ -6868,8 +6864,6 @@ _scsih_scan_for_devices_after_reset(struct 
MPT3SAS_ADAPTER *ioc)
volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) 
MPI2_IOCSTATUS_MASK;
-   if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
-   break;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
pr_info(MPT3SAS_FMT \tbreak from volume scan:  \
ioc_status(0x%04x), loginfo(0x%08x)\n,
@@ -6928,8 +6922,6 @@ _scsih_scan_for_devices_after_reset(struct 
MPT3SAS_ADAPTER *ioc)
handle))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) 
MPI2_IOCSTATUS_MASK;
-   if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
-   break;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
pr_info(MPT3SAS_FMT \tbreak from end device scan:\
 ioc_status(0x%04x), loginfo(0x%08x)\n,
-- 

[PATCH 5/7][SCSI] mpt3sas: MPI2.5 Rev F v2.5.1.1 specification

2013-06-28 Thread Sreekanth Reddy

Change set in MPI v2.5 Rev F(v2.5.1.1) specification and 2.00.29 header files

1. Added a bit to the IOCExceptions field of the IOCFacts Reply to indicate 
that the IOC detected a partial memory failure. 
2. Added ElapsedSeconds field to RAID Volume Indicator Structure. Added Elapsed 
Seconds Valid flag to Flags field of this structure. 
3. Added ElapsedSeconds field to Integrated RAID Operations Status Event Data. 
4. Added two new AbortType values for TargetModeAbort Request, one to abort all 
I/Os from a single initiator, and the other to abort only Command IUs. 
5. Added a new chapter covering DMA Flags and Multicast Modes. 
6. In the IOCSettings field of BIOS Page 1, modified the Adapter Support bits 
description to specify X86 BIOS. 
7. Marked bit 0 of the ControlFlags field of SAS IO Unit Page 1 as obsolete. 
This was the Clear SATA Affiliation flag. 
8. Added additional requirements for certain IOCs that support more than eight 
MSI-x vectors.

Signed-off-by: Sreekanth Reddy sreekanth.re...@lsi.com
---
 drivers/scsi/mpt3sas/mpi/mpi2.h  |   12 +---
 drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h |   15 +--
 drivers/scsi/mpt3sas/mpi/mpi2_init.h |2 +-
 drivers/scsi/mpt3sas/mpi/mpi2_ioc.h  |   10 +++---
 drivers/scsi/mpt3sas/mpi/mpi2_raid.h |   10 +++---
 drivers/scsi/mpt3sas/mpi/mpi2_sas.h  |2 +-
 drivers/scsi/mpt3sas/mpi/mpi2_tool.h |   10 ++
 drivers/scsi/mpt3sas/mpi/mpi2_type.h |2 +-
 8 files changed, 45 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpi/mpi2.h b/drivers/scsi/mpt3sas/mpi/mpi2.h
index 03317ff..cdb92a7 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2012 LSI Corporation.
+ * Copyright (c) 2000-2013 LSI Corporation.
  *
  *
  *  Name:  mpi2.h
@@ -8,7 +8,7 @@
  * scatter/gather formats.
  * Creation Date:  June 21, 2006
  *
- * mpi2.h Version:  02.00.26
+ * mpi2.h Version:  02.00.29
  *
  * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
  *   prefix are for use only on MPI v2.5 products, and must not be used
@@ -82,6 +82,10 @@
  * 03-29-12  02.00.25  Bumped MPI2_HEADER_VERSION_UNIT.
  * Added Hard Reset delay timings.
  * 07-10-12  02.00.26  Bumped MPI2_HEADER_VERSION_UNIT.
+ * 07-26-12  02.00.27  Bumped MPI2_HEADER_VERSION_UNIT.
+ * 11-27-12  02.00.28  Bumped MPI2_HEADER_VERSION_UNIT.
+ * 12-20-12  02.00.29  Bumped MPI2_HEADER_VERSION_UNIT.
+ * Added MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET.
  * --
  */
 
@@ -115,7 +119,7 @@
 #define MPI2_VERSION_02_05  (0x0205)
 
 /*Unit and Dev versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT(0x1A)
+#define MPI2_HEADER_VERSION_UNIT(0x1D)
 #define MPI2_HEADER_VERSION_DEV (0x00)
 #define MPI2_HEADER_VERSION_UNIT_MASK   (0xFF00)
 #define MPI2_HEADER_VERSION_UNIT_SHIFT  (8)
@@ -274,6 +278,8 @@ typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS {
 #define MPI2_REPLY_POST_HOST_INDEX_MASK (0x00FF)
 #define MPI2_RPHI_MSIX_INDEX_MASK   (0xFF00)
 #define MPI2_RPHI_MSIX_INDEX_SHIFT  (24)
+#define MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET  (0x030C) /*MPI v2.5 only*/
+
 
 /*
  *Defines for the HCBSize and address
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h 
b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
index d8b2c3e..889aa70 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2000-2011 LSI Corporation.
+ * Copyright (c) 2000-2013 LSI Corporation.
  *
  *
  *  Name:  mpi2_cnfg.h
  * Title:  MPI Configuration messages and pages
  * Creation Date:  November 10, 2006
  *
- *   mpi2_cnfg.h Version:  02.00.22
+ *   mpi2_cnfg.h Version:  02.00.24
  *
  * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
  *   prefix are for use only on MPI v2.5 products, and must not be used
@@ -155,6 +155,11 @@
  * Added UEFIVersion field to BIOS Page 1 and defined new
  * BiosOptions bits.
  * Incorporating additions for MPI v2.5.
+ * 11-27-12  02.00.23  Added MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER.
+ * Added MPI2_BIOSPAGE1_OPTIONS_MASK_OEM_ID.
+ * 12-20-12  02.00.24  Marked MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION as
+ * obsolete for MPI v2.5 and later.
+ * Added some defines for 12G SAS speeds.
  * --
  */
 
@@ -714,6 +719,7 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_7 {
 #define MPI2_MANUFACTURING7_PAGEVERSION (0x01)
 
 /*defines for the Flags field */
+#define MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER   (0x0002)
 #define 

[PATCH 6/7][SCSI] mpt3sas: when async scanning is enabled then while scanning, devices are removed but their transport layer entries are not removed

2013-06-28 Thread Sreekanth Reddy

When Async scanning mode is enabled and device scanning is in progress, 
devices should not be removed. But in actuality, devices are removed but
their transport layer entries are not removed. This causes error to add
the same device to the transport layer after host reset or diagnostic
reset.

So, in this patch, modified the code in such a way that device is not removed
when Async scanning mode is enabled and device scanning is in progress.

Signed-off-by: Sreekanth Reddy sreekanth.re...@lsi.com
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c |   22 +-
 1 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 632eba7..8cbe8fd 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -675,11 +675,12 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
 * devices while scanning is turned on due to an oops in
 * scsi_sysfs_add_sdev()-add_device()-sysfs_addrm_start()
 */
-   if (!ioc-is_driver_loading)
+   if (!ioc-is_driver_loading) {
mpt3sas_transport_port_remove(ioc,
sas_device-sas_address,
sas_device-sas_address_parent);
-   _scsih_sas_device_remove(ioc, sas_device);
+   _scsih_sas_device_remove(ioc, sas_device);
+   }
}
 }
 
@@ -7531,10 +7532,12 @@ _scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc)
sas_address_parent)) {
_scsih_sas_device_remove(ioc, sas_device);
} else if (!sas_device-starget) {
-   if (!ioc-is_driver_loading)
-   mpt3sas_transport_port_remove(ioc, sas_address,
+   if (!ioc-is_driver_loading) {
+   mpt3sas_transport_port_remove(ioc,
+   sas_address,
sas_address_parent);
-   _scsih_sas_device_remove(ioc, sas_device);
+   _scsih_sas_device_remove(ioc, sas_device);
+   }
}
}
 }
@@ -7590,13 +7593,14 @@ _scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc)
 * oops in scsi_sysfs_add_sdev()-add_device()-
 * sysfs_addrm_start()
 */
-   if (!ioc-is_driver_loading)
+   if (!ioc-is_driver_loading) {
mpt3sas_transport_port_remove(ioc,
sas_device-sas_address,
sas_device-sas_address_parent);
-   list_del(sas_device-list);
-   kfree(sas_device);
-   continue;
+   list_del(sas_device-list);
+   kfree(sas_device);
+   continue;
+   }
}
 
spin_lock_irqsave(ioc-sas_device_lock, flags);
-- 
1.7.3


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


Re: [PATCH 1/2] scsi: ufs: Add support for host assisted background operations

2013-06-28 Thread Sujit Reddy Thumma

On 6/26/2013 11:06 PM, Santosh Y wrote:

+/**
   * ufshcd_memory_alloc - allocate memory for host memory space data
structures
   * @hba: per adapter instance
   *
@@ -1803,6 +1904,9 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,
struct ufshcd_lrb *lrbp)
  */
 scsi_status = result  MASK_SCSI_STATUS;
 result = ufshcd_scsi_cmd_status(lrbp,
scsi_status);
+
+   if (ufshcd_is_exception_event(lrbp-ucd_rsp_ptr))

 ^
This condition will not satisfy until a runtime suspend/resume cycle
completes. Is there any specific reason it is only being enabled in
runtime-resume routine?
As the fBackgroundOpsEn = 1 by default, shouldn't the sequence be 1.
ufshcd_disable_auto_bkops() 2. ufshcd_enable_ee() during the startup.



According to the specification, the host should put in all measures to 
ensure that the device doesn't enter into URGENT_BKOPS need because the 
device may not operate optimally in that case. If your sequence is used 
then we expect a case where URGENT_BKOPS is needed if the runtime PM is 
disabled or prohibited soon after startup.


We wouldn't want to disable auto bkops by default without knowing that 
the runtime PM is enabled, since the device/host/software idleness is 
determined by runtime PM operation as explained in the commit text.


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


[PATCH v2 0/15] IB SRP initiator patches for kernel 3.11

2013-06-28 Thread Bart Van Assche

The purpose of this InfiniBand SRP initiator patch series is as follows:
- Make the SRP initiator driver better suited for use in a H.A. setup.
  Speed up failover by reducing the IB RC retry count and by notifying
  multipathd faster about transport layer failures by adding
  fast_io_fail_tmo and dev_loss_tmo parameters.
- Make the SRP initiator better suited for use on NUMA systems by
  making the HCA completion vector configurable.

Changes since the v1 of the IB SRP initiator patches for kernel 3.11 
patch series:

- scsi_transport_srp: Allowed both fast_io_fail and dev_loss timeouts
  to be disabled.
- scsi_transport_srp, srp_reconnect_rport(): switched from
  scsi_block_requests() to scsi_target_block() for blocking SCSI command
  processing temporarily.
- scsi_transport_srp, srp_start_tl_fail_timers(): only block SCSI device
  command processing if the fast_io_fail timer is enabled.
- Changed srp_abort() such that upon transport offline the value
  FAST_IO_FAIL is returned instead of SUCCESS.
- Fixed a race condition in the maintain single connection patch: a
  new login after removal had started but before removal had finished
  still could create a duplicate connection. Fixed this by deferring
  removal from the target list until removal has finished.
- Modified the error message in the same patch for reporting that a
  duplicate connection has been rejected.
- Modified patch 2/15 such that all possible race conditions with
  srp_claim_req() are addressed.
- Documented the comp_vector and tl_retry_count login string parameters.
- Updated dev_loss_tmo and fast_io_fail_tmo documentation - mentioned
  off is a valid choice.

Changes compared to v5 of the Make ib_srp better suited for H.A. 
purposes patch series:

- Left out patches that are already upstream.
- Made it possible to set dev_loss_tmo to off. This is useful in a
  setup using initiator side mirroring to avoid that new /dev/sd* names
  are reassigned after a failover or cable pull and reinsert.
- Added kernel module parameters to ib_srp for configuring default
  values of the fast_io_fail_tmo and dev_loss_tmo parameters.
- Added a patch from Dotan Barak that fixes a kernel oops during rmmod
  triggered by resource allocation failure at module load time.
- Avoid duplicate connections by refusing relogins instead of dropping
  duplicate connections, as proposed by Sebastian Riemer.
- Added a patch from Sebastian Riemer for failing SCSI commands
  silently.
- Added a patch from Vu Pham to make the transport layer (IB RC) retry
  count configurable.
- Made HCA completion vector configurable.

Changes since v4:
- Added a patch for removing SCSI devices upon a port down event

Changes since v3:
- Restored the dev_loss_tmo and fast_io_fail_tmo sysfs attributes.
- Included a patch to fix an ib_srp crash that could be triggered by
  cable pulling.

Changes since v2:
- Addressed the v2 review comments.
- Dropped the patches that have already been merged.
- Dropped the patches for integration with multipathd.
- Dropped the micro-optimization of the IB completion handlers.

The individual patches in this series are as follows:
0001-IB-srp-Fix-remove_one-crash-due-to-resource-exhausti.patch
0002-IB-srp-Fix-race-between-srp_queuecommand-and-srp_cla.patch
0003-IB-srp-Avoid-that-srp_reset_host-is-skipped-after-a-.patch
0004-IB-srp-Fail-I-O-fast-if-target-offline.patch
0005-IB-srp-Skip-host-settle-delay.patch
0006-IB-srp-Maintain-a-single-connection-per-I_T-nexus.patch
0007-IB-srp-Keep-rport-as-long-as-the-IB-transport-layer.patch
0008-scsi_transport_srp-Add-transport-layer-error-handlin.patch
0009-IB-srp-Add-srp_terminate_io.patch
0010-IB-srp-Use-SRP-transport-layer-error-recovery.patch
0011-IB-srp-Start-timers-if-a-transport-layer-error-occur.patch
0012-IB-srp-Fail-SCSI-commands-silently.patch
0013-IB-srp-Make-HCA-completion-vector-configurable.patch
0014-IB-srp-Make-transport-layer-retry-count-configurable.patch
0015-IB-srp-Bump-driver-version-and-release-date.patch
--
To unsubscribe from this list: send the line unsubscribe linux-scsi in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 06/15] IB/srp: Maintain a single connection per I_T nexus

2013-06-28 Thread Bart Van Assche
An SRP target is required to maintain a single connection between
initiator and target. This means that if the 'add_target' attribute
is used to create a second connection to a target that the first
connection will be logged out and that the SCSI error handler will
kick in. The SCSI error handler will cause the SRP initiator to
reconnect, which will cause I/O over the second connection to fail.
Avoid such ping-pong behavior by disabling relogins. Note: if
reconnecting manually is necessary, that is possible by deleting
and recreating an rport via sysfs.

Signed-off-by: Bart Van Assche bvanass...@acm.org
Signed-off-by: Sebastian Riemer sebastian.rie...@profitbricks.com
Cc: Roland Dreier rol...@kernel.org
Cc: David Dillow dillo...@ornl.gov
Cc: Vu Pham v...@mellanox.com
---
 drivers/infiniband/ulp/srp/ib_srp.c |   44 +--
 1 file changed, 42 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/ulp/srp/ib_srp.c 
b/drivers/infiniband/ulp/srp/ib_srp.c
index 01212c9..4eba1f7 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -542,11 +542,11 @@ static void srp_remove_work(struct work_struct *work)
 
WARN_ON_ONCE(target-state != SRP_TARGET_REMOVED);
 
+   srp_remove_target(target);
+
spin_lock(target-srp_host-target_lock);
list_del(target-list);
spin_unlock(target-srp_host-target_lock);
-
-   srp_remove_target(target);
 }
 
 static void srp_rport_delete(struct srp_rport *rport)
@@ -2010,6 +2010,36 @@ static struct class srp_class = {
.dev_release = srp_release_dev
 };
 
+/**
+ * srp_conn_unique() - check whether the connection to a target is unique
+ */
+static bool srp_conn_unique(struct srp_host *host,
+   struct srp_target_port *target)
+{
+   struct srp_target_port *t;
+   bool ret = false;
+
+   if (target-state == SRP_TARGET_REMOVED)
+   goto out;
+
+   ret = true;
+
+   spin_lock(host-target_lock);
+   list_for_each_entry(t, host-target_list, list) {
+   if (t != target 
+   target-id_ext == t-id_ext 
+   target-ioc_guid == t-ioc_guid 
+   target-initiator_ext == t-initiator_ext) {
+   ret = false;
+   break;
+   }
+   }
+   spin_unlock(host-target_lock);
+
+out:
+   return ret;
+}
+
 /*
  * Target ports are added by writing
  *
@@ -2266,6 +2296,16 @@ static ssize_t srp_create_target(struct device *dev,
if (ret)
goto err;
 
+   if (!srp_conn_unique(target-srp_host, target)) {
+   shost_printk(KERN_INFO, target-scsi_host,
+PFX Already connected to target port with 
id_ext=%016llx;ioc_guid=%016llx;initiator_ext=%016llx\n,
+be64_to_cpu(target-id_ext),
+be64_to_cpu(target-ioc_guid),
+be64_to_cpu(target-initiator_ext));
+   ret = -EEXIST;
+   goto err;
+   }
+
if (!host-srp_dev-fmr_pool  !target-allow_ext_sg 
target-cmd_sg_cnt  target-sg_tablesize) {
pr_warn(No FMR pool and no external indirect descriptors, 
limiting sg_tablesize to cmd_sg_cnt\n);
-- 
1.7.10.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 v2 07/15] IB/srp: Keep rport as long as the IB transport layer

2013-06-28 Thread Bart Van Assche
Keep the rport data structure around after srp_remove_host() has
finished until cleanup of the IB transport layer has finished
completely. This is necessary because later patches use the rport
pointer inside the queuecommand callback. Without this patch
accessing the rport from inside a queuecommand callback is racy
because srp_remove_host() must be invoked before scsi_remove_host()
and because the queuecommand callback may get invoked after
srp_remove_host() has finished.

Signed-off-by: Bart Van Assche bvanass...@acm.org
Cc: Roland Dreier rol...@purestorage.com
Cc: James Bottomley jbottom...@parallels.com
Cc: David Dillow dillo...@ornl.gov
Cc: Vu Pham v...@mellanox.com
Cc: Sebastian Riemer sebastian.rie...@profitbricks.com
---
 drivers/infiniband/ulp/srp/ib_srp.c |3 +++
 drivers/infiniband/ulp/srp/ib_srp.h |1 +
 drivers/scsi/scsi_transport_srp.c   |   18 ++
 include/scsi/scsi_transport_srp.h   |2 ++
 4 files changed, 24 insertions(+)

diff --git a/drivers/infiniband/ulp/srp/ib_srp.c 
b/drivers/infiniband/ulp/srp/ib_srp.c
index 4eba1f7..cb86be5 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -526,11 +526,13 @@ static void srp_remove_target(struct srp_target_port 
*target)
WARN_ON_ONCE(target-state != SRP_TARGET_REMOVED);
 
srp_del_scsi_host_attr(target-scsi_host);
+   srp_rport_get(target-rport);
srp_remove_host(target-scsi_host);
scsi_remove_host(target-scsi_host);
srp_disconnect_target(target);
ib_destroy_cm_id(target-cm_id);
srp_free_target_ib(target);
+   srp_rport_put(target-rport);
srp_free_req_data(target);
scsi_host_put(target-scsi_host);
 }
@@ -1984,6 +1986,7 @@ static int srp_add_target(struct srp_host *host, struct 
srp_target_port *target)
}
 
rport-lld_data = target;
+   target-rport = rport;
 
spin_lock(host-target_lock);
list_add_tail(target-list, host-target_list);
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h 
b/drivers/infiniband/ulp/srp/ib_srp.h
index 66fbedd..1817ed5 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -153,6 +153,7 @@ struct srp_target_port {
u16 io_class;
struct srp_host*srp_host;
struct Scsi_Host   *scsi_host;
+   struct srp_rport   *rport;
chartarget_name[32];
unsigned intscsi_id;
unsigned intsg_tablesize;
diff --git a/drivers/scsi/scsi_transport_srp.c 
b/drivers/scsi/scsi_transport_srp.c
index f379c7f..f7ba94a 100644
--- a/drivers/scsi/scsi_transport_srp.c
+++ b/drivers/scsi/scsi_transport_srp.c
@@ -185,6 +185,24 @@ static int srp_host_match(struct attribute_container 
*cont, struct device *dev)
 }
 
 /**
+ * srp_rport_get() - increment rport reference count
+ */
+void srp_rport_get(struct srp_rport *rport)
+{
+   get_device(rport-dev);
+}
+EXPORT_SYMBOL(srp_rport_get);
+
+/**
+ * srp_rport_put() - decrement rport reference count
+ */
+void srp_rport_put(struct srp_rport *rport)
+{
+   put_device(rport-dev);
+}
+EXPORT_SYMBOL(srp_rport_put);
+
+/**
  * srp_rport_add - add a SRP remote port to the device hierarchy
  * @shost: scsi host the remote port is connected to.
  * @ids:   The port id for the remote port.
diff --git a/include/scsi/scsi_transport_srp.h 
b/include/scsi/scsi_transport_srp.h
index ff0f04a..5a2d2d1 100644
--- a/include/scsi/scsi_transport_srp.h
+++ b/include/scsi/scsi_transport_srp.h
@@ -38,6 +38,8 @@ extern struct scsi_transport_template *
 srp_attach_transport(struct srp_function_template *);
 extern void srp_release_transport(struct scsi_transport_template *);
 
+extern void srp_rport_get(struct srp_rport *rport);
+extern void srp_rport_put(struct srp_rport *rport);
 extern struct srp_rport *srp_rport_add(struct Scsi_Host *,
   struct srp_rport_identifiers *);
 extern void srp_rport_del(struct srp_rport *);
-- 
1.7.10.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 v2 08/15] scsi_transport_srp: Add transport layer error handling

2013-06-28 Thread Bart Van Assche
Add the necessary functions in the SRP transport module to allow
an SRP initiator driver to implement transport layer error handling
similar to the functionality already provided by the FC transport
layer. This includes:
- Support for implementing fast_io_fail_tmo, the time that should
  elapse after having detected a transport layer problem and
  before failing I/O.
- Support for implementing dev_loss_tmo, the time that should
  elapse after having detected a transport layer problem and
  before removing a remote port.

Signed-off-by: Bart Van Assche bvanass...@acm.org
Cc: Roland Dreier rol...@purestorage.com
Cc: James Bottomley jbottom...@parallels.com
Cc: David Dillow dillo...@ornl.gov
Cc: Vu Pham v...@mellanox.com
Cc: Sebastian Riemer sebastian.rie...@profitbricks.com
---
 Documentation/ABI/stable/sysfs-transport-srp |   37 ++
 drivers/scsi/scsi_transport_srp.c|  477 +-
 include/scsi/scsi_transport_srp.h|   62 +++-
 3 files changed, 573 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/stable/sysfs-transport-srp 
b/Documentation/ABI/stable/sysfs-transport-srp
index b36fb0d..6a4d651 100644
--- a/Documentation/ABI/stable/sysfs-transport-srp
+++ b/Documentation/ABI/stable/sysfs-transport-srp
@@ -5,6 +5,24 @@ Contact:   linux-scsi@vger.kernel.org, 
linux-r...@vger.kernel.org
 Description:   Instructs an SRP initiator to disconnect from a target and to
remove all LUNs imported from that target.
 
+What:  /sys/class/srp_remote_ports/port-h:n/dev_loss_tmo
+Date:  October 1, 2013
+KernelVersion: 3.11
+Contact:   linux-scsi@vger.kernel.org, linux-r...@vger.kernel.org
+Description:   Number of seconds the SCSI layer will wait after a transport
+   layer error has been observed before removing a target port.
+   Zero means immediate removal. Setting this attribute to off
+   will disable this behavior.
+
+What:  /sys/class/srp_remote_ports/port-h:n/fast_io_fail_tmo
+Date:  October 1, 2013
+KernelVersion: 3.11
+Contact:   linux-scsi@vger.kernel.org, linux-r...@vger.kernel.org
+Description:   Number of seconds the SCSI layer will wait after a transport
+   layer error has been observed before failing I/O. Zero means
+   immediate removal. Setting this attribute to off will
+   disable this behavior.
+
 What:  /sys/class/srp_remote_ports/port-h:n/port_id
 Date:  June 27, 2007
 KernelVersion: 2.6.24
@@ -12,8 +30,27 @@ Contact: linux-scsi@vger.kernel.org
 Description:   16-byte local SRP port identifier in hexadecimal format. An
example: 4c:49:4e:55:58:20:56:49:4f:00:00:00:00:00:00:00.
 
+What:  /sys/class/srp_remote_ports/port-h:n/reconnect_delay
+Date:  October 1, 2013
+KernelVersion: 3.11
+Contact:   linux-scsi@vger.kernel.org, linux-r...@vger.kernel.org
+Description:   Number of seconds the SCSI layer will wait after a reconnect
+   attempt failed before retrying.
+
 What:  /sys/class/srp_remote_ports/port-h:n/roles
 Date:  June 27, 2007
 KernelVersion: 2.6.24
 Contact:   linux-scsi@vger.kernel.org
 Description:   Role of the remote port. Either SRP Initiator or SRP Target.
+
+What:  /sys/class/srp_remote_ports/port-h:n/state
+Date:  October 1, 2013
+KernelVersion: 3.11
+Contact:   linux-scsi@vger.kernel.org, linux-r...@vger.kernel.org
+Description:   State of the transport layer to the remote port. running if
+   the transport layer is operational; blocked if a transport
+   layer error has been encountered but the fail_io_fast_tmo
+   timer has not yet fired; fail-fast after the
+   fail_io_fast_tmo timer has fired and before the dev_loss_tmo
+   timer has fired; lost after the dev_loss_tmo timer has
+   fired and before the port is finally removed.
diff --git a/drivers/scsi/scsi_transport_srp.c 
b/drivers/scsi/scsi_transport_srp.c
index f7ba94a..44b27dd 100644
--- a/drivers/scsi/scsi_transport_srp.c
+++ b/drivers/scsi/scsi_transport_srp.c
@@ -24,11 +24,13 @@
 #include linux/err.h
 #include linux/slab.h
 #include linux/string.h
+#include linux/delay.h
 
 #include scsi/scsi.h
 #include scsi/scsi_device.h
 #include scsi/scsi_host.h
 #include scsi/scsi_transport.h
+#include scsi/scsi_cmnd.h
 #include scsi/scsi_transport_srp.h
 #include scsi_transport_srp_internal.h
 
@@ -38,7 +40,7 @@ struct srp_host_attrs {
 #define to_srp_host_attrs(host)((struct srp_host_attrs 
*)(host)-shost_data)
 
 #define SRP_HOST_ATTRS 0
-#define SRP_RPORT_ATTRS 3
+#define SRP_RPORT_ATTRS 8
 
 struct srp_internal {
struct scsi_transport_template t;
@@ -54,6 +56,25 @@ struct srp_internal {
 
 #definedev_to_rport(d) container_of(d, struct srp_rport, dev)
 #define transport_class_to_srp_rport(dev) dev_to_rport((dev)-parent)
+static inline struct 

Re: [PATCH 7/7] scsi: Add 'eh_deadline' to limit SCSI EH runtime

2013-06-28 Thread Ewan Milne
On Fri, 2013-06-28 at 09:14 +0200, Hannes Reinecke wrote:

  @@ -232,6 +272,9 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int 
  eh_flag)
 if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY))
 goto out_unlock;
   
  +  if (sdev-eh_deadline  !shost-last_reset)
  +  shost-last_reset = jiffies;
  +
  
  I think this is supposed to be if (shost-eh_deadline ...
  
 No. -last_reset is set to the time the first command timeout/failure.
 
 -last_reset + -eh_deadline will give you the expiry time.

Sorry, I wasn't clear what I meant.  What I meant was:

  if (shost-eh_deadline  !shost-last_reset)
  shost-last_reset = jiffies;

...because the eh_deadline field is in struct Scsi_Host, not
in struct scsi_device.

-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


[PATCH v2 12/15] IB/srp: Fail SCSI commands silently

2013-06-28 Thread Bart Van Assche
From: Sebastian Riemer sebastian.rie...@profitbricks.com

Avoid that path failover in a multipath setup causes the SCSI layer
to generate kernel messages about SCSI command failures. This patch
speeds up SRP initiator operation significantly when monitoring
kernel messages over a serial port.

[bvanassche: Changed patch description]
Signed-off-by: Sebastian Riemer sebastian.rie...@profitbricks.com
Signed-off-by: Bart Van Assche bvanass...@acm.org
Cc: Roland Dreier rol...@purestorage.com
Cc: David Dillow dillo...@ornl.gov
Cc: Vu Pham v...@mellanox.com
---
 drivers/infiniband/ulp/srp/ib_srp.c |3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/infiniband/ulp/srp/ib_srp.c 
b/drivers/infiniband/ulp/srp/ib_srp.c
index a8cc427..e77176e 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -757,6 +757,7 @@ static void srp_finish_req(struct srp_target_port *target,
 
if (scmnd) {
srp_free_req(target, req, scmnd, 0);
+   scmnd-request-cmd_flags |= REQ_QUIET;
scmnd-result = result;
scmnd-scsi_done(scmnd);
}
@@ -1438,6 +1439,7 @@ static int srp_queuecommand(struct Scsi_Host *shost, 
struct scsi_cmnd *scmnd)
 
result = srp_chkready(target-rport);
if (unlikely(result)) {
+   scmnd-request-cmd_flags |= REQ_QUIET;
scmnd-result = result;
scmnd-scsi_done(scmnd);
return 0;
@@ -1843,6 +1845,7 @@ static int srp_abort(struct scsi_cmnd *scmnd)
else
ret = FAILED;
srp_free_req(target, req, scmnd, 0);
+   scmnd-request-cmd_flags |= REQ_QUIET;
scmnd-result = DID_ABORT  16;
scmnd-scsi_done(scmnd);
 
-- 
1.7.10.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


Re: [PATCH 4/7][SCSI] mpt3sas: Infinite loops can occur if MPI2_IOCSTATUS_CONFIG_INVALID_PAGE is not returned

2013-06-28 Thread Bjørn Mork
Sreekanth Reddy sreekanth.re...@lsi.com writes:

 Infinite loop can occur if IOCStatus is not equal to
 MPI2_IOCSTATUS_CONFIG_INVALID_PAGE value in the while loops in functions 
 _scsih_search_responding_sas_devices,
 _scsih_search_responding_raid_devices and
 _scsih_search_responding_expanders

 So, Instead of checking for MPI2_IOCSTATUS_CONFIG_INVALID_PAGE value,
 in this patch code is modified to check for IOCStatus not equals to 
 MPI2_IOCSTATUS_SUCCESS to break the while loop.

 Signed-off-by: Sreekanth Reddy sreekanth.re...@lsi.com
 Cc: sta...@vger.kernel.org
 ---
  drivers/scsi/mpt3sas/mpt3sas_scsih.c |   16 
  1 files changed, 4 insertions(+), 12 deletions(-)

 diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
 b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
 index 9ebc9dc..632eba7 100644
 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
 +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
 @@ -6406,7 +6406,7 @@ _scsih_search_responding_sas_devices(struct 
 MPT3SAS_ADAPTER *ioc)
   handle))) {
   ioc_status = le16_to_cpu(mpi_reply.IOCStatus) 
   MPI2_IOCSTATUS_MASK;
 - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
 + if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
   break;
   handle = le16_to_cpu(sas_device_pg0.DevHandle);
   device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);

Doesn't the same apply to the code mpt2sas driver you copied this code
from?



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


SCSI vs MN10300: Can get_user() be given an array?

2013-06-28 Thread David Howells

The MN10300 arch is throwing up an error in the SCSI driver and I'm not sure
whether it needs fixing in the arch - in get_user() - or in the SCSI code.

The problem is this line in sg_scsi_ioctl():

if (get_user(opcode, sic-data))

sic points to the following struct:

typedef struct scsi_ioctl_command {
unsigned int inlen;
unsigned int outlen;
unsigned char data[0];
} Scsi_Ioctl_Command;

However, __get_user_check() on MN10300 does this:

const __typeof__(ptr) __guc_ptr = (ptr);

which fails with:

block/scsi_ioctl.c:450: error: invalid initializer

The question is what is SCSI actually asking get_user() to do?  As far as I
can tell, gcc thinks that it's being askied to declare some sort of array
here.

Should the SCSI driver be changed to:

if (get_user(opcode, (unsigned char *)sic-data))

or should the MN10300 arch be changed to morph the array into a pointer,
perhaps with:

const __typeof__(ptr[0])* __guc_ptr = (ptr);

or:

const __typeof__(*ptr)* __guc_ptr = (ptr);

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


[PATCH V2 0/2] Add suport for internal request (NOP and Query Request)

2013-06-28 Thread Sujit Reddy Thumma
This patch series replace the previous Query Request and NOP patches:
[PATCH 1/8] scsi: ufs: add support for query
[PATCH 6/8] scsi: ufs: Add support for sending NOP OUT UPIU
[PATCH 7/8] scsi: ufs: Set fDeviceInit flag to initiate device initialization
Major difference -

Sending the query request via the SCSI vendor specific command can
cause a deadlock in case the SCSI command queue is blocked and we
would like to send a query request (for example fDeviceInit in case
of re-initialization). In addition, usage of a vendor specific SCSI
command for UFS can cause future conflicts if this vendor specific
command will be allocated for a different usage.

The new patch series gets an internal tag for NOP and query requests
and do not involve the SCSI layer in UFS specific requests transfers.
This design also resolves the possible deadlock mentioned above.


Depends on:
[PATCH 01/10] scsi: ufs: wrap the i/o access operations
[PATCH 02/10] scsi: ufs: amend interrupt configuration
[PATCH 03/10] scsi: ufs: remove version check before IS reg clear
[PATCH 04/10] scsi: ufs: rework link start-up process
[PATCH 05/10] scsi: ufs: Fix the response UPIU length setting
[PATCH 06/10] scsi: ufs: use devres functions for ufshcd
[PATCH 07/10] ufshcd-pltfrm: add missing empty slot in ufs_of_match[]
[PATCH 08/10] ufs: fix register address in UIC error interrupt handling
[PATCH 09/10] ufshcd-pltfrm: remove unnecessary dma_set_coherent_mask() call
[PATCH 10/10] ufs: fix DMA mask setting

Changes from v1
- Allocate a tag for device management commands dynamically instead
  of reserving tag[MAX_QUEUE - 1].
- Changed the internal_cmd naming to dev_cmd to avoid confusion
  with other type of internal commands other than NOP and QUERY.

Dolev Raviv (1):
  scsi: ufs: Set fDeviceInit flag to initiate device initialization

Sujit Reddy Thumma (1):
  scsi: ufs: Add support for sending NOP OUT UPIU

 drivers/scsi/ufs/ufs.h|  127 ++-
 drivers/scsi/ufs/ufshcd.c |  886 +++--
 drivers/scsi/ufs/ufshcd.h |   43 ++-
 drivers/scsi/ufs/ufshci.h |2 +-
 4 files changed, 939 insertions(+), 119 deletions(-)

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


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

2013-06-28 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.

A tag is acquired from the SCSI tag map space in order to send the device
management command. When the tag is acquired by internal command the scsi
command is rejected with host busy flag in order to requeue the request.
To avoid frequent collisions between internal commands and scsi commands
the device management command tag is allocated in the opposite direction
w.r.t block layer tag allocation.

Signed-off-by: Sujit Reddy Thumma sthu...@codeaurora.org
Signed-off-by: Dolev Raviv dra...@codeaurora.org
---
 drivers/scsi/ufs/ufs.h|   43 +++-
 drivers/scsi/ufs/ufshcd.c |  596 +
 drivers/scsi/ufs/ufshcd.h |   29 ++-
 3 files changed, 552 insertions(+), 116 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 139bc06..4737fad 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -36,10 +36,16 @@
 #ifndef _UFS_H
 #define _UFS_H
 
+#include linux/mutex.h
+#include linux/types.h
+
 #define MAX_CDB_SIZE   16
+#define GENERAL_UPIU_REQUEST_SIZE 32
+#define UPIU_HEADER_DATA_SEGMENT_MAX_SIZE  ((ALIGNED_UPIU_SIZE) - \
+   (GENERAL_UPIU_REQUEST_SIZE))
 
 #define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\
-   ((byte3  24) | (byte2  16) |\
+   cpu_to_be32((byte3  24) | (byte2  16) |\
 (byte1  8) | (byte0))
 
 /*
@@ -73,6 +79,7 @@ enum {
UPIU_TRANSACTION_TASK_RSP   = 0x24,
UPIU_TRANSACTION_READY_XFER = 0x31,
UPIU_TRANSACTION_QUERY_RSP  = 0x36,
+   UPIU_TRANSACTION_REJECT_UPIU= 0x3F,
 };
 
 /* UPIU Read/Write flags */
@@ -110,6 +117,12 @@ enum {
UPIU_COMMAND_SET_TYPE_QUERY = 0x2,
 };
 
+/* UTP Transfer Request Command Offset */
+#define UPIU_COMMAND_TYPE_OFFSET   28
+
+/* Offset of the response code in the UPIU header */
+#define UPIU_RSP_CODE_OFFSET   8
+
 enum {
MASK_SCSI_STATUS= 0xFF,
MASK_TASK_RESPONSE  = 0xFF00,
@@ -138,26 +151,32 @@ struct utp_upiu_header {
 
 /**
  * struct utp_upiu_cmd - Command UPIU structure
- * @header: UPIU header structure DW-0 to DW-2
  * @data_transfer_len: Data Transfer Length DW-3
  * @cdb: Command Descriptor Block CDB DW-4 to DW-7
  */
 struct utp_upiu_cmd {
-   struct utp_upiu_header header;
u32 exp_data_transfer_len;
u8 cdb[MAX_CDB_SIZE];
 };
 
 /**
- * struct utp_upiu_rsp - Response UPIU structure
- * @header: UPIU header DW-0 to DW-2
+ * struct utp_upiu_req - general upiu request structure
+ * @header:UPIU header structure DW-0 to DW-2
+ * @sc: fields structure for scsi command
+ */
+struct utp_upiu_req {
+   struct utp_upiu_header header;
+   struct utp_upiu_cmd sc;
+};
+
+/**
+ * struct utp_cmd_rsp - Response UPIU structure
  * @residual_transfer_count: Residual transfer count DW-3
  * @reserved: Reserved double words DW-4 to DW-7
  * @sense_data_len: Sense data length DW-8 U16
  * @sense_data: Sense data field DW-8 to DW-12
  */
-struct utp_upiu_rsp {
-   struct utp_upiu_header header;
+struct utp_cmd_rsp {
u32 residual_transfer_count;
u32 reserved[4];
u16 sense_data_len;
@@ -165,6 +184,16 @@ struct utp_upiu_rsp {
 };
 
 /**
+ * struct utp_upiu_rsp - general upiu response structure
+ * @header: UPIU header structure DW-0 to DW-2
+ * @sr: fields structure for scsi command
+ */
+struct utp_upiu_rsp {
+   struct utp_upiu_header header;
+   struct utp_cmd_rsp sr;
+};
+
+/**
  * struct utp_upiu_task_req - Task request UPIU structure
  * @header - UPIU header structure DW0 to DW-2
  * @input_param1: Input parameter 1 DW-3
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 431ddb2..d613ae4 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -43,6 +43,11 @@
 /* UIC command timeout, unit: ms */
 #define UIC_CMD_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 */
+
 enum {
UFSHCD_MAX_CHANNEL  = 0,
UFSHCD_MAX_ID   = 1,
@@ -71,6 +76,47 @@ enum {
INT_AGGR_CONFIG,
 };
 
+/*
+ * ufshcd_wait_for_register - wait for register value to change
+ * @hba - per-adapter interface
+ * @reg - mmio register offset
+ * @mask - mask to apply to read register value
+ * @val - wait condition
+ * @interval_us - polling interval in microsecs
+ * @timeout_ms - timeout in millisecs
+ *
+ * Returns final register value after 

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

2013-06-28 Thread Sujit Reddy Thumma
From: Dolev Raviv dra...@codeaurora.org

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 dra...@codeaurora.org
Signed-off-by: Sujit Reddy Thumma sthu...@codeaurora.org
---
 drivers/scsi/ufs/ufs.h|   88 +-
 drivers/scsi/ufs/ufshcd.c |  292 -
 drivers/scsi/ufs/ufshcd.h |   14 ++
 drivers/scsi/ufs/ufshci.h |2 +-
 4 files changed, 390 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 4737fad..5484c59 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -43,6 +43,8 @@
 #define GENERAL_UPIU_REQUEST_SIZE 32
 #define UPIU_HEADER_DATA_SEGMENT_MAX_SIZE  ((ALIGNED_UPIU_SIZE) - \
(GENERAL_UPIU_REQUEST_SIZE))
+#define QUERY_OSF_SIZE ((GENERAL_UPIU_REQUEST_SIZE) - \
+   (sizeof(struct utp_upiu_header)))
 
 #define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\
cpu_to_be32((byte3  24) | (byte2  16) |\
@@ -68,7 +70,7 @@ enum {
UPIU_TRANSACTION_COMMAND= 0x01,
UPIU_TRANSACTION_DATA_OUT   = 0x02,
UPIU_TRANSACTION_TASK_REQ   = 0x04,
-   UPIU_TRANSACTION_QUERY_REQ  = 0x26,
+   UPIU_TRANSACTION_QUERY_REQ  = 0x16,
 };
 
 /* UTP UPIU Transaction Codes Target to Initiator */
@@ -97,8 +99,19 @@ enum {
UPIU_TASK_ATTR_ACA  = 0x03,
 };
 
-/* UTP QUERY Transaction Specific Fields OpCode */
+/* UPIU Query request function */
 enum {
+   UPIU_QUERY_FUNC_STANDARD_READ_REQUEST = 0x01,
+   UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST = 0x81,
+};
+
+/* Flag idn for Query Requests*/
+enum flag_idn {
+   QUERY_FLAG_IDN_FDEVICEINIT = 0x01,
+};
+
+/* UTP QUERY Transaction Specific Fields OpCode */
+enum query_opcode {
UPIU_QUERY_OPCODE_NOP   = 0x0,
UPIU_QUERY_OPCODE_READ_DESC = 0x1,
UPIU_QUERY_OPCODE_WRITE_DESC= 0x2,
@@ -110,6 +123,21 @@ enum {
UPIU_QUERY_OPCODE_TOGGLE_FLAG   = 0x8,
 };
 
+/* Query response result code */
+enum {
+   QUERY_RESULT_SUCCESS= 0x00,
+   QUERY_RESULT_NOT_READABLE   = 0xF6,
+   QUERY_RESULT_NOT_WRITEABLE  = 0xF7,
+   QUERY_RESULT_ALREADY_WRITTEN= 0xF8,
+   QUERY_RESULT_INVALID_LENGTH = 0xF9,
+   QUERY_RESULT_INVALID_VALUE  = 0xFA,
+   QUERY_RESULT_INVALID_SELECTOR   = 0xFB,
+   QUERY_RESULT_INVALID_INDEX  = 0xFC,
+   QUERY_RESULT_INVALID_IDN= 0xFD,
+   QUERY_RESULT_INVALID_OPCODE = 0xFE,
+   QUERY_RESULT_GENERAL_FAILURE= 0xFF,
+};
+
 /* UTP Transfer Request Command Type (CT) */
 enum {
UPIU_COMMAND_SET_TYPE_SCSI  = 0x0,
@@ -127,6 +155,7 @@ enum {
MASK_SCSI_STATUS= 0xFF,
MASK_TASK_RESPONSE  = 0xFF00,
MASK_RSP_UPIU_RESULT= 0x,
+   MASK_QUERY_DATA_SEG_LEN = 0x,
 };
 
 /* Task management service response */
@@ -160,13 +189,40 @@ struct utp_upiu_cmd {
 };
 
 /**
+ * struct utp_upiu_query - upiu request buffer structure for
+ * query request.
+ * @opcode: command to perform B-0
+ * @idn: a value that indicates the particular type of data B-1
+ * @index: Index to further identify data B-2
+ * @selector: Index to further identify data B-3
+ * @reserved_osf: spec reserved field B-4,5
+ * @length: number of descriptor bytes to read/write B-6,7
+ * @value: Attribute value to be written DW-6
+ * @reserved: spec reserved DW-7,8
+ */
+struct utp_upiu_query {
+   u8 opcode;
+   u8 idn;
+   u8 index;
+   u8 selector;
+   u16 reserved_osf;
+   u16 length;
+   u32 value;
+   u32 reserved[2];
+};
+
+/**
  * struct utp_upiu_req - general upiu request structure
  * @header:UPIU header structure DW-0 to DW-2
  * @sc: fields structure for scsi command
+ * @qr: fields structure for query request
  */
 struct utp_upiu_req {
struct utp_upiu_header header;
-   struct utp_upiu_cmd sc;
+   union {
+   struct utp_upiu_cmd sc;
+   struct utp_upiu_query qr;
+   };
 };
 
 /**
@@ -187,10 +243,14 @@ struct utp_cmd_rsp {
  * struct utp_upiu_rsp - general upiu response structure
  * @header: UPIU header structure DW-0 to DW-2
  * @sr: fields structure for scsi command
+ * @qr: fields structure for query request
  */
 struct utp_upiu_rsp {
struct utp_upiu_header header;
-   struct utp_cmd_rsp sr;
+   union {
+   struct utp_cmd_rsp sr;
+   struct utp_upiu_query qr;
+   };
 };
 
 /**
@@ -223,4 +283,24 @@ struct utp_upiu_task_rsp {
u32 

[PATCH V2 0/2] scsi: ufs: Add support to control UFS device background operations

2013-06-28 Thread Sujit Reddy Thumma
Add host assisted background operations for UFS device and runtime PM
helpers for ufshcd platform and pci glue drivers. The background operations
are disabled during runtime resume and enabled when the device is idle and
runtime suspended.

These patches depends on:
[PATCH 01/10] scsi: ufs: wrap the i/o access operations
[PATCH 02/10] scsi: ufs: amend interrupt configuration
[PATCH 03/10] scsi: ufs: remove version check before IS reg clear
[PATCH 04/10] scsi: ufs: rework link start-up process
[PATCH 05/10] scsi: ufs: Fix the response UPIU length setting
[PATCH 06/10] scsi: ufs: use devres functions for ufshcd
[PATCH 07/10] ufshcd-pltfrm: add missing empty slot in ufs_of_match[]
[PATCH 08/10] ufs: fix register address in UIC error interrupt handling
[PATCH 09/10] ufshcd-pltfrm: remove unnecessary dma_set_coherent_mask() call
[PATCH 10/10] ufs: fix DMA mask setting
[PATCH V2 1/2] scsi: ufs: Add support for sending NOP OUT UPIU
[PATCH V2 2/2] scsi: ufs: Set fDeviceInit flag to initiate device initialization

Changes from v1:
- Minor cleanup and rebase
- Forced enable of auto bkops during initialization to make sure device
  and driver state are matched.

Sujit Reddy Thumma (2):
  scsi: ufs: Add support for host assisted background operations
  scsi: ufs: Add runtime PM helpers for UFS host driver

 drivers/scsi/ufs/ufs.h   |   25 +++-
 drivers/scsi/ufs/ufshcd-pci.c|   60 ++-
 drivers/scsi/ufs/ufshcd-pltfrm.c |   41 +
 drivers/scsi/ufs/ufshcd.c|  337 ++
 drivers/scsi/ufs/ufshcd.h|   10 +
 5 files changed, 466 insertions(+), 7 deletions(-)

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


[PATCH V2 1/2] scsi: ufs: Add support for host assisted background operations

2013-06-28 Thread Sujit Reddy Thumma
Background operations in the UFS device can be disabled by
the host to reduce the response latency of transfer requests.
Add support for enabling/disabling the background operations
during runtime suspend/resume of the device.

If the device is in critical need of BKOPS it will raise an
URGENT_BKOPS exception which should be handled by the host to
make sure the device performs as expected.

During bootup, the BKOPS is enabled in the device by default.
The disable of BKOPS is supported only when the driver supports
runtime suspend/resume operations as the runtime PM framework
provides a way to determine the device idleness and hence BKOPS
can be managed effectively. During runtime resume the BKOPS is
disabled to reduce latency and during runtime suspend the BKOPS
is enabled to allow device to carry out idle time BKOPS.

In some cases where the BKOPS is disabled during runtime resume
and due to continuous data transfers the runtime suspend is not
triggered, the BKOPS is enabled when the device raises a level-2
exception (outstanding operations - performance impact).

Signed-off-by: Sujit Reddy Thumma sthu...@codeaurora.org
---
 drivers/scsi/ufs/ufs.h|   25 -
 drivers/scsi/ufs/ufshcd.c |  337 +
 drivers/scsi/ufs/ufshcd.h |   10 ++
 3 files changed, 371 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 5484c59..24e589c 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -107,7 +107,29 @@ enum {
 
 /* Flag idn for Query Requests*/
 enum flag_idn {
-   QUERY_FLAG_IDN_FDEVICEINIT = 0x01,
+   QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
+   QUERY_FLAG_IDN_BKOPS_EN = 0x04,
+};
+
+/* Attribute idn for Query requests */
+enum attr_idn {
+   QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
+   QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
+   QUERY_ATTR_IDN_EE_STATUS= 0x0E,
+};
+
+/* Exception event mask values */
+enum {
+   MASK_EE_STATUS  = 0x,
+   MASK_EE_URGENT_BKOPS= (1  2),
+};
+
+/* Background operation status */
+enum {
+   BKOPS_STATUS_NO_OP   = 0x0,
+   BKOPS_STATUS_NON_CRITICAL= 0x1,
+   BKOPS_STATUS_PERF_IMPACT = 0x2,
+   BKOPS_STATUS_CRITICAL= 0x3,
 };
 
 /* UTP QUERY Transaction Specific Fields OpCode */
@@ -156,6 +178,7 @@ enum {
MASK_TASK_RESPONSE  = 0xFF00,
MASK_RSP_UPIU_RESULT= 0x,
MASK_QUERY_DATA_SEG_LEN = 0x,
+   MASK_RSP_EXCEPTION_EVENT = 0x1,
 };
 
 /* Task management service response */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f8278be..ac323a8 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -300,6 +300,21 @@ ufshcd_get_rsp_upiu_result(struct utp_upiu_rsp 
*ucd_rsp_ptr)
 }
 
 /**
+ * ufshcd_is_exception_event - Check if the device raised an exception event
+ * @ucd_rsp_ptr: pointer to response UPIU
+ *
+ * The function checks if the device raised an exception event indicated in
+ * the Device Information field of response UPIU.
+ *
+ * Returns true if exception is raised, false otherwise.
+ */
+static inline bool ufshcd_is_exception_event(struct utp_upiu_rsp *ucd_rsp_ptr)
+{
+   return be32_to_cpu(ucd_rsp_ptr-header.dword_2) 
+   MASK_RSP_EXCEPTION_EVENT ? true : false;
+}
+
+/**
  * ufshcd_config_int_aggr - Configure interrupt aggregation values.
  * Currently there is no use case where we want to configure
  * interrupt aggregation dynamically. So to configure interrupt
@@ -1206,6 +1221,86 @@ out_no_mem:
 }
 
 /**
+ * ufshcd_query_attr - Helper function for composing attribute requests
+ * hba: per-adapter instance
+ * opcode: attribute opcode
+ * idn: attribute idn to access
+ * index: index field
+ * selector: selector field
+ * attr_val: the attribute value after the query request completes
+ *
+ * Returns 0 for success, non-zero in case of failure
+*/
+int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
+   enum attr_idn idn, u8 index, u8 selector, u32 *attr_val)
+{
+   struct ufs_query_req *query;
+   struct ufs_query_res *response;
+   int err = -ENOMEM;
+
+   if (!attr_val) {
+   dev_err(hba-dev, %s: attribute value required for write 
request\n,
+   __func__);
+   err = -EINVAL;
+   goto out;
+   }
+
+   query = kzalloc(sizeof(struct ufs_query_req), GFP_KERNEL);
+   if (!query) {
+   dev_err(hba-dev,
+   %s: Failed allocating ufs_query_req instance\n,
+   __func__);
+   goto out;
+   }
+
+   response = kzalloc(sizeof(struct ufs_query_res), GFP_KERNEL);
+   if (!response) {
+   dev_err(hba-dev,
+   %s: Failed allocating ufs_query_res instance\n,
+   __func__);
+  

Re: SCSI vs MN10300: Can get_user() be given an array?

2013-06-28 Thread James Bottomley
On Fri, 2013-06-28 at 17:39 +0100, David Howells wrote:
 The MN10300 arch is throwing up an error in the SCSI driver and I'm not sure
 whether it needs fixing in the arch - in get_user() - or in the SCSI code.
 
 The problem is this line in sg_scsi_ioctl():
 
   if (get_user(opcode, sic-data))
 
 sic points to the following struct:
 
   typedef struct scsi_ioctl_command {
   unsigned int inlen;
   unsigned int outlen;
   unsigned char data[0];
   } Scsi_Ioctl_Command;
 
 However, __get_user_check() on MN10300 does this:
 
   const __typeof__(ptr) __guc_ptr = (ptr);
 
 which fails with:
 
   block/scsi_ioctl.c:450: error: invalid initializer
 
 The question is what is SCSI actually asking get_user() to do?  As far as I
 can tell, gcc thinks that it's being askied to declare some sort of array
 here.

I'm surprised you need to ask this.  by convention, an array of char is
usable as a pointer to char *.  The compiler therefore thinks this is a
legitimate conversion which doesn't need a cast:

unsigned char *d = sic-data;

Therefore, sic-data should be usable as a char * pointer everywhere.

 Should the SCSI driver be changed to:
 
   if (get_user(opcode, (unsigned char *)sic-data))

can we visit reality for a minute?  That proposal would require us to do
an explicit (unsigned char *) conversion everywhere we use an array as a
pointer value ... good grief, no!

 or should the MN10300 arch be changed to morph the array into a pointer,
 perhaps with:
 
   const __typeof__(ptr[0])* __guc_ptr = (ptr);

Neither.  It should do what every other architecture does, which is:

const __typeof__(*(ptr)) *__guc_ptr = (ptr);

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 V2 2/2] scsi: ufs: Add runtime PM helpers for UFS host driver

2013-06-28 Thread Sujit Reddy Thumma
Add runtime PM helpers to suspend/resume the UFS controller
device at runtime.

Signed-off-by: Sujit Reddy Thumma sthu...@codeaurora.org
---
 drivers/scsi/ufs/ufshcd-pci.c|   60 ++
 drivers/scsi/ufs/ufshcd-pltfrm.c |   41 ++
 2 files changed, 95 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
index 64d36eb..f669e9a2 100644
--- a/drivers/scsi/ufs/ufshcd-pci.c
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -35,6 +35,7 @@
 
 #include ufshcd.h
 #include linux/pci.h
+#include linux/pm_runtime.h
 
 #ifdef CONFIG_PM
 /**
@@ -44,7 +45,7 @@
  *
  * Returns -ENOSYS
  */
-static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+static int ufshcd_pci_suspend(struct device *dev)
 {
/*
 * TODO:
@@ -61,7 +62,7 @@ static int ufshcd_pci_suspend(struct pci_dev *pdev, 
pm_message_t state)
  *
  * Returns -ENOSYS
  */
-static int ufshcd_pci_resume(struct pci_dev *pdev)
+static int ufshcd_pci_resume(struct device *dev)
 {
/*
 * TODO:
@@ -71,8 +72,48 @@ static int ufshcd_pci_resume(struct pci_dev *pdev)
 
return -ENOSYS;
 }
+#else
+#define ufshcd_pci_suspend NULL
+#define ufshcd_pci_resume  NULL
 #endif /* CONFIG_PM */
 
+#ifdef CONFIG_PM_RUNTIME
+static int ufshcd_pci_runtime_suspend(struct device *dev)
+{
+   struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+   struct ufs_hba *hba = pci_get_drvdata(pdev);
+
+   if (!hba)
+   return 0;
+
+   return ufshcd_runtime_suspend(hba);
+}
+static int ufshcd_pci_runtime_resume(struct device *dev)
+{
+   struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+   struct ufs_hba *hba = pci_get_drvdata(pdev);
+
+   if (!hba)
+   return 0;
+
+   return ufshcd_runtime_resume(hba);
+}
+static int ufshcd_pci_runtime_idle(struct device *dev)
+{
+   struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+   struct ufs_hba *hba = pci_get_drvdata(pdev);
+
+   if (!hba)
+   return 0;
+
+   return ufshcd_runtime_idle(hba);
+}
+#else /* !CONFIG_PM_RUNTIME */
+#define ufshcd_pci_runtime_suspend NULL
+#define ufshcd_pci_runtime_resume  NULL
+#define ufshcd_pci_runtime_idleNULL
+#endif /* CONFIG_PM_RUNTIME */
+
 /**
  * ufshcd_pci_shutdown - main function to put the controller in reset state
  * @pdev: pointer to PCI device handle
@@ -156,6 +197,14 @@ out_error:
return err;
 }
 
+static const struct dev_pm_ops ufshcd_pci_pm_ops = {
+   .suspend= ufshcd_pci_suspend,
+   .resume = ufshcd_pci_resume,
+   .runtime_suspend = ufshcd_pci_runtime_suspend,
+   .runtime_resume  = ufshcd_pci_runtime_resume,
+   .runtime_idle= ufshcd_pci_runtime_idle,
+};
+
 static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
{ PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ } /* terminate list */
@@ -169,10 +218,9 @@ static struct pci_driver ufshcd_pci_driver = {
.probe = ufshcd_pci_probe,
.remove = ufshcd_pci_remove,
.shutdown = ufshcd_pci_shutdown,
-#ifdef CONFIG_PM
-   .suspend = ufshcd_pci_suspend,
-   .resume = ufshcd_pci_resume,
-#endif
+   .driver = {
+   .pm = ufshcd_pci_pm_ops
+   },
 };
 
 module_pci_driver(ufshcd_pci_driver);
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index c42db40..7541054 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -34,6 +34,7 @@
  */
 
 #include linux/platform_device.h
+#include linux/pm_runtime.h
 
 #include ufshcd.h
 
@@ -87,6 +88,43 @@ static int ufshcd_pltfrm_resume(struct device *dev)
 #define ufshcd_pltfrm_resume   NULL
 #endif
 
+#ifdef CONFIG_PM_RUNTIME
+static int ufshcd_pltfrm_runtime_suspend(struct device *dev)
+{
+   struct platform_device *pdev = to_platform_device(dev);
+   struct ufs_hba *hba =  platform_get_drvdata(pdev);
+
+   if (!hba)
+   return 0;
+
+   return ufshcd_runtime_suspend(hba);
+}
+static int ufshcd_pltfrm_runtime_resume(struct device *dev)
+{
+   struct platform_device *pdev = to_platform_device(dev);
+   struct ufs_hba *hba =  platform_get_drvdata(pdev);
+
+   if (!hba)
+   return 0;
+
+   return ufshcd_runtime_resume(hba);
+}
+static int ufshcd_pltfrm_runtime_idle(struct device *dev)
+{
+   struct platform_device *pdev = to_platform_device(dev);
+   struct ufs_hba *hba =  platform_get_drvdata(pdev);
+
+   if (!hba)
+   return 0;
+
+   return ufshcd_runtime_idle(hba);
+}
+#else /* !CONFIG_PM_RUNTIME */
+#define ufshcd_pltfrm_runtime_suspend  NULL
+#define ufshcd_pltfrm_runtime_resume   NULL
+#define ufshcd_pltfrm_runtime_idle NULL
+#endif /* CONFIG_PM_RUNTIME */
+
 /**
  * ufshcd_pltfrm_probe - probe routine of the driver
  * @pdev: pointer to Platform device 

[no subject]

2013-06-28 Thread David Carroll

auth 45008867 subscribe linux-scsi \
david.carr...@pmcs.com

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


[PATCH V2 1/4] scsi: ufs: Fix broken task management command implementation

2013-06-28 Thread Sujit Reddy Thumma
Currently, sending Task Management (TM) command to the card might
be broken in some scenarios as listed below:

Problem: If there are more than 8 TM commands the implementation
 returns error to the caller.
Fix: Wait for one of the slots to be emptied and send the command.

Problem: Sometimes it is necessary for the caller to know the TM service
 response code to determine the task status.
Fix: Propogate the service response to the caller.

Problem: If the TM command times out no proper error recovery is
 implemented.
Fix: Clear the command in the controller door-bell register, so that
 further commands for the same slot don't fail.

Problem: While preparing the TM command descriptor, the tag used should
 be the free slot of TM command and not the task tag of the
 command which the TM command is trying to manage.
Fix: Use free slot tag instead of task tag of SCSI command.

Problem: Since the TM command involves H/W communication, abruptly ending
 the request on kill interrupt signal might cause h/w malfunction.
Fix: Wait for hardware completion interrupt with TASK_UNINTERRUPTIBLE
 set.

Signed-off-by: Sujit Reddy Thumma sthu...@codeaurora.org
---
 drivers/scsi/ufs/ufshcd.c |  175 ++---
 drivers/scsi/ufs/ufshcd.h |8 ++-
 2 files changed, 124 insertions(+), 59 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index ac323a8..4781b00 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -53,6 +53,9 @@
 /* Query request timeout */
 #define QUERY_REQ_TIMEOUT 30 /* msec */
 
+/* Task management command timeout */
+#define TM_CMD_TIMEOUT 100 /* msecs */
+
 /* Expose the flag value from utp_upiu_query.value */
 #define MASK_QUERY_UPIU_FLAG_LOC 0xFF
 
@@ -190,13 +193,35 @@ ufshcd_get_tmr_ocs(struct utp_task_req_desc 
*task_req_descp)
 /**
  * ufshcd_get_tm_free_slot - get a free slot for task management request
  * @hba: per adapter instance
+ * @free_slot: pointer to variable with available slot value
  *
- * Returns maximum number of task management request slots in case of
- * task management queue full or returns the free slot number
+ * Get a free tag and lock it until ufshcd_put_tm_slot() is called.
+ * Returns 0 if free slot is not available, else return 1 with tag value
+ * in @free_slot.
  */
-static inline int ufshcd_get_tm_free_slot(struct ufs_hba *hba)
+static bool ufshcd_get_tm_free_slot(struct ufs_hba *hba, int *free_slot)
+{
+   int tag;
+   bool ret = false;
+
+   if (!free_slot)
+   goto out;
+
+   do {
+   tag = find_first_zero_bit(hba-tm_slots_in_use, hba-nutmrs);
+   if (tag = hba-nutmrs)
+   goto out;
+   } while (test_and_set_bit_lock(tag, hba-tm_slots_in_use));
+
+   *free_slot = tag;
+   ret = true;
+out:
+   return ret;
+}
+
+static inline void ufshcd_put_tm_slot(struct ufs_hba *hba, int slot)
 {
-   return find_first_zero_bit(hba-outstanding_tasks, hba-nutmrs);
+   clear_bit_unlock(slot, hba-tm_slots_in_use);
 }
 
 /**
@@ -1809,10 +1834,11 @@ static void ufshcd_slave_destroy(struct scsi_device 
*sdev)
  * ufshcd_task_req_compl - handle task management request completion
  * @hba: per adapter instance
  * @index: index of the completed request
+ * @resp: task management service response
  *
- * Returns SUCCESS/FAILED
+ * Returns non-zero value on error, zero on success
  */
-static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index)
+static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp)
 {
struct utp_task_req_desc *task_req_descp;
struct utp_upiu_task_rsp *task_rsp_upiup;
@@ -1833,19 +1859,15 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, 
u32 index)
task_req_descp[index].task_rsp_upiu;
task_result = be32_to_cpu(task_rsp_upiup-header.dword_1);
task_result = ((task_result  MASK_TASK_RESPONSE)  8);
-
-   if (task_result != UPIU_TASK_MANAGEMENT_FUNC_COMPL 
-   task_result != UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED)
-   task_result = FAILED;
-   else
-   task_result = SUCCESS;
+   if (resp)
+   *resp = (u8)task_result;
} else {
-   task_result = FAILED;
-   dev_err(hba-dev,
-   trc: Invalid ocs = %x\n, ocs_value);
+   dev_err(hba-dev, %s: failed, ocs = 0x%x\n,
+   __func__, ocs_value);
}
spin_unlock_irqrestore(hba-host-host_lock, flags);
-   return task_result;
+
+   return ocs_value;
 }
 
 /**
@@ -2325,7 +2347,7 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba)
 
tm_doorbell = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
hba-tm_condition = tm_doorbell ^ 

[PATCH V2 3/4] scsi: ufs: Fix device and host reset methods

2013-06-28 Thread Sujit Reddy Thumma
As of now SCSI initiated error handling is broken because,
the reset APIs don't try to bring back the device initialized and
ready for further transfers.

In case of timeouts, the scsi error handler takes care of handling aborts
and resets. Improve the error handling in such scenario by resetting the
device and host and re-initializing them in proper manner.

Signed-off-by: Sujit Reddy Thumma sthu...@codeaurora.org
---
 drivers/scsi/ufs/ufshcd.c |  446 +++--
 drivers/scsi/ufs/ufshcd.h |2 +
 2 files changed, 393 insertions(+), 55 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 6bfe927..2829a42 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -69,9 +69,15 @@ enum {
 
 /* UFSHCD states */
 enum {
-   UFSHCD_STATE_OPERATIONAL,
UFSHCD_STATE_RESET,
UFSHCD_STATE_ERROR,
+   UFSHCD_STATE_OPERATIONAL,
+};
+
+/* UFSHCD error handling flags */
+enum {
+   UFSHCD_EH_HOST_RESET_PENDING = (1  0),
+   UFSHCD_EH_DEVICE_RESET_PENDING = (1  1),
 };
 
 /* Interrupt configuration options */
@@ -87,6 +93,22 @@ enum {
INT_AGGR_CONFIG,
 };
 
+#define ufshcd_set_device_reset_pending(h) \
+   (h-eh_flags |= UFSHCD_EH_DEVICE_RESET_PENDING)
+#define ufshcd_set_host_reset_pending(h) \
+   (h-eh_flags |= UFSHCD_EH_HOST_RESET_PENDING)
+#define ufshcd_device_reset_pending(h) \
+   (h-eh_flags  UFSHCD_EH_DEVICE_RESET_PENDING)
+#define ufshcd_host_reset_pending(h) \
+   (h-eh_flags  UFSHCD_EH_HOST_RESET_PENDING)
+#define ufshcd_clear_device_reset_pending(h) \
+   (h-eh_flags = ~UFSHCD_EH_DEVICE_RESET_PENDING)
+#define ufshcd_clear_host_reset_pending(h) \
+   (h-eh_flags = ~UFSHCD_EH_HOST_RESET_PENDING)
+
+static void ufshcd_tmc_handler(struct ufs_hba *hba);
+static void ufshcd_async_scan(void *data, async_cookie_t cookie);
+
 /*
  * ufshcd_wait_for_register - wait for register value to change
  * @hba - per-adapter interface
@@ -883,9 +905,22 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, 
struct scsi_cmnd *cmd)
 
tag = cmd-request-tag;
 
-   if (hba-ufshcd_state != UFSHCD_STATE_OPERATIONAL) {
+   switch (hba-ufshcd_state) {
+   case UFSHCD_STATE_OPERATIONAL:
+   break;
+   case UFSHCD_STATE_RESET:
err = SCSI_MLQUEUE_HOST_BUSY;
goto out;
+   case UFSHCD_STATE_ERROR:
+   set_host_byte(cmd, DID_ERROR);
+   cmd-scsi_done(cmd);
+   goto out;
+   default:
+   dev_WARN_ONCE(hba-dev, 1, %s: invalid state %d\n,
+   __func__, hba-ufshcd_state);
+   set_host_byte(cmd, DID_BAD_TARGET);
+   cmd-scsi_done(cmd);
+   goto out;
}
 
/* acquire the tag to make sure device cmds don't use it */
@@ -1604,8 +1639,6 @@ static int ufshcd_make_hba_operational(struct ufs_hba 
*hba)
if (hba-ufshcd_state == UFSHCD_STATE_RESET)
scsi_unblock_requests(hba-host);
 
-   hba-ufshcd_state = UFSHCD_STATE_OPERATIONAL;
-
 out:
return err;
 }
@@ -2302,6 +2335,106 @@ out:
 }
 
 /**
+ * ufshcd_utrl_is_rsr_enabled - check if run-stop register is enabled
+ * @hba: per-adapter instance
+ */
+static bool ufshcd_utrl_is_rsr_enabled(struct ufs_hba *hba)
+{
+   return ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_LIST_RUN_STOP)  0x1;
+}
+
+/**
+ * ufshcd_utmrl_is_rsr_enabled - check if run-stop register is enabled
+ * @hba: per-adapter instance
+ */
+static bool ufshcd_utmrl_is_rsr_enabled(struct ufs_hba *hba)
+{
+   return ufshcd_readl(hba, REG_UTP_TASK_REQ_LIST_RUN_STOP)  0x1;
+}
+
+/**
+ * ufshcd_complete_pending_tasks - complete outstanding tasks
+ * @hba: per adapter instance
+ *
+ * Abort in-progress task management commands and wakeup
+ * waiting threads.
+ *
+ * Returns non-zero error value when failed to clear all the commands.
+ */
+static int ufshcd_complete_pending_tasks(struct ufs_hba *hba)
+{
+   u32 reg;
+   int err = 0;
+   unsigned long flags;
+
+   if (!hba-outstanding_tasks)
+   goto out;
+
+   /* Clear UTMRL only when run-stop is enabled */
+   if (ufshcd_utmrl_is_rsr_enabled(hba))
+   ufshcd_writel(hba, ~hba-outstanding_tasks,
+   REG_UTP_TASK_REQ_LIST_CLEAR);
+
+   /* poll for max. 1 sec to clear door bell register by h/w */
+   reg = ufshcd_wait_for_register(hba,
+   REG_UTP_TASK_REQ_DOOR_BELL,
+   hba-outstanding_tasks, 0, 1000, 1000);
+   if (reg  hba-outstanding_tasks)
+   err = -ETIMEDOUT;
+
+   spin_lock_irqsave(hba-host-host_lock, flags);
+   /* complete commands that were cleared out */
+   ufshcd_tmc_handler(hba);
+   spin_unlock_irqrestore(hba-host-host_lock, flags);
+out:
+   if (err)
+   dev_err(hba-dev, %s: failed, still pending = 0x%.8x\n,
+