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_attr.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_attr.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 155 |
1 files changed, 127 insertions, 28 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index c6d683d86cff..0de69324212e 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -39,6 +39,9 @@ | |||
39 | #include "lpfc_compat.h" | 39 | #include "lpfc_compat.h" |
40 | #include "lpfc_crtn.h" | 40 | #include "lpfc_crtn.h" |
41 | 41 | ||
42 | #define LPFC_DEF_DEVLOSS_TMO 30 | ||
43 | #define LPFC_MIN_DEVLOSS_TMO 1 | ||
44 | #define LPFC_MAX_DEVLOSS_TMO 255 | ||
42 | 45 | ||
43 | static void | 46 | static void |
44 | lpfc_jedec_to_ascii(int incr, char hdw[]) | 47 | lpfc_jedec_to_ascii(int incr, char hdw[]) |
@@ -559,6 +562,123 @@ static CLASS_DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR, | |||
559 | lpfc_poll_show, lpfc_poll_store); | 562 | lpfc_poll_show, lpfc_poll_store); |
560 | 563 | ||
561 | /* | 564 | /* |
565 | # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear | ||
566 | # until the timer expires. Value range is [0,255]. Default value is 30. | ||
567 | */ | ||
568 | static int lpfc_nodev_tmo = LPFC_DEF_DEVLOSS_TMO; | ||
569 | static int lpfc_devloss_tmo = LPFC_DEF_DEVLOSS_TMO; | ||
570 | module_param(lpfc_nodev_tmo, int, 0); | ||
571 | MODULE_PARM_DESC(lpfc_nodev_tmo, | ||
572 | "Seconds driver will hold I/O waiting " | ||
573 | "for a device to come back"); | ||
574 | static ssize_t | ||
575 | lpfc_nodev_tmo_show(struct class_device *cdev, char *buf) | ||
576 | { | ||
577 | struct Scsi_Host *host = class_to_shost(cdev); | ||
578 | struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; | ||
579 | int val = 0; | ||
580 | val = phba->cfg_devloss_tmo; | ||
581 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
582 | phba->cfg_devloss_tmo); | ||
583 | } | ||
584 | |||
585 | static int | ||
586 | lpfc_nodev_tmo_init(struct lpfc_hba *phba, int val) | ||
587 | { | ||
588 | static int warned; | ||
589 | if (phba->cfg_devloss_tmo != LPFC_DEF_DEVLOSS_TMO) { | ||
590 | phba->cfg_nodev_tmo = phba->cfg_devloss_tmo; | ||
591 | if (!warned && val != LPFC_DEF_DEVLOSS_TMO) { | ||
592 | warned = 1; | ||
593 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
594 | "%d:0402 Ignoring nodev_tmo module " | ||
595 | "parameter because devloss_tmo is" | ||
596 | " set.\n", | ||
597 | phba->brd_no); | ||
598 | } | ||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { | ||
603 | phba->cfg_nodev_tmo = val; | ||
604 | phba->cfg_devloss_tmo = val; | ||
605 | return 0; | ||
606 | } | ||
607 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
608 | "%d:0400 lpfc_nodev_tmo attribute cannot be set to %d, " | ||
609 | "allowed range is [%d, %d]\n", | ||
610 | phba->brd_no, val, | ||
611 | LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO); | ||
612 | phba->cfg_nodev_tmo = LPFC_DEF_DEVLOSS_TMO; | ||
613 | return -EINVAL; | ||
614 | } | ||
615 | |||
616 | static int | ||
617 | lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val) | ||
618 | { | ||
619 | if (phba->dev_loss_tmo_changed || | ||
620 | (lpfc_devloss_tmo != LPFC_DEF_DEVLOSS_TMO)) { | ||
621 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
622 | "%d:0401 Ignoring change to nodev_tmo " | ||
623 | "because devloss_tmo is set.\n", | ||
624 | phba->brd_no); | ||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { | ||
629 | phba->cfg_nodev_tmo = val; | ||
630 | phba->cfg_devloss_tmo = val; | ||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
635 | "%d:0403 lpfc_nodev_tmo attribute cannot be set to %d, " | ||
636 | "allowed range is [%d, %d]\n", | ||
637 | phba->brd_no, val, LPFC_MIN_DEVLOSS_TMO, | ||
638 | LPFC_MAX_DEVLOSS_TMO); | ||
639 | return -EINVAL; | ||
640 | } | ||
641 | |||
642 | lpfc_param_store(nodev_tmo) | ||
643 | |||
644 | static CLASS_DEVICE_ATTR(lpfc_nodev_tmo, S_IRUGO | S_IWUSR, | ||
645 | lpfc_nodev_tmo_show, lpfc_nodev_tmo_store); | ||
646 | |||
647 | /* | ||
648 | # lpfc_devloss_tmo: If set, it will hold all I/O errors on devices that | ||
649 | # disappear until the timer expires. Value range is [0,255]. Default | ||
650 | # value is 30. | ||
651 | */ | ||
652 | module_param(lpfc_devloss_tmo, int, 0); | ||
653 | MODULE_PARM_DESC(lpfc_devloss_tmo, | ||
654 | "Seconds driver will hold I/O waiting " | ||
655 | "for a device to come back"); | ||
656 | lpfc_param_init(devloss_tmo, LPFC_DEF_DEVLOSS_TMO, | ||
657 | LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO) | ||
658 | lpfc_param_show(devloss_tmo) | ||
659 | static int | ||
660 | lpfc_devloss_tmo_set(struct lpfc_hba *phba, int val) | ||
661 | { | ||
662 | if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { | ||
663 | phba->cfg_nodev_tmo = val; | ||
664 | phba->cfg_devloss_tmo = val; | ||
665 | phba->dev_loss_tmo_changed = 1; | ||
666 | return 0; | ||
667 | } | ||
668 | |||
669 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
670 | "%d:0404 lpfc_devloss_tmo attribute cannot be set to" | ||
671 | " %d, allowed range is [%d, %d]\n", | ||
672 | phba->brd_no, val, LPFC_MIN_DEVLOSS_TMO, | ||
673 | LPFC_MAX_DEVLOSS_TMO); | ||
674 | return -EINVAL; | ||
675 | } | ||
676 | |||
677 | lpfc_param_store(devloss_tmo) | ||
678 | static CLASS_DEVICE_ATTR(lpfc_devloss_tmo, S_IRUGO | S_IWUSR, | ||
679 | lpfc_devloss_tmo_show, lpfc_devloss_tmo_store); | ||
680 | |||
681 | /* | ||
562 | # lpfc_log_verbose: Only turn this flag on if you are willing to risk being | 682 | # lpfc_log_verbose: Only turn this flag on if you are willing to risk being |
563 | # deluged with LOTS of information. | 683 | # deluged with LOTS of information. |
564 | # You can set a bit mask to record specific types of verbose messages: | 684 | # You can set a bit mask to record specific types of verbose messages: |
@@ -617,14 +737,6 @@ LPFC_ATTR_R(scan_down, 1, 0, 1, | |||
617 | "Start scanning for devices from highest ALPA to lowest"); | 737 | "Start scanning for devices from highest ALPA to lowest"); |
618 | 738 | ||
619 | /* | 739 | /* |
620 | # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear | ||
621 | # until the timer expires. Value range is [0,255]. Default value is 30. | ||
622 | # NOTE: this MUST be less then the SCSI Layer command timeout - 1. | ||
623 | */ | ||
624 | LPFC_ATTR_RW(nodev_tmo, 30, 0, 255, | ||
625 | "Seconds driver will hold I/O waiting for a device to come back"); | ||
626 | |||
627 | /* | ||
628 | # lpfc_topology: link topology for init link | 740 | # lpfc_topology: link topology for init link |
629 | # 0x0 = attempt loop mode then point-to-point | 741 | # 0x0 = attempt loop mode then point-to-point |
630 | # 0x01 = internal loopback mode | 742 | # 0x01 = internal loopback mode |
@@ -737,6 +849,7 @@ struct class_device_attribute *lpfc_host_attrs[] = { | |||
737 | &class_device_attr_lpfc_lun_queue_depth, | 849 | &class_device_attr_lpfc_lun_queue_depth, |
738 | &class_device_attr_lpfc_hba_queue_depth, | 850 | &class_device_attr_lpfc_hba_queue_depth, |
739 | &class_device_attr_lpfc_nodev_tmo, | 851 | &class_device_attr_lpfc_nodev_tmo, |
852 | &class_device_attr_lpfc_devloss_tmo, | ||
740 | &class_device_attr_lpfc_fcp_class, | 853 | &class_device_attr_lpfc_fcp_class, |
741 | &class_device_attr_lpfc_use_adisc, | 854 | &class_device_attr_lpfc_use_adisc, |
742 | &class_device_attr_lpfc_ack0, | 855 | &class_device_attr_lpfc_ack0, |
@@ -1450,27 +1563,12 @@ lpfc_get_starget_port_name(struct scsi_target *starget) | |||
1450 | } | 1563 | } |
1451 | 1564 | ||
1452 | static void | 1565 | static void |
1453 | lpfc_get_rport_loss_tmo(struct fc_rport *rport) | ||
1454 | { | ||
1455 | /* | ||
1456 | * Return the driver's global value for device loss timeout plus | ||
1457 | * five seconds to allow the driver's nodev timer to run. | ||
1458 | */ | ||
1459 | rport->dev_loss_tmo = lpfc_nodev_tmo + 5; | ||
1460 | } | ||
1461 | |||
1462 | static void | ||
1463 | lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) | 1566 | lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) |
1464 | { | 1567 | { |
1465 | /* | ||
1466 | * The driver doesn't have a per-target timeout setting. Set | ||
1467 | * this value globally. lpfc_nodev_tmo should be greater then 0. | ||
1468 | */ | ||
1469 | if (timeout) | 1568 | if (timeout) |
1470 | lpfc_nodev_tmo = timeout; | 1569 | rport->dev_loss_tmo = timeout; |
1471 | else | 1570 | else |
1472 | lpfc_nodev_tmo = 1; | 1571 | rport->dev_loss_tmo = 1; |
1473 | rport->dev_loss_tmo = lpfc_nodev_tmo + 5; | ||
1474 | } | 1572 | } |
1475 | 1573 | ||
1476 | 1574 | ||
@@ -1532,7 +1630,6 @@ struct fc_function_template lpfc_transport_functions = { | |||
1532 | .show_rport_maxframe_size = 1, | 1630 | .show_rport_maxframe_size = 1, |
1533 | .show_rport_supported_classes = 1, | 1631 | .show_rport_supported_classes = 1, |
1534 | 1632 | ||
1535 | .get_rport_dev_loss_tmo = lpfc_get_rport_loss_tmo, | ||
1536 | .set_rport_dev_loss_tmo = lpfc_set_rport_loss_tmo, | 1633 | .set_rport_dev_loss_tmo = lpfc_set_rport_loss_tmo, |
1537 | .show_rport_dev_loss_tmo = 1, | 1634 | .show_rport_dev_loss_tmo = 1, |
1538 | 1635 | ||
@@ -1546,6 +1643,8 @@ struct fc_function_template lpfc_transport_functions = { | |||
1546 | .show_starget_port_name = 1, | 1643 | .show_starget_port_name = 1, |
1547 | 1644 | ||
1548 | .issue_fc_host_lip = lpfc_issue_lip, | 1645 | .issue_fc_host_lip = lpfc_issue_lip, |
1646 | .dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk, | ||
1647 | .terminate_rport_io = lpfc_terminate_rport_io, | ||
1549 | }; | 1648 | }; |
1550 | 1649 | ||
1551 | void | 1650 | void |
@@ -1561,13 +1660,13 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) | |||
1561 | lpfc_ack0_init(phba, lpfc_ack0); | 1660 | lpfc_ack0_init(phba, lpfc_ack0); |
1562 | lpfc_topology_init(phba, lpfc_topology); | 1661 | lpfc_topology_init(phba, lpfc_topology); |
1563 | lpfc_scan_down_init(phba, lpfc_scan_down); | 1662 | lpfc_scan_down_init(phba, lpfc_scan_down); |
1564 | lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo); | ||
1565 | lpfc_link_speed_init(phba, lpfc_link_speed); | 1663 | lpfc_link_speed_init(phba, lpfc_link_speed); |
1566 | lpfc_fdmi_on_init(phba, lpfc_fdmi_on); | 1664 | lpfc_fdmi_on_init(phba, lpfc_fdmi_on); |
1567 | lpfc_discovery_threads_init(phba, lpfc_discovery_threads); | 1665 | lpfc_discovery_threads_init(phba, lpfc_discovery_threads); |
1568 | lpfc_max_luns_init(phba, lpfc_max_luns); | 1666 | lpfc_max_luns_init(phba, lpfc_max_luns); |
1569 | lpfc_poll_tmo_init(phba, lpfc_poll_tmo); | 1667 | lpfc_poll_tmo_init(phba, lpfc_poll_tmo); |
1570 | 1668 | lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo); | |
1669 | lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo); | ||
1571 | phba->cfg_poll = lpfc_poll; | 1670 | phba->cfg_poll = lpfc_poll; |
1572 | 1671 | ||
1573 | /* | 1672 | /* |