]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/target/target_core_sbc.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
[karo-tx-linux.git] / drivers / target / target_core_sbc.c
index da441b2782ce69066e43ea9ac3fed95c863ebabc..a9dd9469e3bd4ef9af3b3fa334e54f513d60a316 100644 (file)
@@ -99,81 +99,9 @@ static int sbc_emulate_readcapacity_16(struct se_cmd *cmd)
        return 0;
 }
 
-/*
- * Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support.
- * Note this is not used for TCM/pSCSI passthrough
- */
-static int sbc_emulate_unmap(struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-       unsigned char *buf, *ptr = NULL;
-       unsigned char *cdb = &cmd->t_task_cdb[0];
-       sector_t lba;
-       unsigned int size = cmd->data_length, range;
-       int ret = 0, offset;
-       unsigned short dl, bd_dl;
-
-       if (!dev->transport->do_discard) {
-               pr_err("UNMAP emulation not supported for: %s\n",
-                               dev->transport->name);
-               cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-               return -ENOSYS;
-       }
-
-       /* First UNMAP block descriptor starts at 8 byte offset */
-       offset = 8;
-       size -= 8;
-       dl = get_unaligned_be16(&cdb[0]);
-       bd_dl = get_unaligned_be16(&cdb[2]);
-
-       buf = transport_kmap_data_sg(cmd);
-
-       ptr = &buf[offset];
-       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]);
-               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) {
-                       pr_err("blkdev_issue_discard() failed: %d\n",
-                                       ret);
-                       goto err;
-               }
-
-               ptr += 16;
-               size -= 16;
-       }
-
-err:
-       transport_kunmap_data_sg(cmd);
-       if (!ret)
-               target_complete_cmd(cmd, GOOD);
-       return ret;
-}
-
-/*
- * Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support.
- * Note this is not used for TCM/pSCSI passthrough
- */
-static int sbc_emulate_write_same(struct se_cmd *cmd)
+int spc_get_write_same_sectors(struct se_cmd *cmd)
 {
-       struct se_device *dev = cmd->se_dev;
-       sector_t range;
-       sector_t lba = cmd->t_task_lba;
        u32 num_blocks;
-       int ret;
-
-       if (!dev->transport->do_discard) {
-               pr_err("WRITE_SAME emulation not supported"
-                               " for: %s\n", dev->transport->name);
-               cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-               return -ENOSYS;
-       }
 
        if (cmd->t_task_cdb[0] == WRITE_SAME)
                num_blocks = get_unaligned_be16(&cmd->t_task_cdb[7]);
@@ -186,36 +114,13 @@ static int sbc_emulate_write_same(struct se_cmd *cmd)
         * Use the explicit range when non zero is supplied, otherwise calculate
         * the remaining range based on ->get_blocks() - starting LBA.
         */
-       if (num_blocks != 0)
-               range = num_blocks;
-       else
-               range = (dev->transport->get_blocks(dev) - lba) + 1;
-
-       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) {
-               pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n");
-               return ret;
-       }
-
-       target_complete_cmd(cmd, GOOD);
-       return 0;
-}
-
-static int sbc_emulate_synchronize_cache(struct se_cmd *cmd)
-{
-       if (!cmd->se_dev->transport->do_sync_cache) {
-               pr_err("SYNCHRONIZE_CACHE emulation not supported"
-                       " for: %s\n", cmd->se_dev->transport->name);
-               cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-               return -ENOSYS;
-       }
+       if (num_blocks)
+               return num_blocks;
 
-       cmd->se_dev->transport->do_sync_cache(cmd);
-       return 0;
+       return cmd->se_dev->transport->get_blocks(cmd->se_dev) -
+               cmd->t_task_lba + 1;
 }
+EXPORT_SYMBOL(spc_get_write_same_sectors);
 
 static int sbc_emulate_verify(struct se_cmd *cmd)
 {
@@ -501,6 +406,9 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
                                cmd->se_cmd_flags |= SCF_FUA;
                        break;
                case WRITE_SAME_32:
+                       if (!ops->execute_write_same)
+                               goto out_unsupported_cdb;
+
                        sectors = transport_get_sectors_32(cdb);
                        if (!sectors) {
                                pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not"
@@ -513,7 +421,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
 
                        if (sbc_write_same_supported(dev, &cdb[10]) < 0)
                                goto out_unsupported_cdb;
-                       cmd->execute_cmd = sbc_emulate_write_same;
+                       cmd->execute_cmd = ops->execute_write_same;
                        break;
                default:
                        pr_err("VARIABLE_LENGTH_CMD service action"
@@ -541,6 +449,9 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
                break;
        case SYNCHRONIZE_CACHE:
        case SYNCHRONIZE_CACHE_16:
+               if (!ops->execute_sync_cache)
+                       goto out_unsupported_cdb;
+
                /*
                 * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE
                 */
@@ -562,13 +473,19 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
                        if (sbc_check_valid_sectors(cmd) < 0)
                                goto out_invalid_cdb_field;
                }
-               cmd->execute_cmd = sbc_emulate_synchronize_cache;
+               cmd->execute_cmd = ops->execute_sync_cache;
                break;
        case UNMAP:
+               if (!ops->execute_unmap)
+                       goto out_unsupported_cdb;
+
                size = get_unaligned_be16(&cdb[7]);
-               cmd->execute_cmd = sbc_emulate_unmap;
+               cmd->execute_cmd = ops->execute_unmap;
                break;
        case WRITE_SAME_16:
+               if (!ops->execute_write_same)
+                       goto out_unsupported_cdb;
+
                sectors = transport_get_sectors_16(cdb);
                if (!sectors) {
                        pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
@@ -580,9 +497,12 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
 
                if (sbc_write_same_supported(dev, &cdb[1]) < 0)
                        goto out_unsupported_cdb;
-               cmd->execute_cmd = sbc_emulate_write_same;
+               cmd->execute_cmd = ops->execute_write_same;
                break;
        case WRITE_SAME:
+               if (!ops->execute_write_same)
+                       goto out_unsupported_cdb;
+
                sectors = transport_get_sectors_10(cdb);
                if (!sectors) {
                        pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
@@ -598,7 +518,7 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
                 */
                if (sbc_write_same_supported(dev, &cdb[1]) < 0)
                        goto out_unsupported_cdb;
-               cmd->execute_cmd = sbc_emulate_write_same;
+               cmd->execute_cmd = ops->execute_write_same;
                break;
        case VERIFY:
                size = 0;