[RFC] scsi: generate uevent for SCSI sense code

2017-05-03 Thread Song Liu
This patch adds capability for SCSI layer to generate uevent for SCSI
sense code. The feature is gated by CONFIG_SCSI_SENSE_UEVENT.

We can configure which sense keys generate uevent for each device
through sysfs entry sense_event_filter. For example, the following
enables uevent for MEDIUM_ERROR (0x03) and HARDWARE_ERROR (0x04)
on scsi drive sdc:

echo 0x000c > /sys/block/sdc/device/sense_event_filter

Here is an example output captured by udevadm:

KERNEL[1214.945358] change   /devices/pci:00/XXX
ACTION=change
DEVPATH=/devices/pci:00/:00:01.0/:01:00.0/host6/XXX
DEVTYPE=scsi_device
DRIVER=sd
LBA=0
MODALIAS=scsi:t-0x00
SDEV_UA=SCSI_SENSE
SENSE_CODE=3/11/14
SEQNUM=4536
SIZE=4096
SUBSYSTEM=scsi

Signed-off-by: Song Liu 
---
 drivers/scsi/Kconfig   | 14 +++
 drivers/scsi/scsi_error.c  | 26 
 drivers/scsi/scsi_lib.c| 27 +++--
 drivers/scsi/scsi_sysfs.c  | 60 ++
 include/scsi/scsi_device.h | 26 +++-
 5 files changed, 150 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 3c52867..4f7f211 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -237,6 +237,20 @@ config SCSI_LOGGING
  there should be no noticeable performance impact as long as you have
  logging turned off.
 
+config SCSI_SENSE_UEVENT
+   bool "SCSI sense code logging"
+   depends on SCSI
+   default n
+   ---help---
+ This turns on uevent for SCSI sense code.
+
+ You can configure which sense keys generate uevent for each device
+ through sysfs entry sense_event_filter. For example, the following
+ enables uevent for MEDIUM_ERROR (0x03) and HARDWARE_ERROR (0x04)
+ on scsi drive sdc:
+
+ echo 0x000c > /sys/block/sdc/device/sense_event_filter
+
 config SCSI_SCAN_ASYNC
bool "Asynchronous SCSI scanning"
depends on SCSI
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index d70c67c..eda150e 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -426,6 +426,31 @@ static void scsi_report_sense(struct scsi_device *sdev,
}
 }
 
+/*
+ * generate uevent when receiving sense code from device
+ */
+static void scsi_send_sense_uevent(struct scsi_device *sdev,
+  struct scsi_cmnd *scmd,
+  struct scsi_sense_hdr *sshdr)
+{
+#ifdef CONFIG_SCSI_SENSE_UEVENT
+   struct scsi_event *evt;
+
+   if (!test_bit(sshdr->sense_key & 0xf,
+ >sense_event_filter))
+   return;
+   evt = sdev_evt_alloc(SDEV_EVT_SCSI_SENSE, GFP_ATOMIC);
+   if (!evt)
+   return;
+
+   evt->sense_evt_data.lba = scsi_get_lba(scmd);
+   evt->sense_evt_data.size = blk_rq_bytes(scmd->request);
+   memcpy(>sense_evt_data.sshdr, sshdr,
+  sizeof(struct scsi_sense_hdr));
+   sdev_evt_send(sdev, evt);
+#endif
+}
+
 /**
  * scsi_check_sense - Examine scsi cmd sense
  * @scmd:  Cmd to have sense checked.
@@ -446,6 +471,7 @@ int scsi_check_sense(struct scsi_cmnd *scmd)
return FAILED;  /* no valid sense data */
 
scsi_report_sense(sdev, );
+   scsi_send_sense_uevent(sdev, scmd, );
 
if (scsi_sense_is_deferred())
return NEEDS_RETRY;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 95f963b..1095f27 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -2656,8 +2656,9 @@ EXPORT_SYMBOL(scsi_device_set_state);
  */
 static void scsi_evt_emit(struct scsi_device *sdev, struct scsi_event *evt)
 {
-   int idx = 0;
-   char *envp[3];
+   int idx = 0, i;
+   char *envp[5];  /* SDEV_EVT_SCSI_SENSE needs most entries (4) */
+   int free_envp = -1;
 
switch (evt->evt_type) {
case SDEV_EVT_MEDIA_CHANGE:
@@ -2682,6 +2683,23 @@ static void scsi_evt_emit(struct scsi_device *sdev, 
struct scsi_event *evt)
case SDEV_EVT_ALUA_STATE_CHANGE_REPORTED:
envp[idx++] = "SDEV_UA=ASYMMETRIC_ACCESS_STATE_CHANGED";
break;
+#ifdef CONFIG_SCSI_SENSE_UEVENT
+   case SDEV_EVT_SCSI_SENSE:
+   envp[idx++] = "SDEV_UA=SCSI_SENSE";
+   for (i = idx; i < idx + 3; ++i) {
+   envp[i] = kzalloc(32, GFP_ATOMIC);
+   if (!envp[i])
+   break;
+   free_envp = i;
+   }
+   snprintf(envp[idx++], 32, "LBA=%lu", evt->sense_evt_data.lba);
+   snprintf(envp[idx++], 32, "SIZE=%d", evt->sense_evt_data.size);
+   snprintf(envp[idx++], 32, "SENSE_CODE=%1x/%02x/%02x",
+evt->sense_evt_data.sshdr.sense_key,
+evt->sense_evt_data.sshdr.asc,
+evt->sense_evt_data.sshdr.ascq);
+   

[RFC] generate uevent for SCSI sense code

2017-05-03 Thread Song Liu
This change is to follow up our discussion on event log for media
management during LSF/MM 2017.

Please kindly let me know your thoughts on this.

Thanks,
Song


Song Liu (1):
  scsi: generate uevent for SCSI sense code

 drivers/scsi/Kconfig   | 14 +++
 drivers/scsi/scsi_error.c  | 26 
 drivers/scsi/scsi_lib.c| 27 +++--
 drivers/scsi/scsi_sysfs.c  | 60 ++
 include/scsi/scsi_device.h | 26 +++-
 5 files changed, 150 insertions(+), 3 deletions(-)

--
2.9.3


[PATCH V2 31/36] smartpqi: make ioaccel references consistent

2017-05-03 Thread Don Brace
From: Kevin Barnett 

 - make all references to RAID bypass consistent throughout driver.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h  |   13 
 drivers/scsi/smartpqi/smartpqi_init.c |   56 ++---
 2 files changed, 30 insertions(+), 39 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index 2ed15cf..e9f113a 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -805,12 +805,11 @@ struct pqi_scsi_dev {
u8  bay;
u8  box[8];
u16 phys_connector[8];
-   int offload_configured; /* I/O accel RAID offload configured */
-   int offload_enabled;/* I/O accel RAID offload enabled */
-   int offload_enabled_pending;
-   int offload_to_mirror;  /* Send next I/O accelerator RAID */
-   /* offload request to mirror drive. */
-   struct raid_map *raid_map;  /* I/O accelerator RAID map */
+   boolraid_bypass_configured; /* RAID bypass configured */
+   boolraid_bypass_enabled;/* RAID bypass enabled */
+   int offload_to_mirror;  /* Send next RAID bypass request */
+   /* to mirror drive. */
+   struct raid_map *raid_map;  /* RAID bypass map */
 
struct pqi_sas_port *sas_port;
struct scsi_device *sdev;
@@ -827,7 +826,7 @@ struct pqi_scsi_dev {
 #define SCSI_VPD_SUPPORTED_PAGES   0x0 /* standard page */
 #define SCSI_VPD_DEVICE_ID 0x83/* standard page */
 #define CISS_VPD_LV_DEVICE_GEOMETRY0xc1/* vendor-specific page */
-#define CISS_VPD_LV_OFFLOAD_STATUS 0xc2/* vendor-specific page */
+#define CISS_VPD_LV_BYPASS_STATUS  0xc2/* vendor-specific page */
 #define CISS_VPD_LV_STATUS 0xc3/* vendor-specific page */
 
 #define VPD_PAGE   (1 << 8)
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 4e016df..5f1c607 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -1112,35 +1112,33 @@ static int pqi_get_raid_map(struct pqi_ctrl_info 
*ctrl_info,
return rc;
 }
 
-static void pqi_get_offload_status(struct pqi_ctrl_info *ctrl_info,
+static void pqi_get_raid_bypass_status(struct pqi_ctrl_info *ctrl_info,
struct pqi_scsi_dev *device)
 {
int rc;
u8 *buffer;
-   u8 offload_status;
+   u8 bypass_status;
 
buffer = kmalloc(64, GFP_KERNEL);
if (!buffer)
return;
 
rc = pqi_scsi_inquiry(ctrl_info, device->scsi3addr,
-   VPD_PAGE | CISS_VPD_LV_OFFLOAD_STATUS, buffer, 64);
+   VPD_PAGE | CISS_VPD_LV_BYPASS_STATUS, buffer, 64);
if (rc)
goto out;
 
-#define OFFLOAD_STATUS_BYTE4
-#define OFFLOAD_CONFIGURED_BIT 0x1
-#define OFFLOAD_ENABLED_BIT0x2
+#define RAID_BYPASS_STATUS 4
+#define RAID_BYPASS_CONFIGURED 0x1
+#define RAID_BYPASS_ENABLED0x2
 
-   offload_status = buffer[OFFLOAD_STATUS_BYTE];
-   device->offload_configured =
-   !!(offload_status & OFFLOAD_CONFIGURED_BIT);
-   if (device->offload_configured) {
-   device->offload_enabled_pending =
-   !!(offload_status & OFFLOAD_ENABLED_BIT);
-   if (pqi_get_raid_map(ctrl_info, device))
-   device->offload_enabled_pending = false;
-   }
+   bypass_status = buffer[RAID_BYPASS_STATUS];
+   device->raid_bypass_configured =
+   (bypass_status & RAID_BYPASS_CONFIGURED) != 0;
+   if (device->raid_bypass_configured &&
+   (bypass_status & RAID_BYPASS_ENABLED) &&
+   pqi_get_raid_map(ctrl_info, device) == 0)
+   device->raid_bypass_enabled = true;
 
 out:
kfree(buffer);
@@ -1214,7 +1212,7 @@ static int pqi_get_device_info(struct pqi_ctrl_info 
*ctrl_info,
device->volume_offline = false;
} else {
pqi_get_raid_level(ctrl_info, device);
-   pqi_get_offload_status(ctrl_info, device);
+   pqi_get_raid_bypass_status(ctrl_info, device);
pqi_get_volume_status(ctrl_info, device);
}
}
@@ -1492,9 +1490,8 @@ static void pqi_dev_info(struct pqi_ctrl_info *ctrl_info,
count += snprintf(buffer + count,
PQI_DEV_INFO_BUFFER_LENGTH - count,
"SSDSmartPathCap%c En%c %-12s",
-   device->offload_configured ? '+' : '-',
-   (device->offload_enabled ||
-   

[PATCH V2 36/36] smartpqi: bump driver version

2017-05-03 Thread Don Brace
From: Kevin Barnett 

Reviewed-by: Scott Benesh 
Reviewed-by: Gerry Morong 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |   15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 7bf6222..0b11ae7 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -40,13 +40,14 @@
 #define BUILD_TIMESTAMP
 #endif
 
-#define DRIVER_VERSION "0.9.13-370"
-#define DRIVER_MAJOR   0
-#define DRIVER_MINOR   9
-#define DRIVER_RELEASE 13
-#define DRIVER_REVISION370
-
-#define DRIVER_NAME"Microsemi PQI Driver (v" DRIVER_VERSION ")"
+#define DRIVER_VERSION "1.0.4-100"
+#define DRIVER_MAJOR   1
+#define DRIVER_MINOR   0
+#define DRIVER_RELEASE 4
+#define DRIVER_REVISION100
+
+#define DRIVER_NAME"Microsemi PQI Driver (v" \
+   DRIVER_VERSION BUILD_TIMESTAMP ")"
 #define DRIVER_NAME_SHORT  "smartpqi"
 
 #define PQI_EXTRA_SGL_MEMORY   (12 * sizeof(struct pqi_sg_descriptor))



[PATCH V2 35/36] smartpqi: remove writeq/readq function definitions

2017-05-03 Thread Don Brace
From: Corentin Labbe 

Instead of rewriting write/readq, use existing functions

Reviewed-by: Scott Benesh 
Signed-off-by: Corentin Labbe 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h |   31 ++-
 1 file changed, 2 insertions(+), 29 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index e9f113a..07ec8a88 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -16,6 +16,8 @@
  *
  */
 
+#include 
+
 #if !defined(_SMARTPQI_H)
 #define _SMARTPQI_H
 
@@ -1175,33 +1177,4 @@ void pqi_prep_for_scsi_done(struct scsi_cmnd *scmd);
 
 extern struct sas_function_template pqi_sas_transport_functions;
 
-#if !defined(readq)
-#define readq readq
-static inline u64 readq(const volatile void __iomem *addr)
-{
-   u32 lower32;
-   u32 upper32;
-
-   lower32 = readl(addr);
-   upper32 = readl(addr + 4);
-
-   return ((u64)upper32 << 32) | lower32;
-}
-#endif
-
-#if !defined(writeq)
-#define writeq writeq
-static inline void writeq(u64 value, volatile void __iomem *addr)
-{
-   u32 lower32;
-   u32 upper32;
-
-   lower32 = lower_32_bits(value);
-   upper32 = upper_32_bits(value);
-
-   writel(lower32, addr);
-   writel(upper32, addr + 4);
-}
-#endif
-
 #endif /* _SMARTPQI_H */



[PATCH V2 32/36] smartpqi: add raid level show

2017-05-03 Thread Don Brace
From: Kevin Barnett 

Display the RAID level via sysfs

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |   30 +-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 5f1c607..56c416f 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -144,7 +144,7 @@ static char *pqi_raid_level_to_string(u8 raid_level)
if (raid_level < ARRAY_SIZE(raid_levels))
return raid_levels[raid_level];
 
-   return "";
+   return "RAID UNKNOWN";
 }
 
 #define SA_RAID_0  0
@@ -5754,13 +5754,41 @@ static ssize_t pqi_ssd_smart_path_enabled_show(struct 
device *dev,
return 2;
 }
 
+static ssize_t pqi_raid_level_show(struct device *dev,
+   struct device_attribute *attr, char *buffer)
+{
+   struct pqi_ctrl_info *ctrl_info;
+   struct scsi_device *sdev;
+   struct pqi_scsi_dev *device;
+   unsigned long flags;
+   char *raid_level;
+
+   sdev = to_scsi_device(dev);
+   ctrl_info = shost_to_hba(sdev->host);
+
+   spin_lock_irqsave(_info->scsi_device_list_lock, flags);
+
+   device = sdev->hostdata;
+
+   if (pqi_is_logical_device(device))
+   raid_level = pqi_raid_level_to_string(device->raid_level);
+   else
+   raid_level = "N/A";
+
+   spin_unlock_irqrestore(_info->scsi_device_list_lock, flags);
+
+   return snprintf(buffer, PAGE_SIZE, "%s\n", raid_level);
+}
+
 static DEVICE_ATTR(sas_address, 0444, pqi_sas_address_show, NULL);
 static DEVICE_ATTR(ssd_smart_path_enabled, 0444,
pqi_ssd_smart_path_enabled_show, NULL);
+static DEVICE_ATTR(raid_level, 0444, pqi_raid_level_show, NULL);
 
 static struct device_attribute *pqi_sdev_attrs[] = {
_attr_sas_address,
_attr_ssd_smart_path_enabled,
+   _attr_raid_level,
NULL
 };
 



[PATCH V2 33/36] smartpqi: cleanup list initialization

2017-05-03 Thread Don Brace
From: Kevin Barnett 

Better initialization of linked list heads.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |   11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 56c416f..21fbcf3 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -1591,11 +1591,8 @@ static void pqi_update_device_list(struct pqi_ctrl_info 
*ctrl_info,
struct pqi_scsi_dev *device;
struct pqi_scsi_dev *next;
struct pqi_scsi_dev *matching_device;
-   struct list_head add_list;
-   struct list_head delete_list;
-
-   INIT_LIST_HEAD(_list);
-   INIT_LIST_HEAD(_list);
+   LIST_HEAD(add_list);
+   LIST_HEAD(delete_list);
 
/*
 * The idea here is to do as little work as possible while holding the
@@ -1755,7 +1752,7 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info 
*ctrl_info)
 {
int i;
int rc;
-   struct list_head new_device_list_head;
+   LIST_HEAD(new_device_list_head);
struct report_phys_lun_extended *physdev_list = NULL;
struct report_log_lun_extended *logdev_list = NULL;
struct report_phys_lun_extended_entry *phys_lun_ext_entry;
@@ -1773,8 +1770,6 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info 
*ctrl_info)
static char *out_of_memory_msg =
"failed to allocate memory, device discovery stopped";
 
-   INIT_LIST_HEAD(_device_list_head);
-
rc = pqi_get_device_lists(ctrl_info, _list, _list);
if (rc)
goto out;



[PATCH V2 34/36] smartpqi: add module parameters

2017-05-03 Thread Don Brace
From: Kevin Barnett 

Add module parameters to disable heartbeat support and to disable
shutting down the controller when a controller is taken offline.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |   29 -
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 21fbcf3..7bf6222 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -122,6 +122,18 @@ module_param_named(disable_device_id_wildcards,
 MODULE_PARM_DESC(disable_device_id_wildcards,
"Disable device ID wildcards.");
 
+static int pqi_disable_heartbeat;
+module_param_named(disable_heartbeat,
+   pqi_disable_heartbeat, int, 0644);
+MODULE_PARM_DESC(disable_heartbeat,
+   "Disable heartbeat.");
+
+static int pqi_disable_ctrl_shutdown;
+module_param_named(disable_ctrl_shutdown,
+   pqi_disable_ctrl_shutdown, int, 0644);
+MODULE_PARM_DESC(disable_ctrl_shutdown,
+   "Disable controller shutdown when controller locked up.");
+
 static char *pqi_lockup_action_param;
 module_param_named(lockup_action,
pqi_lockup_action_param, charp, 0644);
@@ -5962,10 +5974,16 @@ static int pqi_process_config_table(struct 
pqi_ctrl_info *ctrl_info)
 
switch (get_unaligned_le16(>section_id)) {
case PQI_CONFIG_TABLE_SECTION_HEARTBEAT:
-   ctrl_info->heartbeat_counter = table_iomem_addr +
-   section_offset +
-   offsetof(struct pqi_config_table_heartbeat,
-   heartbeat_counter);
+   if (pqi_disable_heartbeat)
+   dev_warn(_info->pci_dev->dev,
+   "heartbeat disabled by module parameter\n");
+   else
+   ctrl_info->heartbeat_counter =
+   table_iomem_addr +
+   section_offset +
+   offsetof(
+   struct pqi_config_table_heartbeat,
+   heartbeat_counter);
break;
}
 
@@ -6550,7 +6568,8 @@ static void pqi_take_ctrl_offline(struct pqi_ctrl_info 
*ctrl_info)
ctrl_info->controller_online = false;
ctrl_info->pqi_mode_enabled = false;
pqi_ctrl_block_requests(ctrl_info);
-   sis_shutdown_ctrl(ctrl_info);
+   if (!pqi_disable_ctrl_shutdown)
+   sis_shutdown_ctrl(ctrl_info);
pci_disable_device(ctrl_info->pci_dev);
dev_err(_info->pci_dev->dev, "controller offline\n");
schedule_work(_info->ctrl_offline_work);



[PATCH V2 30/36] smartpqi: enhance device add and remove messages

2017-05-03 Thread Don Brace
From: Kevin Barnett 

Improved formatting of information displayed when devices
are added/removed from the system.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |   90 +
 1 file changed, 69 insertions(+), 21 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index e13dee3..4e016df 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -1448,24 +1448,66 @@ static enum pqi_find_result pqi_scsi_find_entry(struct 
pqi_ctrl_info *ctrl_info,
return DEVICE_NOT_FOUND;
 }
 
+#define PQI_DEV_INFO_BUFFER_LENGTH 128
+
 static void pqi_dev_info(struct pqi_ctrl_info *ctrl_info,
char *action, struct pqi_scsi_dev *device)
 {
-   dev_info(_info->pci_dev->dev,
-   "%s scsi %d:%d:%d:%d: %s %.8s %.16s %-12s SSDSmartPathCap%c 
En%c qd=%d\n",
-   action,
-   ctrl_info->scsi_host->host_no,
-   device->bus,
-   device->target,
-   device->lun,
+   ssize_t count;
+   char buffer[PQI_DEV_INFO_BUFFER_LENGTH];
+
+   count = snprintf(buffer, PQI_DEV_INFO_BUFFER_LENGTH,
+   "%d:%d:", ctrl_info->scsi_host->host_no, device->bus);
+
+   if (device->target_lun_valid)
+   count += snprintf(buffer + count,
+   PQI_DEV_INFO_BUFFER_LENGTH - count,
+   "%d:%d",
+   device->target,
+   device->lun);
+   else
+   count += snprintf(buffer + count,
+   PQI_DEV_INFO_BUFFER_LENGTH - count,
+   "-:-");
+
+   if (pqi_is_logical_device(device))
+   count += snprintf(buffer + count,
+   PQI_DEV_INFO_BUFFER_LENGTH - count,
+   " %08x%08x",
+   *((u32 *)>scsi3addr),
+   *((u32 *)>scsi3addr[4]));
+   else
+   count += snprintf(buffer + count,
+   PQI_DEV_INFO_BUFFER_LENGTH - count,
+   " %016llx", device->sas_address);
+
+   count += snprintf(buffer + count, PQI_DEV_INFO_BUFFER_LENGTH - count,
+   " %s %.8s %.16s ",
scsi_device_type(device->devtype),
device->vendor,
-   device->model,
-   pqi_is_logical_device(device) ?
-   pqi_raid_level_to_string(device->raid_level) : "",
-   device->offload_configured ? '+' : '-',
-   device->offload_enabled_pending ? '+' : '-',
-   device->queue_depth);
+   device->model);
+
+   if (pqi_is_logical_device(device)) {
+   if (device->devtype == TYPE_DISK)
+   count += snprintf(buffer + count,
+   PQI_DEV_INFO_BUFFER_LENGTH - count,
+   "SSDSmartPathCap%c En%c %-12s",
+   device->offload_configured ? '+' : '-',
+   (device->offload_enabled ||
+   device->offload_enabled_pending) ? '+' : '-',
+   pqi_raid_level_to_string(device->raid_level));
+   } else {
+   count += snprintf(buffer + count,
+   PQI_DEV_INFO_BUFFER_LENGTH - count,
+   "AIO%c", device->aio_enabled ? '+' : '-');
+   if (device->devtype == TYPE_DISK ||
+   device->devtype == TYPE_ZBC)
+   count += snprintf(buffer + count,
+   PQI_DEV_INFO_BUFFER_LENGTH - count,
+   " qd=%-6d", device->queue_depth);
+   }
+
+   dev_info(_info->pci_dev->dev, "%s %s\n", action, buffer);
 }
 
 /* Assumes the SCSI device list lock is held. */
@@ -1638,14 +1680,14 @@ static void pqi_update_device_list(struct pqi_ctrl_info 
*ctrl_info,
/* Remove all devices that have gone away. */
list_for_each_entry_safe(device, next, _list,
delete_list_entry) {
-   if (device->sdev)
-   pqi_remove_device(ctrl_info, device);
if (device->volume_offline) {
pqi_dev_info(ctrl_info, "offline", device);
pqi_show_volume_status(ctrl_info, device);
} else {
pqi_dev_info(ctrl_info, "removed", device);
}
+   if (device->sdev)
+   pqi_remove_device(ctrl_info, device);
list_del(>delete_list_entry);
pqi_free_device(device);
}
@@ -1667,6 +1709,7 @@ static void pqi_update_device_list(struct pqi_ctrl_info 
*ctrl_info,
/* 

[PATCH V2 29/36] smartpqi: update timeout on admin commands

2017-05-03 Thread Don Brace
From: Kevin Barnett 

Increase the timeout on admin commands from 3 seconds to 60
seconds and added a check for controller crash in the loop
where the driver polls for admin command completion.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index affbc4f..e13dee3 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -3425,6 +3425,8 @@ static void pqi_submit_admin_request(struct pqi_ctrl_info 
*ctrl_info,
writel(iq_pi, admin_queues->iq_pi);
 }
 
+#define PQI_ADMIN_REQUEST_TIMEOUT_SECS 60
+
 static int pqi_poll_for_admin_response(struct pqi_ctrl_info *ctrl_info,
struct pqi_general_admin_response *response)
 {
@@ -3436,7 +3438,7 @@ static int pqi_poll_for_admin_response(struct 
pqi_ctrl_info *ctrl_info,
admin_queues = _info->admin_queues;
oq_ci = admin_queues->oq_ci_copy;
 
-   timeout = (3 * HZ) + jiffies;
+   timeout = (PQI_ADMIN_REQUEST_TIMEOUT_SECS * HZ) + jiffies;
 
while (1) {
oq_pi = *admin_queues->oq_pi;
@@ -3447,6 +3449,8 @@ static int pqi_poll_for_admin_response(struct 
pqi_ctrl_info *ctrl_info,
"timed out waiting for admin response\n");
return -ETIMEDOUT;
}
+   if (!sis_is_firmware_running(ctrl_info))
+   return -ENXIO;
usleep_range(1000, 2000);
}
 



[PATCH V2 28/36] smartpqi: map more raid errors to SCSI errors

2017-05-03 Thread Don Brace
From: Kevin Barnett 

enhance mapping of RAID path errors to Linux SCSI host
error codes.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |   32 +++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 8f71e17..affbc4f 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -2441,13 +2441,43 @@ static void pqi_process_raid_io_error(struct 
pqi_io_request *io_request)
scsi_status = error_info->status;
host_byte = DID_OK;
 
-   if (error_info->data_out_result == PQI_DATA_IN_OUT_UNDERFLOW) {
+   switch (error_info->data_out_result) {
+   case PQI_DATA_IN_OUT_GOOD:
+   break;
+   case PQI_DATA_IN_OUT_UNDERFLOW:
xfer_count =
get_unaligned_le32(_info->data_out_transferred);
residual_count = scsi_bufflen(scmd) - xfer_count;
scsi_set_resid(scmd, residual_count);
if (xfer_count < scmd->underflow)
host_byte = DID_SOFT_ERROR;
+   break;
+   case PQI_DATA_IN_OUT_UNSOLICITED_ABORT:
+   case PQI_DATA_IN_OUT_ABORTED:
+   host_byte = DID_ABORT;
+   break;
+   case PQI_DATA_IN_OUT_TIMEOUT:
+   host_byte = DID_TIME_OUT;
+   break;
+   case PQI_DATA_IN_OUT_BUFFER_OVERFLOW:
+   case PQI_DATA_IN_OUT_PROTOCOL_ERROR:
+   case PQI_DATA_IN_OUT_BUFFER_ERROR:
+   case PQI_DATA_IN_OUT_BUFFER_OVERFLOW_DESCRIPTOR_AREA:
+   case PQI_DATA_IN_OUT_BUFFER_OVERFLOW_BRIDGE:
+   case PQI_DATA_IN_OUT_ERROR:
+   case PQI_DATA_IN_OUT_HARDWARE_ERROR:
+   case PQI_DATA_IN_OUT_PCIE_FABRIC_ERROR:
+   case PQI_DATA_IN_OUT_PCIE_COMPLETION_TIMEOUT:
+   case PQI_DATA_IN_OUT_PCIE_COMPLETER_ABORT_RECEIVED:
+   case PQI_DATA_IN_OUT_PCIE_UNSUPPORTED_REQUEST_RECEIVED:
+   case PQI_DATA_IN_OUT_PCIE_ECRC_CHECK_FAILED:
+   case PQI_DATA_IN_OUT_PCIE_UNSUPPORTED_REQUEST:
+   case PQI_DATA_IN_OUT_PCIE_ACS_VIOLATION:
+   case PQI_DATA_IN_OUT_PCIE_TLP_PREFIX_BLOCKED:
+   case PQI_DATA_IN_OUT_PCIE_POISONED_MEMORY_READ:
+   default:
+   host_byte = DID_ERROR;
+   break;
}
 
sense_data_length = get_unaligned_le16(_info->sense_data_length);



[PATCH V2 25/36] smartpqi: update device offline

2017-05-03 Thread Don Brace
From: Kevin Barnett 

- Improve handling of offline devices.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |   30 +-
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 57ff80f..f36aace 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -285,6 +285,11 @@ static inline void pqi_ctrl_wait_until_quiesced(struct 
pqi_ctrl_info *ctrl_info)
usleep_range(1000, 2000);
 }
 
+static inline bool pqi_device_offline(struct pqi_scsi_dev *device)
+{
+   return device->device_offline;
+}
+
 static inline void pqi_device_reset_start(struct pqi_scsi_dev *device)
 {
device->in_reset = true;
@@ -2399,15 +2404,17 @@ static inline void pqi_take_device_offline(struct 
scsi_device *sdev, char *path)
struct pqi_ctrl_info *ctrl_info;
struct pqi_scsi_dev *device;
 
-   if (scsi_device_online(sdev)) {
-   scsi_device_set_state(sdev, SDEV_OFFLINE);
-   ctrl_info = shost_to_hba(sdev->host);
-   schedule_delayed_work(_info->rescan_work, 0);
-   device = sdev->hostdata;
-   dev_err(_info->pci_dev->dev, "offlined %s scsi 
%d:%d:%d:%d\n",
-   path, ctrl_info->scsi_host->host_no, device->bus,
-   device->target, device->lun);
-   }
+   device = sdev->hostdata;
+   if (device->device_offline)
+   return;
+
+   device->device_offline = true;
+   scsi_device_set_state(sdev, SDEV_OFFLINE);
+   ctrl_info = shost_to_hba(sdev->host);
+   pqi_schedule_rescan_worker(ctrl_info);
+   dev_err(_info->pci_dev->dev, "offlined %s scsi %d:%d:%d:%d\n",
+   path, ctrl_info->scsi_host->host_no, device->bus,
+   device->target, device->lun);
 }
 
 static void pqi_process_raid_io_error(struct pqi_io_request *io_request)
@@ -4598,6 +4605,7 @@ static inline void pqi_schedule_bypass_retry(struct 
pqi_ctrl_info *ctrl_info)
 static bool pqi_raid_bypass_retry_needed(struct pqi_io_request *io_request)
 {
struct scsi_cmnd *scmd;
+   struct pqi_scsi_dev *device;
struct pqi_ctrl_info *ctrl_info;
 
if (!io_request->raid_bypass)
@@ -4609,6 +4617,10 @@ static bool pqi_raid_bypass_retry_needed(struct 
pqi_io_request *io_request)
if (host_byte(scmd->result) == DID_NO_CONNECT)
return false;
 
+   device = scmd->device->hostdata;
+   if (pqi_device_offline(device))
+   return false;
+
ctrl_info = shost_to_hba(scmd->device->host);
if (pqi_ctrl_offline(ctrl_info))
return false;



[PATCH V2 27/36] smartpqi: cleanup controller branding

2017-05-03 Thread Don Brace
From: Kevin Barnett 

- Improve controller branding support.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |   18 +++---
 1 file changed, 3 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 338ba03..8f71e17 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -58,9 +58,6 @@ MODULE_SUPPORTED_DEVICE("Microsemi Smart Family Controllers");
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
-static char *hpe_branded_controller = "HPE Smart Array Controller";
-static char *microsemi_branded_controller = "Microsemi Smart Family 
Controller";
-
 static void pqi_take_ctrl_offline(struct pqi_ctrl_info *ctrl_info);
 static void pqi_ctrl_offline_worker(struct work_struct *work);
 static void pqi_retry_raid_bypass_requests(struct pqi_ctrl_info *ctrl_info);
@@ -6467,19 +6464,10 @@ static void pqi_print_ctrl_info(struct pci_dev *pci_dev,
 {
char *ctrl_description;
 
-   if (id->driver_data) {
+   if (id->driver_data)
ctrl_description = (char *)id->driver_data;
-   } else {
-   switch (id->subvendor) {
-   case PCI_VENDOR_ID_HP:
-   ctrl_description = hpe_branded_controller;
-   break;
-   case PCI_VENDOR_ID_ADAPTEC2:
-   default:
-   ctrl_description = microsemi_branded_controller;
-   break;
-   }
-   }
+   else
+   ctrl_description = "Microsemi Smart Family Controller";
 
dev_info(_dev->dev, "%s found\n", ctrl_description);
 }



[PATCH V2 26/36] smartpqi: update rescan worker

2017-05-03 Thread Don Brace
From: Kevin Barnett 

improve support for taking controller offline.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h  |2 
 drivers/scsi/smartpqi/smartpqi_init.c |  141 ++---
 2 files changed, 77 insertions(+), 66 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index 94b92ae..2ed15cf 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -994,7 +994,6 @@ struct pqi_ctrl_info {
u8  inbound_spanning_supported : 1;
u8  outbound_spanning_supported : 1;
u8  pqi_mode_enabled : 1;
-   u8  update_time_worker_scheduled : 1;
 
struct list_head scsi_device_list;
spinlock_t  scsi_device_list_lock;
@@ -1016,6 +1015,7 @@ struct pqi_ctrl_info {
u32 previous_heartbeat_count;
__le32 __iomem  *heartbeat_counter;
struct timer_list heartbeat_timer;
+   struct work_struct ctrl_offline_work;
 
struct semaphore sync_request_sem;
atomic_tnum_busy_threads;
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index f36aace..338ba03 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -61,10 +61,8 @@ MODULE_LICENSE("GPL");
 static char *hpe_branded_controller = "HPE Smart Array Controller";
 static char *microsemi_branded_controller = "Microsemi Smart Family 
Controller";
 
-static void pqi_perform_lockup_action(void);
 static void pqi_take_ctrl_offline(struct pqi_ctrl_info *ctrl_info);
-static void pqi_complete_all_queued_raid_bypass_retries(
-   struct pqi_ctrl_info *ctrl_info, int result);
+static void pqi_ctrl_offline_worker(struct work_struct *work);
 static void pqi_retry_raid_bypass_requests(struct pqi_ctrl_info *ctrl_info);
 static int pqi_scan_scsi_devices(struct pqi_ctrl_info *ctrl_info);
 static void pqi_scan_start(struct Scsi_Host *shost);
@@ -219,7 +217,6 @@ static inline void pqi_save_ctrl_mode(struct pqi_ctrl_info 
*ctrl_info,
sis_write_driver_scratch(ctrl_info, mode);
 }
 
-#define PQI_RESCAN_WORK_INTERVAL   (10 * HZ)
 static inline void pqi_ctrl_block_requests(struct pqi_ctrl_info *ctrl_info)
 {
ctrl_info->block_requests = true;
@@ -305,10 +302,26 @@ static inline bool pqi_device_in_reset(struct 
pqi_scsi_dev *device)
return device->in_reset;
 }
 
+static inline void pqi_schedule_rescan_worker_with_delay(
+   struct pqi_ctrl_info *ctrl_info, unsigned long delay)
+{
+   if (pqi_ctrl_offline(ctrl_info))
+   return;
+
+   schedule_delayed_work(_info->rescan_work, delay);
+}
+
 static inline void pqi_schedule_rescan_worker(struct pqi_ctrl_info *ctrl_info)
 {
-   schedule_delayed_work(_info->rescan_work,
-   PQI_RESCAN_WORK_INTERVAL);
+   pqi_schedule_rescan_worker_with_delay(ctrl_info, 0);
+}
+
+#define PQI_RESCAN_WORK_DELAY  (10 * HZ)
+
+static inline void pqi_schedule_rescan_worker_delayed(
+   struct pqi_ctrl_info *ctrl_info)
+{
+   pqi_schedule_rescan_worker_with_delay(ctrl_info, PQI_RESCAN_WORK_DELAY);
 }
 
 static inline void pqi_cancel_rescan_worker(struct pqi_ctrl_info *ctrl_info)
@@ -741,6 +754,9 @@ static void pqi_update_time_worker(struct work_struct *work)
ctrl_info = container_of(to_delayed_work(work), struct pqi_ctrl_info,
update_time_work);
 
+   if (pqi_ctrl_offline(ctrl_info))
+   return;
+
rc = pqi_write_current_time_to_host_wellness(ctrl_info);
if (rc)
dev_warn(_info->pci_dev->dev,
@@ -753,21 +769,13 @@ static void pqi_update_time_worker(struct work_struct 
*work)
 static inline void pqi_schedule_update_time_worker(
struct pqi_ctrl_info *ctrl_info)
 {
-   if (ctrl_info->update_time_worker_scheduled)
-   return;
-
schedule_delayed_work(_info->update_time_work, 0);
-   ctrl_info->update_time_worker_scheduled = true;
 }
 
 static inline void pqi_cancel_update_time_worker(
struct pqi_ctrl_info *ctrl_info)
 {
-   if (!ctrl_info->update_time_worker_scheduled)
-   return;
-
cancel_delayed_work_sync(_info->update_time_work);
-   ctrl_info->update_time_worker_scheduled = false;
 }
 
 static int pqi_report_luns(struct pqi_ctrl_info *ctrl_info, u8 cmd,
@@ -1933,7 +1941,7 @@ static int pqi_scan_scsi_devices(struct pqi_ctrl_info 
*ctrl_info)
 
rc = pqi_update_scsi_devices(ctrl_info);
if (rc)
-   pqi_schedule_rescan_worker(ctrl_info);
+   pqi_schedule_rescan_worker_delayed(ctrl_info);
 
mutex_unlock(_info->scan_mutex);
 
@@ -2756,6 +2764,10 @@ static void pqi_event_worker(struct work_struct *work)
 

[PATCH V2 24/36] smartpqi: correct aio error path

2017-05-03 Thread Don Brace
From: Kevin Barnett 

set the internal flag that causes I/O to be sent down the
RAID path when the AIO path is disabled

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h  |8 +
 drivers/scsi/smartpqi/smartpqi_init.c |  345 +++--
 2 files changed, 285 insertions(+), 68 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index 857d1be..94b92ae 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -785,11 +785,11 @@ struct pqi_scsi_dev {
u8  is_physical_device : 1;
u8  is_external_raid_device : 1;
u8  target_lun_valid : 1;
-   u8  aio_enabled : 1;/* only valid for physical disks */
u8  device_gone : 1;
u8  new_device : 1;
u8  keep_device : 1;
u8  volume_offline : 1;
+   boolaio_enabled;/* only valid for physical disks */
boolin_reset;
booldevice_offline;
u8  vendor[8];  /* bytes 8-15 of inquiry data */
@@ -911,7 +911,9 @@ struct pqi_io_request {
void (*io_complete_callback)(struct pqi_io_request *io_request,
void *context);
void*context;
+   u8  raid_bypass : 1;
int status;
+   struct pqi_queue_group *queue_group;
struct scsi_cmnd *scmd;
void*error_info;
struct pqi_sg_descriptor *sg_chain_buffer;
@@ -1019,6 +1021,10 @@ struct pqi_ctrl_info {
atomic_tnum_busy_threads;
atomic_tnum_blocked_threads;
wait_queue_head_t block_requests_wait;
+
+   struct list_head raid_bypass_retry_list;
+   spinlock_t  raid_bypass_retry_list_lock;
+   struct work_struct raid_bypass_retry_work;
 };
 
 enum pqi_ctrl_mode {
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 15bb8c1..57ff80f 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -63,6 +63,9 @@ static char *microsemi_branded_controller = "Microsemi Smart 
Family Controller";
 
 static void pqi_perform_lockup_action(void);
 static void pqi_take_ctrl_offline(struct pqi_ctrl_info *ctrl_info);
+static void pqi_complete_all_queued_raid_bypass_retries(
+   struct pqi_ctrl_info *ctrl_info, int result);
+static void pqi_retry_raid_bypass_requests(struct pqi_ctrl_info *ctrl_info);
 static int pqi_scan_scsi_devices(struct pqi_ctrl_info *ctrl_info);
 static void pqi_scan_start(struct Scsi_Host *shost);
 static void pqi_start_io(struct pqi_ctrl_info *ctrl_info,
@@ -74,7 +77,7 @@ static int pqi_submit_raid_request_synchronous(struct 
pqi_ctrl_info *ctrl_info,
 static int pqi_aio_submit_io(struct pqi_ctrl_info *ctrl_info,
struct scsi_cmnd *scmd, u32 aio_handle, u8 *cdb,
unsigned int cdb_length, struct pqi_queue_group *queue_group,
-   struct pqi_encryption_info *encryption_info);
+   struct pqi_encryption_info *encryption_info, bool raid_bypass);
 
 /* for flags argument to pqi_submit_raid_request_synchronous() */
 #define PQI_SYNC_FLAGS_INTERRUPTABLE   0x1
@@ -227,6 +230,7 @@ static inline void pqi_ctrl_unblock_requests(struct 
pqi_ctrl_info *ctrl_info)
 {
ctrl_info->block_requests = false;
wake_up_all(_info->block_requests_wait);
+   pqi_retry_raid_bypass_requests(ctrl_info);
scsi_unblock_requests(ctrl_info->scsi_host);
 }
 
@@ -445,6 +449,14 @@ static int pqi_build_raid_path_request(struct 
pqi_ctrl_info *ctrl_info,
buffer, buffer_length, pci_dir);
 }
 
+static inline void pqi_reinit_io_request(struct pqi_io_request *io_request)
+{
+   io_request->scmd = NULL;
+   io_request->status = 0;
+   io_request->error_info = NULL;
+   io_request->raid_bypass = false;
+}
+
 static struct pqi_io_request *pqi_alloc_io_request(
struct pqi_ctrl_info *ctrl_info)
 {
@@ -462,9 +474,7 @@ static struct pqi_io_request *pqi_alloc_io_request(
/* benignly racy */
ctrl_info->next_io_request_slot = (i + 1) % ctrl_info->max_io_slots;
 
-   io_request->scmd = NULL;
-   io_request->status = 0;
-   io_request->error_info = NULL;
+   pqi_reinit_io_request(io_request);
 
return io_request;
 }
@@ -1678,8 +1688,8 @@ static bool pqi_is_supported_device(struct pqi_scsi_dev 
*device)
/*
 * Only support the HBA controller itself as a RAID
 * controller.  If it's a RAID controller other than
-* the HBA itself (an external RAID controller, MSA500
-* or similar), we don't support it.
+* the HBA itself (an external RAID controller, for
+* example), we don't support it.

[PATCH V2 18/36] smartpqi: update copyright

2017-05-03 Thread Don Brace
From: Kevin Barnett 

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h   |2 +-
 drivers/scsi/smartpqi/smartpqi_init.c  |2 +-
 drivers/scsi/smartpqi/smartpqi_sas_transport.c |2 +-
 drivers/scsi/smartpqi/smartpqi_sis.c   |2 +-
 drivers/scsi/smartpqi/smartpqi_sis.h   |2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index 7a95868..d044a58c 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -1,6 +1,6 @@
 /*
  *driver for Microsemi PQI-based storage controllers
- *Copyright (c) 2016 Microsemi Corporation
+ *Copyright (c) 2016-2017 Microsemi Corporation
  *Copyright (c) 2016 PMC-Sierra, Inc.
  *
  *This program is free software; you can redistribute it and/or modify
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 9e782e6..4b0928f 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -1,6 +1,6 @@
 /*
  *driver for Microsemi PQI-based storage controllers
- *Copyright (c) 2016 Microsemi Corporation
+ *Copyright (c) 2016-2017 Microsemi Corporation
  *Copyright (c) 2016 PMC-Sierra, Inc.
  *
  *This program is free software; you can redistribute it and/or modify
diff --git a/drivers/scsi/smartpqi/smartpqi_sas_transport.c 
b/drivers/scsi/smartpqi/smartpqi_sas_transport.c
index 52ca4f9..0d89d37 100644
--- a/drivers/scsi/smartpqi/smartpqi_sas_transport.c
+++ b/drivers/scsi/smartpqi/smartpqi_sas_transport.c
@@ -1,6 +1,6 @@
 /*
  *driver for Microsemi PQI-based storage controllers
- *Copyright (c) 2016 Microsemi Corporation
+ *Copyright (c) 2016-2017 Microsemi Corporation
  *Copyright (c) 2016 PMC-Sierra, Inc.
  *
  *This program is free software; you can redistribute it and/or modify
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c 
b/drivers/scsi/smartpqi/smartpqi_sis.c
index 07c53e9..e55dfcf 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.c
+++ b/drivers/scsi/smartpqi/smartpqi_sis.c
@@ -1,6 +1,6 @@
 /*
  *driver for Microsemi PQI-based storage controllers
- *Copyright (c) 2016 Microsemi Corporation
+ *Copyright (c) 2016-2017 Microsemi Corporation
  *Copyright (c) 2016 PMC-Sierra, Inc.
  *
  *This program is free software; you can redistribute it and/or modify
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.h 
b/drivers/scsi/smartpqi/smartpqi_sis.h
index 08ee0ab..983184b 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.h
+++ b/drivers/scsi/smartpqi/smartpqi_sis.h
@@ -1,6 +1,6 @@
 /*
  *driver for Microsemi PQI-based storage controllers
- *Copyright (c) 2016 Microsemi Corporation
+ *Copyright (c) 2016-2017 Microsemi Corporation
  *Copyright (c) 2016 PMC-Sierra, Inc.
  *
  *This program is free software; you can redistribute it and/or modify



[PATCH V2 16/36] smartpqi: add new PCI device IDs

2017-05-03 Thread Don Brace
From: Kevin Barnett 

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |  134 +++--
 1 file changed, 109 insertions(+), 25 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 91daedc..6b20a91 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -6390,107 +6390,191 @@ static int pqi_resume(struct pci_dev *pci_dev)
 static const struct pci_device_id pqi_pci_id_table[] = {
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+  0x152d, 0x8a22)
+   },
+   {
+   PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+  0x152d, 0x8a23)
+   },
+   {
+   PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+  0x152d, 0x8a24)
+   },
+   {
+   PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+  0x152d, 0x8a36)
+   },
+   {
+   PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+  0x152d, 0x8a37)
+   },
+   {
+   PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
   PCI_VENDOR_ID_ADAPTEC2, 0x0110)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_HP, 0x0600)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0605)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_HP, 0x0601)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0800)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_HP, 0x0602)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0801)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_HP, 0x0603)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0802)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_HP, 0x0650)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0803)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_HP, 0x0651)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0804)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_HP, 0x0652)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0805)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_HP, 0x0653)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0806)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_HP, 0x0654)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0900)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_HP, 0x0655)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0901)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_HP, 0x0700)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0902)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_HP, 0x0701)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0903)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_ADAPTEC2, 0x0800)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0904)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_ADAPTEC2, 0x0801)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0905)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_ADAPTEC2, 0x0802)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0906)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_ADAPTEC2, 0x0803)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0907)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
-  PCI_VENDOR_ID_ADAPTEC2, 0x0804)
+  PCI_VENDOR_ID_ADAPTEC2, 0x0908)
},
{
 

[PATCH V2 23/36] smartpqi: add lockup action

2017-05-03 Thread Don Brace
From: Kevin Barnett 

add support for actions to take when controller goes offline.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |  121 +
 1 file changed, 121 insertions(+)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 23ebe22..15bb8c1 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -60,6 +61,7 @@ MODULE_LICENSE("GPL");
 static char *hpe_branded_controller = "HPE Smart Array Controller";
 static char *microsemi_branded_controller = "Microsemi Smart Family 
Controller";
 
+static void pqi_perform_lockup_action(void);
 static void pqi_take_ctrl_offline(struct pqi_ctrl_info *ctrl_info);
 static int pqi_scan_scsi_devices(struct pqi_ctrl_info *ctrl_info);
 static void pqi_scan_start(struct Scsi_Host *shost);
@@ -81,6 +83,32 @@ static struct scsi_transport_template 
*pqi_sas_transport_template;
 
 static atomic_t pqi_controller_count = ATOMIC_INIT(0);
 
+enum pqi_lockup_action {
+   NONE,
+   REBOOT,
+   PANIC
+};
+
+static enum pqi_lockup_action pqi_lockup_action = NONE;
+
+static struct {
+   enum pqi_lockup_action  action;
+   char*name;
+} pqi_lockup_actions[] = {
+   {
+   .action = NONE,
+   .name = "none",
+   },
+   {
+   .action = REBOOT,
+   .name = "reboot",
+   },
+   {
+   .action = PANIC,
+   .name = "panic",
+   },
+};
+
 static unsigned int pqi_supported_event_types[] = {
PQI_EVENT_TYPE_HOTPLUG,
PQI_EVENT_TYPE_HARDWARE,
@@ -96,6 +124,13 @@ module_param_named(disable_device_id_wildcards,
 MODULE_PARM_DESC(disable_device_id_wildcards,
"Disable device ID wildcards.");
 
+static char *pqi_lockup_action_param;
+module_param_named(lockup_action,
+   pqi_lockup_action_param, charp, 0644);
+MODULE_PARM_DESC(lockup_action, "Action to take when controller locked up.\n"
+   "\t\tSupported: none, reboot, panic\n"
+   "\t\tDefault: none");
+
 static char *raid_levels[] = {
"RAID-0",
"RAID-4",
@@ -2729,6 +2764,8 @@ static void pqi_take_ctrl_offline(struct pqi_ctrl_info 
*ctrl_info)
ctrl_info->controller_online = false;
dev_err(_info->pci_dev->dev, "controller offline\n");
sis_shutdown_ctrl(ctrl_info);
+   pci_disable_device(ctrl_info->pci_dev);
+   pqi_perform_lockup_action();
 
for (i = 0; i < ctrl_info->num_queue_groups; i++) {
queue_group = _info->queue_groups[i];
@@ -5381,12 +5418,55 @@ static ssize_t pqi_host_rescan_store(struct device *dev,
return count;
 }
 
+static ssize_t pqi_lockup_action_show(struct device *dev,
+   struct device_attribute *attr, char *buffer)
+{
+   int count = 0;
+   unsigned int i;
+
+   for (i = 0; i < ARRAY_SIZE(pqi_lockup_actions); i++) {
+   if (pqi_lockup_actions[i].action == pqi_lockup_action)
+   count += snprintf(buffer + count, PAGE_SIZE - count,
+   "[%s] ", pqi_lockup_actions[i].name);
+   else
+   count += snprintf(buffer + count, PAGE_SIZE - count,
+   "%s ", pqi_lockup_actions[i].name);
+   }
+
+   count += snprintf(buffer + count, PAGE_SIZE - count, "\n");
+
+   return count;
+}
+
+static ssize_t pqi_lockup_action_store(struct device *dev,
+   struct device_attribute *attr, const char *buffer, size_t count)
+{
+   unsigned int i;
+   char *action_name;
+   char action_name_buffer[32];
+
+   strlcpy(action_name_buffer, buffer, sizeof(action_name_buffer));
+   action_name = strstrip(action_name_buffer);
+
+   for (i = 0; i < ARRAY_SIZE(pqi_lockup_actions); i++) {
+   if (strcmp(action_name, pqi_lockup_actions[i].name) == 0) {
+   pqi_lockup_action = pqi_lockup_actions[i].action;
+   return count;
+   }
+   }
+
+   return -EINVAL;
+}
+
 static DEVICE_ATTR(version, 0444, pqi_version_show, NULL);
 static DEVICE_ATTR(rescan, 0200, NULL, pqi_host_rescan_store);
+static DEVICE_ATTR(lockup_action, 0644,
+   pqi_lockup_action_show, pqi_lockup_action_store);
 
 static struct device_attribute *pqi_shost_attrs[] = {
_attr_version,
_attr_rescan,
+   _attr_lockup_action,
NULL
 };
 
@@ -6133,6 +6213,21 @@ static void pqi_remove_ctrl(struct pqi_ctrl_info 
*ctrl_info)
pqi_free_ctrl_resources(ctrl_info);
 }
 
+static void pqi_perform_lockup_action(void)
+{
+   switch (pqi_lockup_action) {
+   case PANIC:
+   panic("FATAL: 

[PATCH V2 20/36] smartpqi: change return value for LUN reset operations

2017-05-03 Thread Don Brace
From: Kevin Barnett 

change return value for controller offline to be consistent
with the rest of the driver.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 11545f3..fa61021 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -5025,7 +5025,7 @@ static int pqi_wait_for_lun_reset_completion(struct 
pqi_ctrl_info *ctrl_info,
 
pqi_check_ctrl_health(ctrl_info);
if (pqi_ctrl_offline(ctrl_info)) {
-   rc = -ETIMEDOUT;
+   rc = -ENXIO;
break;
}
}



[PATCH V2 21/36] smartpqi: enhance kdump

2017-05-03 Thread Don Brace
From: Kevin Barnett 

constrain resource usage during kdump to avoid kdump failures

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h  |6 +++-
 drivers/scsi/smartpqi/smartpqi_init.c |   45 +++--
 2 files changed, 36 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index be04bcb..400d1fb 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -686,8 +686,10 @@ struct pqi_config_table_heartbeat {
__le32  heartbeat_counter;
 };
 
-#define PQI_MAX_OUTSTANDING_REQUESTS   ((u32)~0)
-#define PQI_MAX_TRANSFER_SIZE  (4 * 1024U * 1024U)
+#define PQI_MAX_OUTSTANDING_REQUESTS   ((u32)~0)
+#define PQI_MAX_OUTSTANDING_REQUESTS_KDUMP 32
+#define PQI_MAX_TRANSFER_SIZE  (4 * 1024U * 1024U)
+#define PQI_MAX_TRANSFER_SIZE_KDUMP(512 * 1024U)
 
 #define RAID_MAP_MAX_ENTRIES   1024
 
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index fa61021..cdc3407 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -4353,8 +4353,12 @@ static void pqi_calculate_io_resources(struct 
pqi_ctrl_info *ctrl_info)
ctrl_info->error_buffer_length =
ctrl_info->max_io_slots * PQI_ERROR_BUFFER_ELEMENT_LENGTH;
 
-   max_transfer_size =
-   min(ctrl_info->max_transfer_size, PQI_MAX_TRANSFER_SIZE);
+   if (reset_devices)
+   max_transfer_size = min(ctrl_info->max_transfer_size,
+   PQI_MAX_TRANSFER_SIZE_KDUMP);
+   else
+   max_transfer_size = min(ctrl_info->max_transfer_size,
+   PQI_MAX_TRANSFER_SIZE);
 
max_sg_entries = max_transfer_size / PAGE_SIZE;
 
@@ -4374,19 +4378,24 @@ static void pqi_calculate_io_resources(struct 
pqi_ctrl_info *ctrl_info)
 
 static void pqi_calculate_queue_resources(struct pqi_ctrl_info *ctrl_info)
 {
-   int num_cpus;
-   int max_queue_groups;
int num_queue_groups;
u16 num_elements_per_iq;
u16 num_elements_per_oq;
 
-   max_queue_groups = min(ctrl_info->max_inbound_queues / 2,
-   ctrl_info->max_outbound_queues - 1);
-   max_queue_groups = min(max_queue_groups, PQI_MAX_QUEUE_GROUPS);
+   if (reset_devices) {
+   num_queue_groups = 1;
+   } else {
+   int num_cpus;
+   int max_queue_groups;
+
+   max_queue_groups = min(ctrl_info->max_inbound_queues / 2,
+   ctrl_info->max_outbound_queues - 1);
+   max_queue_groups = min(max_queue_groups, PQI_MAX_QUEUE_GROUPS);
 
-   num_cpus = num_online_cpus();
-   num_queue_groups = min(num_cpus, ctrl_info->max_msix_vectors);
-   num_queue_groups = min(num_queue_groups, max_queue_groups);
+   num_cpus = num_online_cpus();
+   num_queue_groups = min(num_cpus, ctrl_info->max_msix_vectors);
+   num_queue_groups = min(num_queue_groups, max_queue_groups);
+   }
 
ctrl_info->num_queue_groups = num_queue_groups;
ctrl_info->max_hw_queue_index = num_queue_groups - 1;
@@ -5827,9 +5836,17 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
return rc;
}
 
-   if (ctrl_info->max_outstanding_requests > PQI_MAX_OUTSTANDING_REQUESTS)
-   ctrl_info->max_outstanding_requests =
-   PQI_MAX_OUTSTANDING_REQUESTS;
+   if (reset_devices) {
+   if (ctrl_info->max_outstanding_requests >
+   PQI_MAX_OUTSTANDING_REQUESTS_KDUMP)
+   ctrl_info->max_outstanding_requests =
+   PQI_MAX_OUTSTANDING_REQUESTS_KDUMP;
+   } else {
+   if (ctrl_info->max_outstanding_requests >
+   PQI_MAX_OUTSTANDING_REQUESTS)
+   ctrl_info->max_outstanding_requests =
+   PQI_MAX_OUTSTANDING_REQUESTS;
+   }
 
pqi_calculate_io_resources(ctrl_info);
 
@@ -7110,4 +7127,6 @@ static void __attribute__((unused)) 
verify_structures(void)
PQI_QUEUE_ELEMENT_LENGTH_ALIGNMENT != 0);
 
BUILD_BUG_ON(PQI_RESERVED_IO_SLOTS >= PQI_MAX_OUTSTANDING_REQUESTS);
+   BUILD_BUG_ON(PQI_RESERVED_IO_SLOTS >=
+   PQI_MAX_OUTSTANDING_REQUESTS_KDUMP);
 }



[PATCH V2 19/36] smartpqi: add ptraid support

2017-05-03 Thread Don Brace
From: Kevin Barnett 

add support for PTRAID devices

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h  |8 --
 drivers/scsi/smartpqi/smartpqi_init.c |   43 -
 2 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index d044a58c..be04bcb 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -694,7 +694,8 @@ struct pqi_config_table_heartbeat {
 #define PQI_PHYSICAL_DEVICE_BUS0
 #define PQI_RAID_VOLUME_BUS1
 #define PQI_HBA_BUS2
-#define PQI_MAX_BUSPQI_HBA_BUS
+#define PQI_EXTERNAL_RAID_VOLUME_BUS   3
+#define PQI_MAX_BUSPQI_EXTERNAL_RAID_VOLUME_BUS
 
 struct report_lun_header {
__be32  list_length;
@@ -781,6 +782,7 @@ struct pqi_scsi_dev {
__be64  wwid;
u8  volume_id[16];
u8  is_physical_device : 1;
+   u8  is_external_raid_device : 1;
u8  target_lun_valid : 1;
u8  expose_device : 1;
u8  no_uld_attach : 1;
@@ -1056,10 +1058,10 @@ enum pqi_ctrl_mode {
 #define SA_CACHE_FLUSH 0x1
 
 #define MASKED_DEVICE(lunid)   ((lunid)[3] & 0xc0)
-#define CISS_GET_BUS(lunid)((lunid)[7] & 0x3f)
+#define CISS_GET_LEVEL_2_BUS(lunid)((lunid)[7] & 0x3f)
 #define CISS_GET_LEVEL_2_TARGET(lunid) ((lunid)[6])
 #define CISS_GET_DRIVE_NUMBER(lunid)   \
-   (((CISS_GET_BUS((lunid)) - 1) << 8) +   \
+   (((CISS_GET_LEVEL_2_BUS((lunid)) - 1) << 8) + \
CISS_GET_LEVEL_2_TARGET((lunid)))
 
 #define NO_TIMEOUT ((unsigned long) -1)
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 4b0928f..11545f3 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -147,6 +147,11 @@ static inline bool pqi_is_logical_device(struct 
pqi_scsi_dev *device)
return !device->is_physical_device;
 }
 
+static inline bool pqi_is_external_raid_addr(u8 *scsi3addr)
+{
+   return scsi3addr[2] != 0;
+}
+
 static inline bool pqi_ctrl_offline(struct pqi_ctrl_info *ctrl_info)
 {
return !ctrl_info->controller_online;
@@ -885,6 +890,9 @@ static void pqi_assign_bus_target_lun(struct pqi_scsi_dev 
*device)
 {
u8 *scsi3addr;
u32 lunid;
+   int bus;
+   int target;
+   int lun;
 
scsi3addr = device->scsi3addr;
lunid = get_unaligned_le32(scsi3addr);
@@ -897,8 +905,16 @@ static void pqi_assign_bus_target_lun(struct pqi_scsi_dev 
*device)
}
 
if (pqi_is_logical_device(device)) {
-   pqi_set_bus_target_lun(device, PQI_RAID_VOLUME_BUS, 0,
-   lunid & 0x3fff);
+   if (device->is_external_raid_device) {
+   bus = PQI_EXTERNAL_RAID_VOLUME_BUS;
+   target = (lunid >> 16) & 0x3fff;
+   lun = lunid & 0xff;
+   } else {
+   bus = PQI_RAID_VOLUME_BUS;
+   target = 0;
+   lun = lunid & 0x3fff;
+   }
+   pqi_set_bus_target_lun(device, bus, target, lun);
device->target_lun_valid = true;
return;
}
@@ -1137,9 +1153,15 @@ static int pqi_get_device_info(struct pqi_ctrl_info 
*ctrl_info,
memcpy(device->model, [16], sizeof(device->model));
 
if (pqi_is_logical_device(device) && device->devtype == TYPE_DISK) {
-   pqi_get_raid_level(ctrl_info, device);
-   pqi_get_offload_status(ctrl_info, device);
-   pqi_get_volume_status(ctrl_info, device);
+   if (device->is_external_raid_device) {
+   device->raid_level = SA_RAID_UNKNOWN;
+   device->volume_status = CISS_LV_OK;
+   device->volume_offline = false;
+   } else {
+   pqi_get_raid_level(ctrl_info, device);
+   pqi_get_offload_status(ctrl_info, device);
+   pqi_get_volume_status(ctrl_info, device);
+   }
}
 
 out:
@@ -1355,6 +1377,8 @@ static void pqi_update_all_logical_drive_queue_depths(
continue;
if (!pqi_is_logical_device(device))
continue;
+   if (device->is_external_raid_device)
+   continue;
pqi_update_logical_drive_queue_depth(ctrl_info, device);
}
 }
@@ -1463,7 +1487,8 @@ static void pqi_dev_info(struct pqi_ctrl_info *ctrl_info,
scsi_device_type(device->devtype),

[PATCH V2 17/36] smartpqi: cleanup messages

2017-05-03 Thread Don Brace
From: Kevin Barnett 

- improve some error messages.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |   41 ++---
 drivers/scsi/smartpqi/smartpqi_sis.c  |3 ++
 2 files changed, 20 insertions(+), 24 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 6b20a91..9e782e6 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -992,7 +992,10 @@ static int pqi_validate_raid_map(struct pqi_ctrl_info 
*ctrl_info,
return 0;
 
 bad_raid_map:
-   dev_warn(_info->pci_dev->dev, "%s\n", err_msg);
+   dev_warn(_info->pci_dev->dev,
+   "scsi %d:%d:%d:%d %s\n",
+   ctrl_info->scsi_host->host_no,
+   device->bus, device->target, device->lun, err_msg);
 
return -EINVAL;
 }
@@ -1250,8 +1253,7 @@ static void pqi_show_volume_status(struct pqi_ctrl_info 
*ctrl_info,
status = "Volume undergoing encryption re-keying process";
break;
case CISS_LV_ENCRYPTED_IN_NON_ENCRYPTED_CONTROLLER:
-   status =
-   "Encrypted volume inaccessible - disabled on ctrl";
+   status = "Volume encrypted but encryption is disabled";
break;
case CISS_LV_PENDING_ENCRYPTION:
status = "Volume pending migration to encrypted state";
@@ -2429,7 +2431,7 @@ static inline void pqi_aio_path_disabled(struct 
pqi_io_request *io_request)
device->offload_enabled = false;
 }
 
-static inline void pqi_take_device_offline(struct scsi_device *sdev)
+static inline void pqi_take_device_offline(struct scsi_device *sdev, char 
*path)
 {
struct pqi_ctrl_info *ctrl_info;
struct pqi_scsi_dev *device;
@@ -2439,8 +2441,8 @@ static inline void pqi_take_device_offline(struct 
scsi_device *sdev)
ctrl_info = shost_to_hba(sdev->host);
schedule_delayed_work(_info->rescan_work, 0);
device = sdev->hostdata;
-   dev_err(_info->pci_dev->dev, "offlined scsi %d:%d:%d:%d\n",
-   ctrl_info->scsi_host->host_no, device->bus,
+   dev_err(_info->pci_dev->dev, "offlined %s scsi 
%d:%d:%d:%d\n",
+   path, ctrl_info->scsi_host->host_no, device->bus,
device->target, device->lun);
}
 }
@@ -2487,7 +2489,7 @@ static void pqi_process_raid_io_error(struct 
pqi_io_request *io_request)
sshdr.sense_key == HARDWARE_ERROR &&
sshdr.asc == 0x3e &&
sshdr.ascq == 0x1) {
-   pqi_take_device_offline(scmd->device);
+   pqi_take_device_offline(scmd->device, "RAID");
host_byte = DID_NO_CONNECT;
}
 
@@ -2547,7 +2549,7 @@ static void pqi_process_aio_io_error(struct 
pqi_io_request *io_request)
case PQI_AIO_STATUS_NO_PATH_TO_DEVICE:
case PQI_AIO_STATUS_INVALID_DEVICE:
device_offline = true;
-   pqi_take_device_offline(scmd->device);
+   pqi_take_device_offline(scmd->device, "AIO");
host_byte = DID_NO_CONNECT;
scsi_status = SAM_STAT_CHECK_CONDITION;
break;
@@ -3202,11 +3204,8 @@ static int pqi_alloc_operational_queues(struct 
pqi_ctrl_info *ctrl_info)
alloc_length,
_info->queue_memory_base_dma_handle, GFP_KERNEL);
 
-   if (!ctrl_info->queue_memory_base) {
-   dev_err(_info->pci_dev->dev,
-   "unable to allocate memory for PQI admin queues\n");
+   if (!ctrl_info->queue_memory_base)
return -ENOMEM;
-   }
 
ctrl_info->queue_memory_length = alloc_length;
 
@@ -3575,7 +3574,6 @@ static int pqi_wait_for_completion_io(struct 
pqi_ctrl_info *ctrl_info,
struct completion *wait)
 {
int rc;
-   unsigned int wait_secs = 0;
 
while (1) {
if (wait_for_completion_io_timeout(wait,
@@ -3589,12 +3587,6 @@ static int pqi_wait_for_completion_io(struct 
pqi_ctrl_info *ctrl_info,
rc = -ENXIO;
break;
}
-
-   wait_secs += PQI_WAIT_FOR_COMPLETION_IO_TIMEOUT_SECS;
-
-   dev_err(_info->pci_dev->dev,
-   "waiting %u seconds for completion\n",
-   wait_secs);
}
 
return rc;
@@ -5699,7 +5691,7 @@ static int pqi_process_config_table(struct pqi_ctrl_info 
*ctrl_info)
config_table = kmalloc(table_length, GFP_KERNEL);
if (!config_table) {

[PATCH V2 22/36] smartpqi: remove qdepth calculations for logical volumes

2017-05-03 Thread Don Brace
From: Kevin Barnett 

make the queue depth for LVs the same as the maximum
I/Os supported by the controller

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h  |6 -
 drivers/scsi/smartpqi/smartpqi_init.c |  140 ++---
 2 files changed, 8 insertions(+), 138 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index 400d1fb..857d1be 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -726,7 +726,6 @@ struct report_phys_lun_extended_entry {
 };
 
 /* for device_flags field of struct report_phys_lun_extended_entry */
-#define REPORT_PHYS_LUN_DEV_FLAG_NON_DISK  0x1
 #define REPORT_PHYS_LUN_DEV_FLAG_AIO_ENABLED   0x8
 
 struct report_phys_lun_extended {
@@ -786,8 +785,6 @@ struct pqi_scsi_dev {
u8  is_physical_device : 1;
u8  is_external_raid_device : 1;
u8  target_lun_valid : 1;
-   u8  expose_device : 1;
-   u8  no_uld_attach : 1;
u8  aio_enabled : 1;/* only valid for physical disks */
u8  device_gone : 1;
u8  new_device : 1;
@@ -1034,9 +1031,6 @@ enum pqi_ctrl_mode {
  */
 #define PQI_PHYSICAL_DISK_DEFAULT_MAX_QUEUE_DEPTH  27
 
-/* 0 = no limit */
-#define PQI_LOGICAL_DRIVE_DEFAULT_MAX_QUEUE_DEPTH  0
-
 /* CISS commands */
 #define CISS_READ  0xc0
 #define CISS_REPORT_LOG0xc2/* Report Logical LUNs */
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index cdc3407..23ebe22 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -1302,87 +1302,6 @@ static void pqi_show_volume_status(struct pqi_ctrl_info 
*ctrl_info,
device->bus, device->target, device->lun, status);
 }
 
-static struct pqi_scsi_dev *pqi_find_disk_by_aio_handle(
-   struct pqi_ctrl_info *ctrl_info, u32 aio_handle)
-{
-   struct pqi_scsi_dev *device;
-
-   list_for_each_entry(device, _info->scsi_device_list,
-   scsi_device_list_entry) {
-   if (device->devtype != TYPE_DISK && device->devtype != TYPE_ZBC)
-   continue;
-   if (pqi_is_logical_device(device))
-   continue;
-   if (device->aio_handle == aio_handle)
-   return device;
-   }
-
-   return NULL;
-}
-
-static void pqi_update_logical_drive_queue_depth(
-   struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev *logical_drive)
-{
-   unsigned int i;
-   struct raid_map *raid_map;
-   struct raid_map_disk_data *disk_data;
-   struct pqi_scsi_dev *phys_disk;
-   unsigned int num_phys_disks;
-   unsigned int num_raid_map_entries;
-   unsigned int queue_depth;
-
-   logical_drive->queue_depth = PQI_LOGICAL_DRIVE_DEFAULT_MAX_QUEUE_DEPTH;
-
-   raid_map = logical_drive->raid_map;
-   if (!raid_map)
-   return;
-
-   disk_data = raid_map->disk_data;
-   num_phys_disks = get_unaligned_le16(_map->layout_map_count) *
-   (get_unaligned_le16(_map->data_disks_per_row) +
-   get_unaligned_le16(_map->metadata_disks_per_row));
-   num_raid_map_entries = num_phys_disks *
-   get_unaligned_le16(_map->row_cnt);
-
-   queue_depth = 0;
-   for (i = 0; i < num_raid_map_entries; i++) {
-   phys_disk = pqi_find_disk_by_aio_handle(ctrl_info,
-   disk_data[i].aio_handle);
-
-   if (!phys_disk) {
-   dev_warn(_info->pci_dev->dev,
-   "failed to find physical disk for logical drive 
%016llx\n",
-   get_unaligned_be64(logical_drive->scsi3addr));
-   logical_drive->offload_enabled = false;
-   logical_drive->offload_enabled_pending = false;
-   kfree(raid_map);
-   logical_drive->raid_map = NULL;
-   return;
-   }
-
-   queue_depth += phys_disk->queue_depth;
-   }
-
-   logical_drive->queue_depth = queue_depth;
-}
-
-static void pqi_update_all_logical_drive_queue_depths(
-   struct pqi_ctrl_info *ctrl_info)
-{
-   struct pqi_scsi_dev *device;
-
-   list_for_each_entry(device, _info->scsi_device_list,
-   scsi_device_list_entry) {
-   if (device->devtype != TYPE_DISK && device->devtype != TYPE_ZBC)
-   continue;
-   if (!pqi_is_logical_device(device))
-   continue;
-   if (device->is_external_raid_device)
-   continue;
-   pqi_update_logical_drive_queue_depth(ctrl_info, device);
-   }

[PATCH V2 15/36] smartpqi: minor driver cleanup

2017-05-03 Thread Don Brace
From: Kevin Barnett 

 - remove debug code that is no longer necessary.
   - Some WARN_ON checks were removed because the driver continues
 to function when the conditions are met.
 - remove a MACRO that is no longer used.
 - remove unnecessary multi-line statements.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h  |2 +-
 drivers/scsi/smartpqi/smartpqi_init.c |   38 -
 2 files changed, 15 insertions(+), 25 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index e74d3ed..7a95868 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -1053,7 +1053,7 @@ enum pqi_ctrl_mode {
 #define BMIC_WRITE_HOST_WELLNESS   0xa5
 #define BMIC_CACHE_FLUSH   0xc2
 
-#define SA_CACHE_FLUSH 0x01
+#define SA_CACHE_FLUSH 0x1
 
 #define MASKED_DEVICE(lunid)   ((lunid)[3] & 0xc0)
 #define CISS_GET_BUS(lunid)((lunid)[7] & 0x3f)
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index acf47d8..91daedc 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -57,8 +57,6 @@ MODULE_SUPPORTED_DEVICE("Microsemi Smart Family Controllers");
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
-#define PQI_ENABLE_MULTI_QUEUE_SUPPORT 0
-
 static char *hpe_branded_controller = "HPE Smart Array Controller";
 static char *microsemi_branded_controller = "Microsemi Smart Family 
Controller";
 
@@ -94,7 +92,7 @@ static unsigned int pqi_supported_event_types[] = {
 
 static int pqi_disable_device_id_wildcards;
 module_param_named(disable_device_id_wildcards,
-   pqi_disable_device_id_wildcards, int, S_IRUGO | S_IWUSR);
+   pqi_disable_device_id_wildcards, int, 0644);
 MODULE_PARM_DESC(disable_device_id_wildcards,
"Disable device ID wildcards.");
 
@@ -383,7 +381,6 @@ static int pqi_build_raid_path_request(struct pqi_ctrl_info 
*ctrl_info,
default:
dev_err(_info->pci_dev->dev, "unknown command 0x%c\n",
cmd);
-   WARN_ON(cmd);
break;
}
 
@@ -1133,10 +1130,8 @@ static int pqi_get_device_info(struct pqi_ctrl_info 
*ctrl_info,
scsi_sanitize_inquiry_string([16], 16);
 
device->devtype = buffer[0] & 0x1f;
-   memcpy(device->vendor, [8],
-   sizeof(device->vendor));
-   memcpy(device->model, [16],
-   sizeof(device->model));
+   memcpy(device->vendor, [8], sizeof(device->vendor));
+   memcpy(device->model, [16], sizeof(device->model));
 
if (pqi_is_logical_device(device) && device->devtype == TYPE_DISK) {
pqi_get_raid_level(ctrl_info, device);
@@ -1607,9 +1602,6 @@ static void pqi_update_device_list(struct pqi_ctrl_info 
*ctrl_info,
 */
device->new_device = true;
break;
-   default:
-   WARN_ON(find_result);
-   break;
}
}
 
@@ -1742,7 +1734,7 @@ static inline bool pqi_skip_device(u8 *scsi3addr,
return false;
 }
 
-static inline bool pqi_expose_device(struct pqi_scsi_dev *device)
+static inline bool pqi_ok_to_expose_device(struct pqi_scsi_dev *device)
 {
/* Expose all devices except for physical devices that are masked. */
if (device->is_physical_device && MASKED_DEVICE(device->scsi3addr))
@@ -1883,7 +1875,7 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info 
*ctrl_info)
 
pqi_assign_bus_target_lun(device);
 
-   device->expose_device = pqi_expose_device(device);
+   device->expose_device = pqi_ok_to_expose_device(device);
 
if (device->is_physical_device) {
device->wwid = phys_lun_ext_entry->wwid;
@@ -2682,7 +2674,6 @@ static unsigned int pqi_process_io_intr(struct 
pqi_ctrl_info *ctrl_info,
dev_err(_info->pci_dev->dev,
"unexpected IU type: 0x%x\n",
response->header.iu_type);
-   WARN_ON(response->header.iu_type);
break;
}
 
@@ -4642,7 +4633,6 @@ static int pqi_raid_submit_scsi_cmd(struct pqi_ctrl_info 
*ctrl_info,
dev_err(_info->pci_dev->dev,
"unknown data direction: %d\n",
scmd->sc_data_direction);
-   WARN_ON(scmd->sc_data_direction);
break;
}
 
@@ -4725,7 +4715,6 @@ static int pqi_aio_submit_io(struct pqi_ctrl_info 
*ctrl_info,
dev_err(_info->pci_dev->dev,
  

[PATCH V2 14/36] smartpqi: correct BMIC identify physical drive

2017-05-03 Thread Don Brace
From: Kevin Barnett 

correct the BMIC Identify Physical Device structure
 - missing 2 fields

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h  |   20 
 drivers/scsi/smartpqi/smartpqi_init.c |   16 
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index 1ac09e7..e74d3ed 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -1126,9 +1126,9 @@ struct bmic_identify_physical_device {
u8  multi_lun_device_lun_count;
u8  minimum_good_fw_revision[8];
u8  unique_inquiry_bytes[20];
-   u8  current_temperature_degreesC;
-   u8  temperature_threshold_degreesC;
-   u8  max_temperature_degreesC;
+   u8  current_temperature_degrees;
+   u8  temperature_threshold_degrees;
+   u8  max_temperature_degrees;
u8  logical_blocks_per_phys_block_exp;
__le16  current_queue_depth_limit;
u8  switch_name[10];
@@ -1141,10 +1141,22 @@ struct bmic_identify_physical_device {
u8  smart_carrier_authentication;
u8  smart_carrier_app_fw_version;
u8  smart_carrier_bootloader_fw_version;
+   u8  sanitize_flags;
+   u8  encryption_key_flags;
u8  encryption_key_name[64];
__le32  misc_drive_flags;
__le16  dek_index;
-   u8  padding[112];
+   __le16  hba_drive_encryption_flags;
+   __le16  max_overwrite_time;
+   __le16  max_block_erase_time;
+   __le16  max_crypto_erase_time;
+   u8  connector_info[5];
+   u8  connector_name[8][8];
+   u8  page_83_identifier[16];
+   u8  maximum_link_rate[256];
+   u8  negotiated_physical_link_rate[256];
+   u8  box_connector_name[8];
+   u8  padding_to_multiple_of_512[9];
 };
 
 #pragma pack()
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index fa21dd4..acf47d8 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -6982,6 +6982,22 @@ static void __attribute__((unused)) 
verify_structures(void)
BUILD_BUG_ON(offsetof(struct bmic_identify_controller,
controller_mode) != 292);
 
+   BUILD_BUG_ON(offsetof(struct bmic_identify_physical_device,
+   phys_bay_in_box) != 115);
+   BUILD_BUG_ON(offsetof(struct bmic_identify_physical_device,
+   device_type) != 120);
+   BUILD_BUG_ON(offsetof(struct bmic_identify_physical_device,
+   redundant_path_present_map) != 1736);
+   BUILD_BUG_ON(offsetof(struct bmic_identify_physical_device,
+   active_path_number) != 1738);
+   BUILD_BUG_ON(offsetof(struct bmic_identify_physical_device,
+   alternate_paths_phys_connector) != 1739);
+   BUILD_BUG_ON(offsetof(struct bmic_identify_physical_device,
+   alternate_paths_phys_box_on_port) != 1755);
+   BUILD_BUG_ON(offsetof(struct bmic_identify_physical_device,
+   current_queue_depth_limit) != 1796);
+   BUILD_BUG_ON(sizeof(struct bmic_identify_physical_device) != 2560);
+
BUILD_BUG_ON(PQI_ADMIN_IQ_NUM_ELEMENTS > 255);
BUILD_BUG_ON(PQI_ADMIN_OQ_NUM_ELEMENTS > 255);
BUILD_BUG_ON(PQI_ADMIN_IQ_ELEMENT_LENGTH %



[PATCH V2 13/36] smartpqi: eliminate redundant error messages

2017-05-03 Thread Don Brace
From: Kevin Barnett 

eliminate redundant error message during initialization
if the controller has crashed.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |5 +
 drivers/scsi/smartpqi/smartpqi_sis.c  |5 -
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 0083ea4..fa21dd4 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -5796,11 +5796,8 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
 * commands.
 */
rc = sis_wait_for_ctrl_ready(ctrl_info);
-   if (rc) {
-   dev_err(_info->pci_dev->dev,
-   "error initializing SIS interface\n");
+   if (rc)
return rc;
-   }
 
/*
 * Get the controller properties.  This allows us to determine
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c 
b/drivers/scsi/smartpqi/smartpqi_sis.c
index 3155bda..d4b1cc7 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.c
+++ b/drivers/scsi/smartpqi/smartpqi_sis.c
@@ -102,8 +102,11 @@ static int sis_wait_for_ctrl_ready_with_timeout(struct 
pqi_ctrl_info *ctrl_info,
if (status & SIS_CTRL_KERNEL_UP)
break;
}
-   if (time_after(jiffies, timeout))
+   if (time_after(jiffies, timeout)) {
+   dev_err(_info->pci_dev->dev,
+   "controller not ready\n");
return -ETIMEDOUT;
+   }
msleep(SIS_CTRL_READY_POLL_INTERVAL_MSECS);
}
 



[PATCH V2 12/36] smartpqi: make pdev pointer names consistent

2017-05-03 Thread Don Brace
From: Kevin Barnett 

make all variable names for pointers to struct pci_dev consistent
throughout the driver.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |   41 +
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 586a1d5..0083ea4 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -3093,19 +3093,19 @@ static irqreturn_t pqi_irq_handler(int irq, void *data)
 
 static int pqi_request_irqs(struct pqi_ctrl_info *ctrl_info)
 {
-   struct pci_dev *pdev = ctrl_info->pci_dev;
+   struct pci_dev *pci_dev = ctrl_info->pci_dev;
int i;
int rc;
 
-   ctrl_info->event_irq = pci_irq_vector(pdev, 0);
+   ctrl_info->event_irq = pci_irq_vector(pci_dev, 0);
 
for (i = 0; i < ctrl_info->num_msix_vectors_enabled; i++) {
-   rc = request_irq(pci_irq_vector(pdev, i), pqi_irq_handler, 0,
+   rc = request_irq(pci_irq_vector(pci_dev, i), pqi_irq_handler, 0,
DRIVER_NAME_SHORT, _info->queue_groups[i]);
if (rc) {
-   dev_err(>dev,
+   dev_err(_dev->dev,
"irq %u init failed with error %d\n",
-   pci_irq_vector(pdev, i), rc);
+   pci_irq_vector(pci_dev, i), rc);
return rc;
}
ctrl_info->num_msix_vectors_initialized++;
@@ -6229,7 +6229,7 @@ static void pqi_remove_ctrl(struct pqi_ctrl_info 
*ctrl_info)
pqi_free_ctrl_resources(ctrl_info);
 }
 
-static void pqi_print_ctrl_info(struct pci_dev *pdev,
+static void pqi_print_ctrl_info(struct pci_dev *pci_dev,
const struct pci_device_id *id)
 {
char *ctrl_description;
@@ -6248,41 +6248,42 @@ static void pqi_print_ctrl_info(struct pci_dev *pdev,
}
}
 
-   dev_info(>dev, "%s found\n", ctrl_description);
+   dev_info(_dev->dev, "%s found\n", ctrl_description);
 }
 
-static int pqi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int pqi_pci_probe(struct pci_dev *pci_dev,
+   const struct pci_device_id *id)
 {
int rc;
int node;
struct pqi_ctrl_info *ctrl_info;
 
-   pqi_print_ctrl_info(pdev, id);
+   pqi_print_ctrl_info(pci_dev, id);
 
if (pqi_disable_device_id_wildcards &&
id->subvendor == PCI_ANY_ID &&
id->subdevice == PCI_ANY_ID) {
-   dev_warn(>dev,
+   dev_warn(_dev->dev,
"controller not probed because device ID wildcards are 
disabled\n");
return -ENODEV;
}
 
if (id->subvendor == PCI_ANY_ID || id->subdevice == PCI_ANY_ID)
-   dev_warn(>dev,
+   dev_warn(_dev->dev,
"controller device ID matched using wildcards\n");
 
-   node = dev_to_node(>dev);
+   node = dev_to_node(_dev->dev);
if (node == NUMA_NO_NODE)
-   set_dev_node(>dev, 0);
+   set_dev_node(_dev->dev, 0);
 
ctrl_info = pqi_alloc_ctrl_info(node);
if (!ctrl_info) {
-   dev_err(>dev,
+   dev_err(_dev->dev,
"failed to allocate controller info block\n");
return -ENOMEM;
}
 
-   ctrl_info->pci_dev = pdev;
+   ctrl_info->pci_dev = pci_dev;
 
rc = pqi_pci_init(ctrl_info);
if (rc)
@@ -6300,23 +6301,23 @@ static int pqi_pci_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
return rc;
 }
 
-static void pqi_pci_remove(struct pci_dev *pdev)
+static void pqi_pci_remove(struct pci_dev *pci_dev)
 {
struct pqi_ctrl_info *ctrl_info;
 
-   ctrl_info = pci_get_drvdata(pdev);
+   ctrl_info = pci_get_drvdata(pci_dev);
if (!ctrl_info)
return;
 
pqi_remove_ctrl(ctrl_info);
 }
 
-static void pqi_shutdown(struct pci_dev *pdev)
+static void pqi_shutdown(struct pci_dev *pci_dev)
 {
int rc;
struct pqi_ctrl_info *ctrl_info;
 
-   ctrl_info = pci_get_drvdata(pdev);
+   ctrl_info = pci_get_drvdata(pci_dev);
if (!ctrl_info)
goto error;
 
@@ -6329,7 +6330,7 @@ static void pqi_shutdown(struct pci_dev *pdev)
return;
 
 error:
-   dev_warn(>dev,
+   dev_warn(_dev->dev,
"unable to flush controller cache\n");
 }
 



[PATCH V2 11/36] smartpqi: add pqi_wait_for_completion_io

2017-05-03 Thread Don Brace
From: Kevin Barnett 

Add check for controller lockup during waits for synchronous
controller commands.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |   33 -
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 6f31cd9..586a1d5 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -3578,6 +3578,37 @@ static void pqi_start_io(struct pqi_ctrl_info *ctrl_info,
spin_unlock_irqrestore(_group->submit_lock[path], flags);
 }
 
+#define PQI_WAIT_FOR_COMPLETION_IO_TIMEOUT_SECS10
+
+static int pqi_wait_for_completion_io(struct pqi_ctrl_info *ctrl_info,
+   struct completion *wait)
+{
+   int rc;
+   unsigned int wait_secs = 0;
+
+   while (1) {
+   if (wait_for_completion_io_timeout(wait,
+   PQI_WAIT_FOR_COMPLETION_IO_TIMEOUT_SECS * HZ)) {
+   rc = 0;
+   break;
+   }
+
+   pqi_check_ctrl_health(ctrl_info);
+   if (pqi_ctrl_offline(ctrl_info)) {
+   rc = -ENXIO;
+   break;
+   }
+
+   wait_secs += PQI_WAIT_FOR_COMPLETION_IO_TIMEOUT_SECS;
+
+   dev_err(_info->pci_dev->dev,
+   "waiting %u seconds for completion\n",
+   wait_secs);
+   }
+
+   return rc;
+}
+
 static void pqi_raid_synchronous_complete(struct pqi_io_request *io_request,
void *context)
 {
@@ -3601,7 +3632,7 @@ static int 
pqi_submit_raid_request_synchronous_with_io_request(
io_request);
 
if (timeout_msecs == NO_TIMEOUT) {
-   wait_for_completion_io();
+   pqi_wait_for_completion_io(ctrl_info, );
} else {
if (!wait_for_completion_io_timeout(,
msecs_to_jiffies(timeout_msecs))) {



[PATCH V2 10/36] smartpqi: correct bdma hw bug

2017-05-03 Thread Don Brace
From: Kevin Barnett 

add workaround for BDMA hardware bug that can cause
hw to read up to 12 SGL elements (192 bytes) beyond the
last element in the list. This fix avoids IOMMU violations

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index de33942..6f31cd9 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -48,6 +48,8 @@
 #define DRIVER_NAME"Microsemi PQI Driver (v" DRIVER_VERSION ")"
 #define DRIVER_NAME_SHORT  "smartpqi"
 
+#define PQI_EXTRA_SGL_MEMORY   (12 * sizeof(struct pqi_sg_descriptor))
+
 MODULE_AUTHOR("Microsemi");
 MODULE_DESCRIPTION("Driver for Microsemi Smart Family Controller version "
DRIVER_VERSION);
@@ -3202,6 +3204,8 @@ static int pqi_alloc_operational_queues(struct 
pqi_ctrl_info *ctrl_info)
alloc_length = (size_t)aligned_pointer +
PQI_QUEUE_ELEMENT_ARRAY_ALIGNMENT;
 
+   alloc_length += PQI_EXTRA_SGL_MEMORY;
+
ctrl_info->queue_memory_base =
dma_zalloc_coherent(_info->pci_dev->dev,
alloc_length,
@@ -4319,7 +4323,8 @@ static void pqi_calculate_io_resources(struct 
pqi_ctrl_info *ctrl_info)
max_transfer_size = (max_sg_entries - 1) * PAGE_SIZE;
 
ctrl_info->sg_chain_buffer_length =
-   max_sg_entries * sizeof(struct pqi_sg_descriptor);
+   (max_sg_entries * sizeof(struct pqi_sg_descriptor)) +
+   PQI_EXTRA_SGL_MEMORY;
ctrl_info->sg_tablesize = max_sg_entries;
ctrl_info->max_sectors = max_transfer_size / 512;
 }



[PATCH V2 08/36] smartpqi: add suspend and resume support

2017-05-03 Thread Don Brace
From: Kevin Barnett 

add support for ACPI S3 (suspend) and S4 (hibernate)
system power states.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h  |   12 +
 drivers/scsi/smartpqi/smartpqi_init.c |  425 +++--
 drivers/scsi/smartpqi/smartpqi_sis.c  |   75 ++
 drivers/scsi/smartpqi/smartpqi_sis.h  |3 
 4 files changed, 485 insertions(+), 30 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index 5b0c6fb..06e2b71 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -61,7 +61,7 @@ struct pqi_device_registers {
 /*
  * controller registers
  *
- * These are defined by the PMC implementation.
+ * These are defined by the Microsemi implementation.
  *
  * Some registers (those named sis_*) are only used when in
  * legacy SIS mode before we transition the controller into
@@ -102,6 +102,12 @@ enum pqi_io_path {
AIO_PATH = 1
 };
 
+enum pqi_irq_mode {
+   IRQ_MODE_NONE,
+   IRQ_MODE_INTX,
+   IRQ_MODE_MSIX
+};
+
 struct pqi_sg_descriptor {
__le64  address;
__le32  length;
@@ -908,7 +914,7 @@ struct pqi_ctrl_info {
dma_addr_t  error_buffer_dma_handle;
size_t  sg_chain_buffer_length;
unsigned intnum_queue_groups;
-   unsigned intnum_active_queue_groups;
+   u16 max_hw_queue_index;
u16 num_elements_per_iq;
u16 num_elements_per_oq;
u16 max_inbound_iu_length_per_firmware;
@@ -923,6 +929,7 @@ struct pqi_ctrl_info {
struct pqi_admin_queues admin_queues;
struct pqi_queue_group queue_groups[PQI_MAX_QUEUE_GROUPS];
struct pqi_event_queue event_queue;
+   enum pqi_irq_mode irq_mode;
int max_msix_vectors;
int num_msix_vectors_enabled;
int num_msix_vectors_initialized;
@@ -937,6 +944,7 @@ struct pqi_ctrl_info {
u8  outbound_spanning_supported : 1;
u8  pqi_mode_enabled : 1;
u8  heartbeat_timer_started : 1;
+   u8  update_time_worker_scheduled : 1;
 
struct list_head scsi_device_list;
spinlock_t  scsi_device_list_lock;
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index bd8a66d..7af4add 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -262,6 +262,11 @@ static inline void pqi_schedule_rescan_worker(struct 
pqi_ctrl_info *ctrl_info)
PQI_RESCAN_WORK_INTERVAL);
 }
 
+static inline void pqi_cancel_rescan_worker(struct pqi_ctrl_info *ctrl_info)
+{
+   cancel_delayed_work_sync(_info->rescan_work);
+}
+
 static int pqi_map_single(struct pci_dev *pci_dev,
struct pqi_sg_descriptor *sg_descriptor, void *buffer,
size_t buffer_length, int data_direction)
@@ -588,7 +593,7 @@ static int pqi_write_driver_version_to_host_wellness(
buffer->driver_version_tag[1] = 'V';
put_unaligned_le16(sizeof(buffer->driver_version),
>driver_version_length);
-   strncpy(buffer->driver_version, DRIVER_VERSION,
+   strncpy(buffer->driver_version, "Linux " DRIVER_VERSION,
sizeof(buffer->driver_version) - 1);
buffer->driver_version[sizeof(buffer->driver_version) - 1] = '\0';
buffer->end_tag[0] = 'Z';
@@ -686,7 +691,21 @@ static void pqi_update_time_worker(struct work_struct 
*work)
 static inline void pqi_schedule_update_time_worker(
struct pqi_ctrl_info *ctrl_info)
 {
+   if (ctrl_info->update_time_worker_scheduled)
+   return;
+
schedule_delayed_work(_info->update_time_work, 0);
+   ctrl_info->update_time_worker_scheduled = true;
+}
+
+static inline void pqi_cancel_update_time_worker(
+   struct pqi_ctrl_info *ctrl_info)
+{
+   if (!ctrl_info->update_time_worker_scheduled)
+   return;
+
+   cancel_delayed_work_sync(_info->update_time_work);
+   ctrl_info->update_time_worker_scheduled = false;
 }
 
 static int pqi_report_luns(struct pqi_ctrl_info *ctrl_info, u8 cmd,
@@ -1967,6 +1986,18 @@ static int pqi_scan_finished(struct Scsi_Host *shost,
return !mutex_is_locked(_info->scan_mutex);
 }
 
+static void pqi_wait_until_scan_finished(struct pqi_ctrl_info *ctrl_info)
+{
+   mutex_lock(_info->scan_mutex);
+   mutex_unlock(_info->scan_mutex);
+}
+
+static void pqi_wait_until_lun_reset_finished(struct pqi_ctrl_info *ctrl_info)
+{
+   mutex_lock(_info->lun_reset_mutex);
+   mutex_unlock(_info->lun_reset_mutex);
+}
+
 static inline void pqi_set_encryption_info(
struct pqi_encryption_info *encryption_info, struct raid_map *raid_map,
u64 

[PATCH V2 04/36] smartpqi: add in controller checkpoint for controller lockups.

2017-05-03 Thread Don Brace
From: Kevin Barnett 

tell smartpqi controller to generate a checkpoint for rare lockup
conditions.

Reviewed-by: Scott Benesh 
Reviewed-by: Scott Teel 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h  |2 +-
 drivers/scsi/smartpqi/smartpqi_init.c |1 +
 drivers/scsi/smartpqi/smartpqi_sis.c  |7 +++
 drivers/scsi/smartpqi/smartpqi_sis.h  |1 +
 4 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index b673825..73754ca 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -933,10 +933,10 @@ struct pqi_ctrl_info {
struct Scsi_Host *scsi_host;
 
struct mutexscan_mutex;
+   boolcontroller_online : 1;
u8  inbound_spanning_supported : 1;
u8  outbound_spanning_supported : 1;
u8  pqi_mode_enabled : 1;
-   u8  controller_online : 1;
u8  heartbeat_timer_started : 1;
 
struct list_head scsi_device_list;
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 735cef5..14d74e1 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -2697,6 +2697,7 @@ static void pqi_take_ctrl_offline(struct pqi_ctrl_info 
*ctrl_info)
 
ctrl_info->controller_online = false;
dev_err(_info->pci_dev->dev, "controller offline\n");
+   sis_shutdown_ctrl(ctrl_info);
 
for (i = 0; i < ctrl_info->num_queue_groups; i++) {
queue_group = _info->queue_groups[i];
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c 
b/drivers/scsi/smartpqi/smartpqi_sis.c
index 71408f9..c7d9ea1 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.c
+++ b/drivers/scsi/smartpqi/smartpqi_sis.c
@@ -34,6 +34,7 @@
 #define SIS_REENABLE_SIS_MODE  0x1
 #define SIS_ENABLE_MSIX0x40
 #define SIS_SOFT_RESET 0x100
+#define SIS_TRIGGER_SHUTDOWN   0x80
 #define SIS_CMD_READY  0x200
 #define SIS_CMD_COMPLETE   0x1000
 #define SIS_CLEAR_CTRL_TO_HOST_DOORBELL0x1000
@@ -342,6 +343,12 @@ void sis_soft_reset(struct pqi_ctrl_info *ctrl_info)
_info->registers->sis_host_to_ctrl_doorbell);
 }
 
+void sis_shutdown_ctrl(struct pqi_ctrl_info *ctrl_info)
+{
+   writel(SIS_TRIGGER_SHUTDOWN,
+   _info->registers->sis_host_to_ctrl_doorbell);
+}
+
 #define SIS_MODE_READY_TIMEOUT_SECS30
 
 int sis_reenable_sis_mode(struct pqi_ctrl_info *ctrl_info)
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.h 
b/drivers/scsi/smartpqi/smartpqi_sis.h
index bd6e7b0..7f7b68c 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.h
+++ b/drivers/scsi/smartpqi/smartpqi_sis.h
@@ -27,6 +27,7 @@ int sis_init_base_struct_addr(struct pqi_ctrl_info 
*ctrl_info);
 void sis_enable_msix(struct pqi_ctrl_info *ctrl_info);
 void sis_disable_msix(struct pqi_ctrl_info *ctrl_info);
 void sis_soft_reset(struct pqi_ctrl_info *ctrl_info);
+void sis_shutdown_ctrl(struct pqi_ctrl_info *ctrl_info);
 int sis_reenable_sis_mode(struct pqi_ctrl_info *ctrl_info);
 void sis_write_driver_scratch(struct pqi_ctrl_info *ctrl_info, u32 value);
 u32 sis_read_driver_scratch(struct pqi_ctrl_info *ctrl_info);



[PATCH V2 07/36] smartpqi: enhance resets

2017-05-03 Thread Don Brace
From: Kevin Barnett 

- Block all I/O targeted at LUN reset device.
- Wait until all I/O targeted at LUN reset device has been
  consumed by the controller.
- Issue LUN reset request.
- Wait until all outstanding I/Os and LUN reset completion
  have been received by the host.
- Return to OS results of LUN reset request.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h  |   13 +-
 drivers/scsi/smartpqi/smartpqi_init.c |  279 ++---
 2 files changed, 265 insertions(+), 27 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index 02b3196..5b0c6fb 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -734,6 +734,8 @@ struct pqi_scsi_dev {
u8  new_device : 1;
u8  keep_device : 1;
u8  volume_offline : 1;
+   boolin_reset;
+   booldevice_offline;
u8  vendor[8];  /* bytes 8-15 of inquiry data */
u8  model[16];  /* bytes 16-31 of inquiry data */
u64 sas_address;
@@ -761,6 +763,8 @@ struct pqi_scsi_dev {
struct list_head new_device_list_entry;
struct list_head add_list_entry;
struct list_head delete_list_entry;
+
+   atomic_t scsi_cmds_outstanding;
 };
 
 /* VPD inquiry pages */
@@ -926,7 +930,9 @@ struct pqi_ctrl_info {
struct Scsi_Host *scsi_host;
 
struct mutexscan_mutex;
-   boolcontroller_online : 1;
+   struct mutexlun_reset_mutex;
+   boolcontroller_online;
+   boolblock_requests;
u8  inbound_spanning_supported : 1;
u8  outbound_spanning_supported : 1;
u8  pqi_mode_enabled : 1;
@@ -953,7 +959,9 @@ struct pqi_ctrl_info {
struct timer_list heartbeat_timer;
 
struct semaphore sync_request_sem;
-   struct semaphore lun_reset_sem;
+   atomic_tnum_busy_threads;
+   atomic_tnum_blocked_threads;
+   wait_queue_head_t block_requests_wait;
 };
 
 enum pqi_ctrl_mode {
@@ -1092,6 +1100,7 @@ int pqi_add_sas_device(struct pqi_sas_node *pqi_sas_node,
 void pqi_remove_sas_device(struct pqi_scsi_dev *device);
 struct pqi_scsi_dev *pqi_find_device_by_sas_rphy(
struct pqi_ctrl_info *ctrl_info, struct sas_rphy *rphy);
+void pqi_prep_for_scsi_done(struct scsi_cmnd *scmd);
 
 extern struct sas_function_template pqi_sas_transport_functions;
 
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 279dd41..bd8a66d 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -126,6 +126,7 @@ static char *pqi_raid_level_to_string(u8 raid_level)
 
 static inline void pqi_scsi_done(struct scsi_cmnd *scmd)
 {
+   pqi_prep_for_scsi_done(scmd);
scmd->scsi_done(scmd);
 }
 
@@ -175,7 +176,85 @@ static inline void pqi_save_ctrl_mode(struct pqi_ctrl_info 
*ctrl_info,
sis_write_driver_scratch(ctrl_info, mode);
 }
 
-#define PQI_RESCAN_WORK_INTERVAL   (10 * HZ)
+#define PQI_RESCAN_WORK_INTERVAL   (10 * HZ)
+static inline void pqi_ctrl_block_requests(struct pqi_ctrl_info *ctrl_info)
+{
+   ctrl_info->block_requests = true;
+   scsi_block_requests(ctrl_info->scsi_host);
+}
+
+static inline void pqi_ctrl_unblock_requests(struct pqi_ctrl_info *ctrl_info)
+{
+   ctrl_info->block_requests = false;
+   wake_up_all(_info->block_requests_wait);
+   scsi_unblock_requests(ctrl_info->scsi_host);
+}
+
+static inline bool pqi_ctrl_blocked(struct pqi_ctrl_info *ctrl_info)
+{
+   return ctrl_info->block_requests;
+}
+
+static unsigned long pqi_wait_if_ctrl_blocked(struct pqi_ctrl_info *ctrl_info,
+   unsigned long timeout_msecs)
+{
+   unsigned long remaining_msecs;
+
+   if (!pqi_ctrl_blocked(ctrl_info))
+   return timeout_msecs;
+
+   atomic_inc(_info->num_blocked_threads);
+
+   if (timeout_msecs == NO_TIMEOUT) {
+   wait_event(ctrl_info->block_requests_wait,
+   !pqi_ctrl_blocked(ctrl_info));
+   remaining_msecs = timeout_msecs;
+   } else {
+   unsigned long remaining_jiffies;
+
+   remaining_jiffies =
+   wait_event_timeout(ctrl_info->block_requests_wait,
+   !pqi_ctrl_blocked(ctrl_info),
+   msecs_to_jiffies(timeout_msecs));
+   remaining_msecs = jiffies_to_msecs(remaining_jiffies);
+   }
+
+   atomic_dec(_info->num_blocked_threads);
+
+   return remaining_msecs;
+}
+
+static inline void pqi_ctrl_busy(struct pqi_ctrl_info *ctrl_info)
+{
+   atomic_inc(_info->num_busy_threads);
+}
+
+static inline void 

[PATCH V2 06/36] smartpqi: add supporting events

2017-05-03 Thread Don Brace
From: Kevin Barnett 

Only register for controller events that driver supports
cleanup event handling.

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h  |   11 +--
 drivers/scsi/smartpqi/smartpqi_init.c |  110 ++---
 2 files changed, 61 insertions(+), 60 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index 62045c1..02b3196 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -860,15 +860,8 @@ struct pqi_io_request {
struct list_head request_list_entry;
 };
 
-/* for indexing into the pending_events[] field of struct pqi_ctrl_info */
 #define PQI_EVENT_HEARTBEAT0
-#define PQI_EVENT_HOTPLUG  1
-#define PQI_EVENT_HARDWARE 2
-#define PQI_EVENT_PHYSICAL_DEVICE  3
-#define PQI_EVENT_LOGICAL_DEVICE   4
-#define PQI_EVENT_AIO_STATE_CHANGE 5
-#define PQI_EVENT_AIO_CONFIG_CHANGE6
-#define PQI_NUM_SUPPORTED_EVENTS   7
+#define PQI_NUM_SUPPORTED_EVENTS   6
 
 struct pqi_event {
boolpending;
@@ -951,7 +944,7 @@ struct pqi_ctrl_info {
struct pqi_io_request *io_request_pool;
u16 next_io_request_slot;
 
-   struct pqi_event pending_events[PQI_NUM_SUPPORTED_EVENTS];
+   struct pqi_event events[PQI_NUM_SUPPORTED_EVENTS];
struct work_struct event_work;
 
atomic_tnum_interrupts;
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 5a5b9ab..279dd41 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -81,6 +81,15 @@ static struct scsi_transport_template 
*pqi_sas_transport_template;
 
 static atomic_t pqi_controller_count = ATOMIC_INIT(0);
 
+static unsigned int pqi_supported_event_types[] = {
+   PQI_EVENT_TYPE_HOTPLUG,
+   PQI_EVENT_TYPE_HARDWARE,
+   PQI_EVENT_TYPE_PHYSICAL_DEVICE,
+   PQI_EVENT_TYPE_LOGICAL_DEVICE,
+   PQI_EVENT_TYPE_AIO_STATE_CHANGE,
+   PQI_EVENT_TYPE_AIO_CONFIG_CHANGE,
+};
+
 static int pqi_disable_device_id_wildcards;
 module_param_named(disable_device_id_wildcards,
pqi_disable_device_id_wildcards, int, S_IRUGO | S_IWUSR);
@@ -2665,20 +2674,20 @@ static void pqi_event_worker(struct work_struct *work)
 {
unsigned int i;
struct pqi_ctrl_info *ctrl_info;
-   struct pqi_event *pending_event;
+   struct pqi_event *event;
bool got_non_heartbeat_event = false;
 
ctrl_info = container_of(work, struct pqi_ctrl_info, event_work);
 
-   pending_event = ctrl_info->pending_events;
+   event = ctrl_info->events;
for (i = 0; i < PQI_NUM_SUPPORTED_EVENTS; i++) {
-   if (pending_event->pending) {
-   pending_event->pending = false;
-   pqi_acknowledge_event(ctrl_info, pending_event);
-   if (i != PQI_EVENT_HEARTBEAT)
+   if (event->pending) {
+   event->pending = false;
+   pqi_acknowledge_event(ctrl_info, event);
+   if (i != PQI_EVENT_TYPE_HEARTBEAT)
got_non_heartbeat_event = true;
}
-   pending_event++;
+   event++;
}
 
if (got_non_heartbeat_event)
@@ -2742,7 +2751,7 @@ static void pqi_heartbeat_timer_handler(unsigned long 
data)
pqi_take_ctrl_offline(ctrl_info);
return;
}
-   ctrl_info->pending_events[PQI_EVENT_HEARTBEAT].pending = true;
+   ctrl_info->events[PQI_EVENT_HEARTBEAT].pending = true;
schedule_work(_info->event_work);
} else {
ctrl_info->num_heartbeats_requested = 0;
@@ -2773,38 +2782,20 @@ static inline void pqi_stop_heartbeat_timer(struct 
pqi_ctrl_info *ctrl_info)
del_timer_sync(_info->heartbeat_timer);
 }
 
-static int pqi_event_type_to_event_index(unsigned int event_type)
+static inline int pqi_event_type_to_event_index(unsigned int event_type)
 {
int index;
 
-   switch (event_type) {
-   case PQI_EVENT_TYPE_HEARTBEAT:
-   index = PQI_EVENT_HEARTBEAT;
-   break;
-   case PQI_EVENT_TYPE_HOTPLUG:
-   index = PQI_EVENT_HOTPLUG;
-   break;
-   case PQI_EVENT_TYPE_HARDWARE:
-   index = PQI_EVENT_HARDWARE;
-   break;
-   case PQI_EVENT_TYPE_PHYSICAL_DEVICE:
-   index = PQI_EVENT_PHYSICAL_DEVICE;
-   break;
-   case PQI_EVENT_TYPE_LOGICAL_DEVICE:
-   index = PQI_EVENT_LOGICAL_DEVICE;
-   break;
-   case PQI_EVENT_TYPE_AIO_STATE_CHANGE:
-   index = 

[PATCH V2 03/36] smartpqi: set pci completion timeout

2017-05-03 Thread Don Brace
From: Kevin Barnett 

add support for setting PCIe completion timeout.

Reviewed-by: Scott Benesh 
Reviewed-by: Scott Teel 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |   18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index b5a3505..735cef5 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -5437,6 +5437,13 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
return 0;
 }
 
+static inline int pqi_set_pcie_completion_timeout(struct pci_dev *pci_dev,
+   u16 timeout)
+{
+   return pcie_capability_clear_and_set_word(pci_dev, PCI_EXP_DEVCTL2,
+   PCI_EXP_DEVCTL2_COMP_TIMEOUT, timeout);
+}
+
 static int pqi_pci_init(struct pqi_ctrl_info *ctrl_info)
 {
int rc;
@@ -5480,6 +5487,17 @@ static int pqi_pci_init(struct pqi_ctrl_info *ctrl_info)
ctrl_info->registers = ctrl_info->iomem_base;
ctrl_info->pqi_registers = _info->registers->pqi_registers;
 
+#define PCI_EXP_COMP_TIMEOUT_65_TO_210_MS  0x6
+
+   /* Increase the PCIe completion timeout. */
+   rc = pqi_set_pcie_completion_timeout(ctrl_info->pci_dev,
+   PCI_EXP_COMP_TIMEOUT_65_TO_210_MS);
+   if (rc) {
+   dev_err(_info->pci_dev->dev,
+   "failed to set PCIe completion timeout\n");
+   goto release_regions;
+   }
+
/* Enable bus mastering. */
pci_set_master(ctrl_info->pci_dev);
 



[PATCH V2 05/36] smartpqi: ensure controller is in SIS mode at init

2017-05-03 Thread Don Brace
From: Kevin Barnett 

put in SIS mode during initialization.
support kexec/kdump

Reviewed-by: Scott Benesh 
Reviewed-by: Scott Teel 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h  |2 +
 drivers/scsi/smartpqi/smartpqi_init.c |   60 +++--
 drivers/scsi/smartpqi/smartpqi_sis.c  |6 +++
 drivers/scsi/smartpqi/smartpqi_sis.h  |1 +
 4 files changed, 42 insertions(+), 27 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index 73754ca..62045c1 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -964,7 +964,7 @@ struct pqi_ctrl_info {
 };
 
 enum pqi_ctrl_mode {
-   UNKNOWN,
+   SIS_MODE = 0,
PQI_MODE
 };
 
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 14d74e1..5a5b9ab 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -5245,38 +5245,50 @@ static int pqi_get_ctrl_firmware_version(struct 
pqi_ctrl_info *ctrl_info)
return rc;
 }
 
-static int pqi_kdump_init(struct pqi_ctrl_info *ctrl_info)
+/* Switches the controller from PQI mode back into SIS mode. */
+
+static int pqi_revert_to_sis_mode(struct pqi_ctrl_info *ctrl_info)
+{
+   int rc;
+
+   sis_disable_msix(ctrl_info);
+   rc = pqi_reset(ctrl_info);
+   if (rc)
+   return rc;
+   sis_reenable_sis_mode(ctrl_info);
+   pqi_save_ctrl_mode(ctrl_info, SIS_MODE);
+
+   return 0;
+}
+
+/*
+ * If the controller isn't already in SIS mode, this function forces it into
+ * SIS mode.
+ */
+
+static int pqi_force_sis_mode(struct pqi_ctrl_info *ctrl_info)
 {
if (!sis_is_firmware_running(ctrl_info))
return -ENXIO;
 
-   if (pqi_get_ctrl_mode(ctrl_info) == PQI_MODE) {
-   sis_disable_msix(ctrl_info);
-   if (pqi_reset(ctrl_info) == 0)
-   sis_reenable_sis_mode(ctrl_info);
+   if (pqi_get_ctrl_mode(ctrl_info) == SIS_MODE)
+   return 0;
+
+   if (sis_is_kernel_up(ctrl_info)) {
+   pqi_save_ctrl_mode(ctrl_info, SIS_MODE);
+   return 0;
}
 
-   return 0;
+   return pqi_revert_to_sis_mode(ctrl_info);
 }
 
 static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
 {
int rc;
 
-   if (reset_devices) {
-   rc = pqi_kdump_init(ctrl_info);
-   if (rc)
-   return rc;
-   }
-
-   /*
-* When the controller comes out of reset, it is always running
-* in legacy SIS mode.  This is so that it can be compatible
-* with legacy drivers shipped with OSes.  So we have to talk
-* to it using SIS commands at first.  Once we are satisified
-* that the controller supports PQI, we transition it into PQI
-* mode.
-*/
+   rc = pqi_force_sis_mode(ctrl_info);
+   if (rc)
+   return rc;
 
/*
 * Wait until the controller is ready to start accepting SIS
@@ -5594,12 +5606,8 @@ static void pqi_remove_ctrl(struct pqi_ctrl_info 
*ctrl_info)
cancel_delayed_work_sync(_info->update_time_work);
pqi_remove_all_scsi_devices(ctrl_info);
pqi_unregister_scsi(ctrl_info);
-
-   if (ctrl_info->pqi_mode_enabled) {
-   sis_disable_msix(ctrl_info);
-   if (pqi_reset(ctrl_info) == 0)
-   sis_reenable_sis_mode(ctrl_info);
-   }
+   if (ctrl_info->pqi_mode_enabled)
+   pqi_revert_to_sis_mode(ctrl_info);
pqi_free_ctrl_resources(ctrl_info);
 }
 
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c 
b/drivers/scsi/smartpqi/smartpqi_sis.c
index c7d9ea1..c5325a4 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.c
+++ b/drivers/scsi/smartpqi/smartpqi_sis.c
@@ -127,6 +127,12 @@ bool sis_is_firmware_running(struct pqi_ctrl_info 
*ctrl_info)
return running;
 }
 
+bool sis_is_kernel_up(struct pqi_ctrl_info *ctrl_info)
+{
+   return readl(_info->registers->sis_firmware_status) &
+   SIS_CTRL_KERNEL_UP;
+}
+
 /* used for passing command parameters/results when issuing SIS commands */
 struct sis_sync_cmd_params {
u32 mailbox[6]; /* mailboxes 0-5 */
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.h 
b/drivers/scsi/smartpqi/smartpqi_sis.h
index 7f7b68c..157768d 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.h
+++ b/drivers/scsi/smartpqi/smartpqi_sis.h
@@ -21,6 +21,7 @@
 
 int sis_wait_for_ctrl_ready(struct pqi_ctrl_info *ctrl_info);
 bool sis_is_firmware_running(struct pqi_ctrl_info *ctrl_info);
+bool sis_is_kernel_up(struct pqi_ctrl_info *ctrl_info);
 int sis_get_ctrl_properties(struct pqi_ctrl_info *ctrl_info);
 int sis_get_pqi_capabilities(struct 

[PATCH V2 09/36] smartpqi: add heartbeat check

2017-05-03 Thread Don Brace
From: Kevin Barnett 

check for controller lockups

Reviewed-by: Scott Benesh 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi.h  |   60 ++--
 drivers/scsi/smartpqi/smartpqi_init.c |  126 ++---
 drivers/scsi/smartpqi/smartpqi_sis.c  |4 +
 3 files changed, 143 insertions(+), 47 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index 06e2b71..1ac09e7 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -490,7 +490,6 @@ struct pqi_raid_error_info {
 #define PQI_EVENT_TYPE_LOGICAL_DEVICE  0x5
 #define PQI_EVENT_TYPE_AIO_STATE_CHANGE0xfd
 #define PQI_EVENT_TYPE_AIO_CONFIG_CHANGE   0xfe
-#define PQI_EVENT_TYPE_HEARTBEAT   0xff
 
 #pragma pack()
 
@@ -635,6 +634,58 @@ struct pqi_encryption_info {
u32 encrypt_tweak_upper;
 };
 
+#pragma pack(1)
+
+#define PQI_CONFIG_TABLE_SIGNATURE "CFGTABLE"
+#define PQI_CONFIG_TABLE_MAX_LENGTH((u16)~0)
+
+/* configuration table section IDs */
+#define PQI_CONFIG_TABLE_SECTION_GENERAL_INFO  0
+#define PQI_CONFIG_TABLE_SECTION_FIRMWARE_FEATURES 1
+#define PQI_CONFIG_TABLE_SECTION_FIRMWARE_ERRATA   2
+#define PQI_CONFIG_TABLE_SECTION_DEBUG 3
+#define PQI_CONFIG_TABLE_SECTION_HEARTBEAT 4
+
+struct pqi_config_table {
+   u8  signature[8];   /* "CFGTABLE" */
+   __le32  first_section_offset;   /* offset in bytes from the base */
+   /* address of this table to the */
+   /* first section */
+};
+
+struct pqi_config_table_section_header {
+   __le16  section_id; /* as defined by the */
+   /* PQI_CONFIG_TABLE_SECTION_* */
+   /* manifest constants above */
+   __le16  next_section_offset;/* offset in bytes from base */
+   /* address of the table of the */
+   /* next section or 0 if last entry */
+};
+
+struct pqi_config_table_general_info {
+   struct pqi_config_table_section_header header;
+   __le32  section_length; /* size of this section in bytes */
+   /* including the section header */
+   __le32  max_outstanding_requests;   /* max. outstanding */
+   /* commands supported by */
+   /* the controller */
+   __le32  max_sg_size;/* max. transfer size of a single */
+   /* command */
+   __le32  max_sg_per_request; /* max. number of scatter-gather */
+   /* entries supported in a single */
+   /* command */
+};
+
+struct pqi_config_table_debug {
+   struct pqi_config_table_section_header header;
+   __le32  scratchpad;
+};
+
+struct pqi_config_table_heartbeat {
+   struct pqi_config_table_section_header header;
+   __le32  heartbeat_counter;
+};
+
 #define PQI_MAX_OUTSTANDING_REQUESTS   ((u32)~0)
 #define PQI_MAX_TRANSFER_SIZE  (4 * 1024U * 1024U)
 
@@ -645,8 +696,6 @@ struct pqi_encryption_info {
 #define PQI_HBA_BUS2
 #define PQI_MAX_BUSPQI_HBA_BUS
 
-#pragma pack(1)
-
 struct report_lun_header {
__be32  list_length;
u8  extended_response;
@@ -870,7 +919,6 @@ struct pqi_io_request {
struct list_head request_list_entry;
 };
 
-#define PQI_EVENT_HEARTBEAT0
 #define PQI_NUM_SUPPORTED_EVENTS   6
 
 struct pqi_event {
@@ -943,7 +991,6 @@ struct pqi_ctrl_info {
u8  inbound_spanning_supported : 1;
u8  outbound_spanning_supported : 1;
u8  pqi_mode_enabled : 1;
-   u8  heartbeat_timer_started : 1;
u8  update_time_worker_scheduled : 1;
 
struct list_head scsi_device_list;
@@ -963,7 +1010,8 @@ struct pqi_ctrl_info {
 
atomic_tnum_interrupts;
int previous_num_interrupts;
-   unsigned intnum_heartbeats_requested;
+   u32 previous_heartbeat_count;
+   __le32 __iomem  *heartbeat_counter;
struct timer_list heartbeat_timer;
 
struct semaphore sync_request_sem;
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 7af4add..de33942 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -267,6 +267,14 @@ static inline void pqi_cancel_rescan_worker(struct 
pqi_ctrl_info *ctrl_info)

[PATCH V2 02/36] smartpqi: cleanup interrupt management

2017-05-03 Thread Don Brace
From: Kevin Barnett 

minor cleanup of interrupt initialization and tear-down.

Reviewed-by: Scott Benesh 
Reviewed-by: Scott Teel 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |   43 ++---
 1 file changed, 29 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index dd00c69..b5a3505 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -2913,23 +2913,44 @@ static int pqi_request_irqs(struct pqi_ctrl_info 
*ctrl_info)
return 0;
 }
 
+static void pqi_free_irqs(struct pqi_ctrl_info *ctrl_info)
+{
+   int i;
+
+   for (i = 0; i < ctrl_info->num_msix_vectors_initialized; i++)
+   free_irq(pci_irq_vector(ctrl_info->pci_dev, i),
+   _info->queue_groups[i]);
+
+   ctrl_info->num_msix_vectors_initialized = 0;
+}
+
 static int pqi_enable_msix_interrupts(struct pqi_ctrl_info *ctrl_info)
 {
-   int ret;
+   int num_vectors_enabled;
 
-   ret = pci_alloc_irq_vectors(ctrl_info->pci_dev,
+   num_vectors_enabled = pci_alloc_irq_vectors(ctrl_info->pci_dev,
PQI_MIN_MSIX_VECTORS, ctrl_info->num_queue_groups,
PCI_IRQ_MSIX | PCI_IRQ_AFFINITY);
-   if (ret < 0) {
+   if (num_vectors_enabled < 0) {
dev_err(_info->pci_dev->dev,
-   "MSI-X init failed with error %d\n", ret);
-   return ret;
+   "MSI-X init failed with error %d\n",
+   num_vectors_enabled);
+   return num_vectors_enabled;
}
 
-   ctrl_info->num_msix_vectors_enabled = ret;
+   ctrl_info->num_msix_vectors_enabled = num_vectors_enabled;
+
return 0;
 }
 
+static void pqi_disable_msix_interrupts(struct pqi_ctrl_info *ctrl_info)
+{
+   if (ctrl_info->num_msix_vectors_enabled) {
+   pci_free_irq_vectors(ctrl_info->pci_dev);
+   ctrl_info->num_msix_vectors_enabled = 0;
+   }
+}
+
 static int pqi_alloc_operational_queues(struct pqi_ctrl_info *ctrl_info)
 {
unsigned int i;
@@ -5519,14 +5540,8 @@ static inline void pqi_free_ctrl_info(struct 
pqi_ctrl_info *ctrl_info)
 
 static void pqi_free_interrupts(struct pqi_ctrl_info *ctrl_info)
 {
-   int i;
-
-   for (i = 0; i < ctrl_info->num_msix_vectors_initialized; i++) {
-   free_irq(pci_irq_vector(ctrl_info->pci_dev, i),
-   _info->queue_groups[i]);
-   }
-
-   pci_free_irq_vectors(ctrl_info->pci_dev);
+   pqi_free_irqs(ctrl_info);
+   pqi_disable_msix_interrupts(ctrl_info);
 }
 
 static void pqi_free_ctrl_resources(struct pqi_ctrl_info *ctrl_info)



[PATCH V2 01/36] smartpqi: correct remove scsi devices

2017-05-03 Thread Don Brace
From: Kevin Barnett 

correct a problem caused by holding a spinlock during device deletion.

Reviewed-by: Scott Benesh 
Reviewed-by: Scott Teel 
Signed-off-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/smartpqi_init.c |   20 +---
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 657ad15..dd00c69 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -1823,19 +1823,25 @@ static void pqi_remove_all_scsi_devices(struct 
pqi_ctrl_info *ctrl_info)
 {
unsigned long flags;
struct pqi_scsi_dev *device;
-   struct pqi_scsi_dev *next;
 
-   spin_lock_irqsave(_info->scsi_device_list_lock, flags);
+   while (1) {
+   spin_lock_irqsave(_info->scsi_device_list_lock, flags);
+
+   device = list_first_entry_or_null(_info->scsi_device_list,
+   struct pqi_scsi_dev, scsi_device_list_entry);
+   if (device)
+   list_del(>scsi_device_list_entry);
+
+   spin_unlock_irqrestore(_info->scsi_device_list_lock,
+   flags);
+
+   if (!device)
+   break;
 
-   list_for_each_entry_safe(device, next, _info->scsi_device_list,
-   scsi_device_list_entry) {
if (device->sdev)
pqi_remove_device(ctrl_info, device);
-   list_del(>scsi_device_list_entry);
pqi_free_device(device);
}
-
-   spin_unlock_irqrestore(_info->scsi_device_list_lock, flags);
 }
 
 static int pqi_scan_scsi_devices(struct pqi_ctrl_info *ctrl_info)



[PATCH V2 00/36] smartpqi updates

2017-05-03 Thread Don Brace
These patches are based on Linus's tree

The changes are:

 - correct remove SCSI devices
   - Remove spin-lock
 - cleanup interrupt management
   - minor cleanup to align with in-house driver
 - set PCI completion timeout 
 - add in controller checkpoint for controller lockups.
   - helps debug rare lockup conditions
 - ensure controller is in SIS mode at driver init
   - needed for kdump/kexec
 - add supporting events
   - manage event changes from controller
 - enhance resets
   - wait for all outstanding I/Os to complete
 - add suspend and resume support
   - Support S3/S4 system power states
 - add heartbeat check
   - add check for controller lockups
 - correct bdma hw bug
   - workaround for BDMA hardware bug 
 - add pqi_wait_for_completion_io
   - add check for controller lockup
 - change functions to inline
   - align code with in-house driver
 - make pdev pointer names consistent
   - align code with in-house driver
 - eliminate redundant error messages
 - correct BMIC identify physical drive
 - minor driver cleanup
   - align code with in-house driver
 - add new PCI device IDs
 - cleanup messages
 - update copyright
 - add ptraid support
   - RBOD support
 - change return value for LUN reset operations
 - enhance kdump
 - remove qdepth calculations for logical volumes
 - add lockup action
 - correct AIO error path
   - send commands down RAID path when they fail
 on AIO path
 - update device offline
   - improve off-lined device detection.
 - update rescan worker
 - cleanup controller branding
   - make more generic
 - map more raid errors to SCSI errors
   - map RAID path errors to Linux SCSI errors
 - update timeout on admin commands
 - enhance device add and remove messages
 - make AIO references consistent
 - add raid level show sysfs entry
 - cleanup list initialization
 - add module parameters
   - heat-beat and controller management
 - remove writeq/readq function definitions
   - from Corentin Labbe 
 - bump driver version

Changes since V1
 - Changes requested by Bart Van Assche 
   - removed unnecessary change in patch smartpqi-cleanup-interrupt-management
   - simplified function sis_is_kernel_up function in
 smartpqi-ensure-controller-in-sis-mode-during-init
   - removed patch smartpqi-change-functions-to-inline
   - provide patch description for smartpqi-minor-driver-cleanup
   - change string alignment in smartpqi-cleanup-messages
   - removed a function call in smartpqi-add-ptraid-support.

---

Corentin Labbe (1):
  smartpqi: remove writeq/readq function definitions

Kevin Barnett (35):
  smartpqi: correct remove scsi devices
  smartpqi: cleanup interrupt management
  smartpqi: set pci completion timeout
  smartpqi: add in controller checkpoint for controller lockups.
  smartpqi: ensure controller is in SIS mode at init
  smartpqi: add supporting events
  smartpqi: enhance resets
  smartpqi: add suspend and resume support
  smartpqi: add heartbeat check
  smartpqi: correct bdma hw bug
  smartpqi: add pqi_wait_for_completion_io
  smartpqi: make pdev pointer names consistent
  smartpqi: eliminate redundant error messages
  smartpqi: correct BMIC identify physical drive
  smartpqi: minor driver cleanup
  smartpqi: add new PCI device IDs
  smartpqi: cleanup messages
  smartpqi: update copyright
  smartpqi: add ptraid support
  smartpqi: change return value for LUN reset operations
  smartpqi: enhance kdump
  smartpqi: remove qdepth calculations for logical volumes
  smartpqi: add lockup action
  smartpqi: correct aio error path
  smartpqi: update device offline
  smartpqi: update rescan worker
  smartpqi: cleanup controller branding
  smartpqi: map more raid errors to SCSI errors
  smartpqi: update timeout on admin commands
  smartpqi: enhance device add and remove messages
  smartpqi: make ioaccel references consistent
  smartpqi: add raid level show
  smartpqi: cleanup list initialization
  smartpqi: add module parameters
  smartpqi: bump driver version


 drivers/scsi/smartpqi/smartpqi.h   |  194 +-
 drivers/scsi/smartpqi/smartpqi_init.c  | 2427 ++--
 drivers/scsi/smartpqi/smartpqi_sas_transport.c |2 
 drivers/scsi/smartpqi/smartpqi_sis.c   |  100 +
 drivers/scsi/smartpqi/smartpqi_sis.h   |7 
 5 files changed, 2039 insertions(+), 691 deletions(-)

--
Signature


[GIT PULL] first round of SCSI updates for the 4.11+ merge window

2017-05-03 Thread James Bottomley
This update includes the usual round of major driver updates (hisi_sas,
ufs, fnic, cxlflash, be2iscsi, ipr, stex).  There's also the usual
amount of cosmetic and spelling stuff.

The major thing you should be aware of is that there's a clash between
a char dev change in the char-misc tree (adding the new cdev_device_add
helper) and the make checking the return value of scsi_device_get()
mandatory (in osd_uld.c).  I was waiting for you to pull Greg's tree,
but since you haven't, here's mine.  Just in case we cross, the
proposed resolution is below (from merging char-misc followed by
scsi/misc).

The patch is available here:

git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git scsi-misc

The short changelog is:

Alexey Khoroshilov (1):
  scsi: mvumi: remove code handling zero scsi_sg_count(scmd) case

Arnd Bergmann (6):
  scsi: pmcraid: use normal copy_from_user
  scsi: pmcraid: fix minor sparse warnings
  scsi: pmcraid: fix endianess sparse annotations
  scsi: pmcraid: use __iomem pointers for ioctl argument
  scsi: advansys: fix uninitialized data access
  scsi: hisi_sas: fix SATA dependency

Bart Van Assche (3):
  scsi: sd_zbc: Remove superfluous assignments
  scsi: Make checking the scsi_device_get() return value mandatory
  scsi: osd_uld: Check scsi_device_get() return value

Brian King (6):
  scsi: ipr: Driver version 2.6.4
  scsi: ipr: Fix SATA EH hang
  scsi: ipr: Error path locking fixes
  scsi: ipr: Fix abort path race condition
  scsi: ipr: Remove redundant initialization
  scsi: ipr: Fix missed EH wakeup

Cathy Avery (2):
  scsi: storvsc: Add support for FC rport.
  scsi: scsi_transport_fc: Add dummy initiator role to rport

Charles (2):
  scsi: stex: Add S6 support
  scsi: stex: Support Pegasus 3 product

Christoph Hellwig (7):
  scsi: sd: Cleanup sd_done sense data handling
  scsi: pmcraid: fix lock imbalance in pmcraid_reset_reload()
  scsi: bfa: remove bfa_module_s madness
  scsi: libsas: allow async aborts
  scsi: csiostor: switch to pci_alloc_irq_vectors
  scsi: be2iscsi: switch to pci_alloc_irq_vectors
  scsi: fnic: switch to pci_alloc_irq_vectors

Colin Ian King (11):
  scsi: qla4xxx: fix spelling mistake: "Tempalate" -> "Template"
  scsi: stex: make S6flag static
  scsi: fcoe: make fcoe_e_d_tov and fcoe_r_a_tov static
  scsi: fusion: fix spelling mistake: "Persistancy" -> "Persistency"
  scsi: BusLogic: fix incorrect spelling of adatper_reset_req
  scsi: aic7xxx: fix order of arguments in function prototype
  scsi: fc: remove redundant check of an unsigned long being less than zero
  scsi: snic: fix spelling mistake: "Cann't" -> "Cannot"
  scsi: qla2xxx: remove some redundant pointer assignments
  scsi: hisi_sas: add missing break in switch statement
  scsi: esas2r: Remove redundant NULL check on buffer

Damien Le Moal (5):
  scsi: sd_zbc: Do not write lock zones for reset
  scsi: sd: sd_zbc: Rename sd_zbc_setup_write_cmnd
  scsi: Improve scsi_get_sense_info_fld
  scsi: sd: Improve sd_completed_bytes
  scsi: sd: Fix function descriptions

Dan Carpenter (1):
  scsi: osd_uld: remove an unneeded NULL check

David Gibson (1):
  scsi: virtio_scsi: Always try to read VPD pages

Dmitry Torokhov (1):
  scsi: remove incorrect __exit markups

Don Brace (2):
  scsi: hpsa: change driver version
  scsi: hpsa: update pci ids

Elena Reshetova (2):
  scsi: libiscsi: qedi: convert iscsi_task.refcount from atomic_t to 
refcount_t
  scsi: libfc: convert fc_fcp_pkt.ref_cnt from atomic_t to refcount_t

Finn Thain (1):
  scsi: mac_esp: Replace bogus memory barrier with spinlock

Hannes Reinecke (13):
  scsi: mpt: Move scsi_remove_host() out of mptscsih_remove_host()
  scsi: sg: reset 'res_in_use' after unlinking reserved array
  scsi: sg: close race condition in sg_remove_sfp_usercontext()
  scsi: sg: use standard lists for sg_requests
  scsi: sg: protect accesses to 'reserved' page array
  scsi: sg: remove 'save_scat_len'
  scsi: sg: disable SET_FORCE_LOW_DMA
  scsi: make asynchronous aborts mandatory
  scsi: make scsi_eh_scmd_add() always succeed
  scsi: make eh_eflags persistent
  scsi: always send command aborts
  scsi: sd: Return SUCCESS in sd_eh_action() after device offline
  scsi: scsi_error: count medium access timeout only once per EH run

Jack Wang (1):
  MAINTAINERS: remove pmchba list for PM8001

Jitendra Bhivare (10):
  scsi: be2iscsi: Update driver version
  scsi: be2iscsi: Update Copyright
  scsi: be2iscsi: Check size before copying ASYNC handle
  scsi: be2iscsi: Remove free_list for ASYNC handles
  scsi: be2iscsi: Use num_cons field in Rx CQE
  scsi: be2iscsi: Increase HDQ default queue size
  scsi: scsi_transport_iscsi: Use flush_work in iscsi_remove_session
  scsi: be2iscsi: Replace 

Re: [PATCH] scsi: lpfc: double lock typo in lpfc_ns_rsp()

2017-05-03 Thread James Smart

On 5/3/2017 2:22 PM, Dan Carpenter wrote:

There is a double lock bug here so this will deadlock instead of
unlocking.

Fixes: 1c5b12f76301 ("Fix implicit logo and RSCN handling for NVMET")
Signed-off-by: Dan Carpenter 

diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c


Yep. looks good

Reviewed-by: James Smart 




[PATCH] scsi: qedf: Cleanup the type of io_log->op

2017-05-03 Thread Dan Carpenter
We store sc_cmd->cmnd[0] which is an unsigned char in io_log->op so
this should also be unsigned char.  The other thing is that this is
displayed in the debugfs:

seq_printf(s, "0x%02x:", io_log->op);

Smatch complains that the formatting won't work for negative values so
changing it to unsigned silences that warning as well.

Signed-off-by: Dan Carpenter 

diff --git a/drivers/scsi/qedf/qedf.h b/drivers/scsi/qedf/qedf.h
index 40aeb6bb96a2..07ee88200e91 100644
--- a/drivers/scsi/qedf/qedf.h
+++ b/drivers/scsi/qedf/qedf.h
@@ -259,7 +259,7 @@ struct qedf_io_log {
uint16_t task_id;
uint32_t port_id; /* Remote port fabric ID */
int lun;
-   char op; /* SCSI CDB */
+   unsigned char op; /* SCSI CDB */
uint8_t lba[4];
unsigned int bufflen; /* SCSI buffer length */
unsigned int sg_count; /* Number of SG elements */


[PATCH] scsi: lpfc: double lock typo in lpfc_ns_rsp()

2017-05-03 Thread Dan Carpenter
There is a double lock bug here so this will deadlock instead of
unlocking.

Fixes: 1c5b12f76301 ("Fix implicit logo and RSCN handling for NVMET")
Signed-off-by: Dan Carpenter 

diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 1487406aea77..c7962dae4dab 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -630,7 +630,7 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf 
*mp, uint8_t fc4_type,
NLP_EVT_DEVICE_RECOVERY);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~NLP_NVMET_RECOV;
-   spin_lock_irq(shost->host_lock);
+   spin_unlock_irq(shost->host_lock);
}
}
 


[bug report] scsi: lpfc: NVME Initiator: Merge into FC discovery

2017-05-03 Thread Dan Carpenter
Hello James Smart,

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

The patch a0f2d3ef374f: "scsi: lpfc: NVME Initiator: Merge into FC
discovery" from Feb 12, 2017, leads to the following Smatch complaint:

drivers/scsi/lpfc/lpfc_ct.c:982 lpfc_cmpl_ct_cmd_gft_id()
 error: we previously assumed 'ndlp' could be null (see line 966)

drivers/scsi/lpfc/lpfc_ct.c
   965  ndlp = lpfc_findnode_did(vport, did);
   966  if (ndlp) {

Check.

   967  /* The bitmask value for FCP and NVME FCP types 
is
   968   * the same because they are 32 bits distant 
from
   969   * each other in word0 and word0.
   970   */
   971  if (fc4_data_0 & LPFC_FC4_TYPE_BITMASK)
   972  ndlp->nlp_fc4_type |= NLP_FC4_FCP;
   973  if (fc4_data_1 &  LPFC_FC4_TYPE_BITMASK)
   974  ndlp->nlp_fc4_type |= NLP_FC4_NVME;
   975  lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
   976   "3064 Setting ndlp %p, DID 
x%06x with "
   977   "FC4 x%08x, Data: x%08x 
x%08x\n",
   978   ndlp, did, ndlp->nlp_fc4_type,
   979   FC_TYPE_FCP, FC_TYPE_NVME);
   980  ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
   981  }
   982  lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
  
Dereferenced inside the function call.

   983  lpfc_issue_els_prli(vport, ndlp, 0);
   984  } else

regards,
dan carpenter


RE: [PATCH 20/37] smartpqi: add ptraid support

2017-05-03 Thread Don Brace
> -Original Message-
> From: Bart Van Assche [mailto:bart.vanass...@sandisk.com]
> Sent: Tuesday, April 25, 2017 3:13 PM
> To: h...@infradead.org; Viswas G ; Gerry
> Morong ; Mahesh Rajashekhara
> ; posw...@suse.com; Scott
> Benesh ; Don Brace
> ; Bader Ali - Saleh
> ; Kevin Barnett
> ; joseph.szczy...@hpe.com; Scott Teel
> ; j...@linux.vnet.ibm.com; Justin Lindley
> ; John Hall 
> Cc: linux-scsi@vger.kernel.org
> Subject: Re: [PATCH 20/37] smartpqi: add ptraid support
> 
> EXTERNAL EMAIL
> 
> 
> On Tue, 2017-04-25 at 14:47 -0500, Don Brace wrote:
> > +static inline bool pqi_is_external_raid_device(struct pqi_scsi_dev
> *device)
> > +{
> > + return device->is_external_raid_device;
> > +}
> 
> The name of this function is almost as long as its implementation. Please drop
> this function definition and inline the function into its callers.
> 
> Thanks,
> 
> Bart.
Done

Thanks,
Don Brace
ESC - Smart Storage
Microsemi Corporation




RE: [PATCH 18/37] smartpqi: cleanup messages

2017-05-03 Thread Don Brace
> -Original Message-
> From: linux-scsi-ow...@vger.kernel.org [mailto:linux-scsi-
> ow...@vger.kernel.org] On Behalf Of Bart Van Assche
> Sent: Tuesday, April 25, 2017 3:11 PM
> To: h...@infradead.org; Viswas G ; Gerry
> Morong ; Mahesh Rajashekhara
> ; posw...@suse.com; Scott
> Benesh ; Don Brace
> ; Bader Ali - Saleh
> ; Kevin Barnett
> ; joseph.szczy...@hpe.com; Scott Teel
> ; j...@linux.vnet.ibm.com; Justin Lindley
> ; John Hall 
> Cc: linux-scsi@vger.kernel.org
> Subject: Re: [PATCH 18/37] smartpqi: cleanup messages
> 
> EXTERNAL EMAIL
> 
> 
> On Tue, 2017-04-25 at 14:47 -0500, Don Brace wrote:
> >   case CISS_LV_ENCRYPTED_IN_NON_ENCRYPTED_CONTROLLER:
> >   status =
> > - "Encrypted volume inaccessible - disabled on ctrl";
> > + "Volume encrypted but encryption disabled on controller";
> >   break;
> 
> This indentation style is confusing. Please don't do this.
> 
> Thanks,
> 
> Bart.

Done

Thanks,
Don Brace
ESC - Smart Storage
Microsemi Corporation




RE: [PATCH 16/37] smartpqi: minor driver cleanup

2017-05-03 Thread Don Brace
> -Original Message-
> From: Bart Van Assche [mailto:bart.vanass...@sandisk.com]
> Sent: Tuesday, April 25, 2017 3:10 PM
> To: h...@infradead.org; Viswas G ; Gerry
> Morong ; Mahesh Rajashekhara
> ; posw...@suse.com; Scott
> Benesh ; Don Brace
> ; Bader Ali - Saleh
> ; Kevin Barnett
> ; joseph.szczy...@hpe.com; Scott Teel
> ; j...@linux.vnet.ibm.com; Justin Lindley
> ; John Hall 
> Cc: linux-scsi@vger.kernel.org
> Subject: Re: [PATCH 16/37] smartpqi: minor driver cleanup
> 
> EXTERNAL EMAIL
> 
> 
> On Tue, 2017-04-25 at 14:47 -0500, Don Brace wrote:
> > From: Kevin Barnett 
> >
> > - align with in-house driver
> 
> This is not an appropriate patch description. A patch description should
> explain what has been changed and also what the purpose is of these
> changes.
> 
> Thanks,
> 
> Bart.

Agreed, added patch description

Thanks,
Don Brace
ESC - Smart Storage
Microsemi Corporation




[PATCH] scsi: qedf: properly update arguments position in function call

2017-05-03 Thread Gustavo A. R. Silva
Properly update the position of the arguments in function call.

Addresses-Coverity-ID: 1402010
Signed-off-by: Gustavo A. R. Silva 
---
 drivers/scsi/qedf/qedf_els.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/qedf/qedf_els.c b/drivers/scsi/qedf/qedf_els.c
index 59f3e5c..107ed2b 100644
--- a/drivers/scsi/qedf/qedf_els.c
+++ b/drivers/scsi/qedf/qedf_els.c
@@ -106,7 +106,7 @@ static int qedf_initiate_els(struct qedf_rport *fcport, 
unsigned int op,
did = fcport->rdata->ids.port_id;
sid = fcport->sid;
 
-   __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, sid, did,
+   __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, did, sid,
   FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
   FC_FC_SEQ_INIT, 0);
 
-- 
2.5.0



RE: [PATCH 12/37] smartpqi: change functions to inline

2017-05-03 Thread Don Brace
> -Original Message-
> From: Bart Van Assche [mailto:bart.vanass...@sandisk.com]
> Sent: Tuesday, April 25, 2017 3:08 PM
> To: h...@infradead.org; Viswas G ; Gerry
> Morong ; Mahesh Rajashekhara
> ; posw...@suse.com; Scott
> Benesh ; Don Brace
> ; Bader Ali - Saleh
> ; Kevin Barnett
> ; joseph.szczy...@hpe.com; Scott Teel
> ; j...@linux.vnet.ibm.com; Justin Lindley
> ; John Hall 
> Cc: linux-scsi@vger.kernel.org
> Subject: Re: [PATCH 12/37] smartpqi: change functions to inline
> 
> EXTERNAL EMAIL
> 
> 
> On Tue, 2017-04-25 at 14:47 -0500, Don Brace wrote:
> > From: Kevin Barnett 
> >
> > Reviewed-by: Scott Benesh 
> > Signed-off-by: Kevin Barnett 
> > Signed-off-by: Don Brace 
> > ---
> >  drivers/scsi/smartpqi/smartpqi_init.c |2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/scsi/smartpqi/smartpqi_init.c
> b/drivers/scsi/smartpqi/smartpqi_init.c
> > index 728db8f..523b730 100644
> > --- a/drivers/scsi/smartpqi/smartpqi_init.c
> > +++ b/drivers/scsi/smartpqi/smartpqi_init.c
> > @@ -432,7 +432,7 @@ static struct pqi_io_request *pqi_alloc_io_request(
> >   return io_request;
> >  }
> >
> > -static void pqi_free_io_request(struct pqi_io_request *io_request)
> > +static inline void pqi_free_io_request(struct pqi_io_request *io_request)
> >  {
> >   atomic_dec(_request->refcount);
> >  }
> 
> A patch description should not only explain what has been changed but also
> why a change has been made. What is the reason that this function has been
> declared inline? Why do you think that the compiler is not smart enough to
> decide on its own to inline this function?
> 
> Thanks,
> 
> Bart.

We could have given a patch description. I'll provide one.

Thanks,
Don Brace
ESC - Smart Storage
Microsemi Corporation




RE: [PATCH 08/37] smartpqi: add suspend and resume support

2017-05-03 Thread Don Brace
> -Original Message-
> On Tue, 2017-04-25 at 14:46 -0500, Don Brace wrote:
> > +static int pqi_device_wait_for_pending_io(struct pqi_ctrl_info *ctrl_info,
> > +   struct pqi_scsi_dev *device)
> > +{
> > +   while (atomic_read(>scsi_cmds_outstanding)) {
> > +   pqi_check_ctrl_health(ctrl_info);
> > +   if (pqi_ctrl_offline(ctrl_info))
> > +   return -ENXIO;
> > +   usleep_range(1000, 2000);
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int pqi_ctrl_wait_for_pending_io(struct pqi_ctrl_info *ctrl_info)
> > +{
> > +   bool io_pending;
> > +   unsigned long flags;
> > +   struct pqi_scsi_dev *device;
> > +
> > +   while (1) {
> > +   io_pending = false;
> > +
> > +   spin_lock_irqsave(_info->scsi_device_list_lock, flags);
> > +   list_for_each_entry(device, _info->scsi_device_list,
> > +   scsi_device_list_entry) {
> > +   if (atomic_read(>scsi_cmds_outstanding)) {
> > +   io_pending = true;
> > +   break;
> > +   }
> > +   }
> > +   spin_unlock_irqrestore(_info->scsi_device_list_lock,
> > +   flags);
> > +
> > +   if (!io_pending)
> > +   break;
> > +
> > +   pqi_check_ctrl_health(ctrl_info);
> > +   if (pqi_ctrl_offline(ctrl_info))
> > +   return -ENXIO;
> > +
> > +   usleep_range(1000, 2000);
> > +   }
> > +
> > +   return 0;
> > +}
> 
> The same comment applies here that applies to the previous patch: please
> use
> scsi_target_block() / scsi_target_unblock() instead of reimplementing these
> functions.
> 
> Thanks,
> 
> Bart.

Our LUN reset functions have to do several PQI-specific things in order to work 
correctly,
which is why we did not use scsi_target_block()/scsi_target_unblock()

Hope this is acceptable

Thanks for your review
Don Brace
ESC - Smart Storage
Microsemi Corporation



RE: [PATCH 07/37] smartpqi: enhance resets

2017-05-03 Thread Don Brace
> -Original Message-
> On Tue, 2017-04-25 at 14:46 -0500, Don Brace wrote:
> > @@ -4655,23 +4860,46 @@ static int pqi_device_reset(struct pqi_ctrl_info
> *ctrl_info,
> >  static int pqi_eh_device_reset_handler(struct scsi_cmnd *scmd)
> >  {
> >   int rc;
> > + struct Scsi_Host *shost;
> >   struct pqi_ctrl_info *ctrl_info;
> >   struct pqi_scsi_dev *device;
> >
> > - ctrl_info = shost_to_hba(scmd->device->host);
> > + shost = scmd->device->host;
> > + ctrl_info = shost_to_hba(shost);
> >   device = scmd->device->hostdata;
> >
> >   dev_err(_info->pci_dev->dev,
> >   "resetting scsi %d:%d:%d:%d\n",
> > - ctrl_info->scsi_host->host_no,
> > - device->bus, device->target, device->lun);
> > + shost->host_no, device->bus, device->target, device->lun);
> >
> > - rc = pqi_device_reset(ctrl_info, device);
> > + pqi_check_ctrl_health(ctrl_info);
> > + if (pqi_ctrl_offline(ctrl_info)) {
> > + rc = FAILED;
> > + goto out;
> > + }
> >
> > + mutex_lock(_info->lun_reset_mutex);
> > +
> > + pqi_ctrl_block_requests(ctrl_info);
> > + pqi_ctrl_wait_until_quiesced(ctrl_info);
> > + pqi_fail_io_queued_for_device(ctrl_info, device);
> > + rc = pqi_wait_until_inbound_queues_empty(ctrl_info);
> > + pqi_device_reset_start(device);
> > + pqi_ctrl_unblock_requests(ctrl_info);
> > +
> > + if (rc)
> > + rc = FAILED;
> > + else
> > + rc = pqi_device_reset(ctrl_info, device);
> > +
> > + pqi_device_reset_done(device);
> > +
> > + mutex_unlock(_info->lun_reset_mutex);
> > +
> > +out:
> >   dev_err(_info->pci_dev->dev,
> >   "reset of scsi %d:%d:%d:%d: %s\n",
> > - ctrl_info->scsi_host->host_no,
> > - device->bus, device->target, device->lun,
> > + shost->host_no, device->bus, device->target, device->lun,
> >   rc == SUCCESS ? "SUCCESS" : "FAILED");
> >
> >   return rc;
> 
> Please use scsi_target_block() / scsi_target_unblock() instead of
> reimplementing
> these functions.
> 
> Thanks,
> 
> Bart.

Our LUN reset functions have to do several PQI-specific things in order to work 
correctly,
which is why we did not use scsi_target_block()/scsi_target_unblock()

Hope this is acceptable

Thanks for your review
Don Brace
ESC - Smart Storage
Microsemi Corporation




Re: [PATCH v2] ibmvscsis: Do not send aborted task response

2017-05-03 Thread Bryant G. Ly

On 5/3/17 11:38 AM, Bryant G. Ly wrote:


Hi Nick,

On 5/2/17 10:43 PM, Nicholas A. Bellinger wrote:


On Tue, 2017-05-02 at 13:54 -0500, Bryant G. Ly wrote:

The driver is sending a response to the actual scsi op that was
aborted by an abort task TM, while LIO is sending a response to
the abort task TM.

ibmvscsis_tgt does not send the response to the client until
release_cmd time. The reason for this was because if we did it
at queue_status time, then the client would be free to reuse the
tag for that command, but we're still using the tag until the
command is released at release_cmd time, so we chose to delay
sending the response until then. That then caused this issue, because
release_cmd is always called, even if queue_status is not.

SCSI spec says that the initiator that sends the abort task
TM NEVER gets a response to the aborted op and with the current
code it will send a response. Thus this fix will remove that response
if the TAS bit is set.

Cc:  # v4.8+
Signed-off-by: Bryant G. Ly 
Reviewed-by: Tyrel Datwyler 
---
  drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 66 
++--

  1 file changed, 45 insertions(+), 21 deletions(-)

Applied, with a small update to the last sentence of the commit log wrt
to 'if ABORTED && !TAS bit is set'.

Thanks Bryant + Tyrel.

So I have been running tests on this patch extensively and it seems 
like after running 2 hrs of consecutive aborts it fails again with the 
same problem of driver sending a response to the actual scsi op.


It looks like when LIO processes the abort and if 
(!__target_check_io_state(se_cmd, se_sess, 0)) then rsp gets set as 
TMR_TASK_DOES_NOT_EXIST.


With that response the CMD_T_ABORTED state is not set, so then the 
ibmvscsis driver still sends that duplicate response.


I think the best solution would be in driver when queue_tm_rsp gets 
called and when the driver builds the response to check for the 
TMR_TASK_DOES_NOT_EXIST and set our own flag.

Then we would also check for that flag, so it would be:

if ((cmd->se_cmd.transport_state & CMD_T_ABORTED && 
!(cmd->se_cmd.transport_state & CMD_T_TAS)) || cmd->flags & 
CMD_ABORTED) {


This will ensure in the CMD_T_ABORTED w/o CMD_T_TAS scenarios are 
handled and the ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST case.


-Bryant



Hi Nick,

You can ignore the email about the patch being broken. The script that was used 
for testing isn't right.

So the patch is working as intended now, where on an abort the client does not 
receive an extra response to the actual scsi op.

Thanks,

Bryant Ly



Re: [scsi-qedf] question about parameter ordering

2017-05-03 Thread Chad Dupuis

On Wed, 3 May 2017, 2:36pm, Randy Dunlap wrote:

> On 05/03/17 11:29, Chad Dupuis wrote:
> > 
> > On Wed, 3 May 2017, 1:58pm, Gustavo A. R. Silva wrote:
> > 
> >>
> >> Hello everybody,
> >>
> >> While looking into Coverity ID 1402011 I ran into the following piece of 
> >> code
> >> at drivers/scsi/qedf/qedf_io.c:2057:
> >>
> >> /* Fill FC header */
> >> fc_hdr = &(tm_req->req_fc_hdr);
> >> sid = fcport->sid;
> >> did = fcport->rdata->ids.port_id;
> >> __fc_fill_fc_hdr(fc_hdr, FC_RCTL_DD_UNSOL_CMD, sid, did,
> >>   FC_TYPE_FCP, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
> >>   FC_FC_SEQ_INIT, 0);
> >>
> >> The issue here is that the position of arguments in the call to
> >> __fc_fill_fc_hdr() function do not match the ordering of the parameters:
> >>
> >> _sid_ is passed to _did_
> >> _did_ is passed to _sid_
> >>
> >> this is the function prototype:
> >>
> >> static inline void __fc_fill_fc_hdr(struct fc_frame_header *fh,
> >>enum fc_rctl r_ctl,
> >>u32 did, u32 sid, enum fc_fh_type type,
> >>u32 f_ctl, u32 parm_offset)
> >>
> >> My question here is if this is intentionala?
> > 
> > This may have been but this code has been superseded by commit  
> > be086e7c53f1fac51eed14523b28f2214b548dd2.B
> 
> what git tree is that in?
> 
> Thanks.
>

Apologies, a couple of stray characters got into the commit ID.  This is 
in mainline:

commit be086e7c53f1fac51eed14523b28f2214b548dd2
Author: Mintz, Yuval 
Date:   Sat Mar 11 18:39:18 2017 +0200

qed*: Utilize Firmware 8.15.3.0
 
> >> In case it is not, I will send a patch to fix it. But first it would be 
> >> great
> >> to hear any comment about it.
> >>
> >> By the way... the same is happening at drivers/scsi/qedf/qedf_els.c:109
> > 
> > May be a bug here so you could send a patch.
> 
> 
> 


Re: [scsi-qedf] question about parameter ordering

2017-05-03 Thread Randy Dunlap
On 05/03/17 11:29, Chad Dupuis wrote:
> 
> On Wed, 3 May 2017, 1:58pm, Gustavo A. R. Silva wrote:
> 
>>
>> Hello everybody,
>>
>> While looking into Coverity ID 1402011 I ran into the following piece of code
>> at drivers/scsi/qedf/qedf_io.c:2057:
>>
>> /* Fill FC header */
>> fc_hdr = &(tm_req->req_fc_hdr);
>> sid = fcport->sid;
>> did = fcport->rdata->ids.port_id;
>> __fc_fill_fc_hdr(fc_hdr, FC_RCTL_DD_UNSOL_CMD, sid, did,
>>   FC_TYPE_FCP, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
>>   FC_FC_SEQ_INIT, 0);
>>
>> The issue here is that the position of arguments in the call to
>> __fc_fill_fc_hdr() function do not match the ordering of the parameters:
>>
>> _sid_ is passed to _did_
>> _did_ is passed to _sid_
>>
>> this is the function prototype:
>>
>> static inline void __fc_fill_fc_hdr(struct fc_frame_header *fh,
>>enum fc_rctl r_ctl,
>>u32 did, u32 sid, enum fc_fh_type type,
>>u32 f_ctl, u32 parm_offset)
>>
>> My question here is if this is intentionala?
> 
> This may have been but this code has been superseded by commit
> be086e7c53f1fac51eed14523b28f2214b548dd2.B

what git tree is that in?

Thanks.

>> In case it is not, I will send a patch to fix it. But first it would be great
>> to hear any comment about it.
>>
>> By the way... the same is happening at drivers/scsi/qedf/qedf_els.c:109
> 
> May be a bug here so you could send a patch.


-- 
~Randy


Re: [scsi-qedf] question about parameter ordering

2017-05-03 Thread Gustavo A. R. Silva

Hi Chad,

Quoting Chad Dupuis :


On Wed, 3 May 2017, 1:58pm, Gustavo A. R. Silva wrote:



Hello everybody,

While looking into Coverity ID 1402011 I ran into the following  
piece of code

at drivers/scsi/qedf/qedf_io.c:2057:

/* Fill FC header */
fc_hdr = &(tm_req->req_fc_hdr);
sid = fcport->sid;
did = fcport->rdata->ids.port_id;
__fc_fill_fc_hdr(fc_hdr, FC_RCTL_DD_UNSOL_CMD, sid, did,
  FC_TYPE_FCP, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
  FC_FC_SEQ_INIT, 0);

The issue here is that the position of arguments in the call to
__fc_fill_fc_hdr() function do not match the ordering of the parameters:

_sid_ is passed to _did_
_did_ is passed to _sid_

this is the function prototype:

static inline void __fc_fill_fc_hdr(struct fc_frame_header *fh,
   enum fc_rctl r_ctl,
   u32 did, u32 sid, enum fc_fh_type type,
   u32 f_ctl, u32 parm_offset)

My question here is if this is intentionala?


This may have been but this code has been superseded by commit
be086e7c53f1fac51eed14523b28f2214b548dd2.B




Oh OK, great.

In case it is not, I will send a patch to fix it. But first it  
would be great

to hear any comment about it.

By the way... the same is happening at drivers/scsi/qedf/qedf_els.c:109


May be a bug here so you could send a patch.



I'll send a patch for this shortly.

Thanks for your comments.
--
Gustavo A. R. Silva








Re: [scsi-qedf] question about parameter ordering

2017-05-03 Thread Chad Dupuis

On Wed, 3 May 2017, 1:58pm, Gustavo A. R. Silva wrote:

> 
> Hello everybody,
> 
> While looking into Coverity ID 1402011 I ran into the following piece of code
> at drivers/scsi/qedf/qedf_io.c:2057:
> 
> /* Fill FC header */
> fc_hdr = &(tm_req->req_fc_hdr);
> sid = fcport->sid;
> did = fcport->rdata->ids.port_id;
> __fc_fill_fc_hdr(fc_hdr, FC_RCTL_DD_UNSOL_CMD, sid, did,
>   FC_TYPE_FCP, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
>   FC_FC_SEQ_INIT, 0);
> 
> The issue here is that the position of arguments in the call to
> __fc_fill_fc_hdr() function do not match the ordering of the parameters:
> 
> _sid_ is passed to _did_
> _did_ is passed to _sid_
> 
> this is the function prototype:
> 
> static inline void __fc_fill_fc_hdr(struct fc_frame_header *fh,
>enum fc_rctl r_ctl,
>u32 did, u32 sid, enum fc_fh_type type,
>u32 f_ctl, u32 parm_offset)
> 
> My question here is if this is intentionala?

This may have been but this code has been superseded by commit  
be086e7c53f1fac51eed14523b28f2214b548dd2.B
> 
> In case it is not, I will send a patch to fix it. But first it would be great
> to hear any comment about it.
> 
> By the way... the same is happening at drivers/scsi/qedf/qedf_els.c:109

May be a bug here so you could send a patch.

> 
> Thank you
> --
> Gustavo A. R. Silva
> 
> 
> 
> 


Re: [PATCH] sd: Ignore sync cache failures when not supported

2017-05-03 Thread Bart Van Assche
On Thu, 2017-03-16 at 17:48 +0100, Thierry Escande wrote:
> -static int sd_sync_cache(struct scsi_disk *sdkp)
> +static int sd_sync_cache(struct scsi_disk *sdkp, int *sense_key)
>  {
>   int retries, res;
>   struct scsi_device *sdp = sdkp->device;

Hello Thierry,

Both in the SCSI spec and in struct scsi_sense_hdr sense keys are declared
as eight bit values. So I would appreciate if the sense_key data type would
be changed from "int" into "u8". Otherwise this patch looks fine to me.

Thanks,

Bart.

[scsi-qedf] question about parameter ordering

2017-05-03 Thread Gustavo A. R. Silva


Hello everybody,

While looking into Coverity ID 1402011 I ran into the following piece  
of code at drivers/scsi/qedf/qedf_io.c:2057:


/* Fill FC header */
fc_hdr = &(tm_req->req_fc_hdr);
sid = fcport->sid;
did = fcport->rdata->ids.port_id;
__fc_fill_fc_hdr(fc_hdr, FC_RCTL_DD_UNSOL_CMD, sid, did,
   FC_TYPE_FCP, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
   FC_FC_SEQ_INIT, 0);

The issue here is that the position of arguments in the call to  
__fc_fill_fc_hdr() function do not match the ordering of the parameters:


_sid_ is passed to _did_
_did_ is passed to _sid_

this is the function prototype:

static inline void __fc_fill_fc_hdr(struct fc_frame_header *fh,
enum fc_rctl r_ctl,
u32 did, u32 sid, enum fc_fh_type type,
u32 f_ctl, u32 parm_offset)

My question here is if this is intentional?

In case it is not, I will send a patch to fix it. But first it would  
be great to hear any comment about it.


By the way... the same is happening at drivers/scsi/qedf/qedf_els.c:109

Thank you
--
Gustavo A. R. Silva






Re: [PATCH RFC] scsi: wait sd probing in manual scan

2017-05-03 Thread Bart Van Assche
On Fri, 2017-04-28 at 15:48 +0800, Peng Tao wrote:
> We have a guest init programe trying to mount a device after doing scsi host 
> scan
> at boot time. Occasionally it fails to find the device when mounting. After 
> digging
> a bit, it seems the root cause is sd async_schedule probing.
> 
> With async probing, there is no guarantee of device readiness when scsi host
> scan finishes. However, users do expect to have a valid way to make sure 
> device
> is usable. Change scsi scan to wait sd probing in manual scan case so that we
> don't leave user with random device state when scsi host scan returns.
> 
> Is this the right way to have such guarantee?

Hello Peng,

Please fix the guest init program such that it waits until the SCSI device
it needs is ready.

Thanks,

Bart.

[PATCH v2] Avoid that scsi_exit_rq() triggers a use-after-free

2017-05-03 Thread Bart Van Assche
Dereferencing shost from scsi_exit_rq() is not safe because the
SCSI host may already have been freed when scsi_exit_rq() is
called. Increasing the shost reference count in scsi_init_rq()
and dropping that reference in scsi_exit_rq() is nontrivial since
scsi_host_dev_release() may sleep and since scsi_exit_rq() may
be called from interrupt context. Since scsi_exit_rq() only needs
a single bit from shost, copy that bit into struct scsi_cmnd.

Reported-by: Scott Bauer 
Fixes: e9c787e65c0c ("scsi: allocate scsi_cmnd structures as part of struct 
request")
Signed-off-by: Bart Van Assche 
Cc: Scott Bauer 
Cc: Christoph Hellwig 
Cc: Jan Kara 
Cc: Hannes Reinecke 
Cc: 
---
 drivers/scsi/scsi_lib.c  | 39 +--
 include/scsi/scsi_cmnd.h |  1 +
 2 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 15c9fe766071..3a5a49e3274a 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -43,23 +43,23 @@ static struct kmem_cache *scsi_sense_isadma_cache;
 static DEFINE_MUTEX(scsi_sense_cache_mutex);
 
 static inline struct kmem_cache *
-scsi_select_sense_cache(struct Scsi_Host *shost)
+scsi_select_sense_cache(bool unchecked_isa_dma)
 {
-   return shost->unchecked_isa_dma ?
-   scsi_sense_isadma_cache : scsi_sense_cache;
+   return unchecked_isa_dma ? scsi_sense_isadma_cache : scsi_sense_cache;
 }
 
-static void scsi_free_sense_buffer(struct Scsi_Host *shost,
-   unsigned char *sense_buffer)
+static void scsi_free_sense_buffer(bool unchecked_isa_dma,
+  unsigned char *sense_buffer)
 {
-   kmem_cache_free(scsi_select_sense_cache(shost), sense_buffer);
+   kmem_cache_free(scsi_select_sense_cache(unchecked_isa_dma),
+   sense_buffer);
 }
 
-static unsigned char *scsi_alloc_sense_buffer(struct Scsi_Host *shost,
+static unsigned char *scsi_alloc_sense_buffer(bool unchecked_isa_dma,
gfp_t gfp_mask, int numa_node)
 {
-   return kmem_cache_alloc_node(scsi_select_sense_cache(shost), gfp_mask,
-   numa_node);
+   return kmem_cache_alloc_node(scsi_select_sense_cache(unchecked_isa_dma),
+gfp_mask, numa_node);
 }
 
 int scsi_init_sense_cache(struct Scsi_Host *shost)
@@ -67,7 +67,7 @@ int scsi_init_sense_cache(struct Scsi_Host *shost)
struct kmem_cache *cache;
int ret = 0;
 
-   cache = scsi_select_sense_cache(shost);
+   cache = scsi_select_sense_cache(shost->unchecked_isa_dma);
if (cache)
return 0;
 
@@ -2004,10 +2004,12 @@ static int scsi_init_request(void *data, struct request 
*rq,
unsigned int numa_node)
 {
struct Scsi_Host *shost = data;
+   const bool unchecked_isa_dma = shost->unchecked_isa_dma;
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
 
-   cmd->sense_buffer =
-   scsi_alloc_sense_buffer(shost, GFP_KERNEL, numa_node);
+   cmd->unchecked_isa_dma = unchecked_isa_dma;
+   cmd->sense_buffer = scsi_alloc_sense_buffer(unchecked_isa_dma,
+   GFP_KERNEL, numa_node);
if (!cmd->sense_buffer)
return -ENOMEM;
cmd->req.sense = cmd->sense_buffer;
@@ -2017,10 +2019,9 @@ static int scsi_init_request(void *data, struct request 
*rq,
 static void scsi_exit_request(void *data, struct request *rq,
unsigned int hctx_idx, unsigned int request_idx)
 {
-   struct Scsi_Host *shost = data;
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
 
-   scsi_free_sense_buffer(shost, cmd->sense_buffer);
+   scsi_free_sense_buffer(cmd->unchecked_isa_dma, cmd->sense_buffer);
 }
 
 static int scsi_map_queues(struct blk_mq_tag_set *set)
@@ -2093,11 +2094,14 @@ EXPORT_SYMBOL_GPL(__scsi_init_queue);
 static int scsi_init_rq(struct request_queue *q, struct request *rq, gfp_t gfp)
 {
struct Scsi_Host *shost = q->rq_alloc_data;
+   const bool unchecked_isa_dma = shost->unchecked_isa_dma;
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
 
memset(cmd, 0, sizeof(*cmd));
 
-   cmd->sense_buffer = scsi_alloc_sense_buffer(shost, gfp, NUMA_NO_NODE);
+   cmd->unchecked_isa_dma = unchecked_isa_dma;
+   cmd->sense_buffer = scsi_alloc_sense_buffer(unchecked_isa_dma, gfp,
+   NUMA_NO_NODE);
if (!cmd->sense_buffer)
goto fail;
cmd->req.sense = cmd->sense_buffer;
@@ -2111,19 +2115,18 @@ static int scsi_init_rq(struct request_queue *q, struct 
request *rq, gfp_t gfp)
return 0;
 
 fail_free_sense:
-   scsi_free_sense_buffer(shost, cmd->sense_buffer);
+   scsi_free_sense_buffer(unchecked_isa_dma, cmd->sense_buffer);
 fail:
 

Re: [PATCH, RFC] MAINTAINERS: update OSD entries

2017-05-03 Thread Benny Halevy
On Wed, May 3, 2017 at 1:08 PM, Boaz Harrosh  wrote:
>
> On 05/02/2017 02:33 PM, Jeff Layton wrote:
> > On Tue, 2017-05-02 at 09:57 +0200, Christoph Hellwig wrote:
> >> The open-osd domain doesn't exist anymore, and mails to the list lead
> >> to really annoying bounced that repeat every day.
> >>
> >> Also the primarydata address for Benny bounces, and while I have a new
> >> one for him he doesn't seem to be maintaining the OSD code any more.
> >>
> >> Which beggs the question:  should we really leave the Supported status
> >> in MAINTAINERS given that the code is barely maintained?
> >>
> >> Signed-off-by: Christoph Hellwig 
> >> ---
> >>  MAINTAINERS | 4 
> >>  1 file changed, 4 deletions(-)
> >>
> >> diff --git a/MAINTAINERS b/MAINTAINERS
> >> index 1bb06c5f7716..28dd83a1d9e2 100644
> >> --- a/MAINTAINERS
> >> +++ b/MAINTAINERS
> >> @@ -9418,10 +9418,6 @@ F:drivers/net/wireless/intersil/orinoco/
> >>
> >>  OSD LIBRARY and FILESYSTEM
> >>  M:  Boaz Harrosh 
> >> -M:  Benny Halevy 
> >> -L:  osd-...@open-osd.org
> >> -W:  http://open-osd.org
> >> -T:  git git://git.open-osd.org/open-osd.git
> >>  S:  Maintained
> >>  F:  drivers/scsi/osd/
> >>  F:  include/scsi/osd_*
> >
> > Hah, you beat me to it! I was going to spin up a patch for this today.
> >
> > Acked-by: Jeff Layton 
>
> Acked-by: Boaz Harrosh 

Acked-by: Benny Halevy 

>
> >
>


Re: [PATCH v2] ibmvscsis: Do not send aborted task response

2017-05-03 Thread Bryant G. Ly

Hi Nick,

On 5/2/17 10:43 PM, Nicholas A. Bellinger wrote:


On Tue, 2017-05-02 at 13:54 -0500, Bryant G. Ly wrote:

The driver is sending a response to the actual scsi op that was
aborted by an abort task TM, while LIO is sending a response to
the abort task TM.

ibmvscsis_tgt does not send the response to the client until
release_cmd time. The reason for this was because if we did it
at queue_status time, then the client would be free to reuse the
tag for that command, but we're still using the tag until the
command is released at release_cmd time, so we chose to delay
sending the response until then. That then caused this issue, because
release_cmd is always called, even if queue_status is not.

SCSI spec says that the initiator that sends the abort task
TM NEVER gets a response to the aborted op and with the current
code it will send a response. Thus this fix will remove that response
if the TAS bit is set.

Cc:  # v4.8+
Signed-off-by: Bryant G. Ly 
Reviewed-by: Tyrel Datwyler 
---
  drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 66 ++--
  1 file changed, 45 insertions(+), 21 deletions(-)

Applied, with a small update to the last sentence of the commit log wrt
to 'if ABORTED && !TAS bit is set'.

Thanks Bryant + Tyrel.


So I have been running tests on this patch extensively and it seems like after 
running 2 hrs of consecutive aborts it fails again with the same problem of 
driver sending a response to the actual scsi op.

It looks like when LIO processes the abort and if 
(!__target_check_io_state(se_cmd, se_sess, 0)) then rsp gets set as 
TMR_TASK_DOES_NOT_EXIST.

With that response the CMD_T_ABORTED state is not set, so then the ibmvscsis 
driver still sends that duplicate response.

I think the best solution would be in driver when queue_tm_rsp gets called and 
when the driver builds the response to check for the TMR_TASK_DOES_NOT_EXIST 
and set our own flag.
Then we would also check for that flag, so it would be:

if ((cmd->se_cmd.transport_state & CMD_T_ABORTED && !(cmd->se_cmd.transport_state & 
CMD_T_TAS)) || cmd->flags & CMD_ABORTED) {

This will ensure in the CMD_T_ABORTED w/o CMD_T_TAS scenarios are handled and 
the ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST case.

-Bryant






[PATCH] scsi: pmcraid: remove redundant check to see if request_size is less than zero

2017-05-03 Thread Colin King
From: Colin Ian King 

The 2nd check to see if request_size is less than zero is redundant
because the first check takes error exit path on this condition. So,
since it is redundant, remove it.

Detected by CoverityScan, CID#146149 ("Logically Dead Code")

Signed-off-by: Colin Ian King 
---
 drivers/scsi/pmcraid.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index a4aadf5f4dc6..1cc814f1505a 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -3770,9 +3770,6 @@ static long pmcraid_ioctl_passthrough(
pmcraid_err("couldn't build passthrough ioadls\n");
goto out_free_cmd;
}
-   } else if (request_size < 0) {
-   rc = -EINVAL;
-   goto out_free_cmd;
}
 
/* If data is being written into the device, copy the data from user
-- 
2.11.0



Re: [PATCH] Avoid that scsi_exit_rq() triggers a use-after-free

2017-05-03 Thread Bart Van Assche
On Wed, 2017-05-03 at 09:54 +0200, Jan Kara wrote:
> Hum, since this didn't quite work out, how about storing that one bit of
> information that scsi_exit_rq() needs from shost inside scsi_cmnd during
> scsi_init_rq()?

Hello Jan,

All what's missing from the patch I posted is a execute_in_process_context()
scsi_host_dev_release() call execute in a context where sleeping is allowed.
What you proposed is something I had considered but that I had not yet tried
to implement because it requires more changes. Anyway, I'll give that approach
a try since it does not require to introduce a new work_struct.

Bart.

Re: [PATCH] Avoid that scsi_exit_rq() triggers a use-after-free

2017-05-03 Thread Bart Van Assche
On Tue, 2017-05-02 at 17:00 -0600, Scott Bauer wrote:
> I've applied this on-top of Jens' For-Linus and re-ran the test. I get the 
> following scheduling
> while atomic BUG() splat:
> 
> [   35.753764] BUG: scheduling while atomic: swapper/0/0/0x0100
> [   35.754333]  [ ... ]
> [   35.765844]  scsi_host_dev_release+0xe7/0x430
> [   35.766155]  [ ... ]
> [   35.769636]  rcu_process_callbacks+0x831/0xfb0

Hello Scott,

Thanks for testing. It's weird that I had not hit this with my own tests.
Anyway, I will post a v2.

Bart.

RE: [PATCH 05/37] smartpqi: ensure controller is in SIS mode at init

2017-05-03 Thread Don Brace
> -Original Message-
> From: Bart Van Assche [mailto:bart.vanass...@sandisk.com]
> Sent: Tuesday, April 25, 2017 2:58 PM
> To: h...@infradead.org; Viswas G ; Gerry
> Morong ; Mahesh Rajashekhara
> ; posw...@suse.com; Scott
> Benesh ; Don Brace
> ; Bader Ali - Saleh
> ; Kevin Barnett
> ; joseph.szczy...@hpe.com; Scott Teel
> ; j...@linux.vnet.ibm.com; Justin Lindley
> ; John Hall 
> Cc: linux-scsi@vger.kernel.org
> Subject: Re: [PATCH 05/37] smartpqi: ensure controller is in SIS mode at init
> 
> EXTERNAL EMAIL
> 
> 
> On Tue, 2017-04-25 at 14:46 -0500, Don Brace wrote:
> > +bool sis_is_kernel_up(struct pqi_ctrl_info *ctrl_info)
> > +{
> > + u32 status;
> > + bool kernel_up;
> > +
> > + status = readl(_info->registers->sis_firmware_status);
> > +
> > + if (status & SIS_CTRL_KERNEL_UP)
> > + kernel_up = true;
> > + else
> > + kernel_up = false;
> > +
> > + return kernel_up;
> > +}
> 
> Since bool is a synonym for the C11 type _Bool, it is not necessary to
> convert explicitly to a truth value. The above code can be simplified into:
> 
> bool sis_is_kernel_up(struct pqi_ctrl_info *ctrl_info)
> {
> return readl(_info->registers->sis_firmware_status) &
> SIS_CTRL_KERNEL_UP;
> }

Done
Thanks for your review

Thanks,
Don Brace
ESC - Smart Storage
Microsemi Corporation




RE: [PATCH 02/37] smartpqi: cleanup interrupt management

2017-05-03 Thread Don Brace
> -Original Message-
> From: Bart Van Assche [mailto:bart.vanass...@sandisk.com]
> Sent: Tuesday, April 25, 2017 2:55 PM
> To: h...@infradead.org; Viswas G ; Gerry
> Morong ; Mahesh Rajashekhara
> ; posw...@suse.com; Scott
> Benesh ; Don Brace
> ; Bader Ali - Saleh
> ; Kevin Barnett
> ; joseph.szczy...@hpe.com; Scott Teel
> ; j...@linux.vnet.ibm.com; Justin Lindley
> ; John Hall 
> Cc: linux-scsi@vger.kernel.org
> Subject: Re: [PATCH 02/37] smartpqi: cleanup interrupt management
> 
> EXTERNAL EMAIL
> 
> 
> On Tue, 2017-04-25 at 14:46 -0500, Don Brace wrote:
> >  static int pqi_request_irqs(struct pqi_ctrl_info *ctrl_info)
> >  {
> > - struct pci_dev *pdev = ctrl_info->pci_dev;
> >   int i;
> >   int rc;
> > + struct pci_dev *pdev = ctrl_info->pci_dev;
> 
> Was this change necessary? If not, please leave it out.
> 
> Thanks,
> 
> Bart.
Done


Re: [PATCH 25/27] block: remove the discard_zeroes_data flag

2017-05-03 Thread Mike Snitzer
On Tue, May 02 2017 at 11:33pm -0400,
Nicholas A. Bellinger  wrote:

> On Tue, 2017-05-02 at 09:23 +0200, h...@lst.de wrote:
> > On Tue, May 02, 2017 at 12:16:13AM -0700, Nicholas A. Bellinger wrote:
> > > Or, another options is use bdev_write_zeroes_sectors() to determine when
> > > dev_attrib->unmap_zeroes_data should be set.
> > 
> > Yes, that in combination with your patch to use bdev_write_zeroes_sectors
> > for zeroing from write same seems like the right fix.
> 
> The larger target/iblock conversion patch looks like post v4.12 material
> at this point, so to avoid breakage wrt to existing LBPRZ behavior, I'll
> plan to push the following patch post -rc1.
> 
> diff --git a/drivers/target/target_core_device.c 
> b/drivers/target/target_core_device.c
> index d2f089c..e7caf78 100644
> --- a/drivers/target/target_core_device.c
> +++ b/drivers/target/target_core_device.c
> @@ -851,7 +851,7 @@ bool target_configure_unmap_from_queue(struct 
> se_dev_attrib *attrib,
> attrib->unmap_granularity = q->limits.discard_granularity / 
> block_size;
> attrib->unmap_granularity_alignment = q->limits.discard_alignment /
> block_size;
> -   attrib->unmap_zeroes_data = 0;
> +   attrib->unmap_zeroes_data = (q->limits.max_write_zeroes_sectors);
> return true;
>  }
>  EXPORT_SYMBOL(target_configure_unmap_from_queue);
> 

Completely a nit but: why the extra parenthesis?


Re: [PATCH, RFC] MAINTAINERS: update OSD entries

2017-05-03 Thread Boaz Harrosh
On 05/02/2017 02:33 PM, Jeff Layton wrote:
> On Tue, 2017-05-02 at 09:57 +0200, Christoph Hellwig wrote:
>> The open-osd domain doesn't exist anymore, and mails to the list lead
>> to really annoying bounced that repeat every day.
>>
>> Also the primarydata address for Benny bounces, and while I have a new
>> one for him he doesn't seem to be maintaining the OSD code any more.
>>
>> Which beggs the question:  should we really leave the Supported status
>> in MAINTAINERS given that the code is barely maintained?
>>
>> Signed-off-by: Christoph Hellwig 
>> ---
>>  MAINTAINERS | 4 
>>  1 file changed, 4 deletions(-)
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 1bb06c5f7716..28dd83a1d9e2 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -9418,10 +9418,6 @@ F:drivers/net/wireless/intersil/orinoco/
>>  
>>  OSD LIBRARY and FILESYSTEM
>>  M:  Boaz Harrosh 
>> -M:  Benny Halevy 
>> -L:  osd-...@open-osd.org
>> -W:  http://open-osd.org
>> -T:  git git://git.open-osd.org/open-osd.git
>>  S:  Maintained
>>  F:  drivers/scsi/osd/
>>  F:  include/scsi/osd_*
> 
> Hah, you beat me to it! I was going to spin up a patch for this today.
> 
> Acked-by: Jeff Layton 

Acked-by: Boaz Harrosh 

> 



Re: [PATCH] Avoid that scsi_exit_rq() triggers a use-after-free

2017-05-03 Thread Jan Kara
On Tue 02-05-17 10:43:30, Bart Van Assche wrote:
> This patch fixes the following KASAN complaint:
> 
> ==
> BUG: KASAN: use-after-free in scsi_exit_rq+0xf3/0x120 at addr 8802b7fedf00
> Read of size 1 by task rcuos/5/53
> CPU: 7 PID: 53 Comm: rcuos/6 Not tainted 4.11.0-rc5+ #13
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5-0 
> ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
> Call Trace:
>  dump_stack+0x63/0x8f
>  kasan_object_err+0x21/0x70
>  kasan_report.part.1+0x231/0x500
>  __asan_report_load1_noabort+0x2e/0x30
>  scsi_exit_rq+0xf3/0x120
>  free_request_size+0x44/0x60
>  mempool_destroy.part.6+0x9b/0x150
>  mempool_destroy+0x13/0x20
>  blk_exit_rl+0x36/0x40
>  blkg_free+0x146/0x200
>  __blkg_release_rcu+0x121/0x220
>  rcu_nocb_kthread+0x61f/0xca0
>  kthread+0x298/0x390
>  ret_from_fork+0x2c/0x40
> Object at 8802b7fedd80, in cache kmalloc-2048 size: 2048
> Allocated:
> PID = 3992
>  save_stack_trace+0x1b/0x20
>  save_stack+0x46/0xd0
>  kasan_kmalloc+0xad/0xe0
>  __kmalloc+0x134/0x220
>  scsi_host_alloc+0x6b/0x11c0
>  0xc101d94a
>  driver_probe_device+0x49e/0xc60
>  __device_attach_driver+0x1d3/0x2a0
>  bus_for_each_drv+0x11a/0x1d0
>  __device_attach+0x1e1/0x2c0
>  device_initial_probe+0x13/0x20
>  bus_probe_device+0x19b/0x240
>  device_add+0x86d/0x1450
>  device_register+0x1a/0x20
>  0xc10270ce
>  0xc1048a62
>  do_one_initcall+0xa7/0x250
>  do_init_module+0x1d0/0x55d
>  load_module+0x7c9f/0x9850
>  SYSC_finit_module+0x189/0x1c0
>  SyS_finit_module+0xe/0x10
>  entry_SYSCALL_64_fastpath+0x1a/0xa9
> Freed:
> PID = 4128
>  save_stack_trace+0x1b/0x20
>  save_stack+0x46/0xd0
>  kasan_slab_free+0x71/0xb0
>  kfree+0x8d/0x1b0
>  scsi_host_dev_release+0x2cb/0x430
>  device_release+0x76/0x1e0
>  kobject_release+0x107/0x370
>  kobject_put+0x56/0xb0
>  put_device+0x17/0x20
>  scsi_host_put+0x15/0x20
>  0xc101fcd7
>  device_release_driver_internal+0x26a/0x4e0
>  device_release_driver+0x12/0x20
>  bus_remove_device+0x2d0/0x590
>  device_del+0x55b/0x920
>  device_unregister+0x1a/0xa0
>  0xc101e0ca
>  0xc102fccc
>  SyS_delete_module+0x334/0x3e0
>  entry_SYSCALL_64_fastpath+0x1a/0xa9
> Memory state around the buggy address:
>  8802b7fede00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>  8802b7fede80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> >8802b7fedf00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>^
>  8802b7fedf80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>  8802b7fee000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> ==
> 
> Reported-by: Scott Bauer 
> Fixes: e9c787e65c0c ("scsi: allocate scsi_cmnd structures as part of struct 
> request")
> Signed-off-by: Bart Van Assche 
> Cc: Scott Bauer 
> Cc: Christoph Hellwig 
> Cc: Jan Kara 
> Cc: Hannes Reinecke 
> Cc: 

Hum, since this didn't quite work out, how about storing that one bit of
information that scsi_exit_rq() needs from shost inside scsi_cmnd during
scsi_init_rq()?

Honza

> ---
>  drivers/scsi/scsi_lib.c | 8 +++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
> index 15c9fe766071..d698364df072 100644
> --- a/drivers/scsi/scsi_lib.c
> +++ b/drivers/scsi/scsi_lib.c
> @@ -2095,11 +2095,14 @@ static int scsi_init_rq(struct request_queue *q, 
> struct request *rq, gfp_t gfp)
>   struct Scsi_Host *shost = q->rq_alloc_data;
>   struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
>  
> + if (!scsi_host_get(shost))
> + goto fail;
> +
>   memset(cmd, 0, sizeof(*cmd));
>  
>   cmd->sense_buffer = scsi_alloc_sense_buffer(shost, gfp, NUMA_NO_NODE);
>   if (!cmd->sense_buffer)
> - goto fail;
> + goto put;
>   cmd->req.sense = cmd->sense_buffer;
>  
>   if (scsi_host_get_prot(shost) >= SHOST_DIX_TYPE0_PROTECTION) {
> @@ -2112,6 +2115,8 @@ static int scsi_init_rq(struct request_queue *q, struct 
> request *rq, gfp_t gfp)
>  
>  fail_free_sense:
>   scsi_free_sense_buffer(shost, cmd->sense_buffer);
> +put:
> + scsi_host_put(shost);
>  fail:
>   return -ENOMEM;
>  }
> @@ -2124,6 +2129,7 @@ static void scsi_exit_rq(struct request_queue *q, 
> struct request *rq)
>   if (cmd->prot_sdb)
>   kmem_cache_free(scsi_sdb_cache, cmd->prot_sdb);
>   scsi_free_sense_buffer(shost, cmd->sense_buffer);
> + scsi_host_put(shost);
>  }
>  
>  struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
> -- 
> 2.12.2
> 
-- 
Jan Kara 
SUSE Labs, CR


Re:

2017-05-03 Thread H.A
With profound love in my heart, I Kindly Oblige your interest to very important 
proposal.. It is Truly Divine and require your utmost attention..

S hlubokou láskou v mém srdci, Laskave jsem prinutit svuj zájem k návrhu .. Je 
velmi duležité, skutecne Divine a vyžadují vaši nejvyšší pozornost.

  Kontaktujte me prímo pres: helenarobert...@gmail.com pro úplné 
podrobnosti.complete.


HELINA .A ROBERTS

---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus



[PATCH 1/3] target: Fix compare_and_write_callback handling for non GOOD status

2017-05-03 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

Following the bugfix for handling non SAM_STAT_GOOD COMPARE_AND_WRITE
status during COMMIT phase in commit 9b2792c3da1, the same bug exists
for the READ phase as well.

This would manifest first as a lost SCSI response, and eventual
hung task during fabric driver logout or re-login, as existing
shutdown logic waited for the COMPARE_AND_WRITE se_cmd->cmd_kref
to reach zero.

To address this bug, compare_and_write_callback() has been changed
to set post_ret = 1 and return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE
as necessary to signal failure status.

Reported-by: Bill Borsari 
Cc: Bill Borsari 
Tested-by: Gary Guo 
Cc: Gary Guo 
Signed-off-by: Nicholas Bellinger 
---
 drivers/target/target_core_sbc.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index f9250b3..a0ad618 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -507,8 +507,11 @@ static sense_reason_t compare_and_write_callback(struct 
se_cmd *cmd, bool succes
 * been failed with a non-zero SCSI status.
 */
if (cmd->scsi_status) {
-   pr_err("compare_and_write_callback: non zero scsi_status:"
+   pr_debug("compare_and_write_callback: non zero scsi_status:"
" 0x%02x\n", cmd->scsi_status);
+   *post_ret = 1;
+   if (cmd->scsi_status == SAM_STAT_CHECK_CONDITION)
+   ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
goto out;
}
 
-- 
1.9.1



[PATCH 3/3] target: Don't force session reset if queue_depth does not change

2017-05-03 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

Keeping in the idempotent nature of target_core_fabric_configfs.c,
if a queue_depth value is set and it's the same as the existing
value, don't attempt to force session reinstatement.

Reported-by: Raghu Krishnamurthy 
Cc: Raghu Krishnamurthy 
Tested-by: Gary Guo 
Cc: Gary Guo 
Signed-off-by: Nicholas Bellinger 
---
 drivers/target/target_core_tpg.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
index dfaef4d..310d9e5 100644
--- a/drivers/target/target_core_tpg.c
+++ b/drivers/target/target_core_tpg.c
@@ -398,6 +398,13 @@ int core_tpg_set_initiator_node_queue_depth(
struct se_portal_group *tpg = acl->se_tpg;
 
/*
+* Allow the setting of se_node_acl queue_depth to be idempotent,
+* and not force a session shutdown event if the value is not
+* changing.
+*/
+   if (acl->queue_depth == queue_depth)
+   return 0;
+   /*
 * User has requested to change the queue depth for a Initiator Node.
 * Change the value in the Node's struct se_node_acl, and call
 * target_set_nacl_queue_depth() to set the new queue depth.
-- 
1.9.1



[PATCH 2/3] iscsi-target: Set session_fall_back_to_erl0 when forcing reinstatement

2017-05-03 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

While testing modification of per se_node_acl queue_depth forcing
session reinstatement via lio_target_nacl_cmdsn_depth_store() ->
core_tpg_set_initiator_node_queue_depth(), a hung task bug triggered
when changing cmdsn_depth invoked session reinstatement while an iscsi
login was already waiting for session reinstatement to complete.

This can happen when an outstanding se_cmd descriptor is taking a
long time to complete, and session reinstatement from iscsi login
or cmdsn_depth change occurs concurrently.

To address this bug, explicitly set session_fall_back_to_erl0 = 1
when forcing session reinstatement, so session reinstatement is
not attempted if an active session is already being shutdown.

This patch has been tested with two scenarios.  The first when
iscsi login is blocked waiting for iscsi session reinstatement
to complete followed by queue_depth change via configfs, and
second when queue_depth change via configfs us blocked followed
by a iscsi login driven session reinstatement.

Note this patch depends on commit d36ad77f702 to handle multiple
sessions per se_node_acl when changing cmdsn_depth, and for
pre v4.5 kernels will need to be included for stable as well.

Reported-by: Gary Guo 
Tested-by: Gary Guo 
Cc: Gary Guo 
Signed-off-by: Nicholas Bellinger 
---
 drivers/target/iscsi/iscsi_target.c  | 1 +
 drivers/target/iscsi/iscsi_target_configfs.c | 1 +
 drivers/target/iscsi/iscsi_target_login.c| 1 +
 3 files changed, 3 insertions(+)

diff --git a/drivers/target/iscsi/iscsi_target.c 
b/drivers/target/iscsi/iscsi_target.c
index 0f7ade0..26a9bcd 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -4663,6 +4663,7 @@ int iscsit_release_sessions_for_tpg(struct 
iscsi_portal_group *tpg, int force)
continue;
}
atomic_set(>session_reinstatement, 1);
+   atomic_set(>session_fall_back_to_erl0, 1);
spin_unlock(>conn_lock);
 
list_move_tail(_sess->sess_list, _list);
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c 
b/drivers/target/iscsi/iscsi_target_configfs.c
index 344e844..96d9c73 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -1528,6 +1528,7 @@ static void lio_tpg_close_session(struct se_session 
*se_sess)
return;
}
atomic_set(>session_reinstatement, 1);
+   atomic_set(>session_fall_back_to_erl0, 1);
spin_unlock(>conn_lock);
 
iscsit_stop_time2retain_timer(sess);
diff --git a/drivers/target/iscsi/iscsi_target_login.c 
b/drivers/target/iscsi/iscsi_target_login.c
index ad8f301..6623847 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -208,6 +208,7 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn 
*conn)
initiatorname_param->value) &&
   (sess_p->sess_ops->SessionType == sessiontype))) {
atomic_set(_p->session_reinstatement, 1);
+   atomic_set(_p->session_fall_back_to_erl0, 1);
spin_unlock(_p->conn_lock);
iscsit_inc_session_usage_count(sess_p);
iscsit_stop_time2retain_timer(sess_p);
-- 
1.9.1



[PATCH 0/3] target: Fixes for v4.12-rc1

2017-05-03 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

Hi all,

Here are a couple of fixes from the last weeks testing while
continuing longevity and scale out workloads on v4.x target code.

This series contains three patches.  The first is to address
a COMPARE_AND_WRITE se_cmd reference leak where the READ phase
hits a non GOOD status, observed with ESX VAAI hosts when
outstanding READ I/O reaches a point where non SAM_STAT_GOOD
status completions start to happen.

The second addresses a hung task bug observed with iscsi-target
ports while explicitly changing the active per se_node_acl
queue_depth via the existing configfs attribute, if a new iscsi
login was already forcing session reinstatement.

And the third to is avoid forcing an session reinstatement if
queue_depth is changed via configfs, but the value itself has
not changed.

The series has been verified on v4.1.y by DATERA Q/A and
automation teams.

Thank you,

--nab

Nicholas Bellinger (3):
  target: Fix compare_and_write_callback handling for non GOOD status
  iscsi-target: Set session_fall_back_to_erl0 when forcing reinstatement
  target: Don't force session reset if queue_depth does not change

 drivers/target/iscsi/iscsi_target.c  | 1 +
 drivers/target/iscsi/iscsi_target_configfs.c | 1 +
 drivers/target/iscsi/iscsi_target_login.c| 1 +
 drivers/target/target_core_sbc.c | 5 -
 drivers/target/target_core_tpg.c | 7 +++
 5 files changed, 14 insertions(+), 1 deletion(-)

-- 
1.9.1