]> Pileus Git - ~andy/linux/blobdiff - drivers/target/target_core_device.c
Merge tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux-2.6
[~andy/linux] / drivers / target / target_core_device.c
index edbcabbf85f7339d1eddef7d618b26181540cd5a..aa6267746383b5070148ac894d27d1706e14e144 100644 (file)
@@ -72,7 +72,7 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
        }
 
        spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags);
-       se_cmd->se_deve = &se_sess->se_node_acl->device_list[unpacked_lun];
+       se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun];
        if (se_cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
                struct se_dev_entry *deve = se_cmd->se_deve;
 
@@ -159,13 +159,8 @@ int transport_lookup_cmd_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
                dev->read_bytes += se_cmd->data_length;
        spin_unlock_irqrestore(&dev->stats_lock, flags);
 
-       /*
-        * Add the iscsi_cmd_t to the struct se_lun's cmd list.  This list is used
-        * for tracking state of struct se_cmds during LUN shutdown events.
-        */
        spin_lock_irqsave(&se_lun->lun_cmd_lock, flags);
        list_add_tail(&se_cmd->se_lun_node, &se_lun->lun_cmd_list);
-       atomic_set(&se_cmd->transport_lun_active, 1);
        spin_unlock_irqrestore(&se_lun->lun_cmd_lock, flags);
 
        return 0;
@@ -187,7 +182,7 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u32 unpacked_lun)
        }
 
        spin_lock_irqsave(&se_sess->se_node_acl->device_list_lock, flags);
-       se_cmd->se_deve = &se_sess->se_node_acl->device_list[unpacked_lun];
+       se_cmd->se_deve = se_sess->se_node_acl->device_list[unpacked_lun];
        deve = se_cmd->se_deve;
 
        if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
@@ -245,7 +240,7 @@ struct se_dev_entry *core_get_se_deve_from_rtpi(
 
        spin_lock_irq(&nacl->device_list_lock);
        for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
-               deve = &nacl->device_list[i];
+               deve = nacl->device_list[i];
 
                if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
                        continue;
@@ -291,7 +286,7 @@ int core_free_device_list_for_node(
 
        spin_lock_irq(&nacl->device_list_lock);
        for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
-               deve = &nacl->device_list[i];
+               deve = nacl->device_list[i];
 
                if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
                        continue;
@@ -311,7 +306,7 @@ int core_free_device_list_for_node(
        }
        spin_unlock_irq(&nacl->device_list_lock);
 
-       kfree(nacl->device_list);
+       array_free(nacl->device_list, TRANSPORT_MAX_LUNS_PER_TPG);
        nacl->device_list = NULL;
 
        return 0;
@@ -323,7 +318,7 @@ void core_dec_lacl_count(struct se_node_acl *se_nacl, struct se_cmd *se_cmd)
        unsigned long flags;
 
        spin_lock_irqsave(&se_nacl->device_list_lock, flags);
-       deve = &se_nacl->device_list[se_cmd->orig_fe_lun];
+       deve = se_nacl->device_list[se_cmd->orig_fe_lun];
        deve->deve_cmds--;
        spin_unlock_irqrestore(&se_nacl->device_list_lock, flags);
 }
@@ -336,7 +331,7 @@ void core_update_device_list_access(
        struct se_dev_entry *deve;
 
        spin_lock_irq(&nacl->device_list_lock);
-       deve = &nacl->device_list[mapped_lun];
+       deve = nacl->device_list[mapped_lun];
        if (lun_access & TRANSPORT_LUNFLAGS_READ_WRITE) {
                deve->lun_flags &= ~TRANSPORT_LUNFLAGS_READ_ONLY;
                deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_WRITE;
@@ -361,7 +356,7 @@ int core_update_device_list_for_node(
        int enable)
 {
        struct se_port *port = lun->lun_sep;
-       struct se_dev_entry *deve = &nacl->device_list[mapped_lun];
+       struct se_dev_entry *deve = nacl->device_list[mapped_lun];
        int trans = 0;
        /*
         * If the MappedLUN entry is being disabled, the entry in
@@ -475,7 +470,7 @@ void core_clear_lun_from_tpg(struct se_lun *lun, struct se_portal_group *tpg)
 
                spin_lock_irq(&nacl->device_list_lock);
                for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
-                       deve = &nacl->device_list[i];
+                       deve = nacl->device_list[i];
                        if (lun != deve->se_lun)
                                continue;
                        spin_unlock_irq(&nacl->device_list_lock);
@@ -652,12 +647,13 @@ int target_report_luns(struct se_task *se_task)
 {
        struct se_cmd *se_cmd = se_task->task_se_cmd;
        struct se_dev_entry *deve;
-       struct se_lun *se_lun;
        struct se_session *se_sess = se_cmd->se_sess;
        unsigned char *buf;
-       u32 cdb_offset = 0, lun_count = 0, offset = 8, i;
+       u32 lun_count = 0, offset = 8, i;
 
-       buf = (unsigned char *) transport_kmap_data_sg(se_cmd);
+       buf = transport_kmap_data_sg(se_cmd);
+       if (!buf)
+               return -ENOMEM;
 
        /*
         * If no struct se_session pointer is present, this struct se_cmd is
@@ -672,22 +668,20 @@ int target_report_luns(struct se_task *se_task)
 
        spin_lock_irq(&se_sess->se_node_acl->device_list_lock);
        for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
-               deve = &se_sess->se_node_acl->device_list[i];
+               deve = se_sess->se_node_acl->device_list[i];
                if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
                        continue;
-               se_lun = deve->se_lun;
                /*
                 * We determine the correct LUN LIST LENGTH even once we
                 * have reached the initial allocation length.
                 * See SPC2-R20 7.19.
                 */
                lun_count++;
-               if ((cdb_offset + 8) >= se_cmd->data_length)
+               if ((offset + 8) > se_cmd->data_length)
                        continue;
 
                int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]);
                offset += 8;
-               cdb_offset += 8;
        }
        spin_unlock_irq(&se_sess->se_node_acl->device_list_lock);
 
@@ -695,12 +689,12 @@ int target_report_luns(struct se_task *se_task)
         * See SPC3 r07, page 159.
         */
 done:
-       transport_kunmap_data_sg(se_cmd);
        lun_count *= 8;
        buf[0] = ((lun_count >> 24) & 0xff);
        buf[1] = ((lun_count >> 16) & 0xff);
        buf[2] = ((lun_count >> 8) & 0xff);
        buf[3] = (lun_count & 0xff);
+       transport_kunmap_data_sg(se_cmd);
 
        se_task->task_scsi_status = GOOD;
        transport_complete_task(se_task, 1);
@@ -894,10 +888,15 @@ void se_dev_set_default_attribs(
                                                limits->logical_block_size);
        dev->se_sub_dev->se_dev_attrib.max_sectors = limits->max_sectors;
        /*
-        * Set optimal_sectors from max_sectors, which can be lowered via
-        * configfs.
+        * Set fabric_max_sectors, which is reported in block limits
+        * VPD page (B0h).
         */
-       dev->se_sub_dev->se_dev_attrib.optimal_sectors = limits->max_sectors;
+       dev->se_sub_dev->se_dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS;
+       /*
+        * Set optimal_sectors from fabric_max_sectors, which can be
+        * lowered via configfs.
+        */
+       dev->se_sub_dev->se_dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS;
        /*
         * queue_depth is based on subsystem plugin dependent requirements.
         */
@@ -1229,6 +1228,54 @@ int se_dev_set_max_sectors(struct se_device *dev, u32 max_sectors)
        return 0;
 }
 
+int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors)
+{
+       if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
+               pr_err("dev[%p]: Unable to change SE Device"
+                       " fabric_max_sectors while dev_export_obj: %d count exists\n",
+                       dev, atomic_read(&dev->dev_export_obj.obj_access_count));
+               return -EINVAL;
+       }
+       if (!fabric_max_sectors) {
+               pr_err("dev[%p]: Illegal ZERO value for"
+                       " fabric_max_sectors\n", dev);
+               return -EINVAL;
+       }
+       if (fabric_max_sectors < DA_STATUS_MAX_SECTORS_MIN) {
+               pr_err("dev[%p]: Passed fabric_max_sectors: %u less than"
+                       " DA_STATUS_MAX_SECTORS_MIN: %u\n", dev, fabric_max_sectors,
+                               DA_STATUS_MAX_SECTORS_MIN);
+               return -EINVAL;
+       }
+       if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
+               if (fabric_max_sectors > dev->se_sub_dev->se_dev_attrib.hw_max_sectors) {
+                       pr_err("dev[%p]: Passed fabric_max_sectors: %u"
+                               " greater than TCM/SE_Device max_sectors:"
+                               " %u\n", dev, fabric_max_sectors,
+                               dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
+                        return -EINVAL;
+               }
+       } else {
+               if (fabric_max_sectors > DA_STATUS_MAX_SECTORS_MAX) {
+                       pr_err("dev[%p]: Passed fabric_max_sectors: %u"
+                               " greater than DA_STATUS_MAX_SECTORS_MAX:"
+                               " %u\n", dev, fabric_max_sectors,
+                               DA_STATUS_MAX_SECTORS_MAX);
+                       return -EINVAL;
+               }
+       }
+       /*
+        * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks()
+        */
+       fabric_max_sectors = se_dev_align_max_sectors(fabric_max_sectors,
+                                                     dev->se_sub_dev->se_dev_attrib.block_size);
+
+       dev->se_sub_dev->se_dev_attrib.fabric_max_sectors = fabric_max_sectors;
+       pr_debug("dev[%p]: SE Device max_sectors changed to %u\n",
+                       dev, fabric_max_sectors);
+       return 0;
+}
+
 int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors)
 {
        if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
@@ -1242,10 +1289,10 @@ int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors)
                                " changed for TCM/pSCSI\n", dev);
                return -EINVAL;
        }
-       if (optimal_sectors > dev->se_sub_dev->se_dev_attrib.max_sectors) {
+       if (optimal_sectors > dev->se_sub_dev->se_dev_attrib.fabric_max_sectors) {
                pr_err("dev[%p]: Passed optimal_sectors %u cannot be"
-                       " greater than max_sectors: %u\n", dev,
-                       optimal_sectors, dev->se_sub_dev->se_dev_attrib.max_sectors);
+                       " greater than fabric_max_sectors: %u\n", dev,
+                       optimal_sectors, dev->se_sub_dev->se_dev_attrib.fabric_max_sectors);
                return -EINVAL;
        }
 
@@ -1380,7 +1427,7 @@ struct se_lun *core_get_lun_from_tpg(struct se_portal_group *tpg, u32 unpacked_l
                spin_unlock(&tpg->tpg_lun_lock);
                return NULL;
        }
-       lun = &tpg->tpg_lun_list[unpacked_lun];
+       lun = tpg->tpg_lun_list[unpacked_lun];
 
        if (lun->lun_status != TRANSPORT_LUN_STATUS_FREE) {
                pr_err("%s Logical Unit Number: %u is not free on"
@@ -1413,7 +1460,7 @@ static struct se_lun *core_dev_get_lun(struct se_portal_group *tpg, u32 unpacked
                spin_unlock(&tpg->tpg_lun_lock);
                return NULL;
        }
-       lun = &tpg->tpg_lun_list[unpacked_lun];
+       lun = tpg->tpg_lun_list[unpacked_lun];
 
        if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) {
                pr_err("%s Logical Unit Number: %u is not active on"