diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2007-12-13 13:43:20 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-01-11 19:28:19 -0500 |
commit | 843c0a8a76078cf961b244b839683d0667313740 (patch) | |
tree | 3feaf71c8e67f38e10e78e315bbc8623dcf38a3d | |
parent | 8ae732a91df051aba6820068a47b631a06599d84 (diff) |
[SCSI] libiscsi, iscsi_tcp: add device support
This patch adds logical unit reset support. This should work for ib_iser,
but I have not finished testing that driver so it is not hooked in yet.
This patch also temporarily reverts the iscsi_tcp r2t write out patch.
That code is completely rewritten in this patchset.
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r-- | drivers/infiniband/ulp/iser/iscsi_iser.c | 6 | ||||
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 151 | ||||
-rw-r--r-- | drivers/scsi/iscsi_tcp.h | 34 | ||||
-rw-r--r-- | drivers/scsi/libiscsi.c | 494 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 4 | ||||
-rw-r--r-- | include/scsi/iscsi_if.h | 2 | ||||
-rw-r--r-- | include/scsi/iscsi_proto.h | 2 | ||||
-rw-r--r-- | include/scsi/libiscsi.h | 25 |
8 files changed, 396 insertions, 322 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index bad8dacafd10..2eadb6d0ad8b 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c | |||
@@ -220,12 +220,6 @@ iscsi_iser_ctask_xmit(struct iscsi_conn *conn, | |||
220 | debug_scsi("ctask deq [cid %d itt 0x%x]\n", | 220 | debug_scsi("ctask deq [cid %d itt 0x%x]\n", |
221 | conn->id, ctask->itt); | 221 | conn->id, ctask->itt); |
222 | 222 | ||
223 | /* | ||
224 | * serialize with TMF AbortTask | ||
225 | */ | ||
226 | if (ctask->mtask) | ||
227 | return error; | ||
228 | |||
229 | /* Send the cmd PDU */ | 223 | /* Send the cmd PDU */ |
230 | if (!iser_ctask->command_sent) { | 224 | if (!iser_ctask->command_sent) { |
231 | error = iser_send_command(conn, ctask); | 225 | error = iser_send_command(conn, ctask); |
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 57ce2251abc8..4b226b88b68a 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -197,7 +197,7 @@ iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
197 | if (unlikely(!sc)) | 197 | if (unlikely(!sc)) |
198 | return; | 198 | return; |
199 | 199 | ||
200 | tcp_ctask->xmstate = XMSTATE_VALUE_IDLE; | 200 | tcp_ctask->xmstate = XMSTATE_IDLE; |
201 | tcp_ctask->r2t = NULL; | 201 | tcp_ctask->r2t = NULL; |
202 | } | 202 | } |
203 | 203 | ||
@@ -369,8 +369,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
369 | spin_lock(&session->lock); | 369 | spin_lock(&session->lock); |
370 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); | 370 | iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); |
371 | 371 | ||
372 | if (!ctask->sc || ctask->mtask || | 372 | if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) { |
373 | session->state != ISCSI_STATE_LOGGED_IN) { | ||
374 | printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in " | 373 | printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in " |
375 | "recovery...\n", ctask->itt); | 374 | "recovery...\n", ctask->itt); |
376 | spin_unlock(&session->lock); | 375 | spin_unlock(&session->lock); |
@@ -409,11 +408,10 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
409 | 408 | ||
410 | tcp_ctask->exp_datasn = r2tsn + 1; | 409 | tcp_ctask->exp_datasn = r2tsn + 1; |
411 | __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); | 410 | __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); |
412 | set_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate); | 411 | tcp_ctask->xmstate |= XMSTATE_SOL_HDR_INIT; |
413 | list_move_tail(&ctask->running, &conn->xmitqueue); | ||
414 | |||
415 | scsi_queue_work(session->host, &conn->xmitwork); | ||
416 | conn->r2t_pdus_cnt++; | 412 | conn->r2t_pdus_cnt++; |
413 | |||
414 | iscsi_requeue_ctask(ctask); | ||
417 | spin_unlock(&session->lock); | 415 | spin_unlock(&session->lock); |
418 | 416 | ||
419 | return 0; | 417 | return 0; |
@@ -1254,7 +1252,7 @@ static void iscsi_set_padding(struct iscsi_tcp_cmd_task *tcp_ctask, | |||
1254 | 1252 | ||
1255 | tcp_ctask->pad_count = ISCSI_PAD_LEN - tcp_ctask->pad_count; | 1253 | tcp_ctask->pad_count = ISCSI_PAD_LEN - tcp_ctask->pad_count; |
1256 | debug_scsi("write padding %d bytes\n", tcp_ctask->pad_count); | 1254 | debug_scsi("write padding %d bytes\n", tcp_ctask->pad_count); |
1257 | set_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate); | 1255 | tcp_ctask->xmstate |= XMSTATE_W_PAD; |
1258 | } | 1256 | } |
1259 | 1257 | ||
1260 | /** | 1258 | /** |
@@ -1269,7 +1267,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) | |||
1269 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1267 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
1270 | 1268 | ||
1271 | BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); | 1269 | BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); |
1272 | tcp_ctask->xmstate = 1 << XMSTATE_BIT_CMD_HDR_INIT; | 1270 | tcp_ctask->xmstate = XMSTATE_CMD_HDR_INIT; |
1273 | } | 1271 | } |
1274 | 1272 | ||
1275 | /** | 1273 | /** |
@@ -1283,10 +1281,10 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) | |||
1283 | * xmit. | 1281 | * xmit. |
1284 | * | 1282 | * |
1285 | * Management xmit state machine consists of these states: | 1283 | * Management xmit state machine consists of these states: |
1286 | * XMSTATE_BIT_IMM_HDR_INIT - calculate digest of PDU Header | 1284 | * XMSTATE_IMM_HDR_INIT - calculate digest of PDU Header |
1287 | * XMSTATE_BIT_IMM_HDR - PDU Header xmit in progress | 1285 | * XMSTATE_IMM_HDR - PDU Header xmit in progress |
1288 | * XMSTATE_BIT_IMM_DATA - PDU Data xmit in progress | 1286 | * XMSTATE_IMM_DATA - PDU Data xmit in progress |
1289 | * XMSTATE_VALUE_IDLE - management PDU is done | 1287 | * XMSTATE_IDLE - management PDU is done |
1290 | **/ | 1288 | **/ |
1291 | static int | 1289 | static int |
1292 | iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) | 1290 | iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) |
@@ -1297,12 +1295,12 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) | |||
1297 | debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n", | 1295 | debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n", |
1298 | conn->id, tcp_mtask->xmstate, mtask->itt); | 1296 | conn->id, tcp_mtask->xmstate, mtask->itt); |
1299 | 1297 | ||
1300 | if (test_bit(XMSTATE_BIT_IMM_HDR_INIT, &tcp_mtask->xmstate)) { | 1298 | if (tcp_mtask->xmstate & XMSTATE_IMM_HDR_INIT) { |
1301 | iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, | 1299 | iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, |
1302 | sizeof(struct iscsi_hdr)); | 1300 | sizeof(struct iscsi_hdr)); |
1303 | 1301 | ||
1304 | if (mtask->data_count) { | 1302 | if (mtask->data_count) { |
1305 | set_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate); | 1303 | tcp_mtask->xmstate |= XMSTATE_IMM_DATA; |
1306 | iscsi_buf_init_iov(&tcp_mtask->sendbuf, | 1304 | iscsi_buf_init_iov(&tcp_mtask->sendbuf, |
1307 | (char*)mtask->data, | 1305 | (char*)mtask->data, |
1308 | mtask->data_count); | 1306 | mtask->data_count); |
@@ -1315,20 +1313,21 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) | |||
1315 | (u8*)tcp_mtask->hdrext); | 1313 | (u8*)tcp_mtask->hdrext); |
1316 | 1314 | ||
1317 | tcp_mtask->sent = 0; | 1315 | tcp_mtask->sent = 0; |
1318 | clear_bit(XMSTATE_BIT_IMM_HDR_INIT, &tcp_mtask->xmstate); | 1316 | tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR_INIT; |
1319 | set_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate); | 1317 | tcp_mtask->xmstate |= XMSTATE_IMM_HDR; |
1320 | } | 1318 | } |
1321 | 1319 | ||
1322 | if (test_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate)) { | 1320 | if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) { |
1323 | rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf, | 1321 | rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf, |
1324 | mtask->data_count); | 1322 | mtask->data_count); |
1325 | if (rc) | 1323 | if (rc) |
1326 | return rc; | 1324 | return rc; |
1327 | clear_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate); | 1325 | tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR; |
1328 | } | 1326 | } |
1329 | 1327 | ||
1330 | if (test_and_clear_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate)) { | 1328 | if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) { |
1331 | BUG_ON(!mtask->data_count); | 1329 | BUG_ON(!mtask->data_count); |
1330 | tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA; | ||
1332 | /* FIXME: implement. | 1331 | /* FIXME: implement. |
1333 | * Virtual buffer could be spreaded across multiple pages... | 1332 | * Virtual buffer could be spreaded across multiple pages... |
1334 | */ | 1333 | */ |
@@ -1338,13 +1337,13 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) | |||
1338 | rc = iscsi_sendpage(conn, &tcp_mtask->sendbuf, | 1337 | rc = iscsi_sendpage(conn, &tcp_mtask->sendbuf, |
1339 | &mtask->data_count, &tcp_mtask->sent); | 1338 | &mtask->data_count, &tcp_mtask->sent); |
1340 | if (rc) { | 1339 | if (rc) { |
1341 | set_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate); | 1340 | tcp_mtask->xmstate |= XMSTATE_IMM_DATA; |
1342 | return rc; | 1341 | return rc; |
1343 | } | 1342 | } |
1344 | } while (mtask->data_count); | 1343 | } while (mtask->data_count); |
1345 | } | 1344 | } |
1346 | 1345 | ||
1347 | BUG_ON(tcp_mtask->xmstate != XMSTATE_VALUE_IDLE); | 1346 | BUG_ON(tcp_mtask->xmstate != XMSTATE_IDLE); |
1348 | if (mtask->hdr->itt == RESERVED_ITT) { | 1347 | if (mtask->hdr->itt == RESERVED_ITT) { |
1349 | struct iscsi_session *session = conn->session; | 1348 | struct iscsi_session *session = conn->session; |
1350 | 1349 | ||
@@ -1364,7 +1363,7 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1364 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1363 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
1365 | int rc = 0; | 1364 | int rc = 0; |
1366 | 1365 | ||
1367 | if (test_bit(XMSTATE_BIT_CMD_HDR_INIT, &tcp_ctask->xmstate)) { | 1366 | if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_INIT) { |
1368 | tcp_ctask->sent = 0; | 1367 | tcp_ctask->sent = 0; |
1369 | tcp_ctask->sg_count = 0; | 1368 | tcp_ctask->sg_count = 0; |
1370 | tcp_ctask->exp_datasn = 0; | 1369 | tcp_ctask->exp_datasn = 0; |
@@ -1389,21 +1388,21 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1389 | if (conn->hdrdgst_en) | 1388 | if (conn->hdrdgst_en) |
1390 | iscsi_hdr_digest(conn, &tcp_ctask->headbuf, | 1389 | iscsi_hdr_digest(conn, &tcp_ctask->headbuf, |
1391 | (u8*)tcp_ctask->hdrext); | 1390 | (u8*)tcp_ctask->hdrext); |
1392 | clear_bit(XMSTATE_BIT_CMD_HDR_INIT, &tcp_ctask->xmstate); | 1391 | tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT; |
1393 | set_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate); | 1392 | tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT; |
1394 | } | 1393 | } |
1395 | 1394 | ||
1396 | if (test_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate)) { | 1395 | if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_XMIT) { |
1397 | rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); | 1396 | rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); |
1398 | if (rc) | 1397 | if (rc) |
1399 | return rc; | 1398 | return rc; |
1400 | clear_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate); | 1399 | tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_XMIT; |
1401 | 1400 | ||
1402 | if (sc->sc_data_direction != DMA_TO_DEVICE) | 1401 | if (sc->sc_data_direction != DMA_TO_DEVICE) |
1403 | return 0; | 1402 | return 0; |
1404 | 1403 | ||
1405 | if (ctask->imm_count) { | 1404 | if (ctask->imm_count) { |
1406 | set_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate); | 1405 | tcp_ctask->xmstate |= XMSTATE_IMM_DATA; |
1407 | iscsi_set_padding(tcp_ctask, ctask->imm_count); | 1406 | iscsi_set_padding(tcp_ctask, ctask->imm_count); |
1408 | 1407 | ||
1409 | if (ctask->conn->datadgst_en) { | 1408 | if (ctask->conn->datadgst_en) { |
@@ -1413,10 +1412,9 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1413 | } | 1412 | } |
1414 | } | 1413 | } |
1415 | 1414 | ||
1416 | if (ctask->unsol_count) { | 1415 | if (ctask->unsol_count) |
1417 | set_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate); | 1416 | tcp_ctask->xmstate |= |
1418 | set_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate); | 1417 | XMSTATE_UNS_HDR | XMSTATE_UNS_INIT; |
1419 | } | ||
1420 | } | 1418 | } |
1421 | return rc; | 1419 | return rc; |
1422 | } | 1420 | } |
@@ -1428,25 +1426,25 @@ iscsi_send_padding(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1428 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 1426 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
1429 | int sent = 0, rc; | 1427 | int sent = 0, rc; |
1430 | 1428 | ||
1431 | if (test_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate)) { | 1429 | if (tcp_ctask->xmstate & XMSTATE_W_PAD) { |
1432 | iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, | 1430 | iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, |
1433 | tcp_ctask->pad_count); | 1431 | tcp_ctask->pad_count); |
1434 | if (conn->datadgst_en) | 1432 | if (conn->datadgst_en) |
1435 | crypto_hash_update(&tcp_conn->tx_hash, | 1433 | crypto_hash_update(&tcp_conn->tx_hash, |
1436 | &tcp_ctask->sendbuf.sg, | 1434 | &tcp_ctask->sendbuf.sg, |
1437 | tcp_ctask->sendbuf.sg.length); | 1435 | tcp_ctask->sendbuf.sg.length); |
1438 | } else if (!test_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate)) | 1436 | } else if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_PAD)) |
1439 | return 0; | 1437 | return 0; |
1440 | 1438 | ||
1441 | clear_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate); | 1439 | tcp_ctask->xmstate &= ~XMSTATE_W_PAD; |
1442 | clear_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate); | 1440 | tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_PAD; |
1443 | debug_scsi("sending %d pad bytes for itt 0x%x\n", | 1441 | debug_scsi("sending %d pad bytes for itt 0x%x\n", |
1444 | tcp_ctask->pad_count, ctask->itt); | 1442 | tcp_ctask->pad_count, ctask->itt); |
1445 | rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, | 1443 | rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, |
1446 | &sent); | 1444 | &sent); |
1447 | if (rc) { | 1445 | if (rc) { |
1448 | debug_scsi("padding send failed %d\n", rc); | 1446 | debug_scsi("padding send failed %d\n", rc); |
1449 | set_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate); | 1447 | tcp_ctask->xmstate |= XMSTATE_W_RESEND_PAD; |
1450 | } | 1448 | } |
1451 | return rc; | 1449 | return rc; |
1452 | } | 1450 | } |
@@ -1465,11 +1463,11 @@ iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
1465 | tcp_ctask = ctask->dd_data; | 1463 | tcp_ctask = ctask->dd_data; |
1466 | tcp_conn = conn->dd_data; | 1464 | tcp_conn = conn->dd_data; |
1467 | 1465 | ||
1468 | if (!test_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate)) { | 1466 | if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_DATA_DIGEST)) { |
1469 | crypto_hash_final(&tcp_conn->tx_hash, (u8*)digest); | 1467 | crypto_hash_final(&tcp_conn->tx_hash, (u8*)digest); |
1470 | iscsi_buf_init_iov(buf, (char*)digest, 4); | 1468 | iscsi_buf_init_iov(buf, (char*)digest, 4); |
1471 | } | 1469 | } |
1472 | clear_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate); | 1470 | tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_DATA_DIGEST; |
1473 | 1471 | ||
1474 | rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent); | 1472 | rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent); |
1475 | if (!rc) | 1473 | if (!rc) |
@@ -1478,7 +1476,7 @@ iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
1478 | else { | 1476 | else { |
1479 | debug_scsi("sending digest 0x%x failed for itt 0x%x!\n", | 1477 | debug_scsi("sending digest 0x%x failed for itt 0x%x!\n", |
1480 | *digest, ctask->itt); | 1478 | *digest, ctask->itt); |
1481 | set_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate); | 1479 | tcp_ctask->xmstate |= XMSTATE_W_RESEND_DATA_DIGEST; |
1482 | } | 1480 | } |
1483 | return rc; | 1481 | return rc; |
1484 | } | 1482 | } |
@@ -1526,8 +1524,8 @@ iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1526 | struct iscsi_data_task *dtask; | 1524 | struct iscsi_data_task *dtask; |
1527 | int rc; | 1525 | int rc; |
1528 | 1526 | ||
1529 | set_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate); | 1527 | tcp_ctask->xmstate |= XMSTATE_UNS_DATA; |
1530 | if (test_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate)) { | 1528 | if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) { |
1531 | dtask = &tcp_ctask->unsol_dtask; | 1529 | dtask = &tcp_ctask->unsol_dtask; |
1532 | 1530 | ||
1533 | iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr); | 1531 | iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr); |
@@ -1537,14 +1535,14 @@ iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1537 | iscsi_hdr_digest(conn, &tcp_ctask->headbuf, | 1535 | iscsi_hdr_digest(conn, &tcp_ctask->headbuf, |
1538 | (u8*)dtask->hdrext); | 1536 | (u8*)dtask->hdrext); |
1539 | 1537 | ||
1540 | clear_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate); | 1538 | tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT; |
1541 | iscsi_set_padding(tcp_ctask, ctask->data_count); | 1539 | iscsi_set_padding(tcp_ctask, ctask->data_count); |
1542 | } | 1540 | } |
1543 | 1541 | ||
1544 | rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count); | 1542 | rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count); |
1545 | if (rc) { | 1543 | if (rc) { |
1546 | clear_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate); | 1544 | tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; |
1547 | set_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate); | 1545 | tcp_ctask->xmstate |= XMSTATE_UNS_HDR; |
1548 | return rc; | 1546 | return rc; |
1549 | } | 1547 | } |
1550 | 1548 | ||
@@ -1565,15 +1563,16 @@ iscsi_send_unsol_pdu(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1565 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1563 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
1566 | int rc; | 1564 | int rc; |
1567 | 1565 | ||
1568 | if (test_and_clear_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate)) { | 1566 | if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) { |
1569 | BUG_ON(!ctask->unsol_count); | 1567 | BUG_ON(!ctask->unsol_count); |
1568 | tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR; | ||
1570 | send_hdr: | 1569 | send_hdr: |
1571 | rc = iscsi_send_unsol_hdr(conn, ctask); | 1570 | rc = iscsi_send_unsol_hdr(conn, ctask); |
1572 | if (rc) | 1571 | if (rc) |
1573 | return rc; | 1572 | return rc; |
1574 | } | 1573 | } |
1575 | 1574 | ||
1576 | if (test_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate)) { | 1575 | if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) { |
1577 | struct iscsi_data_task *dtask = &tcp_ctask->unsol_dtask; | 1576 | struct iscsi_data_task *dtask = &tcp_ctask->unsol_dtask; |
1578 | int start = tcp_ctask->sent; | 1577 | int start = tcp_ctask->sent; |
1579 | 1578 | ||
@@ -1583,14 +1582,14 @@ send_hdr: | |||
1583 | ctask->unsol_count -= tcp_ctask->sent - start; | 1582 | ctask->unsol_count -= tcp_ctask->sent - start; |
1584 | if (rc) | 1583 | if (rc) |
1585 | return rc; | 1584 | return rc; |
1586 | clear_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate); | 1585 | tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; |
1587 | /* | 1586 | /* |
1588 | * Done with the Data-Out. Next, check if we need | 1587 | * Done with the Data-Out. Next, check if we need |
1589 | * to send another unsolicited Data-Out. | 1588 | * to send another unsolicited Data-Out. |
1590 | */ | 1589 | */ |
1591 | if (ctask->unsol_count) { | 1590 | if (ctask->unsol_count) { |
1592 | debug_scsi("sending more uns\n"); | 1591 | debug_scsi("sending more uns\n"); |
1593 | set_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate); | 1592 | tcp_ctask->xmstate |= XMSTATE_UNS_INIT; |
1594 | goto send_hdr; | 1593 | goto send_hdr; |
1595 | } | 1594 | } |
1596 | } | 1595 | } |
@@ -1606,7 +1605,7 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn, | |||
1606 | struct iscsi_data_task *dtask; | 1605 | struct iscsi_data_task *dtask; |
1607 | int left, rc; | 1606 | int left, rc; |
1608 | 1607 | ||
1609 | if (test_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate)) { | 1608 | if (tcp_ctask->xmstate & XMSTATE_SOL_HDR_INIT) { |
1610 | if (!tcp_ctask->r2t) { | 1609 | if (!tcp_ctask->r2t) { |
1611 | spin_lock_bh(&session->lock); | 1610 | spin_lock_bh(&session->lock); |
1612 | __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, | 1611 | __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, |
@@ -1620,19 +1619,19 @@ send_hdr: | |||
1620 | if (conn->hdrdgst_en) | 1619 | if (conn->hdrdgst_en) |
1621 | iscsi_hdr_digest(conn, &r2t->headbuf, | 1620 | iscsi_hdr_digest(conn, &r2t->headbuf, |
1622 | (u8*)dtask->hdrext); | 1621 | (u8*)dtask->hdrext); |
1623 | clear_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate); | 1622 | tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR_INIT; |
1624 | set_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate); | 1623 | tcp_ctask->xmstate |= XMSTATE_SOL_HDR; |
1625 | } | 1624 | } |
1626 | 1625 | ||
1627 | if (test_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate)) { | 1626 | if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) { |
1628 | r2t = tcp_ctask->r2t; | 1627 | r2t = tcp_ctask->r2t; |
1629 | dtask = &r2t->dtask; | 1628 | dtask = &r2t->dtask; |
1630 | 1629 | ||
1631 | rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count); | 1630 | rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count); |
1632 | if (rc) | 1631 | if (rc) |
1633 | return rc; | 1632 | return rc; |
1634 | clear_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate); | 1633 | tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; |
1635 | set_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate); | 1634 | tcp_ctask->xmstate |= XMSTATE_SOL_DATA; |
1636 | 1635 | ||
1637 | if (conn->datadgst_en) { | 1636 | if (conn->datadgst_en) { |
1638 | iscsi_data_digest_init(conn->dd_data, tcp_ctask); | 1637 | iscsi_data_digest_init(conn->dd_data, tcp_ctask); |
@@ -1645,7 +1644,7 @@ send_hdr: | |||
1645 | r2t->sent); | 1644 | r2t->sent); |
1646 | } | 1645 | } |
1647 | 1646 | ||
1648 | if (test_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate)) { | 1647 | if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) { |
1649 | r2t = tcp_ctask->r2t; | 1648 | r2t = tcp_ctask->r2t; |
1650 | dtask = &r2t->dtask; | 1649 | dtask = &r2t->dtask; |
1651 | 1650 | ||
@@ -1654,7 +1653,7 @@ send_hdr: | |||
1654 | &dtask->digestbuf, &dtask->digest); | 1653 | &dtask->digestbuf, &dtask->digest); |
1655 | if (rc) | 1654 | if (rc) |
1656 | return rc; | 1655 | return rc; |
1657 | clear_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate); | 1656 | tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; |
1658 | 1657 | ||
1659 | /* | 1658 | /* |
1660 | * Done with this Data-Out. Next, check if we have | 1659 | * Done with this Data-Out. Next, check if we have |
@@ -1699,32 +1698,32 @@ send_hdr: | |||
1699 | * xmit stages. | 1698 | * xmit stages. |
1700 | * | 1699 | * |
1701 | *iscsi_send_cmd_hdr() | 1700 | *iscsi_send_cmd_hdr() |
1702 | * XMSTATE_BIT_CMD_HDR_INIT - prepare Header and Data buffers Calculate | 1701 | * XMSTATE_CMD_HDR_INIT - prepare Header and Data buffers Calculate |
1703 | * Header Digest | 1702 | * Header Digest |
1704 | * XMSTATE_BIT_CMD_HDR_XMIT - Transmit header in progress | 1703 | * XMSTATE_CMD_HDR_XMIT - Transmit header in progress |
1705 | * | 1704 | * |
1706 | *iscsi_send_padding | 1705 | *iscsi_send_padding |
1707 | * XMSTATE_BIT_W_PAD - Prepare and send pading | 1706 | * XMSTATE_W_PAD - Prepare and send pading |
1708 | * XMSTATE_BIT_W_RESEND_PAD - retry send pading | 1707 | * XMSTATE_W_RESEND_PAD - retry send pading |
1709 | * | 1708 | * |
1710 | *iscsi_send_digest | 1709 | *iscsi_send_digest |
1711 | * XMSTATE_BIT_W_RESEND_DATA_DIGEST - Finalize and send Data Digest | 1710 | * XMSTATE_W_RESEND_DATA_DIGEST - Finalize and send Data Digest |
1712 | * XMSTATE_BIT_W_RESEND_DATA_DIGEST - retry sending digest | 1711 | * XMSTATE_W_RESEND_DATA_DIGEST - retry sending digest |
1713 | * | 1712 | * |
1714 | *iscsi_send_unsol_hdr | 1713 | *iscsi_send_unsol_hdr |
1715 | * XMSTATE_BIT_UNS_INIT - prepare un-solicit data header and digest | 1714 | * XMSTATE_UNS_INIT - prepare un-solicit data header and digest |
1716 | * XMSTATE_BIT_UNS_HDR - send un-solicit header | 1715 | * XMSTATE_UNS_HDR - send un-solicit header |
1717 | * | 1716 | * |
1718 | *iscsi_send_unsol_pdu | 1717 | *iscsi_send_unsol_pdu |
1719 | * XMSTATE_BIT_UNS_DATA - send un-solicit data in progress | 1718 | * XMSTATE_UNS_DATA - send un-solicit data in progress |
1720 | * | 1719 | * |
1721 | *iscsi_send_sol_pdu | 1720 | *iscsi_send_sol_pdu |
1722 | * XMSTATE_BIT_SOL_HDR_INIT - solicit data header and digest initialize | 1721 | * XMSTATE_SOL_HDR_INIT - solicit data header and digest initialize |
1723 | * XMSTATE_BIT_SOL_HDR - send solicit header | 1722 | * XMSTATE_SOL_HDR - send solicit header |
1724 | * XMSTATE_BIT_SOL_DATA - send solicit data | 1723 | * XMSTATE_SOL_DATA - send solicit data |
1725 | * | 1724 | * |
1726 | *iscsi_tcp_ctask_xmit | 1725 | *iscsi_tcp_ctask_xmit |
1727 | * XMSTATE_BIT_IMM_DATA - xmit managment data (??) | 1726 | * XMSTATE_IMM_DATA - xmit managment data (??) |
1728 | **/ | 1727 | **/ |
1729 | static int | 1728 | static int |
1730 | iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1729 | iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) |
@@ -1741,13 +1740,13 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1741 | if (ctask->sc->sc_data_direction != DMA_TO_DEVICE) | 1740 | if (ctask->sc->sc_data_direction != DMA_TO_DEVICE) |
1742 | return 0; | 1741 | return 0; |
1743 | 1742 | ||
1744 | if (test_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate)) { | 1743 | if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) { |
1745 | rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg, | 1744 | rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg, |
1746 | &tcp_ctask->sent, &ctask->imm_count, | 1745 | &tcp_ctask->sent, &ctask->imm_count, |
1747 | &tcp_ctask->immbuf, &tcp_ctask->immdigest); | 1746 | &tcp_ctask->immbuf, &tcp_ctask->immdigest); |
1748 | if (rc) | 1747 | if (rc) |
1749 | return rc; | 1748 | return rc; |
1750 | clear_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate); | 1749 | tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA; |
1751 | } | 1750 | } |
1752 | 1751 | ||
1753 | rc = iscsi_send_unsol_pdu(conn, ctask); | 1752 | rc = iscsi_send_unsol_pdu(conn, ctask); |
@@ -1980,7 +1979,7 @@ static void | |||
1980 | iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) | 1979 | iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) |
1981 | { | 1980 | { |
1982 | struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; | 1981 | struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; |
1983 | tcp_mtask->xmstate = 1 << XMSTATE_BIT_IMM_HDR_INIT; | 1982 | tcp_mtask->xmstate = XMSTATE_IMM_HDR_INIT; |
1984 | } | 1983 | } |
1985 | 1984 | ||
1986 | static int | 1985 | static int |
@@ -2226,6 +2225,7 @@ static struct scsi_host_template iscsi_sht = { | |||
2226 | .max_sectors = 0xFFFF, | 2225 | .max_sectors = 0xFFFF, |
2227 | .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, | 2226 | .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, |
2228 | .eh_abort_handler = iscsi_eh_abort, | 2227 | .eh_abort_handler = iscsi_eh_abort, |
2228 | .eh_device_reset_handler= iscsi_eh_device_reset, | ||
2229 | .eh_host_reset_handler = iscsi_eh_host_reset, | 2229 | .eh_host_reset_handler = iscsi_eh_host_reset, |
2230 | .use_clustering = DISABLE_CLUSTERING, | 2230 | .use_clustering = DISABLE_CLUSTERING, |
2231 | .slave_configure = iscsi_tcp_slave_configure, | 2231 | .slave_configure = iscsi_tcp_slave_configure, |
@@ -2257,7 +2257,8 @@ static struct iscsi_transport iscsi_tcp_transport = { | |||
2257 | ISCSI_PERSISTENT_ADDRESS | | 2257 | ISCSI_PERSISTENT_ADDRESS | |
2258 | ISCSI_TARGET_NAME | ISCSI_TPGT | | 2258 | ISCSI_TARGET_NAME | ISCSI_TPGT | |
2259 | ISCSI_USERNAME | ISCSI_PASSWORD | | 2259 | ISCSI_USERNAME | ISCSI_PASSWORD | |
2260 | ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN, | 2260 | ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN | |
2261 | ISCSI_FAST_ABORT, | ||
2261 | .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | | 2262 | .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | |
2262 | ISCSI_HOST_INITIATOR_NAME | | 2263 | ISCSI_HOST_INITIATOR_NAME | |
2263 | ISCSI_HOST_NETDEV_NAME, | 2264 | ISCSI_HOST_NETDEV_NAME, |
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index 68c36cc8997e..7eba44df0a7f 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h | |||
@@ -32,21 +32,21 @@ | |||
32 | #define IN_PROGRESS_PAD_RECV 0x4 | 32 | #define IN_PROGRESS_PAD_RECV 0x4 |
33 | 33 | ||
34 | /* xmit state machine */ | 34 | /* xmit state machine */ |
35 | #define XMSTATE_VALUE_IDLE 0 | 35 | #define XMSTATE_IDLE 0x0 |
36 | #define XMSTATE_BIT_CMD_HDR_INIT 0 | 36 | #define XMSTATE_CMD_HDR_INIT 0x1 |
37 | #define XMSTATE_BIT_CMD_HDR_XMIT 1 | 37 | #define XMSTATE_CMD_HDR_XMIT 0x2 |
38 | #define XMSTATE_BIT_IMM_HDR 2 | 38 | #define XMSTATE_IMM_HDR 0x4 |
39 | #define XMSTATE_BIT_IMM_DATA 3 | 39 | #define XMSTATE_IMM_DATA 0x8 |
40 | #define XMSTATE_BIT_UNS_INIT 4 | 40 | #define XMSTATE_UNS_INIT 0x10 |
41 | #define XMSTATE_BIT_UNS_HDR 5 | 41 | #define XMSTATE_UNS_HDR 0x20 |
42 | #define XMSTATE_BIT_UNS_DATA 6 | 42 | #define XMSTATE_UNS_DATA 0x40 |
43 | #define XMSTATE_BIT_SOL_HDR 7 | 43 | #define XMSTATE_SOL_HDR 0x80 |
44 | #define XMSTATE_BIT_SOL_DATA 8 | 44 | #define XMSTATE_SOL_DATA 0x100 |
45 | #define XMSTATE_BIT_W_PAD 9 | 45 | #define XMSTATE_W_PAD 0x200 |
46 | #define XMSTATE_BIT_W_RESEND_PAD 10 | 46 | #define XMSTATE_W_RESEND_PAD 0x400 |
47 | #define XMSTATE_BIT_W_RESEND_DATA_DIGEST 11 | 47 | #define XMSTATE_W_RESEND_DATA_DIGEST 0x800 |
48 | #define XMSTATE_BIT_IMM_HDR_INIT 12 | 48 | #define XMSTATE_IMM_HDR_INIT 0x1000 |
49 | #define XMSTATE_BIT_SOL_HDR_INIT 13 | 49 | #define XMSTATE_SOL_HDR_INIT 0x2000 |
50 | 50 | ||
51 | #define ISCSI_PAD_LEN 4 | 51 | #define ISCSI_PAD_LEN 4 |
52 | #define ISCSI_SG_TABLESIZE SG_ALL | 52 | #define ISCSI_SG_TABLESIZE SG_ALL |
@@ -122,7 +122,7 @@ struct iscsi_data_task { | |||
122 | struct iscsi_tcp_mgmt_task { | 122 | struct iscsi_tcp_mgmt_task { |
123 | struct iscsi_hdr hdr; | 123 | struct iscsi_hdr hdr; |
124 | char hdrext[sizeof(__u32)]; /* Header-Digest */ | 124 | char hdrext[sizeof(__u32)]; /* Header-Digest */ |
125 | unsigned long xmstate; /* mgmt xmit progress */ | 125 | int xmstate; /* mgmt xmit progress */ |
126 | struct iscsi_buf headbuf; /* header buffer */ | 126 | struct iscsi_buf headbuf; /* header buffer */ |
127 | struct iscsi_buf sendbuf; /* in progress buffer */ | 127 | struct iscsi_buf sendbuf; /* in progress buffer */ |
128 | int sent; | 128 | int sent; |
@@ -150,7 +150,7 @@ struct iscsi_tcp_cmd_task { | |||
150 | int pad_count; /* padded bytes */ | 150 | int pad_count; /* padded bytes */ |
151 | struct iscsi_buf headbuf; /* header buf (xmit) */ | 151 | struct iscsi_buf headbuf; /* header buf (xmit) */ |
152 | struct iscsi_buf sendbuf; /* in progress buffer*/ | 152 | struct iscsi_buf sendbuf; /* in progress buffer*/ |
153 | unsigned long xmstate; /* xmit xtate machine */ | 153 | int xmstate; /* xmit xtate machine */ |
154 | int sent; | 154 | int sent; |
155 | struct scatterlist *sg; /* per-cmd SG list */ | 155 | struct scatterlist *sg; /* per-cmd SG list */ |
156 | struct scatterlist *bad_sg; /* assert statement */ | 156 | struct scatterlist *bad_sg; /* assert statement */ |
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 8b57af5baaec..176458f35316 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -86,7 +86,7 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) | |||
86 | * xmit thread | 86 | * xmit thread |
87 | */ | 87 | */ |
88 | if (!list_empty(&session->leadconn->xmitqueue) || | 88 | if (!list_empty(&session->leadconn->xmitqueue) || |
89 | __kfifo_len(session->leadconn->mgmtqueue)) | 89 | !list_empty(&session->leadconn->mgmtqueue)) |
90 | scsi_queue_work(session->host, | 90 | scsi_queue_work(session->host, |
91 | &session->leadconn->xmitwork); | 91 | &session->leadconn->xmitwork); |
92 | } | 92 | } |
@@ -318,15 +318,15 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | |||
318 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | 318 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; |
319 | conn->tmfrsp_pdus_cnt++; | 319 | conn->tmfrsp_pdus_cnt++; |
320 | 320 | ||
321 | if (conn->tmabort_state != TMABORT_INITIAL) | 321 | if (conn->tmf_state != TMF_QUEUED) |
322 | return; | 322 | return; |
323 | 323 | ||
324 | if (tmf->response == ISCSI_TMF_RSP_COMPLETE) | 324 | if (tmf->response == ISCSI_TMF_RSP_COMPLETE) |
325 | conn->tmabort_state = TMABORT_SUCCESS; | 325 | conn->tmf_state = TMF_SUCCESS; |
326 | else if (tmf->response == ISCSI_TMF_RSP_NO_TASK) | 326 | else if (tmf->response == ISCSI_TMF_RSP_NO_TASK) |
327 | conn->tmabort_state = TMABORT_NOT_FOUND; | 327 | conn->tmf_state = TMF_NOT_FOUND; |
328 | else | 328 | else |
329 | conn->tmabort_state = TMABORT_FAILED; | 329 | conn->tmf_state = TMF_FAILED; |
330 | wake_up(&conn->ehwait); | 330 | wake_up(&conn->ehwait); |
331 | } | 331 | } |
332 | 332 | ||
@@ -429,7 +429,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
429 | */ | 429 | */ |
430 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) | 430 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) |
431 | rc = ISCSI_ERR_CONN_FAILED; | 431 | rc = ISCSI_ERR_CONN_FAILED; |
432 | list_del(&mtask->running); | 432 | list_del_init(&mtask->running); |
433 | if (conn->login_mtask != mtask) | 433 | if (conn->login_mtask != mtask) |
434 | __kfifo_put(session->mgmtpool.queue, | 434 | __kfifo_put(session->mgmtpool.queue, |
435 | (void*)&mtask, sizeof(void*)); | 435 | (void*)&mtask, sizeof(void*)); |
@@ -451,10 +451,9 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
451 | 451 | ||
452 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) | 452 | if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) |
453 | rc = ISCSI_ERR_CONN_FAILED; | 453 | rc = ISCSI_ERR_CONN_FAILED; |
454 | list_del(&mtask->running); | 454 | list_del_init(&mtask->running); |
455 | if (conn->login_mtask != mtask) | 455 | __kfifo_put(session->mgmtpool.queue, |
456 | __kfifo_put(session->mgmtpool.queue, | 456 | (void*)&mtask, sizeof(void*)); |
457 | (void*)&mtask, sizeof(void*)); | ||
458 | break; | 457 | break; |
459 | default: | 458 | default: |
460 | rc = ISCSI_ERR_BAD_OPCODE; | 459 | rc = ISCSI_ERR_BAD_OPCODE; |
@@ -609,7 +608,8 @@ static void iscsi_prep_mtask(struct iscsi_conn *conn, | |||
609 | session->tt->init_mgmt_task(conn, mtask); | 608 | session->tt->init_mgmt_task(conn, mtask); |
610 | 609 | ||
611 | debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", | 610 | debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", |
612 | hdr->opcode, hdr->itt, mtask->data_count); | 611 | hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt, |
612 | mtask->data_count); | ||
613 | } | 613 | } |
614 | 614 | ||
615 | static int iscsi_xmit_mtask(struct iscsi_conn *conn) | 615 | static int iscsi_xmit_mtask(struct iscsi_conn *conn) |
@@ -658,21 +658,13 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) | |||
658 | static int iscsi_xmit_ctask(struct iscsi_conn *conn) | 658 | static int iscsi_xmit_ctask(struct iscsi_conn *conn) |
659 | { | 659 | { |
660 | struct iscsi_cmd_task *ctask = conn->ctask; | 660 | struct iscsi_cmd_task *ctask = conn->ctask; |
661 | int rc = 0; | 661 | int rc; |
662 | |||
663 | /* | ||
664 | * serialize with TMF AbortTask | ||
665 | */ | ||
666 | if (ctask->state == ISCSI_TASK_ABORTING) | ||
667 | goto done; | ||
668 | 662 | ||
669 | __iscsi_get_ctask(ctask); | 663 | __iscsi_get_ctask(ctask); |
670 | spin_unlock_bh(&conn->session->lock); | 664 | spin_unlock_bh(&conn->session->lock); |
671 | rc = conn->session->tt->xmit_cmd_task(conn, ctask); | 665 | rc = conn->session->tt->xmit_cmd_task(conn, ctask); |
672 | spin_lock_bh(&conn->session->lock); | 666 | spin_lock_bh(&conn->session->lock); |
673 | __iscsi_put_ctask(ctask); | 667 | __iscsi_put_ctask(ctask); |
674 | |||
675 | done: | ||
676 | if (!rc) | 668 | if (!rc) |
677 | /* done with this ctask */ | 669 | /* done with this ctask */ |
678 | conn->ctask = NULL; | 670 | conn->ctask = NULL; |
@@ -680,6 +672,22 @@ done: | |||
680 | } | 672 | } |
681 | 673 | ||
682 | /** | 674 | /** |
675 | * iscsi_requeue_ctask - requeue ctask to run from session workqueue | ||
676 | * @ctask: ctask to requeue | ||
677 | * | ||
678 | * LLDs that need to run a ctask from the session workqueue should call | ||
679 | * this. The session lock must be held. | ||
680 | */ | ||
681 | void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask) | ||
682 | { | ||
683 | struct iscsi_conn *conn = ctask->conn; | ||
684 | |||
685 | list_move_tail(&ctask->running, &conn->requeue); | ||
686 | scsi_queue_work(conn->session->host, &conn->xmitwork); | ||
687 | } | ||
688 | EXPORT_SYMBOL_GPL(iscsi_requeue_ctask); | ||
689 | |||
690 | /** | ||
683 | * iscsi_data_xmit - xmit any command into the scheduled connection | 691 | * iscsi_data_xmit - xmit any command into the scheduled connection |
684 | * @conn: iscsi connection | 692 | * @conn: iscsi connection |
685 | * | 693 | * |
@@ -717,36 +725,27 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) | |||
717 | * overflow us with nop-ins | 725 | * overflow us with nop-ins |
718 | */ | 726 | */ |
719 | check_mgmt: | 727 | check_mgmt: |
720 | while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask, | 728 | while (!list_empty(&conn->mgmtqueue)) { |
721 | sizeof(void*))) { | 729 | conn->mtask = list_entry(conn->mgmtqueue.next, |
730 | struct iscsi_mgmt_task, running); | ||
722 | iscsi_prep_mtask(conn, conn->mtask); | 731 | iscsi_prep_mtask(conn, conn->mtask); |
723 | list_add_tail(&conn->mtask->running, &conn->mgmt_run_list); | 732 | list_move_tail(conn->mgmtqueue.next, &conn->mgmt_run_list); |
724 | rc = iscsi_xmit_mtask(conn); | 733 | rc = iscsi_xmit_mtask(conn); |
725 | if (rc) | 734 | if (rc) |
726 | goto again; | 735 | goto again; |
727 | } | 736 | } |
728 | 737 | ||
729 | /* process command queue */ | 738 | /* process pending command queue */ |
730 | while (!list_empty(&conn->xmitqueue)) { | 739 | while (!list_empty(&conn->xmitqueue)) { |
731 | /* | 740 | if (conn->tmf_state == TMF_QUEUED) |
732 | * iscsi tcp may readd the task to the xmitqueue to send | 741 | break; |
733 | * write data | 742 | |
734 | */ | ||
735 | conn->ctask = list_entry(conn->xmitqueue.next, | 743 | conn->ctask = list_entry(conn->xmitqueue.next, |
736 | struct iscsi_cmd_task, running); | 744 | struct iscsi_cmd_task, running); |
737 | switch (conn->ctask->state) { | 745 | iscsi_prep_scsi_cmd_pdu(conn->ctask); |
738 | case ISCSI_TASK_ABORTING: | 746 | conn->session->tt->init_cmd_task(conn->ctask); |
739 | break; | 747 | conn->ctask->state = ISCSI_TASK_RUNNING; |
740 | case ISCSI_TASK_PENDING: | ||
741 | iscsi_prep_scsi_cmd_pdu(conn->ctask); | ||
742 | conn->session->tt->init_cmd_task(conn->ctask); | ||
743 | /* fall through */ | ||
744 | default: | ||
745 | conn->ctask->state = ISCSI_TASK_RUNNING; | ||
746 | break; | ||
747 | } | ||
748 | list_move_tail(conn->xmitqueue.next, &conn->run_list); | 748 | list_move_tail(conn->xmitqueue.next, &conn->run_list); |
749 | |||
750 | rc = iscsi_xmit_ctask(conn); | 749 | rc = iscsi_xmit_ctask(conn); |
751 | if (rc) | 750 | if (rc) |
752 | goto again; | 751 | goto again; |
@@ -755,7 +754,22 @@ check_mgmt: | |||
755 | * we need to check the mgmt queue for nops that need to | 754 | * we need to check the mgmt queue for nops that need to |
756 | * be sent to aviod starvation | 755 | * be sent to aviod starvation |
757 | */ | 756 | */ |
758 | if (__kfifo_len(conn->mgmtqueue)) | 757 | if (!list_empty(&conn->mgmtqueue)) |
758 | goto check_mgmt; | ||
759 | } | ||
760 | |||
761 | while (!list_empty(&conn->requeue)) { | ||
762 | if (conn->session->fast_abort && conn->tmf_state != TMF_INITIAL) | ||
763 | break; | ||
764 | |||
765 | conn->ctask = list_entry(conn->requeue.next, | ||
766 | struct iscsi_cmd_task, running); | ||
767 | conn->ctask->state = ISCSI_TASK_RUNNING; | ||
768 | list_move_tail(conn->requeue.next, &conn->run_list); | ||
769 | rc = iscsi_xmit_ctask(conn); | ||
770 | if (rc) | ||
771 | goto again; | ||
772 | if (!list_empty(&conn->mgmtqueue)) | ||
759 | goto check_mgmt; | 773 | goto check_mgmt; |
760 | } | 774 | } |
761 | spin_unlock_bh(&conn->session->lock); | 775 | spin_unlock_bh(&conn->session->lock); |
@@ -859,7 +873,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
859 | 873 | ||
860 | atomic_set(&ctask->refcount, 1); | 874 | atomic_set(&ctask->refcount, 1); |
861 | ctask->state = ISCSI_TASK_PENDING; | 875 | ctask->state = ISCSI_TASK_PENDING; |
862 | ctask->mtask = NULL; | ||
863 | ctask->conn = conn; | 876 | ctask->conn = conn; |
864 | ctask->sc = sc; | 877 | ctask->sc = sc; |
865 | INIT_LIST_HEAD(&ctask->running); | 878 | INIT_LIST_HEAD(&ctask->running); |
@@ -929,9 +942,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
929 | } else | 942 | } else |
930 | mtask->data_count = 0; | 943 | mtask->data_count = 0; |
931 | 944 | ||
932 | INIT_LIST_HEAD(&mtask->running); | ||
933 | memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr)); | 945 | memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr)); |
934 | __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); | 946 | INIT_LIST_HEAD(&mtask->running); |
947 | list_add_tail(&mtask->running, &conn->mgmtqueue); | ||
935 | return mtask; | 948 | return mtask; |
936 | } | 949 | } |
937 | 950 | ||
@@ -954,13 +967,12 @@ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); | |||
954 | void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) | 967 | void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) |
955 | { | 968 | { |
956 | struct iscsi_session *session = class_to_transport_session(cls_session); | 969 | struct iscsi_session *session = class_to_transport_session(cls_session); |
957 | struct iscsi_conn *conn = session->leadconn; | ||
958 | 970 | ||
959 | spin_lock_bh(&session->lock); | 971 | spin_lock_bh(&session->lock); |
960 | if (session->state != ISCSI_STATE_LOGGED_IN) { | 972 | if (session->state != ISCSI_STATE_LOGGED_IN) { |
961 | session->state = ISCSI_STATE_RECOVERY_FAILED; | 973 | session->state = ISCSI_STATE_RECOVERY_FAILED; |
962 | if (conn) | 974 | if (session->leadconn) |
963 | wake_up(&conn->ehwait); | 975 | wake_up(&session->leadconn->ehwait); |
964 | } | 976 | } |
965 | spin_unlock_bh(&session->lock); | 977 | spin_unlock_bh(&session->lock); |
966 | } | 978 | } |
@@ -971,7 +983,6 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc) | |||
971 | struct Scsi_Host *host = sc->device->host; | 983 | struct Scsi_Host *host = sc->device->host; |
972 | struct iscsi_session *session = iscsi_hostdata(host->hostdata); | 984 | struct iscsi_session *session = iscsi_hostdata(host->hostdata); |
973 | struct iscsi_conn *conn = session->leadconn; | 985 | struct iscsi_conn *conn = session->leadconn; |
974 | int fail_session = 0; | ||
975 | 986 | ||
976 | spin_lock_bh(&session->lock); | 987 | spin_lock_bh(&session->lock); |
977 | if (session->state == ISCSI_STATE_TERMINATE) { | 988 | if (session->state == ISCSI_STATE_TERMINATE) { |
@@ -982,19 +993,13 @@ failed: | |||
982 | return FAILED; | 993 | return FAILED; |
983 | } | 994 | } |
984 | 995 | ||
985 | if (sc->SCp.phase == session->age) { | ||
986 | debug_scsi("failing connection CID %d due to SCSI host reset\n", | ||
987 | conn->id); | ||
988 | fail_session = 1; | ||
989 | } | ||
990 | spin_unlock_bh(&session->lock); | 996 | spin_unlock_bh(&session->lock); |
991 | 997 | ||
992 | /* | 998 | /* |
993 | * we drop the lock here but the leadconn cannot be destoyed while | 999 | * we drop the lock here but the leadconn cannot be destoyed while |
994 | * we are in the scsi eh | 1000 | * we are in the scsi eh |
995 | */ | 1001 | */ |
996 | if (fail_session) | 1002 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); |
997 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | ||
998 | 1003 | ||
999 | debug_scsi("iscsi_eh_host_reset wait for relogin\n"); | 1004 | debug_scsi("iscsi_eh_host_reset wait for relogin\n"); |
1000 | wait_event_interruptible(conn->ehwait, | 1005 | wait_event_interruptible(conn->ehwait, |
@@ -1015,62 +1020,43 @@ failed: | |||
1015 | } | 1020 | } |
1016 | EXPORT_SYMBOL_GPL(iscsi_eh_host_reset); | 1021 | EXPORT_SYMBOL_GPL(iscsi_eh_host_reset); |
1017 | 1022 | ||
1018 | static void iscsi_tmabort_timedout(unsigned long data) | 1023 | static void iscsi_tmf_timedout(unsigned long data) |
1019 | { | 1024 | { |
1020 | struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)data; | 1025 | struct iscsi_conn *conn = (struct iscsi_conn *)data; |
1021 | struct iscsi_conn *conn = ctask->conn; | ||
1022 | struct iscsi_session *session = conn->session; | 1026 | struct iscsi_session *session = conn->session; |
1023 | 1027 | ||
1024 | spin_lock(&session->lock); | 1028 | spin_lock(&session->lock); |
1025 | if (conn->tmabort_state == TMABORT_INITIAL) { | 1029 | if (conn->tmf_state == TMF_QUEUED) { |
1026 | conn->tmabort_state = TMABORT_TIMEDOUT; | 1030 | conn->tmf_state = TMF_TIMEDOUT; |
1027 | debug_scsi("tmabort timedout [sc %p itt 0x%x]\n", | 1031 | debug_scsi("tmf timedout\n"); |
1028 | ctask->sc, ctask->itt); | ||
1029 | /* unblock eh_abort() */ | 1032 | /* unblock eh_abort() */ |
1030 | wake_up(&conn->ehwait); | 1033 | wake_up(&conn->ehwait); |
1031 | } | 1034 | } |
1032 | spin_unlock(&session->lock); | 1035 | spin_unlock(&session->lock); |
1033 | } | 1036 | } |
1034 | 1037 | ||
1035 | static int iscsi_exec_abort_task(struct scsi_cmnd *sc, | 1038 | static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, |
1036 | struct iscsi_cmd_task *ctask) | 1039 | struct iscsi_tm *hdr, int age) |
1037 | { | 1040 | { |
1038 | struct iscsi_conn *conn = ctask->conn; | ||
1039 | struct iscsi_session *session = conn->session; | 1041 | struct iscsi_session *session = conn->session; |
1040 | struct iscsi_tm *hdr = &conn->tmhdr; | 1042 | struct iscsi_mgmt_task *mtask; |
1041 | |||
1042 | /* | ||
1043 | * ctask timed out but session is OK requests must be serialized. | ||
1044 | */ | ||
1045 | memset(hdr, 0, sizeof(struct iscsi_tm)); | ||
1046 | hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; | ||
1047 | hdr->flags = ISCSI_TM_FUNC_ABORT_TASK; | ||
1048 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | ||
1049 | memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); | ||
1050 | hdr->rtt = ctask->hdr->itt; | ||
1051 | hdr->refcmdsn = ctask->hdr->cmdsn; | ||
1052 | 1043 | ||
1053 | ctask->mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, | 1044 | mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, |
1054 | NULL, 0); | 1045 | NULL, 0); |
1055 | if (!ctask->mtask) { | 1046 | if (!mtask) { |
1056 | spin_unlock_bh(&session->lock); | 1047 | spin_unlock_bh(&session->lock); |
1057 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | 1048 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); |
1058 | spin_lock_bh(&session->lock) | 1049 | spin_lock_bh(&session->lock); |
1059 | debug_scsi("abort sent failure [itt 0x%x]\n", ctask->itt); | 1050 | debug_scsi("tmf exec failure\n"); |
1060 | return -EPERM; | 1051 | return -EPERM; |
1061 | } | 1052 | } |
1062 | ctask->state = ISCSI_TASK_ABORTING; | 1053 | conn->tmfcmd_pdus_cnt++; |
1063 | 1054 | conn->tmf_timer.expires = 30 * HZ + jiffies; | |
1064 | debug_scsi("abort sent [itt 0x%x]\n", ctask->itt); | 1055 | conn->tmf_timer.function = iscsi_tmf_timedout; |
1056 | conn->tmf_timer.data = (unsigned long)conn; | ||
1057 | add_timer(&conn->tmf_timer); | ||
1058 | debug_scsi("tmf set timeout\n"); | ||
1065 | 1059 | ||
1066 | if (conn->tmabort_state == TMABORT_INITIAL) { | ||
1067 | conn->tmfcmd_pdus_cnt++; | ||
1068 | conn->tmabort_timer.expires = 20*HZ + jiffies; | ||
1069 | conn->tmabort_timer.function = iscsi_tmabort_timedout; | ||
1070 | conn->tmabort_timer.data = (unsigned long)ctask; | ||
1071 | add_timer(&conn->tmabort_timer); | ||
1072 | debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt); | ||
1073 | } | ||
1074 | spin_unlock_bh(&session->lock); | 1060 | spin_unlock_bh(&session->lock); |
1075 | mutex_unlock(&session->eh_mutex); | 1061 | mutex_unlock(&session->eh_mutex); |
1076 | scsi_queue_work(session->host, &conn->xmitwork); | 1062 | scsi_queue_work(session->host, &conn->xmitwork); |
@@ -1078,61 +1064,30 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, | |||
1078 | /* | 1064 | /* |
1079 | * block eh thread until: | 1065 | * block eh thread until: |
1080 | * | 1066 | * |
1081 | * 1) abort response | 1067 | * 1) tmf response |
1082 | * 2) abort timeout | 1068 | * 2) tmf timeout |
1083 | * 3) session is terminated or restarted or userspace has | 1069 | * 3) session is terminated or restarted or userspace has |
1084 | * given up on recovery | 1070 | * given up on recovery |
1085 | */ | 1071 | */ |
1086 | wait_event_interruptible(conn->ehwait, | 1072 | wait_event_interruptible(conn->ehwait, age != session->age || |
1087 | sc->SCp.phase != session->age || | ||
1088 | session->state != ISCSI_STATE_LOGGED_IN || | 1073 | session->state != ISCSI_STATE_LOGGED_IN || |
1089 | conn->tmabort_state != TMABORT_INITIAL); | 1074 | conn->tmf_state != TMF_QUEUED); |
1090 | if (signal_pending(current)) | 1075 | if (signal_pending(current)) |
1091 | flush_signals(current); | 1076 | flush_signals(current); |
1092 | del_timer_sync(&conn->tmabort_timer); | 1077 | del_timer_sync(&conn->tmf_timer); |
1078 | |||
1093 | mutex_lock(&session->eh_mutex); | 1079 | mutex_lock(&session->eh_mutex); |
1094 | spin_lock_bh(&session->lock); | 1080 | spin_lock_bh(&session->lock); |
1095 | return 0; | 1081 | /* if the session drops it will clean up the mtask */ |
1096 | } | 1082 | if (age != session->age || |
1097 | 1083 | session->state != ISCSI_STATE_LOGGED_IN) | |
1098 | /* | 1084 | return -ENOTCONN; |
1099 | * session lock must be held | ||
1100 | */ | ||
1101 | static struct iscsi_mgmt_task * | ||
1102 | iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt) | ||
1103 | { | ||
1104 | int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*); | ||
1105 | struct iscsi_mgmt_task *task; | ||
1106 | |||
1107 | debug_scsi("searching %d tasks\n", nr_tasks); | ||
1108 | |||
1109 | for (i = 0; i < nr_tasks; i++) { | ||
1110 | __kfifo_get(fifo, (void*)&task, sizeof(void*)); | ||
1111 | debug_scsi("check task %u\n", task->itt); | ||
1112 | |||
1113 | if (task->itt == itt) { | ||
1114 | debug_scsi("matched task\n"); | ||
1115 | return task; | ||
1116 | } | ||
1117 | 1085 | ||
1118 | __kfifo_put(fifo, (void*)&task, sizeof(void*)); | 1086 | if (!list_empty(&mtask->running)) { |
1087 | list_del_init(&mtask->running); | ||
1088 | __kfifo_put(session->mgmtpool.queue, (void*)&mtask, | ||
1089 | sizeof(void*)); | ||
1119 | } | 1090 | } |
1120 | return NULL; | ||
1121 | } | ||
1122 | |||
1123 | static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask) | ||
1124 | { | ||
1125 | struct iscsi_conn *conn = ctask->conn; | ||
1126 | struct iscsi_session *session = conn->session; | ||
1127 | |||
1128 | if (!ctask->mtask) | ||
1129 | return -EINVAL; | ||
1130 | |||
1131 | if (!iscsi_remove_mgmt_task(conn->mgmtqueue, ctask->mtask->itt)) | ||
1132 | list_del(&ctask->mtask->running); | ||
1133 | __kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask, | ||
1134 | sizeof(void*)); | ||
1135 | ctask->mtask = NULL; | ||
1136 | return 0; | 1091 | return 0; |
1137 | } | 1092 | } |
1138 | 1093 | ||
@@ -1156,7 +1111,6 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
1156 | conn->session->queued_cmdsn--; | 1111 | conn->session->queued_cmdsn--; |
1157 | else | 1112 | else |
1158 | conn->session->tt->cleanup_cmd_task(conn, ctask); | 1113 | conn->session->tt->cleanup_cmd_task(conn, ctask); |
1159 | iscsi_ctask_mtask_cleanup(ctask); | ||
1160 | 1114 | ||
1161 | sc->result = err; | 1115 | sc->result = err; |
1162 | scsi_set_resid(sc, scsi_bufflen(sc)); | 1116 | scsi_set_resid(sc, scsi_bufflen(sc)); |
@@ -1166,6 +1120,44 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
1166 | __iscsi_put_ctask(ctask); | 1120 | __iscsi_put_ctask(ctask); |
1167 | } | 1121 | } |
1168 | 1122 | ||
1123 | /* | ||
1124 | * Fail commands. session lock held and recv side suspended and xmit | ||
1125 | * thread flushed | ||
1126 | */ | ||
1127 | static void fail_all_commands(struct iscsi_conn *conn, unsigned lun) | ||
1128 | { | ||
1129 | struct iscsi_cmd_task *ctask, *tmp; | ||
1130 | |||
1131 | if (conn->ctask && (conn->ctask->sc->device->lun == lun || lun == -1)) | ||
1132 | conn->ctask = NULL; | ||
1133 | |||
1134 | /* flush pending */ | ||
1135 | list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) { | ||
1136 | if (lun == ctask->sc->device->lun || lun == -1) { | ||
1137 | debug_scsi("failing pending sc %p itt 0x%x\n", | ||
1138 | ctask->sc, ctask->itt); | ||
1139 | fail_command(conn, ctask, DID_BUS_BUSY << 16); | ||
1140 | } | ||
1141 | } | ||
1142 | |||
1143 | list_for_each_entry_safe(ctask, tmp, &conn->requeue, running) { | ||
1144 | if (lun == ctask->sc->device->lun || lun == -1) { | ||
1145 | debug_scsi("failing requeued sc %p itt 0x%x\n", | ||
1146 | ctask->sc, ctask->itt); | ||
1147 | fail_command(conn, ctask, DID_BUS_BUSY << 16); | ||
1148 | } | ||
1149 | } | ||
1150 | |||
1151 | /* fail all other running */ | ||
1152 | list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) { | ||
1153 | if (lun == ctask->sc->device->lun || lun == -1) { | ||
1154 | debug_scsi("failing in progress sc %p itt 0x%x\n", | ||
1155 | ctask->sc, ctask->itt); | ||
1156 | fail_command(conn, ctask, DID_BUS_BUSY << 16); | ||
1157 | } | ||
1158 | } | ||
1159 | } | ||
1160 | |||
1169 | static void iscsi_suspend_tx(struct iscsi_conn *conn) | 1161 | static void iscsi_suspend_tx(struct iscsi_conn *conn) |
1170 | { | 1162 | { |
1171 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | 1163 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
@@ -1178,13 +1170,26 @@ static void iscsi_start_tx(struct iscsi_conn *conn) | |||
1178 | scsi_queue_work(conn->session->host, &conn->xmitwork); | 1170 | scsi_queue_work(conn->session->host, &conn->xmitwork); |
1179 | } | 1171 | } |
1180 | 1172 | ||
1173 | static void iscsi_prep_abort_task_pdu(struct iscsi_cmd_task *ctask, | ||
1174 | struct iscsi_tm *hdr) | ||
1175 | { | ||
1176 | memset(hdr, 0, sizeof(*hdr)); | ||
1177 | hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; | ||
1178 | hdr->flags = ISCSI_TM_FUNC_ABORT_TASK & ISCSI_FLAG_TM_FUNC_MASK; | ||
1179 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | ||
1180 | memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); | ||
1181 | hdr->rtt = ctask->hdr->itt; | ||
1182 | hdr->refcmdsn = ctask->hdr->cmdsn; | ||
1183 | } | ||
1184 | |||
1181 | int iscsi_eh_abort(struct scsi_cmnd *sc) | 1185 | int iscsi_eh_abort(struct scsi_cmnd *sc) |
1182 | { | 1186 | { |
1183 | struct Scsi_Host *host = sc->device->host; | 1187 | struct Scsi_Host *host = sc->device->host; |
1184 | struct iscsi_session *session = iscsi_hostdata(host->hostdata); | 1188 | struct iscsi_session *session = iscsi_hostdata(host->hostdata); |
1185 | struct iscsi_cmd_task *ctask; | ||
1186 | struct iscsi_conn *conn; | 1189 | struct iscsi_conn *conn; |
1187 | int rc; | 1190 | struct iscsi_cmd_task *ctask; |
1191 | struct iscsi_tm *hdr; | ||
1192 | int rc, age; | ||
1188 | 1193 | ||
1189 | mutex_lock(&session->eh_mutex); | 1194 | mutex_lock(&session->eh_mutex); |
1190 | spin_lock_bh(&session->lock); | 1195 | spin_lock_bh(&session->lock); |
@@ -1199,19 +1204,23 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1199 | return SUCCESS; | 1204 | return SUCCESS; |
1200 | } | 1205 | } |
1201 | 1206 | ||
1202 | ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; | ||
1203 | conn = ctask->conn; | ||
1204 | |||
1205 | conn->eh_abort_cnt++; | ||
1206 | debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); | ||
1207 | |||
1208 | /* | 1207 | /* |
1209 | * If we are not logged in or we have started a new session | 1208 | * If we are not logged in or we have started a new session |
1210 | * then let the host reset code handle this | 1209 | * then let the host reset code handle this |
1211 | */ | 1210 | */ |
1212 | if (session->state != ISCSI_STATE_LOGGED_IN || | 1211 | if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN || |
1213 | sc->SCp.phase != session->age) | 1212 | sc->SCp.phase != session->age) { |
1214 | goto failed; | 1213 | spin_unlock_bh(&session->lock); |
1214 | mutex_unlock(&session->eh_mutex); | ||
1215 | return FAILED; | ||
1216 | } | ||
1217 | |||
1218 | conn = session->leadconn; | ||
1219 | conn->eh_abort_cnt++; | ||
1220 | age = session->age; | ||
1221 | |||
1222 | ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; | ||
1223 | debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); | ||
1215 | 1224 | ||
1216 | /* ctask completed before time out */ | 1225 | /* ctask completed before time out */ |
1217 | if (!ctask->sc) { | 1226 | if (!ctask->sc) { |
@@ -1219,27 +1228,26 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1219 | goto success; | 1228 | goto success; |
1220 | } | 1229 | } |
1221 | 1230 | ||
1222 | /* what should we do here ? */ | ||
1223 | if (conn->ctask == ctask) { | ||
1224 | printk(KERN_INFO "iscsi: sc %p itt 0x%x partially sent. " | ||
1225 | "Failing abort\n", sc, ctask->itt); | ||
1226 | goto failed; | ||
1227 | } | ||
1228 | |||
1229 | if (ctask->state == ISCSI_TASK_PENDING) { | 1231 | if (ctask->state == ISCSI_TASK_PENDING) { |
1230 | fail_command(conn, ctask, DID_ABORT << 16); | 1232 | fail_command(conn, ctask, DID_ABORT << 16); |
1231 | goto success; | 1233 | goto success; |
1232 | } | 1234 | } |
1233 | 1235 | ||
1234 | conn->tmabort_state = TMABORT_INITIAL; | 1236 | /* only have one tmf outstanding at a time */ |
1235 | rc = iscsi_exec_abort_task(sc, ctask); | 1237 | if (conn->tmf_state != TMF_INITIAL) |
1236 | if (rc || sc->SCp.phase != session->age || | ||
1237 | session->state != ISCSI_STATE_LOGGED_IN) | ||
1238 | goto failed; | 1238 | goto failed; |
1239 | iscsi_ctask_mtask_cleanup(ctask); | 1239 | conn->tmf_state = TMF_QUEUED; |
1240 | 1240 | ||
1241 | switch (conn->tmabort_state) { | 1241 | hdr = &conn->tmhdr; |
1242 | case TMABORT_SUCCESS: | 1242 | iscsi_prep_abort_task_pdu(ctask, hdr); |
1243 | |||
1244 | if (iscsi_exec_task_mgmt_fn(conn, hdr, age)) { | ||
1245 | rc = FAILED; | ||
1246 | goto failed; | ||
1247 | } | ||
1248 | |||
1249 | switch (conn->tmf_state) { | ||
1250 | case TMF_SUCCESS: | ||
1243 | spin_unlock_bh(&session->lock); | 1251 | spin_unlock_bh(&session->lock); |
1244 | iscsi_suspend_tx(conn); | 1252 | iscsi_suspend_tx(conn); |
1245 | /* | 1253 | /* |
@@ -1248,22 +1256,26 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) | |||
1248 | write_lock_bh(conn->recv_lock); | 1256 | write_lock_bh(conn->recv_lock); |
1249 | spin_lock(&session->lock); | 1257 | spin_lock(&session->lock); |
1250 | fail_command(conn, ctask, DID_ABORT << 16); | 1258 | fail_command(conn, ctask, DID_ABORT << 16); |
1259 | conn->tmf_state = TMF_INITIAL; | ||
1251 | spin_unlock(&session->lock); | 1260 | spin_unlock(&session->lock); |
1252 | write_unlock_bh(conn->recv_lock); | 1261 | write_unlock_bh(conn->recv_lock); |
1253 | iscsi_start_tx(conn); | 1262 | iscsi_start_tx(conn); |
1254 | goto success_unlocked; | 1263 | goto success_unlocked; |
1255 | case TMABORT_NOT_FOUND: | 1264 | case TMF_TIMEDOUT: |
1256 | if (!ctask->sc) { | 1265 | spin_unlock_bh(&session->lock); |
1266 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | ||
1267 | goto failed_unlocked; | ||
1268 | case TMF_NOT_FOUND: | ||
1269 | if (!sc->SCp.ptr) { | ||
1270 | conn->tmf_state = TMF_INITIAL; | ||
1257 | /* ctask completed before tmf abort response */ | 1271 | /* ctask completed before tmf abort response */ |
1258 | debug_scsi("sc completed while abort in progress\n"); | 1272 | debug_scsi("sc completed while abort in progress\n"); |
1259 | goto success; | 1273 | goto success; |
1260 | } | 1274 | } |
1261 | /* fall through */ | 1275 | /* fall through */ |
1262 | default: | 1276 | default: |
1263 | /* timedout or failed */ | 1277 | conn->tmf_state = TMF_INITIAL; |
1264 | spin_unlock_bh(&session->lock); | 1278 | goto failed; |
1265 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | ||
1266 | goto failed_unlocked; | ||
1267 | } | 1279 | } |
1268 | 1280 | ||
1269 | success: | 1281 | success: |
@@ -1276,12 +1288,93 @@ success_unlocked: | |||
1276 | failed: | 1288 | failed: |
1277 | spin_unlock_bh(&session->lock); | 1289 | spin_unlock_bh(&session->lock); |
1278 | failed_unlocked: | 1290 | failed_unlocked: |
1279 | debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); | 1291 | debug_scsi("abort failed [sc %p itt 0x%x]\n", sc, |
1292 | ctask ? ctask->itt : 0); | ||
1280 | mutex_unlock(&session->eh_mutex); | 1293 | mutex_unlock(&session->eh_mutex); |
1281 | return FAILED; | 1294 | return FAILED; |
1282 | } | 1295 | } |
1283 | EXPORT_SYMBOL_GPL(iscsi_eh_abort); | 1296 | EXPORT_SYMBOL_GPL(iscsi_eh_abort); |
1284 | 1297 | ||
1298 | static void iscsi_prep_lun_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr) | ||
1299 | { | ||
1300 | memset(hdr, 0, sizeof(*hdr)); | ||
1301 | hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; | ||
1302 | hdr->flags = ISCSI_TM_FUNC_LOGICAL_UNIT_RESET & ISCSI_FLAG_TM_FUNC_MASK; | ||
1303 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | ||
1304 | int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); | ||
1305 | hdr->rtt = ISCSI_RESERVED_TAG; | ||
1306 | } | ||
1307 | |||
1308 | int iscsi_eh_device_reset(struct scsi_cmnd *sc) | ||
1309 | { | ||
1310 | struct Scsi_Host *host = sc->device->host; | ||
1311 | struct iscsi_session *session = iscsi_hostdata(host->hostdata); | ||
1312 | struct iscsi_conn *conn; | ||
1313 | struct iscsi_tm *hdr; | ||
1314 | int rc = FAILED; | ||
1315 | |||
1316 | debug_scsi("LU Reset [sc %p lun %u]\n", sc, sc->device->lun); | ||
1317 | |||
1318 | mutex_lock(&session->eh_mutex); | ||
1319 | spin_lock_bh(&session->lock); | ||
1320 | /* | ||
1321 | * Just check if we are not logged in. We cannot check for | ||
1322 | * the phase because the reset could come from a ioctl. | ||
1323 | */ | ||
1324 | if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) | ||
1325 | goto unlock; | ||
1326 | conn = session->leadconn; | ||
1327 | |||
1328 | /* only have one tmf outstanding at a time */ | ||
1329 | if (conn->tmf_state != TMF_INITIAL) | ||
1330 | goto unlock; | ||
1331 | conn->tmf_state = TMF_QUEUED; | ||
1332 | |||
1333 | hdr = &conn->tmhdr; | ||
1334 | iscsi_prep_lun_reset_pdu(sc, hdr); | ||
1335 | |||
1336 | if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age)) { | ||
1337 | rc = FAILED; | ||
1338 | goto unlock; | ||
1339 | } | ||
1340 | |||
1341 | switch (conn->tmf_state) { | ||
1342 | case TMF_SUCCESS: | ||
1343 | break; | ||
1344 | case TMF_TIMEDOUT: | ||
1345 | spin_unlock_bh(&session->lock); | ||
1346 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | ||
1347 | goto done; | ||
1348 | default: | ||
1349 | conn->tmf_state = TMF_INITIAL; | ||
1350 | goto unlock; | ||
1351 | } | ||
1352 | |||
1353 | rc = SUCCESS; | ||
1354 | spin_unlock_bh(&session->lock); | ||
1355 | |||
1356 | iscsi_suspend_tx(conn); | ||
1357 | /* need to grab the recv lock then session lock */ | ||
1358 | write_lock_bh(conn->recv_lock); | ||
1359 | spin_lock(&session->lock); | ||
1360 | fail_all_commands(conn, sc->device->lun); | ||
1361 | conn->tmf_state = TMF_INITIAL; | ||
1362 | spin_unlock(&session->lock); | ||
1363 | write_unlock_bh(conn->recv_lock); | ||
1364 | |||
1365 | iscsi_start_tx(conn); | ||
1366 | goto done; | ||
1367 | |||
1368 | unlock: | ||
1369 | spin_unlock_bh(&session->lock); | ||
1370 | done: | ||
1371 | debug_scsi("iscsi_eh_device_reset %s\n", | ||
1372 | rc == SUCCESS ? "SUCCESS" : "FAILED"); | ||
1373 | mutex_unlock(&session->eh_mutex); | ||
1374 | return rc; | ||
1375 | } | ||
1376 | EXPORT_SYMBOL_GPL(iscsi_eh_device_reset); | ||
1377 | |||
1285 | int | 1378 | int |
1286 | iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size) | 1379 | iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size) |
1287 | { | 1380 | { |
@@ -1546,17 +1639,12 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | |||
1546 | conn->c_stage = ISCSI_CONN_INITIAL_STAGE; | 1639 | conn->c_stage = ISCSI_CONN_INITIAL_STAGE; |
1547 | conn->id = conn_idx; | 1640 | conn->id = conn_idx; |
1548 | conn->exp_statsn = 0; | 1641 | conn->exp_statsn = 0; |
1549 | conn->tmabort_state = TMABORT_INITIAL; | 1642 | conn->tmf_state = TMF_INITIAL; |
1550 | INIT_LIST_HEAD(&conn->run_list); | 1643 | INIT_LIST_HEAD(&conn->run_list); |
1551 | INIT_LIST_HEAD(&conn->mgmt_run_list); | 1644 | INIT_LIST_HEAD(&conn->mgmt_run_list); |
1645 | INIT_LIST_HEAD(&conn->mgmtqueue); | ||
1552 | INIT_LIST_HEAD(&conn->xmitqueue); | 1646 | INIT_LIST_HEAD(&conn->xmitqueue); |
1553 | 1647 | INIT_LIST_HEAD(&conn->requeue); | |
1554 | /* initialize general immediate & non-immediate PDU commands queue */ | ||
1555 | conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), | ||
1556 | GFP_KERNEL, NULL); | ||
1557 | if (conn->mgmtqueue == ERR_PTR(-ENOMEM)) | ||
1558 | goto mgmtqueue_alloc_fail; | ||
1559 | |||
1560 | INIT_WORK(&conn->xmitwork, iscsi_xmitworker); | 1648 | INIT_WORK(&conn->xmitwork, iscsi_xmitworker); |
1561 | 1649 | ||
1562 | /* allocate login_mtask used for the login/text sequences */ | 1650 | /* allocate login_mtask used for the login/text sequences */ |
@@ -1574,7 +1662,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) | |||
1574 | goto login_mtask_data_alloc_fail; | 1662 | goto login_mtask_data_alloc_fail; |
1575 | conn->login_mtask->data = conn->data = data; | 1663 | conn->login_mtask->data = conn->data = data; |
1576 | 1664 | ||
1577 | init_timer(&conn->tmabort_timer); | 1665 | init_timer(&conn->tmf_timer); |
1578 | init_waitqueue_head(&conn->ehwait); | 1666 | init_waitqueue_head(&conn->ehwait); |
1579 | 1667 | ||
1580 | return cls_conn; | 1668 | return cls_conn; |
@@ -1583,8 +1671,6 @@ login_mtask_data_alloc_fail: | |||
1583 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, | 1671 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, |
1584 | sizeof(void*)); | 1672 | sizeof(void*)); |
1585 | login_mtask_alloc_fail: | 1673 | login_mtask_alloc_fail: |
1586 | kfifo_free(conn->mgmtqueue); | ||
1587 | mgmtqueue_alloc_fail: | ||
1588 | iscsi_destroy_conn(cls_conn); | 1674 | iscsi_destroy_conn(cls_conn); |
1589 | return NULL; | 1675 | return NULL; |
1590 | } | 1676 | } |
@@ -1604,7 +1690,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
1604 | unsigned long flags; | 1690 | unsigned long flags; |
1605 | 1691 | ||
1606 | spin_lock_bh(&session->lock); | 1692 | spin_lock_bh(&session->lock); |
1607 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | ||
1608 | conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; | 1693 | conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; |
1609 | if (session->leadconn == conn) { | 1694 | if (session->leadconn == conn) { |
1610 | /* | 1695 | /* |
@@ -1637,7 +1722,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
1637 | } | 1722 | } |
1638 | 1723 | ||
1639 | /* flush queued up work because we free the connection below */ | 1724 | /* flush queued up work because we free the connection below */ |
1640 | scsi_flush_work(session->host); | 1725 | iscsi_suspend_tx(conn); |
1641 | 1726 | ||
1642 | spin_lock_bh(&session->lock); | 1727 | spin_lock_bh(&session->lock); |
1643 | kfree(conn->data); | 1728 | kfree(conn->data); |
@@ -1648,8 +1733,6 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
1648 | session->leadconn = NULL; | 1733 | session->leadconn = NULL; |
1649 | spin_unlock_bh(&session->lock); | 1734 | spin_unlock_bh(&session->lock); |
1650 | 1735 | ||
1651 | kfifo_free(conn->mgmtqueue); | ||
1652 | |||
1653 | iscsi_destroy_conn(cls_conn); | 1736 | iscsi_destroy_conn(cls_conn); |
1654 | } | 1737 | } |
1655 | EXPORT_SYMBOL_GPL(iscsi_conn_teardown); | 1738 | EXPORT_SYMBOL_GPL(iscsi_conn_teardown); |
@@ -1684,7 +1767,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) | |||
1684 | * commands after successful recovery | 1767 | * commands after successful recovery |
1685 | */ | 1768 | */ |
1686 | conn->stop_stage = 0; | 1769 | conn->stop_stage = 0; |
1687 | conn->tmabort_state = TMABORT_INITIAL; | 1770 | conn->tmf_state = TMF_INITIAL; |
1688 | session->age++; | 1771 | session->age++; |
1689 | spin_unlock_bh(&session->lock); | 1772 | spin_unlock_bh(&session->lock); |
1690 | 1773 | ||
@@ -1709,10 +1792,11 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) | |||
1709 | struct iscsi_mgmt_task *mtask, *tmp; | 1792 | struct iscsi_mgmt_task *mtask, *tmp; |
1710 | 1793 | ||
1711 | /* handle pending */ | 1794 | /* handle pending */ |
1712 | while (__kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) { | 1795 | list_for_each_entry_safe(mtask, tmp, &conn->mgmtqueue, running) { |
1796 | debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt); | ||
1797 | list_del_init(&mtask->running); | ||
1713 | if (mtask == conn->login_mtask) | 1798 | if (mtask == conn->login_mtask) |
1714 | continue; | 1799 | continue; |
1715 | debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt); | ||
1716 | __kfifo_put(session->mgmtpool.queue, (void*)&mtask, | 1800 | __kfifo_put(session->mgmtpool.queue, (void*)&mtask, |
1717 | sizeof(void*)); | 1801 | sizeof(void*)); |
1718 | } | 1802 | } |
@@ -1720,7 +1804,7 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) | |||
1720 | /* handle running */ | 1804 | /* handle running */ |
1721 | list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) { | 1805 | list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) { |
1722 | debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt); | 1806 | debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt); |
1723 | list_del(&mtask->running); | 1807 | list_del_init(&mtask->running); |
1724 | 1808 | ||
1725 | if (mtask == conn->login_mtask) | 1809 | if (mtask == conn->login_mtask) |
1726 | continue; | 1810 | continue; |
@@ -1731,28 +1815,6 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn) | |||
1731 | conn->mtask = NULL; | 1815 | conn->mtask = NULL; |
1732 | } | 1816 | } |
1733 | 1817 | ||
1734 | /* Fail commands. Mutex and session lock held and recv side suspended */ | ||
1735 | static void fail_all_commands(struct iscsi_conn *conn) | ||
1736 | { | ||
1737 | struct iscsi_cmd_task *ctask, *tmp; | ||
1738 | |||
1739 | /* flush pending */ | ||
1740 | list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) { | ||
1741 | debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc, | ||
1742 | ctask->itt); | ||
1743 | fail_command(conn, ctask, DID_BUS_BUSY << 16); | ||
1744 | } | ||
1745 | |||
1746 | /* fail all other running */ | ||
1747 | list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) { | ||
1748 | debug_scsi("failing in progress sc %p itt 0x%x\n", | ||
1749 | ctask->sc, ctask->itt); | ||
1750 | fail_command(conn, ctask, DID_BUS_BUSY << 16); | ||
1751 | } | ||
1752 | |||
1753 | conn->ctask = NULL; | ||
1754 | } | ||
1755 | |||
1756 | static void iscsi_start_session_recovery(struct iscsi_session *session, | 1818 | static void iscsi_start_session_recovery(struct iscsi_session *session, |
1757 | struct iscsi_conn *conn, int flag) | 1819 | struct iscsi_conn *conn, int flag) |
1758 | { | 1820 | { |
@@ -1818,7 +1880,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
1818 | * flush queues. | 1880 | * flush queues. |
1819 | */ | 1881 | */ |
1820 | spin_lock_bh(&session->lock); | 1882 | spin_lock_bh(&session->lock); |
1821 | fail_all_commands(conn); | 1883 | fail_all_commands(conn, -1); |
1822 | flush_control_queues(session, conn); | 1884 | flush_control_queues(session, conn); |
1823 | spin_unlock_bh(&session->lock); | 1885 | spin_unlock_bh(&session->lock); |
1824 | mutex_unlock(&session->eh_mutex); | 1886 | mutex_unlock(&session->eh_mutex); |
@@ -1869,6 +1931,9 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn, | |||
1869 | uint32_t value; | 1931 | uint32_t value; |
1870 | 1932 | ||
1871 | switch(param) { | 1933 | switch(param) { |
1934 | case ISCSI_PARAM_FAST_ABORT: | ||
1935 | sscanf(buf, "%d", &session->fast_abort); | ||
1936 | break; | ||
1872 | case ISCSI_PARAM_MAX_RECV_DLENGTH: | 1937 | case ISCSI_PARAM_MAX_RECV_DLENGTH: |
1873 | sscanf(buf, "%d", &conn->max_recv_dlength); | 1938 | sscanf(buf, "%d", &conn->max_recv_dlength); |
1874 | break; | 1939 | break; |
@@ -1983,6 +2048,9 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session, | |||
1983 | int len; | 2048 | int len; |
1984 | 2049 | ||
1985 | switch(param) { | 2050 | switch(param) { |
2051 | case ISCSI_PARAM_FAST_ABORT: | ||
2052 | len = sprintf(buf, "%d\n", session->fast_abort); | ||
2053 | break; | ||
1986 | case ISCSI_PARAM_INITIAL_R2T_EN: | 2054 | case ISCSI_PARAM_INITIAL_R2T_EN: |
1987 | len = sprintf(buf, "%d\n", session->initial_r2t_en); | 2055 | len = sprintf(buf, "%d\n", session->initial_r2t_en); |
1988 | break; | 2056 | break; |
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index cb48b80c0865..75d3069ecaa0 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <scsi/scsi_transport_iscsi.h> | 30 | #include <scsi/scsi_transport_iscsi.h> |
31 | #include <scsi/iscsi_if.h> | 31 | #include <scsi/iscsi_if.h> |
32 | 32 | ||
33 | #define ISCSI_SESSION_ATTRS 15 | 33 | #define ISCSI_SESSION_ATTRS 16 |
34 | #define ISCSI_CONN_ATTRS 11 | 34 | #define ISCSI_CONN_ATTRS 11 |
35 | #define ISCSI_HOST_ATTRS 4 | 35 | #define ISCSI_HOST_ATTRS 4 |
36 | #define ISCSI_TRANSPORT_VERSION "2.0-724" | 36 | #define ISCSI_TRANSPORT_VERSION "2.0-724" |
@@ -1218,6 +1218,7 @@ iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1); | |||
1218 | iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1); | 1218 | iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1); |
1219 | iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1); | 1219 | iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1); |
1220 | iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1); | 1220 | iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1); |
1221 | iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 1); | ||
1221 | 1222 | ||
1222 | #define iscsi_priv_session_attr_show(field, format) \ | 1223 | #define iscsi_priv_session_attr_show(field, format) \ |
1223 | static ssize_t \ | 1224 | static ssize_t \ |
@@ -1439,6 +1440,7 @@ iscsi_register_transport(struct iscsi_transport *tt) | |||
1439 | SETUP_SESSION_RD_ATTR(password_in, ISCSI_USERNAME_IN); | 1440 | SETUP_SESSION_RD_ATTR(password_in, ISCSI_USERNAME_IN); |
1440 | SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD); | 1441 | SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD); |
1441 | SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN); | 1442 | SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN); |
1443 | SETUP_SESSION_RD_ATTR(fast_abort, ISCSI_FAST_ABORT); | ||
1442 | SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo); | 1444 | SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo); |
1443 | 1445 | ||
1444 | BUG_ON(count > ISCSI_SESSION_ATTRS); | 1446 | BUG_ON(count > ISCSI_SESSION_ATTRS); |
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 50e907f42048..bff0b1f7857b 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h | |||
@@ -236,6 +236,7 @@ enum iscsi_param { | |||
236 | ISCSI_PARAM_PASSWORD, | 236 | ISCSI_PARAM_PASSWORD, |
237 | ISCSI_PARAM_PASSWORD_IN, | 237 | ISCSI_PARAM_PASSWORD_IN, |
238 | 238 | ||
239 | ISCSI_PARAM_FAST_ABORT, | ||
239 | /* must always be last */ | 240 | /* must always be last */ |
240 | ISCSI_PARAM_MAX, | 241 | ISCSI_PARAM_MAX, |
241 | }; | 242 | }; |
@@ -266,6 +267,7 @@ enum iscsi_param { | |||
266 | #define ISCSI_USERNAME_IN (1 << ISCSI_PARAM_USERNAME_IN) | 267 | #define ISCSI_USERNAME_IN (1 << ISCSI_PARAM_USERNAME_IN) |
267 | #define ISCSI_PASSWORD (1 << ISCSI_PARAM_PASSWORD) | 268 | #define ISCSI_PASSWORD (1 << ISCSI_PARAM_PASSWORD) |
268 | #define ISCSI_PASSWORD_IN (1 << ISCSI_PARAM_PASSWORD_IN) | 269 | #define ISCSI_PASSWORD_IN (1 << ISCSI_PARAM_PASSWORD_IN) |
270 | #define ISCSI_FAST_ABORT (1 << ISCSI_PARAM_FAST_ABORT) | ||
269 | 271 | ||
270 | /* iSCSI HBA params */ | 272 | /* iSCSI HBA params */ |
271 | enum iscsi_host_param { | 273 | enum iscsi_host_param { |
diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h index 8d1e4e8026fe..751c81eaa7f3 100644 --- a/include/scsi/iscsi_proto.h +++ b/include/scsi/iscsi_proto.h | |||
@@ -600,6 +600,8 @@ struct iscsi_reject { | |||
600 | #define ISCSI_MIN_MAX_BURST_LEN 512 | 600 | #define ISCSI_MIN_MAX_BURST_LEN 512 |
601 | #define ISCSI_MAX_MAX_BURST_LEN 16777215 | 601 | #define ISCSI_MAX_MAX_BURST_LEN 16777215 |
602 | 602 | ||
603 | #define ISCSI_DEF_TIME2WAIT 2 | ||
604 | |||
603 | /************************* RFC 3720 End *****************************/ | 605 | /************************* RFC 3720 End *****************************/ |
604 | 606 | ||
605 | #endif /* ISCSI_PROTO_H */ | 607 | #endif /* ISCSI_PROTO_H */ |
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index b4b31132618b..89429f433f85 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h | |||
@@ -57,11 +57,14 @@ struct iscsi_nopin; | |||
57 | #define ISCSI_MAX_CMD_PER_LUN 128 | 57 | #define ISCSI_MAX_CMD_PER_LUN 128 |
58 | 58 | ||
59 | /* Task Mgmt states */ | 59 | /* Task Mgmt states */ |
60 | #define TMABORT_INITIAL 0x0 | 60 | enum { |
61 | #define TMABORT_SUCCESS 0x1 | 61 | TMF_INITIAL, |
62 | #define TMABORT_FAILED 0x2 | 62 | TMF_QUEUED, |
63 | #define TMABORT_TIMEDOUT 0x3 | 63 | TMF_SUCCESS, |
64 | #define TMABORT_NOT_FOUND 0x4 | 64 | TMF_FAILED, |
65 | TMF_TIMEDOUT, | ||
66 | TMF_NOT_FOUND, | ||
67 | }; | ||
65 | 68 | ||
66 | /* Connection suspend "bit" */ | 69 | /* Connection suspend "bit" */ |
67 | #define ISCSI_SUSPEND_BIT 1 | 70 | #define ISCSI_SUSPEND_BIT 1 |
@@ -91,7 +94,6 @@ enum { | |||
91 | ISCSI_TASK_COMPLETED, | 94 | ISCSI_TASK_COMPLETED, |
92 | ISCSI_TASK_PENDING, | 95 | ISCSI_TASK_PENDING, |
93 | ISCSI_TASK_RUNNING, | 96 | ISCSI_TASK_RUNNING, |
94 | ISCSI_TASK_ABORTING, | ||
95 | }; | 97 | }; |
96 | 98 | ||
97 | struct iscsi_cmd_task { | 99 | struct iscsi_cmd_task { |
@@ -110,7 +112,6 @@ struct iscsi_cmd_task { | |||
110 | unsigned data_count; /* remaining Data-Out */ | 112 | unsigned data_count; /* remaining Data-Out */ |
111 | struct scsi_cmnd *sc; /* associated SCSI cmd*/ | 113 | struct scsi_cmnd *sc; /* associated SCSI cmd*/ |
112 | struct iscsi_conn *conn; /* used connection */ | 114 | struct iscsi_conn *conn; /* used connection */ |
113 | struct iscsi_mgmt_task *mtask; /* tmf mtask in progr */ | ||
114 | 115 | ||
115 | /* state set/tested under session->lock */ | 116 | /* state set/tested under session->lock */ |
116 | int state; | 117 | int state; |
@@ -152,10 +153,11 @@ struct iscsi_conn { | |||
152 | struct iscsi_cmd_task *ctask; /* xmit ctask in progress */ | 153 | struct iscsi_cmd_task *ctask; /* xmit ctask in progress */ |
153 | 154 | ||
154 | /* xmit */ | 155 | /* xmit */ |
155 | struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ | 156 | struct list_head mgmtqueue; /* mgmt (control) xmit queue */ |
156 | struct list_head mgmt_run_list; /* list of control tasks */ | 157 | struct list_head mgmt_run_list; /* list of control tasks */ |
157 | struct list_head xmitqueue; /* data-path cmd queue */ | 158 | struct list_head xmitqueue; /* data-path cmd queue */ |
158 | struct list_head run_list; /* list of cmds in progress */ | 159 | struct list_head run_list; /* list of cmds in progress */ |
160 | struct list_head requeue; /* tasks needing another run */ | ||
159 | struct work_struct xmitwork; /* per-conn. xmit workqueue */ | 161 | struct work_struct xmitwork; /* per-conn. xmit workqueue */ |
160 | unsigned long suspend_tx; /* suspend Tx */ | 162 | unsigned long suspend_tx; /* suspend Tx */ |
161 | unsigned long suspend_rx; /* suspend Rx */ | 163 | unsigned long suspend_rx; /* suspend Rx */ |
@@ -163,8 +165,8 @@ struct iscsi_conn { | |||
163 | /* abort */ | 165 | /* abort */ |
164 | wait_queue_head_t ehwait; /* used in eh_abort() */ | 166 | wait_queue_head_t ehwait; /* used in eh_abort() */ |
165 | struct iscsi_tm tmhdr; | 167 | struct iscsi_tm tmhdr; |
166 | struct timer_list tmabort_timer; | 168 | struct timer_list tmf_timer; |
167 | int tmabort_state; /* see TMABORT_INITIAL, etc.*/ | 169 | int tmf_state; /* see TMF_INITIAL, etc.*/ |
168 | 170 | ||
169 | /* negotiated params */ | 171 | /* negotiated params */ |
170 | unsigned max_recv_dlength; /* initiator_max_recv_dsl*/ | 172 | unsigned max_recv_dlength; /* initiator_max_recv_dsl*/ |
@@ -231,6 +233,7 @@ struct iscsi_session { | |||
231 | int pdu_inorder_en; | 233 | int pdu_inorder_en; |
232 | int dataseq_inorder_en; | 234 | int dataseq_inorder_en; |
233 | int erl; | 235 | int erl; |
236 | int fast_abort; | ||
234 | int tpgt; | 237 | int tpgt; |
235 | char *username; | 238 | char *username; |
236 | char *username_in; | 239 | char *username_in; |
@@ -268,6 +271,7 @@ struct iscsi_session { | |||
268 | extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth); | 271 | extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth); |
269 | extern int iscsi_eh_abort(struct scsi_cmnd *sc); | 272 | extern int iscsi_eh_abort(struct scsi_cmnd *sc); |
270 | extern int iscsi_eh_host_reset(struct scsi_cmnd *sc); | 273 | extern int iscsi_eh_host_reset(struct scsi_cmnd *sc); |
274 | extern int iscsi_eh_device_reset(struct scsi_cmnd *sc); | ||
271 | extern int iscsi_queuecommand(struct scsi_cmnd *sc, | 275 | extern int iscsi_queuecommand(struct scsi_cmnd *sc, |
272 | void (*done)(struct scsi_cmnd *)); | 276 | void (*done)(struct scsi_cmnd *)); |
273 | 277 | ||
@@ -326,6 +330,7 @@ extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *, | |||
326 | char *, int); | 330 | char *, int); |
327 | extern int iscsi_verify_itt(struct iscsi_conn *, struct iscsi_hdr *, | 331 | extern int iscsi_verify_itt(struct iscsi_conn *, struct iscsi_hdr *, |
328 | uint32_t *); | 332 | uint32_t *); |
333 | extern void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask); | ||
329 | 334 | ||
330 | /* | 335 | /* |
331 | * generic helpers | 336 | * generic helpers |