aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/lpfc/lpfc.h3
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c25
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c78
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c5
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*/
1507LPFC_ATTR_R(use_msi, 0, 0, 1, "Use Message Signaled Interrupts, if possible"); 1514LPFC_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*/
1522LPFC_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*/
1530LPFC_ATTR_R(enable_hba_heartbeat, 1, 0, 1, "Enable HBA Heartbeat.");
1510 1531
1511struct class_device_attribute *lpfc_hba_attrs[] = { 1532struct 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);