diff options
Diffstat (limited to 'drivers/target/loopback/tcm_loop.c')
-rw-r--r-- | drivers/target/loopback/tcm_loop.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index aa2d67997235..3df1c9b8ae6b 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c | |||
@@ -174,6 +174,24 @@ static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd) | |||
174 | sgl_bidi = sdb->table.sgl; | 174 | sgl_bidi = sdb->table.sgl; |
175 | sgl_bidi_count = sdb->table.nents; | 175 | sgl_bidi_count = sdb->table.nents; |
176 | } | 176 | } |
177 | /* | ||
178 | * Because some userspace code via scsi-generic do not memset their | ||
179 | * associated read buffers, go ahead and do that here for type | ||
180 | * SCF_SCSI_CONTROL_SG_IO_CDB. Also note that this is currently | ||
181 | * guaranteed to be a single SGL for SCF_SCSI_CONTROL_SG_IO_CDB | ||
182 | * by target core in transport_generic_allocate_tasks() -> | ||
183 | * transport_generic_cmd_sequencer(). | ||
184 | */ | ||
185 | if (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB && | ||
186 | se_cmd->data_direction == DMA_FROM_DEVICE) { | ||
187 | struct scatterlist *sg = scsi_sglist(sc); | ||
188 | unsigned char *buf = kmap(sg_page(sg)) + sg->offset; | ||
189 | |||
190 | if (buf != NULL) { | ||
191 | memset(buf, 0, sg->length); | ||
192 | kunmap(sg_page(sg)); | ||
193 | } | ||
194 | } | ||
177 | 195 | ||
178 | /* Tell the core about our preallocated memory */ | 196 | /* Tell the core about our preallocated memory */ |
179 | ret = transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc), | 197 | ret = transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc), |
@@ -187,7 +205,7 @@ static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd) | |||
187 | /* | 205 | /* |
188 | * Called from struct target_core_fabric_ops->check_stop_free() | 206 | * Called from struct target_core_fabric_ops->check_stop_free() |
189 | */ | 207 | */ |
190 | static void tcm_loop_check_stop_free(struct se_cmd *se_cmd) | 208 | static int tcm_loop_check_stop_free(struct se_cmd *se_cmd) |
191 | { | 209 | { |
192 | /* | 210 | /* |
193 | * Do not release struct se_cmd's containing a valid TMR | 211 | * Do not release struct se_cmd's containing a valid TMR |
@@ -195,12 +213,13 @@ static void tcm_loop_check_stop_free(struct se_cmd *se_cmd) | |||
195 | * with transport_generic_free_cmd(). | 213 | * with transport_generic_free_cmd(). |
196 | */ | 214 | */ |
197 | if (se_cmd->se_tmr_req) | 215 | if (se_cmd->se_tmr_req) |
198 | return; | 216 | return 0; |
199 | /* | 217 | /* |
200 | * Release the struct se_cmd, which will make a callback to release | 218 | * Release the struct se_cmd, which will make a callback to release |
201 | * struct tcm_loop_cmd * in tcm_loop_deallocate_core_cmd() | 219 | * struct tcm_loop_cmd * in tcm_loop_deallocate_core_cmd() |
202 | */ | 220 | */ |
203 | transport_generic_free_cmd(se_cmd, 0, 0); | 221 | transport_generic_free_cmd(se_cmd, 0); |
222 | return 1; | ||
204 | } | 223 | } |
205 | 224 | ||
206 | static void tcm_loop_release_cmd(struct se_cmd *se_cmd) | 225 | static void tcm_loop_release_cmd(struct se_cmd *se_cmd) |
@@ -290,6 +309,15 @@ static int tcm_loop_queuecommand( | |||
290 | */ | 309 | */ |
291 | tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); | 310 | tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); |
292 | tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; | 311 | tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; |
312 | /* | ||
313 | * Ensure that this tl_tpg reference from the incoming sc->device->id | ||
314 | * has already been configured via tcm_loop_make_naa_tpg(). | ||
315 | */ | ||
316 | if (!tl_tpg->tl_hba) { | ||
317 | set_host_byte(sc, DID_NO_CONNECT); | ||
318 | sc->scsi_done(sc); | ||
319 | return 0; | ||
320 | } | ||
293 | se_tpg = &tl_tpg->tl_se_tpg; | 321 | se_tpg = &tl_tpg->tl_se_tpg; |
294 | /* | 322 | /* |
295 | * Determine the SAM Task Attribute and allocate tl_cmd and | 323 | * Determine the SAM Task Attribute and allocate tl_cmd and |
@@ -366,7 +394,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc) | |||
366 | * Allocate the LUN_RESET TMR | 394 | * Allocate the LUN_RESET TMR |
367 | */ | 395 | */ |
368 | se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd, tl_tmr, | 396 | se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd, tl_tmr, |
369 | TMR_LUN_RESET); | 397 | TMR_LUN_RESET, GFP_KERNEL); |
370 | if (IS_ERR(se_cmd->se_tmr_req)) | 398 | if (IS_ERR(se_cmd->se_tmr_req)) |
371 | goto release; | 399 | goto release; |
372 | /* | 400 | /* |
@@ -388,7 +416,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc) | |||
388 | SUCCESS : FAILED; | 416 | SUCCESS : FAILED; |
389 | release: | 417 | release: |
390 | if (se_cmd) | 418 | if (se_cmd) |
391 | transport_generic_free_cmd(se_cmd, 1, 0); | 419 | transport_generic_free_cmd(se_cmd, 1); |
392 | else | 420 | else |
393 | kmem_cache_free(tcm_loop_cmd_cache, tl_cmd); | 421 | kmem_cache_free(tcm_loop_cmd_cache, tl_cmd); |
394 | kfree(tl_tmr); | 422 | kfree(tl_tmr); |
@@ -1245,6 +1273,9 @@ void tcm_loop_drop_naa_tpg( | |||
1245 | */ | 1273 | */ |
1246 | core_tpg_deregister(se_tpg); | 1274 | core_tpg_deregister(se_tpg); |
1247 | 1275 | ||
1276 | tl_tpg->tl_hba = NULL; | ||
1277 | tl_tpg->tl_tpgt = 0; | ||
1278 | |||
1248 | pr_debug("TCM_Loop_ConfigFS: Deallocated Emulated %s" | 1279 | pr_debug("TCM_Loop_ConfigFS: Deallocated Emulated %s" |
1249 | " Target Port %s,t,0x%04x\n", tcm_loop_dump_proto_id(tl_hba), | 1280 | " Target Port %s,t,0x%04x\n", tcm_loop_dump_proto_id(tl_hba), |
1250 | config_item_name(&wwn->wwn_group.cg_item), tpgt); | 1281 | config_item_name(&wwn->wwn_group.cg_item), tpgt); |