[PATCH v1 3/3] TARGET/sbc,loopback: Adjust command data length in case pi exists on the wire

2014-06-08 Thread Sagi Grimberg
In various areas of the code, it is assumed that
se_cmd-data_length describes pure data. In case
that protection information exists over the wire
(protect bits is are on) the target core decrease
the protection length from the data length (instead
of each transport peeking in the cdb).

Modify loopback device to include protection information
in the transferred data length (like other scsi transports).

Signed-off-by: Sagi Grimberg sa...@mellanox.com
---
 drivers/target/loopback/tcm_loop.c |   15 ---
 drivers/target/target_core_sbc.c   |   15 +--
 2 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/drivers/target/loopback/tcm_loop.c 
b/drivers/target/loopback/tcm_loop.c
index c886ad1..1f4c015 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -179,7 +179,7 @@ static void tcm_loop_submission_work(struct work_struct 
*work)
struct tcm_loop_hba *tl_hba;
struct tcm_loop_tpg *tl_tpg;
struct scatterlist *sgl_bidi = NULL;
-   u32 sgl_bidi_count = 0;
+   u32 sgl_bidi_count = 0, transfer_length;
int rc;
 
tl_hba = *(struct tcm_loop_hba **)shost_priv(sc-device-host);
@@ -213,12 +213,21 @@ static void tcm_loop_submission_work(struct work_struct 
*work)
 
}
 
-   if (!scsi_prot_sg_count(sc)  scsi_get_prot_op(sc) != SCSI_PROT_NORMAL)
+   transfer_length = scsi_transfer_length(sc);
+   if (!scsi_prot_sg_count(sc) 
+   scsi_get_prot_op(sc) != SCSI_PROT_NORMAL) {
se_cmd-prot_pto = true;
+   /*
+* loopback transport doesn't support
+* WRITE_GENERATE, READ_STRIP protection
+* information operations, go ahead unprotected.
+*/
+   transfer_length = scsi_bufflen(sc);
+   }
 
rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus-se_sess, sc-cmnd,
tl_cmd-tl_sense_buf[0], tl_cmd-sc-device-lun,
-   scsi_bufflen(sc), tcm_loop_sam_attr(sc),
+   transfer_length, tcm_loop_sam_attr(sc),
sc-sc_data_direction, 0,
scsi_sglist(sc), scsi_sg_count(sc),
sgl_bidi, sgl_bidi_count,
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index e022959..06f8ecd 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -665,8 +665,19 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, 
unsigned char *cdb,
 
cmd-prot_type = dev-dev_attrib.pi_prot_type;
cmd-prot_length = dev-prot_length * sectors;
-   pr_debug(%s: prot_type=%d, prot_length=%d prot_op=%d prot_checks=%d\n,
-__func__, cmd-prot_type, cmd-prot_length,
+
+   /**
+* In case protection information exists over the wire
+* we modify command data length to describe pure data.
+* The actual transfer length is data length + protection
+* length
+**/
+   if (protect)
+   cmd-data_length -= cmd-prot_length;
+
+   pr_debug(%s: prot_type=%d, data_length=%d, prot_length=%d 
+prot_op=%d prot_checks=%d\n,
+__func__, cmd-prot_type, cmd-data_length, cmd-prot_length,
 cmd-prot_op, cmd-prot_checks);
 
return true;
-- 
1.7.1

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


[PATCH v1 0/3] Include protection information in iscsi header

2014-06-08 Thread Sagi Grimberg
At the SCSI transport level, there is no distinction between
user data and protection information. Thus, iscsi header field
expected data transfer length should include protection
information.

Patch #1 introduces scsi helpers scsi_transfer_length (compute
wire transfer byte count) and scsi_prot_len (compute protection
information byte count).

Patch #2 modifies iscsi initiator to set correct wire transfer length
in iscsi header data_length field (and modifies iser accordingly).

Patch #3 modifies target core to expect protection information included
in the wire transfer length (and modifies loopback transport to do so).

I have 2 patches that convert lpfc/qla2xxx drivers to use scsi helpers
but these are completely untested at the moment. Once we get this set
to land upstream, I can queue them up as RFCs.

Changes from v0:
- Introduce scsi helpers to compute correct transfer length in the
  presence of protection information (instead of having each transport
  doing the same computation).
- Modify iscsi to set correct transfer length using scsi helpers
- Modify loopback transport to set correct transfer length using
  scsi helpers

Sagi Grimberg (3):
  scsi_cmnd: Introduce scsi_transfer_length helper
  libiscsi, iser: Adjust data_length to include protection information
  TARGET/sbc,loopback: Adjust command data length in case pi exists on
the wire

 drivers/infiniband/ulp/iser/iser_initiator.c |   34 ++
 drivers/scsi/libiscsi.c  |   18 ++--
 drivers/target/loopback/tcm_loop.c   |   15 --
 drivers/target/target_core_sbc.c |   15 -
 include/scsi/scsi_cmnd.h |   39 ++
 5 files changed, 83 insertions(+), 38 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 v1 1/3] scsi_cmnd: Introduce scsi_transfer_length helper

2014-06-08 Thread Sagi Grimberg
In case protection information exists on the wire
scsi transports should include it in the transfer
byte count (even if protection information does not
exist in the host memory space). This helper will
compute the total transfer length from the scsi
command data length and protection attributes.

Signed-off-by: Sagi Grimberg sa...@mellanox.com
---
 include/scsi/scsi_cmnd.h |   39 +++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index dd7c998..84d9593 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -7,6 +7,7 @@
 #include linux/types.h
 #include linux/timer.h
 #include linux/scatterlist.h
+#include scsi/scsi_device.h
 
 struct Scsi_Host;
 struct scsi_device;
@@ -306,4 +307,42 @@ static inline void set_driver_byte(struct scsi_cmnd *cmd, 
char status)
cmd-result = (cmd-result  0x00ff) | (status  24);
 }
 
+static inline unsigned scsi_prot_length(unsigned data_length,
+   unsigned sector_size)
+{
+   switch (sector_size) {
+   case 512:
+   return (data_length  9) * 8;
+   case 1024:
+   return (data_length  10) * 8;
+   case 2048:
+   return (data_length  11) * 8;
+   case 4096:
+   return (data_length  12) * 8;
+   default:
+   return (data_length  ilog2(sector_size)) * 8;
+   }
+}
+
+static inline unsigned scsi_transfer_length(struct scsi_cmnd *cmd)
+{
+   unsigned data_length;
+
+   if (cmd-sc_data_direction == DMA_FROM_DEVICE) {
+   data_length = scsi_in(cmd)-length;
+   if (scsi_get_prot_op(cmd) ==  SCSI_PROT_NORMAL ||
+   scsi_get_prot_op(cmd) ==  SCSI_PROT_READ_INSERT)
+   return data_length;
+   } else {
+   data_length = scsi_out(cmd)-length;
+   if (scsi_get_prot_op(cmd) ==  SCSI_PROT_NORMAL ||
+   scsi_get_prot_op(cmd) ==  SCSI_PROT_WRITE_STRIP)
+   return data_length;
+   }
+
+   /* Protection information exists on the wire */
+   return data_length + scsi_prot_length(data_length,
+ cmd-device-sector_size);
+}
+
 #endif /* _SCSI_SCSI_CMND_H */
-- 
1.7.1

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


[PATCH v1 2/3] libiscsi, iser: Adjust data_length to include protection information

2014-06-08 Thread Sagi Grimberg
In case protection information exists over the wire
iscsi header data_length is required to include it.
Use protection information aware scsi helpers to set
the correct transfer length.

In order to avoid breakage, remove iser transfer length
checks for each task as they are not always true and
somewhat redundant anyway.

Signed-off-by: Sagi Grimberg sa...@mellanox.com
---
 drivers/infiniband/ulp/iser/iser_initiator.c |   34 +++--
 drivers/scsi/libiscsi.c  |   18 +++---
 2 files changed, 19 insertions(+), 33 deletions(-)

diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c 
b/drivers/infiniband/ulp/iser/iser_initiator.c
index 2e2d903..e3b0af5 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -41,11 +41,11 @@
 #include iscsi_iser.h
 
 /* Register user buffer memory and initialize passive rdma
- *  dto descriptor. Total data size is stored in
- *  iser_task-data[ISER_DIR_IN].data_len
+ *  dto descriptor. Data size is stored in
+ *  task-data[ISER_DIR_IN].data_len, Protection size
+ *  os stored in task-prot[ISER_DIR_IN].data_len
  */
-static int iser_prepare_read_cmd(struct iscsi_task *task,
-unsigned int edtl)
+static int iser_prepare_read_cmd(struct iscsi_task *task)
 
 {
struct iscsi_iser_task *iser_task = task-dd_data;
@@ -73,14 +73,6 @@ static int iser_prepare_read_cmd(struct iscsi_task *task,
return err;
}
 
-   if (edtl  iser_task-data[ISER_DIR_IN].data_len) {
-   iser_err(Total data length: %ld, less than EDTL: 
-%d, in READ cmd BHS itt: %d, conn: 0x%p\n,
-iser_task-data[ISER_DIR_IN].data_len, edtl,
-task-itt, iser_task-ib_conn);
-   return -EINVAL;
-   }
-
err = device-iser_reg_rdma_mem(iser_task, ISER_DIR_IN);
if (err) {
iser_err(Failed to set up Data-IN RDMA\n);
@@ -100,8 +92,9 @@ static int iser_prepare_read_cmd(struct iscsi_task *task,
 }
 
 /* Register user buffer memory and initialize passive rdma
- *  dto descriptor. Total data size is stored in
- *  task-data[ISER_DIR_OUT].data_len
+ *  dto descriptor. Data size is stored in
+ *  task-data[ISER_DIR_OUT].data_len, Protection size
+ *  is stored at task-prot[ISER_DIR_OUT].data_len
  */
 static int
 iser_prepare_write_cmd(struct iscsi_task *task,
@@ -135,14 +128,6 @@ iser_prepare_write_cmd(struct iscsi_task *task,
return err;
}
 
-   if (edtl  iser_task-data[ISER_DIR_OUT].data_len) {
-   iser_err(Total data length: %ld, less than EDTL: %d, 
-in WRITE cmd BHS itt: %d, conn: 0x%p\n,
-iser_task-data[ISER_DIR_OUT].data_len,
-edtl, task-itt, task-conn);
-   return -EINVAL;
-   }
-
err = device-iser_reg_rdma_mem(iser_task, ISER_DIR_OUT);
if (err != 0) {
iser_err(Failed to register write cmd RDMA mem\n);
@@ -417,11 +402,12 @@ int iser_send_command(struct iscsi_conn *conn,
if (scsi_prot_sg_count(sc)) {
prot_buf-buf  = scsi_prot_sglist(sc);
prot_buf-size = scsi_prot_sg_count(sc);
-   prot_buf-data_len = sc-prot_sdb-length;
+   prot_buf-data_len = scsi_prot_length(data_buf-data_len,
+ sc-device-sector_size);
}
 
if (hdr-flags  ISCSI_FLAG_CMD_READ) {
-   err = iser_prepare_read_cmd(task, edtl);
+   err = iser_prepare_read_cmd(task);
if (err)
goto send_command_error;
}
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 26dc005..3f46234 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -338,7 +338,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
struct iscsi_session *session = conn-session;
struct scsi_cmnd *sc = task-sc;
struct iscsi_scsi_req *hdr;
-   unsigned hdrlength, cmd_len;
+   unsigned hdrlength, cmd_len, transfer_length;
itt_t itt;
int rc;
 
@@ -391,11 +391,11 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task 
*task)
if (scsi_get_prot_op(sc) != SCSI_PROT_NORMAL)
task-protected = true;
 
+   transfer_length = scsi_transfer_length(sc);
+   hdr-data_length = cpu_to_be32(transfer_length);
if (sc-sc_data_direction == DMA_TO_DEVICE) {
-   unsigned out_len = scsi_out(sc)-length;
struct iscsi_r2t_info *r2t = task-unsol_r2t;
 
-   hdr-data_length = cpu_to_be32(out_len);
hdr-flags |= ISCSI_FLAG_CMD_WRITE;
/*
 * Write counters:
@@ -414,18 +414,19 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task 
*task)
memset(r2t, 0, 

Re: [PATCH-v2 0/6] vhost/scsi: Add T10 PI SGL passthrough support

2014-06-08 Thread Michael S. Tsirkin
On Thu, May 22, 2014 at 02:26:16AM +, Nicholas A. Bellinger wrote:
 From: Nicholas Bellinger n...@linux-iscsi.org
 
 Hi MST, MKP, Paolo  Co,
 
 Here is the v2 patch series for adding T1O protection information (PI)
 SGL passthrough support between virtio-scsi LLD + vhost-scsi fabric
 endpoints.
 
 Following MST's recommendation, it includes the changes for using
 bytes intead of number of iovecs in virtio_scsi_cmd_req_pi along with
 the associated changes to virtio-scsi + vhost/scsi code.
 
 For vhost/scsi, this includes walking the leading iovec's length(s)
 to determine where protection payload ends, and real data payload 
 starts.  For virtio-scsi LLD code, this includes locating struct
 blk_integrity for using blk_rq_sectors + -tuple_size to calculate
 the total bytes for outgoing cmd_pi-pi_bytes[out,in] values.
 
 The full list of changes from last series include:
 
   - Use pi_bytesout + pi_bytesin instead of niovs in virtio-scsi PI
 header (mst + paolo)
   - Add prot_pto=1 in tcm_vhost_submission_work() when no PI buffer
 exists (nab)
   - Get rid of req + cdb pointer casts in vhost_scsi_handle_vq (mst)
   - Ensure that virtio_scsi_cmd_req_pi processing happens regardless
 of data_num in vhost_scsi_handle_vq (nab)
   - Pass TARGET_PROT_ALL into transport_init_session_tags() (nab)
   - Convert vhost_scsi_handle_vq to use memcpy_fromiovecend() (mst)
   - Convert vhost_scsi_handle_vq to use pi_bytesout + pi_bytesin (nab)
   - Convert virtio_scsi_init_hdr_pi() to use pi_bytesout + pi_bytesin
 (mst + paolo + nab)
   - Use blk_integrity-tuple_size to calculate pi bytes (nab)
 
 Please review for v3.16-rc1 code.
 
 Thanks!
 
 --nab


OK, finally went over this, looks good to me:

Acked-by: Michael S. Tsirkin m...@redhat.com

However, we really should stop making more changes
before fixing ANY_LAYOUT in this driver.

virtio 1.0 should be out soon and that makes ANY_LAYOUT
a required feature.



 Nicholas Bellinger (6):
   virtio-scsi.h: Add virtio_scsi_cmd_req_pi + VIRTIO_SCSI_F_T10_PI bits
   vhost/scsi: Move sanity check into vhost_scsi_map_iov_to_sgl
   vhost/scsi: Add preallocation of protection SGLs
   vhost/scsi: Add T10 PI IOV - SGL memory mapping logic
   vhost/scsi: Enable T10 PI IOV - SGL memory mapping
   virtio-scsi: Enable DIF/DIX modes in SCSI host LLD
 
  drivers/scsi/virtio_scsi.c  |   86 +---
  drivers/vhost/scsi.c|  305 
 +--
  include/linux/virtio_scsi.h |   15 ++-
  3 files changed, 292 insertions(+), 114 deletions(-)
 
 -- 
 1.7.10.4
--
To unsubscribe from this list: send the line unsubscribe linux-scsi in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH RESEND] [SCSI] bfa: Fix undefined bit shift on big-endian architectures with 32-bit DMA address

2014-06-08 Thread Ben Hutchings
bfa_swap_words() shifts its argument (assumed to be 64-bit) by 32 bits
each way.  In two places the argument type is dma_addr_t, which may be
32-bit, in which case the effect of the bit shift is undefined:

drivers/scsi/bfa/bfa_fcpim.c: In function 'bfa_ioim_send_ioreq':
drivers/scsi/bfa/bfa_fcpim.c:2497:4: warning: left shift count = width of type 
[enabled by default]
addr = bfa_sgaddr_le(sg_dma_address(sg));
^
drivers/scsi/bfa/bfa_fcpim.c:2497:4: warning: right shift count = width of 
type [enabled by default]
drivers/scsi/bfa/bfa_fcpim.c:2509:4: warning: left shift count = width of type 
[enabled by default]
addr = bfa_sgaddr_le(sg_dma_address(sg));
^
drivers/scsi/bfa/bfa_fcpim.c:2509:4: warning: right shift count = width of 
type [enabled by default]

Avoid this by adding casts to u64 in bfa_swap_words().

Compile-tested only.

Signed-off-by: Ben Hutchings b...@decadent.org.uk
Cc: sta...@vger.kernel.org
Fixes: f16a17507b09 ('[SCSI] bfa: remove all OS wrappers')
---
 drivers/scsi/bfa/bfa_ioc.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index 2e28392..a38aafa0 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -72,7 +72,7 @@ struct bfa_sge_s {
 } while (0)
 
 #define bfa_swap_words(_x)  (  \
-   ((_x)  32) | ((_x)  32))
+   ((u64)(_x)  32) | ((u64)(_x)  32))
 
 #ifdef __BIG_ENDIAN
 #define bfa_sge_to_be(_x)

-- 
Ben Hutchings
Never attribute to conspiracy what can adequately be explained by stupidity.


signature.asc
Description: This is a digitally signed message part


[PATCH RESEND] [SCSI] aic94xx: Remove broken fallback for missing 'Ctrl-A' user settings

2014-06-08 Thread Ben Hutchings
asd_process_ctrl_a_user() attempts to find user settings in flash, and
if they are missing it prepares a substitute structure containing
default values for PHY settings.  But having done so, it will still
try to read user settings - from some random address in flash, as the
local variable 'offs' has not been initialised.

Since asd_common_setup() already sets default PHY settings, there
seems to be no need to repeat them here, and we can just return 0.

Compile-tested only.

Signed-off-by: Ben Hutchings b...@decadent.org.uk
---
 drivers/scsi/aic94xx/aic94xx_sds.c | 18 ++
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c 
b/drivers/scsi/aic94xx/aic94xx_sds.c
index edb43fd..f5d51d2 100644
--- a/drivers/scsi/aic94xx/aic94xx_sds.c
+++ b/drivers/scsi/aic94xx/aic94xx_sds.c
@@ -981,29 +981,15 @@ static int asd_process_ctrla_phy_settings(struct 
asd_ha_struct *asd_ha,
 static int asd_process_ctrl_a_user(struct asd_ha_struct *asd_ha,
   struct asd_flash_dir *flash_dir)
 {
-   int err, i;
+   int err;
u32 offs, size;
struct asd_ll_el *el;
struct asd_ctrla_phy_settings *ps;
-   struct asd_ctrla_phy_settings dflt_ps;
 
err = asd_find_flash_de(flash_dir, FLASH_DE_CTRL_A_USER, offs, size);
if (err) {
ASD_DPRINTK(couldn't find CTRL-A user settings section\n);
-   ASD_DPRINTK(Creating default CTRL-A user settings section\n);
-
-   dflt_ps.id0 = 'h';
-   dflt_ps.num_phys = 8;
-   for (i =0; i  ASD_MAX_PHYS; i++) {
-   memcpy(dflt_ps.phy_ent[i].sas_addr,
-  asd_ha-hw_prof.sas_addr, SAS_ADDR_SIZE);
-   dflt_ps.phy_ent[i].sas_link_rates = 0x98;
-   dflt_ps.phy_ent[i].flags = 0x0;
-   dflt_ps.phy_ent[i].sata_link_rates = 0x0;
-   }
-
-   size = sizeof(struct asd_ctrla_phy_settings);
-   ps = dflt_ps;
+   return 0;
}
 
if (size == 0)


-- 
Ben Hutchings
Never attribute to conspiracy what can adequately be explained by stupidity.


signature.asc
Description: This is a digitally signed message part


[PATCH RESEND] [SCSI] bfa: Fix undefined bit shift on big-endian architectures with 32-bit DMA address

2014-06-08 Thread Ben Hutchings
bfa_swap_words() shifts its argument (assumed to be 64-bit) by 32 bits
each way.  In two places the argument type is dma_addr_t, which may be
32-bit, in which case the effect of the bit shift is undefined:

drivers/scsi/bfa/bfa_fcpim.c: In function 'bfa_ioim_send_ioreq':
drivers/scsi/bfa/bfa_fcpim.c:2497:4: warning: left shift count = width of type 
[enabled by default]
addr = bfa_sgaddr_le(sg_dma_address(sg));
^
drivers/scsi/bfa/bfa_fcpim.c:2497:4: warning: right shift count = width of 
type [enabled by default]
drivers/scsi/bfa/bfa_fcpim.c:2509:4: warning: left shift count = width of type 
[enabled by default]
addr = bfa_sgaddr_le(sg_dma_address(sg));
^
drivers/scsi/bfa/bfa_fcpim.c:2509:4: warning: right shift count = width of 
type [enabled by default]

Avoid this by adding casts to u64 in bfa_swap_words().

Compile-tested only.

Signed-off-by: Ben Hutchings b...@decadent.org.uk
Cc: sta...@vger.kernel.org
Fixes: f16a17507b09 ('[SCSI] bfa: remove all OS wrappers')
---
Resending yet again, this time with current maintainer addresses.

Ben.

 drivers/scsi/bfa/bfa_ioc.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index 2e28392..a38aafa0 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -72,7 +72,7 @@ struct bfa_sge_s {
 } while (0)
 
 #define bfa_swap_words(_x)  (  \
-   ((_x)  32) | ((_x)  32))
+   ((u64)(_x)  32) | ((u64)(_x)  32))
 
 #ifdef __BIG_ENDIAN
 #define bfa_sge_to_be(_x)


-- 
Ben Hutchings
One of the nice things about standards is that there are so many of them.


signature.asc
Description: This is a digitally signed message part