aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/loopback
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/target/loopback')
-rw-r--r--drivers/target/loopback/tcm_loop.c363
-rw-r--r--drivers/target/loopback/tcm_loop.h4
2 files changed, 161 insertions, 206 deletions
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index c47ff7f59e57..a9b4eeefe9fc 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -44,138 +44,12 @@
44/* Local pointer to allocated TCM configfs fabric module */ 44/* Local pointer to allocated TCM configfs fabric module */
45static struct target_fabric_configfs *tcm_loop_fabric_configfs; 45static struct target_fabric_configfs *tcm_loop_fabric_configfs;
46 46
47static struct workqueue_struct *tcm_loop_workqueue;
47static struct kmem_cache *tcm_loop_cmd_cache; 48static struct kmem_cache *tcm_loop_cmd_cache;
48 49
49static int tcm_loop_hba_no_cnt; 50static int tcm_loop_hba_no_cnt;
50 51
51/* 52static int tcm_loop_queue_status(struct se_cmd *se_cmd);
52 * Allocate a tcm_loop cmd descriptor from target_core_mod code
53 *
54 * Can be called from interrupt context in tcm_loop_queuecommand() below
55 */
56static struct se_cmd *tcm_loop_allocate_core_cmd(
57 struct tcm_loop_hba *tl_hba,
58 struct se_portal_group *se_tpg,
59 struct scsi_cmnd *sc)
60{
61 struct se_cmd *se_cmd;
62 struct se_session *se_sess;
63 struct tcm_loop_nexus *tl_nexus = tl_hba->tl_nexus;
64 struct tcm_loop_cmd *tl_cmd;
65 int sam_task_attr;
66
67 if (!tl_nexus) {
68 scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus"
69 " does not exist\n");
70 set_host_byte(sc, DID_ERROR);
71 return NULL;
72 }
73 se_sess = tl_nexus->se_sess;
74
75 tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_ATOMIC);
76 if (!tl_cmd) {
77 pr_err("Unable to allocate struct tcm_loop_cmd\n");
78 set_host_byte(sc, DID_ERROR);
79 return NULL;
80 }
81 se_cmd = &tl_cmd->tl_se_cmd;
82 /*
83 * Save the pointer to struct scsi_cmnd *sc
84 */
85 tl_cmd->sc = sc;
86 /*
87 * Locate the SAM Task Attr from struct scsi_cmnd *
88 */
89 if (sc->device->tagged_supported) {
90 switch (sc->tag) {
91 case HEAD_OF_QUEUE_TAG:
92 sam_task_attr = MSG_HEAD_TAG;
93 break;
94 case ORDERED_QUEUE_TAG:
95 sam_task_attr = MSG_ORDERED_TAG;
96 break;
97 default:
98 sam_task_attr = MSG_SIMPLE_TAG;
99 break;
100 }
101 } else
102 sam_task_attr = MSG_SIMPLE_TAG;
103
104 /*
105 * Initialize struct se_cmd descriptor from target_core_mod infrastructure
106 */
107 transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess,
108 scsi_bufflen(sc), sc->sc_data_direction, sam_task_attr,
109 &tl_cmd->tl_sense_buf[0]);
110
111 if (scsi_bidi_cmnd(sc))
112 se_cmd->se_cmd_flags |= SCF_BIDI;
113
114 /*
115 * Locate the struct se_lun pointer and attach it to struct se_cmd
116 */
117 if (transport_lookup_cmd_lun(se_cmd, tl_cmd->sc->device->lun) < 0) {
118 kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
119 set_host_byte(sc, DID_NO_CONNECT);
120 return NULL;
121 }
122
123 return se_cmd;
124}
125
126/*
127 * Called by struct target_core_fabric_ops->new_cmd_map()
128 *
129 * Always called in process context. A non zero return value
130 * here will signal to handle an exception based on the return code.
131 */
132static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd)
133{
134 struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
135 struct tcm_loop_cmd, tl_se_cmd);
136 struct scsi_cmnd *sc = tl_cmd->sc;
137 struct scatterlist *sgl_bidi = NULL;
138 u32 sgl_bidi_count = 0;
139 int ret;
140 /*
141 * Allocate the necessary tasks to complete the received CDB+data
142 */
143 ret = transport_generic_allocate_tasks(se_cmd, sc->cmnd);
144 if (ret != 0)
145 return ret;
146 /*
147 * For BIDI commands, pass in the extra READ buffer
148 * to transport_generic_map_mem_to_cmd() below..
149 */
150 if (se_cmd->se_cmd_flags & SCF_BIDI) {
151 struct scsi_data_buffer *sdb = scsi_in(sc);
152
153 sgl_bidi = sdb->table.sgl;
154 sgl_bidi_count = sdb->table.nents;
155 }
156 /*
157 * Because some userspace code via scsi-generic do not memset their
158 * associated read buffers, go ahead and do that here for type
159 * SCF_SCSI_CONTROL_SG_IO_CDB. Also note that this is currently
160 * guaranteed to be a single SGL for SCF_SCSI_CONTROL_SG_IO_CDB
161 * by target core in transport_generic_allocate_tasks() ->
162 * transport_generic_cmd_sequencer().
163 */
164 if (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB &&
165 se_cmd->data_direction == DMA_FROM_DEVICE) {
166 struct scatterlist *sg = scsi_sglist(sc);
167 unsigned char *buf = kmap(sg_page(sg)) + sg->offset;
168
169 if (buf != NULL) {
170 memset(buf, 0, sg->length);
171 kunmap(sg_page(sg));
172 }
173 }
174
175 /* Tell the core about our preallocated memory */
176 return transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc),
177 scsi_sg_count(sc), sgl_bidi, sgl_bidi_count);
178}
179 53
180/* 54/*
181 * Called from struct target_core_fabric_ops->check_stop_free() 55 * Called from struct target_core_fabric_ops->check_stop_free()
@@ -187,7 +61,7 @@ static int tcm_loop_check_stop_free(struct se_cmd *se_cmd)
187 * pointer. These will be released directly in tcm_loop_device_reset() 61 * pointer. These will be released directly in tcm_loop_device_reset()
188 * with transport_generic_free_cmd(). 62 * with transport_generic_free_cmd().
189 */ 63 */
190 if (se_cmd->se_tmr_req) 64 if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
191 return 0; 65 return 0;
192 /* 66 /*
193 * Release the struct se_cmd, which will make a callback to release 67 * Release the struct se_cmd, which will make a callback to release
@@ -263,50 +137,152 @@ static int tcm_loop_change_queue_depth(
263} 137}
264 138
265/* 139/*
266 * Main entry point from struct scsi_host_template for incoming SCSI CDB+Data 140 * Locate the SAM Task Attr from struct scsi_cmnd *
267 * from Linux/SCSI subsystem for SCSI low level device drivers (LLDs)
268 */ 141 */
269static int tcm_loop_queuecommand( 142static int tcm_loop_sam_attr(struct scsi_cmnd *sc)
270 struct Scsi_Host *sh,
271 struct scsi_cmnd *sc)
272{ 143{
273 struct se_cmd *se_cmd; 144 if (sc->device->tagged_supported) {
274 struct se_portal_group *se_tpg; 145 switch (sc->tag) {
146 case HEAD_OF_QUEUE_TAG:
147 return MSG_HEAD_TAG;
148 case ORDERED_QUEUE_TAG:
149 return MSG_ORDERED_TAG;
150 default:
151 break;
152 }
153 }
154
155 return MSG_SIMPLE_TAG;
156}
157
158static void tcm_loop_submission_work(struct work_struct *work)
159{
160 struct tcm_loop_cmd *tl_cmd =
161 container_of(work, struct tcm_loop_cmd, work);
162 struct se_cmd *se_cmd = &tl_cmd->tl_se_cmd;
163 struct scsi_cmnd *sc = tl_cmd->sc;
164 struct tcm_loop_nexus *tl_nexus;
275 struct tcm_loop_hba *tl_hba; 165 struct tcm_loop_hba *tl_hba;
276 struct tcm_loop_tpg *tl_tpg; 166 struct tcm_loop_tpg *tl_tpg;
167 struct scatterlist *sgl_bidi = NULL;
168 u32 sgl_bidi_count = 0;
169 int ret;
277 170
278 pr_debug("tcm_loop_queuecommand() %d:%d:%d:%d got CDB: 0x%02x"
279 " scsi_buf_len: %u\n", sc->device->host->host_no,
280 sc->device->id, sc->device->channel, sc->device->lun,
281 sc->cmnd[0], scsi_bufflen(sc));
282 /*
283 * Locate the tcm_loop_hba_t pointer
284 */
285 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); 171 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
286 tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; 172 tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
173
287 /* 174 /*
288 * Ensure that this tl_tpg reference from the incoming sc->device->id 175 * Ensure that this tl_tpg reference from the incoming sc->device->id
289 * has already been configured via tcm_loop_make_naa_tpg(). 176 * has already been configured via tcm_loop_make_naa_tpg().
290 */ 177 */
291 if (!tl_tpg->tl_hba) { 178 if (!tl_tpg->tl_hba) {
292 set_host_byte(sc, DID_NO_CONNECT); 179 set_host_byte(sc, DID_NO_CONNECT);
293 sc->scsi_done(sc); 180 goto out_done;
294 return 0;
295 } 181 }
296 se_tpg = &tl_tpg->tl_se_tpg; 182
183 tl_nexus = tl_hba->tl_nexus;
184 if (!tl_nexus) {
185 scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus"
186 " does not exist\n");
187 set_host_byte(sc, DID_ERROR);
188 goto out_done;
189 }
190
191 transport_init_se_cmd(se_cmd, tl_tpg->tl_se_tpg.se_tpg_tfo,
192 tl_nexus->se_sess,
193 scsi_bufflen(sc), sc->sc_data_direction,
194 tcm_loop_sam_attr(sc), &tl_cmd->tl_sense_buf[0]);
195
196 if (scsi_bidi_cmnd(sc)) {
197 struct scsi_data_buffer *sdb = scsi_in(sc);
198
199 sgl_bidi = sdb->table.sgl;
200 sgl_bidi_count = sdb->table.nents;
201 se_cmd->se_cmd_flags |= SCF_BIDI;
202
203 }
204
205 if (transport_lookup_cmd_lun(se_cmd, tl_cmd->sc->device->lun) < 0) {
206 kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
207 set_host_byte(sc, DID_NO_CONNECT);
208 goto out_done;
209 }
210
297 /* 211 /*
298 * Determine the SAM Task Attribute and allocate tl_cmd and 212 * Because some userspace code via scsi-generic do not memset their
299 * tl_cmd->tl_se_cmd from TCM infrastructure 213 * associated read buffers, go ahead and do that here for type
214 * SCF_SCSI_CONTROL_SG_IO_CDB. Also note that this is currently
215 * guaranteed to be a single SGL for SCF_SCSI_CONTROL_SG_IO_CDB
216 * by target core in transport_generic_allocate_tasks() ->
217 * transport_generic_cmd_sequencer().
300 */ 218 */
301 se_cmd = tcm_loop_allocate_core_cmd(tl_hba, se_tpg, sc); 219 if (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB &&
302 if (!se_cmd) { 220 se_cmd->data_direction == DMA_FROM_DEVICE) {
221 struct scatterlist *sg = scsi_sglist(sc);
222 unsigned char *buf = kmap(sg_page(sg)) + sg->offset;
223
224 if (buf != NULL) {
225 memset(buf, 0, sg->length);
226 kunmap(sg_page(sg));
227 }
228 }
229
230 ret = transport_generic_allocate_tasks(se_cmd, sc->cmnd);
231 if (ret == -ENOMEM) {
232 transport_send_check_condition_and_sense(se_cmd,
233 TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
234 transport_generic_free_cmd(se_cmd, 0);
235 return;
236 } else if (ret < 0) {
237 if (se_cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)
238 tcm_loop_queue_status(se_cmd);
239 else
240 transport_send_check_condition_and_sense(se_cmd,
241 se_cmd->scsi_sense_reason, 0);
242 transport_generic_free_cmd(se_cmd, 0);
243 return;
244 }
245
246 ret = transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc),
247 scsi_sg_count(sc), sgl_bidi, sgl_bidi_count);
248 if (ret) {
249 transport_send_check_condition_and_sense(se_cmd,
250 se_cmd->scsi_sense_reason, 0);
251 transport_generic_free_cmd(se_cmd, 0);
252 return;
253 }
254 transport_handle_cdb_direct(se_cmd);
255 return;
256
257out_done:
258 sc->scsi_done(sc);
259 return;
260}
261
262/*
263 * ->queuecommand can be and usually is called from interrupt context, so
264 * defer the actual submission to a workqueue.
265 */
266static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
267{
268 struct tcm_loop_cmd *tl_cmd;
269
270 pr_debug("tcm_loop_queuecommand() %d:%d:%d:%d got CDB: 0x%02x"
271 " scsi_buf_len: %u\n", sc->device->host->host_no,
272 sc->device->id, sc->device->channel, sc->device->lun,
273 sc->cmnd[0], scsi_bufflen(sc));
274
275 tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_ATOMIC);
276 if (!tl_cmd) {
277 pr_err("Unable to allocate struct tcm_loop_cmd\n");
278 set_host_byte(sc, DID_ERROR);
303 sc->scsi_done(sc); 279 sc->scsi_done(sc);
304 return 0; 280 return 0;
305 } 281 }
306 /* 282
307 * Queue up the newly allocated to be processed in TCM thread context. 283 tl_cmd->sc = sc;
308 */ 284 INIT_WORK(&tl_cmd->work, tcm_loop_submission_work);
309 transport_generic_handle_cdb_map(se_cmd); 285 queue_work(tcm_loop_workqueue, &tl_cmd->work);
310 return 0; 286 return 0;
311} 287}
312 288
@@ -324,7 +300,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
324 struct tcm_loop_nexus *tl_nexus; 300 struct tcm_loop_nexus *tl_nexus;
325 struct tcm_loop_tmr *tl_tmr = NULL; 301 struct tcm_loop_tmr *tl_tmr = NULL;
326 struct tcm_loop_tpg *tl_tpg; 302 struct tcm_loop_tpg *tl_tpg;
327 int ret = FAILED; 303 int ret = FAILED, rc;
328 /* 304 /*
329 * Locate the tcm_loop_hba_t pointer 305 * Locate the tcm_loop_hba_t pointer
330 */ 306 */
@@ -365,12 +341,9 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
365 transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, 0, 341 transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, 0,
366 DMA_NONE, MSG_SIMPLE_TAG, 342 DMA_NONE, MSG_SIMPLE_TAG,
367 &tl_cmd->tl_sense_buf[0]); 343 &tl_cmd->tl_sense_buf[0]);
368 /* 344
369 * Allocate the LUN_RESET TMR 345 rc = core_tmr_alloc_req(se_cmd, tl_tmr, TMR_LUN_RESET, GFP_KERNEL);
370 */ 346 if (rc < 0)
371 se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd, tl_tmr,
372 TMR_LUN_RESET, GFP_KERNEL);
373 if (IS_ERR(se_cmd->se_tmr_req))
374 goto release; 347 goto release;
375 /* 348 /*
376 * Locate the underlying TCM struct se_lun from sc->device->lun 349 * Locate the underlying TCM struct se_lun from sc->device->lun
@@ -762,22 +735,6 @@ static u32 tcm_loop_get_inst_index(struct se_portal_group *se_tpg)
762 return 1; 735 return 1;
763} 736}
764 737
765static int tcm_loop_is_state_remove(struct se_cmd *se_cmd)
766{
767 /*
768 * Assume struct scsi_cmnd is not in remove state..
769 */
770 return 0;
771}
772
773static int tcm_loop_sess_logged_in(struct se_session *se_sess)
774{
775 /*
776 * Assume that TL Nexus is always active
777 */
778 return 1;
779}
780
781static u32 tcm_loop_sess_get_index(struct se_session *se_sess) 738static u32 tcm_loop_sess_get_index(struct se_session *se_sess)
782{ 739{
783 return 1; 740 return 1;
@@ -811,19 +768,6 @@ static void tcm_loop_close_session(struct se_session *se_sess)
811 return; 768 return;
812}; 769};
813 770
814static void tcm_loop_stop_session(
815 struct se_session *se_sess,
816 int sess_sleep,
817 int conn_sleep)
818{
819 return;
820}
821
822static void tcm_loop_fall_back_to_erl0(struct se_session *se_sess)
823{
824 return;
825}
826
827static int tcm_loop_write_pending(struct se_cmd *se_cmd) 771static int tcm_loop_write_pending(struct se_cmd *se_cmd)
828{ 772{
829 /* 773 /*
@@ -855,6 +799,9 @@ static int tcm_loop_queue_data_in(struct se_cmd *se_cmd)
855 799
856 sc->result = SAM_STAT_GOOD; 800 sc->result = SAM_STAT_GOOD;
857 set_host_byte(sc, DID_OK); 801 set_host_byte(sc, DID_OK);
802 if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
803 (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT))
804 scsi_set_resid(sc, se_cmd->residual_count);
858 sc->scsi_done(sc); 805 sc->scsi_done(sc);
859 return 0; 806 return 0;
860} 807}
@@ -880,6 +827,9 @@ static int tcm_loop_queue_status(struct se_cmd *se_cmd)
880 sc->result = se_cmd->scsi_status; 827 sc->result = se_cmd->scsi_status;
881 828
882 set_host_byte(sc, DID_OK); 829 set_host_byte(sc, DID_OK);
830 if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
831 (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT))
832 scsi_set_resid(sc, se_cmd->residual_count);
883 sc->scsi_done(sc); 833 sc->scsi_done(sc);
884 return 0; 834 return 0;
885} 835}
@@ -1361,7 +1311,6 @@ static struct configfs_attribute *tcm_loop_wwn_attrs[] = {
1361static int tcm_loop_register_configfs(void) 1311static int tcm_loop_register_configfs(void)
1362{ 1312{
1363 struct target_fabric_configfs *fabric; 1313 struct target_fabric_configfs *fabric;
1364 struct config_group *tf_cg;
1365 int ret; 1314 int ret;
1366 /* 1315 /*
1367 * Set the TCM Loop HBA counter to zero 1316 * Set the TCM Loop HBA counter to zero
@@ -1407,14 +1356,10 @@ static int tcm_loop_register_configfs(void)
1407 /* 1356 /*
1408 * Used for setting up remaining TCM resources in process context 1357 * Used for setting up remaining TCM resources in process context
1409 */ 1358 */
1410 fabric->tf_ops.new_cmd_map = &tcm_loop_new_cmd_map;
1411 fabric->tf_ops.check_stop_free = &tcm_loop_check_stop_free; 1359 fabric->tf_ops.check_stop_free = &tcm_loop_check_stop_free;
1412 fabric->tf_ops.release_cmd = &tcm_loop_release_cmd; 1360 fabric->tf_ops.release_cmd = &tcm_loop_release_cmd;
1413 fabric->tf_ops.shutdown_session = &tcm_loop_shutdown_session; 1361 fabric->tf_ops.shutdown_session = &tcm_loop_shutdown_session;
1414 fabric->tf_ops.close_session = &tcm_loop_close_session; 1362 fabric->tf_ops.close_session = &tcm_loop_close_session;
1415 fabric->tf_ops.stop_session = &tcm_loop_stop_session;
1416 fabric->tf_ops.fall_back_to_erl0 = &tcm_loop_fall_back_to_erl0;
1417 fabric->tf_ops.sess_logged_in = &tcm_loop_sess_logged_in;
1418 fabric->tf_ops.sess_get_index = &tcm_loop_sess_get_index; 1363 fabric->tf_ops.sess_get_index = &tcm_loop_sess_get_index;
1419 fabric->tf_ops.sess_get_initiator_sid = NULL; 1364 fabric->tf_ops.sess_get_initiator_sid = NULL;
1420 fabric->tf_ops.write_pending = &tcm_loop_write_pending; 1365 fabric->tf_ops.write_pending = &tcm_loop_write_pending;
@@ -1431,9 +1376,7 @@ static int tcm_loop_register_configfs(void)
1431 fabric->tf_ops.queue_tm_rsp = &tcm_loop_queue_tm_rsp; 1376 fabric->tf_ops.queue_tm_rsp = &tcm_loop_queue_tm_rsp;
1432 fabric->tf_ops.set_fabric_sense_len = &tcm_loop_set_fabric_sense_len; 1377 fabric->tf_ops.set_fabric_sense_len = &tcm_loop_set_fabric_sense_len;
1433 fabric->tf_ops.get_fabric_sense_len = &tcm_loop_get_fabric_sense_len; 1378 fabric->tf_ops.get_fabric_sense_len = &tcm_loop_get_fabric_sense_len;
1434 fabric->tf_ops.is_state_remove = &tcm_loop_is_state_remove;
1435 1379
1436 tf_cg = &fabric->tf_group;
1437 /* 1380 /*
1438 * Setup function pointers for generic logic in target_core_fabric_configfs.c 1381 * Setup function pointers for generic logic in target_core_fabric_configfs.c
1439 */ 1382 */
@@ -1490,7 +1433,11 @@ static void tcm_loop_deregister_configfs(void)
1490 1433
1491static int __init tcm_loop_fabric_init(void) 1434static int __init tcm_loop_fabric_init(void)
1492{ 1435{
1493 int ret; 1436 int ret = -ENOMEM;
1437
1438 tcm_loop_workqueue = alloc_workqueue("tcm_loop", 0, 0);
1439 if (!tcm_loop_workqueue)
1440 goto out;
1494 1441
1495 tcm_loop_cmd_cache = kmem_cache_create("tcm_loop_cmd_cache", 1442 tcm_loop_cmd_cache = kmem_cache_create("tcm_loop_cmd_cache",
1496 sizeof(struct tcm_loop_cmd), 1443 sizeof(struct tcm_loop_cmd),
@@ -1499,20 +1446,27 @@ static int __init tcm_loop_fabric_init(void)
1499 if (!tcm_loop_cmd_cache) { 1446 if (!tcm_loop_cmd_cache) {
1500 pr_debug("kmem_cache_create() for" 1447 pr_debug("kmem_cache_create() for"
1501 " tcm_loop_cmd_cache failed\n"); 1448 " tcm_loop_cmd_cache failed\n");
1502 return -ENOMEM; 1449 goto out_destroy_workqueue;
1503 } 1450 }
1504 1451
1505 ret = tcm_loop_alloc_core_bus(); 1452 ret = tcm_loop_alloc_core_bus();
1506 if (ret) 1453 if (ret)
1507 return ret; 1454 goto out_destroy_cache;
1508 1455
1509 ret = tcm_loop_register_configfs(); 1456 ret = tcm_loop_register_configfs();
1510 if (ret) { 1457 if (ret)
1511 tcm_loop_release_core_bus(); 1458 goto out_release_core_bus;
1512 return ret;
1513 }
1514 1459
1515 return 0; 1460 return 0;
1461
1462out_release_core_bus:
1463 tcm_loop_release_core_bus();
1464out_destroy_cache:
1465 kmem_cache_destroy(tcm_loop_cmd_cache);
1466out_destroy_workqueue:
1467 destroy_workqueue(tcm_loop_workqueue);
1468out:
1469 return ret;
1516} 1470}
1517 1471
1518static void __exit tcm_loop_fabric_exit(void) 1472static void __exit tcm_loop_fabric_exit(void)
@@ -1520,6 +1474,7 @@ static void __exit tcm_loop_fabric_exit(void)
1520 tcm_loop_deregister_configfs(); 1474 tcm_loop_deregister_configfs();
1521 tcm_loop_release_core_bus(); 1475 tcm_loop_release_core_bus();
1522 kmem_cache_destroy(tcm_loop_cmd_cache); 1476 kmem_cache_destroy(tcm_loop_cmd_cache);
1477 destroy_workqueue(tcm_loop_workqueue);
1523} 1478}
1524 1479
1525MODULE_DESCRIPTION("TCM loopback virtual Linux/SCSI fabric module"); 1480MODULE_DESCRIPTION("TCM loopback virtual Linux/SCSI fabric module");
diff --git a/drivers/target/loopback/tcm_loop.h b/drivers/target/loopback/tcm_loop.h
index 15a036441471..7b54893db665 100644
--- a/drivers/target/loopback/tcm_loop.h
+++ b/drivers/target/loopback/tcm_loop.h
@@ -1,4 +1,4 @@
1#define TCM_LOOP_VERSION "v2.1-rc1" 1#define TCM_LOOP_VERSION "v2.1-rc2"
2#define TL_WWN_ADDR_LEN 256 2#define TL_WWN_ADDR_LEN 256
3#define TL_TPGS_PER_HBA 32 3#define TL_TPGS_PER_HBA 32
4 4
@@ -12,9 +12,9 @@ struct tcm_loop_cmd {
12 u32 sc_cmd_state; 12 u32 sc_cmd_state;
13 /* Pointer to the CDB+Data descriptor from Linux/SCSI subsystem */ 13 /* Pointer to the CDB+Data descriptor from Linux/SCSI subsystem */
14 struct scsi_cmnd *sc; 14 struct scsi_cmnd *sc;
15 struct list_head *tl_cmd_list;
16 /* The TCM I/O descriptor that is accessed via container_of() */ 15 /* The TCM I/O descriptor that is accessed via container_of() */
17 struct se_cmd tl_se_cmd; 16 struct se_cmd tl_se_cmd;
17 struct work_struct work;
18 /* Sense buffer that will be mapped into outgoing status */ 18 /* Sense buffer that will be mapped into outgoing status */
19 unsigned char tl_sense_buf[TRANSPORT_SENSE_BUFFER]; 19 unsigned char tl_sense_buf[TRANSPORT_SENSE_BUFFER];
20}; 20};