diff options
author | Christoph Hellwig <hch@infradead.org> | 2012-02-02 17:04:40 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2012-02-25 17:37:48 -0500 |
commit | f872c9f417a38a08b6ffe46e1f937d3db1d22775 (patch) | |
tree | c475f8e56b369bd8d03343e97ab171ef6cfe0ac5 /drivers/target | |
parent | 59dcb5ec47965d8d22428db67cbea33a9ec4f347 (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.c | 147 |
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; | |||
49 | static int tcm_loop_hba_no_cnt; | 49 | static 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 | */ | ||
56 | static 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 | */ | ||
193 | static 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 | |||
279 | out_done: | ||
280 | sc->scsi_done(sc); | ||
281 | return 0; | ||
311 | } | 282 | } |
312 | 283 | ||
313 | /* | 284 | /* |