diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-04-25 09:51:45 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-06 10:33:13 -0400 |
commit | 46fa311e6967b526e1fd9b0b44edda6841dcac27 (patch) | |
tree | 939fe8d2023c86b17f0f4ee9f3d627e64e2604de /drivers/scsi/lpfc | |
parent | 07951076aefa4194e1dbf1d8c89eaff040c45155 (diff) |
[SCSI] lpfc 8.1.12 : Rework offline path to solve HBA reset issues
Rework offline path to solve HBA reset issues
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 83 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 5 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 20 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 92 |
6 files changed, 150 insertions, 52 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index e57a9f5b9d84..6aa91530fcde 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -244,6 +244,7 @@ struct lpfc_hba { | |||
244 | #define FC_FABRIC 0x100 /* We are fabric attached */ | 244 | #define FC_FABRIC 0x100 /* We are fabric attached */ |
245 | #define FC_ESTABLISH_LINK 0x200 /* Reestablish Link */ | 245 | #define FC_ESTABLISH_LINK 0x200 /* Reestablish Link */ |
246 | #define FC_RSCN_DISCOVERY 0x400 /* Authenticate all devices after RSCN*/ | 246 | #define FC_RSCN_DISCOVERY 0x400 /* Authenticate all devices after RSCN*/ |
247 | #define FC_BLOCK_MGMT_IO 0x800 /* Don't allow mgmt mbx or iocb cmds */ | ||
247 | #define FC_LOADING 0x1000 /* HBA in process of loading drvr */ | 248 | #define FC_LOADING 0x1000 /* HBA in process of loading drvr */ |
248 | #define FC_UNLOADING 0x2000 /* HBA in process of unloading drvr */ | 249 | #define FC_UNLOADING 0x2000 /* HBA in process of unloading drvr */ |
249 | #define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */ | 250 | #define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */ |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 6cc88b198fa3..c0b02b11d88f 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -20,6 +20,7 @@ | |||
20 | *******************************************************************/ | 20 | *******************************************************************/ |
21 | 21 | ||
22 | #include <linux/ctype.h> | 22 | #include <linux/ctype.h> |
23 | #include <linux/delay.h> | ||
23 | #include <linux/pci.h> | 24 | #include <linux/pci.h> |
24 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
25 | 26 | ||
@@ -213,6 +214,7 @@ lpfc_issue_lip(struct Scsi_Host *host) | |||
213 | int mbxstatus = MBXERR_ERROR; | 214 | int mbxstatus = MBXERR_ERROR; |
214 | 215 | ||
215 | if ((phba->fc_flag & FC_OFFLINE_MODE) || | 216 | if ((phba->fc_flag & FC_OFFLINE_MODE) || |
217 | (phba->fc_flag & FC_BLOCK_MGMT_IO) || | ||
216 | (phba->hba_state != LPFC_HBA_READY)) | 218 | (phba->hba_state != LPFC_HBA_READY)) |
217 | return -EPERM; | 219 | return -EPERM; |
218 | 220 | ||
@@ -247,19 +249,62 @@ lpfc_issue_lip(struct Scsi_Host *host) | |||
247 | } | 249 | } |
248 | 250 | ||
249 | static int | 251 | static int |
250 | lpfc_selective_reset(struct lpfc_hba *phba) | 252 | lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) |
251 | { | 253 | { |
252 | struct completion online_compl; | 254 | struct completion online_compl; |
255 | struct lpfc_sli_ring *pring; | ||
256 | struct lpfc_sli *psli; | ||
253 | int status = 0; | 257 | int status = 0; |
258 | int cnt = 0; | ||
259 | int i; | ||
254 | 260 | ||
255 | init_completion(&online_compl); | 261 | init_completion(&online_compl); |
256 | lpfc_workq_post_event(phba, &status, &online_compl, | 262 | lpfc_workq_post_event(phba, &status, &online_compl, |
257 | LPFC_EVT_OFFLINE); | 263 | LPFC_EVT_OFFLINE_PREP); |
264 | wait_for_completion(&online_compl); | ||
265 | |||
266 | if (status != 0) | ||
267 | return -EIO; | ||
268 | |||
269 | psli = &phba->sli; | ||
270 | |||
271 | for (i = 0; i < psli->num_rings; i++) { | ||
272 | pring = &psli->ring[i]; | ||
273 | /* The linkdown event takes 30 seconds to timeout. */ | ||
274 | while (pring->txcmplq_cnt) { | ||
275 | msleep(10); | ||
276 | if (cnt++ > 3000) { | ||
277 | lpfc_printf_log(phba, | ||
278 | KERN_WARNING, LOG_INIT, | ||
279 | "%d:0466 Outstanding IO when " | ||
280 | "bringing Adapter offline\n", | ||
281 | phba->brd_no); | ||
282 | break; | ||
283 | } | ||
284 | } | ||
285 | } | ||
286 | |||
287 | init_completion(&online_compl); | ||
288 | lpfc_workq_post_event(phba, &status, &online_compl, type); | ||
258 | wait_for_completion(&online_compl); | 289 | wait_for_completion(&online_compl); |
259 | 290 | ||
260 | if (status != 0) | 291 | if (status != 0) |
261 | return -EIO; | 292 | return -EIO; |
262 | 293 | ||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | static int | ||
298 | lpfc_selective_reset(struct lpfc_hba *phba) | ||
299 | { | ||
300 | struct completion online_compl; | ||
301 | int status = 0; | ||
302 | |||
303 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); | ||
304 | |||
305 | if (status != 0) | ||
306 | return status; | ||
307 | |||
263 | init_completion(&online_compl); | 308 | init_completion(&online_compl); |
264 | lpfc_workq_post_event(phba, &status, &online_compl, | 309 | lpfc_workq_post_event(phba, &status, &online_compl, |
265 | LPFC_EVT_ONLINE); | 310 | LPFC_EVT_ONLINE); |
@@ -324,23 +369,19 @@ lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count) | |||
324 | 369 | ||
325 | init_completion(&online_compl); | 370 | init_completion(&online_compl); |
326 | 371 | ||
327 | if(strncmp(buf, "online", sizeof("online") - 1) == 0) | 372 | if(strncmp(buf, "online", sizeof("online") - 1) == 0) { |
328 | lpfc_workq_post_event(phba, &status, &online_compl, | 373 | lpfc_workq_post_event(phba, &status, &online_compl, |
329 | LPFC_EVT_ONLINE); | 374 | LPFC_EVT_ONLINE); |
330 | else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) | 375 | wait_for_completion(&online_compl); |
331 | lpfc_workq_post_event(phba, &status, &online_compl, | 376 | } else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) |
332 | LPFC_EVT_OFFLINE); | 377 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); |
333 | else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0) | 378 | else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0) |
334 | lpfc_workq_post_event(phba, &status, &online_compl, | 379 | status = lpfc_do_offline(phba, LPFC_EVT_WARM_START); |
335 | LPFC_EVT_WARM_START); | 380 | else if (strncmp(buf, "error", sizeof("error") - 1) == 0) |
336 | else if (strncmp(buf, "error", sizeof("error") - 1) == 0) | 381 | status = lpfc_do_offline(phba, LPFC_EVT_KILL); |
337 | lpfc_workq_post_event(phba, &status, &online_compl, | ||
338 | LPFC_EVT_KILL); | ||
339 | else | 382 | else |
340 | return -EINVAL; | 383 | return -EINVAL; |
341 | 384 | ||
342 | wait_for_completion(&online_compl); | ||
343 | |||
344 | if (!status) | 385 | if (!status) |
345 | return strlen(buf); | 386 | return strlen(buf); |
346 | else | 387 | else |
@@ -645,9 +686,7 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) | |||
645 | dev_printk(KERN_NOTICE, &phba->pcidev->dev, | 686 | dev_printk(KERN_NOTICE, &phba->pcidev->dev, |
646 | "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no); | 687 | "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no); |
647 | 688 | ||
648 | init_completion(&online_compl); | 689 | stat1 = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); |
649 | lpfc_workq_post_event(phba, &stat1, &online_compl, LPFC_EVT_OFFLINE); | ||
650 | wait_for_completion(&online_compl); | ||
651 | if (stat1) | 690 | if (stat1) |
652 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 691 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
653 | "%d:0463 lpfc_soft_wwpn attribute set failed to reinit " | 692 | "%d:0463 lpfc_soft_wwpn attribute set failed to reinit " |
@@ -1307,6 +1346,12 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
1307 | return -EPERM; | 1346 | return -EPERM; |
1308 | } | 1347 | } |
1309 | 1348 | ||
1349 | if (phba->fc_flag & FC_BLOCK_MGMT_IO) { | ||
1350 | sysfs_mbox_idle(phba); | ||
1351 | spin_unlock_irq(host->host_lock); | ||
1352 | return -EAGAIN; | ||
1353 | } | ||
1354 | |||
1310 | if ((phba->fc_flag & FC_OFFLINE_MODE) || | 1355 | if ((phba->fc_flag & FC_OFFLINE_MODE) || |
1311 | (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE))){ | 1356 | (!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE))){ |
1312 | 1357 | ||
@@ -1551,6 +1596,9 @@ lpfc_get_stats(struct Scsi_Host *shost) | |||
1551 | unsigned long seconds; | 1596 | unsigned long seconds; |
1552 | int rc = 0; | 1597 | int rc = 0; |
1553 | 1598 | ||
1599 | if (phba->fc_flag & FC_BLOCK_MGMT_IO) | ||
1600 | return NULL; | ||
1601 | |||
1554 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 1602 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
1555 | if (!pmboxq) | 1603 | if (!pmboxq) |
1556 | return NULL; | 1604 | return NULL; |
@@ -1651,6 +1699,9 @@ lpfc_reset_stats(struct Scsi_Host *shost) | |||
1651 | MAILBOX_t *pmb; | 1699 | MAILBOX_t *pmb; |
1652 | int rc = 0; | 1700 | int rc = 0; |
1653 | 1701 | ||
1702 | if (phba->fc_flag & FC_BLOCK_MGMT_IO) | ||
1703 | return; | ||
1704 | |||
1654 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 1705 | pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
1655 | if (!pmboxq) | 1706 | if (!pmboxq) |
1656 | return; | 1707 | return; |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 4132a2dfac54..bf555d37e8d9 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -112,7 +112,10 @@ void lpfc_hba_init(struct lpfc_hba *, uint32_t *); | |||
112 | int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, int); | 112 | int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, int); |
113 | void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int); | 113 | void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int); |
114 | int lpfc_online(struct lpfc_hba *); | 114 | int lpfc_online(struct lpfc_hba *); |
115 | int lpfc_offline(struct lpfc_hba *); | 115 | void lpfc_block_mgmt_io(struct lpfc_hba *); |
116 | void lpfc_unblock_mgmt_io(struct lpfc_hba *); | ||
117 | void lpfc_offline_prep(struct lpfc_hba *); | ||
118 | void lpfc_offline(struct lpfc_hba *); | ||
116 | 119 | ||
117 | int lpfc_sli_setup(struct lpfc_hba *); | 120 | int lpfc_sli_setup(struct lpfc_hba *); |
118 | int lpfc_sli_queue_setup(struct lpfc_hba *); | 121 | int lpfc_sli_queue_setup(struct lpfc_hba *); |
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 9766f909c9c6..cfafff09dcfe 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
@@ -31,6 +31,7 @@ | |||
31 | /* worker thread events */ | 31 | /* worker thread events */ |
32 | enum lpfc_work_type { | 32 | enum lpfc_work_type { |
33 | LPFC_EVT_ONLINE, | 33 | LPFC_EVT_ONLINE, |
34 | LPFC_EVT_OFFLINE_PREP, | ||
34 | LPFC_EVT_OFFLINE, | 35 | LPFC_EVT_OFFLINE, |
35 | LPFC_EVT_WARM_START, | 36 | LPFC_EVT_WARM_START, |
36 | LPFC_EVT_KILL, | 37 | LPFC_EVT_KILL, |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 485a13fa527d..92c0c4b88953 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -185,29 +185,35 @@ lpfc_work_list_done(struct lpfc_hba * phba) | |||
185 | *(int *)(evtp->evt_arg1) = 0; | 185 | *(int *)(evtp->evt_arg1) = 0; |
186 | complete((struct completion *)(evtp->evt_arg2)); | 186 | complete((struct completion *)(evtp->evt_arg2)); |
187 | break; | 187 | break; |
188 | case LPFC_EVT_OFFLINE: | 188 | case LPFC_EVT_OFFLINE_PREP: |
189 | if (phba->hba_state >= LPFC_LINK_DOWN) | 189 | if (phba->hba_state >= LPFC_LINK_DOWN) |
190 | lpfc_offline(phba); | 190 | lpfc_offline_prep(phba); |
191 | *(int *)(evtp->evt_arg1) = 0; | ||
192 | complete((struct completion *)(evtp->evt_arg2)); | ||
193 | break; | ||
194 | case LPFC_EVT_OFFLINE: | ||
195 | lpfc_offline(phba); | ||
191 | lpfc_sli_brdrestart(phba); | 196 | lpfc_sli_brdrestart(phba); |
192 | *(int *)(evtp->evt_arg1) = | 197 | *(int *)(evtp->evt_arg1) = |
193 | lpfc_sli_brdready(phba,HS_FFRDY | HS_MBRDY); | 198 | lpfc_sli_brdready(phba, HS_FFRDY | HS_MBRDY); |
199 | lpfc_unblock_mgmt_io(phba); | ||
194 | complete((struct completion *)(evtp->evt_arg2)); | 200 | complete((struct completion *)(evtp->evt_arg2)); |
195 | break; | 201 | break; |
196 | case LPFC_EVT_WARM_START: | 202 | case LPFC_EVT_WARM_START: |
197 | if (phba->hba_state >= LPFC_LINK_DOWN) | 203 | lpfc_offline(phba); |
198 | lpfc_offline(phba); | ||
199 | lpfc_reset_barrier(phba); | 204 | lpfc_reset_barrier(phba); |
200 | lpfc_sli_brdreset(phba); | 205 | lpfc_sli_brdreset(phba); |
201 | lpfc_hba_down_post(phba); | 206 | lpfc_hba_down_post(phba); |
202 | *(int *)(evtp->evt_arg1) = | 207 | *(int *)(evtp->evt_arg1) = |
203 | lpfc_sli_brdready(phba, HS_MBRDY); | 208 | lpfc_sli_brdready(phba, HS_MBRDY); |
209 | lpfc_unblock_mgmt_io(phba); | ||
204 | complete((struct completion *)(evtp->evt_arg2)); | 210 | complete((struct completion *)(evtp->evt_arg2)); |
205 | break; | 211 | break; |
206 | case LPFC_EVT_KILL: | 212 | case LPFC_EVT_KILL: |
207 | if (phba->hba_state >= LPFC_LINK_DOWN) | 213 | lpfc_offline(phba); |
208 | lpfc_offline(phba); | ||
209 | *(int *)(evtp->evt_arg1) | 214 | *(int *)(evtp->evt_arg1) |
210 | = (phba->stopped) ? 0 : lpfc_sli_brdkill(phba); | 215 | = (phba->stopped) ? 0 : lpfc_sli_brdkill(phba); |
216 | lpfc_unblock_mgmt_io(phba); | ||
211 | complete((struct completion *)(evtp->evt_arg2)); | 217 | complete((struct completion *)(evtp->evt_arg2)); |
212 | break; | 218 | break; |
213 | } | 219 | } |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 62677da28c9d..dc0fd2e36de1 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -549,12 +549,15 @@ lpfc_handle_eratt(struct lpfc_hba * phba) | |||
549 | * There was a firmware error. Take the hba offline and then | 549 | * There was a firmware error. Take the hba offline and then |
550 | * attempt to restart it. | 550 | * attempt to restart it. |
551 | */ | 551 | */ |
552 | lpfc_offline_prep(phba); | ||
552 | lpfc_offline(phba); | 553 | lpfc_offline(phba); |
553 | lpfc_sli_brdrestart(phba); | 554 | lpfc_sli_brdrestart(phba); |
554 | if (lpfc_online(phba) == 0) { /* Initialize the HBA */ | 555 | if (lpfc_online(phba) == 0) { /* Initialize the HBA */ |
555 | mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); | 556 | mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); |
557 | lpfc_unblock_mgmt_io(phba); | ||
556 | return; | 558 | return; |
557 | } | 559 | } |
560 | lpfc_unblock_mgmt_io(phba); | ||
558 | } else { | 561 | } else { |
559 | /* The if clause above forces this code path when the status | 562 | /* The if clause above forces this code path when the status |
560 | * failure is a value other than FFER6. Do not call the offline | 563 | * failure is a value other than FFER6. Do not call the offline |
@@ -572,7 +575,9 @@ lpfc_handle_eratt(struct lpfc_hba * phba) | |||
572 | SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX); | 575 | SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX); |
573 | 576 | ||
574 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | 577 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; |
578 | lpfc_offline_prep(phba); | ||
575 | lpfc_offline(phba); | 579 | lpfc_offline(phba); |
580 | lpfc_unblock_mgmt_io(phba); | ||
576 | phba->hba_state = LPFC_HBA_ERROR; | 581 | phba->hba_state = LPFC_HBA_ERROR; |
577 | lpfc_hba_down_post(phba); | 582 | lpfc_hba_down_post(phba); |
578 | } | 583 | } |
@@ -1286,55 +1291,87 @@ lpfc_online(struct lpfc_hba * phba) | |||
1286 | "%d:0458 Bring Adapter online\n", | 1291 | "%d:0458 Bring Adapter online\n", |
1287 | phba->brd_no); | 1292 | phba->brd_no); |
1288 | 1293 | ||
1289 | if (!lpfc_sli_queue_setup(phba)) | 1294 | lpfc_block_mgmt_io(phba); |
1295 | |||
1296 | if (!lpfc_sli_queue_setup(phba)) { | ||
1297 | lpfc_unblock_mgmt_io(phba); | ||
1290 | return 1; | 1298 | return 1; |
1299 | } | ||
1291 | 1300 | ||
1292 | if (lpfc_sli_hba_setup(phba)) /* Initialize the HBA */ | 1301 | if (lpfc_sli_hba_setup(phba)) { /* Initialize the HBA */ |
1302 | lpfc_unblock_mgmt_io(phba); | ||
1293 | return 1; | 1303 | return 1; |
1304 | } | ||
1294 | 1305 | ||
1295 | spin_lock_irq(phba->host->host_lock); | 1306 | spin_lock_irq(phba->host->host_lock); |
1296 | phba->fc_flag &= ~FC_OFFLINE_MODE; | 1307 | phba->fc_flag &= ~FC_OFFLINE_MODE; |
1297 | spin_unlock_irq(phba->host->host_lock); | 1308 | spin_unlock_irq(phba->host->host_lock); |
1298 | 1309 | ||
1310 | lpfc_unblock_mgmt_io(phba); | ||
1299 | return 0; | 1311 | return 0; |
1300 | } | 1312 | } |
1301 | 1313 | ||
1302 | int | 1314 | void |
1303 | lpfc_offline(struct lpfc_hba * phba) | 1315 | lpfc_block_mgmt_io(struct lpfc_hba * phba) |
1304 | { | 1316 | { |
1305 | struct lpfc_sli_ring *pring; | ||
1306 | struct lpfc_sli *psli; | ||
1307 | unsigned long iflag; | 1317 | unsigned long iflag; |
1308 | int i; | ||
1309 | int cnt = 0; | ||
1310 | 1318 | ||
1311 | if (!phba) | 1319 | spin_lock_irqsave(phba->host->host_lock, iflag); |
1312 | return 0; | 1320 | phba->fc_flag |= FC_BLOCK_MGMT_IO; |
1321 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | ||
1322 | } | ||
1323 | |||
1324 | void | ||
1325 | lpfc_unblock_mgmt_io(struct lpfc_hba * phba) | ||
1326 | { | ||
1327 | unsigned long iflag; | ||
1328 | |||
1329 | spin_lock_irqsave(phba->host->host_lock, iflag); | ||
1330 | phba->fc_flag &= ~FC_BLOCK_MGMT_IO; | ||
1331 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | ||
1332 | } | ||
1333 | |||
1334 | void | ||
1335 | lpfc_offline_prep(struct lpfc_hba * phba) | ||
1336 | { | ||
1337 | struct lpfc_nodelist *ndlp, *next_ndlp; | ||
1338 | struct list_head *listp, *node_list[7]; | ||
1339 | int i; | ||
1313 | 1340 | ||
1314 | if (phba->fc_flag & FC_OFFLINE_MODE) | 1341 | if (phba->fc_flag & FC_OFFLINE_MODE) |
1315 | return 0; | 1342 | return; |
1316 | 1343 | ||
1317 | psli = &phba->sli; | 1344 | lpfc_block_mgmt_io(phba); |
1318 | 1345 | ||
1319 | lpfc_linkdown(phba); | 1346 | lpfc_linkdown(phba); |
1320 | lpfc_sli_flush_mbox_queue(phba); | ||
1321 | 1347 | ||
1322 | for (i = 0; i < psli->num_rings; i++) { | 1348 | /* Issue an unreg_login to all nodes */ |
1323 | pring = &psli->ring[i]; | 1349 | node_list[0] = &phba->fc_npr_list; /* MUST do this list first */ |
1324 | /* The linkdown event takes 30 seconds to timeout. */ | 1350 | node_list[1] = &phba->fc_nlpmap_list; |
1325 | while (pring->txcmplq_cnt) { | 1351 | node_list[2] = &phba->fc_nlpunmap_list; |
1326 | msleep(10); | 1352 | node_list[3] = &phba->fc_prli_list; |
1327 | if (cnt++ > 3000) { | 1353 | node_list[4] = &phba->fc_reglogin_list; |
1328 | lpfc_printf_log(phba, | 1354 | node_list[5] = &phba->fc_adisc_list; |
1329 | KERN_WARNING, LOG_INIT, | 1355 | node_list[6] = &phba->fc_plogi_list; |
1330 | "%d:0466 Outstanding IO when " | 1356 | for (i = 0; i < 7; i++) { |
1331 | "bringing Adapter offline\n", | 1357 | listp = node_list[i]; |
1332 | phba->brd_no); | 1358 | if (list_empty(listp)) |
1333 | break; | 1359 | continue; |
1334 | } | 1360 | |
1335 | } | 1361 | list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) |
1362 | lpfc_unreg_rpi(phba, ndlp); | ||
1336 | } | 1363 | } |
1337 | 1364 | ||
1365 | lpfc_sli_flush_mbox_queue(phba); | ||
1366 | } | ||
1367 | |||
1368 | void | ||
1369 | lpfc_offline(struct lpfc_hba * phba) | ||
1370 | { | ||
1371 | unsigned long iflag; | ||
1372 | |||
1373 | if (phba->fc_flag & FC_OFFLINE_MODE) | ||
1374 | return; | ||
1338 | 1375 | ||
1339 | /* stop all timers associated with this hba */ | 1376 | /* stop all timers associated with this hba */ |
1340 | lpfc_stop_timer(phba); | 1377 | lpfc_stop_timer(phba); |
@@ -1354,7 +1391,6 @@ lpfc_offline(struct lpfc_hba * phba) | |||
1354 | spin_lock_irqsave(phba->host->host_lock, iflag); | 1391 | spin_lock_irqsave(phba->host->host_lock, iflag); |
1355 | phba->fc_flag |= FC_OFFLINE_MODE; | 1392 | phba->fc_flag |= FC_OFFLINE_MODE; |
1356 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | 1393 | spin_unlock_irqrestore(phba->host->host_lock, iflag); |
1357 | return 0; | ||
1358 | } | 1394 | } |
1359 | 1395 | ||
1360 | /****************************************************************************** | 1396 | /****************************************************************************** |