diff options
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 25 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 78 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 5 |
4 files changed, 73 insertions, 38 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index b06635ac3356..5bf402a20682 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -471,7 +471,8 @@ struct lpfc_hba { | |||
471 | uint64_t cfg_soft_wwnn; | 471 | uint64_t cfg_soft_wwnn; |
472 | uint64_t cfg_soft_wwpn; | 472 | uint64_t cfg_soft_wwpn; |
473 | uint32_t cfg_hba_queue_depth; | 473 | uint32_t cfg_hba_queue_depth; |
474 | 474 | uint32_t cfg_enable_hba_reset; | |
475 | uint32_t cfg_enable_hba_heartbeat; | ||
475 | 476 | ||
476 | lpfc_vpd_t vpd; /* vital product data */ | 477 | lpfc_vpd_t vpd; /* vital product data */ |
477 | 478 | ||
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index e1b041d8f6d5..68e92be1ef5b 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -342,6 +342,9 @@ lpfc_selective_reset(struct lpfc_hba *phba) | |||
342 | struct completion online_compl; | 342 | struct completion online_compl; |
343 | int status = 0; | 343 | int status = 0; |
344 | 344 | ||
345 | if (!phba->cfg_enable_hba_reset) | ||
346 | return -EIO; | ||
347 | |||
345 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); | 348 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); |
346 | 349 | ||
347 | if (status != 0) | 350 | if (status != 0) |
@@ -415,6 +418,8 @@ lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count) | |||
415 | struct completion online_compl; | 418 | struct completion online_compl; |
416 | int status=0; | 419 | int status=0; |
417 | 420 | ||
421 | if (!phba->cfg_enable_hba_reset) | ||
422 | return -EACCES; | ||
418 | init_completion(&online_compl); | 423 | init_completion(&online_compl); |
419 | 424 | ||
420 | if(strncmp(buf, "online", sizeof("online") - 1) == 0) { | 425 | if(strncmp(buf, "online", sizeof("online") - 1) == 0) { |
@@ -979,6 +984,8 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) | |||
979 | unsigned int i, j, cnt=count; | 984 | unsigned int i, j, cnt=count; |
980 | u8 wwpn[8]; | 985 | u8 wwpn[8]; |
981 | 986 | ||
987 | if (!phba->cfg_enable_hba_reset) | ||
988 | return -EACCES; | ||
982 | spin_lock_irq(&phba->hbalock); | 989 | spin_lock_irq(&phba->hbalock); |
983 | if (phba->over_temp_state == HBA_OVER_TEMP) { | 990 | if (phba->over_temp_state == HBA_OVER_TEMP) { |
984 | spin_unlock_irq(&phba->hbalock); | 991 | spin_unlock_irq(&phba->hbalock); |
@@ -1506,7 +1513,21 @@ LPFC_ATTR_RW(poll_tmo, 10, 1, 255, | |||
1506 | */ | 1513 | */ |
1507 | LPFC_ATTR_R(use_msi, 0, 0, 1, "Use Message Signaled Interrupts, if possible"); | 1514 | LPFC_ATTR_R(use_msi, 0, 0, 1, "Use Message Signaled Interrupts, if possible"); |
1508 | 1515 | ||
1516 | /* | ||
1517 | # lpfc_enable_hba_reset: Allow or prevent HBA resets to the hardware. | ||
1518 | # 0 = HBA resets disabled | ||
1519 | # 1 = HBA resets enabled (default) | ||
1520 | # Value range is [0,1]. Default value is 1. | ||
1521 | */ | ||
1522 | LPFC_ATTR_R(enable_hba_reset, 1, 0, 1, "Enable HBA resets from the driver."); | ||
1509 | 1523 | ||
1524 | /* | ||
1525 | # lpfc_enable_hba_heartbeat: Enable HBA heartbeat timer.. | ||
1526 | # 0 = HBA Heartbeat disabled | ||
1527 | # 1 = HBA Heartbeat enabled (default) | ||
1528 | # Value range is [0,1]. Default value is 1. | ||
1529 | */ | ||
1530 | LPFC_ATTR_R(enable_hba_heartbeat, 1, 0, 1, "Enable HBA Heartbeat."); | ||
1510 | 1531 | ||
1511 | struct class_device_attribute *lpfc_hba_attrs[] = { | 1532 | struct class_device_attribute *lpfc_hba_attrs[] = { |
1512 | &class_device_attr_info, | 1533 | &class_device_attr_info, |
@@ -1558,6 +1579,8 @@ struct class_device_attribute *lpfc_hba_attrs[] = { | |||
1558 | &class_device_attr_lpfc_soft_wwnn, | 1579 | &class_device_attr_lpfc_soft_wwnn, |
1559 | &class_device_attr_lpfc_soft_wwpn, | 1580 | &class_device_attr_lpfc_soft_wwpn, |
1560 | &class_device_attr_lpfc_soft_wwn_enable, | 1581 | &class_device_attr_lpfc_soft_wwn_enable, |
1582 | &class_device_attr_lpfc_enable_hba_reset, | ||
1583 | &class_device_attr_lpfc_enable_hba_heartbeat, | ||
1561 | NULL, | 1584 | NULL, |
1562 | }; | 1585 | }; |
1563 | 1586 | ||
@@ -2448,6 +2471,8 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) | |||
2448 | lpfc_poll_tmo_init(phba, lpfc_poll_tmo); | 2471 | lpfc_poll_tmo_init(phba, lpfc_poll_tmo); |
2449 | lpfc_enable_npiv_init(phba, lpfc_enable_npiv); | 2472 | lpfc_enable_npiv_init(phba, lpfc_enable_npiv); |
2450 | lpfc_use_msi_init(phba, lpfc_use_msi); | 2473 | lpfc_use_msi_init(phba, lpfc_use_msi); |
2474 | lpfc_enable_hba_reset_init(phba, lpfc_enable_hba_reset); | ||
2475 | lpfc_enable_hba_heartbeat_init(phba, lpfc_enable_hba_heartbeat); | ||
2451 | phba->cfg_poll = lpfc_poll; | 2476 | phba->cfg_poll = lpfc_poll; |
2452 | phba->cfg_soft_wwnn = 0L; | 2477 | phba->cfg_soft_wwnn = 0L; |
2453 | phba->cfg_soft_wwpn = 0L; | 2478 | phba->cfg_soft_wwpn = 0L; |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f32cd9acd3f6..c6b30a8617bc 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -594,49 +594,50 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) | |||
594 | } | 594 | } |
595 | phba->elsbuf_prev_cnt = phba->elsbuf_cnt; | 595 | phba->elsbuf_prev_cnt = phba->elsbuf_cnt; |
596 | 596 | ||
597 | |||
598 | /* If there is no heart beat outstanding, issue a heartbeat command */ | 597 | /* If there is no heart beat outstanding, issue a heartbeat command */ |
599 | if (!phba->hb_outstanding) { | 598 | if (phba->cfg_enable_hba_heartbeat) { |
600 | pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL); | 599 | if (!phba->hb_outstanding) { |
601 | if (!pmboxq) { | 600 | pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL); |
602 | mod_timer(&phba->hb_tmofunc, | 601 | if (!pmboxq) { |
603 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | 602 | mod_timer(&phba->hb_tmofunc, |
604 | return; | 603 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); |
605 | } | 604 | return; |
605 | } | ||
606 | 606 | ||
607 | lpfc_heart_beat(phba, pmboxq); | 607 | lpfc_heart_beat(phba, pmboxq); |
608 | pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl; | 608 | pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl; |
609 | pmboxq->vport = phba->pport; | 609 | pmboxq->vport = phba->pport; |
610 | retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); | 610 | retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); |
611 | 611 | ||
612 | if (retval != MBX_BUSY && retval != MBX_SUCCESS) { | 612 | if (retval != MBX_BUSY && retval != MBX_SUCCESS) { |
613 | mempool_free(pmboxq, phba->mbox_mem_pool); | 613 | mempool_free(pmboxq, phba->mbox_mem_pool); |
614 | mod_timer(&phba->hb_tmofunc, | ||
615 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | ||
616 | return; | ||
617 | } | ||
614 | mod_timer(&phba->hb_tmofunc, | 618 | mod_timer(&phba->hb_tmofunc, |
615 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | 619 | jiffies + HZ * LPFC_HB_MBOX_TIMEOUT); |
620 | phba->hb_outstanding = 1; | ||
616 | return; | 621 | return; |
622 | } else { | ||
623 | /* | ||
624 | * If heart beat timeout called with hb_outstanding set | ||
625 | * we need to take the HBA offline. | ||
626 | */ | ||
627 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
628 | "0459 Adapter heartbeat failure, " | ||
629 | "taking this port offline.\n"); | ||
630 | |||
631 | spin_lock_irq(&phba->hbalock); | ||
632 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | ||
633 | spin_unlock_irq(&phba->hbalock); | ||
634 | |||
635 | lpfc_offline_prep(phba); | ||
636 | lpfc_offline(phba); | ||
637 | lpfc_unblock_mgmt_io(phba); | ||
638 | phba->link_state = LPFC_HBA_ERROR; | ||
639 | lpfc_hba_down_post(phba); | ||
617 | } | 640 | } |
618 | mod_timer(&phba->hb_tmofunc, | ||
619 | jiffies + HZ * LPFC_HB_MBOX_TIMEOUT); | ||
620 | phba->hb_outstanding = 1; | ||
621 | return; | ||
622 | } else { | ||
623 | /* | ||
624 | * If heart beat timeout called with hb_outstanding set we | ||
625 | * need to take the HBA offline. | ||
626 | */ | ||
627 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
628 | "0459 Adapter heartbeat failure, taking " | ||
629 | "this port offline.\n"); | ||
630 | |||
631 | spin_lock_irq(&phba->hbalock); | ||
632 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | ||
633 | spin_unlock_irq(&phba->hbalock); | ||
634 | |||
635 | lpfc_offline_prep(phba); | ||
636 | lpfc_offline(phba); | ||
637 | lpfc_unblock_mgmt_io(phba); | ||
638 | phba->link_state = LPFC_HBA_ERROR; | ||
639 | lpfc_hba_down_post(phba); | ||
640 | } | 641 | } |
641 | } | 642 | } |
642 | 643 | ||
@@ -665,6 +666,9 @@ lpfc_handle_eratt(struct lpfc_hba *phba) | |||
665 | * since we cannot communicate with the pci card anyway. */ | 666 | * since we cannot communicate with the pci card anyway. */ |
666 | if (pci_channel_offline(phba->pcidev)) | 667 | if (pci_channel_offline(phba->pcidev)) |
667 | return; | 668 | return; |
669 | /* If resets are disabled then leave the HBA alone and return */ | ||
670 | if (!phba->cfg_enable_hba_reset) | ||
671 | return; | ||
668 | 672 | ||
669 | if (phba->work_hs & HS_FFER6 || | 673 | if (phba->work_hs & HS_FFER6 || |
670 | phba->work_hs & HS_FFER5) { | 674 | phba->work_hs & HS_FFER5) { |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index be6519793f8a..46d529d6ac6b 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -2559,6 +2559,11 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) | |||
2559 | * lpfc_offline calls lpfc_sli_hba_down which will clean up | 2559 | * lpfc_offline calls lpfc_sli_hba_down which will clean up |
2560 | * on oustanding mailbox commands. | 2560 | * on oustanding mailbox commands. |
2561 | */ | 2561 | */ |
2562 | /* If resets are disabled then set error state and return. */ | ||
2563 | if (!phba->cfg_enable_hba_reset) { | ||
2564 | phba->link_state = LPFC_HBA_ERROR; | ||
2565 | return; | ||
2566 | } | ||
2562 | lpfc_offline_prep(phba); | 2567 | lpfc_offline_prep(phba); |
2563 | lpfc_offline(phba); | 2568 | lpfc_offline(phba); |
2564 | lpfc_sli_brdrestart(phba); | 2569 | lpfc_sli_brdrestart(phba); |