[PATCH 1/3] documentation/scsi: Remove nodisconnect parameter

2016-08-26 Thread Finn Thain
The driver that used the 'nodisconnect' parameter was removed in
commit 565bae6a4a8f ("[SCSI] 53c7xx: kill driver"). Related documentation
was cleaned up in commit f37a7238d379 ("[SCSI] 53c7xx: fix removal
fallout"), except for the remaining two mentions that are removed here.

Signed-off-by: Finn Thain 

---
 Documentation/kernel-parameters.txt|2 --
 Documentation/scsi/scsi-parameters.txt |2 --
 2 files changed, 4 deletions(-)

Index: linux/Documentation/kernel-parameters.txt
===
--- linux.orig/Documentation/kernel-parameters.txt  2016-08-27 
12:29:57.0 +1000
+++ linux/Documentation/kernel-parameters.txt   2016-08-27 12:29:57.0 
+1000
@@ -2543,8 +2543,6 @@ bytes respectively. Such letter suffixes
 
nodelayacct [KNL] Disable per-task delay accounting
 
-   nodisconnect[HW,SCSI,M68K] Disables SCSI disconnects.
-
nodsp   [SH] Disable hardware DSP at boot time.
 
noefi   Disable EFI runtime services support.
Index: linux/Documentation/scsi/scsi-parameters.txt
===
--- linux.orig/Documentation/scsi/scsi-parameters.txt   2016-08-27 
12:29:57.0 +1000
+++ linux/Documentation/scsi/scsi-parameters.txt2016-08-27 
12:29:57.0 +1000
@@ -79,8 +79,6 @@ parameters may be changed at runtime by
 
ncr53c8xx=  [HW,SCSI]
 
-   nodisconnect[HW,SCSI,M68K] Disables SCSI disconnects.
-
osst=   [HW,SCSI] SCSI Tape Driver
Format: ,
See also Documentation/scsi/st.txt.


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


[PATCH 0/3] Small fixes and cleanup

2016-08-26 Thread Finn Thain

Miscellaneous small patches for an interrupt latency issue,
a compiler warning and a documentation cleanup.

---
 Documentation/kernel-parameters.txt|2 --
 Documentation/scsi/scsi-parameters.txt |2 --
 drivers/scsi/NCR5380.c |   13 +++--
 drivers/scsi/NCR5380.h |8 +++-
 4 files changed, 10 insertions(+), 15 deletions(-)




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


[PATCH 3/3] scsi/ncr5380: Improve interrupt latency during PIO tranfers

2016-08-26 Thread Finn Thain
Large PIO transfers are broken up into chunks to try to avoid disabling
local IRQs for long periods. But IRQs are still disabled for too long
and this causes SCC FIFO overruns during serial port transfers. This
patch fixes the problem by halving the PIO chunk size.

Testing with mac_scsi shows that the extra NCR5380_main() loop iterations
have negligible performance impact on SCSI transfers (about 1% slower).
On a faster system (using the dmx3191d module) transfers showed no
measurable change.

Signed-off-by: Finn Thain 

---
 drivers/scsi/NCR5380.c |6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Index: linux/drivers/scsi/NCR5380.c
===
--- linux.orig/drivers/scsi/NCR5380.c   2016-08-27 12:29:57.0 +1000
+++ linux/drivers/scsi/NCR5380.c2016-08-27 12:29:58.0 +1000
@@ -1847,11 +1847,11 @@ static void NCR5380_information_transfer
/* XXX - need to source or sink 
data here, as appropriate */
}
} else {
-   /* Break up transfer into 3 ms chunks,
-* presuming 6 accesses per handshake.
+   /* Transfer a small chunk so that the
+* irq mode lock is not held too long.
 */
transfersize = min((unsigned 
long)cmd->SCp.this_residual,
-  
hostdata->accesses_per_ms / 2);
+  
hostdata->accesses_per_ms >> 2);
len = transfersize;
NCR5380_transfer_pio(instance, , 
,
 (unsigned char 
**)>SCp.ptr);


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


[PATCH 2/3] scsi/ncr5380: Avoid a compiler warning

2016-08-26 Thread Finn Thain
With commit 3a0f64bfa907 ("mac_scsi: Fix pseudo DMA implementation")
some versions of gcc now warn:

In file included from drivers/scsi/mac_scsi.c:335:
drivers/scsi/NCR5380.h:295: warning: `NCR5380_poll_politely' declared inline 
after being called
drivers/scsi/NCR5380.h:295: warning: previous declaration of 
`NCR5380_poll_politely' was here

Avoid this by defining NCR5380_poll_politely() in NCR5380.h.

Suggested-by: Geert Uytterhoeven 
Signed-off-by: Finn Thain 

---
 drivers/scsi/NCR5380.c |7 ---
 drivers/scsi/NCR5380.h |8 +++-
 2 files changed, 7 insertions(+), 8 deletions(-)

Index: linux/drivers/scsi/NCR5380.c
===
--- linux.orig/drivers/scsi/NCR5380.c   2016-08-27 12:29:57.0 +1000
+++ linux/drivers/scsi/NCR5380.c2016-08-27 12:29:57.0 +1000
@@ -230,13 +230,6 @@ static int NCR5380_poll_politely2(struct
return -ETIMEDOUT;
 }
 
-static inline int NCR5380_poll_politely(struct Scsi_Host *instance,
-int reg, int bit, int val, int wait)
-{
-   return NCR5380_poll_politely2(instance, reg, bit, val,
-   reg, bit, val, wait);
-}
-
 #if NDEBUG
 static struct {
unsigned char mask;
Index: linux/drivers/scsi/NCR5380.h
===
--- linux.orig/drivers/scsi/NCR5380.h   2016-08-27 12:29:57.0 +1000
+++ linux/drivers/scsi/NCR5380.h2016-08-27 12:29:57.0 +1000
@@ -292,8 +292,14 @@ static void NCR5380_reselect(struct Scsi
 static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *, struct scsi_cmnd 
*);
 static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char 
*phase, int *count, unsigned char **data);
 static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char 
*phase, int *count, unsigned char **data);
-static int NCR5380_poll_politely(struct Scsi_Host *, int, int, int, int);
 static int NCR5380_poll_politely2(struct Scsi_Host *, int, int, int, int, int, 
int, int);
 
+static inline int NCR5380_poll_politely(struct Scsi_Host *instance,
+int reg, int bit, int val, int wait)
+{
+   return NCR5380_poll_politely2(instance, reg, bit, val,
+   reg, bit, val, wait);
+}
+
 #endif /* __KERNEL__ */
 #endif /* NCR5380_H */


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


Re: [PATCH 1/2] scsi: sg: Avoid overflow when USER_HZ > HZ

2016-08-26 Thread Douglas Gilbert

On 2016-08-19 06:43 PM, Paul Burton wrote:

Calculating the maximum timeout that a user can set via the
SG_SET_TIMEOUT ioctl involves multiplying INT_MAX by USER_HZ/HZ. If
USER_HZ is larger than HZ then this results in an overflow when
performed as a 32 bit integer calculation, resulting in compiler
warnings such as the following:

  drivers/scsi/sg.c: In function 'sg_ioctl':
  drivers/scsi/sg.c:91:67: warning: integer overflow in expression [-Woverflow]
   #define MULDIV(X,MUL,DIV) X % DIV) * MUL) / DIV) + ((X / DIV) * MUL))
 ^
  drivers/scsi/sg.c:887:14: note: in expansion of macro 'MULDIV'
 if (val >= MULDIV (INT_MAX, USER_HZ, HZ))
^
  drivers/scsi/sg.c:91:67: warning: integer overflow in expression [-Woverflow]
   #define MULDIV(X,MUL,DIV) X % DIV) * MUL) / DIV) + ((X / DIV) * MUL))
 ^
  drivers/scsi/sg.c:888:13: note: in expansion of macro 'MULDIV'
 val = MULDIV (INT_MAX, USER_HZ, HZ);
   ^

Avoid this overflow by performing the (constant) arithmetic on 64 bit
integers, which ensures that overflow from multiplying the 32 bit values
cannot occur. When converting the result back to a 32 bit integer use
min_t to ensure that we don't simply truncate a value beyond INT_MAX to
a 32 bit integer, but instead use INT_MAX where the result was larger
than it. As the values are all compile time constant the 64 bit
arithmetic should have no runtime cost.

Signed-off-by: Paul Burton 


That macro has been changed several times, hopefully this is the final
time.

Acked by: Douglas Gilbert 


---
 drivers/scsi/sg.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index ae7d9bd..bb5ec2d 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -884,8 +884,9 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned 
long arg)
return result;
if (val < 0)
return -EIO;
-   if (val >= MULDIV (INT_MAX, USER_HZ, HZ))
-   val = MULDIV (INT_MAX, USER_HZ, HZ);
+   if (val >= MULDIV((s64)INT_MAX, USER_HZ, HZ))
+   val = min_t(s64, MULDIV((s64)INT_MAX, USER_HZ, HZ),
+   INT_MAX);
sfp->timeout_user = val;
sfp->timeout = MULDIV (val, HZ, USER_HZ);




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


Re: [PATCH 2/2] scsi: sg: Use mult_frac, drop MULDIV macro

2016-08-26 Thread Douglas Gilbert

On 2016-08-19 06:43 PM, Paul Burton wrote:

The MULDIV macro is essentially a duplicate of the more standard
mult_frac macro. Replace use of MULDIV with mult_frac & drop the
duplication.

Signed-off-by: Paul Burton 


I spoke too soon, as this patch changes the last one :-)
As far as I can determine mult_frac() is a cleaner version of
MULDIV(); so

Acked by: Douglas Gilbert 


---
 drivers/scsi/sg.c | 19 ---
 1 file changed, 4 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index bb5ec2d..070332e 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -79,18 +79,7 @@ static void sg_proc_cleanup(void);
  */
 #define SG_MAX_CDB_SIZE 252

-/*
- * Suppose you want to calculate the formula muldiv(x,m,d)=int(x * m / d)
- * Then when using 32 bit integers x * m may overflow during the calculation.
- * Replacing muldiv(x) by muldiv(x)=((x % d) * m) / d + int(x / d) * m
- * calculates the same, but prevents the overflow when both m and d
- * are "small" numbers (like HZ and USER_HZ).
- * Of course an overflow is inavoidable if the result of muldiv doesn't fit
- * in 32 bits.
- */
-#define MULDIV(X,MUL,DIV) X % DIV) * MUL) / DIV) + ((X / DIV) * MUL))
-
-#define SG_DEFAULT_TIMEOUT MULDIV(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)
+#define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ)

 int sg_big_buff = SG_DEF_RESERVED_SIZE;
 /* N.B. This variable is readable and writeable via
@@ -884,11 +873,11 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned 
long arg)
return result;
if (val < 0)
return -EIO;
-   if (val >= MULDIV((s64)INT_MAX, USER_HZ, HZ))
-   val = min_t(s64, MULDIV((s64)INT_MAX, USER_HZ, HZ),
+   if (val >= mult_frac((s64)INT_MAX, USER_HZ, HZ))
+   val = min_t(s64, mult_frac((s64)INT_MAX, USER_HZ, HZ),
INT_MAX);
sfp->timeout_user = val;
-   sfp->timeout = MULDIV (val, HZ, USER_HZ);
+   sfp->timeout = mult_frac(val, HZ, USER_HZ);

return 0;
case SG_GET_TIMEOUT:/* N.B. User receives timeout as return value */



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


[PATCH] Return TCMU-generated sense data to fabric module

2016-08-26 Thread Michael Cyr
If an error status is passed to target_complete_cmd, then by default it
queues the command to target_complete_failure_work, which will generate
Logical Unit Communication Failure sense data, overwriting any sense data
already set in the command.  This means that any sense data returned by
TCMU does not get returned to the fabric module.

This change implements a transport_complete function for target-user which
will set the SCF_TRANSPORT_TASK_SENSE flag if we have valid sense data,
which will cause target_complete_cmd to queue the command to
target_complete_ok_work instead of target_complete_failure_work.

Signed-off-by: Michael Cyr 
Reviewed-by: Andy Grover 
---
 drivers/target/target_core_user.c | 26 +-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/target/target_core_user.c 
b/drivers/target/target_core_user.c
index 62bf4fe..81ab42e 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -158,6 +158,14 @@ static struct genl_family tcmu_genl_family = {
.netnsok = true,
 };
 
+/* Sense Key = 2 (Not Ready)
+ * ASC/ASCQ = 0x0800 (Logical Unit Communication Failure)
+ */
+static const char lu_comm_failure_sense[18] = {
+   0x70, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x0a,
+   0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+   0x00, 0x00 };
+
 static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd)
 {
struct se_device *se_dev = se_cmd->se_dev;
@@ -574,9 +582,11 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, 
struct tcmu_cmd_entry *
pr_warn("TCMU: Userspace set UNKNOWN_OP flag on se_cmd %p\n",
cmd->se_cmd);
entry->rsp.scsi_status = SAM_STAT_CHECK_CONDITION;
+   memcpy(se_cmd->sense_buffer, lu_comm_failure_sense,
+  sizeof(lu_comm_failure_sense));
} else if (entry->rsp.scsi_status == SAM_STAT_CHECK_CONDITION) {
memcpy(se_cmd->sense_buffer, entry->rsp.sense_buffer,
-  se_cmd->scsi_sense_length);
+  TRANSPORT_SENSE_BUFFER);
free_data_area(udev, cmd);
} else if (se_cmd->se_cmd_flags & SCF_BIDI) {
DECLARE_BITMAP(bitmap, DATA_BLOCK_BITS);
@@ -679,6 +689,8 @@ static int tcmu_check_expired_cmd(int id, void *p, void 
*data)
return 0;
 
set_bit(TCMU_CMD_BIT_EXPIRED, >flags);
+   memcpy(cmd->se_cmd->sense_buffer, lu_comm_failure_sense,
+  sizeof(lu_comm_failure_sense));
target_complete_cmd(cmd->se_cmd, SAM_STAT_CHECK_CONDITION);
cmd->se_cmd = NULL;
 
@@ -1145,6 +1157,17 @@ tcmu_parse_cdb(struct se_cmd *cmd)
return passthrough_parse_cdb(cmd, tcmu_pass_op);
 }
 
+static void tcmu_transport_complete(struct se_cmd *cmd, struct scatterlist *sg,
+   unsigned char *sense_buffer)
+{
+   if (cmd->scsi_status == SAM_STAT_CHECK_CONDITION)
+   /* Setting this flag will prevent target_complete_cmd from
+* calling target_complete_failure_work, which would overwrite
+* the sense data we already set.
+*/
+   cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE;
+}
+
 static const struct target_backend_ops tcmu_ops = {
.name   = "user",
.owner  = THIS_MODULE,
@@ -1155,6 +1178,7 @@ static const struct target_backend_ops tcmu_ops = {
.configure_device   = tcmu_configure_device,
.free_device= tcmu_free_device,
.parse_cdb  = tcmu_parse_cdb,
+   .transport_complete = tcmu_transport_complete,
.set_configfs_dev_params = tcmu_set_configfs_dev_params,
.show_configfs_dev_params = tcmu_show_configfs_dev_params,
.get_device_type= sbc_get_device_type,
-- 
2.5.0

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


[PATCH 06/17] smartpqi: change commonly used function to inline

2016-08-26 Thread Don Brace
From: Kevin Barnett 

A tiny tweak to convert a small, commonly used function to inline.

Reviewed-by: Scott Teel 
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 dbc8b40..2656124 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -316,7 +316,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);
 }

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


[PATCH 09/17] smartpqi: correct event acknowledgment timeout issue

2016-08-26 Thread Don Brace
From: Kevin Barnett 

the driver no longer waits for the firmware to consume
the event ack IU.

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

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index 5f965ad..07b6444 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -634,13 +634,6 @@ struct pqi_encryption_info {
 
 #define RAID_MAP_MAX_ENTRIES   1024
 
-#define PQI_RESERVED_IO_SLOTS_LUN_RESET1
-#define PQI_RESERVED_IO_SLOTS_EVENT_ACK1
-#define PQI_RESERVED_IO_SLOTS_SYNCHRONOUS_REQUESTS 3
-#define PQI_RESERVED_IO_SLOTS  \
-   (PQI_RESERVED_IO_SLOTS_LUN_RESET + PQI_RESERVED_IO_SLOTS_EVENT_ACK + \
-   PQI_RESERVED_IO_SLOTS_SYNCHRONOUS_REQUESTS)
-
 #define PQI_PHYSICAL_DEVICE_BUS0
 #define PQI_RAID_VOLUME_BUS1
 #define PQI_HBA_BUS2
@@ -884,6 +877,13 @@ struct pqi_event {
__le32  additional_event_id;
 };
 
+#define PQI_RESERVED_IO_SLOTS_LUN_RESET1
+#define PQI_RESERVED_IO_SLOTS_EVENT_ACK
PQI_NUM_SUPPORTED_EVENTS
+#define PQI_RESERVED_IO_SLOTS_SYNCHRONOUS_REQUESTS 3
+#define PQI_RESERVED_IO_SLOTS  \
+   (PQI_RESERVED_IO_SLOTS_LUN_RESET + PQI_RESERVED_IO_SLOTS_EVENT_ACK + \
+   PQI_RESERVED_IO_SLOTS_SYNCHRONOUS_REQUESTS)
+
 struct pqi_ctrl_info {
unsigned intctrl_id;
struct pci_dev  *pci_dev;
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 6dda9f5..52c752f 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -2642,26 +2642,6 @@ static void pqi_start_event_ack(struct pqi_ctrl_info 
*ctrl_info,
writel(iq_pi, queue_group->iq_pi[RAID_PATH]);
 
spin_unlock_irqrestore(_group->submit_lock[RAID_PATH], flags);
-
-   /*
-* We have to special-case this type of request because the firmware
-* does not generate an interrupt when this type of request completes.
-* Therefore, we have to poll until we see that the firmware has
-* consumed the request before we move on.
-*/
-
-   timeout = (PQI_EVENT_ACK_TIMEOUT * HZ) + jiffies;
-
-   while (1) {
-   if (*queue_group->iq_ci[RAID_PATH] == iq_pi)
-   break;
-   if (time_after(jiffies, timeout)) {
-   dev_err(_info->pci_dev->dev,
-   "completing event acknowledge timed out\n");
-   break;
-   }
-   usleep_range(1000, 2000);
-   }
 }
 
 static void pqi_acknowledge_event(struct pqi_ctrl_info *ctrl_info,

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


[PATCH 11/17] smartpqi: minor tweaks to update time support

2016-08-26 Thread Don Brace
From: Kevin Barnett 

minor tweaks to update time support

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

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 2759c90..a8b8671 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -588,10 +588,6 @@ 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 (!ctrl_info) {
-   printk("%s: NULL controller pointer.\n", __func__);
-   return;
-   }
rc = pqi_write_current_time_to_host_wellness(ctrl_info);
if (rc)
dev_warn(_info->pci_dev->dev,
@@ -602,9 +598,9 @@ static void pqi_update_time_worker(struct work_struct *work)
 }
 
 static inline void pqi_schedule_update_time_worker(
-   struct pqi_ctrl_info *ctrl_info)
+   struct pqi_ctrl_info *ctrl_info)
 {
-   schedule_delayed_work(_info->update_time_work, 120);
+   schedule_delayed_work(_info->update_time_work, 0);
 }
 
 static int pqi_report_luns(struct pqi_ctrl_info *ctrl_info, u8 cmd,

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


[PATCH 15/17] smartpqi: update maintainers

2016-08-26 Thread Don Brace
From: Kevin Barnett 

added Documentation/scsi/smartpqi.txt

Reviewed-by: Kevin Barnett 
Reviewed-by: Scott Benesh 
Signed-off-by: Don Brace 
---
 MAINTAINERS |1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index f50fe50..d980685 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5447,6 +5447,7 @@ F:drivers/scsi/smartpqi/Kconfig
 F: drivers/scsi/smartpqi/Makefile
 F: include/linux/cciss*.h
 F: include/uapi/linux/cciss*.h
+F: Documentation/scsi/smartpqi.txt
 
 HEWLETT-PACKARD SMART ARRAY RAID DRIVER (hpsa)
 M: Don Brace 

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


[PATCH 02/17] smartpqi: change tmf macro names

2016-08-26 Thread Don Brace
From: Kevin Barnett 

small change to make code look cleaner

Reviewed-by: Scott Teel 
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 |4 ++--
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index ea49005..dbcdb03 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -545,10 +545,8 @@ typedef u32 pqi_index_t;
 #define SOP_TASK_ATTRIBUTE_ORDERED 2
 #define SOP_TASK_ATTRIBUTE_ACA 4
 
-#define SOP_TASK_MANAGEMENT_FUNCTION_COMPLETE  0x0
-#define SOP_TASK_MANAGEMENT_FUNCTION_REJECTED  0x4
-#define SOP_TASK_MANAGEMENT_FUNCTION_FAILED0x5
-#define SOP_TASK_MANAGEMENT_FUNCTION_SUCCEEDED 0x8
+#define SOP_TMF_COMPLETE   0x0
+#define SOP_TMF_FUNCTION_SUCCEEDED 0x8
 
 /* additional CDB bytes usage field codes */
 #define SOP_ADDITIONAL_CDB_BYTES_0 0   /* 16-byte CDB */
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 418f636..6eab38e 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -2469,8 +2469,8 @@ static int pqi_interpret_task_management_response(
int rc;
 
switch (response->response_code) {
-   case SOP_TASK_MANAGEMENT_FUNCTION_COMPLETE:
-   case SOP_TASK_MANAGEMENT_FUNCTION_SUCCEEDED:
+   case SOP_TMF_COMPLETE:
+   case SOP_TMF_FUNCTION_SUCCEEDED:
rc = 0;
break;
default:

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


[PATCH 13/17] smartpqi: remove timeout for cache flush operations

2016-08-26 Thread Don Brace
From: Kevin Barnett 

Some cache flush operations can take longer than the
timeout value. Best to not impose a time limit to
handle all cases.

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

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 87eb603..e7d7e99 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -407,7 +407,6 @@ static int pqi_identify_physical_device(struct 
pqi_ctrl_info *ctrl_info,
 }
 
 #define SA_CACHE_FLUSH_BUFFER_LENGTH   4
-#define PQI_FLUSH_CACHE_TIMEOUT(30 * 1000)
 
 static int pqi_flush_cache(struct pqi_ctrl_info *ctrl_info)
 {
@@ -434,7 +433,7 @@ static int pqi_flush_cache(struct pqi_ctrl_info *ctrl_info)
goto out;
 
rc = pqi_submit_raid_request_synchronous(ctrl_info, ,
-   0, NULL, PQI_FLUSH_CACHE_TIMEOUT);
+   0, NULL, NO_TIMEOUT);
 
pqi_pci_unmap(ctrl_info->pci_dev, request.sg_descriptors, 1,
pci_direction);

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


[PATCH 16/17] smartpqi: add smartpqi.txt

2016-08-26 Thread Don Brace
From: Kevin Barnett 

Reviewed-by: Kevin Barnett 
Reviewed-by: Scott Benesh 
Signed-off-by: Don Brace 
---
 Documentation/scsi/smartpqi.txt |   80 +++
 1 file changed, 80 insertions(+)
 create mode 100644 Documentation/scsi/smartpqi.txt

diff --git a/Documentation/scsi/smartpqi.txt b/Documentation/scsi/smartpqi.txt
new file mode 100644
index 000..ab377d9
--- /dev/null
+++ b/Documentation/scsi/smartpqi.txt
@@ -0,0 +1,80 @@
+
+SMARTPQI - Microsemi Smart PQI Driver
+-
+
+This file describes the smartpqi SCSI driver for Microsemi
+(http://www.microsemi.com) PQI controllers. The smartpqi driver
+is the next generation SCSI driver for Microsemi Corp. The smartpqi
+driver is the first SCSI driver to implement the PQI queuing model.
+
+The smartpqi driver will replace the aacraid driver for Adaptec Series 9
+controllers. Customers running an older kernel (Pre-4.9) using an Adaptec
+Series 9 controller will have to configure the smartpqi driver or their
+volumes will not be added to the OS.
+
+For Microsemi smartpqi controller support, enable the smartpqi driver
+when configuring the kernel.
+
+For more information on the PQI Queuing Interface, please see:
+http://www.t10.org/drafts.htm
+http://www.t10.org/members/w_pqi2.htm
+
+Supported devices:
+--
+
+
+smartpqi specific entries in /sys
+-
+
+  smartpqi host attributes:
+  -
+  /sys/class/scsi_host/host*/rescan
+  /sys/class/scsi_host/host*/version
+
+  The host rescan attribute is a write only attribute. Writing to this
+  attribute will trigger the driver to scan for new, changed, or removed
+  devices and notify the SCSI mid-layer of any changes detected.
+
+  The version attribute is read-only and will return the driver version
+  and the controller firmware version.
+  For example:
+  driver: 0.9.13-370
+  firmware: 0.01-522
+
+  smartpqi sas device attributes
+  --
+  HBA devices are added to the SAS transport layer. These attributes are
+  automatically added by the SAS transport layer.
+
+  /sys/class/sas_device/end_device-X:X/sas_address
+  /sys/class/sas_device/end_device-X:X/enclosure_identifier
+  /sys/class/sas_device/end_device-X:X/scsi_target_id
+
+smartpqi specific ioctls:
+-
+
+  For compatibility with applications written for the cciss protocol.
+
+  CCISS_DEREGDISK
+  CCISS_REGNEWDISK
+  CCISS_REGNEWD
+
+  The above three ioctls all do exactly the same thing, which is to cause the 
driver
+  to rescan for new devices.  This does exactly the same thing as writing to 
the
+  smartpqi specific host "rescan" attribute.
+
+  CCISS_GETPCIINFO
+
+   Returns PCI domain, bus, device and function and "board ID" (PCI 
subsystem ID).
+
+  CCISS_GETDRIVVER
+
+   Returns driver version in three bytes encoded as:
+   (DRIVER_MAJOR << 28) | (DRIVER_MINOR << 24) | (DRIVER_RELEASE << 16) | 
DRIVER_REVISION;
+
+  CCISS_PASSTHRU
+
+   Allows "BMIC" and "CISS" commands to be passed through to the Smart 
Storage Array.
+   These are used extensively by the SSA Array Configuration Utility, SNMP 
storage
+   agents, etc.
+

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


[PATCH 17/17] smartqi: bump driver version

2016-08-26 Thread Don Brace
From: Kevin Barnett 

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

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index e7d7e99..3b3c7eb 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -38,11 +38,11 @@
 #define BUILD_TIMESTAMP
 #endif
 
-#define DRIVER_VERSION "0.9.9-100"
+#define DRIVER_VERSION "0.9.13-370"
 #define DRIVER_MAJOR   0
 #define DRIVER_MINOR   9
-#define DRIVER_RELEASE 9
-#define DRIVER_REVISION100
+#define DRIVER_RELEASE 13
+#define DRIVER_REVISION370
 
 #define DRIVER_NAME"Microsemi PQI Driver (v" DRIVER_VERSION ")"
 #define DRIVER_NAME_SHORT  "smartpqi"

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


[PATCH 00/17] smartpqi updates

2016-08-26 Thread Don Brace
These changes are based on Linus's tree

The changes are:
 - simplify aio processing
 - simplify tmf macro names
 - remove workaround for spanning
 - add message for offlined drives
 - enhance reset logic
 - make some functions in-line
 - add support for kdump
 - correct issue with offlined controller
 - change timeout for events
 - reformat function to match svn version
 - correct update time scheduling
 - minor queuecommand cleanup
 - remove timeout on cache flush operation
 - update smartpqi/Kconfig
   - Martin K. Peterson's review
 - updated MAINTAINERS for smartpqi.txt addition
 - add Documentation/scsi/smartpqi.txt
   - Martin K. Peterson's review
 - bump driver version

---

Kevin Barnett (17):
  smartpqi: change aio sg processing
  smartpqi: change tmf macro names
  smartpqi: simplify spanning
  smartpqi: enhance drive offline informational message
  smartpqi: enhance reset logic
  smartpqi: change commonly used function to inline
  smartpqi: add kdump support
  smartpqi: correct controller offline issue
  smartpqi: correct event acknowledgment timeout issue
  smartpqi: minor function reformating
  smartpqi: minor tweaks to update time support
  smartpqi: scsi queuecommand cleanup
  smartpqi: remove timeout for cache flush operations
  smartpqi: update Kconfig
  smartpqi: update maintainers
  smartpqi: add smartpqi.txt
  smartqi: bump driver version


 Documentation/scsi/smartpqi.txt   |   80 
 MAINTAINERS   |1 
 drivers/scsi/smartpqi/Kconfig |8 +
 drivers/scsi/smartpqi/smartpqi.h  |   35 ++--
 drivers/scsi/smartpqi/smartpqi_init.c |  316 -
 drivers/scsi/smartpqi/smartpqi_sis.c  |   10 +
 drivers/scsi/smartpqi/smartpqi_sis.h  |2 
 7 files changed, 274 insertions(+), 178 deletions(-)
 create mode 100644 Documentation/scsi/smartpqi.txt

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


Re: [PATCH -next] ibmvscsis: Use list_move_tail instead of list_del/list_add_tail

2016-08-26 Thread Bryant G. Ly
On 7/22/16, 9:03 AM, "Wei Yongjun"  wrote:

Using list_move_tail() instead of list_del() + list_add_tail().

Signed-off-by: Wei Yongjun 
---
 drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)


Looks good to me.


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


[PATCH 14/17] smartpqi: update Kconfig

2016-08-26 Thread Don Brace
From: Kevin Barnett 

The aacraid driver will not managage Microsemi
smartpqi controllers, but will still manage
older aacraid devices.

Updated help section.

Reviewed-by: Scott Teel 
Reviewed-by: Scott Benesh 
Reviewed-by: Kevin Barnett 
Signed-off-by: Don Brace 
---
 drivers/scsi/smartpqi/Kconfig |8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/smartpqi/Kconfig b/drivers/scsi/smartpqi/Kconfig
index 5d77a80..97e159c 100644
--- a/drivers/scsi/smartpqi/Kconfig
+++ b/drivers/scsi/smartpqi/Kconfig
@@ -37,7 +37,6 @@
 
 config SCSI_SMARTPQI
tristate "Microsemi PQI Driver"
-   default n
depends on PCI && SCSI && !S390
select SCSI_SAS_ATTRS
select RAID_ATTRS
@@ -47,4 +46,9 @@ config SCSI_SMARTPQI

 
To compile this driver as a module, choose M here: the
-   module will be called smartpqi
+   module will be called smartpqi.
+
+Note: the aacraid driver will not manage a smartpqi
+  controller. You need to enable smartpqi for smartpqi
+  controllers. For more information, please see
+  Documentation/scsi/smartpqi.txt

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


[PATCH 03/17] smartpqi: simplify spanning

2016-08-26 Thread Don Brace
From: Kevin Barnett 

Removed the workaround for the transition to spanning.

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

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 6eab38e..9922e31 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -3663,6 +3663,18 @@ static int pqi_validate_device_capability(struct 
pqi_ctrl_info *ctrl_info)
return -EINVAL;
}
 
+   if (!ctrl_info->inbound_spanning_supported) {
+   dev_err(_info->pci_dev->dev,
+   "the controller does not support inbound spanning\n");
+   return -EINVAL;
+   }
+
+   if (ctrl_info->outbound_spanning_supported) {
+   dev_err(_info->pci_dev->dev,
+   "the controller supports outbound spanning but this 
driver does not\n");
+   return -EINVAL;
+   }
+
return 0;
 }
 
@@ -4138,24 +4150,14 @@ static void pqi_calculate_queue_resources(struct 
pqi_ctrl_info *ctrl_info)
 
ctrl_info->num_queue_groups = num_queue_groups;
 
-   if (ctrl_info->max_inbound_iu_length_per_firmware == 256 &&
-   ctrl_info->outbound_spanning_supported) {
-   /*
-* TEMPHACK
-* This is older f/w that doesn't actually support spanning.
-*/
-   ctrl_info->max_inbound_iu_length =
-   PQI_OPERATIONAL_IQ_ELEMENT_LENGTH;
-   } else {
-   /*
-* Make sure that the max. inbound IU length is an even multiple
-* of our inbound element length.
-*/
-   ctrl_info->max_inbound_iu_length =
-   (ctrl_info->max_inbound_iu_length_per_firmware /
-   PQI_OPERATIONAL_IQ_ELEMENT_LENGTH) *
-   PQI_OPERATIONAL_IQ_ELEMENT_LENGTH;
-   }
+   /*
+* Make sure that the max. inbound IU length is an even multiple
+* of our inbound element length.
+*/
+   ctrl_info->max_inbound_iu_length =
+   (ctrl_info->max_inbound_iu_length_per_firmware /
+   PQI_OPERATIONAL_IQ_ELEMENT_LENGTH) *
+   PQI_OPERATIONAL_IQ_ELEMENT_LENGTH;
 
num_elements_per_iq =
(ctrl_info->max_inbound_iu_length /

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


[PATCH 08/17] smartpqi: correct controller offline issue

2016-08-26 Thread Don Brace
From: Kevin Barnett 

Fixed a bug where the driver would not free all of the
controller resources if the controller ever went offline.

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

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 67661de..6dda9f5 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -5609,19 +5609,14 @@ static void pqi_free_ctrl_resources(struct 
pqi_ctrl_info *ctrl_info)
 
 static void pqi_remove_ctrl(struct pqi_ctrl_info *ctrl_info)
 {
-   int rc;
+   cancel_delayed_work_sync(_info->rescan_work);
+   cancel_delayed_work_sync(_info->update_time_work);
+   pqi_remove_all_scsi_devices(ctrl_info);
+   pqi_unregister_scsi(ctrl_info);
 
-   if (ctrl_info->controller_online) {
-   cancel_delayed_work_sync(_info->rescan_work);
-   cancel_delayed_work_sync(_info->update_time_work);
-   pqi_remove_all_scsi_devices(ctrl_info);
-   pqi_unregister_scsi(ctrl_info);
-   ctrl_info->controller_online = false;
-   }
if (ctrl_info->pqi_mode_enabled) {
sis_disable_msix(ctrl_info);
-   rc = pqi_reset(ctrl_info);
-   if (rc == 0)
+   if (pqi_reset(ctrl_info) == 0)
sis_reenable_sis_mode(ctrl_info);
}
pqi_free_ctrl_resources(ctrl_info);

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


[PATCH 04/17] smartpqi: enhance drive offline informational message

2016-08-26 Thread Don Brace
From: Kevin Barnett 

Made a couple of error messages more verbose.

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

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 9922e31..198a7c2 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -2298,11 +2298,16 @@ static inline void pqi_aio_path_disabled(struct 
pqi_io_request *io_request)
 static inline void pqi_take_device_offline(struct scsi_device *sdev)
 {
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 scsi %d:%d:%d:%d\n",
+   ctrl_info->scsi_host->host_no, device->bus,
+   device->target, device->lun);
}
 }
 

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


[PATCH 01/17] smartpqi: change aio sg processing

2016-08-26 Thread Don Brace
From: Kevin Barnett 

Take advantage of controller improvements.

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

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 906f1aa..418f636 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -4263,48 +4263,58 @@ static int pqi_build_aio_sg_list(struct pqi_ctrl_info 
*ctrl_info,
int i;
u16 iu_length;
int sg_count;
-   unsigned int num_sg_in_iu = 0;
+   bool chained;
+   unsigned int num_sg_in_iu;
+   unsigned int max_sg_per_iu;
struct scatterlist *sg;
struct pqi_sg_descriptor *sg_descriptor;
 
sg_count = scsi_dma_map(scmd);
if (sg_count < 0)
return sg_count;
+
+   iu_length = offsetof(struct pqi_aio_path_request, sg_descriptors) -
+   PQI_REQUEST_HEADER_LENGTH;
+   num_sg_in_iu = 0;
+
if (sg_count == 0)
goto out;
 
-   if (sg_count <= ctrl_info->max_sg_per_iu) {
-   sg_descriptor = >sg_descriptors[0];
-   scsi_for_each_sg(scmd, sg, sg_count, i) {
-   pqi_set_sg_descriptor(sg_descriptor, sg);
-   sg_descriptor++;
-   }
-   put_unaligned_le32(CISS_SG_LAST,
-   >sg_descriptors[sg_count - 1].flags);
-   num_sg_in_iu = sg_count;
-   } else {
-   sg_descriptor = >sg_descriptors[0];
-   put_unaligned_le64((u64)io_request->sg_chain_buffer_dma_handle,
-   _descriptor->address);
-   put_unaligned_le32(sg_count * sizeof(*sg_descriptor),
-   _descriptor->length);
-   put_unaligned_le32(CISS_SG_CHAIN, _descriptor->flags);
-
-   sg_descriptor = io_request->sg_chain_buffer;
-   scsi_for_each_sg(scmd, sg, sg_count, i) {
-   pqi_set_sg_descriptor(sg_descriptor, sg);
-   sg_descriptor++;
+   sg = scsi_sglist(scmd);
+   sg_descriptor = request->sg_descriptors;
+   max_sg_per_iu = ctrl_info->max_sg_per_iu - 1;
+   chained = false;
+   i = 0;
+
+   while (1) {
+   pqi_set_sg_descriptor(sg_descriptor, sg);
+   if (!chained)
+   num_sg_in_iu++;
+   i++;
+   if (i == sg_count)
+   break;
+   sg_descriptor++;
+   if (i == max_sg_per_iu) {
+   put_unaligned_le64(
+   (u64)io_request->sg_chain_buffer_dma_handle,
+   _descriptor->address);
+   put_unaligned_le32((sg_count - num_sg_in_iu)
+   * sizeof(*sg_descriptor),
+   _descriptor->length);
+   put_unaligned_le32(CISS_SG_CHAIN,
+   _descriptor->flags);
+   chained = true;
+   num_sg_in_iu++;
+   sg_descriptor = io_request->sg_chain_buffer;
}
-   put_unaligned_le32(CISS_SG_LAST,
-   _request->sg_chain_buffer[sg_count - 1].flags);
-   num_sg_in_iu = 1;
-   request->partial = 1;
+   sg = sg_next(sg);
}
 
-out:
-   iu_length = offsetof(struct pqi_aio_path_request, sg_descriptors) -
-   PQI_REQUEST_HEADER_LENGTH;
+   put_unaligned_le32(CISS_SG_LAST, _descriptor->flags);
+   request->partial = chained;
iu_length += num_sg_in_iu * sizeof(*sg_descriptor);
+
+out:
put_unaligned_le16(iu_length, >header.iu_length);
request->num_sg_descriptors = num_sg_in_iu;
 

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


[PATCH 10/17] smartpqi: minor function reformating

2016-08-26 Thread Don Brace
From: Kevin Barnett 

reformatted pqi_num_elements_free() to match the rest of the driver

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

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 52c752f..2759c90 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -2576,8 +2576,7 @@ static unsigned int pqi_process_io_intr(struct 
pqi_ctrl_info *ctrl_info,
 }
 
 static inline unsigned int pqi_num_elements_free(unsigned int pi,
-   unsigned int ci,
-   unsigned int elements_in_queue)
+   unsigned int ci, unsigned int elements_in_queue)
 {
unsigned int num_elements_used;
 

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


[PATCH 05/17] smartpqi: enhance reset logic

2016-08-26 Thread Don Brace
From: Kevin Barnett 

Eliminated timeout from LUN reset logic.

Reviewed-by: Scott Teel 
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 |  101 +++--
 2 files changed, 35 insertions(+), 68 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index dbcdb03..053be6b 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -370,7 +370,6 @@ struct pqi_task_management_request {
 };
 
 #define SOP_TASK_MANAGEMENT_LUN_RESET  0x8
-#define PQI_ABORT_TIMEOUT_MSECS(20 * 1000)
 
 struct pqi_task_management_response {
struct pqi_iu_header header;
@@ -762,7 +761,6 @@ struct pqi_scsi_dev {
 
struct pqi_sas_port *sas_port;
struct scsi_device *sdev;
-   boolreset_in_progress;
 
struct list_head scsi_device_list_entry;
struct list_head new_device_list_entry;
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 198a7c2..dbc8b40 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -4537,13 +4537,6 @@ static int pqi_scsi_queue_command(struct Scsi_Host 
*shost,
bool raid_bypassed;
 
device = scmd->device->hostdata;
-
-   if (device->reset_in_progress) {
-   set_host_byte(scmd, DID_RESET);
-   pqi_scsi_done(scmd);
-   return 0;
-   }
-
ctrl_info = shost_to_hba(shost);
 
if (pqi_ctrl_offline(ctrl_info)) {
@@ -4585,61 +4578,47 @@ static int pqi_scsi_queue_command(struct Scsi_Host 
*shost,
return rc;
 }
 
-static inline void pqi_complete_queued_requests_queue_group(
-   struct pqi_queue_group *queue_group,
-   struct pqi_scsi_dev *device_in_reset)
+static void pqi_lun_reset_complete(struct pqi_io_request *io_request,
+   void *context)
 {
-   unsigned int path;
-   unsigned long flags;
-   struct pqi_io_request *io_request;
-   struct pqi_io_request *next;
-   struct scsi_cmnd *scmd;
-   struct pqi_scsi_dev *device;
+   struct completion *waiting = context;
 
-   for (path = 0; path < 2; path++) {
-   spin_lock_irqsave(_group->submit_lock[path], flags);
+   complete(waiting);
+}
 
-   list_for_each_entry_safe(io_request, next,
-   _group->request_list[path],
-   request_list_entry) {
-   scmd = io_request->scmd;
-   if (!scmd)
-   continue;
-   device = scmd->device->hostdata;
-   if (device == device_in_reset) {
-   set_host_byte(scmd, DID_RESET);
-   pqi_scsi_done(scmd);
-   list_del(_request->
-   request_list_entry);
-   }
+#define PQI_LUN_RESET_TIMEOUT_SECS 10
+
+static int pqi_wait_for_lun_reset_completion(struct pqi_ctrl_info *ctrl_info,
+   struct pqi_scsi_dev *device, struct completion *wait)
+{
+   int rc;
+   unsigned int wait_secs = 0;
+
+   while (1) {
+   if (wait_for_completion_io_timeout(wait,
+   PQI_LUN_RESET_TIMEOUT_SECS * HZ)) {
+   rc = 0;
+   break;
}
 
-   spin_unlock_irqrestore(_group->submit_lock[path], flags);
-   }
-}
+   pqi_check_ctrl_health(ctrl_info);
+   if (pqi_ctrl_offline(ctrl_info)) {
+   rc = -ETIMEDOUT;
+   break;
+   }
 
-static void pqi_complete_queued_requests(struct pqi_ctrl_info *ctrl_info,
-   struct pqi_scsi_dev *device_in_reset)
-{
-   unsigned int i;
-   struct pqi_queue_group *queue_group;
+   wait_secs += PQI_LUN_RESET_TIMEOUT_SECS;
 
-   for (i = 0; i < ctrl_info->num_queue_groups; i++) {
-   queue_group = _info->queue_groups[i];
-   pqi_complete_queued_requests_queue_group(queue_group,
-   device_in_reset);
+   dev_err(_info->pci_dev->dev,
+   "resetting scsi %d:%d:%d:%d - waiting %u seconds\n",
+   ctrl_info->scsi_host->host_no, device->bus,
+   device->target, device->lun, wait_secs);
}
-}
 
-static void pqi_reset_lun_complete(struct pqi_io_request *io_request,
-   void *context)
-{
-   struct completion *waiting = context;
-
-   complete(waiting);
+   return rc;
 }
 
-static int pqi_reset_lun(struct pqi_ctrl_info *ctrl_info,
+static int pqi_lun_reset(struct pqi_ctrl_info 

[PATCH 12/17] smartpqi: scsi queuecommand cleanup

2016-08-26 Thread Don Brace
From: Kevin Barnett 

minor cleanup of scsi queue command function

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

diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index a8b8671..87eb603 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -4514,7 +4514,7 @@ static int pqi_aio_submit_io(struct pqi_ctrl_info 
*ctrl_info,
 }
 
 static int pqi_scsi_queue_command(struct Scsi_Host *shost,
-   struct scsi_cmnd *scmd)
+   struct scsi_cmnd *scmd)
 {
int rc;
struct pqi_ctrl_info *ctrl_info;
@@ -4532,6 +4532,12 @@ static int pqi_scsi_queue_command(struct Scsi_Host 
*shost,
return 0;
}
 
+   /*
+* This is necessary because the SML doesn't zero out this field during
+* error recovery.
+*/
+   scmd->result = 0;
+
hwq = blk_mq_unique_tag_to_hwq(blk_mq_unique_tag(scmd->request));
if (hwq >= ctrl_info->num_queue_groups)
hwq = 0;

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


[PATCH 07/17] smartpqi: add kdump support

2016-08-26 Thread Don Brace
From: Kevin Barnett 

Reviewed-by: Scott Teel 
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 |   35 +
 drivers/scsi/smartpqi/smartpqi_sis.c  |   10 +
 drivers/scsi/smartpqi/smartpqi_sis.h  |2 ++
 4 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index 053be6b..5f965ad 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -79,11 +79,13 @@ struct pqi_ctrl_registers {
__le32  sis_ctrl_to_host_doorbell;  /* 9Ch */
u8  reserved3[0xa0 - (0x9c + sizeof(__le32))];
__le32  sis_ctrl_to_host_doorbell_clear;/* A0h */
-   u8  reserved4[0xbc - (0xa0 + sizeof(__le32))];
+   u8  reserved4[0xb0 - (0xa0 + sizeof(__le32))];
+   __le32  sis_driver_scratch; /* B0h */
+   u8  reserved5[0xbc - (0xb0 + sizeof(__le32))];
__le32  sis_firmware_status;/* BCh */
-   u8  reserved5[0x1000 - (0xbc + sizeof(__le32))];
+   u8  reserved6[0x1000 - (0xbc + sizeof(__le32))];
__le32  sis_mailbox[8]; /* 1000h */
-   u8  reserved6[0x4000 - (0x1000 + (sizeof(__le32) * 8))];
+   u8  reserved7[0x4000 - (0x1000 + (sizeof(__le32) * 8))];
/*
 * The PQI spec states that the PQI registers should be at
 * offset 0 from the PCIe BAR 0.  However, we can't map
@@ -963,6 +965,11 @@ struct pqi_ctrl_info {
struct semaphore lun_reset_sem;
 };
 
+enum pqi_ctrl_mode {
+   UNKNOWN,
+   PQI_MODE
+};
+
 /*
  * assume worst case: SATA queue depth of 31 minus 4 internal firmware commands
  */
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c 
b/drivers/scsi/smartpqi/smartpqi_init.c
index 2656124..67661de 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -153,6 +153,18 @@ static inline bool pqi_is_hba_lunid(u8 *scsi3addr)
return pqi_scsi3addr_equal(scsi3addr, RAID_CTLR_LUNID);
 }
 
+static inline enum pqi_ctrl_mode pqi_get_ctrl_mode(
+   struct pqi_ctrl_info *ctrl_info)
+{
+   return sis_read_driver_scratch(ctrl_info);
+}
+
+static inline void pqi_save_ctrl_mode(struct pqi_ctrl_info *ctrl_info,
+   enum pqi_ctrl_mode mode)
+{
+   sis_write_driver_scratch(ctrl_info, mode);
+}
+
 #define PQI_RESCAN_WORK_INTERVAL   (10 * HZ)
 
 static inline void pqi_schedule_rescan_worker(struct pqi_ctrl_info *ctrl_info)
@@ -5266,10 +5278,30 @@ out:
return rc;
 }
 
+static int pqi_kdump_init(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);
+   }
+
+   return 0;
+}
+
 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
@@ -5343,6 +5375,7 @@ static int pqi_ctrl_init(struct pqi_ctrl_info *ctrl_info)
 
/* From here on, we are running in PQI mode. */
ctrl_info->pqi_mode_enabled = true;
+   pqi_save_ctrl_mode(ctrl_info, PQI_MODE);
 
rc = pqi_alloc_admin_queues(ctrl_info);
if (rc) {
@@ -5879,6 +5912,8 @@ static void __attribute__((unused)) 
verify_structures(void)
BUILD_BUG_ON(offsetof(struct pqi_ctrl_registers,
sis_ctrl_to_host_doorbell_clear) != 0xa0);
BUILD_BUG_ON(offsetof(struct pqi_ctrl_registers,
+   sis_driver_scratch) != 0xb0);
+   BUILD_BUG_ON(offsetof(struct pqi_ctrl_registers,
sis_firmware_status) != 0xbc);
BUILD_BUG_ON(offsetof(struct pqi_ctrl_registers,
sis_mailbox) != 0x1000);
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c 
b/drivers/scsi/smartpqi/smartpqi_sis.c
index 5d416a8..71408f9 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.c
+++ b/drivers/scsi/smartpqi/smartpqi_sis.c
@@ -376,6 +376,16 @@ int sis_reenable_sis_mode(struct pqi_ctrl_info *ctrl_info)
return rc;
 }
 
+void sis_write_driver_scratch(struct pqi_ctrl_info *ctrl_info, u32 value)
+{
+   writel(value, _info->registers->sis_driver_scratch);
+}
+
+u32 sis_read_driver_scratch(struct pqi_ctrl_info *ctrl_info)
+{
+   return 

Re: [PATCH 00/30] FCoE VN2VN fixes

2016-08-26 Thread Johannes Thumshirn
On Fri, Aug 26, 2016 at 02:01:23PM +0200, Hannes Reinecke wrote:
> Hi all,
> 
> here's a patchset to get VN2VN running on non-DCB fabrics.
> With it it's possible to run FCoE VN2VN over virtio, allowing
> for a fully virtualized FC testbed. Which would make it ideal
> to integrate into Mike's mptest test suite.
> It also irons out some generic issues with the libfc stack,
> like another round for kref handling updates and handling PRLI correctly.
> (The PRLI problems even have a workaround in iPXE, so it's time to do
> something about it ...)
> 
> As usual, comments and reviews are welcome.
> 
> Hannes Reinecke (29):
>   libfc: Revisit kref handling
>   libfc: additional debugging messages
>   libfc: spurious I/O error under high load
>   libfc: Do not login if the port is already started
>   libfc: use configured lport R_A_TOV when sending
>   libfc: use configured e_d_tov for remote port state
>   libfc: do not overwrite DID_TIME_OUT status
>   libfc: use error code for fc_rport_error()
>   libfc: Send LS_RJT responses on frame allocation
>   libfc: don't advance state machine for incoming FLOGI
>   libfc: Fixup disc_mutex handling
>   libfc: Do not drop down to FLOGI for fc_rport_login()
>   libfc: Implement RTV responder
>   libfc: Rework PRLI handling
>   libfc: Return LS_RJT_BUSY for PRLI in status PLOGI
>   libfc: Clarify ramp-down messages
>   libfc: sanitize E_D_TOV and R_A_TOV setting
>   libfc: safeguard against invalid exchange index
>   libfc: quarantine timed out xids
>   libfc: don't fail sequence abort for completed
>   libfc: Do not drop out-of-order frames
>   libfc: reset timeout on queue full
>   libfc: wait for E_D_TOV when out-of-order sequence is received
>   fcoe: set default TC priority
>   fcoe: inhibit writing invalid values into the 'enabled'
>   fcoe: correct sending FIP VLAN packets on VLAN 0
>   fcoe: FIP debugging
>   fcoe: filter out frames from invalid vlans

I _think_ I already reviewed them (at least I do have a deja-vu when I
read 'Revisit kref handling')

> 
> Wei Yongjun (1):
>   fcoe: Use kfree_skb() instead of kfree()

This one is already in Linus' tree as commit
ea0a95d7f162bfa1c9df74471f0064f71cdf80ea.


-- 
Johannes Thumshirn  Storage
jthumsh...@suse.de+49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 01/30] libfc: Revisit kref handling

2016-08-26 Thread Johannes Thumshirn
On Fri, Aug 26, 2016 at 02:01:24PM +0200, Hannes Reinecke wrote:
> The kref handling in fc_rport is a mess. This patch updates
> the kref handling according to the following rules:
> 
> - Take a reference whenever scheduling a workqueue
> - Take a reference whenever an ELS command is send
> - Drop the reference at the end of the workqueue function
> - Drop the reference at the end of handling ELS replies
> - Take a reference when allocating an rport
> - Drop the reference when removing an rport
> 
> Signed-off-by: Hannes Reinecke 
> ---

Acked-by: Johannes Thumshirn 

-- 
Johannes Thumshirn  Storage
jthumsh...@suse.de+49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 3/3] be2iscsi: Add missing unlock for mbox_lock

2016-08-26 Thread Johannes Thumshirn
On Fri, Aug 26, 2016 at 03:09:08PM +0530, Jitendra Bhivare wrote:
> Julia pointed out beiscsi_boot_get_sinfo does not unlock
> mbox_lock on nonemb_cmd memory allocation failure.
> 
> Signed-off-by: Jitendra Bhivare 
> ---

Reviewed-by: Johannes Thumshirn 

-- 
Johannes Thumshirn  Storage
jthumsh...@suse.de+49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 2/3] be2iscsi: Remove redundant iscsi_wrb desc memset

2016-08-26 Thread Johannes Thumshirn
On Fri, Aug 26, 2016 at 03:09:07PM +0530, Jitendra Bhivare wrote:
> alloc_wrb_handle already does memset zero of iscsi_wrb descriptor so
> remove redundant memset in WRB submission paths.
> 
> Add pwrb_handle NULL check before memsett'ing pwrb.
> 
> Signed-off-by: Jitendra Bhivare 
> ---
Reviewed-by: Johannes Thumshirn 

-- 
Johannes Thumshirn  Storage
jthumsh...@suse.de+49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/3] be2iscsi: Fix error return code

2016-08-26 Thread Johannes Thumshirn
On Fri, Aug 26, 2016 at 03:09:06PM +0530, Jitendra Bhivare wrote:
> From: Christophe JAILLET 
> 
> We know that 'ret' is not an error code because it has been tested a few
> lines above.
> So, if one of these function fails, 0 will be returned instead of an error
> code.
> Return -ENOMEM instead.
> 
> Signed-off-by: Christophe JAILLET 
> 
> 'ret' needs to be set with error code if hba_setup_cid_tbls fails.
> 
> Signed-off-by: Jitendra Bhivare 
> ---

Reviewed-by: Johannes Thumshirn 

-- 
Johannes Thumshirn  Storage
jthumsh...@suse.de+49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 14/30] libfc: Rework PRLI handling

2016-08-26 Thread Hannes Reinecke
PRLI is only required if the port is acting as an initiator; ports
which support target functionality only do not need to send PRLI.
At the same time the PRLI state is only used if the port initiated
a PRLI transfer; if we received a PRLI request we should _not_
change the state as this would cause our PRLI response to be dropped.
And when we receive a PRLI response we need to check if an image
pair has been established; if not the remote port cannot act as a
target for us and we need to disable target functionality.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_rport.c | 62 +--
 1 file changed, 42 insertions(+), 20 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index a76f29d..69c93c7 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1120,7 +1120,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct 
fc_frame *fp,
u32 roles = FC_RPORT_ROLE_UNKNOWN;
u32 fcp_parm = 0;
u8 op;
-   u8 resp_code = 0;
+   enum fc_els_spp_resp resp_code;
 
mutex_lock(>rp_mutex);
 
@@ -1149,8 +1149,8 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct 
fc_frame *fp,
goto out;
 
resp_code = (pp->spp.spp_flags & FC_SPP_RESP_MASK);
-   FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x\n",
-pp->spp.spp_flags);
+   FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x spp_type 0x%x\n",
+pp->spp.spp_flags, pp->spp.spp_type);
rdata->spp_type = pp->spp.spp_type;
if (resp_code != FC_SPP_RESP_ACK) {
if (resp_code == FC_SPP_RESP_CONF)
@@ -1168,13 +1168,28 @@ static void fc_rport_prli_resp(struct fc_seq *sp, 
struct fc_frame *fp,
if (fcp_parm & FCP_SPPF_CONF_COMPL)
rdata->flags |= FC_RP_FLAGS_CONF_REQ;
 
-   prov = fc_passive_prov[FC_TYPE_FCP];
+   /*
+* Call prli provider if we should act as a target
+*/
+   prov = fc_passive_prov[rdata->spp_type];
if (prov) {
memset(_spp, 0, sizeof(temp_spp));
-   prov->prli(rdata, pp->prli.prli_spp_len,
-  >spp, _spp);
+   resp_code = prov->prli(rdata, pp->prli.prli_spp_len,
+  >spp, _spp);
+   } else {
+   memcpy(_spp, >spp, sizeof(temp_spp));
+   }
+   /*
+* Check if the image pair could be established
+*/
+   if (rdata->spp_type != FC_TYPE_FCP ||
+   resp_code != FC_SPP_RESP_ACK ||
+   !(temp_spp.spp_flags & FC_SPP_EST_IMG_PAIR)) {
+   /*
+* Nope; we can't use this port as a target.
+*/
+   fcp_parm &= ~FCP_SPPF_TARG_FCN;
}
-
rdata->supported_classes = FC_COS_CLASS3;
if (fcp_parm & FCP_SPPF_INIT_FCN)
roles |= FC_RPORT_ROLE_FCP_INITIATOR;
@@ -1226,6 +1241,15 @@ static void fc_rport_enter_prli(struct fc_rport_priv 
*rdata)
return;
}
 
+   /*
+* And if the local port does not support the initiator function
+* there's no need to send a PRLI, either.
+*/
+   if (!(lport->service_params & FCP_SPPF_INIT_FCN)) {
+   fc_rport_enter_ready(rdata);
+   return;
+   }
+
FC_RPORT_DBG(rdata, "Port entered PRLI state from %s state\n",
 fc_rport_state(rdata));
 
@@ -1913,7 +1937,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv 
*rdata,
unsigned int len;
unsigned int plen;
enum fc_els_spp_resp resp;
-   enum fc_els_spp_resp passive;
struct fc_seq_els_data rjt_data;
struct fc4_prov *prov;
 
@@ -1963,15 +1986,21 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv 
*rdata,
resp = 0;
 
if (rspp->spp_type < FC_FC4_PROV_SIZE) {
+   enum fc_els_spp_resp active = 0, passive = 0;
+
prov = fc_active_prov[rspp->spp_type];
if (prov)
-   resp = prov->prli(rdata, plen, rspp, spp);
+   active = prov->prli(rdata, plen, rspp, spp);
prov = fc_passive_prov[rspp->spp_type];
-   if (prov) {
+   if (prov)
passive = prov->prli(rdata, plen, rspp, spp);
-   if (!resp || passive == FC_SPP_RESP_ACK)
-   resp = passive;
-   }
+  

[PATCH 09/30] libfc: Send LS_RJT responses on frame allocation

2016-08-26 Thread Hannes Reinecke
When we fail to allocate a frame we should be sending an LS_RJT
response and not just silently drop the frame altogether.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_rport.c | 27 +++
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 29a51c6..f9b6f59 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -926,8 +926,12 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
}
 
fp = fc_frame_alloc(lport, sizeof(*flp));
-   if (!fp)
-   goto out;
+   if (!fp) {
+   mutex_unlock(>rp_mutex);
+   rjt_data.reason = ELS_RJT_UNAB;
+   rjt_data.explan = ELS_EXPL_INSUF_RES;
+   goto reject_put;
+   }
 
fc_flogi_fill(lport, fp);
flp = fc_frame_payload_get(fp, sizeof(*flp));
@@ -940,7 +944,7 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
fc_rport_enter_plogi(rdata);
else
fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT);
-out:
+
mutex_unlock(>rp_mutex);
kref_put(>kref, lport->tt.rport_destroy);
fc_frame_free(rx_fp);
@@ -1503,8 +1507,12 @@ static void fc_rport_recv_adisc_req(struct fc_rport_priv 
*rdata,
}
 
fp = fc_frame_alloc(lport, sizeof(*adisc));
-   if (!fp)
+   if (!fp) {
+   rjt_data.reason = ELS_RJT_UNAB;
+   rjt_data.explan = ELS_EXPL_INSUF_RES;
+   lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, _data);
goto drop;
+   }
fc_adisc_fill(lport, fp);
adisc = fc_frame_payload_get(fp, sizeof(*adisc));
adisc->adisc_cmd = ELS_LS_ACC;
@@ -1812,14 +1820,17 @@ static void fc_rport_recv_plogi_req(struct fc_lport 
*lport,
 * Send LS_ACC.  If this fails, the originator should retry.
 */
fp = fc_frame_alloc(lport, sizeof(*pl));
-   if (!fp)
-   goto out;
-
+   if (!fp) {
+   mutex_unlock(>rp_mutex);
+   rjt_data.reason = ELS_RJT_UNAB;
+   rjt_data.explan = ELS_EXPL_INSUF_RES;
+   goto reject;
+   }
fc_plogi_fill(lport, fp, ELS_LS_ACC);
fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);
lport->tt.frame_send(lport, fp);
fc_rport_enter_prli(rdata);
-out:
+
mutex_unlock(>rp_mutex);
fc_frame_free(rx_fp);
return;
-- 
1.8.5.6

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


[PATCH 12/30] libfc: Do not drop down to FLOGI for fc_rport_login()

2016-08-26 Thread Hannes Reinecke
When fc_rport_login() is called while the rport is not
in RPORT_ST_INIT, RPORT_ST_READY, or RPORT_ST_DELETE
login is already in progress and there's no need to
drop down to FLOGI; doing so will only confuse the
other side.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_rport.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index fa716f5..d392d45 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -437,10 +437,14 @@ static int fc_rport_login(struct fc_rport_priv *rdata)
case RPORT_ST_DELETE:
FC_RPORT_DBG(rdata, "Restart deleted port\n");
break;
-   default:
+   case RPORT_ST_INIT:
FC_RPORT_DBG(rdata, "Login to port\n");
fc_rport_enter_flogi(rdata);
break;
+   default:
+   FC_RPORT_DBG(rdata, "Login in progress, state %s\n",
+fc_rport_state(rdata));
+   break;
}
mutex_unlock(>rp_mutex);
 
-- 
1.8.5.6

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


[PATCH 23/30] libfc: wait for E_D_TOV when out-of-order sequence is received

2016-08-26 Thread Hannes Reinecke
When detecting an out-of-order sequence we should be waiting for
E_D_TOV before trying to abort the sequence.
The response might still be stuck in the queue somewhere.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_fcp.c | 38 --
 1 file changed, 20 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 3e059e4..f087c6e 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -460,6 +460,22 @@ static inline struct fc_frame *fc_fcp_frame_alloc(struct 
fc_lport *lport,
 }
 
 /**
+ * get_fsp_rec_tov() - Helper function to get REC_TOV
+ * @fsp: the FCP packet
+ *
+ * Returns rec tov in jiffies as rpriv->e_d_tov + 1 second
+ */
+static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
+{
+   struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data;
+   unsigned int e_d_tov = FC_DEF_E_D_TOV;
+
+   if (rpriv && rpriv->e_d_tov > e_d_tov)
+   e_d_tov = rpriv->e_d_tov;
+   return msecs_to_jiffies(e_d_tov) + HZ;
+}
+
+/**
  * fc_fcp_recv_data() - Handler for receiving SCSI-FCP data from a target
  * @fsp: The FCP packet the data is on
  * @fp: The data frame
@@ -562,8 +578,10 @@ crc_err:
 * and completes the transfer, call the completion handler.
 */
if (unlikely(fsp->state & FC_SRB_RCV_STATUS) &&
-   fsp->xfer_len == fsp->data_len - fsp->scsi_resid)
+   fsp->xfer_len == fsp->data_len - fsp->scsi_resid) {
+   FC_FCP_DBG( fsp, "complete out-of-order sequence\n" );
fc_fcp_complete_locked(fsp);
+   }
return;
 err:
fc_fcp_recovery(fsp, host_bcode);
@@ -944,7 +962,7 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct 
fc_frame *fp)
   "len %x, data len %x\n",
   fsp->rport->port_id,
   fsp->xfer_len, expected_len, fsp->data_len);
-   fc_fcp_timer_set(fsp, 2);
+   fc_fcp_timer_set(fsp, get_fsp_rec_tov(fsp));
return;
}
fsp->status_code = FC_DATA_OVRRUN;
@@ -1154,22 +1172,6 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, 
struct fc_fcp_pkt *fsp)
 }
 
 /**
- * get_fsp_rec_tov() - Helper function to get REC_TOV
- * @fsp: the FCP packet
- *
- * Returns rec tov in jiffies as rpriv->e_d_tov + 1 second
- */
-static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
-{
-   struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data;
-   unsigned int e_d_tov = FC_DEF_E_D_TOV;
-
-   if (rpriv && rpriv->e_d_tov > e_d_tov)
-   e_d_tov = rpriv->e_d_tov;
-   return msecs_to_jiffies(e_d_tov) + HZ;
-}
-
-/**
  * fc_fcp_cmd_send() - Send a FCP command
  * @lport: The local port to send the command on
  * @fsp:   The FCP packet the command is on
-- 
1.8.5.6

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


[PATCH 13/30] libfc: Implement RTV responder

2016-08-26 Thread Hannes Reinecke
The libfc stack generates an RTV request, so we should be implementing
an RTV responder, too.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_rport.c | 41 -
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index d392d45..a76f29d 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1258,7 +1258,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv 
*rdata)
 }
 
 /**
- * fc_rport_els_rtv_resp() - Handler for Request Timeout Value (RTV) responses
+ * fc_rport_rtv_resp() - Handler for Request Timeout Value (RTV) responses
  * @sp:   The sequence the RTV was on
  * @fp:   The RTV response frame
  * @rdata_arg: The remote port that sent the RTV response
@@ -1358,6 +1358,41 @@ static void fc_rport_enter_rtv(struct fc_rport_priv 
*rdata)
 }
 
 /**
+ * fc_rport_recv_rtv_req() - Handler for Read Timeout Value (RTV) requests
+ * @rdata: The remote port that sent the RTV request
+ * @in_fp: The RTV request frame
+ *
+ * Locking Note:  Called with the lport and rport locks held.
+ */
+static void fc_rport_recv_rtv_req(struct fc_rport_priv *rdata,
+ struct fc_frame *in_fp)
+{
+   struct fc_lport *lport = rdata->local_port;
+   struct fc_frame *fp;
+   struct fc_els_rtv_acc *rtv;
+   struct fc_seq_els_data rjt_data;
+
+   FC_RPORT_DBG(rdata, "Received RTV request\n");
+
+   fp = fc_frame_alloc(lport, sizeof(*rtv));
+   if (!fp) {
+   rjt_data.reason = ELS_RJT_UNAB;
+   rjt_data.reason = ELS_EXPL_INSUF_RES;
+   lport->tt.seq_els_rsp_send(in_fp, ELS_LS_RJT, _data);
+   goto drop;
+   }
+   rtv = fc_frame_payload_get(fp, sizeof(*rtv));
+   rtv->rtv_cmd = ELS_LS_ACC;
+   rtv->rtv_r_a_tov = htonl(lport->r_a_tov);
+   rtv->rtv_e_d_tov = htonl(lport->e_d_tov);
+   rtv->rtv_toq = 0;
+   fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0);
+   lport->tt.frame_send(lport, fp);
+drop:
+   fc_frame_free(in_fp);
+}
+
+/**
  * fc_rport_logo_resp() - Handler for logout (LOGO) responses
  * @sp:   The sequence the LOGO was on
  * @fp:   The LOGO response frame
@@ -1662,6 +1697,9 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, 
struct fc_frame *fp)
case ELS_RLS:
fc_rport_recv_rls_req(rdata, fp);
break;
+   case ELS_RTV:
+   fc_rport_recv_rtv_req(rdata, fp);
+   break;
default:
fc_frame_free(fp);  /* can't happen */
break;
@@ -1713,6 +1751,7 @@ static void fc_rport_recv_req(struct fc_lport *lport, 
struct fc_frame *fp)
case ELS_RRQ:
case ELS_REC:
case ELS_RLS:
+   case ELS_RTV:
fc_rport_recv_els_req(lport, fp);
break;
default:
-- 
1.8.5.6

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


[PATCH 26/30] fcoe: inhibit writing invalid values into the 'enabled'

2016-08-26 Thread Hannes Reinecke
The 'enabled' sysfs attribute only accepts the values '0' and '1',
so we should error out any other values.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/fcoe/fcoe_sysfs.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c
index 0675fd1..5bfa2b1 100644
--- a/drivers/scsi/fcoe/fcoe_sysfs.c
+++ b/drivers/scsi/fcoe/fcoe_sysfs.c
@@ -335,16 +335,24 @@ static ssize_t store_ctlr_enabled(struct device *dev,
  const char *buf, size_t count)
 {
struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
+   bool enabled;
int rc;
 
+   if (*buf == '1')
+   enabled = true;
+   else if (*buf == '0')
+   enabled = false;
+   else
+   return -EINVAL;
+
switch (ctlr->enabled) {
case FCOE_CTLR_ENABLED:
-   if (*buf == '1')
+   if (enabled)
return count;
ctlr->enabled = FCOE_CTLR_DISABLED;
break;
case FCOE_CTLR_DISABLED:
-   if (*buf == '0')
+   if (!enabled)
return count;
ctlr->enabled = FCOE_CTLR_ENABLED;
break;
-- 
1.8.5.6

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


[PATCH 20/30] libfc: don't fail sequence abort for completed

2016-08-26 Thread Hannes Reinecke
If a sequence should be aborted the exchange might already
be completed (eg if the response is still queued in the rx
queue), so this shouldn't considered as an error.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_fcp.c | 40 ++--
 1 file changed, 30 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 8694e87..63c821b 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -258,6 +258,17 @@ static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, 
unsigned long delay)
mod_timer(>timer, jiffies + delay);
 }
 
+static void fc_fcp_abort_done(struct fc_fcp_pkt *fsp)
+{
+   fsp->state |= FC_SRB_ABORTED;
+   fsp->state &= ~FC_SRB_ABORT_PENDING;
+
+   if (fsp->wait_for_comp)
+   complete(>tm_done);
+   else
+   fc_fcp_complete_locked(fsp);
+}
+
 /**
  * fc_fcp_send_abort() - Send an abort for exchanges associated with a
  *  fcp_pkt
@@ -265,6 +276,8 @@ static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, 
unsigned long delay)
  */
 static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp)
 {
+   int rc;
+
if (!fsp->seq_ptr)
return -EINVAL;
 
@@ -272,7 +285,16 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp)
put_cpu();
 
fsp->state |= FC_SRB_ABORT_PENDING;
-   return fsp->lp->tt.seq_exch_abort(fsp->seq_ptr, 0);
+   rc = fsp->lp->tt.seq_exch_abort(fsp->seq_ptr, 0);
+   /*
+* ->seq_exch_abort() might return -ENXIO if
+* the sequence is already completed
+*/
+   if (rc == -ENXIO) {
+   fc_fcp_abort_done(fsp);
+   rc = 0;
+   }
+   return rc;
 }
 
 /**
@@ -729,15 +751,8 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, 
struct fc_frame *fp)
ba_done = 0;
}
 
-   if (ba_done) {
-   fsp->state |= FC_SRB_ABORTED;
-   fsp->state &= ~FC_SRB_ABORT_PENDING;
-
-   if (fsp->wait_for_comp)
-   complete(>tm_done);
-   else
-   fc_fcp_complete_locked(fsp);
-   }
+   if (ba_done)
+   fc_fcp_abort_done(fsp);
 }
 
 /**
@@ -1246,6 +1261,11 @@ static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp)
return FAILED;
}
 
+   if (fsp->state & FC_SRB_ABORTED) {
+   FC_FCP_DBG(fsp, "target abort cmd  completed\n");
+   return SUCCESS;
+   }
+
init_completion(>tm_done);
fsp->wait_for_comp = 1;
 
-- 
1.8.5.6

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


[PATCH 21/30] libfc: Do not drop out-of-order frames

2016-08-26 Thread Hannes Reinecke
When receiving packets from the network we cannot guarantee any
frame ordering, so we should be receiving all valid frames and
let the upper layers deal with it.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_exch.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 510f38c..b366bb5 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -1592,9 +1592,6 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, 
struct fc_frame *fp)
if (fc_sof_is_init(sof)) {
sp->ssb_stat |= SSB_ST_RESP;
sp->id = fh->fh_seq_id;
-   } else if (sp->id != fh->fh_seq_id) {
-   atomic_inc(>stats.seq_not_found);
-   goto rel;
}
 
f_ctl = ntoh24(fh->fh_f_ctl);
-- 
1.8.5.6

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


[PATCH 27/30] fcoe: correct sending FIP VLAN packets on VLAN 0

2016-08-26 Thread Hannes Reinecke
The FIP VLAN frame consists of an ethernet header followed
by the FIP VLAN frame, so we need to skip the ethernet header
if we want to check the FIP opcode.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/fcoe/fcoe.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 81e7f99..706de91 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -582,7 +582,8 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct 
sk_buff *skb)
 * Use default VLAN for FIP VLAN discovery protocol
 */
frame = (struct fip_frame *)skb->data;
-   if (frame->fip.fip_op == ntohs(FIP_OP_VLAN) &&
+   if (ntohs(frame->eth.h_proto) == ETH_P_FIP &&
+   ntohs(frame->fip.fip_op) == FIP_OP_VLAN &&
fcoe->realdev != fcoe->netdev)
skb->dev = fcoe->realdev;
else
-- 
1.8.5.6

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


[PATCH 25/30] fcoe: set default TC priority

2016-08-26 Thread Hannes Reinecke
If DCB is not enabled or compiled in we still should be setting
a sane default priority. So put FCoE frames in priority class
'interactive' and FIP frames in priority class 'besteffort'.

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

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 9bd41a3..81e7f99 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -2160,6 +2160,8 @@ static bool fcoe_match(struct net_device *netdev)
  */
 static void fcoe_dcb_create(struct fcoe_interface *fcoe)
 {
+   int ctlr_prio = TC_PRIO_BESTEFFORT;
+   int fcoe_prio = TC_PRIO_INTERACTIVE;
 #ifdef CONFIG_DCB
int dcbx;
u8 fup, up;
@@ -2186,10 +2188,12 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe)
fup = dcb_getapp(netdev, );
}
 
-   fcoe->priority = ffs(up) ? ffs(up) - 1 : 0;
-   ctlr->priority = ffs(fup) ? ffs(fup) - 1 : fcoe->priority;
+   fcoe_prio = ffs(up) ? ffs(up) - 1 : 0;
+   ctlr_prio = ffs(fup) ? ffs(fup) - 1 : fcoe_prio;
}
 #endif
+   fcoe->priority = fcoe_prio;
+   ctlr->priority = ctlr_prio;
 }
 
 enum fcoe_create_link_state {
-- 
1.8.5.6

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


[PATCH 30/30] fcoe: make R_A_TOV and E_D_TOV configurable

2016-08-26 Thread Hannes Reinecke
The user might want to modify the values for R_A_TOV and E_D_TOV,
so add new module parameters 'e_d_tov' and 'r_a_tov' for the
'fcoe' modules and allow to modify them via sysfs attributes.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/fcoe/fcoe.c   | 12 +--
 drivers/scsi/fcoe/fcoe_sysfs.c | 71 ++
 2 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 706de91..cf4adaa 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -63,6 +63,14 @@ unsigned int fcoe_debug_logging;
 module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
 
+unsigned int fcoe_e_d_tov = 2 * 1000;
+module_param_named(e_d_tov, fcoe_e_d_tov, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(e_d_tov, "E_D_TOV in ms, default 2000");
+
+unsigned int fcoe_r_a_tov = 2 * 2 * 1000;
+module_param_named(r_a_tov, fcoe_r_a_tov, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(r_a_tov, "R_A_TOV in ms, default 4000");
+
 static DEFINE_MUTEX(fcoe_config_mutex);
 
 static struct workqueue_struct *fcoe_wq;
@@ -634,8 +642,8 @@ static int fcoe_lport_config(struct fc_lport *lport)
lport->qfull = 0;
lport->max_retry_count = 3;
lport->max_rport_retry_count = 3;
-   lport->e_d_tov = 2 * 1000;  /* FC-FS default */
-   lport->r_a_tov = 2 * 2 * 1000;
+   lport->e_d_tov = fcoe_e_d_tov;
+   lport->r_a_tov = fcoe_r_a_tov;
lport->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
 FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL);
lport->does_npiv = 1;
diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c
index 5bfa2b1..9cf3d56 100644
--- a/drivers/scsi/fcoe/fcoe_sysfs.c
+++ b/drivers/scsi/fcoe/fcoe_sysfs.c
@@ -432,6 +432,75 @@ static FCOE_DEVICE_ATTR(ctlr, fip_vlan_responder, S_IRUGO 
| S_IWUSR,
store_ctlr_fip_resp);
 
 static ssize_t
+fcoe_ctlr_var_store(u32 *var, const char *buf, size_t count)
+{
+   int err;
+   unsigned long v;
+
+   err = kstrtoul(buf, 10, );
+   if (err || v > UINT_MAX)
+   return -EINVAL;
+
+   *var = v;
+
+   return count;
+}
+
+static ssize_t store_ctlr_r_a_tov(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
+   struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+
+   if (ctlr_dev->enabled == FCOE_CTLR_ENABLED)
+   return -EBUSY;
+   if (ctlr_dev->enabled == FCOE_CTLR_DISABLED)
+   return fcoe_ctlr_var_store(>lp->r_a_tov, buf, count);
+   return -ENOTSUPP;
+}
+
+static ssize_t show_ctlr_r_a_tov(struct device *dev,
+struct device_attribute *attr,
+char *buf)
+{
+   struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
+   struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+
+   return sprintf(buf, "%d\n", ctlr->lp->r_a_tov);
+}
+
+static FCOE_DEVICE_ATTR(ctlr, r_a_tov, S_IRUGO | S_IWUSR,
+   show_ctlr_r_a_tov, store_ctlr_r_a_tov);
+
+static ssize_t store_ctlr_e_d_tov(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
+   struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+
+   if (ctlr_dev->enabled == FCOE_CTLR_ENABLED)
+   return -EBUSY;
+   if (ctlr_dev->enabled == FCOE_CTLR_DISABLED)
+   return fcoe_ctlr_var_store(>lp->e_d_tov, buf, count);
+   return -ENOTSUPP;
+}
+
+static ssize_t show_ctlr_e_d_tov(struct device *dev,
+struct device_attribute *attr,
+char *buf)
+{
+   struct fcoe_ctlr_device *ctlr_dev = dev_to_ctlr(dev);
+   struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+
+   return sprintf(buf, "%d\n", ctlr->lp->e_d_tov);
+}
+
+static FCOE_DEVICE_ATTR(ctlr, e_d_tov, S_IRUGO | S_IWUSR,
+   show_ctlr_e_d_tov, store_ctlr_e_d_tov);
+
+static ssize_t
 store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev,
 struct device_attribute *attr,
 const char *buf, size_t count)
@@ -515,6 +584,8 @@ static struct attribute_group fcoe_ctlr_lesb_attr_group = {
 static struct attribute *fcoe_ctlr_attrs[] = {
_attr_fcoe_ctlr_fip_vlan_responder.attr,
_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr,
+   _attr_fcoe_ctlr_r_a_tov.attr,
+   _attr_fcoe_ctlr_e_d_tov.attr,
_attr_fcoe_ctlr_enabled.attr,
_attr_fcoe_ctlr_mode.attr,

[PATCH 03/30] libfc: spurious I/O error under high load

2016-08-26 Thread Hannes Reinecke
If a command times out libfc is sending an REC, which also
might fail (due to frames being lost or something).
If no data has been transferred we can simply retry
the command, but the current code sets a state of FC_ERROR,
which then is being translated into DID_ERROR, resulting
in an I/O error.
So to handle this properly we need to set a separate
state FC_TRANS_RESET and mapping it onto DID_SOFT_RETRY.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_fcp.c | 27 +--
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index bd4bdbf..289c481 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -122,6 +122,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct 
fc_frame *);
 #define FC_HRD_ERROR   9
 #define FC_CRC_ERROR   10
 #define FC_TIMED_OUT   11
+#define FC_TRANS_RESET 12
 
 /*
  * Error recovery timeout values.
@@ -283,7 +284,7 @@ static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp)
  * fc_io_compl() will notify the SCSI-ml that the I/O is done.
  * The SCSI-ml will retry the command.
  */
-static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp)
+static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp, int status_code)
 {
if (fsp->seq_ptr) {
fsp->lp->tt.exch_done(fsp->seq_ptr);
@@ -292,7 +293,7 @@ static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp)
 
fsp->state &= ~FC_SRB_ABORT_PENDING;
fsp->io_status = 0;
-   fsp->status_code = FC_ERROR;
+   fsp->status_code = status_code;
fc_fcp_complete_locked(fsp);
 }
 
@@ -1209,7 +1210,7 @@ static void fc_fcp_error(struct fc_fcp_pkt *fsp, struct 
fc_frame *fp)
return;
 
if (error == -FC_EX_CLOSED) {
-   fc_fcp_retry_cmd(fsp);
+   fc_fcp_retry_cmd(fsp, FC_ERROR);
goto unlock;
}
 
@@ -1522,9 +1523,9 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct 
fc_frame *fp, void *arg)
case ELS_RJT_LOGIC:
case ELS_RJT_UNAB:
FC_FCP_DBG(fsp, "device %x REC reject "
-  "reason %d expl %d\n",
+  "reason %x expl %x xfer_len %zx\n",
   fsp->rport->port_id, rjt->er_reason,
-  rjt->er_explan);
+  rjt->er_explan, fsp->xfer_len);
/*
 * If no data transfer, the command frame got dropped
 * so we just retry.  If data was transferred, we
@@ -1533,10 +1534,11 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct 
fc_frame *fp, void *arg)
 */
if (rjt->er_explan == ELS_EXPL_OXID_RXID &&
fsp->xfer_len == 0) {
-   fc_fcp_retry_cmd(fsp);
+   fsp->state |= FC_SRB_ABORTED;
+   fc_fcp_retry_cmd(fsp, FC_TRANS_RESET);
break;
}
-   fc_fcp_recovery(fsp, FC_ERROR);
+   fc_fcp_recovery(fsp, FC_TRANS_RESET);
break;
}
} else if (opcode == ELS_LS_ACC) {
@@ -1632,7 +1634,7 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, 
struct fc_frame *fp)
case -FC_EX_CLOSED:
FC_FCP_DBG(fsp, "REC %p fid %6.6x exchange closed\n",
   fsp, fsp->rport->port_id);
-   fc_fcp_retry_cmd(fsp);
+   fc_fcp_retry_cmd(fsp, FC_ERROR);
break;
 
default:
@@ -1731,7 +1733,7 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum 
fc_rctl r_ctl, u32 offset)
fc_fcp_pkt_hold(fsp);   /* hold for outstanding SRR */
return;
 retry:
-   fc_fcp_retry_cmd(fsp);
+   fc_fcp_retry_cmd(fsp, FC_TRANS_RESET);
 }
 
 /**
@@ -1803,7 +1805,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, 
struct fc_frame *fp)
FC_FCP_DBG(fsp, "SRR error, exchange closed\n");
/* fall through */
default:
-   fc_fcp_retry_cmd(fsp);
+   fc_fcp_retry_cmd(fsp, FC_ERROR);
break;
}
fc_fcp_unlock_pkt(fsp);
@@ -2016,6 +2018,11 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
   "due to FC_CMD_RESET\n");
sc_cmd->result = (DID_RESET << 16);
break;
+   case FC_TRANS_RESET:
+   FC_FCP_DBG(fsp, "Returning DID_SOFT_ERROR to scsi-ml "
+  "due to FC_TRANS_RESET\n");
+   sc_cmd->result = (DID_SOFT_ERROR << 16);
+   break;
case FC_HRD_ERROR:
FC_FCP_DBG(fsp, "Returning DID_NO_CONNECT to scsi-ml "
   

[PATCH 15/30] libfc: Return LS_RJT_BUSY for PRLI in status PLOGI

2016-08-26 Thread Hannes Reinecke
Occasionally it might happen that we receive a PRLI while we're still
waiting for our PLOGI response. In that case we should return
'busy' LS status instead of 'plogi required' LS status.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_rport.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 69c93c7..68d4c92 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1691,6 +1691,15 @@ static void fc_rport_recv_els_req(struct fc_lport 
*lport, struct fc_frame *fp)
case RPORT_ST_READY:
case RPORT_ST_ADISC:
break;
+   case RPORT_ST_PLOGI:
+   if (fc_frame_payload_op(fp) == ELS_PRLI) {
+   FC_RPORT_DBG(rdata, "Reject ELS PRLI "
+"while in state %s\n",
+fc_rport_state(rdata));
+   mutex_unlock(>rp_mutex);
+   kref_put(>kref, lport->tt.rport_destroy);
+   goto busy;
+   }
default:
FC_RPORT_DBG(rdata,
 "Reject ELS 0x%02x while in state %s\n",
@@ -1738,6 +1747,14 @@ reject:
els_data.explan = ELS_EXPL_PLOGI_REQD;
lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, _data);
fc_frame_free(fp);
+   return;
+
+busy:
+   els_data.reason = ELS_RJT_BUSY;
+   els_data.explan = ELS_EXPL_NONE;
+   lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, _data);
+   fc_frame_free(fp);
+   return;
 }
 
 /**
-- 
1.8.5.6

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


[PATCH 24/30] fcoe: Use kfree_skb() instead of kfree()

2016-08-26 Thread Hannes Reinecke
From: Wei Yongjun 

Use kfree_skb() instead of kfree() to free sk_buff.

Signed-off-by: Wei Yongjun 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/fcoe/fcoe_ctlr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 5eacd33..1dd8a7c 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -2934,7 +2934,7 @@ static int fcoe_ctlr_vlan_recv(struct fcoe_ctlr *fip, 
struct sk_buff *skb)
mutex_unlock(>ctlr_mutex);
 
 drop:
-   kfree(skb);
+   kfree_skb(skb);
return rc;
 }
 
-- 
1.8.5.6

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


[PATCH 01/30] libfc: Revisit kref handling

2016-08-26 Thread Hannes Reinecke
The kref handling in fc_rport is a mess. This patch updates
the kref handling according to the following rules:

- Take a reference whenever scheduling a workqueue
- Take a reference whenever an ELS command is send
- Drop the reference at the end of the workqueue function
- Drop the reference at the end of handling ELS replies
- Take a reference when allocating an rport
- Drop the reference when removing an rport

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_rport.c | 136 --
 1 file changed, 105 insertions(+), 31 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 97aeadd..8909280 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -44,6 +44,19 @@
  * path this potential over-use of the mutex is acceptable.
  */
 
+/*
+ * RPORT REFERENCE COUNTING
+ *
+ * A rport reference should be taken when:
+ * - an rport is allocated
+ * - a workqueue item is scheduled
+ * - an ELS request is send
+ * The reference should be dropped when:
+ * - the workqueue function has finished
+ * - the ELS response is handled
+ * - an rport is removed
+ */
+
 #include 
 #include 
 #include 
@@ -242,6 +255,8 @@ static void fc_rport_state_enter(struct fc_rport_priv 
*rdata,
 /**
  * fc_rport_work() - Handler for remote port events in the rport_event_queue
  * @work: Handle to the remote port being dequeued
+ *
+ * Reference counting: drops kref on return
  */
 static void fc_rport_work(struct work_struct *work)
 {
@@ -272,8 +287,10 @@ static void fc_rport_work(struct work_struct *work)
kref_get(>kref);
mutex_unlock(>rp_mutex);
 
-   if (!rport)
+   if (!rport) {
+   FC_RPORT_DBG(rdata, "No rport!\n");
rport = fc_remote_port_add(lport->host, 0, );
+   }
if (!rport) {
FC_RPORT_DBG(rdata, "Failed to add the rport\n");
lport->tt.rport_logoff(rdata);
@@ -329,7 +346,8 @@ static void fc_rport_work(struct work_struct *work)
FC_RPORT_DBG(rdata, "lld callback ev %d\n", event);
rdata->lld_event_callback(lport, rdata, event);
}
-   cancel_delayed_work_sync(>retry_work);
+   if (cancel_delayed_work_sync(>retry_work))
+   kref_put(>kref, lport->tt.rport_destroy);
 
/*
 * Reset any outstanding exchanges before freeing rport.
@@ -381,6 +399,7 @@ static void fc_rport_work(struct work_struct *work)
mutex_unlock(>rp_mutex);
break;
}
+   kref_put(>kref, lport->tt.rport_destroy);
 }
 
 /**
@@ -431,10 +450,14 @@ static int fc_rport_login(struct fc_rport_priv *rdata)
  * Set the new event so that the old pending event will not occur.
  * Since we have the mutex, even if fc_rport_work() is already started,
  * it'll see the new event.
+ *
+ * Reference counting: does not modify kref
  */
 static void fc_rport_enter_delete(struct fc_rport_priv *rdata,
  enum fc_rport_event event)
 {
+   struct fc_lport *lport = rdata->local_port;
+
if (rdata->rp_state == RPORT_ST_DELETE)
return;
 
@@ -442,8 +465,11 @@ static void fc_rport_enter_delete(struct fc_rport_priv 
*rdata,
 
fc_rport_state_enter(rdata, RPORT_ST_DELETE);
 
-   if (rdata->event == RPORT_EV_NONE)
-   queue_work(rport_event_queue, >event_work);
+   kref_get(>kref);
+   if (rdata->event == RPORT_EV_NONE &&
+   !queue_work(rport_event_queue, >event_work))
+   kref_put(>kref, lport->tt.rport_destroy);
+
rdata->event = event;
 }
 
@@ -496,15 +522,22 @@ out:
  *
  * Locking Note: The rport lock is expected to be held before calling
  * this routine.
+ *
+ * Reference counting: schedules workqueue, does not modify kref
  */
 static void fc_rport_enter_ready(struct fc_rport_priv *rdata)
 {
+   struct fc_lport *lport = rdata->local_port;
+
fc_rport_state_enter(rdata, RPORT_ST_READY);
 
FC_RPORT_DBG(rdata, "Port is Ready\n");
 
-   if (rdata->event == RPORT_EV_NONE)
-   queue_work(rport_event_queue, >event_work);
+   kref_get(>kref);
+   if (rdata->event == RPORT_EV_NONE &&
+   !queue_work(rport_event_queue, >event_work))
+   kref_put(>kref, lport->tt.rport_destroy);
+
rdata->event = RPORT_EV_READY;
 }
 
@@ -515,13 +548,17 @@ static void fc_rport_enter_ready(struct fc_rport_priv 
*rdata)
  * Locking Note: Called without the rport lock held. This
  * function will hold the rport lock, call an _enter_*
  * function and then unlock the rport.
+ *
+ * Reference counting: Drops kref on return.
  */
 static void fc_rport_timeout(struct work_struct *work)
 {
struct fc_rport_priv *rdata =
container_of(work, struct 

[PATCH 22/30] libfc: reset timeout on queue full

2016-08-26 Thread Hannes Reinecke
When we're receiving a timeout we should be checking for queue
full status; if there are still some packets pending we should
be resetting the counter to ensure we're not missing out any
packets which are still queued.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_fcp.c | 21 ++---
 include/scsi/libfc.h|  3 ++-
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 63c821b..3e059e4 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -254,8 +254,10 @@ static inline void fc_fcp_unlock_pkt(struct fc_fcp_pkt 
*fsp)
  */
 static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay)
 {
-   if (!(fsp->state & FC_SRB_COMPL))
+   if (!(fsp->state & FC_SRB_COMPL)) {
mod_timer(>timer, jiffies + delay);
+   fsp->timer_delay = delay;
+   }
 }
 
 static void fc_fcp_abort_done(struct fc_fcp_pkt *fsp)
@@ -932,6 +934,12 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct 
fc_frame *fp)
 * Wait a at least one jiffy to see if it is delivered.
 * If this expires without data, we may do SRR.
 */
+   if (fsp->lp->qfull) {
+   FC_FCP_DBG(fsp, "tgt %6.6x data underrun, "
+  "retry due to queue busy\n",
+  fsp->rport->port_id);
+   return;
+   }
FC_FCP_DBG(fsp, "tgt %6.6x xfer len %zx data underrun "
   "len %x, data len %x\n",
   fsp->rport->port_id,
@@ -1435,8 +1443,15 @@ static void fc_fcp_timeout(unsigned long data)
if (fsp->cdb_cmd.fc_tm_flags)
goto unlock;
 
-   FC_FCP_DBG(fsp, "fcp timeout, flags %x state %x\n",
-  rpriv->flags, fsp->state);
+   if (fsp->lp->qfull) {
+   FC_FCP_DBG(fsp, "fcp timeout, resetting timer delay %d\n",
+  fsp->timer_delay);
+   setup_timer(>timer, fc_fcp_timeout, (unsigned long)fsp);
+   fc_fcp_timer_set(fsp, fsp->timer_delay);
+   goto unlock;
+   }
+   FC_FCP_DBG(fsp, "fcp timeout, delay %d flags %x state %x\n",
+  fsp->timer_delay, rpriv->flags, fsp->state);
fsp->state |= FC_SRB_FCP_PROCESSING_TMO;
 
if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 8cb752f..f5aa54b 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -355,7 +355,8 @@ struct fc_fcp_pkt {
 
/* Timeout/error related information */
struct timer_list timer;
-   int   wait_for_comp;
+   int   wait_for_comp;
+   int   timer_delay;
u32   recov_retry;
struct fc_seq *recov_seq;
struct completion tm_done;
-- 
1.8.5.6

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


[PATCH 28/30] fcoe: FIP debugging

2016-08-26 Thread Hannes Reinecke
Add additional statements for debugging FIP frames.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/fcoe/fcoe_ctlr.c | 51 ++-
 1 file changed, 46 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 1dd8a7c..8be27ea 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -801,6 +801,8 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct 
fc_lport *lport,
return -EINPROGRESS;
 drop:
kfree_skb(skb);
+   LIBFCOE_FIP_DBG(fip, "drop els_send op %u d_id %x\n",
+   op, ntoh24(fh->fh_d_id));
return -EINVAL;
 }
 EXPORT_SYMBOL(fcoe_ctlr_els_send);
@@ -2399,6 +2401,8 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
switch (fip->state) {
case FIP_ST_VNMP_CLAIM:
case FIP_ST_VNMP_UP:
+   LIBFCOE_FIP_DBG(fip, "vn_probe_req: send reply, state %x\n",
+   fip->state);
fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
  frport->enode_mac, 0);
break;
@@ -2413,15 +2417,21 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr 
*fip,
 */
if (fip->lp->wwpn > rdata->ids.port_name &&
!(frport->flags & FIP_FL_REC_OR_P2P)) {
+   LIBFCOE_FIP_DBG(fip, "vn_probe_req: "
+   "port_id collision\n");
fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
  frport->enode_mac, 0);
break;
}
/* fall through */
case FIP_ST_VNMP_START:
+   LIBFCOE_FIP_DBG(fip, "vn_probe_req: "
+   "restart VN2VN negotiation\n");
fcoe_ctlr_vn_restart(fip);
break;
default:
+   LIBFCOE_FIP_DBG(fip, "vn_probe_req: ignore state %x\n",
+   fip->state);
break;
}
 }
@@ -2443,9 +2453,12 @@ static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr 
*fip,
case FIP_ST_VNMP_PROBE1:
case FIP_ST_VNMP_PROBE2:
case FIP_ST_VNMP_CLAIM:
+   LIBFCOE_FIP_DBG(fip, "vn_probe_reply: restart state %x\n",
+   fip->state);
fcoe_ctlr_vn_restart(fip);
break;
case FIP_ST_VNMP_UP:
+   LIBFCOE_FIP_DBG(fip, "vn_probe_reply: send claim notify\n");
fcoe_ctlr_vn_send_claim(fip);
break;
default:
@@ -2484,15 +2497,18 @@ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, 
struct fc_rport_priv *new)
 
ids = >ids;
if ((ids->port_name != -1 && ids->port_name != new->ids.port_name) ||
-   (ids->node_name != -1 && ids->node_name != new->ids.node_name))
+   (ids->node_name != -1 && ids->node_name != new->ids.node_name)) {
+   LIBFCOE_FIP_DBG(fip, "vn_add rport logoff %6.6x\n", port_id);
lport->tt.rport_logoff(rdata);
+   }
ids->port_name = new->ids.port_name;
ids->node_name = new->ids.node_name;
mutex_unlock(>disc.disc_mutex);
 
frport = fcoe_ctlr_rport(rdata);
-   LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s\n",
-   port_id, frport->fcoe_len ? "old" : "new");
+   LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s state %d\n",
+   port_id, frport->fcoe_len ? "old" : "new",
+   rdata->rp_state);
*frport = *fcoe_ctlr_rport(new);
frport->time = 0;
 }
@@ -2535,6 +2551,7 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr 
*fip,
struct fcoe_rport *frport = fcoe_ctlr_rport(new);
 
if (frport->flags & FIP_FL_REC_OR_P2P) {
+   LIBFCOE_FIP_DBG(fip, "send probe req for P2P/REC\n");
fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
return;
}
@@ -2542,25 +2559,37 @@ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr 
*fip,
case FIP_ST_VNMP_START:
case FIP_ST_VNMP_PROBE1:
case FIP_ST_VNMP_PROBE2:
-   if (new->ids.port_id == fip->port_id)
+   if (new->ids.port_id == fip->port_id) {
+   LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
+   "restart, state %d\n",
+   fip->state);
fcoe_ctlr_vn_restart(fip);
+   }
break;
case FIP_ST_VNMP_CLAIM:
case FIP_ST_VNMP_UP:
if (new->ids.port_id == fip->port_id) {
if (new->ids.port_name > fip->lp->wwpn) {
+   LIBFCOE_FIP_DBG(fip, "vn_claim_notify: "
+   "restart, port_id collision\n");
 

[PATCH 29/30] fcoe: filter out frames from invalid vlans

2016-08-26 Thread Hannes Reinecke
Any multicase address is set on all interfaces, the base interface
and any VLAN interface on top of this. So we might receive frames
which are not destined for us but in fact on another VLAN.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/fcoe/fcoe_ctlr.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 8be27ea..e6557ea 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -2721,11 +2721,21 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, 
struct sk_buff *skb)
struct fc_rport_priv rdata;
struct fcoe_rport frport;
} buf;
-   int rc;
+   int rc, vlan_id = 0;
 
fiph = (struct fip_header *)skb->data;
sub = fiph->fip_subcode;
 
+   if (fip->lp->vlan)
+   vlan_id = skb_vlan_tag_get_id(skb);
+
+   if (vlan_id && vlan_id != fip->lp->vlan) {
+   LIBFCOE_FIP_DBG(fip, "vn_recv drop frame sub %x vlan %d\n",
+   sub, vlan_id);
+   rc = -EAGAIN;
+   goto drop;
+   }
+
rc = fcoe_ctlr_vn_parse(fip, skb, );
if (rc) {
LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc);
-- 
1.8.5.6

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


[PATCH 18/30] libfc: safeguard against invalid exchange index

2016-08-26 Thread Hannes Reinecke
The cached exchange index might be invalid, in which case
we should drop down to allocate a new one.
And we should not try to access an invalid exchange when
responding to a BA_ABTS.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_exch.c | 21 ++---
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 7d0e7ca..da9c727 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -827,14 +827,18 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport 
*lport,
 
/* peek cache of free slot */
if (pool->left != FC_XID_UNKNOWN) {
-   index = pool->left;
-   pool->left = FC_XID_UNKNOWN;
-   goto hit;
+   if (!WARN_ON(fc_exch_ptr_get(pool, pool->left))) {
+   index = pool->left;
+   pool->left = FC_XID_UNKNOWN;
+   goto hit;
+   }
}
if (pool->right != FC_XID_UNKNOWN) {
-   index = pool->right;
-   pool->right = FC_XID_UNKNOWN;
-   goto hit;
+   if (!WARN_ON(fc_exch_ptr_get(pool, pool->right))) {
+   index = pool->right;
+   pool->right = FC_XID_UNKNOWN;
+   goto hit;
+   }
}
 
index = pool->next_index;
@@ -1777,7 +1781,10 @@ static void fc_exch_recv_bls(struct fc_exch_mgr *mp, 
struct fc_frame *fp)
fc_frame_free(fp);
break;
case FC_RCTL_BA_ABTS:
-   fc_exch_recv_abts(ep, fp);
+   if (ep)
+   fc_exch_recv_abts(ep, fp);
+   else
+   fc_frame_free(fp);
break;
default:/* ignore junk */
fc_frame_free(fp);
-- 
1.8.5.6

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


[PATCH 11/30] libfc: Fixup disc_mutex handling

2016-08-26 Thread Hannes Reinecke
The list of attached 'rdata' remote port structures is RCU
protected, so there is no need to take the 'disc_mutex' when
traversing it.
Rather we should be using rcu_read_lock() and kref_get_unless_zero()
to validate the entries.
We need, however, take the disc_mutex when deleting an entry;
otherwise we risk clashes with list_add.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/fcoe/fcoe_ctlr.c | 28 ++--
 drivers/scsi/libfc/fc_disc.c  | 30 +++---
 drivers/scsi/libfc/fc_rport.c |  2 ++
 3 files changed, 43 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index a569c65..5eacd33 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -2145,9 +2145,15 @@ static void fcoe_ctlr_disc_stop_locked(struct fc_lport 
*lport)
 {
struct fc_rport_priv *rdata;
 
+   rcu_read_lock();
+   list_for_each_entry_rcu(rdata, >disc.rports, peers) {
+   if (kref_get_unless_zero(>kref)) {
+   lport->tt.rport_logoff(rdata);
+   kref_put(>kref, lport->tt.rport_destroy);
+   }
+   }
+   rcu_read_unlock();
mutex_lock(>disc.disc_mutex);
-   list_for_each_entry_rcu(rdata, >disc.rports, peers)
-   lport->tt.rport_logoff(rdata);
lport->disc.disc_callback = NULL;
mutex_unlock(>disc.disc_mutex);
 }
@@ -2638,11 +2644,15 @@ static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr 
*fip)
unsigned long deadline;
 
next_time = jiffies + msecs_to_jiffies(FIP_VN_BEACON_INT * 10);
-   mutex_lock(>disc.disc_mutex);
+   rcu_read_lock();
list_for_each_entry_rcu(rdata, >disc.rports, peers) {
+   if (!kref_get_unless_zero(>kref))
+   continue;
frport = fcoe_ctlr_rport(rdata);
-   if (!frport->time)
+   if (!frport->time) {
+   kref_put(>kref, lport->tt.rport_destroy);
continue;
+   }
deadline = frport->time +
   msecs_to_jiffies(FIP_VN_BEACON_INT * 25 / 10);
if (time_after_eq(jiffies, deadline)) {
@@ -2653,8 +2663,9 @@ static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr 
*fip)
lport->tt.rport_logoff(rdata);
} else if (time_before(deadline, next_time))
next_time = deadline;
+   kref_put(>kref, lport->tt.rport_destroy);
}
-   mutex_unlock(>disc.disc_mutex);
+   rcu_read_unlock();
return next_time;
 }
 
@@ -2991,12 +3002,17 @@ static void fcoe_ctlr_vn_disc(struct fcoe_ctlr *fip)
mutex_lock(>disc_mutex);
callback = disc->pending ? disc->disc_callback : NULL;
disc->pending = 0;
+   mutex_unlock(>disc_mutex);
+   rcu_read_lock();
list_for_each_entry_rcu(rdata, >rports, peers) {
+   if (!kref_get_unless_zero(>kref))
+   continue;
frport = fcoe_ctlr_rport(rdata);
if (frport->time)
lport->tt.rport_login(rdata);
+   kref_put(>kref, lport->tt.rport_destroy);
}
-   mutex_unlock(>disc_mutex);
+   rcu_read_unlock();
if (callback)
callback(lport, DISC_EV_SUCCESS);
 }
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 880a906..351022a 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -68,10 +68,14 @@ static void fc_disc_stop_rports(struct fc_disc *disc)
 
lport = fc_disc_lport(disc);
 
-   mutex_lock(>disc_mutex);
-   list_for_each_entry_rcu(rdata, >rports, peers)
-   lport->tt.rport_logoff(rdata);
-   mutex_unlock(>disc_mutex);
+   rcu_read_lock();
+   list_for_each_entry_rcu(rdata, >rports, peers) {
+   if (kref_get_unless_zero(>kref)) {
+   lport->tt.rport_logoff(rdata);
+   kref_put(>kref, lport->tt.rport_destroy);
+   }
+   }
+   rcu_read_unlock();
 }
 
 /**
@@ -289,16 +293,20 @@ static void fc_disc_done(struct fc_disc *disc, enum 
fc_disc_event event)
 * Skip ports which were never discovered.  These are the dNS port
 * and ports which were created by PLOGI.
 */
+   mutex_unlock(>disc_mutex);
+   rcu_read_lock();
list_for_each_entry_rcu(rdata, >rports, peers) {
-   if (!rdata->disc_id)
+   if (!kref_get_unless_zero(>kref))
continue;
-   if (rdata->disc_id == disc->disc_id)
-   lport->tt.rport_login(rdata);
-   else
-   lport->tt.rport_logoff(rdata);
+   if (rdata->disc_id) {
+   if (rdata->disc_id == disc->disc_id)
+   

[PATCH 00/30] FCoE VN2VN fixes

2016-08-26 Thread Hannes Reinecke
Hi all,

here's a patchset to get VN2VN running on non-DCB fabrics.
With it it's possible to run FCoE VN2VN over virtio, allowing
for a fully virtualized FC testbed. Which would make it ideal
to integrate into Mike's mptest test suite.
It also irons out some generic issues with the libfc stack,
like another round for kref handling updates and handling PRLI correctly.
(The PRLI problems even have a workaround in iPXE, so it's time to do
something about it ...)

As usual, comments and reviews are welcome.

Hannes Reinecke (29):
  libfc: Revisit kref handling
  libfc: additional debugging messages
  libfc: spurious I/O error under high load
  libfc: Do not login if the port is already started
  libfc: use configured lport R_A_TOV when sending
  libfc: use configured e_d_tov for remote port state
  libfc: do not overwrite DID_TIME_OUT status
  libfc: use error code for fc_rport_error()
  libfc: Send LS_RJT responses on frame allocation
  libfc: don't advance state machine for incoming FLOGI
  libfc: Fixup disc_mutex handling
  libfc: Do not drop down to FLOGI for fc_rport_login()
  libfc: Implement RTV responder
  libfc: Rework PRLI handling
  libfc: Return LS_RJT_BUSY for PRLI in status PLOGI
  libfc: Clarify ramp-down messages
  libfc: sanitize E_D_TOV and R_A_TOV setting
  libfc: safeguard against invalid exchange index
  libfc: quarantine timed out xids
  libfc: don't fail sequence abort for completed
  libfc: Do not drop out-of-order frames
  libfc: reset timeout on queue full
  libfc: wait for E_D_TOV when out-of-order sequence is received
  fcoe: set default TC priority
  fcoe: inhibit writing invalid values into the 'enabled'
  fcoe: correct sending FIP VLAN packets on VLAN 0
  fcoe: FIP debugging
  fcoe: filter out frames from invalid vlans
  fcoe: make R_A_TOV and E_D_TOV configurable

Wei Yongjun (1):
  fcoe: Use kfree_skb() instead of kfree()

 drivers/scsi/fcoe/fcoe.c   |  23 ++-
 drivers/scsi/fcoe/fcoe_ctlr.c  |  93 +++--
 drivers/scsi/fcoe/fcoe_sysfs.c |  83 +++-
 drivers/scsi/libfc/fc_disc.c   |  30 +--
 drivers/scsi/libfc/fc_exch.c   | 118 +++
 drivers/scsi/libfc/fc_fcp.c| 195 --
 drivers/scsi/libfc/fc_lport.c  |   8 +-
 drivers/scsi/libfc/fc_rport.c  | 436 ++---
 include/scsi/libfc.h   |   9 +-
 9 files changed, 760 insertions(+), 235 deletions(-)

-- 
1.8.5.6

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


[PATCH 19/30] libfc: quarantine timed out xids

2016-08-26 Thread Hannes Reinecke
When a sequence times out we have no idea what happened to the
frame. And we do not know if we will ever receive the frame.
Hence we cannot re-use the xid as we would risk data corruption
if the xid had been re-used and the timed out frame would be
received after that.
So we need to quarantine the xid until the lport is reset.
Yes, I know this will (eventually) deplete the xid pool.
But for now it's the safest method.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_exch.c | 33 ++---
 drivers/scsi/libfc/fc_fcp.c  | 13 +++--
 include/scsi/libfc.h |  1 +
 3 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index da9c727..510f38c 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -94,6 +94,7 @@ struct fc_exch_pool {
 struct fc_exch_mgr {
struct fc_exch_pool __percpu *pool;
mempool_t   *ep_pool;
+   struct fc_lport *lport;
enum fc_class   class;
struct kref kref;
u16 min_xid;
@@ -408,6 +409,8 @@ static int fc_exch_done_locked(struct fc_exch *ep)
return rc;
 }
 
+static struct fc_exch fc_quarantine_exch;
+
 /**
  * fc_exch_ptr_get() - Return an exchange from an exchange pool
  * @pool:  Exchange Pool to get an exchange from
@@ -452,14 +455,17 @@ static void fc_exch_delete(struct fc_exch *ep)
 
/* update cache of free slot */
index = (ep->xid - ep->em->min_xid) >> fc_cpu_order;
-   if (pool->left == FC_XID_UNKNOWN)
-   pool->left = index;
-   else if (pool->right == FC_XID_UNKNOWN)
-   pool->right = index;
-   else
-   pool->next_index = index;
-
-   fc_exch_ptr_set(pool, index, NULL);
+   if (!(ep->state & FC_EX_QUARANTINE)) {
+   if (pool->left == FC_XID_UNKNOWN)
+   pool->left = index;
+   else if (pool->right == FC_XID_UNKNOWN)
+   pool->right = index;
+   else
+   pool->next_index = index;
+   fc_exch_ptr_set(pool, index, NULL);
+   } else {
+   fc_exch_ptr_set(pool, index, _quarantine_exch);
+   }
list_del(>ex_list);
spin_unlock_bh(>lock);
fc_exch_release(ep);/* drop hold for exch in mp */
@@ -916,14 +922,14 @@ static inline struct fc_exch *fc_exch_alloc(struct 
fc_lport *lport,
  */
 static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid)
 {
+   struct fc_lport *lport = mp->lport;
struct fc_exch_pool *pool;
struct fc_exch *ep = NULL;
u16 cpu = xid & fc_cpu_mask;
 
if (cpu >= nr_cpu_ids || !cpu_possible(cpu)) {
-   printk_ratelimited(KERN_ERR
-   "libfc: lookup request for XID = %d, "
-   "indicates invalid CPU %d\n", xid, cpu);
+   pr_err("host%u: lport %6.6x: xid %d invalid CPU %d\n:",
+  lport->host->host_no, lport->port_id, xid, cpu);
return NULL;
}
 
@@ -931,6 +937,10 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr 
*mp, u16 xid)
pool = per_cpu_ptr(mp->pool, cpu);
spin_lock_bh(>lock);
ep = fc_exch_ptr_get(pool, (xid - mp->min_xid) >> fc_cpu_order);
+   if (ep == _quarantine_exch) {
+   FC_LPORT_DBG(lport, "xid %x quarantined\n", xid);
+   ep = NULL;
+   }
if (ep) {
WARN_ON(ep->xid != xid);
fc_exch_hold(ep);
@@ -2429,6 +2439,7 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport 
*lport,
return NULL;
 
mp->class = class;
+   mp->lport = lport;
/* adjust em exch xid range for offload */
mp->min_xid = min_xid;
 
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 1cb2c59..8694e87 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1531,13 +1531,14 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct 
fc_frame *fp, void *arg)
   fsp->rport->port_id, rjt->er_reason,
   rjt->er_explan, fsp->xfer_len);
/*
-* If no data transfer, the command frame got dropped
-* so we just retry.  If data was transferred, we
-* lost the response but the target has no record,
-* so we abort and retry.
+* If response got lost or is stuck in the
+* queue somewhere we have no idea if and when
+* the response will be received. So quarantine
+* the xid and retry the command.
 */
-   if (rjt->er_explan == 

[PATCH 02/30] libfc: additional debugging messages

2016-08-26 Thread Hannes Reinecke
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_exch.c  | 59 +++
 drivers/scsi/libfc/fc_fcp.c   | 39 +++-
 drivers/scsi/libfc/fc_rport.c | 20 ---
 3 files changed, 97 insertions(+), 21 deletions(-)

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 16ca31a..f178084 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -362,8 +362,10 @@ static inline void fc_exch_timer_set_locked(struct fc_exch 
*ep,
 
fc_exch_hold(ep);   /* hold for timer */
if (!queue_delayed_work(fc_exch_workqueue, >timeout_work,
-   msecs_to_jiffies(timer_msec)))
+   msecs_to_jiffies(timer_msec))) {
+   FC_EXCH_DBG(ep, "Exchange already queued\n");
fc_exch_release(ep);
+   }
 }
 
 /**
@@ -632,9 +634,13 @@ static int fc_exch_abort_locked(struct fc_exch *ep,
struct fc_frame *fp;
int error;
 
+   FC_EXCH_DBG(ep, "exch: abort, time %d msecs\n", timer_msec);
if (ep->esb_stat & (ESB_ST_COMPLETE | ESB_ST_ABNORMAL) ||
-   ep->state & (FC_EX_DONE | FC_EX_RST_CLEANUP))
+   ep->state & (FC_EX_DONE | FC_EX_RST_CLEANUP)) {
+   FC_EXCH_DBG(ep, "exch: already completed esb %x state %x\n",
+   ep->esb_stat, ep->state);
return -ENXIO;
+   }
 
/*
 * Send the abort on a new sequence if possible.
@@ -758,7 +764,7 @@ static void fc_exch_timeout(struct work_struct *work)
u32 e_stat;
int rc = 1;
 
-   FC_EXCH_DBG(ep, "Exchange timed out\n");
+   FC_EXCH_DBG(ep, "Exchange timed out state %x\n", ep->state);
 
spin_lock_bh(>ex_lock);
if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE))
@@ -1258,8 +1264,10 @@ static void fc_seq_send_ack(struct fc_seq *sp, const 
struct fc_frame *rx_fp)
 */
if (fc_sof_needs_ack(fr_sof(rx_fp))) {
fp = fc_frame_alloc(lport, 0);
-   if (!fp)
+   if (!fp) {
+   FC_EXCH_DBG(ep, "Drop ACK request, out of memory\n");
return;
+   }
 
fh = fc_frame_header_get(fp);
fh->fh_r_ctl = FC_RCTL_ACK_1;
@@ -1312,13 +1320,18 @@ static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp,
struct fc_frame_header *rx_fh;
struct fc_frame_header *fh;
struct fc_ba_rjt *rp;
+   struct fc_seq *sp;
struct fc_lport *lport;
unsigned int f_ctl;
 
lport = fr_dev(rx_fp);
+   sp = fr_seq(rx_fp);
fp = fc_frame_alloc(lport, sizeof(*rp));
-   if (!fp)
+   if (!fp) {
+   FC_EXCH_DBG(fc_seq_exch(sp),
+"Drop BA_RJT request, out of memory\n");
return;
+   }
fh = fc_frame_header_get(fp);
rx_fh = fc_frame_header_get(rx_fp);
 
@@ -1383,14 +1396,17 @@ static void fc_exch_recv_abts(struct fc_exch *ep, 
struct fc_frame *rx_fp)
if (!ep)
goto reject;
 
+   FC_EXCH_DBG(ep, "exch: ABTS received\n");
fp = fc_frame_alloc(ep->lp, sizeof(*ap));
-   if (!fp)
+   if (!fp) {
+   FC_EXCH_DBG(ep, "Drop ABTS request, out of memory\n");
goto free;
+   }
 
spin_lock_bh(>ex_lock);
if (ep->esb_stat & ESB_ST_COMPLETE) {
spin_unlock_bh(>ex_lock);
-
+   FC_EXCH_DBG(ep, "exch: ABTS rejected, exchange complete\n");
fc_frame_free(fp);
goto reject;
}
@@ -1784,11 +1800,16 @@ static void fc_seq_ls_acc(struct fc_frame *rx_fp)
struct fc_lport *lport;
struct fc_els_ls_acc *acc;
struct fc_frame *fp;
+   struct fc_seq *sp;
 
lport = fr_dev(rx_fp);
+   sp = fr_seq(rx_fp);
fp = fc_frame_alloc(lport, sizeof(*acc));
-   if (!fp)
+   if (!fp) {
+   FC_EXCH_DBG(fc_seq_exch(sp),
+   "exch: drop LS_ACC, out of memory\n");
return;
+   }
acc = fc_frame_payload_get(fp, sizeof(*acc));
memset(acc, 0, sizeof(*acc));
acc->la_cmd = ELS_LS_ACC;
@@ -1811,11 +1832,16 @@ static void fc_seq_ls_rjt(struct fc_frame *rx_fp, enum 
fc_els_rjt_reason reason,
struct fc_lport *lport;
struct fc_els_ls_rjt *rjt;
struct fc_frame *fp;
+   struct fc_seq *sp;
 
lport = fr_dev(rx_fp);
+   sp = fr_seq(rx_fp);
fp = fc_frame_alloc(lport, sizeof(*rjt));
-   if (!fp)
+   if (!fp) {
+   FC_EXCH_DBG(fc_seq_exch(sp),
+   "exch: drop LS_ACC, out of memory\n");
return;
+   }
rjt = fc_frame_payload_get(fp, sizeof(*rjt));
memset(rjt, 0, sizeof(*rjt));
rjt->er_cmd = ELS_LS_RJT;
@@ -1975,15 +2001,23 @@ static void 

[PATCH 06/30] libfc: use configured e_d_tov for remote port state

2016-08-26 Thread Hannes Reinecke
If fc_rport_error_retry() is attempting to retry the remote
port state we should be waiting for the configured e_d_tov
value rather than the default.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_rport.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 2406276..4c13acc 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -656,7 +656,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, 
struct fc_frame *fp)
 static void fc_rport_error_retry(struct fc_rport_priv *rdata,
 struct fc_frame *fp)
 {
-   unsigned long delay = msecs_to_jiffies(FC_DEF_E_D_TOV);
+   unsigned long delay = msecs_to_jiffies(rdata->e_d_tov);
struct fc_lport *lport = rdata->local_port;
 
/* make sure this isn't an FC_EX_CLOSED error, never retry those */
-- 
1.8.5.6

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


[PATCH 08/30] libfc: use error code for fc_rport_error()

2016-08-26 Thread Hannes Reinecke
We only ever use the 'fp' argument for fc_rport_error() to
encapsulate the error code, so we can as well do away with that
and pass the error directly.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_rport.c | 97 +--
 include/scsi/libfc.h  |  5 +++
 2 files changed, 62 insertions(+), 40 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 4c13acc..29a51c6 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -87,8 +87,8 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *, 
struct fc_frame *);
 static void fc_rport_recv_prlo_req(struct fc_rport_priv *, struct fc_frame *);
 static void fc_rport_recv_logo_req(struct fc_lport *, struct fc_frame *);
 static void fc_rport_timeout(struct work_struct *);
-static void fc_rport_error(struct fc_rport_priv *, struct fc_frame *);
-static void fc_rport_error_retry(struct fc_rport_priv *, struct fc_frame *);
+static void fc_rport_error(struct fc_rport_priv *, int);
+static void fc_rport_error_retry(struct fc_rport_priv *, int);
 static void fc_rport_work(struct work_struct *);
 
 static const char *fc_rport_state_names[] = {
@@ -598,20 +598,19 @@ static void fc_rport_timeout(struct work_struct *work)
 /**
  * fc_rport_error() - Error handler, called once retries have been exhausted
  * @rdata: The remote port the error is happened on
- * @fp:   The error code encapsulated in a frame pointer
+ * @err:   The error code
  *
  * Locking Note: The rport lock is expected to be held before
  * calling this routine
  *
  * Reference counting: does not modify kref
  */
-static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
+static void fc_rport_error(struct fc_rport_priv *rdata, int err)
 {
struct fc_lport *lport = rdata->local_port;
 
-   FC_RPORT_DBG(rdata, "Error %ld in state %s, retries %d\n",
-IS_ERR(fp) ? -PTR_ERR(fp) : 0,
-fc_rport_state(rdata), rdata->retries);
+   FC_RPORT_DBG(rdata, "Error %d in state %s, retries %d\n",
+-err, fc_rport_state(rdata), rdata->retries);
 
switch (rdata->rp_state) {
case RPORT_ST_FLOGI:
@@ -643,7 +642,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, 
struct fc_frame *fp)
 /**
  * fc_rport_error_retry() - Handler for remote port state retries
  * @rdata: The remote port whose state is to be retried
- * @fp:   The error code encapsulated in a frame pointer
+ * @err:   The error code
  *
  * If the error was an exchange timeout retry immediately,
  * otherwise wait for E_D_TOV.
@@ -653,22 +652,21 @@ static void fc_rport_error(struct fc_rport_priv *rdata, 
struct fc_frame *fp)
  *
  * Reference counting: increments kref when scheduling retry_work
  */
-static void fc_rport_error_retry(struct fc_rport_priv *rdata,
-struct fc_frame *fp)
+static void fc_rport_error_retry(struct fc_rport_priv *rdata, int err)
 {
unsigned long delay = msecs_to_jiffies(rdata->e_d_tov);
struct fc_lport *lport = rdata->local_port;
 
/* make sure this isn't an FC_EX_CLOSED error, never retry those */
-   if (PTR_ERR(fp) == -FC_EX_CLOSED)
+   if (err == -FC_EX_CLOSED)
goto out;
 
if (rdata->retries < rdata->local_port->max_rport_retry_count) {
-   FC_RPORT_DBG(rdata, "Error %ld in state %s, retrying\n",
-PTR_ERR(fp), fc_rport_state(rdata));
+   FC_RPORT_DBG(rdata, "Error %d in state %s, retrying\n",
+err, fc_rport_state(rdata));
rdata->retries++;
/* no additional delay on exchange timeouts */
-   if (PTR_ERR(fp) == -FC_EX_TIMEOUT)
+   if (err == -FC_EX_TIMEOUT)
delay = 0;
kref_get(>kref);
if (!schedule_delayed_work(>retry_work, delay))
@@ -677,7 +675,7 @@ static void fc_rport_error_retry(struct fc_rport_priv 
*rdata,
}
 
 out:
-   fc_rport_error(rdata, fp);
+   fc_rport_error(rdata, err);
 }
 
 /**
@@ -737,8 +735,10 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct 
fc_frame *fp,
struct fc_lport *lport = rdata->local_port;
struct fc_els_flogi *flogi;
unsigned int r_a_tov;
+   int err = 0;
 
-   FC_RPORT_DBG(rdata, "Received a FLOGI %s\n", fc_els_resp_type(fp));
+   FC_RPORT_DBG(rdata, "Received a FLOGI %s\n",
+IS_ERR(fp)? "error" : fc_els_resp_type(fp));
 
if (fp == ERR_PTR(-FC_EX_CLOSED))
goto put;
@@ -754,18 +754,30 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct 
fc_frame *fp,
}
 
if (IS_ERR(fp)) {
-   fc_rport_error(rdata, fp);
+   fc_rport_error(rdata, PTR_ERR(fp));
goto err;
}
 
-   if (fc_frame_payload_op(fp) != 

[PATCH 07/30] libfc: do not overwrite DID_TIME_OUT status

2016-08-26 Thread Hannes Reinecke
When a command is aborted it might already have the DID_TIME_OUT
status set, so we shouldn't be overwriting that.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_fcp.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 289c481..a667c8c 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -2009,9 +2009,15 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
sc_cmd->result = (DID_ERROR << 16) | fsp->cdb_status;
break;
case FC_CMD_ABORTED:
-   FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml "
- "due to FC_CMD_ABORTED\n");
-   sc_cmd->result = (DID_ERROR << 16) | fsp->io_status;
+   if (host_byte(sc_cmd->result) == DID_TIME_OUT)
+   FC_FCP_DBG(fsp, "Returning DID_TIME_OUT to scsi-ml "
+  "due to FC_CMD_ABORTED\n");
+   else {
+   FC_FCP_DBG(fsp, "Returning DID_ERROR to scsi-ml "
+  "due to FC_CMD_ABORTED\n");
+   set_host_byte(sc_cmd, DID_ERROR);
+   }
+   sc_cmd->result |= fsp->io_status;
break;
case FC_CMD_RESET:
FC_FCP_DBG(fsp, "Returning DID_RESET to scsi-ml "
-- 
1.8.5.6

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


[PATCH 10/30] libfc: don't advance state machine for incoming FLOGI

2016-08-26 Thread Hannes Reinecke
When we receive an FLOGI but have already sent our own we should
not advance the state machine but rather wait for our FLOGI to
return before continuing with PLOGI.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_rport.c | 18 --
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index f9b6f59..91866a5 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -775,6 +775,7 @@ static void fc_rport_flogi_resp(struct fc_seq *sp, struct 
fc_frame *fp,
 
flogi = fc_frame_payload_get(fp, sizeof(*flogi));
if (!flogi) {
+   FC_RPORT_DBG(rdata, "Bad FLOGI response\n");
err = -FC_EX_ALLOC_ERR;
goto bad;
}
@@ -794,7 +795,6 @@ put:
kref_put(>kref, lport->tt.rport_destroy);
return;
 bad:
-   FC_RPORT_DBG(rdata, "Bad FLOGI response\n");
fc_rport_error_retry(rdata, err);
goto out;
 }
@@ -940,11 +940,17 @@ static void fc_rport_recv_flogi_req(struct fc_lport 
*lport,
fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0);
lport->tt.frame_send(lport, fp);
 
-   if (rdata->ids.port_name < lport->wwpn)
-   fc_rport_enter_plogi(rdata);
-   else
-   fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT);
-
+   /*
+* Do not proceed with the state machine if our
+* FLOGI has crossed with an FLOGI from the
+* remote port; wait for the FLOGI response instead.
+*/
+   if (rdata->rp_state != RPORT_ST_FLOGI) {
+   if (rdata->ids.port_name < lport->wwpn)
+   fc_rport_enter_plogi(rdata);
+   else
+   fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT);
+   }
mutex_unlock(>rp_mutex);
kref_put(>kref, lport->tt.rport_destroy);
fc_frame_free(rx_fp);
-- 
1.8.5.6

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


[PATCH 17/30] libfc: sanitize E_D_TOV and R_A_TOV setting

2016-08-26 Thread Hannes Reinecke
When setting the FCP timeout we need to ensure a lower boundary
for E_D_TOV and R_A_TOV, otherwise we'd be getting spurious I/O
issues due to the fcp timer firing too early.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_fcp.c   | 9 +
 drivers/scsi/libfc/fc_lport.c | 8 +---
 drivers/scsi/libfc/fc_rport.c | 6 --
 3 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index abddfe2..1cb2c59 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1139,8 +1139,11 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, 
struct fc_fcp_pkt *fsp)
 static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
 {
struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data;
+   unsigned int e_d_tov = FC_DEF_E_D_TOV;
 
-   return msecs_to_jiffies(rpriv->e_d_tov) + HZ;
+   if (rpriv && rpriv->e_d_tov > e_d_tov)
+   e_d_tov = rpriv->e_d_tov;
+   return msecs_to_jiffies(e_d_tov) + HZ;
 }
 
 /**
@@ -1696,7 +1699,6 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum 
fc_rctl r_ctl, u32 offset)
struct fc_seq *seq;
struct fcp_srr *srr;
struct fc_frame *fp;
-   unsigned int rec_tov;
 
rport = fsp->rport;
rpriv = rport->dd_data;
@@ -1720,10 +1722,9 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum 
fc_rctl r_ctl, u32 offset)
   rpriv->local_port->port_id, FC_TYPE_FCP,
   FC_FCTL_REQ, 0);
 
-   rec_tov = get_fsp_rec_tov(fsp);
seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp,
  fc_fcp_pkt_destroy,
- fsp, jiffies_to_msecs(rec_tov));
+ fsp, get_fsp_rec_tov(fsp));
if (!seq)
goto retry;
 
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 04ce7cf..ccf773a 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1772,7 +1772,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct 
fc_frame *fp,
if ((csp_flags & FC_SP_FT_FPORT) == 0) {
if (e_d_tov > lport->e_d_tov)
lport->e_d_tov = e_d_tov;
-   lport->r_a_tov = 2 * e_d_tov;
+   lport->r_a_tov = 2 * lport->e_d_tov;
fc_lport_set_port_id(lport, did, fp);
printk(KERN_INFO "host%d: libfc: "
   "Port (%6.6x) entered "
@@ -1784,8 +1784,10 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct 
fc_frame *fp,
   get_unaligned_be64(
   >fl_wwnn));
} else {
-   lport->e_d_tov = e_d_tov;
-   lport->r_a_tov = r_a_tov;
+   if (e_d_tov > lport->e_d_tov)
+   lport->e_d_tov = e_d_tov;
+   if (r_a_tov > lport->r_a_tov)
+   lport->r_a_tov = r_a_tov;
fc_host_fabric_name(lport->host) =
get_unaligned_be64(>fl_wwnn);
fc_lport_set_port_id(lport, did, fp);
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 68d4c92..5a9c871 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -1328,13 +1328,15 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct 
fc_frame *fp,
tov = ntohl(rtv->rtv_r_a_tov);
if (tov == 0)
tov = 1;
-   rdata->r_a_tov = tov;
+   if (tov > rdata->r_a_tov)
+   rdata->r_a_tov = tov;
tov = ntohl(rtv->rtv_e_d_tov);
if (toq & FC_ELS_RTV_EDRES)
tov /= 100;
if (tov == 0)
tov = 1;
-   rdata->e_d_tov = tov;
+   if (tov > rdata->e_d_tov)
+   rdata->e_d_tov = tov;
}
}
 
-- 
1.8.5.6

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


[PATCH 05/30] libfc: use configured lport R_A_TOV when sending

2016-08-26 Thread Hannes Reinecke
We should be using the configured R_A_TOV value when sending the
exchange.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_exch.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index f178084..7d0e7ca 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -2135,7 +2135,7 @@ static struct fc_seq *fc_exch_seq_send(struct fc_lport 
*lport,
ep->resp = resp;
ep->destructor = destructor;
ep->arg = arg;
-   ep->r_a_tov = FC_DEF_R_A_TOV;
+   ep->r_a_tov = lport->r_a_tov;
ep->lp = lport;
sp = >seq;
 
-- 
1.8.5.6

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


[PATCH 04/30] libfc: Do not login if the port is already started

2016-08-26 Thread Hannes Reinecke
When the port is already started we don't need to login; that
will only confuse the state machine.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_rport.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index a37b37b..2406276 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -420,6 +420,12 @@ static int fc_rport_login(struct fc_rport_priv *rdata)
 {
mutex_lock(>rp_mutex);
 
+   if (rdata->flags & FC_RP_STARTED) {
+   FC_RPORT_DBG(rdata, "port already started\n");
+   mutex_unlock(>rp_mutex);
+   return 0;
+   }
+
rdata->flags |= FC_RP_STARTED;
switch (rdata->rp_state) {
case RPORT_ST_READY:
-- 
1.8.5.6

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


[PATCH 16/30] libfc: Clarify ramp-down messages

2016-08-26 Thread Hannes Reinecke
When the queue depth is reduced we should print out the reason
for this; it might be due to a queue full condition.

Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/libfc/fc_fcp.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index a667c8c..abddfe2 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -403,8 +403,6 @@ static void fc_fcp_can_queue_ramp_down(struct fc_lport 
*lport)
if (!can_queue)
can_queue = 1;
lport->host->can_queue = can_queue;
-   shost_printk(KERN_ERR, lport->host, "libfc: Could not allocate frame.\n"
-"Reducing can_queue to %d.\n", can_queue);
 
 unlock:
spin_unlock_irqrestore(lport->host->host_lock, flags);
@@ -431,6 +429,9 @@ static inline struct fc_frame *fc_fcp_frame_alloc(struct 
fc_lport *lport,
put_cpu();
/* error case */
fc_fcp_can_queue_ramp_down(lport);
+   shost_printk(KERN_ERR, lport->host,
+"libfc: Could not allocate frame, "
+"reducing can_queue to %d.\n", lport->host->can_queue);
return NULL;
 }
 
@@ -1861,8 +1862,13 @@ int fc_queuecommand(struct Scsi_Host *shost, struct 
scsi_cmnd *sc_cmd)
rpriv = rport->dd_data;
 
if (!fc_fcp_lport_queue_ready(lport)) {
-   if (lport->qfull)
+   if (lport->qfull) {
fc_fcp_can_queue_ramp_down(lport);
+   shost_printk(KERN_ERR, lport->host,
+"libfc: queue full, "
+"reducing can_queue to %d.\n",
+lport->host->can_queue);
+   }
rc = SCSI_MLQUEUE_HOST_BUSY;
goto out;
}
-- 
1.8.5.6

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


[PATCH 1/1] ses: Retry UNIT ATTENTION for receive diagnostics

2016-08-26 Thread Brian King

If the ses driver receives a UNIT ATTENTION when issuing
a receive diagnostics while probing a SES device, it
fails to attach with messages such as:

scsi 1:0:7:0: Failed to get diagnostic page 0x802
scsi 1:0:7:0: Failed to bind enclosure -19

Fix this by eating unit attentions for these commands.

Cc: 
Suggested-by: Wen Xiong 
Signed-off-by: Brian King 
---

 drivers/scsi/ses.c |   13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff -puN drivers/scsi/ses.c~ses_rcv_diag_retry drivers/scsi/ses.c
--- linux-2.6.git/drivers/scsi/ses.c~ses_rcv_diag_retry 2016-08-25 
18:28:18.720565322 -0500
+++ linux-2.6.git-bjking1/drivers/scsi/ses.c2016-08-25 18:28:29.687496342 
-0500
@@ -86,7 +86,7 @@ static void init_device_slot_control(uns
 static int ses_recv_diag(struct scsi_device *sdev, int page_code,
 void *buf, int bufflen)
 {
-   int ret;
+   int ret, retries = SES_RETRIES;
unsigned char cmd[] = {
RECEIVE_DIAGNOSTIC,
1,  /* Set PCV bit */
@@ -96,11 +96,14 @@ static int ses_recv_diag(struct scsi_dev
0
};
unsigned char recv_page_code;
+   struct scsi_sense_hdr sshdr;
 
-   ret =  scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen,
-   NULL, SES_TIMEOUT, SES_RETRIES, NULL);
-   if (unlikely(!ret))
-   return ret;
+   do {
+   memset(, 0, sizeof(sshdr));
+   ret =  scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, 
bufflen,
+   , SES_TIMEOUT, retries, NULL);
+   } while (scsi_sense_valid() &&
+sshdr.sense_key == UNIT_ATTENTION && --retries);
 
recv_page_code = ((unsigned char *)buf)[0];
 
_

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


[PATCH v2 0/3] be2iscsi: cleanup of 11.2 in 4.9/scsi-queue

2016-08-26 Thread Jitendra Bhivare
These patches address some auto built issues of 11.2.0.0 be2iscsi
committed in 4.9/scsi-queue.

v2 changes:
Added NULL check for pwrb_handle in PATCH v2 2/3

Christophe JAILLET (1):
  be2iscsi: Fix error return code

Jitendra Bhivare (2):
  be2iscsi: Remove redundant iscsi_wrb desc memset
  be2iscsi: Add missing unlock for mbox_lock

 drivers/scsi/be2iscsi/be_main.c | 27 ---
 drivers/scsi/be2iscsi/be_mgmt.c |  7 +++
 2 files changed, 19 insertions(+), 15 deletions(-)

-- 
2.7.4

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


[PATCH v2 2/3] be2iscsi: Remove redundant iscsi_wrb desc memset

2016-08-26 Thread Jitendra Bhivare
alloc_wrb_handle already does memset zero of iscsi_wrb descriptor so
remove redundant memset in WRB submission paths.

Add pwrb_handle NULL check before memsett'ing pwrb.

Signed-off-by: Jitendra Bhivare 
---
 drivers/scsi/be2iscsi/be_main.c | 5 +++--
 drivers/scsi/be2iscsi/be_mgmt.c | 3 ---
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index b30db87..6a6906f 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -967,7 +967,9 @@ beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context,
else
pwrb_context->alloc_index++;
spin_unlock_bh(_context->wrb_lock);
-   memset(pwrb_handle->pwrb, 0, sizeof(*pwrb_handle->pwrb));
+
+   if (pwrb_handle)
+   memset(pwrb_handle->pwrb, 0, sizeof(*pwrb_handle->pwrb));
 
return pwrb_handle;
 }
@@ -4718,7 +4720,6 @@ static int beiscsi_mtask(struct iscsi_task *task)
 
cid = beiscsi_conn->beiscsi_conn_cid;
pwrb = io_task->pwrb_handle->pwrb;
-   memset(pwrb, 0, sizeof(*pwrb));
 
if (is_chip_be2_be3r(phba)) {
AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb,
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index 3ac7b88..b9ff939 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -1350,7 +1350,6 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params 
*params,
 {
struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
 
-   memset(pwrb, 0, sizeof(*pwrb));
AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
  max_send_data_segment_length, pwrb,
  params->dw[offsetof(struct amap_beiscsi_offload_params,
@@ -1422,8 +1421,6 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params 
*params,
 {
struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
 
-   memset(pwrb, 0, sizeof(*pwrb));
-
AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
  max_burst_length, pwrb, params->dw[offsetof
  (struct amap_beiscsi_offload_params,
-- 
2.7.4

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


[PATCH v2 1/3] be2iscsi: Fix error return code

2016-08-26 Thread Jitendra Bhivare
From: Christophe JAILLET 

We know that 'ret' is not an error code because it has been tested a few
lines above.
So, if one of these function fails, 0 will be returned instead of an error
code.
Return -ENOMEM instead.

Signed-off-by: Christophe JAILLET 

'ret' needs to be set with error code if hba_setup_cid_tbls fails.

Signed-off-by: Jitendra Bhivare 
---
 drivers/scsi/be2iscsi/be_main.c | 22 +-
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 222edfc..b30db87 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -3017,8 +3017,8 @@ static int be_fill_queue(struct be_queue_info *q,
 static int beiscsi_create_eqs(struct beiscsi_hba *phba,
 struct hwi_context_memory *phwi_context)
 {
+   int ret = -ENOMEM, eq_for_mcc;
unsigned int i, num_eq_pages;
-   int ret = 0, eq_for_mcc;
struct be_queue_info *eq;
struct be_dma_mem *mem;
void *eq_vaddress;
@@ -3036,8 +3036,8 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba,
mem = >dma_mem;
phwi_context->be_eq[i].phba = phba;
eq_vaddress = pci_alloc_consistent(phba->pcidev,
-num_eq_pages * PAGE_SIZE,
-);
+  num_eq_pages * PAGE_SIZE,
+  );
if (!eq_vaddress)
goto create_eq_error;
 
@@ -3065,6 +3065,7 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba,
phwi_context->be_eq[i].q.id);
}
return 0;
+
 create_eq_error:
for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) {
eq = _context->be_eq[i].q;
@@ -3081,11 +3082,11 @@ static int beiscsi_create_cqs(struct beiscsi_hba *phba,
 struct hwi_context_memory *phwi_context)
 {
unsigned int i, num_cq_pages;
-   int ret = 0;
struct be_queue_info *cq, *eq;
struct be_dma_mem *mem;
struct be_eq_obj *pbe_eq;
void *cq_vaddress;
+   int ret = -ENOMEM;
dma_addr_t paddr;
 
num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \
@@ -3099,10 +3100,11 @@ static int beiscsi_create_cqs(struct beiscsi_hba *phba,
pbe_eq->phba = phba;
mem = >dma_mem;
cq_vaddress = pci_alloc_consistent(phba->pcidev,
-num_cq_pages * PAGE_SIZE,
-);
+  num_cq_pages * PAGE_SIZE,
+  );
if (!cq_vaddress)
goto create_cq_error;
+
ret = be_fill_queue(cq, phba->params.num_cq_entries,
sizeof(struct sol_cqe), cq_vaddress);
if (ret) {
@@ -3137,7 +3139,6 @@ create_cq_error:
mem->va, mem->dma);
}
return ret;
-
 }
 
 static int
@@ -4230,7 +4231,8 @@ static int beiscsi_init_port(struct beiscsi_hba *phba)
goto do_cleanup_ctrlr;
}
 
-   if (hba_setup_cid_tbls(phba)) {
+   ret = hba_setup_cid_tbls(phba);
+   if (ret < 0) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : Failed in hba_setup_cid_tbls\n");
kfree(phba->io_sgl_hndl_base);
@@ -5627,7 +5629,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
struct hwi_context_memory *phwi_context;
struct be_eq_obj *pbe_eq;
unsigned int s_handle;
-   int ret = 0, i;
+   int ret, i;
 
ret = beiscsi_enable_pci(pcidev);
if (ret < 0) {
@@ -5640,6 +5642,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
if (!phba) {
dev_err(>dev,
"beiscsi_dev_probe - Failed in beiscsi_hba_alloc\n");
+   ret = -ENOMEM;
goto disable_pci;
}
 
@@ -5744,6 +5747,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : beiscsi_dev_probe-"
"Failed to allocate work queue\n");
+   ret = -ENOMEM;
goto free_twq;
}
 
-- 
2.7.4

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


[PATCH v2 3/3] be2iscsi: Add missing unlock for mbox_lock

2016-08-26 Thread Jitendra Bhivare
Julia pointed out beiscsi_boot_get_sinfo does not unlock
mbox_lock on nonemb_cmd memory allocation failure.

Signed-off-by: Jitendra Bhivare 
---
 drivers/scsi/be2iscsi/be_mgmt.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index b9ff939..aebc4dd 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -1085,8 +1085,10 @@ unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba 
*phba)
nonemb_cmd->va = pci_alloc_consistent(phba->ctrl.pdev,
  sizeof(nonemb_cmd->size),
  _cmd->dma);
-   if (!nonemb_cmd->va)
+   if (!nonemb_cmd->va) {
+   mutex_unlock(>mbox_lock);
return 0;
+   }
 
req = nonemb_cmd->va;
memset(req, 0, sizeof(*req));
-- 
2.7.4

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