]> Pileus Git - ~andy/linux/blobdiff - drivers/target/target_core_cdb.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs...
[~andy/linux] / drivers / target / target_core_cdb.c
index 418282d926fad6d0e2bd291b5813f3bb5ce55715..8ae09a1bdf74a8744b4884df7cddb792af6f8f0f 100644 (file)
@@ -23,6 +23,7 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+#include <linux/kernel.h>
 #include <asm/unaligned.h>
 #include <scsi/scsi.h>
 
@@ -73,7 +74,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
         * payload going back for EVPD=0
         */
        if (cmd->data_length < 6) {
-               printk(KERN_ERR "SCSI Inquiry payload length: %u"
+               pr_err("SCSI Inquiry payload length: %u"
                        " too small for EVPD=0\n", cmd->data_length);
                return -EINVAL;
        }
@@ -162,11 +163,9 @@ target_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
        struct t10_alua_lu_gp_member *lu_gp_mem;
        struct t10_alua_tg_pt_gp *tg_pt_gp;
        struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
-       unsigned char binary, binary_new;
        unsigned char *prod = &dev->se_sub_dev->t10_wwn.model[0];
        u32 prod_len;
        u32 unit_serial_len, off = 0;
-       int i;
        u16 len = 0, id_len;
 
        off = 4;
@@ -188,11 +187,11 @@ target_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
        /* CODE SET == Binary */
        buf[off++] = 0x1;
 
-       /* Set ASSOICATION == addressed logical unit: 0)b */
+       /* Set ASSOCIATION == addressed logical unit: 0)b */
        buf[off] = 0x00;
 
        /* Identifier/Designator type == NAA identifier */
-       buf[off++] = 0x3;
+       buf[off++] |= 0x3;
        off++;
 
        /* Identifier/Designator length */
@@ -215,16 +214,9 @@ target_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
         * VENDOR_SPECIFIC_IDENTIFIER and
         * VENDOR_SPECIFIC_IDENTIFIER_EXTENTION
         */
-       binary = transport_asciihex_to_binaryhex(
-                               &dev->se_sub_dev->t10_wwn.unit_serial[0]);
-       buf[off++] |= (binary & 0xf0) >> 4;
-       for (i = 0; i < 24; i += 2) {
-               binary_new = transport_asciihex_to_binaryhex(
-                       &dev->se_sub_dev->t10_wwn.unit_serial[i+2]);
-               buf[off] = (binary & 0x0f) << 4;
-               buf[off++] |= (binary_new & 0xf0) >> 4;
-               binary = binary_new;
-       }
+       buf[off++] |= hex_to_bin(dev->se_sub_dev->t10_wwn.unit_serial[0]);
+       hex2bin(&buf[off], &dev->se_sub_dev->t10_wwn.unit_serial[1], 12);
+
        len = 20;
        off = (len + 4);
 
@@ -293,7 +285,7 @@ check_port:
                        (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
                buf[off++] |= 0x1; /* CODE SET == Binary */
                buf[off] = 0x80; /* Set PIV=1 */
-               /* Set ASSOICATION == target port: 01b */
+               /* Set ASSOCIATION == target port: 01b */
                buf[off] |= 0x10;
                /* DESIGNATOR TYPE == Relative target port identifer */
                buf[off++] |= 0x4;
@@ -327,7 +319,7 @@ check_tpgi:
 
                spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
                tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
-               if (!(tg_pt_gp)) {
+               if (!tg_pt_gp) {
                        spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
                        goto check_lu_gp;
                }
@@ -338,7 +330,7 @@ check_tpgi:
                        (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
                buf[off++] |= 0x1; /* CODE SET == Binary */
                buf[off] = 0x80; /* Set PIV=1 */
-               /* Set ASSOICATION == target port: 01b */
+               /* Set ASSOCIATION == target port: 01b */
                buf[off] |= 0x10;
                /* DESIGNATOR TYPE == Target port group identifier */
                buf[off++] |= 0x5;
@@ -358,12 +350,12 @@ check_lu_gp:
                        goto check_scsi_name;
                }
                lu_gp_mem = dev->dev_alua_lu_gp_mem;
-               if (!(lu_gp_mem))
+               if (!lu_gp_mem)
                        goto check_scsi_name;
 
                spin_lock(&lu_gp_mem->lu_gp_mem_lock);
                lu_gp = lu_gp_mem->lu_gp;
-               if (!(lu_gp)) {
+               if (!lu_gp) {
                        spin_unlock(&lu_gp_mem->lu_gp_mem_lock);
                        goto check_scsi_name;
                }
@@ -405,7 +397,7 @@ check_scsi_name:
                        (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
                buf[off++] |= 0x3; /* CODE SET == UTF-8 */
                buf[off] = 0x80; /* Set PIV=1 */
-               /* Set ASSOICATION == target port: 01b */
+               /* Set ASSOCIATION == target port: 01b */
                buf[off] |= 0x10;
                /* DESIGNATOR TYPE == SCSI name string */
                buf[off++] |= 0x8;
@@ -475,14 +467,14 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
                have_tp = 1;
 
        if (cmd->data_length < (0x10 + 4)) {
-               printk(KERN_INFO "Received data_length: %u"
+               pr_debug("Received data_length: %u"
                        " too small for EVPD 0xb0\n",
                        cmd->data_length);
                return -EINVAL;
        }
 
        if (have_tp && cmd->data_length < (0x3c + 4)) {
-               printk(KERN_INFO "Received data_length: %u"
+               pr_debug("Received data_length: %u"
                        " too small for TPE=1 EVPD 0xb0\n",
                        cmd->data_length);
                have_tp = 0;
@@ -491,6 +483,9 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
        buf[0] = dev->transport->get_device_type(dev);
        buf[3] = have_tp ? 0x3c : 0x10;
 
+       /* Set WSNZ to 1 */
+       buf[4] = 0x01;
+
        /*
         * Set OPTIMAL TRANSFER LENGTH GRANULARITY
         */
@@ -667,7 +662,7 @@ target_emulate_inquiry(struct se_cmd *cmd)
         * payload length left for the next outgoing EVPD metadata
         */
        if (cmd->data_length < 4) {
-               printk(KERN_ERR "SCSI Inquiry payload length: %u"
+               pr_err("SCSI Inquiry payload length: %u"
                        " too small for EVPD=1\n", cmd->data_length);
                return -EINVAL;
        }
@@ -685,7 +680,7 @@ target_emulate_inquiry(struct se_cmd *cmd)
                }
 
        transport_kunmap_first_data_page(cmd);
-       printk(KERN_ERR "Unknown VPD Code: 0x%02x\n", cdb[2]);
+       pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]);
        return -EINVAL;
 }
 
@@ -771,6 +766,35 @@ target_modesense_control(struct se_device *dev, unsigned char *p)
        p[0] = 0x0a;
        p[1] = 0x0a;
        p[2] = 2;
+       /*
+        * From spc4r23, 7.4.7 Control mode page
+        *
+        * The QUEUE ALGORITHM MODIFIER field (see table 368) specifies
+        * restrictions on the algorithm used for reordering commands
+        * having the SIMPLE task attribute (see SAM-4).
+        *
+        *                    Table 368 -- QUEUE ALGORITHM MODIFIER field
+        *                         Code      Description
+        *                          0h       Restricted reordering
+        *                          1h       Unrestricted reordering allowed
+        *                          2h to 7h    Reserved
+        *                          8h to Fh    Vendor specific
+        *
+        * A value of zero in the QUEUE ALGORITHM MODIFIER field specifies that
+        * the device server shall order the processing sequence of commands
+        * having the SIMPLE task attribute such that data integrity is maintained
+        * for that I_T nexus (i.e., if the transmission of new SCSI transport protocol
+        * requests is halted at any time, the final value of all data observable
+        * on the medium shall be the same as if all the commands had been processed
+        * with the ORDERED task attribute).
+        *
+        * A value of one in the QUEUE ALGORITHM MODIFIER field specifies that the
+        * device server may reorder the processing sequence of commands having the
+        * SIMPLE task attribute in any manner. Any data integrity exposures related to
+        * command sequence order shall be explicitly handled by the application client
+        * through the selection of appropriate ommands and task attributes.
+        */
+       p[3] = (dev->se_sub_dev->se_dev_attrib.emulate_rest_reord == 1) ? 0x00 : 0x10;
        /*
         * From spc4r17, section 7.4.6 Control mode Page
         *
@@ -891,7 +915,7 @@ target_emulate_modesense(struct se_cmd *cmd, int ten)
                length += target_modesense_control(dev, &buf[offset+length]);
                break;
        default:
-               printk(KERN_ERR "Got Unknown Mode Page: 0x%02x\n",
+               pr_err("Got Unknown Mode Page: 0x%02x\n",
                                cdb[2] & 0x3f);
                return PYX_TRANSPORT_UNKNOWN_MODE_PAGE;
        }
@@ -947,14 +971,14 @@ target_emulate_request_sense(struct se_cmd *cmd)
        int err = 0;
 
        if (cdb[1] & 0x01) {
-               printk(KERN_ERR "REQUEST_SENSE description emulation not"
+               pr_err("REQUEST_SENSE description emulation not"
                        " supported\n");
                return PYX_TRANSPORT_INVALID_CDB_FIELD;
        }
 
        buf = transport_kmap_first_data_page(cmd);
 
-       if (!(core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq))) {
+       if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
                /*
                 * CURRENT ERROR, UNIT ATTENTION
                 */
@@ -1028,18 +1052,18 @@ target_emulate_unmap(struct se_task *task)
        buf = transport_kmap_first_data_page(cmd);
 
        ptr = &buf[offset];
-       printk(KERN_INFO "UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu"
+       pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu"
                " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr);
 
        while (size) {
                lba = get_unaligned_be64(&ptr[0]);
                range = get_unaligned_be32(&ptr[8]);
-               printk(KERN_INFO "UNMAP: Using lba: %llu and range: %u\n",
+               pr_debug("UNMAP: Using lba: %llu and range: %u\n",
                                 (unsigned long long)lba, range);
 
                ret = dev->transport->do_discard(dev, lba, range);
                if (ret < 0) {
-                       printk(KERN_ERR "blkdev_issue_discard() failed: %d\n",
+                       pr_err("blkdev_issue_discard() failed: %d\n",
                                        ret);
                        goto err;
                }
@@ -1084,12 +1108,12 @@ target_emulate_write_same(struct se_task *task, int write_same32)
        else
                range = (dev->transport->get_blocks(dev) - lba);
 
-       printk(KERN_INFO "WRITE_SAME UNMAP: LBA: %llu Range: %llu\n",
+       pr_debug("WRITE_SAME UNMAP: LBA: %llu Range: %llu\n",
                 (unsigned long long)lba, (unsigned long long)range);
 
        ret = dev->transport->do_discard(dev, lba, range);
        if (ret < 0) {
-               printk(KERN_INFO "blkdev_issue_discard() failed for WRITE_SAME\n");
+               pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n");
                return ret;
        }
 
@@ -1125,7 +1149,7 @@ transport_emulate_control_cdb(struct se_task *task)
                        ret = target_emulate_readcapacity_16(cmd);
                        break;
                default:
-                       printk(KERN_ERR "Unsupported SA: 0x%02x\n",
+                       pr_err("Unsupported SA: 0x%02x\n",
                                cmd->t_task_cdb[1] & 0x1f);
                        return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
                }
@@ -1135,7 +1159,7 @@ transport_emulate_control_cdb(struct se_task *task)
                break;
        case UNMAP:
                if (!dev->transport->do_discard) {
-                       printk(KERN_ERR "UNMAP emulation not supported for: %s\n",
+                       pr_err("UNMAP emulation not supported for: %s\n",
                                        dev->transport->name);
                        return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
                }
@@ -1143,7 +1167,7 @@ transport_emulate_control_cdb(struct se_task *task)
                break;
        case WRITE_SAME_16:
                if (!dev->transport->do_discard) {
-                       printk(KERN_ERR "WRITE_SAME_16 emulation not supported"
+                       pr_err("WRITE_SAME_16 emulation not supported"
                                        " for: %s\n", dev->transport->name);
                        return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
                }
@@ -1155,7 +1179,7 @@ transport_emulate_control_cdb(struct se_task *task)
                switch (service_action) {
                case WRITE_SAME_32:
                        if (!dev->transport->do_discard) {
-                               printk(KERN_ERR "WRITE_SAME_32 SA emulation not"
+                               pr_err("WRITE_SAME_32 SA emulation not"
                                        " supported for: %s\n",
                                        dev->transport->name);
                                return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
@@ -1163,7 +1187,7 @@ transport_emulate_control_cdb(struct se_task *task)
                        ret = target_emulate_write_same(task, 1);
                        break;
                default:
-                       printk(KERN_ERR "Unsupported VARIABLE_LENGTH_CMD SA:"
+                       pr_err("Unsupported VARIABLE_LENGTH_CMD SA:"
                                        " 0x%02x\n", service_action);
                        break;
                }
@@ -1171,8 +1195,7 @@ transport_emulate_control_cdb(struct se_task *task)
        case SYNCHRONIZE_CACHE:
        case 0x91: /* SYNCHRONIZE_CACHE_16: */
                if (!dev->transport->do_sync_cache) {
-                       printk(KERN_ERR
-                               "SYNCHRONIZE_CACHE emulation not supported"
+                       pr_err("SYNCHRONIZE_CACHE emulation not supported"
                                " for: %s\n", dev->transport->name);
                        return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
                }
@@ -1189,7 +1212,7 @@ transport_emulate_control_cdb(struct se_task *task)
        case WRITE_FILEMARKS:
                break;
        default:
-               printk(KERN_ERR "Unsupported SCSI Opcode: 0x%02x for %s\n",
+               pr_err("Unsupported SCSI Opcode: 0x%02x for %s\n",
                        cmd->t_task_cdb[0], dev->transport->name);
                return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
        }