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/lpfc_init.c | |
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/lpfc_init.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 92 |
1 files changed, 64 insertions, 28 deletions
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 | /****************************************************************************** |