diff options
author | john fastabend <john.r.fastabend@intel.com> | 2010-11-30 19:18:44 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-12-21 13:24:22 -0500 |
commit | e0883a3c3e7766b390971a49bf728004816c9520 (patch) | |
tree | 503e3ad2aa159def3f97e8001338bfeab4649b2f /drivers/scsi | |
parent | ac17ea8d7d45d0495316edff13faa0dfd6bb2225 (diff) |
[SCSI] libfc: use rport timeout values for fcp recovery
Use the rport value for rec_tov for timeout values when
sending fcp commands. Currently, defaults are being used
which may or may not match the advertised values.
The default may cause i/o to timeout on networks that
set this value larger then the default value. To make
the timeout more configurable in the non-REC mode we
remove the FC_SCSI_ER_TIMEOUT completely allowing the
scsi-ml to do the timeout. This removes an unneeded
timer and allows the i/o timeout to be configured
using the scsi-ml knobs.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/libfc/fc_fcp.c | 58 |
1 files changed, 42 insertions, 16 deletions
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 8eb67676d0dd..a7d956ad16e3 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c | |||
@@ -57,6 +57,9 @@ struct kmem_cache *scsi_pkt_cachep; | |||
57 | #define FC_SRB_READ (1 << 1) | 57 | #define FC_SRB_READ (1 << 1) |
58 | #define FC_SRB_WRITE (1 << 0) | 58 | #define FC_SRB_WRITE (1 << 0) |
59 | 59 | ||
60 | /* constant added to e_d_tov timeout to get rec_tov value */ | ||
61 | #define REC_TOV_CONST 1 | ||
62 | |||
60 | /* | 63 | /* |
61 | * The SCp.ptr should be tested and set under the scsi_pkt_queue lock | 64 | * The SCp.ptr should be tested and set under the scsi_pkt_queue lock |
62 | */ | 65 | */ |
@@ -126,9 +129,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *); | |||
126 | /* | 129 | /* |
127 | * Error recovery timeout values. | 130 | * Error recovery timeout values. |
128 | */ | 131 | */ |
129 | #define FC_SCSI_ER_TIMEOUT (10 * HZ) | ||
130 | #define FC_SCSI_TM_TOV (10 * HZ) | 132 | #define FC_SCSI_TM_TOV (10 * HZ) |
131 | #define FC_SCSI_REC_TOV (2 * HZ) | ||
132 | #define FC_HOST_RESET_TIMEOUT (30 * HZ) | 133 | #define FC_HOST_RESET_TIMEOUT (30 * HZ) |
133 | #define FC_CAN_QUEUE_PERIOD (60 * HZ) | 134 | #define FC_CAN_QUEUE_PERIOD (60 * HZ) |
134 | 135 | ||
@@ -1083,6 +1084,21 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp) | |||
1083 | } | 1084 | } |
1084 | 1085 | ||
1085 | /** | 1086 | /** |
1087 | * get_fsp_rec_tov() - Helper function to get REC_TOV | ||
1088 | * @fsp: the FCP packet | ||
1089 | */ | ||
1090 | static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp) | ||
1091 | { | ||
1092 | struct fc_rport *rport; | ||
1093 | struct fc_rport_libfc_priv *rpriv; | ||
1094 | |||
1095 | rport = fsp->rport; | ||
1096 | rpriv = rport->dd_data; | ||
1097 | |||
1098 | return rpriv->e_d_tov + REC_TOV_CONST; | ||
1099 | } | ||
1100 | |||
1101 | /** | ||
1086 | * fc_fcp_cmd_send() - Send a FCP command | 1102 | * fc_fcp_cmd_send() - Send a FCP command |
1087 | * @lport: The local port to send the command on | 1103 | * @lport: The local port to send the command on |
1088 | * @fsp: The FCP packet the command is on | 1104 | * @fsp: The FCP packet the command is on |
@@ -1099,6 +1115,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp, | |||
1099 | struct fc_rport_libfc_priv *rpriv; | 1115 | struct fc_rport_libfc_priv *rpriv; |
1100 | const size_t len = sizeof(fsp->cdb_cmd); | 1116 | const size_t len = sizeof(fsp->cdb_cmd); |
1101 | int rc = 0; | 1117 | int rc = 0; |
1118 | unsigned int rec_tov; | ||
1102 | 1119 | ||
1103 | if (fc_fcp_lock_pkt(fsp)) | 1120 | if (fc_fcp_lock_pkt(fsp)) |
1104 | return 0; | 1121 | return 0; |
@@ -1129,10 +1146,12 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp, | |||
1129 | fsp->seq_ptr = seq; | 1146 | fsp->seq_ptr = seq; |
1130 | fc_fcp_pkt_hold(fsp); /* hold for fc_fcp_pkt_destroy */ | 1147 | fc_fcp_pkt_hold(fsp); /* hold for fc_fcp_pkt_destroy */ |
1131 | 1148 | ||
1149 | rec_tov = get_fsp_rec_tov(fsp); | ||
1150 | |||
1132 | setup_timer(&fsp->timer, fc_fcp_timeout, (unsigned long)fsp); | 1151 | setup_timer(&fsp->timer, fc_fcp_timeout, (unsigned long)fsp); |
1133 | fc_fcp_timer_set(fsp, | 1152 | |
1134 | (fsp->tgt_flags & FC_RP_FLAGS_REC_SUPPORTED) ? | 1153 | if (fsp->tgt_flags & FC_RP_FLAGS_REC_SUPPORTED) |
1135 | FC_SCSI_REC_TOV : FC_SCSI_ER_TIMEOUT); | 1154 | fc_fcp_timer_set(fsp, rec_tov); |
1136 | unlock: | 1155 | unlock: |
1137 | fc_fcp_unlock_pkt(fsp); | 1156 | fc_fcp_unlock_pkt(fsp); |
1138 | return rc; | 1157 | return rc; |
@@ -1207,13 +1226,16 @@ static void fc_lun_reset_send(unsigned long data) | |||
1207 | { | 1226 | { |
1208 | struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)data; | 1227 | struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)data; |
1209 | struct fc_lport *lport = fsp->lp; | 1228 | struct fc_lport *lport = fsp->lp; |
1229 | unsigned int rec_tov; | ||
1230 | |||
1210 | if (lport->tt.fcp_cmd_send(lport, fsp, fc_tm_done)) { | 1231 | if (lport->tt.fcp_cmd_send(lport, fsp, fc_tm_done)) { |
1211 | if (fsp->recov_retry++ >= FC_MAX_RECOV_RETRY) | 1232 | if (fsp->recov_retry++ >= FC_MAX_RECOV_RETRY) |
1212 | return; | 1233 | return; |
1213 | if (fc_fcp_lock_pkt(fsp)) | 1234 | if (fc_fcp_lock_pkt(fsp)) |
1214 | return; | 1235 | return; |
1236 | rec_tov = get_fsp_rec_tov(fsp); | ||
1215 | setup_timer(&fsp->timer, fc_lun_reset_send, (unsigned long)fsp); | 1237 | setup_timer(&fsp->timer, fc_lun_reset_send, (unsigned long)fsp); |
1216 | fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV); | 1238 | fc_fcp_timer_set(fsp, rec_tov); |
1217 | fc_fcp_unlock_pkt(fsp); | 1239 | fc_fcp_unlock_pkt(fsp); |
1218 | } | 1240 | } |
1219 | } | 1241 | } |
@@ -1351,9 +1373,6 @@ static void fc_fcp_timeout(unsigned long data) | |||
1351 | 1373 | ||
1352 | if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED) | 1374 | if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED) |
1353 | fc_fcp_rec(fsp); | 1375 | fc_fcp_rec(fsp); |
1354 | else if (time_after_eq(fsp->last_pkt_time + (FC_SCSI_ER_TIMEOUT / 2), | ||
1355 | jiffies)) | ||
1356 | fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT); | ||
1357 | else if (fsp->state & FC_SRB_RCV_STATUS) | 1376 | else if (fsp->state & FC_SRB_RCV_STATUS) |
1358 | fc_fcp_complete_locked(fsp); | 1377 | fc_fcp_complete_locked(fsp); |
1359 | else | 1378 | else |
@@ -1373,6 +1392,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) | |||
1373 | struct fc_frame *fp; | 1392 | struct fc_frame *fp; |
1374 | struct fc_rport *rport; | 1393 | struct fc_rport *rport; |
1375 | struct fc_rport_libfc_priv *rpriv; | 1394 | struct fc_rport_libfc_priv *rpriv; |
1395 | unsigned int rec_tov; | ||
1376 | 1396 | ||
1377 | lport = fsp->lp; | 1397 | lport = fsp->lp; |
1378 | rport = fsp->rport; | 1398 | rport = fsp->rport; |
@@ -1383,6 +1403,9 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) | |||
1383 | fc_fcp_complete_locked(fsp); | 1403 | fc_fcp_complete_locked(fsp); |
1384 | return; | 1404 | return; |
1385 | } | 1405 | } |
1406 | |||
1407 | rec_tov = get_fsp_rec_tov(fsp); | ||
1408 | |||
1386 | fp = fc_fcp_frame_alloc(lport, sizeof(struct fc_els_rec)); | 1409 | fp = fc_fcp_frame_alloc(lport, sizeof(struct fc_els_rec)); |
1387 | if (!fp) | 1410 | if (!fp) |
1388 | goto retry; | 1411 | goto retry; |
@@ -1393,13 +1416,13 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) | |||
1393 | FC_FCTL_REQ, 0); | 1416 | FC_FCTL_REQ, 0); |
1394 | if (lport->tt.elsct_send(lport, rport->port_id, fp, ELS_REC, | 1417 | if (lport->tt.elsct_send(lport, rport->port_id, fp, ELS_REC, |
1395 | fc_fcp_rec_resp, fsp, | 1418 | fc_fcp_rec_resp, fsp, |
1396 | jiffies_to_msecs(FC_SCSI_REC_TOV))) { | 1419 | jiffies_to_msecs(rec_tov))) { |
1397 | fc_fcp_pkt_hold(fsp); /* hold while REC outstanding */ | 1420 | fc_fcp_pkt_hold(fsp); /* hold while REC outstanding */ |
1398 | return; | 1421 | return; |
1399 | } | 1422 | } |
1400 | retry: | 1423 | retry: |
1401 | if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) | 1424 | if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) |
1402 | fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV); | 1425 | fc_fcp_timer_set(fsp, rec_tov); |
1403 | else | 1426 | else |
1404 | fc_fcp_recovery(fsp, FC_TIMED_OUT); | 1427 | fc_fcp_recovery(fsp, FC_TIMED_OUT); |
1405 | } | 1428 | } |
@@ -1455,7 +1478,6 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) | |||
1455 | * making progress. | 1478 | * making progress. |
1456 | */ | 1479 | */ |
1457 | rpriv->flags &= ~FC_RP_FLAGS_REC_SUPPORTED; | 1480 | rpriv->flags &= ~FC_RP_FLAGS_REC_SUPPORTED; |
1458 | fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT); | ||
1459 | break; | 1481 | break; |
1460 | case ELS_RJT_LOGIC: | 1482 | case ELS_RJT_LOGIC: |
1461 | case ELS_RJT_UNAB: | 1483 | case ELS_RJT_UNAB: |
@@ -1508,12 +1530,12 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) | |||
1508 | } | 1530 | } |
1509 | fc_fcp_srr(fsp, r_ctl, offset); | 1531 | fc_fcp_srr(fsp, r_ctl, offset); |
1510 | } else if (e_stat & ESB_ST_SEQ_INIT) { | 1532 | } else if (e_stat & ESB_ST_SEQ_INIT) { |
1511 | 1533 | unsigned int rec_tov = get_fsp_rec_tov(fsp); | |
1512 | /* | 1534 | /* |
1513 | * The remote port has the initiative, so just | 1535 | * The remote port has the initiative, so just |
1514 | * keep waiting for it to complete. | 1536 | * keep waiting for it to complete. |
1515 | */ | 1537 | */ |
1516 | fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV); | 1538 | fc_fcp_timer_set(fsp, rec_tov); |
1517 | } else { | 1539 | } else { |
1518 | 1540 | ||
1519 | /* | 1541 | /* |
@@ -1626,6 +1648,7 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) | |||
1626 | struct fcp_srr *srr; | 1648 | struct fcp_srr *srr; |
1627 | struct fc_frame *fp; | 1649 | struct fc_frame *fp; |
1628 | u8 cdb_op; | 1650 | u8 cdb_op; |
1651 | unsigned int rec_tov; | ||
1629 | 1652 | ||
1630 | rport = fsp->rport; | 1653 | rport = fsp->rport; |
1631 | rpriv = rport->dd_data; | 1654 | rpriv = rport->dd_data; |
@@ -1650,8 +1673,9 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) | |||
1650 | rpriv->local_port->port_id, FC_TYPE_FCP, | 1673 | rpriv->local_port->port_id, FC_TYPE_FCP, |
1651 | FC_FCTL_REQ, 0); | 1674 | FC_FCTL_REQ, 0); |
1652 | 1675 | ||
1676 | rec_tov = get_fsp_rec_tov(fsp); | ||
1653 | seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL, | 1677 | seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL, |
1654 | fsp, jiffies_to_msecs(FC_SCSI_REC_TOV)); | 1678 | fsp, jiffies_to_msecs(rec_tov)); |
1655 | if (!seq) | 1679 | if (!seq) |
1656 | goto retry; | 1680 | goto retry; |
1657 | 1681 | ||
@@ -1675,6 +1699,7 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) | |||
1675 | { | 1699 | { |
1676 | struct fc_fcp_pkt *fsp = arg; | 1700 | struct fc_fcp_pkt *fsp = arg; |
1677 | struct fc_frame_header *fh; | 1701 | struct fc_frame_header *fh; |
1702 | unsigned int rec_tov; | ||
1678 | 1703 | ||
1679 | if (IS_ERR(fp)) { | 1704 | if (IS_ERR(fp)) { |
1680 | fc_fcp_srr_error(fsp, fp); | 1705 | fc_fcp_srr_error(fsp, fp); |
@@ -1701,7 +1726,8 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) | |||
1701 | switch (fc_frame_payload_op(fp)) { | 1726 | switch (fc_frame_payload_op(fp)) { |
1702 | case ELS_LS_ACC: | 1727 | case ELS_LS_ACC: |
1703 | fsp->recov_retry = 0; | 1728 | fsp->recov_retry = 0; |
1704 | fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV); | 1729 | rec_tov = get_fsp_rec_tov(fsp); |
1730 | fc_fcp_timer_set(fsp, rec_tov); | ||
1705 | break; | 1731 | break; |
1706 | case ELS_LS_RJT: | 1732 | case ELS_LS_RJT: |
1707 | default: | 1733 | default: |