diff options
author | James Smart <James.Smart@Emulex.Com> | 2006-08-18 17:47:08 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-09-04 22:25:21 -0400 |
commit | c01f32087960edd60a302ad62ad6b8b525e4aeec (patch) | |
tree | abefc5afc051d379802de42175e14df37d79b4ae /drivers/scsi/lpfc/lpfc_hbadisc.c | |
parent | 0f29b966d60e9a4f5ecff9f3832257b38aea4f13 (diff) |
[SCSI] lpfc 8.1.10 : Add support for dev_loss_tmo_callbk and fast_io_fail_tmo_callbk
Add support for new dev_loss_tmo callback
Goodness is that it removes code for a parallel nodev timer that
existed in the driver
Add support for the new fast_io_fail callback
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 178 |
1 files changed, 69 insertions, 109 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 53821e5778b3..97973af980a0 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -56,28 +56,63 @@ static uint8_t lpfcAlpaArray[] = { | |||
56 | 56 | ||
57 | static void lpfc_disc_timeout_handler(struct lpfc_hba *); | 57 | static void lpfc_disc_timeout_handler(struct lpfc_hba *); |
58 | 58 | ||
59 | static void | 59 | void |
60 | lpfc_process_nodev_timeout(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | 60 | lpfc_terminate_rport_io(struct fc_rport *rport) |
61 | { | 61 | { |
62 | uint8_t *name = (uint8_t *)&ndlp->nlp_portname; | 62 | struct lpfc_rport_data *rdata; |
63 | int warn_on = 0; | 63 | struct lpfc_nodelist * ndlp; |
64 | struct lpfc_hba *phba; | ||
64 | 65 | ||
65 | spin_lock_irq(phba->host->host_lock); | 66 | rdata = rport->dd_data; |
66 | if (!(ndlp->nlp_flag & NLP_NODEV_TMO)) { | 67 | ndlp = rdata->pnode; |
67 | spin_unlock_irq(phba->host->host_lock); | 68 | |
69 | if (!ndlp) { | ||
70 | if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) | ||
71 | printk(KERN_ERR "Cannot find remote node" | ||
72 | " to terminate I/O Data x%x\n", | ||
73 | rport->port_id); | ||
68 | return; | 74 | return; |
69 | } | 75 | } |
70 | 76 | ||
71 | /* | 77 | phba = ndlp->nlp_phba; |
72 | * If a discovery event readded nodev_timer after timer | 78 | |
73 | * firing and before processing the timer, cancel the | ||
74 | * nlp_tmofunc. | ||
75 | */ | ||
76 | spin_unlock_irq(phba->host->host_lock); | ||
77 | del_timer_sync(&ndlp->nlp_tmofunc); | ||
78 | spin_lock_irq(phba->host->host_lock); | 79 | spin_lock_irq(phba->host->host_lock); |
80 | if (ndlp->nlp_sid != NLP_NO_SID) { | ||
81 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | ||
82 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); | ||
83 | } | ||
84 | spin_unlock_irq(phba->host->host_lock); | ||
85 | |||
86 | return; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * This function will be called when dev_loss_tmo fire. | ||
91 | */ | ||
92 | void | ||
93 | lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | ||
94 | { | ||
95 | struct lpfc_rport_data *rdata; | ||
96 | struct lpfc_nodelist * ndlp; | ||
97 | uint8_t *name; | ||
98 | int warn_on = 0; | ||
99 | struct lpfc_hba *phba; | ||
100 | |||
101 | rdata = rport->dd_data; | ||
102 | ndlp = rdata->pnode; | ||
79 | 103 | ||
80 | ndlp->nlp_flag &= ~NLP_NODEV_TMO; | 104 | if (!ndlp) { |
105 | if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) | ||
106 | printk(KERN_ERR "Cannot find remote node" | ||
107 | " for rport in dev_loss_tmo_callbk x%x\n", | ||
108 | rport->port_id); | ||
109 | return; | ||
110 | } | ||
111 | |||
112 | name = (uint8_t *)&ndlp->nlp_portname; | ||
113 | phba = ndlp->nlp_phba; | ||
114 | |||
115 | spin_lock_irq(phba->host->host_lock); | ||
81 | 116 | ||
82 | if (ndlp->nlp_sid != NLP_NO_SID) { | 117 | if (ndlp->nlp_sid != NLP_NO_SID) { |
83 | warn_on = 1; | 118 | warn_on = 1; |
@@ -85,11 +120,14 @@ lpfc_process_nodev_timeout(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
85 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | 120 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], |
86 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); | 121 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); |
87 | } | 122 | } |
123 | if (phba->fc_flag & FC_UNLOADING) | ||
124 | warn_on = 0; | ||
125 | |||
88 | spin_unlock_irq(phba->host->host_lock); | 126 | spin_unlock_irq(phba->host->host_lock); |
89 | 127 | ||
90 | if (warn_on) { | 128 | if (warn_on) { |
91 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, | 129 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, |
92 | "%d:0203 Nodev timeout on " | 130 | "%d:0203 Devloss timeout on " |
93 | "WWPN %x:%x:%x:%x:%x:%x:%x:%x " | 131 | "WWPN %x:%x:%x:%x:%x:%x:%x:%x " |
94 | "NPort x%x Data: x%x x%x x%x\n", | 132 | "NPort x%x Data: x%x x%x x%x\n", |
95 | phba->brd_no, | 133 | phba->brd_no, |
@@ -99,7 +137,7 @@ lpfc_process_nodev_timeout(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
99 | ndlp->nlp_state, ndlp->nlp_rpi); | 137 | ndlp->nlp_state, ndlp->nlp_rpi); |
100 | } else { | 138 | } else { |
101 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 139 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
102 | "%d:0204 Nodev timeout on " | 140 | "%d:0204 Devloss timeout on " |
103 | "WWPN %x:%x:%x:%x:%x:%x:%x:%x " | 141 | "WWPN %x:%x:%x:%x:%x:%x:%x:%x " |
104 | "NPort x%x Data: x%x x%x x%x\n", | 142 | "NPort x%x Data: x%x x%x x%x\n", |
105 | phba->brd_no, | 143 | phba->brd_no, |
@@ -109,7 +147,12 @@ lpfc_process_nodev_timeout(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
109 | ndlp->nlp_state, ndlp->nlp_rpi); | 147 | ndlp->nlp_state, ndlp->nlp_rpi); |
110 | } | 148 | } |
111 | 149 | ||
112 | lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RM); | 150 | ndlp->rport = NULL; |
151 | rdata->pnode = NULL; | ||
152 | |||
153 | if (!(phba->fc_flag & FC_UNLOADING)) | ||
154 | lpfc_disc_state_machine(phba, ndlp, NULL, NLP_EVT_DEVICE_RM); | ||
155 | |||
113 | return; | 156 | return; |
114 | } | 157 | } |
115 | 158 | ||
@@ -127,11 +170,6 @@ lpfc_work_list_done(struct lpfc_hba * phba) | |||
127 | spin_unlock_irq(phba->host->host_lock); | 170 | spin_unlock_irq(phba->host->host_lock); |
128 | free_evt = 1; | 171 | free_evt = 1; |
129 | switch (evtp->evt) { | 172 | switch (evtp->evt) { |
130 | case LPFC_EVT_NODEV_TMO: | ||
131 | ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1); | ||
132 | lpfc_process_nodev_timeout(phba, ndlp); | ||
133 | free_evt = 0; | ||
134 | break; | ||
135 | case LPFC_EVT_ELS_RETRY: | 173 | case LPFC_EVT_ELS_RETRY: |
136 | ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1); | 174 | ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1); |
137 | lpfc_els_retry_delay_handler(ndlp); | 175 | lpfc_els_retry_delay_handler(ndlp); |
@@ -377,16 +415,6 @@ lpfc_linkdown(struct lpfc_hba * phba) | |||
377 | rc = lpfc_disc_state_machine(phba, ndlp, NULL, | 415 | rc = lpfc_disc_state_machine(phba, ndlp, NULL, |
378 | NLP_EVT_DEVICE_RECOVERY); | 416 | NLP_EVT_DEVICE_RECOVERY); |
379 | 417 | ||
380 | /* Check config parameter use-adisc or FCP-2 */ | ||
381 | if ((rc != NLP_STE_FREED_NODE) && | ||
382 | (phba->cfg_use_adisc == 0) && | ||
383 | !(ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE)) { | ||
384 | /* We know we will have to relogin, so | ||
385 | * unreglogin the rpi right now to fail | ||
386 | * any outstanding I/Os quickly. | ||
387 | */ | ||
388 | lpfc_unreg_rpi(phba, ndlp); | ||
389 | } | ||
390 | } | 418 | } |
391 | } | 419 | } |
392 | 420 | ||
@@ -1104,8 +1132,11 @@ lpfc_unregister_remote_port(struct lpfc_hba * phba, | |||
1104 | struct fc_rport *rport = ndlp->rport; | 1132 | struct fc_rport *rport = ndlp->rport; |
1105 | struct lpfc_rport_data *rdata = rport->dd_data; | 1133 | struct lpfc_rport_data *rdata = rport->dd_data; |
1106 | 1134 | ||
1107 | ndlp->rport = NULL; | 1135 | if (rport->scsi_target_id == -1) { |
1108 | rdata->pnode = NULL; | 1136 | ndlp->rport = NULL; |
1137 | rdata->pnode = NULL; | ||
1138 | } | ||
1139 | |||
1109 | fc_remote_port_delete(rport); | 1140 | fc_remote_port_delete(rport); |
1110 | 1141 | ||
1111 | return; | 1142 | return; |
@@ -1233,17 +1264,6 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) | |||
1233 | list_add_tail(&nlp->nlp_listp, &phba->fc_nlpunmap_list); | 1264 | list_add_tail(&nlp->nlp_listp, &phba->fc_nlpunmap_list); |
1234 | phba->fc_unmap_cnt++; | 1265 | phba->fc_unmap_cnt++; |
1235 | phba->nport_event_cnt++; | 1266 | phba->nport_event_cnt++; |
1236 | /* stop nodev tmo if running */ | ||
1237 | if (nlp->nlp_flag & NLP_NODEV_TMO) { | ||
1238 | nlp->nlp_flag &= ~NLP_NODEV_TMO; | ||
1239 | spin_unlock_irq(phba->host->host_lock); | ||
1240 | del_timer_sync(&nlp->nlp_tmofunc); | ||
1241 | spin_lock_irq(phba->host->host_lock); | ||
1242 | if (!list_empty(&nlp->nodev_timeout_evt.evt_listp)) | ||
1243 | list_del_init(&nlp->nodev_timeout_evt. | ||
1244 | evt_listp); | ||
1245 | |||
1246 | } | ||
1247 | nlp->nlp_flag &= ~NLP_NODEV_REMOVE; | 1267 | nlp->nlp_flag &= ~NLP_NODEV_REMOVE; |
1248 | nlp->nlp_type |= NLP_FC_NODE; | 1268 | nlp->nlp_type |= NLP_FC_NODE; |
1249 | break; | 1269 | break; |
@@ -1254,17 +1274,6 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) | |||
1254 | list_add_tail(&nlp->nlp_listp, &phba->fc_nlpmap_list); | 1274 | list_add_tail(&nlp->nlp_listp, &phba->fc_nlpmap_list); |
1255 | phba->fc_map_cnt++; | 1275 | phba->fc_map_cnt++; |
1256 | phba->nport_event_cnt++; | 1276 | phba->nport_event_cnt++; |
1257 | /* stop nodev tmo if running */ | ||
1258 | if (nlp->nlp_flag & NLP_NODEV_TMO) { | ||
1259 | nlp->nlp_flag &= ~NLP_NODEV_TMO; | ||
1260 | spin_unlock_irq(phba->host->host_lock); | ||
1261 | del_timer_sync(&nlp->nlp_tmofunc); | ||
1262 | spin_lock_irq(phba->host->host_lock); | ||
1263 | if (!list_empty(&nlp->nodev_timeout_evt.evt_listp)) | ||
1264 | list_del_init(&nlp->nodev_timeout_evt. | ||
1265 | evt_listp); | ||
1266 | |||
1267 | } | ||
1268 | nlp->nlp_flag &= ~NLP_NODEV_REMOVE; | 1277 | nlp->nlp_flag &= ~NLP_NODEV_REMOVE; |
1269 | break; | 1278 | break; |
1270 | case NLP_NPR_LIST: | 1279 | case NLP_NPR_LIST: |
@@ -1273,11 +1282,6 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) | |||
1273 | list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list); | 1282 | list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list); |
1274 | phba->fc_npr_cnt++; | 1283 | phba->fc_npr_cnt++; |
1275 | 1284 | ||
1276 | if (!(nlp->nlp_flag & NLP_NODEV_TMO)) | ||
1277 | mod_timer(&nlp->nlp_tmofunc, | ||
1278 | jiffies + HZ * phba->cfg_nodev_tmo); | ||
1279 | |||
1280 | nlp->nlp_flag |= NLP_NODEV_TMO; | ||
1281 | nlp->nlp_flag &= ~NLP_RCV_PLOGI; | 1285 | nlp->nlp_flag &= ~NLP_RCV_PLOGI; |
1282 | break; | 1286 | break; |
1283 | case NLP_JUST_DQ: | 1287 | case NLP_JUST_DQ: |
@@ -1307,7 +1311,8 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list) | |||
1307 | * already. If we have, and it's a scsi entity, be | 1311 | * already. If we have, and it's a scsi entity, be |
1308 | * sure to unblock any attached scsi devices | 1312 | * sure to unblock any attached scsi devices |
1309 | */ | 1313 | */ |
1310 | if (!nlp->rport) | 1314 | if ((!nlp->rport) || (nlp->rport->port_state == |
1315 | FC_PORTSTATE_BLOCKED)) | ||
1311 | lpfc_register_remote_port(phba, nlp); | 1316 | lpfc_register_remote_port(phba, nlp); |
1312 | 1317 | ||
1313 | /* | 1318 | /* |
@@ -1581,15 +1586,12 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1581 | 1586 | ||
1582 | lpfc_els_abort(phba,ndlp,0); | 1587 | lpfc_els_abort(phba,ndlp,0); |
1583 | spin_lock_irq(phba->host->host_lock); | 1588 | spin_lock_irq(phba->host->host_lock); |
1584 | ndlp->nlp_flag &= ~(NLP_NODEV_TMO|NLP_DELAY_TMO); | 1589 | ndlp->nlp_flag &= ~NLP_DELAY_TMO; |
1585 | spin_unlock_irq(phba->host->host_lock); | 1590 | spin_unlock_irq(phba->host->host_lock); |
1586 | del_timer_sync(&ndlp->nlp_tmofunc); | ||
1587 | 1591 | ||
1588 | ndlp->nlp_last_elscmd = 0; | 1592 | ndlp->nlp_last_elscmd = 0; |
1589 | del_timer_sync(&ndlp->nlp_delayfunc); | 1593 | del_timer_sync(&ndlp->nlp_delayfunc); |
1590 | 1594 | ||
1591 | if (!list_empty(&ndlp->nodev_timeout_evt.evt_listp)) | ||
1592 | list_del_init(&ndlp->nodev_timeout_evt.evt_listp); | ||
1593 | if (!list_empty(&ndlp->els_retry_evt.evt_listp)) | 1595 | if (!list_empty(&ndlp->els_retry_evt.evt_listp)) |
1594 | list_del_init(&ndlp->els_retry_evt.evt_listp); | 1596 | list_del_init(&ndlp->els_retry_evt.evt_listp); |
1595 | 1597 | ||
@@ -1606,16 +1608,6 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
1606 | int | 1608 | int |
1607 | lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | 1609 | lpfc_nlp_remove(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) |
1608 | { | 1610 | { |
1609 | if (ndlp->nlp_flag & NLP_NODEV_TMO) { | ||
1610 | spin_lock_irq(phba->host->host_lock); | ||
1611 | ndlp->nlp_flag &= ~NLP_NODEV_TMO; | ||
1612 | spin_unlock_irq(phba->host->host_lock); | ||
1613 | del_timer_sync(&ndlp->nlp_tmofunc); | ||
1614 | if (!list_empty(&ndlp->nodev_timeout_evt.evt_listp)) | ||
1615 | list_del_init(&ndlp->nodev_timeout_evt.evt_listp); | ||
1616 | |||
1617 | } | ||
1618 | |||
1619 | 1611 | ||
1620 | if (ndlp->nlp_flag & NLP_DELAY_TMO) { | 1612 | if (ndlp->nlp_flag & NLP_DELAY_TMO) { |
1621 | lpfc_cancel_retry_delay_tmo(phba, ndlp); | 1613 | lpfc_cancel_retry_delay_tmo(phba, ndlp); |
@@ -2430,34 +2422,6 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) | |||
2430 | return; | 2422 | return; |
2431 | } | 2423 | } |
2432 | 2424 | ||
2433 | static void | ||
2434 | lpfc_nodev_timeout(unsigned long ptr) | ||
2435 | { | ||
2436 | struct lpfc_hba *phba; | ||
2437 | struct lpfc_nodelist *ndlp; | ||
2438 | unsigned long iflag; | ||
2439 | struct lpfc_work_evt *evtp; | ||
2440 | |||
2441 | ndlp = (struct lpfc_nodelist *)ptr; | ||
2442 | phba = ndlp->nlp_phba; | ||
2443 | evtp = &ndlp->nodev_timeout_evt; | ||
2444 | spin_lock_irqsave(phba->host->host_lock, iflag); | ||
2445 | |||
2446 | if (!list_empty(&evtp->evt_listp)) { | ||
2447 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | ||
2448 | return; | ||
2449 | } | ||
2450 | evtp->evt_arg1 = ndlp; | ||
2451 | evtp->evt = LPFC_EVT_NODEV_TMO; | ||
2452 | list_add_tail(&evtp->evt_listp, &phba->work_list); | ||
2453 | if (phba->work_wait) | ||
2454 | wake_up(phba->work_wait); | ||
2455 | |||
2456 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | ||
2457 | return; | ||
2458 | } | ||
2459 | |||
2460 | |||
2461 | /* | 2425 | /* |
2462 | * This routine handles processing a NameServer REG_LOGIN mailbox | 2426 | * This routine handles processing a NameServer REG_LOGIN mailbox |
2463 | * command upon completion. It is setup in the LPFC_MBOXQ | 2427 | * command upon completion. It is setup in the LPFC_MBOXQ |
@@ -2581,11 +2545,7 @@ lpfc_nlp_init(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
2581 | uint32_t did) | 2545 | uint32_t did) |
2582 | { | 2546 | { |
2583 | memset(ndlp, 0, sizeof (struct lpfc_nodelist)); | 2547 | memset(ndlp, 0, sizeof (struct lpfc_nodelist)); |
2584 | INIT_LIST_HEAD(&ndlp->nodev_timeout_evt.evt_listp); | ||
2585 | INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp); | 2548 | INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp); |
2586 | init_timer(&ndlp->nlp_tmofunc); | ||
2587 | ndlp->nlp_tmofunc.function = lpfc_nodev_timeout; | ||
2588 | ndlp->nlp_tmofunc.data = (unsigned long)ndlp; | ||
2589 | init_timer(&ndlp->nlp_delayfunc); | 2549 | init_timer(&ndlp->nlp_delayfunc); |
2590 | ndlp->nlp_delayfunc.function = lpfc_els_retry_delay; | 2550 | ndlp->nlp_delayfunc.function = lpfc_els_retry_delay; |
2591 | ndlp->nlp_delayfunc.data = (unsigned long)ndlp; | 2551 | ndlp->nlp_delayfunc.data = (unsigned long)ndlp; |