diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-15 21:58:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-15 21:58:04 -0400 |
commit | 89a93f2f4834f8c126e8d9dd6b368d0b9e21ec3d (patch) | |
tree | e731456fec0cab1225ad3e806dc8d3efefa0a78b /drivers/scsi/libiscsi.c | |
parent | 260eddf4391f162a69d1d163729249635fa7a78f (diff) | |
parent | fe9233fb6914a0eb20166c967e3020f7f0fba2c9 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (102 commits)
[SCSI] scsi_dh: fix kconfig related build errors
[SCSI] sym53c8xx: Fix bogus sym_que_entry re-implementation of container_of
[SCSI] scsi_cmnd.h: remove double inclusion of linux/blkdev.h
[SCSI] make struct scsi_{host,target}_type static
[SCSI] fix locking in host use of blk_plug_device()
[SCSI] zfcp: Cleanup external header file
[SCSI] zfcp: Cleanup code in zfcp_erp.c
[SCSI] zfcp: zfcp_fsf cleanup.
[SCSI] zfcp: consolidate sysfs things into one file.
[SCSI] zfcp: Cleanup of code in zfcp_aux.c
[SCSI] zfcp: Cleanup of code in zfcp_scsi.c
[SCSI] zfcp: Move status accessors from zfcp to SCSI include file.
[SCSI] zfcp: Small QDIO cleanups
[SCSI] zfcp: Adapter reopen for large number of unsolicited status
[SCSI] zfcp: Fix error checking for ELS ADISC requests
[SCSI] zfcp: wait until adapter is finished with ERP during auto-port
[SCSI] ibmvfc: IBM Power Virtual Fibre Channel Adapter Client Driver
[SCSI] sg: Add target reset support
[SCSI] lib: Add support for the T10 (SCSI) Data Integrity Field CRC
[SCSI] sd: Move scsi_disk() accessor function to sd.h
...
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 1359 |
1 files changed, 741 insertions, 618 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index b43bf1d60dac..299e075a7b34 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -38,14 +38,6 @@ | |||
38 | #include <scsi/scsi_transport_iscsi.h> | 38 | #include <scsi/scsi_transport_iscsi.h> |
39 | #include <scsi/libiscsi.h> | 39 | #include <scsi/libiscsi.h> |
40 | 40 | ||
41 | struct iscsi_session * | ||
42 | class_to_transport_session(struct iscsi_cls_session *cls_session) | ||
43 | { | ||
44 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); | ||
45 | return iscsi_hostdata(shost->hostdata); | ||
46 | } | ||
47 | EXPORT_SYMBOL_GPL(class_to_transport_session); | ||
48 | |||
49 | /* Serial Number Arithmetic, 32 bits, less than, RFC1982 */ | 41 | /* Serial Number Arithmetic, 32 bits, less than, RFC1982 */ |
50 | #define SNA32_CHECK 2147483648UL | 42 | #define SNA32_CHECK 2147483648UL |
51 | 43 | ||
@@ -87,68 +79,70 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) | |||
87 | * xmit thread | 79 | * xmit thread |
88 | */ | 80 | */ |
89 | if (!list_empty(&session->leadconn->xmitqueue) || | 81 | if (!list_empty(&session->leadconn->xmitqueue) || |
90 | !list_empty(&session->leadconn->mgmtqueue)) | 82 | !list_empty(&session->leadconn->mgmtqueue)) { |
91 | scsi_queue_work(session->host, | 83 | if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD)) |
92 | &session->leadconn->xmitwork); | 84 | scsi_queue_work(session->host, |
85 | &session->leadconn->xmitwork); | ||
86 | } | ||
93 | } | 87 | } |
94 | } | 88 | } |
95 | EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); | 89 | EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); |
96 | 90 | ||
97 | void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask, | 91 | void iscsi_prep_unsolicit_data_pdu(struct iscsi_task *task, |
98 | struct iscsi_data *hdr) | 92 | struct iscsi_data *hdr) |
99 | { | 93 | { |
100 | struct iscsi_conn *conn = ctask->conn; | 94 | struct iscsi_conn *conn = task->conn; |
101 | 95 | ||
102 | memset(hdr, 0, sizeof(struct iscsi_data)); | 96 | memset(hdr, 0, sizeof(struct iscsi_data)); |
103 | hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); | 97 | hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); |
104 | hdr->datasn = cpu_to_be32(ctask->unsol_datasn); | 98 | hdr->datasn = cpu_to_be32(task->unsol_datasn); |
105 | ctask->unsol_datasn++; | 99 | task->unsol_datasn++; |
106 | hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; | 100 | hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; |
107 | memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); | 101 | memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun)); |
108 | 102 | ||
109 | hdr->itt = ctask->hdr->itt; | 103 | hdr->itt = task->hdr->itt; |
110 | hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); | 104 | hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); |
111 | hdr->offset = cpu_to_be32(ctask->unsol_offset); | 105 | hdr->offset = cpu_to_be32(task->unsol_offset); |
112 | 106 | ||
113 | if (ctask->unsol_count > conn->max_xmit_dlength) { | 107 | if (task->unsol_count > conn->max_xmit_dlength) { |
114 | hton24(hdr->dlength, conn->max_xmit_dlength); | 108 | hton24(hdr->dlength, conn->max_xmit_dlength); |
115 | ctask->data_count = conn->max_xmit_dlength; | 109 | task->data_count = conn->max_xmit_dlength; |
116 | ctask->unsol_offset += ctask->data_count; | 110 | task->unsol_offset += task->data_count; |
117 | hdr->flags = 0; | 111 | hdr->flags = 0; |
118 | } else { | 112 | } else { |
119 | hton24(hdr->dlength, ctask->unsol_count); | 113 | hton24(hdr->dlength, task->unsol_count); |
120 | ctask->data_count = ctask->unsol_count; | 114 | task->data_count = task->unsol_count; |
121 | hdr->flags = ISCSI_FLAG_CMD_FINAL; | 115 | hdr->flags = ISCSI_FLAG_CMD_FINAL; |
122 | } | 116 | } |
123 | } | 117 | } |
124 | EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu); | 118 | EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu); |
125 | 119 | ||
126 | static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len) | 120 | static int iscsi_add_hdr(struct iscsi_task *task, unsigned len) |
127 | { | 121 | { |
128 | unsigned exp_len = ctask->hdr_len + len; | 122 | unsigned exp_len = task->hdr_len + len; |
129 | 123 | ||
130 | if (exp_len > ctask->hdr_max) { | 124 | if (exp_len > task->hdr_max) { |
131 | WARN_ON(1); | 125 | WARN_ON(1); |
132 | return -EINVAL; | 126 | return -EINVAL; |
133 | } | 127 | } |
134 | 128 | ||
135 | WARN_ON(len & (ISCSI_PAD_LEN - 1)); /* caller must pad the AHS */ | 129 | WARN_ON(len & (ISCSI_PAD_LEN - 1)); /* caller must pad the AHS */ |
136 | ctask->hdr_len = exp_len; | 130 | task->hdr_len = exp_len; |
137 | return 0; | 131 | return 0; |
138 | } | 132 | } |
139 | 133 | ||
140 | /* | 134 | /* |
141 | * make an extended cdb AHS | 135 | * make an extended cdb AHS |
142 | */ | 136 | */ |
143 | static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask) | 137 | static int iscsi_prep_ecdb_ahs(struct iscsi_task *task) |
144 | { | 138 | { |
145 | struct scsi_cmnd *cmd = ctask->sc; | 139 | struct scsi_cmnd *cmd = task->sc; |
146 | unsigned rlen, pad_len; | 140 | unsigned rlen, pad_len; |
147 | unsigned short ahslength; | 141 | unsigned short ahslength; |
148 | struct iscsi_ecdb_ahdr *ecdb_ahdr; | 142 | struct iscsi_ecdb_ahdr *ecdb_ahdr; |
149 | int rc; | 143 | int rc; |
150 | 144 | ||
151 | ecdb_ahdr = iscsi_next_hdr(ctask); | 145 | ecdb_ahdr = iscsi_next_hdr(task); |
152 | rlen = cmd->cmd_len - ISCSI_CDB_SIZE; | 146 | rlen = cmd->cmd_len - ISCSI_CDB_SIZE; |
153 | 147 | ||
154 | BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb)); | 148 | BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb)); |
@@ -156,7 +150,7 @@ static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask) | |||
156 | 150 | ||
157 | pad_len = iscsi_padding(rlen); | 151 | pad_len = iscsi_padding(rlen); |
158 | 152 | ||
159 | rc = iscsi_add_hdr(ctask, sizeof(ecdb_ahdr->ahslength) + | 153 | rc = iscsi_add_hdr(task, sizeof(ecdb_ahdr->ahslength) + |
160 | sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len); | 154 | sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len); |
161 | if (rc) | 155 | if (rc) |
162 | return rc; | 156 | return rc; |
@@ -171,19 +165,19 @@ static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask) | |||
171 | 165 | ||
172 | debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d " | 166 | debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d " |
173 | "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n", | 167 | "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n", |
174 | cmd->cmd_len, rlen, pad_len, ahslength, ctask->hdr_len); | 168 | cmd->cmd_len, rlen, pad_len, ahslength, task->hdr_len); |
175 | 169 | ||
176 | return 0; | 170 | return 0; |
177 | } | 171 | } |
178 | 172 | ||
179 | static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask) | 173 | static int iscsi_prep_bidi_ahs(struct iscsi_task *task) |
180 | { | 174 | { |
181 | struct scsi_cmnd *sc = ctask->sc; | 175 | struct scsi_cmnd *sc = task->sc; |
182 | struct iscsi_rlength_ahdr *rlen_ahdr; | 176 | struct iscsi_rlength_ahdr *rlen_ahdr; |
183 | int rc; | 177 | int rc; |
184 | 178 | ||
185 | rlen_ahdr = iscsi_next_hdr(ctask); | 179 | rlen_ahdr = iscsi_next_hdr(task); |
186 | rc = iscsi_add_hdr(ctask, sizeof(*rlen_ahdr)); | 180 | rc = iscsi_add_hdr(task, sizeof(*rlen_ahdr)); |
187 | if (rc) | 181 | if (rc) |
188 | return rc; | 182 | return rc; |
189 | 183 | ||
@@ -203,28 +197,28 @@ static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask) | |||
203 | 197 | ||
204 | /** | 198 | /** |
205 | * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu | 199 | * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu |
206 | * @ctask: iscsi cmd task | 200 | * @task: iscsi task |
207 | * | 201 | * |
208 | * Prep basic iSCSI PDU fields for a scsi cmd pdu. The LLD should set | 202 | * Prep basic iSCSI PDU fields for a scsi cmd pdu. The LLD should set |
209 | * fields like dlength or final based on how much data it sends | 203 | * fields like dlength or final based on how much data it sends |
210 | */ | 204 | */ |
211 | static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) | 205 | static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) |
212 | { | 206 | { |
213 | struct iscsi_conn *conn = ctask->conn; | 207 | struct iscsi_conn *conn = task->conn; |
214 | struct iscsi_session *session = conn->session; | 208 | struct iscsi_session *session = conn->session; |
215 | struct iscsi_cmd *hdr = ctask->hdr; | 209 | struct iscsi_cmd *hdr = task->hdr; |
216 | struct scsi_cmnd *sc = ctask->sc; | 210 | struct scsi_cmnd *sc = task->sc; |
217 | unsigned hdrlength, cmd_len; | 211 | unsigned hdrlength, cmd_len; |
218 | int rc; | 212 | int rc; |
219 | 213 | ||
220 | ctask->hdr_len = 0; | 214 | task->hdr_len = 0; |
221 | rc = iscsi_add_hdr(ctask, sizeof(*hdr)); | 215 | rc = iscsi_add_hdr(task, sizeof(*hdr)); |
222 | if (rc) | 216 | if (rc) |
223 | return rc; | 217 | return rc; |
224 | hdr->opcode = ISCSI_OP_SCSI_CMD; | 218 | hdr->opcode = ISCSI_OP_SCSI_CMD; |
225 | hdr->flags = ISCSI_ATTR_SIMPLE; | 219 | hdr->flags = ISCSI_ATTR_SIMPLE; |
226 | int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); | 220 | int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); |
227 | hdr->itt = build_itt(ctask->itt, session->age); | 221 | hdr->itt = build_itt(task->itt, session->age); |
228 | hdr->cmdsn = cpu_to_be32(session->cmdsn); | 222 | hdr->cmdsn = cpu_to_be32(session->cmdsn); |
229 | session->cmdsn++; | 223 | session->cmdsn++; |
230 | hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); | 224 | hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); |
@@ -232,17 +226,17 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) | |||
232 | if (cmd_len < ISCSI_CDB_SIZE) | 226 | if (cmd_len < ISCSI_CDB_SIZE) |
233 | memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len); | 227 | memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len); |
234 | else if (cmd_len > ISCSI_CDB_SIZE) { | 228 | else if (cmd_len > ISCSI_CDB_SIZE) { |
235 | rc = iscsi_prep_ecdb_ahs(ctask); | 229 | rc = iscsi_prep_ecdb_ahs(task); |
236 | if (rc) | 230 | if (rc) |
237 | return rc; | 231 | return rc; |
238 | cmd_len = ISCSI_CDB_SIZE; | 232 | cmd_len = ISCSI_CDB_SIZE; |
239 | } | 233 | } |
240 | memcpy(hdr->cdb, sc->cmnd, cmd_len); | 234 | memcpy(hdr->cdb, sc->cmnd, cmd_len); |
241 | 235 | ||
242 | ctask->imm_count = 0; | 236 | task->imm_count = 0; |
243 | if (scsi_bidi_cmnd(sc)) { | 237 | if (scsi_bidi_cmnd(sc)) { |
244 | hdr->flags |= ISCSI_FLAG_CMD_READ; | 238 | hdr->flags |= ISCSI_FLAG_CMD_READ; |
245 | rc = iscsi_prep_bidi_ahs(ctask); | 239 | rc = iscsi_prep_bidi_ahs(task); |
246 | if (rc) | 240 | if (rc) |
247 | return rc; | 241 | return rc; |
248 | } | 242 | } |
@@ -264,28 +258,28 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) | |||
264 | * | 258 | * |
265 | * pad_count bytes to be sent as zero-padding | 259 | * pad_count bytes to be sent as zero-padding |
266 | */ | 260 | */ |
267 | ctask->unsol_count = 0; | 261 | task->unsol_count = 0; |
268 | ctask->unsol_offset = 0; | 262 | task->unsol_offset = 0; |
269 | ctask->unsol_datasn = 0; | 263 | task->unsol_datasn = 0; |
270 | 264 | ||
271 | if (session->imm_data_en) { | 265 | if (session->imm_data_en) { |
272 | if (out_len >= session->first_burst) | 266 | if (out_len >= session->first_burst) |
273 | ctask->imm_count = min(session->first_burst, | 267 | task->imm_count = min(session->first_burst, |
274 | conn->max_xmit_dlength); | 268 | conn->max_xmit_dlength); |
275 | else | 269 | else |
276 | ctask->imm_count = min(out_len, | 270 | task->imm_count = min(out_len, |
277 | conn->max_xmit_dlength); | 271 | conn->max_xmit_dlength); |
278 | hton24(hdr->dlength, ctask->imm_count); | 272 | hton24(hdr->dlength, task->imm_count); |
279 | } else | 273 | } else |
280 | zero_data(hdr->dlength); | 274 | zero_data(hdr->dlength); |
281 | 275 | ||
282 | if (!session->initial_r2t_en) { | 276 | if (!session->initial_r2t_en) { |
283 | ctask->unsol_count = min(session->first_burst, out_len) | 277 | task->unsol_count = min(session->first_burst, out_len) |
284 | - ctask->imm_count; | 278 | - task->imm_count; |
285 | ctask->unsol_offset = ctask->imm_count; | 279 | task->unsol_offset = task->imm_count; |
286 | } | 280 | } |
287 | 281 | ||
288 | if (!ctask->unsol_count) | 282 | if (!task->unsol_count) |
289 | /* No unsolicit Data-Out's */ | 283 | /* No unsolicit Data-Out's */ |
290 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | 284 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; |
291 | } else { | 285 | } else { |
@@ -298,7 +292,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) | |||
298 | } | 292 | } |
299 | 293 | ||
300 | /* calculate size of additional header segments (AHSs) */ | 294 | /* calculate size of additional header segments (AHSs) */ |
301 | hdrlength = ctask->hdr_len - sizeof(*hdr); | 295 | hdrlength = task->hdr_len - sizeof(*hdr); |
302 | 296 | ||
303 | WARN_ON(hdrlength & (ISCSI_PAD_LEN-1)); | 297 | WARN_ON(hdrlength & (ISCSI_PAD_LEN-1)); |
304 | hdrlength /= ISCSI_PAD_LEN; | 298 | hdrlength /= ISCSI_PAD_LEN; |
@@ -306,76 +300,115 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) | |||
306 | WARN_ON(hdrlength >= 256); | 300 | WARN_ON(hdrlength >= 256); |
307 | hdr->hlength = hdrlength & 0xFF; | 301 | hdr->hlength = hdrlength & 0xFF; |
308 | 302 | ||
309 | if (conn->session->tt->init_cmd_task(conn->ctask)) | 303 | if (conn->session->tt->init_task && |
310 | return EIO; | 304 | conn->session->tt->init_task(task)) |
305 | return -EIO; | ||
306 | |||
307 | task->state = ISCSI_TASK_RUNNING; | ||
308 | list_move_tail(&task->running, &conn->run_list); | ||
311 | 309 | ||
312 | conn->scsicmd_pdus_cnt++; | 310 | conn->scsicmd_pdus_cnt++; |
313 | debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x " | 311 | debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d " |
314 | "len %d bidi_len %d cmdsn %d win %d]\n", | 312 | "bidi_len %d cmdsn %d win %d]\n", scsi_bidi_cmnd(sc) ? |
315 | scsi_bidi_cmnd(sc) ? "bidirectional" : | 313 | "bidirectional" : sc->sc_data_direction == DMA_TO_DEVICE ? |
316 | sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", | 314 | "write" : "read", conn->id, sc, sc->cmnd[0], task->itt, |
317 | conn->id, sc, sc->cmnd[0], ctask->itt, | 315 | scsi_bufflen(sc), |
318 | scsi_bufflen(sc), scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0, | 316 | scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0, |
319 | session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); | 317 | session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); |
320 | return 0; | 318 | return 0; |
321 | } | 319 | } |
322 | 320 | ||
323 | /** | 321 | /** |
324 | * iscsi_complete_command - return command back to scsi-ml | 322 | * iscsi_complete_command - finish a task |
325 | * @ctask: iscsi cmd task | 323 | * @task: iscsi cmd task |
326 | * | 324 | * |
327 | * Must be called with session lock. | 325 | * Must be called with session lock. |
328 | * This function returns the scsi command to scsi-ml and returns | 326 | * This function returns the scsi command to scsi-ml or cleans |
329 | * the cmd task to the pool of available cmd tasks. | 327 | * up mgmt tasks then returns the task to the pool. |
330 | */ | 328 | */ |
331 | static void iscsi_complete_command(struct iscsi_cmd_task *ctask) | 329 | static void iscsi_complete_command(struct iscsi_task *task) |
332 | { | 330 | { |
333 | struct iscsi_conn *conn = ctask->conn; | 331 | struct iscsi_conn *conn = task->conn; |
334 | struct iscsi_session *session = conn->session; | 332 | struct iscsi_session *session = conn->session; |
335 | struct scsi_cmnd *sc = ctask->sc; | 333 | struct scsi_cmnd *sc = task->sc; |
336 | 334 | ||
337 | ctask->state = ISCSI_TASK_COMPLETED; | 335 | list_del_init(&task->running); |
338 | ctask->sc = NULL; | 336 | task->state = ISCSI_TASK_COMPLETED; |
339 | /* SCSI eh reuses commands to verify us */ | 337 | task->sc = NULL; |
340 | sc->SCp.ptr = NULL; | 338 | |
341 | if (conn->ctask == ctask) | 339 | if (conn->task == task) |
342 | conn->ctask = NULL; | 340 | conn->task = NULL; |
343 | list_del_init(&ctask->running); | 341 | /* |
344 | __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); | 342 | * login task is preallocated so do not free |
345 | sc->scsi_done(sc); | 343 | */ |
344 | if (conn->login_task == task) | ||
345 | return; | ||
346 | |||
347 | __kfifo_put(session->cmdpool.queue, (void*)&task, sizeof(void*)); | ||
348 | |||
349 | if (conn->ping_task == task) | ||
350 | conn->ping_task = NULL; | ||
351 | |||
352 | if (sc) { | ||
353 | task->sc = NULL; | ||
354 | /* SCSI eh reuses commands to verify us */ | ||
355 | sc->SCp.ptr = NULL; | ||
356 | /* | ||
357 | * queue command may call this to free the task, but | ||
358 | * not have setup the sc callback | ||
359 | */ | ||
360 | if (sc->scsi_done) | ||
361 | sc->scsi_done(sc); | ||
362 | } | ||
363 | } | ||
364 | |||
365 | void __iscsi_get_task(struct iscsi_task *task) | ||
366 | { | ||
367 | atomic_inc(&task->refcount); | ||
346 | } | 368 | } |
369 | EXPORT_SYMBOL_GPL(__iscsi_get_task); | ||
347 | 370 | ||
348 | static void __iscsi_get_ctask(struct iscsi_cmd_task *ctask) | 371 | static void __iscsi_put_task(struct iscsi_task *task) |
349 | { | 372 | { |
350 | atomic_inc(&ctask->refcount); | 373 | if (atomic_dec_and_test(&task->refcount)) |
374 | iscsi_complete_command(task); | ||
351 | } | 375 | } |
352 | 376 | ||
353 | static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask) | 377 | void iscsi_put_task(struct iscsi_task *task) |
354 | { | 378 | { |
355 | if (atomic_dec_and_test(&ctask->refcount)) | 379 | struct iscsi_session *session = task->conn->session; |
356 | iscsi_complete_command(ctask); | 380 | |
381 | spin_lock_bh(&session->lock); | ||
382 | __iscsi_put_task(task); | ||
383 | spin_unlock_bh(&session->lock); | ||
357 | } | 384 | } |
385 | EXPORT_SYMBOL_GPL(iscsi_put_task); | ||
358 | 386 | ||
359 | /* | 387 | /* |
360 | * session lock must be held | 388 | * session lock must be held |
361 | */ | 389 | */ |
362 | static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | 390 | static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task, |
363 | int err) | 391 | int err) |
364 | { | 392 | { |
365 | struct scsi_cmnd *sc; | 393 | struct scsi_cmnd *sc; |
366 | 394 | ||
367 | sc = ctask->sc; | 395 | sc = task->sc; |
368 | if (!sc) | 396 | if (!sc) |
369 | return; | 397 | return; |
370 | 398 | ||
371 | if (ctask->state == ISCSI_TASK_PENDING) | 399 | if (task->state == ISCSI_TASK_PENDING) |
372 | /* | 400 | /* |
373 | * cmd never made it to the xmit thread, so we should not count | 401 | * cmd never made it to the xmit thread, so we should not count |
374 | * the cmd in the sequencing | 402 | * the cmd in the sequencing |
375 | */ | 403 | */ |
376 | conn->session->queued_cmdsn--; | 404 | conn->session->queued_cmdsn--; |
377 | else | 405 | else |
378 | conn->session->tt->cleanup_cmd_task(conn, ctask); | 406 | conn->session->tt->cleanup_task(conn, task); |
407 | /* | ||
408 | * Check if cleanup_task dropped the lock and the command completed, | ||
409 | */ | ||
410 | if (!task->sc) | ||
411 | return; | ||
379 | 412 | ||
380 | sc->result = err; | 413 | sc->result = err; |
381 | if (!scsi_bidi_cmnd(sc)) | 414 | if (!scsi_bidi_cmnd(sc)) |
@@ -384,39 +417,63 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
384 | scsi_out(sc)->resid = scsi_out(sc)->length; | 417 | scsi_out(sc)->resid = scsi_out(sc)->length; |
385 | scsi_in(sc)->resid = scsi_in(sc)->length; | 418 | scsi_in(sc)->resid = scsi_in(sc)->length; |
386 | } | 419 | } |
387 | if (conn->ctask == ctask) | 420 | |
388 | conn->ctask = NULL; | 421 | if (conn->task == task) |
422 | conn->task = NULL; | ||
389 | /* release ref from queuecommand */ | 423 | /* release ref from queuecommand */ |
390 | __iscsi_put_ctask(ctask); | 424 | __iscsi_put_task(task); |
391 | } | 425 | } |
392 | 426 | ||
393 | /** | 427 | static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, |
394 | * iscsi_free_mgmt_task - return mgmt task back to pool | 428 | struct iscsi_task *task) |
395 | * @conn: iscsi connection | ||
396 | * @mtask: mtask | ||
397 | * | ||
398 | * Must be called with session lock. | ||
399 | */ | ||
400 | void iscsi_free_mgmt_task(struct iscsi_conn *conn, | ||
401 | struct iscsi_mgmt_task *mtask) | ||
402 | { | 429 | { |
403 | list_del_init(&mtask->running); | 430 | struct iscsi_session *session = conn->session; |
404 | if (conn->login_mtask == mtask) | 431 | struct iscsi_hdr *hdr = (struct iscsi_hdr *)task->hdr; |
405 | return; | 432 | struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; |
433 | |||
434 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) | ||
435 | return -ENOTCONN; | ||
436 | |||
437 | if (hdr->opcode != (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) && | ||
438 | hdr->opcode != (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE)) | ||
439 | nop->exp_statsn = cpu_to_be32(conn->exp_statsn); | ||
440 | /* | ||
441 | * pre-format CmdSN for outgoing PDU. | ||
442 | */ | ||
443 | nop->cmdsn = cpu_to_be32(session->cmdsn); | ||
444 | if (hdr->itt != RESERVED_ITT) { | ||
445 | hdr->itt = build_itt(task->itt, session->age); | ||
446 | /* | ||
447 | * TODO: We always use immediate, so we never hit this. | ||
448 | * If we start to send tmfs or nops as non-immediate then | ||
449 | * we should start checking the cmdsn numbers for mgmt tasks. | ||
450 | */ | ||
451 | if (conn->c_stage == ISCSI_CONN_STARTED && | ||
452 | !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { | ||
453 | session->queued_cmdsn++; | ||
454 | session->cmdsn++; | ||
455 | } | ||
456 | } | ||
406 | 457 | ||
407 | if (conn->ping_mtask == mtask) | 458 | if (session->tt->init_task) |
408 | conn->ping_mtask = NULL; | 459 | session->tt->init_task(task); |
409 | __kfifo_put(conn->session->mgmtpool.queue, | 460 | |
410 | (void*)&mtask, sizeof(void*)); | 461 | if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) |
462 | session->state = ISCSI_STATE_LOGGING_OUT; | ||
463 | |||
464 | list_move_tail(&task->running, &conn->mgmt_run_list); | ||
465 | debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", | ||
466 | hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt, | ||
467 | task->data_count); | ||
468 | return 0; | ||
411 | } | 469 | } |
412 | EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task); | ||
413 | 470 | ||
414 | static struct iscsi_mgmt_task * | 471 | static struct iscsi_task * |
415 | __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | 472 | __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, |
416 | char *data, uint32_t data_size) | 473 | char *data, uint32_t data_size) |
417 | { | 474 | { |
418 | struct iscsi_session *session = conn->session; | 475 | struct iscsi_session *session = conn->session; |
419 | struct iscsi_mgmt_task *mtask; | 476 | struct iscsi_task *task; |
420 | 477 | ||
421 | if (session->state == ISCSI_STATE_TERMINATE) | 478 | if (session->state == ISCSI_STATE_TERMINATE) |
422 | return NULL; | 479 | return NULL; |
@@ -426,29 +483,56 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
426 | /* | 483 | /* |
427 | * Login and Text are sent serially, in | 484 | * Login and Text are sent serially, in |
428 | * request-followed-by-response sequence. | 485 | * request-followed-by-response sequence. |
429 | * Same mtask can be used. Same ITT must be used. | 486 | * Same task can be used. Same ITT must be used. |
430 | * Note that login_mtask is preallocated at conn_create(). | 487 | * Note that login_task is preallocated at conn_create(). |
431 | */ | 488 | */ |
432 | mtask = conn->login_mtask; | 489 | task = conn->login_task; |
433 | else { | 490 | else { |
434 | BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); | 491 | BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); |
435 | BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); | 492 | BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); |
436 | 493 | ||
437 | if (!__kfifo_get(session->mgmtpool.queue, | 494 | if (!__kfifo_get(session->cmdpool.queue, |
438 | (void*)&mtask, sizeof(void*))) | 495 | (void*)&task, sizeof(void*))) |
439 | return NULL; | 496 | return NULL; |
497 | |||
498 | if ((hdr->opcode == (ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE)) && | ||
499 | hdr->ttt == RESERVED_ITT) { | ||
500 | conn->ping_task = task; | ||
501 | conn->last_ping = jiffies; | ||
502 | } | ||
440 | } | 503 | } |
504 | /* | ||
505 | * released in complete pdu for task we expect a response for, and | ||
506 | * released by the lld when it has transmitted the task for | ||
507 | * pdus we do not expect a response for. | ||
508 | */ | ||
509 | atomic_set(&task->refcount, 1); | ||
510 | task->conn = conn; | ||
511 | task->sc = NULL; | ||
441 | 512 | ||
442 | if (data_size) { | 513 | if (data_size) { |
443 | memcpy(mtask->data, data, data_size); | 514 | memcpy(task->data, data, data_size); |
444 | mtask->data_count = data_size; | 515 | task->data_count = data_size; |
516 | } else | ||
517 | task->data_count = 0; | ||
518 | |||
519 | memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr)); | ||
520 | INIT_LIST_HEAD(&task->running); | ||
521 | list_add_tail(&task->running, &conn->mgmtqueue); | ||
522 | |||
523 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { | ||
524 | if (iscsi_prep_mgmt_task(conn, task)) { | ||
525 | __iscsi_put_task(task); | ||
526 | return NULL; | ||
527 | } | ||
528 | |||
529 | if (session->tt->xmit_task(task)) | ||
530 | task = NULL; | ||
531 | |||
445 | } else | 532 | } else |
446 | mtask->data_count = 0; | 533 | scsi_queue_work(conn->session->host, &conn->xmitwork); |
447 | 534 | ||
448 | memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr)); | 535 | return task; |
449 | INIT_LIST_HEAD(&mtask->running); | ||
450 | list_add_tail(&mtask->running, &conn->mgmtqueue); | ||
451 | return mtask; | ||
452 | } | 536 | } |
453 | 537 | ||
454 | int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, | 538 | int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, |
@@ -462,7 +546,6 @@ int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, | |||
462 | if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size)) | 546 | if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size)) |
463 | err = -EPERM; | 547 | err = -EPERM; |
464 | spin_unlock_bh(&session->lock); | 548 | spin_unlock_bh(&session->lock); |
465 | scsi_queue_work(session->host, &conn->xmitwork); | ||
466 | return err; | 549 | return err; |
467 | } | 550 | } |
468 | EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); | 551 | EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); |
@@ -471,7 +554,7 @@ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); | |||
471 | * iscsi_cmd_rsp - SCSI Command Response processing | 554 | * iscsi_cmd_rsp - SCSI Command Response processing |
472 | * @conn: iscsi connection | 555 | * @conn: iscsi connection |
473 | * @hdr: iscsi header | 556 | * @hdr: iscsi header |
474 | * @ctask: scsi command task | 557 | * @task: scsi command task |
475 | * @data: cmd data buffer | 558 | * @data: cmd data buffer |
476 | * @datalen: len of buffer | 559 | * @datalen: len of buffer |
477 | * | 560 | * |
@@ -479,12 +562,12 @@ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); | |||
479 | * then completes the command and task. | 562 | * then completes the command and task. |
480 | **/ | 563 | **/ |
481 | static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | 564 | static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, |
482 | struct iscsi_cmd_task *ctask, char *data, | 565 | struct iscsi_task *task, char *data, |
483 | int datalen) | 566 | int datalen) |
484 | { | 567 | { |
485 | struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)hdr; | 568 | struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)hdr; |
486 | struct iscsi_session *session = conn->session; | 569 | struct iscsi_session *session = conn->session; |
487 | struct scsi_cmnd *sc = ctask->sc; | 570 | struct scsi_cmnd *sc = task->sc; |
488 | 571 | ||
489 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); | 572 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); |
490 | conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; | 573 | conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; |
@@ -508,7 +591,7 @@ invalid_datalen: | |||
508 | goto out; | 591 | goto out; |
509 | } | 592 | } |
510 | 593 | ||
511 | senselen = be16_to_cpu(get_unaligned((__be16 *) data)); | 594 | senselen = get_unaligned_be16(data); |
512 | if (datalen < senselen) | 595 | if (datalen < senselen) |
513 | goto invalid_datalen; | 596 | goto invalid_datalen; |
514 | 597 | ||
@@ -544,10 +627,10 @@ invalid_datalen: | |||
544 | } | 627 | } |
545 | out: | 628 | out: |
546 | debug_scsi("done [sc %lx res %d itt 0x%x]\n", | 629 | debug_scsi("done [sc %lx res %d itt 0x%x]\n", |
547 | (long)sc, sc->result, ctask->itt); | 630 | (long)sc, sc->result, task->itt); |
548 | conn->scsirsp_pdus_cnt++; | 631 | conn->scsirsp_pdus_cnt++; |
549 | 632 | ||
550 | __iscsi_put_ctask(ctask); | 633 | __iscsi_put_task(task); |
551 | } | 634 | } |
552 | 635 | ||
553 | static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | 636 | static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) |
@@ -572,9 +655,9 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | |||
572 | static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) | 655 | static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) |
573 | { | 656 | { |
574 | struct iscsi_nopout hdr; | 657 | struct iscsi_nopout hdr; |
575 | struct iscsi_mgmt_task *mtask; | 658 | struct iscsi_task *task; |
576 | 659 | ||
577 | if (!rhdr && conn->ping_mtask) | 660 | if (!rhdr && conn->ping_task) |
578 | return; | 661 | return; |
579 | 662 | ||
580 | memset(&hdr, 0, sizeof(struct iscsi_nopout)); | 663 | memset(&hdr, 0, sizeof(struct iscsi_nopout)); |
@@ -588,18 +671,9 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) | |||
588 | } else | 671 | } else |
589 | hdr.ttt = RESERVED_ITT; | 672 | hdr.ttt = RESERVED_ITT; |
590 | 673 | ||
591 | mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); | 674 | task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); |
592 | if (!mtask) { | 675 | if (!task) |
593 | iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); | 676 | iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); |
594 | return; | ||
595 | } | ||
596 | |||
597 | /* only track our nops */ | ||
598 | if (!rhdr) { | ||
599 | conn->ping_mtask = mtask; | ||
600 | conn->last_ping = jiffies; | ||
601 | } | ||
602 | scsi_queue_work(conn->session->host, &conn->xmitwork); | ||
603 | } | 677 | } |
604 | 678 | ||
605 | static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | 679 | static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, |
@@ -628,6 +702,31 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
628 | } | 702 | } |
629 | 703 | ||
630 | /** | 704 | /** |
705 | * iscsi_itt_to_task - look up task by itt | ||
706 | * @conn: iscsi connection | ||
707 | * @itt: itt | ||
708 | * | ||
709 | * This should be used for mgmt tasks like login and nops, or if | ||
710 | * the LDD's itt space does not include the session age. | ||
711 | * | ||
712 | * The session lock must be held. | ||
713 | */ | ||
714 | static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) | ||
715 | { | ||
716 | struct iscsi_session *session = conn->session; | ||
717 | uint32_t i; | ||
718 | |||
719 | if (itt == RESERVED_ITT) | ||
720 | return NULL; | ||
721 | |||
722 | i = get_itt(itt); | ||
723 | if (i >= session->cmds_max) | ||
724 | return NULL; | ||
725 | |||
726 | return session->cmds[i]; | ||
727 | } | ||
728 | |||
729 | /** | ||
631 | * __iscsi_complete_pdu - complete pdu | 730 | * __iscsi_complete_pdu - complete pdu |
632 | * @conn: iscsi conn | 731 | * @conn: iscsi conn |
633 | * @hdr: iscsi header | 732 | * @hdr: iscsi header |
@@ -638,108 +737,28 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
638 | * queuecommand or send generic. session lock must be held and verify | 737 | * queuecommand or send generic. session lock must be held and verify |
639 | * itt must have been called. | 738 | * itt must have been called. |
640 | */ | 739 | */ |
641 | static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | 740 | int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, |
642 | char *data, int datalen) | 741 | char *data, int datalen) |
643 | { | 742 | { |
644 | struct iscsi_session *session = conn->session; | 743 | struct iscsi_session *session = conn->session; |
645 | int opcode = hdr->opcode & ISCSI_OPCODE_MASK, rc = 0; | 744 | int opcode = hdr->opcode & ISCSI_OPCODE_MASK, rc = 0; |
646 | struct iscsi_cmd_task *ctask; | 745 | struct iscsi_task *task; |
647 | struct iscsi_mgmt_task *mtask; | ||
648 | uint32_t itt; | 746 | uint32_t itt; |
649 | 747 | ||
650 | conn->last_recv = jiffies; | 748 | conn->last_recv = jiffies; |
749 | rc = iscsi_verify_itt(conn, hdr->itt); | ||
750 | if (rc) | ||
751 | return rc; | ||
752 | |||
651 | if (hdr->itt != RESERVED_ITT) | 753 | if (hdr->itt != RESERVED_ITT) |
652 | itt = get_itt(hdr->itt); | 754 | itt = get_itt(hdr->itt); |
653 | else | 755 | else |
654 | itt = ~0U; | 756 | itt = ~0U; |
655 | 757 | ||
656 | if (itt < session->cmds_max) { | 758 | debug_scsi("[op 0x%x cid %d itt 0x%x len %d]\n", |
657 | ctask = session->cmds[itt]; | 759 | opcode, conn->id, itt, datalen); |
658 | |||
659 | debug_scsi("cmdrsp [op 0x%x cid %d itt 0x%x len %d]\n", | ||
660 | opcode, conn->id, ctask->itt, datalen); | ||
661 | |||
662 | switch(opcode) { | ||
663 | case ISCSI_OP_SCSI_CMD_RSP: | ||
664 | BUG_ON((void*)ctask != ctask->sc->SCp.ptr); | ||
665 | iscsi_scsi_cmd_rsp(conn, hdr, ctask, data, | ||
666 | datalen); | ||
667 | break; | ||
668 | case ISCSI_OP_SCSI_DATA_IN: | ||
669 | BUG_ON((void*)ctask != ctask->sc->SCp.ptr); | ||
670 | if (hdr->flags & ISCSI_FLAG_DATA_STATUS) { | ||
671 | conn->scsirsp_pdus_cnt++; | ||
672 | __iscsi_put_ctask(ctask); | ||
673 | } | ||
674 | break; | ||
675 | case ISCSI_OP_R2T: | ||
676 | /* LLD handles this for now */ | ||
677 | break; | ||
678 | default: | ||
679 | rc = ISCSI_ERR_BAD_OPCODE; | ||
680 | break; | ||
681 | } | ||
682 | } else if (itt >= ISCSI_MGMT_ITT_OFFSET && | ||
683 | itt < ISCSI_MGMT_ITT_OFFSET + session->mgmtpool_max) { | ||
684 | mtask = session->mgmt_cmds[itt - ISCSI_MGMT_ITT_OFFSET]; | ||
685 | |||
686 | debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n", | ||
687 | opcode, conn->id, mtask->itt, datalen); | ||
688 | 760 | ||
689 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); | 761 | if (itt == ~0U) { |
690 | switch(opcode) { | ||
691 | case ISCSI_OP_LOGOUT_RSP: | ||
692 | if (datalen) { | ||
693 | rc = ISCSI_ERR_PROTO; | ||
694 | break; | ||
695 | } | ||
696 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | ||
697 | /* fall through */ | ||
698 | case ISCSI_OP_LOGIN_RSP: | ||
699 | case ISCSI_OP_TEXT_RSP: | ||
700 | /* | ||
701 | * login related PDU's exp_statsn is handled in | ||
702 | * userspace | ||
703 | */ | ||
704 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) | ||
705 | rc = ISCSI_ERR_CONN_FAILED; | ||
706 | iscsi_free_mgmt_task(conn, mtask); | ||
707 | break; | ||
708 | case ISCSI_OP_SCSI_TMFUNC_RSP: | ||
709 | if (datalen) { | ||
710 | rc = ISCSI_ERR_PROTO; | ||
711 | break; | ||
712 | } | ||
713 | |||
714 | iscsi_tmf_rsp(conn, hdr); | ||
715 | iscsi_free_mgmt_task(conn, mtask); | ||
716 | break; | ||
717 | case ISCSI_OP_NOOP_IN: | ||
718 | if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) || | ||
719 | datalen) { | ||
720 | rc = ISCSI_ERR_PROTO; | ||
721 | break; | ||
722 | } | ||
723 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | ||
724 | |||
725 | if (conn->ping_mtask != mtask) { | ||
726 | /* | ||
727 | * If this is not in response to one of our | ||
728 | * nops then it must be from userspace. | ||
729 | */ | ||
730 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, | ||
731 | datalen)) | ||
732 | rc = ISCSI_ERR_CONN_FAILED; | ||
733 | } else | ||
734 | mod_timer(&conn->transport_timer, | ||
735 | jiffies + conn->recv_timeout); | ||
736 | iscsi_free_mgmt_task(conn, mtask); | ||
737 | break; | ||
738 | default: | ||
739 | rc = ISCSI_ERR_BAD_OPCODE; | ||
740 | break; | ||
741 | } | ||
742 | } else if (itt == ~0U) { | ||
743 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); | 762 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); |
744 | 763 | ||
745 | switch(opcode) { | 764 | switch(opcode) { |
@@ -766,11 +785,104 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
766 | rc = ISCSI_ERR_BAD_OPCODE; | 785 | rc = ISCSI_ERR_BAD_OPCODE; |
767 | break; | 786 | break; |
768 | } | 787 | } |
769 | } else | 788 | goto out; |
770 | rc = ISCSI_ERR_BAD_ITT; | 789 | } |
771 | 790 | ||
791 | switch(opcode) { | ||
792 | case ISCSI_OP_SCSI_CMD_RSP: | ||
793 | case ISCSI_OP_SCSI_DATA_IN: | ||
794 | task = iscsi_itt_to_ctask(conn, hdr->itt); | ||
795 | if (!task) | ||
796 | return ISCSI_ERR_BAD_ITT; | ||
797 | break; | ||
798 | case ISCSI_OP_R2T: | ||
799 | /* | ||
800 | * LLD handles R2Ts if they need to. | ||
801 | */ | ||
802 | return 0; | ||
803 | case ISCSI_OP_LOGOUT_RSP: | ||
804 | case ISCSI_OP_LOGIN_RSP: | ||
805 | case ISCSI_OP_TEXT_RSP: | ||
806 | case ISCSI_OP_SCSI_TMFUNC_RSP: | ||
807 | case ISCSI_OP_NOOP_IN: | ||
808 | task = iscsi_itt_to_task(conn, hdr->itt); | ||
809 | if (!task) | ||
810 | return ISCSI_ERR_BAD_ITT; | ||
811 | break; | ||
812 | default: | ||
813 | return ISCSI_ERR_BAD_OPCODE; | ||
814 | } | ||
815 | |||
816 | switch(opcode) { | ||
817 | case ISCSI_OP_SCSI_CMD_RSP: | ||
818 | iscsi_scsi_cmd_rsp(conn, hdr, task, data, datalen); | ||
819 | break; | ||
820 | case ISCSI_OP_SCSI_DATA_IN: | ||
821 | if (hdr->flags & ISCSI_FLAG_DATA_STATUS) { | ||
822 | conn->scsirsp_pdus_cnt++; | ||
823 | iscsi_update_cmdsn(session, | ||
824 | (struct iscsi_nopin*) hdr); | ||
825 | __iscsi_put_task(task); | ||
826 | } | ||
827 | break; | ||
828 | case ISCSI_OP_LOGOUT_RSP: | ||
829 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); | ||
830 | if (datalen) { | ||
831 | rc = ISCSI_ERR_PROTO; | ||
832 | break; | ||
833 | } | ||
834 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | ||
835 | goto recv_pdu; | ||
836 | case ISCSI_OP_LOGIN_RSP: | ||
837 | case ISCSI_OP_TEXT_RSP: | ||
838 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); | ||
839 | /* | ||
840 | * login related PDU's exp_statsn is handled in | ||
841 | * userspace | ||
842 | */ | ||
843 | goto recv_pdu; | ||
844 | case ISCSI_OP_SCSI_TMFUNC_RSP: | ||
845 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); | ||
846 | if (datalen) { | ||
847 | rc = ISCSI_ERR_PROTO; | ||
848 | break; | ||
849 | } | ||
850 | |||
851 | iscsi_tmf_rsp(conn, hdr); | ||
852 | __iscsi_put_task(task); | ||
853 | break; | ||
854 | case ISCSI_OP_NOOP_IN: | ||
855 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); | ||
856 | if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) || datalen) { | ||
857 | rc = ISCSI_ERR_PROTO; | ||
858 | break; | ||
859 | } | ||
860 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | ||
861 | |||
862 | if (conn->ping_task != task) | ||
863 | /* | ||
864 | * If this is not in response to one of our | ||
865 | * nops then it must be from userspace. | ||
866 | */ | ||
867 | goto recv_pdu; | ||
868 | |||
869 | mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout); | ||
870 | __iscsi_put_task(task); | ||
871 | break; | ||
872 | default: | ||
873 | rc = ISCSI_ERR_BAD_OPCODE; | ||
874 | break; | ||
875 | } | ||
876 | |||
877 | out: | ||
878 | return rc; | ||
879 | recv_pdu: | ||
880 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) | ||
881 | rc = ISCSI_ERR_CONN_FAILED; | ||
882 | __iscsi_put_task(task); | ||
772 | return rc; | 883 | return rc; |
773 | } | 884 | } |
885 | EXPORT_SYMBOL_GPL(__iscsi_complete_pdu); | ||
774 | 886 | ||
775 | int iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | 887 | int iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, |
776 | char *data, int datalen) | 888 | char *data, int datalen) |
@@ -784,51 +896,63 @@ int iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
784 | } | 896 | } |
785 | EXPORT_SYMBOL_GPL(iscsi_complete_pdu); | 897 | EXPORT_SYMBOL_GPL(iscsi_complete_pdu); |
786 | 898 | ||
787 | /* verify itt (itt encoding: age+cid+itt) */ | 899 | int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt) |
788 | int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | ||
789 | uint32_t *ret_itt) | ||
790 | { | 900 | { |
791 | struct iscsi_session *session = conn->session; | 901 | struct iscsi_session *session = conn->session; |
792 | struct iscsi_cmd_task *ctask; | 902 | uint32_t i; |
793 | uint32_t itt; | ||
794 | 903 | ||
795 | if (hdr->itt != RESERVED_ITT) { | 904 | if (itt == RESERVED_ITT) |
796 | if (((__force u32)hdr->itt & ISCSI_AGE_MASK) != | 905 | return 0; |
797 | (session->age << ISCSI_AGE_SHIFT)) { | ||
798 | iscsi_conn_printk(KERN_ERR, conn, | ||
799 | "received itt %x expected session " | ||
800 | "age (%x)\n", (__force u32)hdr->itt, | ||
801 | session->age & ISCSI_AGE_MASK); | ||
802 | return ISCSI_ERR_BAD_ITT; | ||
803 | } | ||
804 | 906 | ||
805 | itt = get_itt(hdr->itt); | 907 | if (((__force u32)itt & ISCSI_AGE_MASK) != |
806 | } else | 908 | (session->age << ISCSI_AGE_SHIFT)) { |
807 | itt = ~0U; | 909 | iscsi_conn_printk(KERN_ERR, conn, |
910 | "received itt %x expected session age (%x)\n", | ||
911 | (__force u32)itt, session->age); | ||
912 | return ISCSI_ERR_BAD_ITT; | ||
913 | } | ||
808 | 914 | ||
809 | if (itt < session->cmds_max) { | 915 | i = get_itt(itt); |
810 | ctask = session->cmds[itt]; | 916 | if (i >= session->cmds_max) { |
917 | iscsi_conn_printk(KERN_ERR, conn, | ||
918 | "received invalid itt index %u (max cmds " | ||
919 | "%u.\n", i, session->cmds_max); | ||
920 | return ISCSI_ERR_BAD_ITT; | ||
921 | } | ||
922 | return 0; | ||
923 | } | ||
924 | EXPORT_SYMBOL_GPL(iscsi_verify_itt); | ||
811 | 925 | ||
812 | if (!ctask->sc) { | 926 | /** |
813 | iscsi_conn_printk(KERN_INFO, conn, "dropping ctask " | 927 | * iscsi_itt_to_ctask - look up ctask by itt |
814 | "with itt 0x%x\n", ctask->itt); | 928 | * @conn: iscsi connection |
815 | /* force drop */ | 929 | * @itt: itt |
816 | return ISCSI_ERR_NO_SCSI_CMD; | 930 | * |
817 | } | 931 | * This should be used for cmd tasks. |
932 | * | ||
933 | * The session lock must be held. | ||
934 | */ | ||
935 | struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt) | ||
936 | { | ||
937 | struct iscsi_task *task; | ||
818 | 938 | ||
819 | if (ctask->sc->SCp.phase != session->age) { | 939 | if (iscsi_verify_itt(conn, itt)) |
820 | iscsi_conn_printk(KERN_ERR, conn, | 940 | return NULL; |
821 | "iscsi: ctask's session age %d, " | 941 | |
822 | "expected %d\n", ctask->sc->SCp.phase, | 942 | task = iscsi_itt_to_task(conn, itt); |
823 | session->age); | 943 | if (!task || !task->sc) |
824 | return ISCSI_ERR_SESSION_FAILED; | 944 | return NULL; |
825 | } | 945 | |
946 | if (task->sc->SCp.phase != conn->session->age) { | ||
947 | iscsi_session_printk(KERN_ERR, conn->session, | ||
948 | "task's session age %d, expected %d\n", | ||
949 | task->sc->SCp.phase, conn->session->age); | ||
950 | return NULL; | ||
826 | } | 951 | } |
827 | 952 | ||
828 | *ret_itt = itt; | 953 | return task; |
829 | return 0; | ||
830 | } | 954 | } |
831 | EXPORT_SYMBOL_GPL(iscsi_verify_itt); | 955 | EXPORT_SYMBOL_GPL(iscsi_itt_to_ctask); |
832 | 956 | ||
833 | void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) | 957 | void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) |
834 | { | 958 | { |
@@ -850,61 +974,6 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) | |||
850 | } | 974 | } |
851 | EXPORT_SYMBOL_GPL(iscsi_conn_failure); | 975 | EXPORT_SYMBOL_GPL(iscsi_conn_failure); |
852 | 976 | ||
853 | static void iscsi_prep_mtask(struct iscsi_conn *conn, | ||
854 | struct iscsi_mgmt_task *mtask) | ||
855 | { | ||
856 | struct iscsi_session *session = conn->session; | ||
857 | struct iscsi_hdr *hdr = mtask->hdr; | ||
858 | struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; | ||
859 | |||
860 | if (hdr->opcode != (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) && | ||
861 | hdr->opcode != (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE)) | ||
862 | nop->exp_statsn = cpu_to_be32(conn->exp_statsn); | ||
863 | /* | ||
864 | * pre-format CmdSN for outgoing PDU. | ||
865 | */ | ||
866 | nop->cmdsn = cpu_to_be32(session->cmdsn); | ||
867 | if (hdr->itt != RESERVED_ITT) { | ||
868 | hdr->itt = build_itt(mtask->itt, session->age); | ||
869 | /* | ||
870 | * TODO: We always use immediate, so we never hit this. | ||
871 | * If we start to send tmfs or nops as non-immediate then | ||
872 | * we should start checking the cmdsn numbers for mgmt tasks. | ||
873 | */ | ||
874 | if (conn->c_stage == ISCSI_CONN_STARTED && | ||
875 | !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { | ||
876 | session->queued_cmdsn++; | ||
877 | session->cmdsn++; | ||
878 | } | ||
879 | } | ||
880 | |||
881 | if (session->tt->init_mgmt_task) | ||
882 | session->tt->init_mgmt_task(conn, mtask); | ||
883 | |||
884 | debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", | ||
885 | hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt, | ||
886 | mtask->data_count); | ||
887 | } | ||
888 | |||
889 | static int iscsi_xmit_mtask(struct iscsi_conn *conn) | ||
890 | { | ||
891 | struct iscsi_hdr *hdr = conn->mtask->hdr; | ||
892 | int rc; | ||
893 | |||
894 | if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) | ||
895 | conn->session->state = ISCSI_STATE_LOGGING_OUT; | ||
896 | spin_unlock_bh(&conn->session->lock); | ||
897 | |||
898 | rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask); | ||
899 | spin_lock_bh(&conn->session->lock); | ||
900 | if (rc) | ||
901 | return rc; | ||
902 | |||
903 | /* done with this in-progress mtask */ | ||
904 | conn->mtask = NULL; | ||
905 | return 0; | ||
906 | } | ||
907 | |||
908 | static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) | 977 | static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) |
909 | { | 978 | { |
910 | struct iscsi_session *session = conn->session; | 979 | struct iscsi_session *session = conn->session; |
@@ -922,37 +991,38 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) | |||
922 | return 0; | 991 | return 0; |
923 | } | 992 | } |
924 | 993 | ||
925 | static int iscsi_xmit_ctask(struct iscsi_conn *conn) | 994 | static int iscsi_xmit_task(struct iscsi_conn *conn) |
926 | { | 995 | { |
927 | struct iscsi_cmd_task *ctask = conn->ctask; | 996 | struct iscsi_task *task = conn->task; |
928 | int rc; | 997 | int rc; |
929 | 998 | ||
930 | __iscsi_get_ctask(ctask); | 999 | __iscsi_get_task(task); |
931 | spin_unlock_bh(&conn->session->lock); | 1000 | spin_unlock_bh(&conn->session->lock); |
932 | rc = conn->session->tt->xmit_cmd_task(conn, ctask); | 1001 | rc = conn->session->tt->xmit_task(task); |
933 | spin_lock_bh(&conn->session->lock); | 1002 | spin_lock_bh(&conn->session->lock); |
934 | __iscsi_put_ctask(ctask); | 1003 | __iscsi_put_task(task); |
935 | if (!rc) | 1004 | if (!rc) |
936 | /* done with this ctask */ | 1005 | /* done with this task */ |
937 | conn->ctask = NULL; | 1006 | conn->task = NULL; |
938 | return rc; | 1007 | return rc; |
939 | } | 1008 | } |
940 | 1009 | ||
941 | /** | 1010 | /** |
942 | * iscsi_requeue_ctask - requeue ctask to run from session workqueue | 1011 | * iscsi_requeue_task - requeue task to run from session workqueue |
943 | * @ctask: ctask to requeue | 1012 | * @task: task to requeue |
944 | * | 1013 | * |
945 | * LLDs that need to run a ctask from the session workqueue should call | 1014 | * LLDs that need to run a task from the session workqueue should call |
946 | * this. The session lock must be held. | 1015 | * this. The session lock must be held. This should only be called |
1016 | * by software drivers. | ||
947 | */ | 1017 | */ |
948 | void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask) | 1018 | void iscsi_requeue_task(struct iscsi_task *task) |
949 | { | 1019 | { |
950 | struct iscsi_conn *conn = ctask->conn; | 1020 | struct iscsi_conn *conn = task->conn; |
951 | 1021 | ||
952 | list_move_tail(&ctask->running, &conn->requeue); | 1022 | list_move_tail(&task->running, &conn->requeue); |
953 | scsi_queue_work(conn->session->host, &conn->xmitwork); | 1023 | scsi_queue_work(conn->session->host, &conn->xmitwork); |
954 | } | 1024 | } |
955 | EXPORT_SYMBOL_GPL(iscsi_requeue_ctask); | 1025 | EXPORT_SYMBOL_GPL(iscsi_requeue_task); |
956 | 1026 | ||
957 | /** | 1027 | /** |
958 | * iscsi_data_xmit - xmit any command into the scheduled connection | 1028 | * iscsi_data_xmit - xmit any command into the scheduled connection |
@@ -974,14 +1044,8 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) | |||
974 | return -ENODATA; | 1044 | return -ENODATA; |
975 | } | 1045 | } |
976 | 1046 | ||
977 | if (conn->ctask) { | 1047 | if (conn->task) { |
978 | rc = iscsi_xmit_ctask(conn); | 1048 | rc = iscsi_xmit_task(conn); |
979 | if (rc) | ||
980 | goto again; | ||
981 | } | ||
982 | |||
983 | if (conn->mtask) { | ||
984 | rc = iscsi_xmit_mtask(conn); | ||
985 | if (rc) | 1049 | if (rc) |
986 | goto again; | 1050 | goto again; |
987 | } | 1051 | } |
@@ -993,17 +1057,14 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) | |||
993 | */ | 1057 | */ |
994 | check_mgmt: | 1058 | check_mgmt: |
995 | while (!list_empty(&conn->mgmtqueue)) { | 1059 | while (!list_empty(&conn->mgmtqueue)) { |
996 | conn->mtask = list_entry(conn->mgmtqueue.next, | 1060 | conn->task = list_entry(conn->mgmtqueue.next, |
997 | struct iscsi_mgmt_task, running); | 1061 | struct iscsi_task, running); |
998 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { | 1062 | if (iscsi_prep_mgmt_task(conn, conn->task)) { |
999 | iscsi_free_mgmt_task(conn, conn->mtask); | 1063 | __iscsi_put_task(conn->task); |
1000 | conn->mtask = NULL; | 1064 | conn->task = NULL; |
1001 | continue; | 1065 | continue; |
1002 | } | 1066 | } |
1003 | 1067 | rc = iscsi_xmit_task(conn); | |
1004 | iscsi_prep_mtask(conn, conn->mtask); | ||
1005 | list_move_tail(conn->mgmtqueue.next, &conn->mgmt_run_list); | ||
1006 | rc = iscsi_xmit_mtask(conn); | ||
1007 | if (rc) | 1068 | if (rc) |
1008 | goto again; | 1069 | goto again; |
1009 | } | 1070 | } |
@@ -1013,24 +1074,21 @@ check_mgmt: | |||
1013 | if (conn->tmf_state == TMF_QUEUED) | 1074 | if (conn->tmf_state == TMF_QUEUED) |
1014 | break; | 1075 | break; |
1015 | 1076 | ||
1016 | conn->ctask = list_entry(conn->xmitqueue.next, | 1077 | conn->task = list_entry(conn->xmitqueue.next, |
1017 | struct iscsi_cmd_task, running); | 1078 | struct iscsi_task, running); |
1018 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { | 1079 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { |
1019 | fail_command(conn, conn->ctask, DID_IMM_RETRY << 16); | 1080 | fail_command(conn, conn->task, DID_IMM_RETRY << 16); |
1020 | continue; | 1081 | continue; |
1021 | } | 1082 | } |
1022 | if (iscsi_prep_scsi_cmd_pdu(conn->ctask)) { | 1083 | if (iscsi_prep_scsi_cmd_pdu(conn->task)) { |
1023 | fail_command(conn, conn->ctask, DID_ABORT << 16); | 1084 | fail_command(conn, conn->task, DID_ABORT << 16); |
1024 | continue; | 1085 | continue; |
1025 | } | 1086 | } |
1026 | 1087 | rc = iscsi_xmit_task(conn); | |
1027 | conn->ctask->state = ISCSI_TASK_RUNNING; | ||
1028 | list_move_tail(conn->xmitqueue.next, &conn->run_list); | ||
1029 | rc = iscsi_xmit_ctask(conn); | ||
1030 | if (rc) | 1088 | if (rc) |
1031 | goto again; | 1089 | goto again; |
1032 | /* | 1090 | /* |
1033 | * we could continuously get new ctask requests so | 1091 | * we could continuously get new task requests so |
1034 | * we need to check the mgmt queue for nops that need to | 1092 | * we need to check the mgmt queue for nops that need to |
1035 | * be sent to aviod starvation | 1093 | * be sent to aviod starvation |
1036 | */ | 1094 | */ |
@@ -1048,11 +1106,11 @@ check_mgmt: | |||
1048 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) | 1106 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) |
1049 | break; | 1107 | break; |
1050 | 1108 | ||
1051 | conn->ctask = list_entry(conn->requeue.next, | 1109 | conn->task = list_entry(conn->requeue.next, |
1052 | struct iscsi_cmd_task, running); | 1110 | struct iscsi_task, running); |
1053 | conn->ctask->state = ISCSI_TASK_RUNNING; | 1111 | conn->task->state = ISCSI_TASK_RUNNING; |
1054 | list_move_tail(conn->requeue.next, &conn->run_list); | 1112 | list_move_tail(conn->requeue.next, &conn->run_list); |
1055 | rc = iscsi_xmit_ctask(conn); | 1113 | rc = iscsi_xmit_task(conn); |
1056 | if (rc) | 1114 | if (rc) |
1057 | goto again; | 1115 | goto again; |
1058 | if (!list_empty(&conn->mgmtqueue)) | 1116 | if (!list_empty(&conn->mgmtqueue)) |
@@ -1096,11 +1154,12 @@ enum { | |||
1096 | 1154 | ||
1097 | int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | 1155 | int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) |
1098 | { | 1156 | { |
1157 | struct iscsi_cls_session *cls_session; | ||
1099 | struct Scsi_Host *host; | 1158 | struct Scsi_Host *host; |
1100 | int reason = 0; | 1159 | int reason = 0; |
1101 | struct iscsi_session *session; | 1160 | struct iscsi_session *session; |
1102 | struct iscsi_conn *conn; | 1161 | struct iscsi_conn *conn; |
1103 | struct iscsi_cmd_task *ctask = NULL; | 1162 | struct iscsi_task *task = NULL; |
1104 | 1163 | ||
1105 | sc->scsi_done = done; | 1164 | sc->scsi_done = done; |
1106 | sc->result = 0; | 1165 | sc->result = 0; |
@@ -1109,10 +1168,11 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1109 | host = sc->device->host; | 1168 | host = sc->device->host; |
1110 | spin_unlock(host->host_lock); | 1169 | spin_unlock(host->host_lock); |
1111 | 1170 | ||
1112 | session = iscsi_hostdata(host->hostdata); | 1171 | cls_session = starget_to_session(scsi_target(sc->device)); |
1172 | session = cls_session->dd_data; | ||
1113 | spin_lock(&session->lock); | 1173 | spin_lock(&session->lock); |
1114 | 1174 | ||
1115 | reason = iscsi_session_chkready(session_to_cls(session)); | 1175 | reason = iscsi_session_chkready(cls_session); |
1116 | if (reason) { | 1176 | if (reason) { |
1117 | sc->result = reason; | 1177 | sc->result = reason; |
1118 | goto fault; | 1178 | goto fault; |
@@ -1167,26 +1227,39 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1167 | goto reject; | 1227 | goto reject; |
1168 | } | 1228 | } |
1169 | 1229 | ||
1170 | if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask, | 1230 | if (!__kfifo_get(session->cmdpool.queue, (void*)&task, |
1171 | sizeof(void*))) { | 1231 | sizeof(void*))) { |
1172 | reason = FAILURE_OOM; | 1232 | reason = FAILURE_OOM; |
1173 | goto reject; | 1233 | goto reject; |
1174 | } | 1234 | } |
1175 | session->queued_cmdsn++; | ||
1176 | |||
1177 | sc->SCp.phase = session->age; | 1235 | sc->SCp.phase = session->age; |
1178 | sc->SCp.ptr = (char *)ctask; | 1236 | sc->SCp.ptr = (char *)task; |
1179 | 1237 | ||
1180 | atomic_set(&ctask->refcount, 1); | 1238 | atomic_set(&task->refcount, 1); |
1181 | ctask->state = ISCSI_TASK_PENDING; | 1239 | task->state = ISCSI_TASK_PENDING; |
1182 | ctask->conn = conn; | 1240 | task->conn = conn; |
1183 | ctask->sc = sc; | 1241 | task->sc = sc; |
1184 | INIT_LIST_HEAD(&ctask->running); | 1242 | INIT_LIST_HEAD(&task->running); |
1243 | list_add_tail(&task->running, &conn->xmitqueue); | ||
1244 | |||
1245 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { | ||
1246 | if (iscsi_prep_scsi_cmd_pdu(task)) { | ||
1247 | sc->result = DID_ABORT << 16; | ||
1248 | sc->scsi_done = NULL; | ||
1249 | iscsi_complete_command(task); | ||
1250 | goto fault; | ||
1251 | } | ||
1252 | if (session->tt->xmit_task(task)) { | ||
1253 | sc->scsi_done = NULL; | ||
1254 | iscsi_complete_command(task); | ||
1255 | reason = FAILURE_SESSION_NOT_READY; | ||
1256 | goto reject; | ||
1257 | } | ||
1258 | } else | ||
1259 | scsi_queue_work(session->host, &conn->xmitwork); | ||
1185 | 1260 | ||
1186 | list_add_tail(&ctask->running, &conn->xmitqueue); | 1261 | session->queued_cmdsn++; |
1187 | spin_unlock(&session->lock); | 1262 | spin_unlock(&session->lock); |
1188 | |||
1189 | scsi_queue_work(host, &conn->xmitwork); | ||
1190 | spin_lock(host->host_lock); | 1263 | spin_lock(host->host_lock); |
1191 | return 0; | 1264 | return 0; |
1192 | 1265 | ||
@@ -1205,7 +1278,7 @@ fault: | |||
1205 | scsi_out(sc)->resid = scsi_out(sc)->length; | 1278 | scsi_out(sc)->resid = scsi_out(sc)->length; |
1206 | scsi_in(sc)->resid = scsi_in(sc)->length; | 1279 | scsi_in(sc)->resid = scsi_in(sc)->length; |
1207 | } | 1280 | } |
1208 | sc->scsi_done(sc); | 1281 | done(sc); |
1209 | spin_lock(host->host_lock); | 1282 | spin_lock(host->host_lock); |
1210 | return 0; | 1283 | return 0; |
1211 | } | 1284 | } |
@@ -1222,7 +1295,7 @@ EXPORT_SYMBOL_GPL(iscsi_change_queue_depth); | |||
1222 | 1295 | ||
1223 | void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) | 1296 | void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) |
1224 | { | 1297 | { |
1225 | struct iscsi_session *session = class_to_transport_session(cls_session); | 1298 | struct iscsi_session *session = cls_session->dd_data; |
1226 | 1299 | ||
1227 | spin_lock_bh(&session->lock); | 1300 | spin_lock_bh(&session->lock); |
1228 | if (session->state != ISCSI_STATE_LOGGED_IN) { | 1301 | if (session->state != ISCSI_STATE_LOGGED_IN) { |
@@ -1236,9 +1309,13 @@ EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout); | |||
1236 | 1309 | ||
1237 | int iscsi_eh_host_reset(struct scsi_cmnd *sc) | 1310 | int iscsi_eh_host_reset(struct scsi_cmnd *sc) |
1238 | { | 1311 | { |
1239 | struct Scsi_Host *host = sc->device->host; | 1312 | struct iscsi_cls_session *cls_session; |
1240 | struct iscsi_session *session = iscsi_hostdata(host->hostdata); | 1313 | struct iscsi_session *session; |
1241 | struct iscsi_conn *conn = session->leadconn; | 1314 | struct iscsi_conn *conn; |
1315 | |||
1316 | cls_session = starget_to_session(scsi_target(sc->device)); | ||
1317 | session = cls_session->dd_data; | ||
1318 | conn = session->leadconn; | ||
1242 | 1319 | ||
1243 | mutex_lock(&session->eh_mutex); | 1320 | mutex_lock(&session->eh_mutex); |
1244 | spin_lock_bh(&session->lock); | 1321 | spin_lock_bh(&session->lock); |
@@ -1300,11 +1377,11 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, | |||
1300 | int timeout) | 1377 | int timeout) |
1301 | { | 1378 | { |
1302 | struct iscsi_session *session = conn->session; | 1379 | struct iscsi_session *session = conn->session; |
1303 | struct iscsi_mgmt_task *mtask; | 1380 | struct iscsi_task *task; |
1304 | 1381 | ||
1305 | mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, | 1382 | task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, |
1306 | NULL, 0); | 1383 | NULL, 0); |
1307 | if (!mtask) { | 1384 | if (!task) { |
1308 | spin_unlock_bh(&session->lock); | 1385 | spin_unlock_bh(&session->lock); |
1309 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | 1386 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); |
1310 | spin_lock_bh(&session->lock); | 1387 | spin_lock_bh(&session->lock); |
@@ -1320,7 +1397,6 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, | |||
1320 | 1397 | ||
1321 | spin_unlock_bh(&session->lock); | 1398 | spin_unlock_bh(&session->lock); |
1322 | mutex_unlock(&session->eh_mutex); | 1399 | mutex_unlock(&session->eh_mutex); |
1323 | scsi_queue_work(session->host, &conn->xmitwork); | ||
1324 | 1400 | ||
1325 | /* | 1401 | /* |
1326 | * block eh thread until: | 1402 | * block eh thread until: |
@@ -1339,7 +1415,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, | |||
1339 | 1415 | ||
1340 | mutex_lock(&session->eh_mutex); | 1416 | mutex_lock(&session->eh_mutex); |
1341 | spin_lock_bh(&session->lock); | 1417 | spin_lock_bh(&session->lock); |
1342 | /* if the session drops it will clean up the mtask */ | 1418 | /* if the session drops it will clean up the task */ |
1343 | if (age != session->age || | 1419 | if (age != session->age || |
1344 | session->state != ISCSI_STATE_LOGGED_IN) | 1420 | session->state != ISCSI_STATE_LOGGED_IN) |
1345 | return -ENOTCONN; | 1421 | return -ENOTCONN; |
@@ -1353,48 +1429,51 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, | |||
1353 | static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, | 1429 | static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, |
1354 | int error) | 1430 | int error) |
1355 | { | 1431 | { |
1356 | struct iscsi_cmd_task *ctask, *tmp; | 1432 | struct iscsi_task *task, *tmp; |
1357 | 1433 | ||
1358 | if (conn->ctask && (conn->ctask->sc->device->lun == lun || lun == -1)) | 1434 | if (conn->task && (conn->task->sc->device->lun == lun || lun == -1)) |
1359 | conn->ctask = NULL; | 1435 | conn->task = NULL; |
1360 | 1436 | ||
1361 | /* flush pending */ | 1437 | /* flush pending */ |
1362 | list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) { | 1438 | list_for_each_entry_safe(task, tmp, &conn->xmitqueue, running) { |
1363 | if (lun == ctask->sc->device->lun || lun == -1) { | 1439 | if (lun == task->sc->device->lun || lun == -1) { |
1364 | debug_scsi("failing pending sc %p itt 0x%x\n", | 1440 | debug_scsi("failing pending sc %p itt 0x%x\n", |
1365 | ctask->sc, ctask->itt); | 1441 | task->sc, task->itt); |
1366 | fail_command(conn, ctask, error << 16); | 1442 | fail_command(conn, task, error << 16); |
1367 | } | 1443 | } |
1368 | } | 1444 | } |
1369 | 1445 | ||
1370 | list_for_each_entry_safe(ctask, tmp, &conn->requeue, running) { | 1446 | list_for_each_entry_safe(task, tmp, &conn->requeue, running) { |
1371 | if (lun == ctask->sc->device->lun || lun == -1) { | 1447 | if (lun == task->sc->device->lun || lun == -1) { |
1372 | debug_scsi("failing requeued sc %p itt 0x%x\n", | 1448 | debug_scsi("failing requeued sc %p itt 0x%x\n", |
1373 | ctask->sc, ctask->itt); | 1449 | task->sc, task->itt); |
1374 | fail_command(conn, ctask, error << 16); | 1450 | fail_command(conn, task, error << 16); |
1375 | } | 1451 | } |
1376 | } | 1452 | } |
1377 | 1453 | ||
1378 | /* fail all other running */ | 1454 | /* fail all other running */ |
1379 | list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) { | 1455 | list_for_each_entry_safe(task, tmp, &conn->run_list, running) { |
1380 | if (lun == ctask->sc->device->lun || lun == -1) { | 1456 | if (lun == task->sc->device->lun || lun == -1) { |
1381 | debug_scsi("failing in progress sc %p itt 0x%x\n", | 1457 | debug_scsi("failing in progress sc %p itt 0x%x\n", |
1382 | ctask->sc, ctask->itt); | 1458 | task->sc, task->itt); |
1383 | fail_command(conn, ctask, DID_BUS_BUSY << 16); | 1459 | fail_command(conn, task, DID_BUS_BUSY << 16); |
1384 | } | 1460 | } |
1385 | } | 1461 | } |
1386 | } | 1462 | } |
1387 | 1463 | ||
1388 | static void iscsi_suspend_tx(struct iscsi_conn *conn) | 1464 | void iscsi_suspend_tx(struct iscsi_conn *conn) |
1389 | { | 1465 | { |
1390 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | 1466 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
1391 | scsi_flush_work(conn->session->host); | 1467 | if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) |
1468 | scsi_flush_work(conn->session->host); | ||
1392 | } | 1469 | } |
1470 | EXPORT_SYMBOL_GPL(iscsi_suspend_tx); | ||
1393 | 1471 | ||
1394 | static void iscsi_start_tx(struct iscsi_conn *conn) | 1472 | static void iscsi_start_tx(struct iscsi_conn *conn) |
1395 | { | 1473 | { |
1396 | clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | 1474 | clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
1397 | scsi_queue_work(conn->session->host, &conn->xmitwork); | 1475 | if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD)) |
1476 | scsi_queue_work(conn->session->host, &conn->xmitwork); | ||
1398 | } | 1477 | } |
1399 | 1478 | ||
1400 | static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) | 1479 | static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) |
@@ -1405,7 +1484,7 @@ static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) | |||
1405 | enum scsi_eh_timer_return rc = EH_NOT_HANDLED; | 1484 | enum scsi_eh_timer_return rc = EH_NOT_HANDLED; |
1406 | 1485 | ||
1407 | cls_session = starget_to_session(scsi_target(scmd->device)); | 1486 | cls_session = starget_to_session(scsi_target(scmd->device)); |
1408 | session = class_to_transport_session(cls_session); | 1487 | session = cls_session->dd_data; |
1409 | 1488 | ||
1410 | debug_scsi("scsi cmd %p timedout\n", scmd); | 1489 | debug_scsi("scsi cmd %p timedout\n", scmd); |
1411 | 1490 | ||
@@ -1443,7 +1522,7 @@ static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) | |||
1443 | jiffies)) | 1522 | jiffies)) |
1444 | rc = EH_RESET_TIMER; | 1523 | rc = EH_RESET_TIMER; |
1445 | /* if in the middle of checking the transport then give us more time */ | 1524 | /* if in the middle of checking the transport then give us more time */ |
1446 | if (conn->ping_mtask) | 1525 | if (conn->ping_task) |
1447 | rc = EH_RESET_TIMER; | 1526 | rc = EH_RESET_TIMER; |
1448 | done: | 1527 | done: |
1449 | spin_unlock(&session->lock); | 1528 | spin_unlock(&session->lock); |
@@ -1467,7 +1546,7 @@ static void iscsi_check_transport_timeouts(unsigned long data) | |||
1467 | 1546 | ||
1468 | recv_timeout *= HZ; | 1547 | recv_timeout *= HZ; |
1469 | last_recv = conn->last_recv; | 1548 | last_recv = conn->last_recv; |
1470 | if (conn->ping_mtask && | 1549 | if (conn->ping_task && |
1471 | time_before_eq(conn->last_ping + (conn->ping_timeout * HZ), | 1550 | time_before_eq(conn->last_ping + (conn->ping_timeout * HZ), |
1472 | jiffies)) { | 1551 | jiffies)) { |
1473 | iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " | 1552 | iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " |
@@ -1493,27 +1572,30 @@ done: | |||
1493 | spin_unlock(&session->lock); | 1572 | spin_unlock(&session->lock); |
1494 | } | 1573 | } |
1495 | 1574 | ||
1496 | static void iscsi_prep_abort_task_pdu(struct iscsi_cmd_task *ctask, | 1575 | static void iscsi_prep_abort_task_pdu(struct iscsi_task *task, |
1497 | struct iscsi_tm *hdr) | 1576 | struct iscsi_tm *hdr) |
1498 | { | 1577 | { |
1499 | memset(hdr, 0, sizeof(*hdr)); | 1578 | memset(hdr, 0, sizeof(*hdr)); |
1500 | hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; | 1579 | hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; |
1501 | hdr->flags = ISCSI_TM_FUNC_ABORT_TASK & ISCSI_FLAG_TM_FUNC_MASK; | 1580 | hdr->flags = ISCSI_TM_FUNC_ABORT_TASK & ISCSI_FLAG_TM_FUNC_MASK; |
1502 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | 1581 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; |
1503 | memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); | 1582 | memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun)); |
1504 | hdr->rtt = ctask->hdr->itt; | 1583 | hdr->rtt = task->hdr->itt; |
1505 | hdr->refcmdsn = ctask->hdr->cmdsn; | 1584 | hdr->refcmdsn = task->hdr->cmdsn; |
1506 | } | 1585 | } |
1507 | 1586 | ||
1508 | int iscsi_eh_abort(struct scsi_cmnd *sc) | 1587 | int iscsi_eh_abort(struct scsi_cmnd *sc) |
1509 | { | 1588 | { |
1510 | struct Scsi_Host *host = sc->device->host; | 1589 | struct iscsi_cls_session *cls_session; |
1511 | struct iscsi_session *session = iscsi_hostdata(host->hostdata); | 1590 | struct iscsi_session *session; |
1512 | struct iscsi_conn *conn; | 1591 | struct iscsi_conn *conn; |
1513 | struct iscsi_cmd_task *ctask; | 1592 | struct iscsi_task *task; |
1514 | struct iscsi_tm *hdr; | 1593 | struct iscsi_tm *hdr; |
1515 | int rc, age; | 1594 | int rc, age; |
1516 | 1595 | ||
1596 | cls_session = starget_to_session(scsi_target(sc->device)); | ||
1597 | session = cls_session->dd_data; | ||
1598 | |||
1517 | mutex_lock(&session->eh_mutex); | 1599 | mutex_lock(&session->eh_mutex); |
1518 | spin_lock_bh(&session->lock); | 1600 | spin_lock_bh(&session->lock); |
1519 | /* | 1601 | /* |
@@ -1542,17 +1624,17 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1542 | conn->eh_abort_cnt++; | 1624 | conn->eh_abort_cnt++; |
1543 | age = session->age; | 1625 | age = session->age; |
1544 | 1626 | ||
1545 | ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; | 1627 | task = (struct iscsi_task *)sc->SCp.ptr; |
1546 | debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); | 1628 | debug_scsi("aborting [sc %p itt 0x%x]\n", sc, task->itt); |
1547 | 1629 | ||
1548 | /* ctask completed before time out */ | 1630 | /* task completed before time out */ |
1549 | if (!ctask->sc) { | 1631 | if (!task->sc) { |
1550 | debug_scsi("sc completed while abort in progress\n"); | 1632 | debug_scsi("sc completed while abort in progress\n"); |
1551 | goto success; | 1633 | goto success; |
1552 | } | 1634 | } |
1553 | 1635 | ||
1554 | if (ctask->state == ISCSI_TASK_PENDING) { | 1636 | if (task->state == ISCSI_TASK_PENDING) { |
1555 | fail_command(conn, ctask, DID_ABORT << 16); | 1637 | fail_command(conn, task, DID_ABORT << 16); |
1556 | goto success; | 1638 | goto success; |
1557 | } | 1639 | } |
1558 | 1640 | ||
@@ -1562,7 +1644,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1562 | conn->tmf_state = TMF_QUEUED; | 1644 | conn->tmf_state = TMF_QUEUED; |
1563 | 1645 | ||
1564 | hdr = &conn->tmhdr; | 1646 | hdr = &conn->tmhdr; |
1565 | iscsi_prep_abort_task_pdu(ctask, hdr); | 1647 | iscsi_prep_abort_task_pdu(task, hdr); |
1566 | 1648 | ||
1567 | if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) { | 1649 | if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) { |
1568 | rc = FAILED; | 1650 | rc = FAILED; |
@@ -1572,16 +1654,20 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1572 | switch (conn->tmf_state) { | 1654 | switch (conn->tmf_state) { |
1573 | case TMF_SUCCESS: | 1655 | case TMF_SUCCESS: |
1574 | spin_unlock_bh(&session->lock); | 1656 | spin_unlock_bh(&session->lock); |
1657 | /* | ||
1658 | * stop tx side incase the target had sent a abort rsp but | ||
1659 | * the initiator was still writing out data. | ||
1660 | */ | ||
1575 | iscsi_suspend_tx(conn); | 1661 | iscsi_suspend_tx(conn); |
1576 | /* | 1662 | /* |
1577 | * clean up task if aborted. grab the recv lock as a writer | 1663 | * we do not stop the recv side because targets have been |
1664 | * good and have never sent us a successful tmf response | ||
1665 | * then sent more data for the cmd. | ||
1578 | */ | 1666 | */ |
1579 | write_lock_bh(conn->recv_lock); | ||
1580 | spin_lock(&session->lock); | 1667 | spin_lock(&session->lock); |
1581 | fail_command(conn, ctask, DID_ABORT << 16); | 1668 | fail_command(conn, task, DID_ABORT << 16); |
1582 | conn->tmf_state = TMF_INITIAL; | 1669 | conn->tmf_state = TMF_INITIAL; |
1583 | spin_unlock(&session->lock); | 1670 | spin_unlock(&session->lock); |
1584 | write_unlock_bh(conn->recv_lock); | ||
1585 | iscsi_start_tx(conn); | 1671 | iscsi_start_tx(conn); |
1586 | goto success_unlocked; | 1672 | goto success_unlocked; |
1587 | case TMF_TIMEDOUT: | 1673 | case TMF_TIMEDOUT: |
@@ -1591,7 +1677,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1591 | case TMF_NOT_FOUND: | 1677 | case TMF_NOT_FOUND: |
1592 | if (!sc->SCp.ptr) { | 1678 | if (!sc->SCp.ptr) { |
1593 | conn->tmf_state = TMF_INITIAL; | 1679 | conn->tmf_state = TMF_INITIAL; |
1594 | /* ctask completed before tmf abort response */ | 1680 | /* task completed before tmf abort response */ |
1595 | debug_scsi("sc completed while abort in progress\n"); | 1681 | debug_scsi("sc completed while abort in progress\n"); |
1596 | goto success; | 1682 | goto success; |
1597 | } | 1683 | } |
@@ -1604,7 +1690,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1604 | success: | 1690 | success: |
1605 | spin_unlock_bh(&session->lock); | 1691 | spin_unlock_bh(&session->lock); |
1606 | success_unlocked: | 1692 | success_unlocked: |
1607 | debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); | 1693 | debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, task->itt); |
1608 | mutex_unlock(&session->eh_mutex); | 1694 | mutex_unlock(&session->eh_mutex); |
1609 | return SUCCESS; | 1695 | return SUCCESS; |
1610 | 1696 | ||
@@ -1612,7 +1698,7 @@ failed: | |||
1612 | spin_unlock_bh(&session->lock); | 1698 | spin_unlock_bh(&session->lock); |
1613 | failed_unlocked: | 1699 | failed_unlocked: |
1614 | debug_scsi("abort failed [sc %p itt 0x%x]\n", sc, | 1700 | debug_scsi("abort failed [sc %p itt 0x%x]\n", sc, |
1615 | ctask ? ctask->itt : 0); | 1701 | task ? task->itt : 0); |
1616 | mutex_unlock(&session->eh_mutex); | 1702 | mutex_unlock(&session->eh_mutex); |
1617 | return FAILED; | 1703 | return FAILED; |
1618 | } | 1704 | } |
@@ -1630,12 +1716,15 @@ static void iscsi_prep_lun_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr) | |||
1630 | 1716 | ||
1631 | int iscsi_eh_device_reset(struct scsi_cmnd *sc) | 1717 | int iscsi_eh_device_reset(struct scsi_cmnd *sc) |
1632 | { | 1718 | { |
1633 | struct Scsi_Host *host = sc->device->host; | 1719 | struct iscsi_cls_session *cls_session; |
1634 | struct iscsi_session *session = iscsi_hostdata(host->hostdata); | 1720 | struct iscsi_session *session; |
1635 | struct iscsi_conn *conn; | 1721 | struct iscsi_conn *conn; |
1636 | struct iscsi_tm *hdr; | 1722 | struct iscsi_tm *hdr; |
1637 | int rc = FAILED; | 1723 | int rc = FAILED; |
1638 | 1724 | ||
1725 | cls_session = starget_to_session(scsi_target(sc->device)); | ||
1726 | session = cls_session->dd_data; | ||
1727 | |||
1639 | debug_scsi("LU Reset [sc %p lun %u]\n", sc, sc->device->lun); | 1728 | debug_scsi("LU Reset [sc %p lun %u]\n", sc, sc->device->lun); |
1640 | 1729 | ||
1641 | mutex_lock(&session->eh_mutex); | 1730 | mutex_lock(&session->eh_mutex); |
@@ -1678,13 +1767,11 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) | |||
1678 | spin_unlock_bh(&session->lock); | 1767 | spin_unlock_bh(&session->lock); |
1679 | 1768 | ||
1680 | iscsi_suspend_tx(conn); | 1769 | iscsi_suspend_tx(conn); |
1681 | /* need to grab the recv lock then session lock */ | 1770 | |
1682 | write_lock_bh(conn->recv_lock); | ||
1683 | spin_lock(&session->lock); | 1771 | spin_lock(&session->lock); |
1684 | fail_all_commands(conn, sc->device->lun, DID_ERROR); | 1772 | fail_all_commands(conn, sc->device->lun, DID_ERROR); |
1685 | conn->tmf_state = TMF_INITIAL; | 1773 | conn->tmf_state = TMF_INITIAL; |
1686 | spin_unlock(&session->lock); | 1774 | spin_unlock(&session->lock); |
1687 | write_unlock_bh(conn->recv_lock); | ||
1688 | 1775 | ||
1689 | iscsi_start_tx(conn); | 1776 | iscsi_start_tx(conn); |
1690 | goto done; | 1777 | goto done; |
@@ -1760,177 +1847,203 @@ void iscsi_pool_free(struct iscsi_pool *q) | |||
1760 | } | 1847 | } |
1761 | EXPORT_SYMBOL_GPL(iscsi_pool_free); | 1848 | EXPORT_SYMBOL_GPL(iscsi_pool_free); |
1762 | 1849 | ||
1763 | /* | 1850 | /** |
1764 | * iSCSI Session's hostdata organization: | 1851 | * iscsi_host_add - add host to system |
1852 | * @shost: scsi host | ||
1853 | * @pdev: parent device | ||
1854 | * | ||
1855 | * This should be called by partial offload and software iscsi drivers | ||
1856 | * to add a host to the system. | ||
1857 | */ | ||
1858 | int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev) | ||
1859 | { | ||
1860 | if (!shost->can_queue) | ||
1861 | shost->can_queue = ISCSI_DEF_XMIT_CMDS_MAX; | ||
1862 | |||
1863 | return scsi_add_host(shost, pdev); | ||
1864 | } | ||
1865 | EXPORT_SYMBOL_GPL(iscsi_host_add); | ||
1866 | |||
1867 | /** | ||
1868 | * iscsi_host_alloc - allocate a host and driver data | ||
1869 | * @sht: scsi host template | ||
1870 | * @dd_data_size: driver host data size | ||
1871 | * @qdepth: default device queue depth | ||
1872 | * | ||
1873 | * This should be called by partial offload and software iscsi drivers. | ||
1874 | * To access the driver specific memory use the iscsi_host_priv() macro. | ||
1875 | */ | ||
1876 | struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, | ||
1877 | int dd_data_size, uint16_t qdepth) | ||
1878 | { | ||
1879 | struct Scsi_Host *shost; | ||
1880 | |||
1881 | shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size); | ||
1882 | if (!shost) | ||
1883 | return NULL; | ||
1884 | shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out; | ||
1885 | |||
1886 | if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) { | ||
1887 | if (qdepth != 0) | ||
1888 | printk(KERN_ERR "iscsi: invalid queue depth of %d. " | ||
1889 | "Queue depth must be between 1 and %d.\n", | ||
1890 | qdepth, ISCSI_MAX_CMD_PER_LUN); | ||
1891 | qdepth = ISCSI_DEF_CMD_PER_LUN; | ||
1892 | } | ||
1893 | shost->cmd_per_lun = qdepth; | ||
1894 | return shost; | ||
1895 | } | ||
1896 | EXPORT_SYMBOL_GPL(iscsi_host_alloc); | ||
1897 | |||
1898 | /** | ||
1899 | * iscsi_host_remove - remove host and sessions | ||
1900 | * @shost: scsi host | ||
1765 | * | 1901 | * |
1766 | * *------------------* <== hostdata_session(host->hostdata) | 1902 | * This will also remove any sessions attached to the host, but if userspace |
1767 | * | ptr to class sess| | 1903 | * is managing the session at the same time this will break. TODO: add |
1768 | * |------------------| <== iscsi_hostdata(host->hostdata) | 1904 | * refcounting to the netlink iscsi interface so a rmmod or host hot unplug |
1769 | * | iscsi_session | | 1905 | * does not remove the memory from under us. |
1770 | * *------------------* | ||
1771 | */ | 1906 | */ |
1907 | void iscsi_host_remove(struct Scsi_Host *shost) | ||
1908 | { | ||
1909 | iscsi_host_for_each_session(shost, iscsi_session_teardown); | ||
1910 | scsi_remove_host(shost); | ||
1911 | } | ||
1912 | EXPORT_SYMBOL_GPL(iscsi_host_remove); | ||
1772 | 1913 | ||
1773 | #define hostdata_privsize(_sz) (sizeof(unsigned long) + _sz + \ | 1914 | void iscsi_host_free(struct Scsi_Host *shost) |
1774 | _sz % sizeof(unsigned long)) | 1915 | { |
1916 | struct iscsi_host *ihost = shost_priv(shost); | ||
1775 | 1917 | ||
1776 | #define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata)) | 1918 | kfree(ihost->netdev); |
1919 | kfree(ihost->hwaddress); | ||
1920 | kfree(ihost->initiatorname); | ||
1921 | scsi_host_put(shost); | ||
1922 | } | ||
1923 | EXPORT_SYMBOL_GPL(iscsi_host_free); | ||
1777 | 1924 | ||
1778 | /** | 1925 | /** |
1779 | * iscsi_session_setup - create iscsi cls session and host and session | 1926 | * iscsi_session_setup - create iscsi cls session and host and session |
1780 | * @scsit: scsi transport template | ||
1781 | * @iscsit: iscsi transport template | 1927 | * @iscsit: iscsi transport template |
1782 | * @cmds_max: scsi host can queue | 1928 | * @shost: scsi host |
1783 | * @qdepth: scsi host cmds per lun | 1929 | * @cmds_max: session can queue |
1784 | * @cmd_task_size: LLD ctask private data size | 1930 | * @cmd_task_size: LLD task private data size |
1785 | * @mgmt_task_size: LLD mtask private data size | ||
1786 | * @initial_cmdsn: initial CmdSN | 1931 | * @initial_cmdsn: initial CmdSN |
1787 | * @hostno: host no allocated | ||
1788 | * | 1932 | * |
1789 | * This can be used by software iscsi_transports that allocate | 1933 | * This can be used by software iscsi_transports that allocate |
1790 | * a session per scsi host. | 1934 | * a session per scsi host. |
1791 | **/ | 1935 | * |
1936 | * Callers should set cmds_max to the largest total numer (mgmt + scsi) of | ||
1937 | * tasks they support. The iscsi layer reserves ISCSI_MGMT_CMDS_MAX tasks | ||
1938 | * for nop handling and login/logout requests. | ||
1939 | */ | ||
1792 | struct iscsi_cls_session * | 1940 | struct iscsi_cls_session * |
1793 | iscsi_session_setup(struct iscsi_transport *iscsit, | 1941 | iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, |
1794 | struct scsi_transport_template *scsit, | 1942 | uint16_t cmds_max, int cmd_task_size, |
1795 | uint16_t cmds_max, uint16_t qdepth, | 1943 | uint32_t initial_cmdsn, unsigned int id) |
1796 | int cmd_task_size, int mgmt_task_size, | ||
1797 | uint32_t initial_cmdsn, uint32_t *hostno) | ||
1798 | { | 1944 | { |
1799 | struct Scsi_Host *shost; | ||
1800 | struct iscsi_session *session; | 1945 | struct iscsi_session *session; |
1801 | struct iscsi_cls_session *cls_session; | 1946 | struct iscsi_cls_session *cls_session; |
1802 | int cmd_i; | 1947 | int cmd_i, scsi_cmds, total_cmds = cmds_max; |
1803 | 1948 | ||
1804 | if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) { | 1949 | if (!total_cmds) |
1805 | if (qdepth != 0) | 1950 | total_cmds = ISCSI_DEF_XMIT_CMDS_MAX; |
1806 | printk(KERN_ERR "iscsi: invalid queue depth of %d. " | 1951 | /* |
1807 | "Queue depth must be between 1 and %d.\n", | 1952 | * The iscsi layer needs some tasks for nop handling and tmfs, |
1808 | qdepth, ISCSI_MAX_CMD_PER_LUN); | 1953 | * so the cmds_max must at least be greater than ISCSI_MGMT_CMDS_MAX |
1809 | qdepth = ISCSI_DEF_CMD_PER_LUN; | 1954 | * + 1 command for scsi IO. |
1955 | */ | ||
1956 | if (total_cmds < ISCSI_TOTAL_CMDS_MIN) { | ||
1957 | printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue " | ||
1958 | "must be a power of two that is at least %d.\n", | ||
1959 | total_cmds, ISCSI_TOTAL_CMDS_MIN); | ||
1960 | return NULL; | ||
1810 | } | 1961 | } |
1811 | 1962 | ||
1812 | if (!is_power_of_2(cmds_max) || cmds_max >= ISCSI_MGMT_ITT_OFFSET || | 1963 | if (total_cmds > ISCSI_TOTAL_CMDS_MAX) { |
1813 | cmds_max < 2) { | 1964 | printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue " |
1814 | if (cmds_max != 0) | 1965 | "must be a power of 2 less than or equal to %d.\n", |
1815 | printk(KERN_ERR "iscsi: invalid can_queue of %d. " | 1966 | cmds_max, ISCSI_TOTAL_CMDS_MAX); |
1816 | "can_queue must be a power of 2 and between " | 1967 | total_cmds = ISCSI_TOTAL_CMDS_MAX; |
1817 | "2 and %d - setting to %d.\n", cmds_max, | ||
1818 | ISCSI_MGMT_ITT_OFFSET, ISCSI_DEF_XMIT_CMDS_MAX); | ||
1819 | cmds_max = ISCSI_DEF_XMIT_CMDS_MAX; | ||
1820 | } | 1968 | } |
1821 | 1969 | ||
1822 | shost = scsi_host_alloc(iscsit->host_template, | 1970 | if (!is_power_of_2(total_cmds)) { |
1823 | hostdata_privsize(sizeof(*session))); | 1971 | printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue " |
1824 | if (!shost) | 1972 | "must be a power of 2.\n", total_cmds); |
1825 | return NULL; | 1973 | total_cmds = rounddown_pow_of_two(total_cmds); |
1826 | 1974 | if (total_cmds < ISCSI_TOTAL_CMDS_MIN) | |
1827 | /* the iscsi layer takes one task for reserve */ | 1975 | return NULL; |
1828 | shost->can_queue = cmds_max - 1; | 1976 | printk(KERN_INFO "iscsi: Rounding can_queue to %d.\n", |
1829 | shost->cmd_per_lun = qdepth; | 1977 | total_cmds); |
1830 | shost->max_id = 1; | 1978 | } |
1831 | shost->max_channel = 0; | 1979 | scsi_cmds = total_cmds - ISCSI_MGMT_CMDS_MAX; |
1832 | shost->max_lun = iscsit->max_lun; | ||
1833 | shost->max_cmd_len = iscsit->max_cmd_len; | ||
1834 | shost->transportt = scsit; | ||
1835 | shost->transportt->create_work_queue = 1; | ||
1836 | shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out; | ||
1837 | *hostno = shost->host_no; | ||
1838 | 1980 | ||
1839 | session = iscsi_hostdata(shost->hostdata); | 1981 | cls_session = iscsi_alloc_session(shost, iscsit, |
1840 | memset(session, 0, sizeof(struct iscsi_session)); | 1982 | sizeof(struct iscsi_session)); |
1983 | if (!cls_session) | ||
1984 | return NULL; | ||
1985 | session = cls_session->dd_data; | ||
1986 | session->cls_session = cls_session; | ||
1841 | session->host = shost; | 1987 | session->host = shost; |
1842 | session->state = ISCSI_STATE_FREE; | 1988 | session->state = ISCSI_STATE_FREE; |
1843 | session->fast_abort = 1; | 1989 | session->fast_abort = 1; |
1844 | session->lu_reset_timeout = 15; | 1990 | session->lu_reset_timeout = 15; |
1845 | session->abort_timeout = 10; | 1991 | session->abort_timeout = 10; |
1846 | session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; | 1992 | session->scsi_cmds_max = scsi_cmds; |
1847 | session->cmds_max = cmds_max; | 1993 | session->cmds_max = total_cmds; |
1848 | session->queued_cmdsn = session->cmdsn = initial_cmdsn; | 1994 | session->queued_cmdsn = session->cmdsn = initial_cmdsn; |
1849 | session->exp_cmdsn = initial_cmdsn + 1; | 1995 | session->exp_cmdsn = initial_cmdsn + 1; |
1850 | session->max_cmdsn = initial_cmdsn + 1; | 1996 | session->max_cmdsn = initial_cmdsn + 1; |
1851 | session->max_r2t = 1; | 1997 | session->max_r2t = 1; |
1852 | session->tt = iscsit; | 1998 | session->tt = iscsit; |
1853 | mutex_init(&session->eh_mutex); | 1999 | mutex_init(&session->eh_mutex); |
2000 | spin_lock_init(&session->lock); | ||
1854 | 2001 | ||
1855 | /* initialize SCSI PDU commands pool */ | 2002 | /* initialize SCSI PDU commands pool */ |
1856 | if (iscsi_pool_init(&session->cmdpool, session->cmds_max, | 2003 | if (iscsi_pool_init(&session->cmdpool, session->cmds_max, |
1857 | (void***)&session->cmds, | 2004 | (void***)&session->cmds, |
1858 | cmd_task_size + sizeof(struct iscsi_cmd_task))) | 2005 | cmd_task_size + sizeof(struct iscsi_task))) |
1859 | goto cmdpool_alloc_fail; | 2006 | goto cmdpool_alloc_fail; |
1860 | 2007 | ||
1861 | /* pre-format cmds pool with ITT */ | 2008 | /* pre-format cmds pool with ITT */ |
1862 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { | 2009 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { |
1863 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; | 2010 | struct iscsi_task *task = session->cmds[cmd_i]; |
1864 | 2011 | ||
1865 | if (cmd_task_size) | 2012 | if (cmd_task_size) |
1866 | ctask->dd_data = &ctask[1]; | 2013 | task->dd_data = &task[1]; |
1867 | ctask->itt = cmd_i; | 2014 | task->itt = cmd_i; |
1868 | INIT_LIST_HEAD(&ctask->running); | 2015 | INIT_LIST_HEAD(&task->running); |
1869 | } | ||
1870 | |||
1871 | spin_lock_init(&session->lock); | ||
1872 | |||
1873 | /* initialize immediate command pool */ | ||
1874 | if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max, | ||
1875 | (void***)&session->mgmt_cmds, | ||
1876 | mgmt_task_size + sizeof(struct iscsi_mgmt_task))) | ||
1877 | goto mgmtpool_alloc_fail; | ||
1878 | |||
1879 | |||
1880 | /* pre-format immediate cmds pool with ITT */ | ||
1881 | for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) { | ||
1882 | struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i]; | ||
1883 | |||
1884 | if (mgmt_task_size) | ||
1885 | mtask->dd_data = &mtask[1]; | ||
1886 | mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i; | ||
1887 | INIT_LIST_HEAD(&mtask->running); | ||
1888 | } | 2016 | } |
1889 | 2017 | ||
1890 | if (scsi_add_host(shost, NULL)) | ||
1891 | goto add_host_fail; | ||
1892 | |||
1893 | if (!try_module_get(iscsit->owner)) | 2018 | if (!try_module_get(iscsit->owner)) |
1894 | goto cls_session_fail; | 2019 | goto module_get_fail; |
1895 | |||
1896 | cls_session = iscsi_create_session(shost, iscsit, 0); | ||
1897 | if (!cls_session) | ||
1898 | goto module_put; | ||
1899 | *(unsigned long*)shost->hostdata = (unsigned long)cls_session; | ||
1900 | 2020 | ||
2021 | if (iscsi_add_session(cls_session, id)) | ||
2022 | goto cls_session_fail; | ||
1901 | return cls_session; | 2023 | return cls_session; |
1902 | 2024 | ||
1903 | module_put: | ||
1904 | module_put(iscsit->owner); | ||
1905 | cls_session_fail: | 2025 | cls_session_fail: |
1906 | scsi_remove_host(shost); | 2026 | module_put(iscsit->owner); |
1907 | add_host_fail: | 2027 | module_get_fail: |
1908 | iscsi_pool_free(&session->mgmtpool); | ||
1909 | mgmtpool_alloc_fail: | ||
1910 | iscsi_pool_free(&session->cmdpool); | 2028 | iscsi_pool_free(&session->cmdpool); |
1911 | cmdpool_alloc_fail: | 2029 | cmdpool_alloc_fail: |
1912 | scsi_host_put(shost); | 2030 | iscsi_free_session(cls_session); |
1913 | return NULL; | 2031 | return NULL; |
1914 | } | 2032 | } |
1915 | EXPORT_SYMBOL_GPL(iscsi_session_setup); | 2033 | EXPORT_SYMBOL_GPL(iscsi_session_setup); |
1916 | 2034 | ||
1917 | /** | 2035 | /** |
1918 | * iscsi_session_teardown - destroy session, host, and cls_session | 2036 | * iscsi_session_teardown - destroy session, host, and cls_session |
1919 | * shost: scsi host | 2037 | * @cls_session: iscsi session |
1920 | * | 2038 | * |
1921 | * This can be used by software iscsi_transports that allocate | 2039 | * The driver must have called iscsi_remove_session before |
1922 | * a session per scsi host. | 2040 | * calling this. |
1923 | **/ | 2041 | */ |
1924 | void iscsi_session_teardown(struct iscsi_cls_session *cls_session) | 2042 | void iscsi_session_teardown(struct iscsi_cls_session *cls_session) |
1925 | { | 2043 | { |
1926 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); | 2044 | struct iscsi_session *session = cls_session->dd_data; |
1927 | struct iscsi_session *session = iscsi_hostdata(shost->hostdata); | ||
1928 | struct module *owner = cls_session->transport->owner; | 2045 | struct module *owner = cls_session->transport->owner; |
1929 | 2046 | ||
1930 | iscsi_remove_session(cls_session); | ||
1931 | scsi_remove_host(shost); | ||
1932 | |||
1933 | iscsi_pool_free(&session->mgmtpool); | ||
1934 | iscsi_pool_free(&session->cmdpool); | 2047 | iscsi_pool_free(&session->cmdpool); |
1935 | 2048 | ||
1936 | kfree(session->password); | 2049 | kfree(session->password); |
@@ -1938,12 +2051,10 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session) | |||
1938 | kfree(session->username); | 2051 | kfree(session->username); |
1939 | kfree(session->username_in); | 2052 | kfree(session->username_in); |
1940 | kfree(session->targetname); | 2053 | kfree(session->targetname); |
1941 | kfree(session->netdev); | ||
1942 | kfree(session->hwaddress); | ||
1943 | kfree(session->initiatorname); | 2054 | kfree(session->initiatorname); |
2055 | kfree(session->ifacename); | ||
1944 | 2056 | ||
1945 | iscsi_free_session(cls_session); | 2057 | iscsi_destroy_session(cls_session); |
1946 | scsi_host_put(shost); | ||
1947 | module_put(owner); | 2058 | module_put(owner); |
1948 | } | 2059 | } |
1949 | EXPORT_SYMBOL_GPL(iscsi_session_teardown); | 2060 | EXPORT_SYMBOL_GPL(iscsi_session_teardown); |
@@ -1951,22 +2062,26 @@ EXPORT_SYMBOL_GPL(iscsi_session_teardown); | |||
1951 | /** | 2062 | /** |
1952 | * iscsi_conn_setup - create iscsi_cls_conn and iscsi_conn | 2063 | * iscsi_conn_setup - create iscsi_cls_conn and iscsi_conn |
1953 | * @cls_session: iscsi_cls_session | 2064 | * @cls_session: iscsi_cls_session |
2065 | * @dd_size: private driver data size | ||
1954 | * @conn_idx: cid | 2066 | * @conn_idx: cid |
1955 | **/ | 2067 | */ |
1956 | struct iscsi_cls_conn * | 2068 | struct iscsi_cls_conn * |
1957 | iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | 2069 | iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, |
2070 | uint32_t conn_idx) | ||
1958 | { | 2071 | { |
1959 | struct iscsi_session *session = class_to_transport_session(cls_session); | 2072 | struct iscsi_session *session = cls_session->dd_data; |
1960 | struct iscsi_conn *conn; | 2073 | struct iscsi_conn *conn; |
1961 | struct iscsi_cls_conn *cls_conn; | 2074 | struct iscsi_cls_conn *cls_conn; |
1962 | char *data; | 2075 | char *data; |
1963 | 2076 | ||
1964 | cls_conn = iscsi_create_conn(cls_session, conn_idx); | 2077 | cls_conn = iscsi_create_conn(cls_session, sizeof(*conn) + dd_size, |
2078 | conn_idx); | ||
1965 | if (!cls_conn) | 2079 | if (!cls_conn) |
1966 | return NULL; | 2080 | return NULL; |
1967 | conn = cls_conn->dd_data; | 2081 | conn = cls_conn->dd_data; |
1968 | memset(conn, 0, sizeof(*conn)); | 2082 | memset(conn, 0, sizeof(*conn) + dd_size); |
1969 | 2083 | ||
2084 | conn->dd_data = cls_conn->dd_data + sizeof(*conn); | ||
1970 | conn->session = session; | 2085 | conn->session = session; |
1971 | conn->cls_conn = cls_conn; | 2086 | conn->cls_conn = cls_conn; |
1972 | conn->c_stage = ISCSI_CONN_INITIAL_STAGE; | 2087 | conn->c_stage = ISCSI_CONN_INITIAL_STAGE; |
@@ -1985,30 +2100,30 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | |||
1985 | INIT_LIST_HEAD(&conn->requeue); | 2100 | INIT_LIST_HEAD(&conn->requeue); |
1986 | INIT_WORK(&conn->xmitwork, iscsi_xmitworker); | 2101 | INIT_WORK(&conn->xmitwork, iscsi_xmitworker); |
1987 | 2102 | ||
1988 | /* allocate login_mtask used for the login/text sequences */ | 2103 | /* allocate login_task used for the login/text sequences */ |
1989 | spin_lock_bh(&session->lock); | 2104 | spin_lock_bh(&session->lock); |
1990 | if (!__kfifo_get(session->mgmtpool.queue, | 2105 | if (!__kfifo_get(session->cmdpool.queue, |
1991 | (void*)&conn->login_mtask, | 2106 | (void*)&conn->login_task, |
1992 | sizeof(void*))) { | 2107 | sizeof(void*))) { |
1993 | spin_unlock_bh(&session->lock); | 2108 | spin_unlock_bh(&session->lock); |
1994 | goto login_mtask_alloc_fail; | 2109 | goto login_task_alloc_fail; |
1995 | } | 2110 | } |
1996 | spin_unlock_bh(&session->lock); | 2111 | spin_unlock_bh(&session->lock); |
1997 | 2112 | ||
1998 | data = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN, GFP_KERNEL); | 2113 | data = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN, GFP_KERNEL); |
1999 | if (!data) | 2114 | if (!data) |
2000 | goto login_mtask_data_alloc_fail; | 2115 | goto login_task_data_alloc_fail; |
2001 | conn->login_mtask->data = conn->data = data; | 2116 | conn->login_task->data = conn->data = data; |
2002 | 2117 | ||
2003 | init_timer(&conn->tmf_timer); | 2118 | init_timer(&conn->tmf_timer); |
2004 | init_waitqueue_head(&conn->ehwait); | 2119 | init_waitqueue_head(&conn->ehwait); |
2005 | 2120 | ||
2006 | return cls_conn; | 2121 | return cls_conn; |
2007 | 2122 | ||
2008 | login_mtask_data_alloc_fail: | 2123 | login_task_data_alloc_fail: |
2009 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, | 2124 | __kfifo_put(session->cmdpool.queue, (void*)&conn->login_task, |
2010 | sizeof(void*)); | 2125 | sizeof(void*)); |
2011 | login_mtask_alloc_fail: | 2126 | login_task_alloc_fail: |
2012 | iscsi_destroy_conn(cls_conn); | 2127 | iscsi_destroy_conn(cls_conn); |
2013 | return NULL; | 2128 | return NULL; |
2014 | } | 2129 | } |
@@ -2068,7 +2183,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
2068 | spin_lock_bh(&session->lock); | 2183 | spin_lock_bh(&session->lock); |
2069 | kfree(conn->data); | 2184 | kfree(conn->data); |
2070 | kfree(conn->persistent_address); | 2185 | kfree(conn->persistent_address); |
2071 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, | 2186 | __kfifo_put(session->cmdpool.queue, (void*)&conn->login_task, |
2072 | sizeof(void*)); | 2187 | sizeof(void*)); |
2073 | if (session->leadconn == conn) | 2188 | if (session->leadconn == conn) |
2074 | session->leadconn = NULL; | 2189 | session->leadconn = NULL; |
@@ -2140,7 +2255,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) | |||
2140 | } | 2255 | } |
2141 | spin_unlock_bh(&session->lock); | 2256 | spin_unlock_bh(&session->lock); |
2142 | 2257 | ||
2143 | iscsi_unblock_session(session_to_cls(session)); | 2258 | iscsi_unblock_session(session->cls_session); |
2144 | wake_up(&conn->ehwait); | 2259 | wake_up(&conn->ehwait); |
2145 | return 0; | 2260 | return 0; |
2146 | } | 2261 | } |
@@ -2149,21 +2264,23 @@ EXPORT_SYMBOL_GPL(iscsi_conn_start); | |||
2149 | static void | 2264 | static void |
2150 | flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) | 2265 | flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) |
2151 | { | 2266 | { |
2152 | struct iscsi_mgmt_task *mtask, *tmp; | 2267 | struct iscsi_task *task, *tmp; |
2153 | 2268 | ||
2154 | /* handle pending */ | 2269 | /* handle pending */ |
2155 | list_for_each_entry_safe(mtask, tmp, &conn->mgmtqueue, running) { | 2270 | list_for_each_entry_safe(task, tmp, &conn->mgmtqueue, running) { |
2156 | debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt); | 2271 | debug_scsi("flushing pending mgmt task itt 0x%x\n", task->itt); |
2157 | iscsi_free_mgmt_task(conn, mtask); | 2272 | /* release ref from prep task */ |
2273 | __iscsi_put_task(task); | ||
2158 | } | 2274 | } |
2159 | 2275 | ||
2160 | /* handle running */ | 2276 | /* handle running */ |
2161 | list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) { | 2277 | list_for_each_entry_safe(task, tmp, &conn->mgmt_run_list, running) { |
2162 | debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt); | 2278 | debug_scsi("flushing running mgmt task itt 0x%x\n", task->itt); |
2163 | iscsi_free_mgmt_task(conn, mtask); | 2279 | /* release ref from prep task */ |
2280 | __iscsi_put_task(task); | ||
2164 | } | 2281 | } |
2165 | 2282 | ||
2166 | conn->mtask = NULL; | 2283 | conn->task = NULL; |
2167 | } | 2284 | } |
2168 | 2285 | ||
2169 | static void iscsi_start_session_recovery(struct iscsi_session *session, | 2286 | static void iscsi_start_session_recovery(struct iscsi_session *session, |
@@ -2182,17 +2299,6 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
2182 | } | 2299 | } |
2183 | 2300 | ||
2184 | /* | 2301 | /* |
2185 | * The LLD either freed/unset the lock on us, or userspace called | ||
2186 | * stop but did not create a proper connection (connection was never | ||
2187 | * bound or it was unbound then stop was called). | ||
2188 | */ | ||
2189 | if (!conn->recv_lock) { | ||
2190 | spin_unlock_bh(&session->lock); | ||
2191 | mutex_unlock(&session->eh_mutex); | ||
2192 | return; | ||
2193 | } | ||
2194 | |||
2195 | /* | ||
2196 | * When this is called for the in_login state, we only want to clean | 2302 | * When this is called for the in_login state, we only want to clean |
2197 | * up the login task and connection. We do not need to block and set | 2303 | * up the login task and connection. We do not need to block and set |
2198 | * the recovery state again | 2304 | * the recovery state again |
@@ -2208,11 +2314,6 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
2208 | spin_unlock_bh(&session->lock); | 2314 | spin_unlock_bh(&session->lock); |
2209 | 2315 | ||
2210 | iscsi_suspend_tx(conn); | 2316 | iscsi_suspend_tx(conn); |
2211 | |||
2212 | write_lock_bh(conn->recv_lock); | ||
2213 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); | ||
2214 | write_unlock_bh(conn->recv_lock); | ||
2215 | |||
2216 | /* | 2317 | /* |
2217 | * for connection level recovery we should not calculate | 2318 | * for connection level recovery we should not calculate |
2218 | * header digest. conn->hdr_size used for optimization | 2319 | * header digest. conn->hdr_size used for optimization |
@@ -2225,7 +2326,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
2225 | if (session->state == ISCSI_STATE_IN_RECOVERY && | 2326 | if (session->state == ISCSI_STATE_IN_RECOVERY && |
2226 | old_stop_stage != STOP_CONN_RECOVER) { | 2327 | old_stop_stage != STOP_CONN_RECOVER) { |
2227 | debug_scsi("blocking session\n"); | 2328 | debug_scsi("blocking session\n"); |
2228 | iscsi_block_session(session_to_cls(session)); | 2329 | iscsi_block_session(session->cls_session); |
2229 | } | 2330 | } |
2230 | } | 2331 | } |
2231 | 2332 | ||
@@ -2260,7 +2361,7 @@ EXPORT_SYMBOL_GPL(iscsi_conn_stop); | |||
2260 | int iscsi_conn_bind(struct iscsi_cls_session *cls_session, | 2361 | int iscsi_conn_bind(struct iscsi_cls_session *cls_session, |
2261 | struct iscsi_cls_conn *cls_conn, int is_leading) | 2362 | struct iscsi_cls_conn *cls_conn, int is_leading) |
2262 | { | 2363 | { |
2263 | struct iscsi_session *session = class_to_transport_session(cls_session); | 2364 | struct iscsi_session *session = cls_session->dd_data; |
2264 | struct iscsi_conn *conn = cls_conn->dd_data; | 2365 | struct iscsi_conn *conn = cls_conn->dd_data; |
2265 | 2366 | ||
2266 | spin_lock_bh(&session->lock); | 2367 | spin_lock_bh(&session->lock); |
@@ -2399,6 +2500,14 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn, | |||
2399 | if (!conn->persistent_address) | 2500 | if (!conn->persistent_address) |
2400 | return -ENOMEM; | 2501 | return -ENOMEM; |
2401 | break; | 2502 | break; |
2503 | case ISCSI_PARAM_IFACE_NAME: | ||
2504 | if (!session->ifacename) | ||
2505 | session->ifacename = kstrdup(buf, GFP_KERNEL); | ||
2506 | break; | ||
2507 | case ISCSI_PARAM_INITIATOR_NAME: | ||
2508 | if (!session->initiatorname) | ||
2509 | session->initiatorname = kstrdup(buf, GFP_KERNEL); | ||
2510 | break; | ||
2402 | default: | 2511 | default: |
2403 | return -ENOSYS; | 2512 | return -ENOSYS; |
2404 | } | 2513 | } |
@@ -2410,8 +2519,7 @@ EXPORT_SYMBOL_GPL(iscsi_set_param); | |||
2410 | int iscsi_session_get_param(struct iscsi_cls_session *cls_session, | 2519 | int iscsi_session_get_param(struct iscsi_cls_session *cls_session, |
2411 | enum iscsi_param param, char *buf) | 2520 | enum iscsi_param param, char *buf) |
2412 | { | 2521 | { |
2413 | struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); | 2522 | struct iscsi_session *session = cls_session->dd_data; |
2414 | struct iscsi_session *session = iscsi_hostdata(shost->hostdata); | ||
2415 | int len; | 2523 | int len; |
2416 | 2524 | ||
2417 | switch(param) { | 2525 | switch(param) { |
@@ -2466,6 +2574,15 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session, | |||
2466 | case ISCSI_PARAM_PASSWORD_IN: | 2574 | case ISCSI_PARAM_PASSWORD_IN: |
2467 | len = sprintf(buf, "%s\n", session->password_in); | 2575 | len = sprintf(buf, "%s\n", session->password_in); |
2468 | break; | 2576 | break; |
2577 | case ISCSI_PARAM_IFACE_NAME: | ||
2578 | len = sprintf(buf, "%s\n", session->ifacename); | ||
2579 | break; | ||
2580 | case ISCSI_PARAM_INITIATOR_NAME: | ||
2581 | if (!session->initiatorname) | ||
2582 | len = sprintf(buf, "%s\n", "unknown"); | ||
2583 | else | ||
2584 | len = sprintf(buf, "%s\n", session->initiatorname); | ||
2585 | break; | ||
2469 | default: | 2586 | default: |
2470 | return -ENOSYS; | 2587 | return -ENOSYS; |
2471 | } | 2588 | } |
@@ -2525,29 +2642,35 @@ EXPORT_SYMBOL_GPL(iscsi_conn_get_param); | |||
2525 | int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param, | 2642 | int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param, |
2526 | char *buf) | 2643 | char *buf) |
2527 | { | 2644 | { |
2528 | struct iscsi_session *session = iscsi_hostdata(shost->hostdata); | 2645 | struct iscsi_host *ihost = shost_priv(shost); |
2529 | int len; | 2646 | int len; |
2530 | 2647 | ||
2531 | switch (param) { | 2648 | switch (param) { |
2532 | case ISCSI_HOST_PARAM_NETDEV_NAME: | 2649 | case ISCSI_HOST_PARAM_NETDEV_NAME: |
2533 | if (!session->netdev) | 2650 | if (!ihost->netdev) |
2534 | len = sprintf(buf, "%s\n", "default"); | 2651 | len = sprintf(buf, "%s\n", "default"); |
2535 | else | 2652 | else |
2536 | len = sprintf(buf, "%s\n", session->netdev); | 2653 | len = sprintf(buf, "%s\n", ihost->netdev); |
2537 | break; | 2654 | break; |
2538 | case ISCSI_HOST_PARAM_HWADDRESS: | 2655 | case ISCSI_HOST_PARAM_HWADDRESS: |
2539 | if (!session->hwaddress) | 2656 | if (!ihost->hwaddress) |
2540 | len = sprintf(buf, "%s\n", "default"); | 2657 | len = sprintf(buf, "%s\n", "default"); |
2541 | else | 2658 | else |
2542 | len = sprintf(buf, "%s\n", session->hwaddress); | 2659 | len = sprintf(buf, "%s\n", ihost->hwaddress); |
2543 | break; | 2660 | break; |
2544 | case ISCSI_HOST_PARAM_INITIATOR_NAME: | 2661 | case ISCSI_HOST_PARAM_INITIATOR_NAME: |
2545 | if (!session->initiatorname) | 2662 | if (!ihost->initiatorname) |
2546 | len = sprintf(buf, "%s\n", "unknown"); | 2663 | len = sprintf(buf, "%s\n", "unknown"); |
2547 | else | 2664 | else |
2548 | len = sprintf(buf, "%s\n", session->initiatorname); | 2665 | len = sprintf(buf, "%s\n", ihost->initiatorname); |
2666 | break; | ||
2667 | case ISCSI_HOST_PARAM_IPADDRESS: | ||
2668 | if (!strlen(ihost->local_address)) | ||
2669 | len = sprintf(buf, "%s\n", "unknown"); | ||
2670 | else | ||
2671 | len = sprintf(buf, "%s\n", | ||
2672 | ihost->local_address); | ||
2549 | break; | 2673 | break; |
2550 | |||
2551 | default: | 2674 | default: |
2552 | return -ENOSYS; | 2675 | return -ENOSYS; |
2553 | } | 2676 | } |
@@ -2559,20 +2682,20 @@ EXPORT_SYMBOL_GPL(iscsi_host_get_param); | |||
2559 | int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param, | 2682 | int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param, |
2560 | char *buf, int buflen) | 2683 | char *buf, int buflen) |
2561 | { | 2684 | { |
2562 | struct iscsi_session *session = iscsi_hostdata(shost->hostdata); | 2685 | struct iscsi_host *ihost = shost_priv(shost); |
2563 | 2686 | ||
2564 | switch (param) { | 2687 | switch (param) { |
2565 | case ISCSI_HOST_PARAM_NETDEV_NAME: | 2688 | case ISCSI_HOST_PARAM_NETDEV_NAME: |
2566 | if (!session->netdev) | 2689 | if (!ihost->netdev) |
2567 | session->netdev = kstrdup(buf, GFP_KERNEL); | 2690 | ihost->netdev = kstrdup(buf, GFP_KERNEL); |
2568 | break; | 2691 | break; |
2569 | case ISCSI_HOST_PARAM_HWADDRESS: | 2692 | case ISCSI_HOST_PARAM_HWADDRESS: |
2570 | if (!session->hwaddress) | 2693 | if (!ihost->hwaddress) |
2571 | session->hwaddress = kstrdup(buf, GFP_KERNEL); | 2694 | ihost->hwaddress = kstrdup(buf, GFP_KERNEL); |
2572 | break; | 2695 | break; |
2573 | case ISCSI_HOST_PARAM_INITIATOR_NAME: | 2696 | case ISCSI_HOST_PARAM_INITIATOR_NAME: |
2574 | if (!session->initiatorname) | 2697 | if (!ihost->initiatorname) |
2575 | session->initiatorname = kstrdup(buf, GFP_KERNEL); | 2698 | ihost->initiatorname = kstrdup(buf, GFP_KERNEL); |
2576 | break; | 2699 | break; |
2577 | default: | 2700 | default: |
2578 | return -ENOSYS; | 2701 | return -ENOSYS; |