aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c4
-rw-r--r--drivers/scsi/iscsi_tcp.c4
-rw-r--r--drivers/scsi/libiscsi.c331
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c4
-rw-r--r--include/scsi/iscsi_if.h11
-rw-r--r--include/scsi/libiscsi.h8
6 files changed, 294 insertions, 68 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index a2622f4bd858..265606422278 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -577,7 +577,9 @@ static struct iscsi_transport iscsi_iser_transport = {
577 ISCSI_PERSISTENT_ADDRESS | 577 ISCSI_PERSISTENT_ADDRESS |
578 ISCSI_TARGET_NAME | ISCSI_TPGT | 578 ISCSI_TARGET_NAME | ISCSI_TPGT |
579 ISCSI_USERNAME | ISCSI_PASSWORD | 579 ISCSI_USERNAME | ISCSI_PASSWORD |
580 ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN, 580 ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
581 ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
582 ISCSI_PING_TMO | ISCSI_RECV_TMO,
581 .host_param_mask = ISCSI_HOST_HWADDRESS | 583 .host_param_mask = ISCSI_HOST_HWADDRESS |
582 ISCSI_HOST_NETDEV_NAME | 584 ISCSI_HOST_NETDEV_NAME |
583 ISCSI_HOST_INITIATOR_NAME, 585 ISCSI_HOST_INITIATOR_NAME,
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 90eae8e0d978..9b418522c9bf 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -2246,7 +2246,9 @@ static struct iscsi_transport iscsi_tcp_transport = {
2246 ISCSI_TARGET_NAME | ISCSI_TPGT | 2246 ISCSI_TARGET_NAME | ISCSI_TPGT |
2247 ISCSI_USERNAME | ISCSI_PASSWORD | 2247 ISCSI_USERNAME | ISCSI_PASSWORD |
2248 ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN | 2248 ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
2249 ISCSI_FAST_ABORT, 2249 ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
2250 ISCSI_LU_RESET_TMO |
2251 ISCSI_PING_TMO | ISCSI_RECV_TMO,
2250 .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | 2252 .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |
2251 ISCSI_HOST_INITIATOR_NAME | 2253 ISCSI_HOST_INITIATOR_NAME |
2252 ISCSI_HOST_NETDEV_NAME, 2254 ISCSI_HOST_NETDEV_NAME,
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 5205ef2c29b2..96883614ba08 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -313,11 +313,70 @@ void iscsi_free_mgmt_task(struct iscsi_conn *conn,
313 list_del_init(&mtask->running); 313 list_del_init(&mtask->running);
314 if (conn->login_mtask == mtask) 314 if (conn->login_mtask == mtask)
315 return; 315 return;
316
317 if (conn->ping_mtask == mtask)
318 conn->ping_mtask = NULL;
316 __kfifo_put(conn->session->mgmtpool.queue, 319 __kfifo_put(conn->session->mgmtpool.queue,
317 (void*)&mtask, sizeof(void*)); 320 (void*)&mtask, sizeof(void*));
318} 321}
319EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task); 322EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task);
320 323
324static struct iscsi_mgmt_task *
325__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
326 char *data, uint32_t data_size)
327{
328 struct iscsi_session *session = conn->session;
329 struct iscsi_mgmt_task *mtask;
330
331 if (session->state == ISCSI_STATE_TERMINATE)
332 return NULL;
333
334 if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
335 hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
336 /*
337 * Login and Text are sent serially, in
338 * request-followed-by-response sequence.
339 * Same mtask can be used. Same ITT must be used.
340 * Note that login_mtask is preallocated at conn_create().
341 */
342 mtask = conn->login_mtask;
343 else {
344 BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
345 BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
346
347 if (!__kfifo_get(session->mgmtpool.queue,
348 (void*)&mtask, sizeof(void*)))
349 return NULL;
350 }
351
352 if (data_size) {
353 memcpy(mtask->data, data, data_size);
354 mtask->data_count = data_size;
355 } else
356 mtask->data_count = 0;
357
358 memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
359 INIT_LIST_HEAD(&mtask->running);
360 list_add_tail(&mtask->running, &conn->mgmtqueue);
361 return mtask;
362}
363
364int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
365 char *data, uint32_t data_size)
366{
367 struct iscsi_conn *conn = cls_conn->dd_data;
368 struct iscsi_session *session = conn->session;
369 int err = 0;
370
371 spin_lock_bh(&session->lock);
372 if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size))
373 err = -EPERM;
374 spin_unlock_bh(&session->lock);
375 scsi_queue_work(session->host, &conn->xmitwork);
376 return err;
377}
378EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
379
321/** 380/**
322 * iscsi_cmd_rsp - SCSI Command Response processing 381 * iscsi_cmd_rsp - SCSI Command Response processing
323 * @conn: iscsi connection 382 * @conn: iscsi connection
@@ -409,6 +468,39 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
409 wake_up(&conn->ehwait); 468 wake_up(&conn->ehwait);
410} 469}
411 470
471static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
472{
473 struct iscsi_nopout hdr;
474 struct iscsi_mgmt_task *mtask;
475
476 if (!rhdr && conn->ping_mtask)
477 return;
478
479 memset(&hdr, 0, sizeof(struct iscsi_nopout));
480 hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
481 hdr.flags = ISCSI_FLAG_CMD_FINAL;
482
483 if (rhdr) {
484 memcpy(hdr.lun, rhdr->lun, 8);
485 hdr.ttt = rhdr->ttt;
486 hdr.itt = RESERVED_ITT;
487 } else
488 hdr.ttt = RESERVED_ITT;
489
490 mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
491 if (!mtask) {
492 printk(KERN_ERR "Could not send nopout\n");
493 return;
494 }
495
496 /* only track our nops */
497 if (!rhdr) {
498 conn->ping_mtask = mtask;
499 conn->last_ping = jiffies;
500 }
501 scsi_queue_work(conn->session->host, &conn->xmitwork);
502}
503
412static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, 504static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
413 char *data, int datalen) 505 char *data, int datalen)
414{ 506{
@@ -453,6 +545,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
453 struct iscsi_mgmt_task *mtask; 545 struct iscsi_mgmt_task *mtask;
454 uint32_t itt; 546 uint32_t itt;
455 547
548 conn->last_recv = jiffies;
456 if (hdr->itt != RESERVED_ITT) 549 if (hdr->itt != RESERVED_ITT)
457 itt = get_itt(hdr->itt); 550 itt = get_itt(hdr->itt);
458 else 551 else
@@ -520,14 +613,22 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
520 iscsi_free_mgmt_task(conn, mtask); 613 iscsi_free_mgmt_task(conn, mtask);
521 break; 614 break;
522 case ISCSI_OP_NOOP_IN: 615 case ISCSI_OP_NOOP_IN:
523 if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) || datalen) { 616 if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) ||
617 datalen) {
524 rc = ISCSI_ERR_PROTO; 618 rc = ISCSI_ERR_PROTO;
525 break; 619 break;
526 } 620 }
527 conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; 621 conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
528 622
529 if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) 623 if (conn->ping_mtask != mtask) {
530 rc = ISCSI_ERR_CONN_FAILED; 624 /*
625 * If this is not in response to one of our
626 * nops then it must be from userspace.
627 */
628 if (iscsi_recv_pdu(conn->cls_conn, hdr, data,
629 datalen))
630 rc = ISCSI_ERR_CONN_FAILED;
631 }
531 iscsi_free_mgmt_task(conn, mtask); 632 iscsi_free_mgmt_task(conn, mtask);
532 break; 633 break;
533 default: 634 default:
@@ -547,8 +648,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
547 if (hdr->ttt == cpu_to_be32(ISCSI_RESERVED_TAG)) 648 if (hdr->ttt == cpu_to_be32(ISCSI_RESERVED_TAG))
548 break; 649 break;
549 650
550 if (iscsi_recv_pdu(conn->cls_conn, hdr, NULL, 0)) 651 iscsi_send_nopout(conn, (struct iscsi_nopin*)hdr);
551 rc = ISCSI_ERR_CONN_FAILED;
552 break; 652 break;
553 case ISCSI_OP_REJECT: 653 case ISCSI_OP_REJECT:
554 rc = iscsi_handle_reject(conn, hdr, data, datalen); 654 rc = iscsi_handle_reject(conn, hdr, data, datalen);
@@ -1003,62 +1103,6 @@ int iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
1003} 1103}
1004EXPORT_SYMBOL_GPL(iscsi_change_queue_depth); 1104EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
1005 1105
1006static struct iscsi_mgmt_task *
1007__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
1008 char *data, uint32_t data_size)
1009{
1010 struct iscsi_session *session = conn->session;
1011 struct iscsi_mgmt_task *mtask;
1012
1013 if (session->state == ISCSI_STATE_TERMINATE)
1014 return NULL;
1015
1016 if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
1017 hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
1018 /*
1019 * Login and Text are sent serially, in
1020 * request-followed-by-response sequence.
1021 * Same mtask can be used. Same ITT must be used.
1022 * Note that login_mtask is preallocated at conn_create().
1023 */
1024 mtask = conn->login_mtask;
1025 else {
1026 BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
1027 BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
1028
1029 if (!__kfifo_get(session->mgmtpool.queue,
1030 (void*)&mtask, sizeof(void*)))
1031 return NULL;
1032 }
1033
1034 if (data_size) {
1035 memcpy(mtask->data, data, data_size);
1036 mtask->data_count = data_size;
1037 } else
1038 mtask->data_count = 0;
1039
1040 memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
1041 INIT_LIST_HEAD(&mtask->running);
1042 list_add_tail(&mtask->running, &conn->mgmtqueue);
1043 return mtask;
1044}
1045
1046int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
1047 char *data, uint32_t data_size)
1048{
1049 struct iscsi_conn *conn = cls_conn->dd_data;
1050 struct iscsi_session *session = conn->session;
1051 int err = 0;
1052
1053 spin_lock_bh(&session->lock);
1054 if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size))
1055 err = -EPERM;
1056 spin_unlock_bh(&session->lock);
1057 scsi_queue_work(session->host, &conn->xmitwork);
1058 return err;
1059}
1060EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
1061
1062void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) 1106void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
1063{ 1107{
1064 struct iscsi_session *session = class_to_transport_session(cls_session); 1108 struct iscsi_session *session = class_to_transport_session(cls_session);
@@ -1134,7 +1178,8 @@ static void iscsi_tmf_timedout(unsigned long data)
1134} 1178}
1135 1179
1136static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, 1180static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
1137 struct iscsi_tm *hdr, int age) 1181 struct iscsi_tm *hdr, int age,
1182 int timeout)
1138{ 1183{
1139 struct iscsi_session *session = conn->session; 1184 struct iscsi_session *session = conn->session;
1140 struct iscsi_mgmt_task *mtask; 1185 struct iscsi_mgmt_task *mtask;
@@ -1149,7 +1194,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
1149 return -EPERM; 1194 return -EPERM;
1150 } 1195 }
1151 conn->tmfcmd_pdus_cnt++; 1196 conn->tmfcmd_pdus_cnt++;
1152 conn->tmf_timer.expires = 30 * HZ + jiffies; 1197 conn->tmf_timer.expires = timeout * HZ + jiffies;
1153 conn->tmf_timer.function = iscsi_tmf_timedout; 1198 conn->tmf_timer.function = iscsi_tmf_timedout;
1154 conn->tmf_timer.data = (unsigned long)conn; 1199 conn->tmf_timer.data = (unsigned long)conn;
1155 add_timer(&conn->tmf_timer); 1200 add_timer(&conn->tmf_timer);
@@ -1233,6 +1278,106 @@ static void iscsi_start_tx(struct iscsi_conn *conn)
1233 scsi_queue_work(conn->session->host, &conn->xmitwork); 1278 scsi_queue_work(conn->session->host, &conn->xmitwork);
1234} 1279}
1235 1280
1281static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
1282{
1283 struct iscsi_cls_session *cls_session;
1284 struct iscsi_session *session;
1285 struct iscsi_conn *conn;
1286 enum scsi_eh_timer_return rc = EH_NOT_HANDLED;
1287
1288 cls_session = starget_to_session(scsi_target(scmd->device));
1289 session = class_to_transport_session(cls_session);
1290
1291 debug_scsi("scsi cmd %p timedout\n", scmd);
1292
1293 spin_lock(&session->lock);
1294 if (session->state != ISCSI_STATE_LOGGED_IN) {
1295 /*
1296 * We are probably in the middle of iscsi recovery so let
1297 * that complete and handle the error.
1298 */
1299 rc = EH_RESET_TIMER;
1300 goto done;
1301 }
1302
1303 conn = session->leadconn;
1304 if (!conn) {
1305 /* In the middle of shuting down */
1306 rc = EH_RESET_TIMER;
1307 goto done;
1308 }
1309
1310 if (!conn->recv_timeout && !conn->ping_timeout)
1311 goto done;
1312 /*
1313 * if the ping timedout then we are in the middle of cleaning up
1314 * and can let the iscsi eh handle it
1315 */
1316 if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) +
1317 (conn->ping_timeout * HZ), jiffies))
1318 rc = EH_RESET_TIMER;
1319 /*
1320 * if we are about to check the transport then give the command
1321 * more time
1322 */
1323 if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ),
1324 jiffies))
1325 rc = EH_RESET_TIMER;
1326 /* if in the middle of checking the transport then give us more time */
1327 if (conn->ping_mtask)
1328 rc = EH_RESET_TIMER;
1329done:
1330 spin_unlock(&session->lock);
1331 debug_scsi("return %s\n", rc == EH_RESET_TIMER ? "timer reset" : "nh");
1332 return rc;
1333}
1334
1335static void iscsi_check_transport_timeouts(unsigned long data)
1336{
1337 struct iscsi_conn *conn = (struct iscsi_conn *)data;
1338 struct iscsi_session *session = conn->session;
1339 unsigned long timeout, next_timeout = 0, last_recv;
1340
1341 spin_lock(&session->lock);
1342 if (session->state != ISCSI_STATE_LOGGED_IN)
1343 goto done;
1344
1345 timeout = conn->recv_timeout;
1346 if (!timeout)
1347 goto done;
1348
1349 timeout *= HZ;
1350 last_recv = conn->last_recv;
1351 if (time_before_eq(last_recv + timeout + (conn->ping_timeout * HZ),
1352 jiffies)) {
1353 printk(KERN_ERR "ping timeout of %d secs expired, "
1354 "last rx %lu, last ping %lu, now %lu\n",
1355 conn->ping_timeout, last_recv,
1356 conn->last_ping, jiffies);
1357 spin_unlock(&session->lock);
1358 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
1359 return;
1360 }
1361
1362 if (time_before_eq(last_recv + timeout, jiffies)) {
1363 if (time_before_eq(conn->last_ping, last_recv)) {
1364 /* send a ping to try to provoke some traffic */
1365 debug_scsi("Sending nopout as ping on conn %p\n", conn);
1366 iscsi_send_nopout(conn, NULL);
1367 }
1368 next_timeout = last_recv + timeout + (conn->ping_timeout * HZ);
1369 } else {
1370 next_timeout = last_recv + timeout;
1371 }
1372
1373 if (next_timeout) {
1374 debug_scsi("Setting next tmo %lu\n", next_timeout);
1375 mod_timer(&conn->transport_timer, next_timeout);
1376 }
1377done:
1378 spin_unlock(&session->lock);
1379}
1380
1236static void iscsi_prep_abort_task_pdu(struct iscsi_cmd_task *ctask, 1381static void iscsi_prep_abort_task_pdu(struct iscsi_cmd_task *ctask,
1237 struct iscsi_tm *hdr) 1382 struct iscsi_tm *hdr)
1238{ 1383{
@@ -1304,7 +1449,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
1304 hdr = &conn->tmhdr; 1449 hdr = &conn->tmhdr;
1305 iscsi_prep_abort_task_pdu(ctask, hdr); 1450 iscsi_prep_abort_task_pdu(ctask, hdr);
1306 1451
1307 if (iscsi_exec_task_mgmt_fn(conn, hdr, age)) { 1452 if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) {
1308 rc = FAILED; 1453 rc = FAILED;
1309 goto failed; 1454 goto failed;
1310 } 1455 }
@@ -1365,7 +1510,7 @@ static void iscsi_prep_lun_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr)
1365 hdr->flags = ISCSI_TM_FUNC_LOGICAL_UNIT_RESET & ISCSI_FLAG_TM_FUNC_MASK; 1510 hdr->flags = ISCSI_TM_FUNC_LOGICAL_UNIT_RESET & ISCSI_FLAG_TM_FUNC_MASK;
1366 hdr->flags |= ISCSI_FLAG_CMD_FINAL; 1511 hdr->flags |= ISCSI_FLAG_CMD_FINAL;
1367 int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); 1512 int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
1368 hdr->rtt = ISCSI_RESERVED_TAG; 1513 hdr->rtt = RESERVED_ITT;
1369} 1514}
1370 1515
1371int iscsi_eh_device_reset(struct scsi_cmnd *sc) 1516int iscsi_eh_device_reset(struct scsi_cmnd *sc)
@@ -1396,7 +1541,8 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
1396 hdr = &conn->tmhdr; 1541 hdr = &conn->tmhdr;
1397 iscsi_prep_lun_reset_pdu(sc, hdr); 1542 iscsi_prep_lun_reset_pdu(sc, hdr);
1398 1543
1399 if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age)) { 1544 if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age,
1545 session->lu_reset_timeout)) {
1400 rc = FAILED; 1546 rc = FAILED;
1401 goto unlock; 1547 goto unlock;
1402 } 1548 }
@@ -1572,12 +1718,14 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
1572 shost->max_cmd_len = iscsit->max_cmd_len; 1718 shost->max_cmd_len = iscsit->max_cmd_len;
1573 shost->transportt = scsit; 1719 shost->transportt = scsit;
1574 shost->transportt->create_work_queue = 1; 1720 shost->transportt->create_work_queue = 1;
1721 shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
1575 *hostno = shost->host_no; 1722 *hostno = shost->host_no;
1576 1723
1577 session = iscsi_hostdata(shost->hostdata); 1724 session = iscsi_hostdata(shost->hostdata);
1578 memset(session, 0, sizeof(struct iscsi_session)); 1725 memset(session, 0, sizeof(struct iscsi_session));
1579 session->host = shost; 1726 session->host = shost;
1580 session->state = ISCSI_STATE_FREE; 1727 session->state = ISCSI_STATE_FREE;
1728 session->fast_abort = 1;
1581 session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; 1729 session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
1582 session->cmds_max = cmds_max; 1730 session->cmds_max = cmds_max;
1583 session->queued_cmdsn = session->cmdsn = initial_cmdsn; 1731 session->queued_cmdsn = session->cmdsn = initial_cmdsn;
@@ -1708,6 +1856,11 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
1708 conn->id = conn_idx; 1856 conn->id = conn_idx;
1709 conn->exp_statsn = 0; 1857 conn->exp_statsn = 0;
1710 conn->tmf_state = TMF_INITIAL; 1858 conn->tmf_state = TMF_INITIAL;
1859
1860 init_timer(&conn->transport_timer);
1861 conn->transport_timer.data = (unsigned long)conn;
1862 conn->transport_timer.function = iscsi_check_transport_timeouts;
1863
1711 INIT_LIST_HEAD(&conn->run_list); 1864 INIT_LIST_HEAD(&conn->run_list);
1712 INIT_LIST_HEAD(&conn->mgmt_run_list); 1865 INIT_LIST_HEAD(&conn->mgmt_run_list);
1713 INIT_LIST_HEAD(&conn->mgmtqueue); 1866 INIT_LIST_HEAD(&conn->mgmtqueue);
@@ -1757,6 +1910,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
1757 struct iscsi_session *session = conn->session; 1910 struct iscsi_session *session = conn->session;
1758 unsigned long flags; 1911 unsigned long flags;
1759 1912
1913 del_timer_sync(&conn->transport_timer);
1914
1760 spin_lock_bh(&session->lock); 1915 spin_lock_bh(&session->lock);
1761 conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; 1916 conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
1762 if (session->leadconn == conn) { 1917 if (session->leadconn == conn) {
@@ -1823,11 +1978,29 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
1823 return -EINVAL; 1978 return -EINVAL;
1824 } 1979 }
1825 1980
1981 if (conn->ping_timeout && !conn->recv_timeout) {
1982 printk(KERN_ERR "iscsi: invalid recv timeout of zero "
1983 "Using 5 seconds\n.");
1984 conn->recv_timeout = 5;
1985 }
1986
1987 if (conn->recv_timeout && !conn->ping_timeout) {
1988 printk(KERN_ERR "iscsi: invalid ping timeout of zero "
1989 "Using 5 seconds.\n");
1990 conn->ping_timeout = 5;
1991 }
1992
1826 spin_lock_bh(&session->lock); 1993 spin_lock_bh(&session->lock);
1827 conn->c_stage = ISCSI_CONN_STARTED; 1994 conn->c_stage = ISCSI_CONN_STARTED;
1828 session->state = ISCSI_STATE_LOGGED_IN; 1995 session->state = ISCSI_STATE_LOGGED_IN;
1829 session->queued_cmdsn = session->cmdsn; 1996 session->queued_cmdsn = session->cmdsn;
1830 1997
1998 conn->last_recv = jiffies;
1999 conn->last_ping = jiffies;
2000 if (conn->recv_timeout && conn->ping_timeout)
2001 mod_timer(&conn->transport_timer,
2002 jiffies + (conn->recv_timeout * HZ));
2003
1831 switch(conn->stop_stage) { 2004 switch(conn->stop_stage) {
1832 case STOP_CONN_RECOVER: 2005 case STOP_CONN_RECOVER:
1833 /* 2006 /*
@@ -1879,6 +2052,8 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
1879{ 2052{
1880 int old_stop_stage; 2053 int old_stop_stage;
1881 2054
2055 del_timer_sync(&conn->transport_timer);
2056
1882 mutex_lock(&session->eh_mutex); 2057 mutex_lock(&session->eh_mutex);
1883 spin_lock_bh(&session->lock); 2058 spin_lock_bh(&session->lock);
1884 if (conn->stop_stage == STOP_CONN_TERM) { 2059 if (conn->stop_stage == STOP_CONN_TERM) {
@@ -1993,6 +2168,18 @@ int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
1993 case ISCSI_PARAM_FAST_ABORT: 2168 case ISCSI_PARAM_FAST_ABORT:
1994 sscanf(buf, "%d", &session->fast_abort); 2169 sscanf(buf, "%d", &session->fast_abort);
1995 break; 2170 break;
2171 case ISCSI_PARAM_ABORT_TMO:
2172 sscanf(buf, "%d", &session->abort_timeout);
2173 break;
2174 case ISCSI_PARAM_LU_RESET_TMO:
2175 sscanf(buf, "%d", &session->lu_reset_timeout);
2176 break;
2177 case ISCSI_PARAM_PING_TMO:
2178 sscanf(buf, "%d", &conn->ping_timeout);
2179 break;
2180 case ISCSI_PARAM_RECV_TMO:
2181 sscanf(buf, "%d", &conn->recv_timeout);
2182 break;
1996 case ISCSI_PARAM_MAX_RECV_DLENGTH: 2183 case ISCSI_PARAM_MAX_RECV_DLENGTH:
1997 sscanf(buf, "%d", &conn->max_recv_dlength); 2184 sscanf(buf, "%d", &conn->max_recv_dlength);
1998 break; 2185 break;
@@ -2110,6 +2297,12 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
2110 case ISCSI_PARAM_FAST_ABORT: 2297 case ISCSI_PARAM_FAST_ABORT:
2111 len = sprintf(buf, "%d\n", session->fast_abort); 2298 len = sprintf(buf, "%d\n", session->fast_abort);
2112 break; 2299 break;
2300 case ISCSI_PARAM_ABORT_TMO:
2301 len = sprintf(buf, "%d\n", session->abort_timeout);
2302 break;
2303 case ISCSI_PARAM_LU_RESET_TMO:
2304 len = sprintf(buf, "%d\n", session->lu_reset_timeout);
2305 break;
2113 case ISCSI_PARAM_INITIAL_R2T_EN: 2306 case ISCSI_PARAM_INITIAL_R2T_EN:
2114 len = sprintf(buf, "%d\n", session->initial_r2t_en); 2307 len = sprintf(buf, "%d\n", session->initial_r2t_en);
2115 break; 2308 break;
@@ -2167,6 +2360,12 @@ int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
2167 int len; 2360 int len;
2168 2361
2169 switch(param) { 2362 switch(param) {
2363 case ISCSI_PARAM_PING_TMO:
2364 len = sprintf(buf, "%u\n", conn->ping_timeout);
2365 break;
2366 case ISCSI_PARAM_RECV_TMO:
2367 len = sprintf(buf, "%u\n", conn->recv_timeout);
2368 break;
2170 case ISCSI_PARAM_MAX_RECV_DLENGTH: 2369 case ISCSI_PARAM_MAX_RECV_DLENGTH:
2171 len = sprintf(buf, "%u\n", conn->max_recv_dlength); 2370 len = sprintf(buf, "%u\n", conn->max_recv_dlength);
2172 break; 2371 break;
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index b82139dc4830..36aa50e45ec7 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1202,6 +1202,8 @@ iscsi_conn_attr(port, ISCSI_PARAM_CONN_PORT);
1202iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN); 1202iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
1203iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS); 1203iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
1204iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS); 1204iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS);
1205iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO);
1206iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO);
1205 1207
1206#define iscsi_cdev_to_session(_cdev) \ 1208#define iscsi_cdev_to_session(_cdev) \
1207 iscsi_dev_to_session(_cdev->dev) 1209 iscsi_dev_to_session(_cdev->dev)
@@ -1437,6 +1439,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
1437 SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN); 1439 SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN);
1438 SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS); 1440 SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS);
1439 SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT); 1441 SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT);
1442 SETUP_CONN_RD_ATTR(ping_tmo, ISCSI_PING_TMO);
1443 SETUP_CONN_RD_ATTR(recv_tmo, ISCSI_RECV_TMO);
1440 1444
1441 BUG_ON(count > ISCSI_CONN_ATTRS); 1445 BUG_ON(count > ISCSI_CONN_ATTRS);
1442 priv->conn_attrs[count] = NULL; 1446 priv->conn_attrs[count] = NULL;
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index 8a4426df6c3a..e19e58423166 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -244,6 +244,12 @@ enum iscsi_param {
244 ISCSI_PARAM_PASSWORD_IN, 244 ISCSI_PARAM_PASSWORD_IN,
245 245
246 ISCSI_PARAM_FAST_ABORT, 246 ISCSI_PARAM_FAST_ABORT,
247 ISCSI_PARAM_ABORT_TMO,
248 ISCSI_PARAM_LU_RESET_TMO,
249 ISCSI_PARAM_HOST_RESET_TMO,
250
251 ISCSI_PARAM_PING_TMO,
252 ISCSI_PARAM_RECV_TMO,
247 /* must always be last */ 253 /* must always be last */
248 ISCSI_PARAM_MAX, 254 ISCSI_PARAM_MAX,
249}; 255};
@@ -275,6 +281,11 @@ enum iscsi_param {
275#define ISCSI_PASSWORD (1 << ISCSI_PARAM_PASSWORD) 281#define ISCSI_PASSWORD (1 << ISCSI_PARAM_PASSWORD)
276#define ISCSI_PASSWORD_IN (1 << ISCSI_PARAM_PASSWORD_IN) 282#define ISCSI_PASSWORD_IN (1 << ISCSI_PARAM_PASSWORD_IN)
277#define ISCSI_FAST_ABORT (1 << ISCSI_PARAM_FAST_ABORT) 283#define ISCSI_FAST_ABORT (1 << ISCSI_PARAM_FAST_ABORT)
284#define ISCSI_ABORT_TMO (1 << ISCSI_PARAM_ABORT_TMO)
285#define ISCSI_LU_RESET_TMO (1 << ISCSI_PARAM_LU_RESET_TMO)
286#define ISCSI_HOST_RESET_TMO (1 << ISCSI_PARAM_HOST_RESET_TMO)
287#define ISCSI_PING_TMO (1 << ISCSI_PARAM_PING_TMO)
288#define ISCSI_RECV_TMO (1 << ISCSI_PARAM_RECV_TMO)
278 289
279/* iSCSI HBA params */ 290/* iSCSI HBA params */
280enum iscsi_host_param { 291enum iscsi_host_param {
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index d68f74523f2e..889f51fabab9 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -148,6 +148,12 @@ struct iscsi_conn {
148 * conn_stop() flag: stop to recover, stop to terminate 148 * conn_stop() flag: stop to recover, stop to terminate
149 */ 149 */
150 int stop_stage; 150 int stop_stage;
151 struct timer_list transport_timer;
152 unsigned long last_recv;
153 unsigned long last_ping;
154 int ping_timeout;
155 int recv_timeout;
156 struct iscsi_mgmt_task *ping_mtask;
151 157
152 /* iSCSI connection-wide sequencing */ 158 /* iSCSI connection-wide sequencing */
153 uint32_t exp_statsn; 159 uint32_t exp_statsn;
@@ -238,6 +244,8 @@ struct iscsi_session {
238 uint32_t queued_cmdsn; 244 uint32_t queued_cmdsn;
239 245
240 /* configuration */ 246 /* configuration */
247 int abort_timeout;
248 int lu_reset_timeout;
241 int initial_r2t_en; 249 int initial_r2t_en;
242 unsigned max_r2t; 250 unsigned max_r2t;
243 int imm_data_en; 251 int imm_data_en;