aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2012-02-02 17:04:40 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2012-02-25 17:37:48 -0500
commitf872c9f417a38a08b6ffe46e1f937d3db1d22775 (patch)
treec475f8e56b369bd8d03343e97ab171ef6cfe0ac5 /drivers/target
parent59dcb5ec47965d8d22428db67cbea33a9ec4f347 (diff)
tcm_loop: kill tcm_loop_allocate_core_cmd
This function makes little sense as a separate abstraction as it's deeply interwinded with the control flow of its only caller. Merged it into tcm_loop_queuecommand after factoring out a helper to convert the task attribute representation. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/loopback/tcm_loop.c147
1 files changed, 59 insertions, 88 deletions
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 7cfbcb00b3c3..b1edc517f4e3 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -49,81 +49,6 @@ static struct kmem_cache *tcm_loop_cmd_cache;
49static int tcm_loop_hba_no_cnt; 49static int tcm_loop_hba_no_cnt;
50 50
51/* 51/*
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() 52 * Called by struct target_core_fabric_ops->new_cmd_map()
128 * 53 *
129 * Always called in process context. A non zero return value 54 * Always called in process context. A non zero return value
@@ -263,6 +188,25 @@ static int tcm_loop_change_queue_depth(
263} 188}
264 189
265/* 190/*
191 * Locate the SAM Task Attr from struct scsi_cmnd *
192 */
193static int tcm_loop_sam_attr(struct scsi_cmnd *sc)
194{
195 if (sc->device->tagged_supported) {
196 switch (sc->tag) {
197 case HEAD_OF_QUEUE_TAG:
198 return MSG_HEAD_TAG;
199 case ORDERED_QUEUE_TAG:
200 return MSG_ORDERED_TAG;
201 default:
202 break;
203 }
204 }
205
206 return MSG_SIMPLE_TAG;
207}
208
209/*
266 * Main entry point from struct scsi_host_template for incoming SCSI CDB+Data 210 * Main entry point from struct scsi_host_template for incoming SCSI CDB+Data
267 * from Linux/SCSI subsystem for SCSI low level device drivers (LLDs) 211 * from Linux/SCSI subsystem for SCSI low level device drivers (LLDs)
268 */ 212 */
@@ -274,6 +218,10 @@ static int tcm_loop_queuecommand(
274 struct se_portal_group *se_tpg; 218 struct se_portal_group *se_tpg;
275 struct tcm_loop_hba *tl_hba; 219 struct tcm_loop_hba *tl_hba;
276 struct tcm_loop_tpg *tl_tpg; 220 struct tcm_loop_tpg *tl_tpg;
221 struct se_session *se_sess;
222 struct tcm_loop_nexus *tl_nexus;
223 struct tcm_loop_cmd *tl_cmd;
224
277 225
278 pr_debug("tcm_loop_queuecommand() %d:%d:%d:%d got CDB: 0x%02x" 226 pr_debug("tcm_loop_queuecommand() %d:%d:%d:%d got CDB: 0x%02x"
279 " scsi_buf_len: %u\n", sc->device->host->host_no, 227 " scsi_buf_len: %u\n", sc->device->host->host_no,
@@ -290,24 +238,47 @@ static int tcm_loop_queuecommand(
290 */ 238 */
291 if (!tl_tpg->tl_hba) { 239 if (!tl_tpg->tl_hba) {
292 set_host_byte(sc, DID_NO_CONNECT); 240 set_host_byte(sc, DID_NO_CONNECT);
293 sc->scsi_done(sc); 241 goto out_done;
294 return 0;
295 } 242 }
296 se_tpg = &tl_tpg->tl_se_tpg; 243 se_tpg = &tl_tpg->tl_se_tpg;
297 /* 244
298 * Determine the SAM Task Attribute and allocate tl_cmd and 245 tl_nexus = tl_hba->tl_nexus;
299 * tl_cmd->tl_se_cmd from TCM infrastructure 246 if (!tl_nexus) {
300 */ 247 scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus"
301 se_cmd = tcm_loop_allocate_core_cmd(tl_hba, se_tpg, sc); 248 " does not exist\n");
302 if (!se_cmd) { 249 set_host_byte(sc, DID_ERROR);
303 sc->scsi_done(sc); 250 goto out_done;
304 return 0;
305 } 251 }
306 /* 252 se_sess = tl_nexus->se_sess;
307 * Queue up the newly allocated to be processed in TCM thread context. 253
308 */ 254 tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_ATOMIC);
255 if (!tl_cmd) {
256 pr_err("Unable to allocate struct tcm_loop_cmd\n");
257 set_host_byte(sc, DID_ERROR);
258 goto out_done;
259 }
260 se_cmd = &tl_cmd->tl_se_cmd;
261 tl_cmd->sc = sc;
262
263 transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess,
264 scsi_bufflen(sc), sc->sc_data_direction,
265 tcm_loop_sam_attr(sc), &tl_cmd->tl_sense_buf[0]);
266
267 if (scsi_bidi_cmnd(sc))
268 se_cmd->se_cmd_flags |= SCF_BIDI;
269
270 if (transport_lookup_cmd_lun(se_cmd, tl_cmd->sc->device->lun) < 0) {
271 kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
272 set_host_byte(sc, DID_NO_CONNECT);
273 goto out_done;
274 }
275
309 transport_generic_handle_cdb_map(se_cmd); 276 transport_generic_handle_cdb_map(se_cmd);
310 return 0; 277 return 0;
278
279out_done:
280 sc->scsi_done(sc);
281 return 0;
311} 282}
312 283
313/* 284/*