diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_scsih.c')
| -rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 634 |
1 files changed, 503 insertions, 131 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 1da1aa1a11e2..8889b1babcac 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
| @@ -71,6 +71,9 @@ static void _firmware_event_work(struct work_struct *work); | |||
| 71 | 71 | ||
| 72 | static u8 _scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid); | 72 | static u8 _scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid); |
| 73 | 73 | ||
| 74 | static void _scsih_scan_start(struct Scsi_Host *shost); | ||
| 75 | static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time); | ||
| 76 | |||
| 74 | /* global parameters */ | 77 | /* global parameters */ |
| 75 | LIST_HEAD(mpt2sas_ioc_list); | 78 | LIST_HEAD(mpt2sas_ioc_list); |
| 76 | 79 | ||
| @@ -79,6 +82,7 @@ static u8 scsi_io_cb_idx = -1; | |||
| 79 | static u8 tm_cb_idx = -1; | 82 | static u8 tm_cb_idx = -1; |
| 80 | static u8 ctl_cb_idx = -1; | 83 | static u8 ctl_cb_idx = -1; |
| 81 | static u8 base_cb_idx = -1; | 84 | static u8 base_cb_idx = -1; |
| 85 | static u8 port_enable_cb_idx = -1; | ||
| 82 | static u8 transport_cb_idx = -1; | 86 | static u8 transport_cb_idx = -1; |
| 83 | static u8 scsih_cb_idx = -1; | 87 | static u8 scsih_cb_idx = -1; |
| 84 | static u8 config_cb_idx = -1; | 88 | static u8 config_cb_idx = -1; |
| @@ -103,6 +107,18 @@ static int max_lun = MPT2SAS_MAX_LUN; | |||
| 103 | module_param(max_lun, int, 0); | 107 | module_param(max_lun, int, 0); |
| 104 | MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); | 108 | MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); |
| 105 | 109 | ||
| 110 | /* diag_buffer_enable is bitwise | ||
| 111 | * bit 0 set = TRACE | ||
| 112 | * bit 1 set = SNAPSHOT | ||
| 113 | * bit 2 set = EXTENDED | ||
| 114 | * | ||
| 115 | * Either bit can be set, or both | ||
| 116 | */ | ||
| 117 | static int diag_buffer_enable = -1; | ||
| 118 | module_param(diag_buffer_enable, int, 0); | ||
| 119 | MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers " | ||
| 120 | "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)"); | ||
| 121 | |||
| 106 | /** | 122 | /** |
| 107 | * struct sense_info - common structure for obtaining sense keys | 123 | * struct sense_info - common structure for obtaining sense keys |
| 108 | * @skey: sense key | 124 | * @skey: sense key |
| @@ -117,8 +133,8 @@ struct sense_info { | |||
| 117 | 133 | ||
| 118 | 134 | ||
| 119 | #define MPT2SAS_TURN_ON_FAULT_LED (0xFFFC) | 135 | #define MPT2SAS_TURN_ON_FAULT_LED (0xFFFC) |
| 120 | #define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF) | 136 | #define MPT2SAS_PORT_ENABLE_COMPLETE (0xFFFD) |
| 121 | 137 | #define MPT2SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF) | |
| 122 | /** | 138 | /** |
| 123 | * struct fw_event_work - firmware event struct | 139 | * struct fw_event_work - firmware event struct |
| 124 | * @list: link list framework | 140 | * @list: link list framework |
| @@ -372,31 +388,34 @@ _scsih_get_sas_address(struct MPT2SAS_ADAPTER *ioc, u16 handle, | |||
| 372 | Mpi2SasDevicePage0_t sas_device_pg0; | 388 | Mpi2SasDevicePage0_t sas_device_pg0; |
| 373 | Mpi2ConfigReply_t mpi_reply; | 389 | Mpi2ConfigReply_t mpi_reply; |
| 374 | u32 ioc_status; | 390 | u32 ioc_status; |
| 391 | *sas_address = 0; | ||
| 375 | 392 | ||
| 376 | if (handle <= ioc->sas_hba.num_phys) { | 393 | if (handle <= ioc->sas_hba.num_phys) { |
| 377 | *sas_address = ioc->sas_hba.sas_address; | 394 | *sas_address = ioc->sas_hba.sas_address; |
| 378 | return 0; | 395 | return 0; |
| 379 | } else | 396 | } |
| 380 | *sas_address = 0; | ||
| 381 | 397 | ||
| 382 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | 398 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, |
| 383 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { | 399 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { |
| 384 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 400 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, |
| 385 | ioc->name, __FILE__, __LINE__, __func__); | 401 | __FILE__, __LINE__, __func__); |
| 386 | return -ENXIO; | 402 | return -ENXIO; |
| 387 | } | 403 | } |
| 388 | 404 | ||
| 389 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | 405 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; |
| 390 | MPI2_IOCSTATUS_MASK; | 406 | if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { |
| 391 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | 407 | *sas_address = le64_to_cpu(sas_device_pg0.SASAddress); |
| 392 | printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)" | 408 | return 0; |
| 393 | "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status, | ||
| 394 | __FILE__, __LINE__, __func__); | ||
| 395 | return -EIO; | ||
| 396 | } | 409 | } |
| 397 | 410 | ||
| 398 | *sas_address = le64_to_cpu(sas_device_pg0.SASAddress); | 411 | /* we hit this becuase the given parent handle doesn't exist */ |
| 399 | return 0; | 412 | if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) |
| 413 | return -ENXIO; | ||
| 414 | /* else error case */ | ||
| 415 | printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x), " | ||
| 416 | "failure at %s:%d/%s()!\n", ioc->name, handle, ioc_status, | ||
| 417 | __FILE__, __LINE__, __func__); | ||
| 418 | return -EIO; | ||
| 400 | } | 419 | } |
| 401 | 420 | ||
| 402 | /** | 421 | /** |
| @@ -424,7 +443,11 @@ _scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc, | |||
| 424 | u16 slot; | 443 | u16 slot; |
| 425 | 444 | ||
| 426 | /* only process this function when driver loads */ | 445 | /* only process this function when driver loads */ |
| 427 | if (!ioc->wait_for_port_enable_to_complete) | 446 | if (!ioc->is_driver_loading) |
| 447 | return; | ||
| 448 | |||
| 449 | /* no Bios, return immediately */ | ||
| 450 | if (!ioc->bios_pg3.BiosVersion) | ||
| 428 | return; | 451 | return; |
| 429 | 452 | ||
| 430 | if (!is_raid) { | 453 | if (!is_raid) { |
| @@ -587,8 +610,15 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc, | |||
| 587 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 610 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 588 | 611 | ||
| 589 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, | 612 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, |
| 590 | sas_device->sas_address_parent)) | 613 | sas_device->sas_address_parent)) { |
| 591 | _scsih_sas_device_remove(ioc, sas_device); | 614 | _scsih_sas_device_remove(ioc, sas_device); |
| 615 | } else if (!sas_device->starget) { | ||
| 616 | if (!ioc->is_driver_loading) | ||
| 617 | mpt2sas_transport_port_remove(ioc, | ||
| 618 | sas_device->sas_address, | ||
| 619 | sas_device->sas_address_parent); | ||
| 620 | _scsih_sas_device_remove(ioc, sas_device); | ||
| 621 | } | ||
| 592 | } | 622 | } |
| 593 | 623 | ||
| 594 | /** | 624 | /** |
| @@ -1400,6 +1430,10 @@ _scsih_slave_destroy(struct scsi_device *sdev) | |||
| 1400 | { | 1430 | { |
| 1401 | struct MPT2SAS_TARGET *sas_target_priv_data; | 1431 | struct MPT2SAS_TARGET *sas_target_priv_data; |
| 1402 | struct scsi_target *starget; | 1432 | struct scsi_target *starget; |
| 1433 | struct Scsi_Host *shost; | ||
| 1434 | struct MPT2SAS_ADAPTER *ioc; | ||
| 1435 | struct _sas_device *sas_device; | ||
| 1436 | unsigned long flags; | ||
| 1403 | 1437 | ||
| 1404 | if (!sdev->hostdata) | 1438 | if (!sdev->hostdata) |
| 1405 | return; | 1439 | return; |
| @@ -1407,6 +1441,19 @@ _scsih_slave_destroy(struct scsi_device *sdev) | |||
| 1407 | starget = scsi_target(sdev); | 1441 | starget = scsi_target(sdev); |
| 1408 | sas_target_priv_data = starget->hostdata; | 1442 | sas_target_priv_data = starget->hostdata; |
| 1409 | sas_target_priv_data->num_luns--; | 1443 | sas_target_priv_data->num_luns--; |
| 1444 | |||
| 1445 | shost = dev_to_shost(&starget->dev); | ||
| 1446 | ioc = shost_priv(shost); | ||
| 1447 | |||
| 1448 | if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { | ||
| 1449 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 1450 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | ||
| 1451 | sas_target_priv_data->sas_address); | ||
| 1452 | if (sas_device) | ||
| 1453 | sas_device->starget = NULL; | ||
| 1454 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 1455 | } | ||
| 1456 | |||
| 1410 | kfree(sdev->hostdata); | 1457 | kfree(sdev->hostdata); |
| 1411 | sdev->hostdata = NULL; | 1458 | sdev->hostdata = NULL; |
| 1412 | } | 1459 | } |
| @@ -1598,8 +1645,10 @@ _scsih_set_level(struct scsi_device *sdev, struct _raid_device *raid_device) | |||
| 1598 | * _scsih_get_volume_capabilities - volume capabilities | 1645 | * _scsih_get_volume_capabilities - volume capabilities |
| 1599 | * @ioc: per adapter object | 1646 | * @ioc: per adapter object |
| 1600 | * @sas_device: the raid_device object | 1647 | * @sas_device: the raid_device object |
| 1648 | * | ||
| 1649 | * Returns 0 for success, else 1 | ||
| 1601 | */ | 1650 | */ |
| 1602 | static void | 1651 | static int |
| 1603 | _scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc, | 1652 | _scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc, |
| 1604 | struct _raid_device *raid_device) | 1653 | struct _raid_device *raid_device) |
| 1605 | { | 1654 | { |
| @@ -1612,9 +1661,10 @@ _scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc, | |||
| 1612 | 1661 | ||
| 1613 | if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle, | 1662 | if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle, |
| 1614 | &num_pds)) || !num_pds) { | 1663 | &num_pds)) || !num_pds) { |
| 1615 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 1664 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT |
| 1616 | ioc->name, __FILE__, __LINE__, __func__); | 1665 | "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, |
| 1617 | return; | 1666 | __func__)); |
| 1667 | return 1; | ||
| 1618 | } | 1668 | } |
| 1619 | 1669 | ||
| 1620 | raid_device->num_pds = num_pds; | 1670 | raid_device->num_pds = num_pds; |
| @@ -1622,17 +1672,19 @@ _scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc, | |||
| 1622 | sizeof(Mpi2RaidVol0PhysDisk_t)); | 1672 | sizeof(Mpi2RaidVol0PhysDisk_t)); |
| 1623 | vol_pg0 = kzalloc(sz, GFP_KERNEL); | 1673 | vol_pg0 = kzalloc(sz, GFP_KERNEL); |
| 1624 | if (!vol_pg0) { | 1674 | if (!vol_pg0) { |
| 1625 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 1675 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT |
| 1626 | ioc->name, __FILE__, __LINE__, __func__); | 1676 | "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, |
| 1627 | return; | 1677 | __func__)); |
| 1678 | return 1; | ||
| 1628 | } | 1679 | } |
| 1629 | 1680 | ||
| 1630 | if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0, | 1681 | if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0, |
| 1631 | MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) { | 1682 | MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) { |
| 1632 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 1683 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT |
| 1633 | ioc->name, __FILE__, __LINE__, __func__); | 1684 | "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, |
| 1685 | __func__)); | ||
| 1634 | kfree(vol_pg0); | 1686 | kfree(vol_pg0); |
| 1635 | return; | 1687 | return 1; |
| 1636 | } | 1688 | } |
| 1637 | 1689 | ||
| 1638 | raid_device->volume_type = vol_pg0->VolumeType; | 1690 | raid_device->volume_type = vol_pg0->VolumeType; |
| @@ -1652,6 +1704,7 @@ _scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc, | |||
| 1652 | } | 1704 | } |
| 1653 | 1705 | ||
| 1654 | kfree(vol_pg0); | 1706 | kfree(vol_pg0); |
| 1707 | return 0; | ||
| 1655 | } | 1708 | } |
| 1656 | /** | 1709 | /** |
| 1657 | * _scsih_disable_ddio - Disable direct I/O for all the volumes | 1710 | * _scsih_disable_ddio - Disable direct I/O for all the volumes |
| @@ -1922,13 +1975,20 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 1922 | sas_target_priv_data->handle); | 1975 | sas_target_priv_data->handle); |
| 1923 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | 1976 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); |
| 1924 | if (!raid_device) { | 1977 | if (!raid_device) { |
| 1925 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 1978 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT |
| 1926 | ioc->name, __FILE__, __LINE__, __func__); | 1979 | "failure at %s:%d/%s()!\n", ioc->name, __FILE__, |
| 1927 | return 0; | 1980 | __LINE__, __func__)); |
| 1981 | return 1; | ||
| 1928 | } | 1982 | } |
| 1929 | 1983 | ||
| 1930 | _scsih_get_volume_capabilities(ioc, raid_device); | 1984 | _scsih_get_volume_capabilities(ioc, raid_device); |
| 1931 | 1985 | ||
| 1986 | if (_scsih_get_volume_capabilities(ioc, raid_device)) { | ||
| 1987 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT | ||
| 1988 | "failure at %s:%d/%s()!\n", ioc->name, __FILE__, | ||
| 1989 | __LINE__, __func__)); | ||
| 1990 | return 1; | ||
| 1991 | } | ||
| 1932 | /* | 1992 | /* |
| 1933 | * WARPDRIVE: Initialize the required data for Direct IO | 1993 | * WARPDRIVE: Initialize the required data for Direct IO |
| 1934 | */ | 1994 | */ |
| @@ -2002,11 +2062,22 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 2002 | if (sas_device) { | 2062 | if (sas_device) { |
| 2003 | if (sas_target_priv_data->flags & | 2063 | if (sas_target_priv_data->flags & |
| 2004 | MPT_TARGET_FLAGS_RAID_COMPONENT) { | 2064 | MPT_TARGET_FLAGS_RAID_COMPONENT) { |
| 2005 | mpt2sas_config_get_volume_handle(ioc, | 2065 | if (mpt2sas_config_get_volume_handle(ioc, |
| 2006 | sas_device->handle, &sas_device->volume_handle); | 2066 | sas_device->handle, &sas_device->volume_handle)) { |
| 2007 | mpt2sas_config_get_volume_wwid(ioc, | 2067 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT |
| 2068 | "failure at %s:%d/%s()!\n", ioc->name, | ||
| 2069 | __FILE__, __LINE__, __func__)); | ||
| 2070 | return 1; | ||
| 2071 | } | ||
| 2072 | if (sas_device->volume_handle && | ||
| 2073 | mpt2sas_config_get_volume_wwid(ioc, | ||
| 2008 | sas_device->volume_handle, | 2074 | sas_device->volume_handle, |
| 2009 | &sas_device->volume_wwid); | 2075 | &sas_device->volume_wwid)) { |
| 2076 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT | ||
| 2077 | "failure at %s:%d/%s()!\n", ioc->name, | ||
| 2078 | __FILE__, __LINE__, __func__)); | ||
| 2079 | return 1; | ||
| 2080 | } | ||
| 2010 | } | 2081 | } |
| 2011 | if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) { | 2082 | if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) { |
| 2012 | qdepth = MPT2SAS_SAS_QUEUE_DEPTH; | 2083 | qdepth = MPT2SAS_SAS_QUEUE_DEPTH; |
| @@ -2035,6 +2106,11 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 2035 | 2106 | ||
| 2036 | if (!ssp_target) | 2107 | if (!ssp_target) |
| 2037 | _scsih_display_sata_capabilities(ioc, sas_device, sdev); | 2108 | _scsih_display_sata_capabilities(ioc, sas_device, sdev); |
| 2109 | } else { | ||
| 2110 | dfailprintk(ioc, printk(MPT2SAS_WARN_FMT | ||
| 2111 | "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, | ||
| 2112 | __func__)); | ||
| 2113 | return 1; | ||
| 2038 | } | 2114 | } |
| 2039 | 2115 | ||
| 2040 | _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); | 2116 | _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); |
| @@ -2714,22 +2790,38 @@ _scsih_fw_event_free(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work | |||
| 2714 | 2790 | ||
| 2715 | 2791 | ||
| 2716 | /** | 2792 | /** |
| 2717 | * _scsih_queue_rescan - queue a topology rescan from user context | 2793 | * _scsih_error_recovery_delete_devices - remove devices not responding |
| 2718 | * @ioc: per adapter object | 2794 | * @ioc: per adapter object |
| 2719 | * | 2795 | * |
| 2720 | * Return nothing. | 2796 | * Return nothing. |
| 2721 | */ | 2797 | */ |
| 2722 | static void | 2798 | static void |
| 2723 | _scsih_queue_rescan(struct MPT2SAS_ADAPTER *ioc) | 2799 | _scsih_error_recovery_delete_devices(struct MPT2SAS_ADAPTER *ioc) |
| 2724 | { | 2800 | { |
| 2725 | struct fw_event_work *fw_event; | 2801 | struct fw_event_work *fw_event; |
| 2726 | 2802 | ||
| 2727 | if (ioc->wait_for_port_enable_to_complete) | 2803 | if (ioc->is_driver_loading) |
| 2728 | return; | 2804 | return; |
| 2805 | fw_event->event = MPT2SAS_REMOVE_UNRESPONDING_DEVICES; | ||
| 2806 | fw_event->ioc = ioc; | ||
| 2807 | _scsih_fw_event_add(ioc, fw_event); | ||
| 2808 | } | ||
| 2809 | |||
| 2810 | /** | ||
| 2811 | * mpt2sas_port_enable_complete - port enable completed (fake event) | ||
| 2812 | * @ioc: per adapter object | ||
| 2813 | * | ||
| 2814 | * Return nothing. | ||
| 2815 | */ | ||
| 2816 | void | ||
| 2817 | mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc) | ||
| 2818 | { | ||
| 2819 | struct fw_event_work *fw_event; | ||
| 2820 | |||
| 2729 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); | 2821 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); |
| 2730 | if (!fw_event) | 2822 | if (!fw_event) |
| 2731 | return; | 2823 | return; |
| 2732 | fw_event->event = MPT2SAS_RESCAN_AFTER_HOST_RESET; | 2824 | fw_event->event = MPT2SAS_PORT_ENABLE_COMPLETE; |
| 2733 | fw_event->ioc = ioc; | 2825 | fw_event->ioc = ioc; |
| 2734 | _scsih_fw_event_add(ioc, fw_event); | 2826 | _scsih_fw_event_add(ioc, fw_event); |
| 2735 | } | 2827 | } |
| @@ -2977,14 +3069,27 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 2977 | Mpi2SCSITaskManagementRequest_t *mpi_request; | 3069 | Mpi2SCSITaskManagementRequest_t *mpi_request; |
| 2978 | u16 smid; | 3070 | u16 smid; |
| 2979 | struct _sas_device *sas_device; | 3071 | struct _sas_device *sas_device; |
| 2980 | struct MPT2SAS_TARGET *sas_target_priv_data; | 3072 | struct MPT2SAS_TARGET *sas_target_priv_data = NULL; |
| 3073 | u64 sas_address = 0; | ||
| 2981 | unsigned long flags; | 3074 | unsigned long flags; |
| 2982 | struct _tr_list *delayed_tr; | 3075 | struct _tr_list *delayed_tr; |
| 3076 | u32 ioc_state; | ||
| 2983 | 3077 | ||
| 2984 | if (ioc->shost_recovery || ioc->remove_host || | 3078 | if (ioc->remove_host) { |
| 2985 | ioc->pci_error_recovery) { | 3079 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been " |
| 2986 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in " | 3080 | "removed: handle(0x%04x)\n", __func__, ioc->name, handle)); |
| 2987 | "progress!\n", __func__, ioc->name)); | 3081 | return; |
| 3082 | } else if (ioc->pci_error_recovery) { | ||
| 3083 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci " | ||
| 3084 | "error recovery: handle(0x%04x)\n", __func__, ioc->name, | ||
| 3085 | handle)); | ||
| 3086 | return; | ||
| 3087 | } | ||
| 3088 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 3089 | if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | ||
| 3090 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not " | ||
| 3091 | "operational: handle(0x%04x)\n", __func__, ioc->name, | ||
| 3092 | handle)); | ||
| 2988 | return; | 3093 | return; |
| 2989 | } | 3094 | } |
| 2990 | 3095 | ||
| @@ -2998,13 +3103,18 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 2998 | sas_device->starget->hostdata) { | 3103 | sas_device->starget->hostdata) { |
| 2999 | sas_target_priv_data = sas_device->starget->hostdata; | 3104 | sas_target_priv_data = sas_device->starget->hostdata; |
| 3000 | sas_target_priv_data->deleted = 1; | 3105 | sas_target_priv_data->deleted = 1; |
| 3001 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | 3106 | sas_address = sas_device->sas_address; |
| 3002 | "setting delete flag: handle(0x%04x), " | ||
| 3003 | "sas_addr(0x%016llx)\n", ioc->name, handle, | ||
| 3004 | (unsigned long long) sas_device->sas_address)); | ||
| 3005 | } | 3107 | } |
| 3006 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 3108 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 3007 | 3109 | ||
| 3110 | if (sas_target_priv_data) { | ||
| 3111 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "setting delete flag: " | ||
| 3112 | "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, handle, | ||
| 3113 | (unsigned long long)sas_address)); | ||
| 3114 | _scsih_ublock_io_device(ioc, handle); | ||
| 3115 | sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE; | ||
| 3116 | } | ||
| 3117 | |||
| 3008 | smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx); | 3118 | smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx); |
| 3009 | if (!smid) { | 3119 | if (!smid) { |
| 3010 | delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); | 3120 | delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); |
| @@ -3185,11 +3295,21 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
| 3185 | mpt2sas_base_get_reply_virt_addr(ioc, reply); | 3295 | mpt2sas_base_get_reply_virt_addr(ioc, reply); |
| 3186 | Mpi2SasIoUnitControlRequest_t *mpi_request; | 3296 | Mpi2SasIoUnitControlRequest_t *mpi_request; |
| 3187 | u16 smid_sas_ctrl; | 3297 | u16 smid_sas_ctrl; |
| 3298 | u32 ioc_state; | ||
| 3188 | 3299 | ||
| 3189 | if (ioc->shost_recovery || ioc->remove_host || | 3300 | if (ioc->remove_host) { |
| 3190 | ioc->pci_error_recovery) { | 3301 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been " |
| 3191 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in " | 3302 | "removed\n", __func__, ioc->name)); |
| 3192 | "progress!\n", __func__, ioc->name)); | 3303 | return 1; |
| 3304 | } else if (ioc->pci_error_recovery) { | ||
| 3305 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci " | ||
| 3306 | "error recovery\n", __func__, ioc->name)); | ||
| 3307 | return 1; | ||
| 3308 | } | ||
| 3309 | ioc_state = mpt2sas_base_get_iocstate(ioc, 1); | ||
| 3310 | if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { | ||
| 3311 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not " | ||
| 3312 | "operational\n", __func__, ioc->name)); | ||
| 3193 | return 1; | 3313 | return 1; |
| 3194 | } | 3314 | } |
| 3195 | 3315 | ||
| @@ -5099,7 +5219,7 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
| 5099 | /* get device name */ | 5219 | /* get device name */ |
| 5100 | sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName); | 5220 | sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName); |
| 5101 | 5221 | ||
| 5102 | if (ioc->wait_for_port_enable_to_complete) | 5222 | if (ioc->wait_for_discovery_to_complete) |
| 5103 | _scsih_sas_device_init_add(ioc, sas_device); | 5223 | _scsih_sas_device_init_add(ioc, sas_device); |
| 5104 | else | 5224 | else |
| 5105 | _scsih_sas_device_add(ioc, sas_device); | 5225 | _scsih_sas_device_add(ioc, sas_device); |
| @@ -5135,6 +5255,9 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, | |||
| 5135 | if (sas_device_backup.starget && sas_device_backup.starget->hostdata) { | 5255 | if (sas_device_backup.starget && sas_device_backup.starget->hostdata) { |
| 5136 | sas_target_priv_data = sas_device_backup.starget->hostdata; | 5256 | sas_target_priv_data = sas_device_backup.starget->hostdata; |
| 5137 | sas_target_priv_data->deleted = 1; | 5257 | sas_target_priv_data->deleted = 1; |
| 5258 | _scsih_ublock_io_device(ioc, sas_device_backup.handle); | ||
| 5259 | sas_target_priv_data->handle = | ||
| 5260 | MPT2SAS_INVALID_DEVICE_HANDLE; | ||
| 5138 | } | 5261 | } |
| 5139 | 5262 | ||
| 5140 | _scsih_ublock_io_device(ioc, sas_device_backup.handle); | 5263 | _scsih_ublock_io_device(ioc, sas_device_backup.handle); |
| @@ -5288,7 +5411,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 5288 | _scsih_sas_topology_change_event_debug(ioc, event_data); | 5411 | _scsih_sas_topology_change_event_debug(ioc, event_data); |
| 5289 | #endif | 5412 | #endif |
| 5290 | 5413 | ||
| 5291 | if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery) | 5414 | if (ioc->remove_host || ioc->pci_error_recovery) |
| 5292 | return; | 5415 | return; |
| 5293 | 5416 | ||
| 5294 | if (!ioc->sas_hba.num_phys) | 5417 | if (!ioc->sas_hba.num_phys) |
| @@ -5349,6 +5472,9 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 5349 | switch (reason_code) { | 5472 | switch (reason_code) { |
| 5350 | case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: | 5473 | case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: |
| 5351 | 5474 | ||
| 5475 | if (ioc->shost_recovery) | ||
| 5476 | break; | ||
| 5477 | |||
| 5352 | if (link_rate == prev_link_rate) | 5478 | if (link_rate == prev_link_rate) |
| 5353 | break; | 5479 | break; |
| 5354 | 5480 | ||
| @@ -5362,6 +5488,9 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 5362 | break; | 5488 | break; |
| 5363 | case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: | 5489 | case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: |
| 5364 | 5490 | ||
| 5491 | if (ioc->shost_recovery) | ||
| 5492 | break; | ||
| 5493 | |||
| 5365 | mpt2sas_transport_update_links(ioc, sas_address, | 5494 | mpt2sas_transport_update_links(ioc, sas_address, |
| 5366 | handle, phy_number, link_rate); | 5495 | handle, phy_number, link_rate); |
| 5367 | 5496 | ||
| @@ -5622,7 +5751,7 @@ broadcast_aen_retry: | |||
| 5622 | termination_count = 0; | 5751 | termination_count = 0; |
| 5623 | query_count = 0; | 5752 | query_count = 0; |
| 5624 | for (smid = 1; smid <= ioc->scsiio_depth; smid++) { | 5753 | for (smid = 1; smid <= ioc->scsiio_depth; smid++) { |
| 5625 | if (ioc->ioc_reset_in_progress_status) | 5754 | if (ioc->shost_recovery) |
| 5626 | goto out; | 5755 | goto out; |
| 5627 | scmd = _scsih_scsi_lookup_get(ioc, smid); | 5756 | scmd = _scsih_scsi_lookup_get(ioc, smid); |
| 5628 | if (!scmd) | 5757 | if (!scmd) |
| @@ -5644,7 +5773,7 @@ broadcast_aen_retry: | |||
| 5644 | lun = sas_device_priv_data->lun; | 5773 | lun = sas_device_priv_data->lun; |
| 5645 | query_count++; | 5774 | query_count++; |
| 5646 | 5775 | ||
| 5647 | if (ioc->ioc_reset_in_progress_status) | 5776 | if (ioc->shost_recovery) |
| 5648 | goto out; | 5777 | goto out; |
| 5649 | 5778 | ||
| 5650 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | 5779 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); |
| @@ -5686,7 +5815,7 @@ broadcast_aen_retry: | |||
| 5686 | goto broadcast_aen_retry; | 5815 | goto broadcast_aen_retry; |
| 5687 | } | 5816 | } |
| 5688 | 5817 | ||
| 5689 | if (ioc->ioc_reset_in_progress_status) | 5818 | if (ioc->shost_recovery) |
| 5690 | goto out_no_lock; | 5819 | goto out_no_lock; |
| 5691 | 5820 | ||
| 5692 | r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id, | 5821 | r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id, |
| @@ -5725,7 +5854,7 @@ broadcast_aen_retry: | |||
| 5725 | ioc->name, __func__, query_count, termination_count)); | 5854 | ioc->name, __func__, query_count, termination_count)); |
| 5726 | 5855 | ||
| 5727 | ioc->broadcast_aen_busy = 0; | 5856 | ioc->broadcast_aen_busy = 0; |
| 5728 | if (!ioc->ioc_reset_in_progress_status) | 5857 | if (!ioc->shost_recovery) |
| 5729 | _scsih_ublock_io_all_device(ioc); | 5858 | _scsih_ublock_io_all_device(ioc); |
| 5730 | mutex_unlock(&ioc->tm_cmds.mutex); | 5859 | mutex_unlock(&ioc->tm_cmds.mutex); |
| 5731 | } | 5860 | } |
| @@ -5789,8 +5918,11 @@ _scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach) | |||
| 5789 | static void | 5918 | static void |
| 5790 | _scsih_reprobe_target(struct scsi_target *starget, int no_uld_attach) | 5919 | _scsih_reprobe_target(struct scsi_target *starget, int no_uld_attach) |
| 5791 | { | 5920 | { |
| 5792 | struct MPT2SAS_TARGET *sas_target_priv_data = starget->hostdata; | 5921 | struct MPT2SAS_TARGET *sas_target_priv_data; |
| 5793 | 5922 | ||
| 5923 | if (starget == NULL) | ||
| 5924 | return; | ||
| 5925 | sas_target_priv_data = starget->hostdata; | ||
| 5794 | if (no_uld_attach) | 5926 | if (no_uld_attach) |
| 5795 | sas_target_priv_data->flags |= MPT_TARGET_FLAGS_RAID_COMPONENT; | 5927 | sas_target_priv_data->flags |= MPT_TARGET_FLAGS_RAID_COMPONENT; |
| 5796 | else | 5928 | else |
| @@ -5845,7 +5977,7 @@ _scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc, | |||
| 5845 | raid_device->handle = handle; | 5977 | raid_device->handle = handle; |
| 5846 | raid_device->wwid = wwid; | 5978 | raid_device->wwid = wwid; |
| 5847 | _scsih_raid_device_add(ioc, raid_device); | 5979 | _scsih_raid_device_add(ioc, raid_device); |
| 5848 | if (!ioc->wait_for_port_enable_to_complete) { | 5980 | if (!ioc->wait_for_discovery_to_complete) { |
| 5849 | rc = scsi_add_device(ioc->shost, RAID_CHANNEL, | 5981 | rc = scsi_add_device(ioc->shost, RAID_CHANNEL, |
| 5850 | raid_device->id, 0); | 5982 | raid_device->id, 0); |
| 5851 | if (rc) | 5983 | if (rc) |
| @@ -6127,6 +6259,10 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 6127 | _scsih_sas_ir_config_change_event_debug(ioc, event_data); | 6259 | _scsih_sas_ir_config_change_event_debug(ioc, event_data); |
| 6128 | 6260 | ||
| 6129 | #endif | 6261 | #endif |
| 6262 | |||
| 6263 | if (ioc->shost_recovery) | ||
| 6264 | return; | ||
| 6265 | |||
| 6130 | foreign_config = (le32_to_cpu(event_data->Flags) & | 6266 | foreign_config = (le32_to_cpu(event_data->Flags) & |
| 6131 | MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0; | 6267 | MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0; |
| 6132 | 6268 | ||
| @@ -6185,6 +6321,9 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 6185 | int rc; | 6321 | int rc; |
| 6186 | Mpi2EventDataIrVolume_t *event_data = fw_event->event_data; | 6322 | Mpi2EventDataIrVolume_t *event_data = fw_event->event_data; |
| 6187 | 6323 | ||
| 6324 | if (ioc->shost_recovery) | ||
| 6325 | return; | ||
| 6326 | |||
| 6188 | if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) | 6327 | if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) |
| 6189 | return; | 6328 | return; |
| 6190 | 6329 | ||
| @@ -6267,6 +6406,9 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 6267 | Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; | 6406 | Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; |
| 6268 | u64 sas_address; | 6407 | u64 sas_address; |
| 6269 | 6408 | ||
| 6409 | if (ioc->shost_recovery) | ||
| 6410 | return; | ||
| 6411 | |||
| 6270 | if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) | 6412 | if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) |
| 6271 | return; | 6413 | return; |
| 6272 | 6414 | ||
| @@ -6510,10 +6652,10 @@ _scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 6510 | u32 device_info; | 6652 | u32 device_info; |
| 6511 | u16 slot; | 6653 | u16 slot; |
| 6512 | 6654 | ||
| 6513 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__); | 6655 | printk(MPT2SAS_INFO_FMT "search for end-devices: start\n", ioc->name); |
| 6514 | 6656 | ||
| 6515 | if (list_empty(&ioc->sas_device_list)) | 6657 | if (list_empty(&ioc->sas_device_list)) |
| 6516 | return; | 6658 | goto out; |
| 6517 | 6659 | ||
| 6518 | handle = 0xFFFF; | 6660 | handle = 0xFFFF; |
| 6519 | while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, | 6661 | while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, |
| @@ -6532,6 +6674,9 @@ _scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 6532 | _scsih_mark_responding_sas_device(ioc, sas_address, slot, | 6674 | _scsih_mark_responding_sas_device(ioc, sas_address, slot, |
| 6533 | handle); | 6675 | handle); |
| 6534 | } | 6676 | } |
| 6677 | out: | ||
| 6678 | printk(MPT2SAS_INFO_FMT "search for end-devices: complete\n", | ||
| 6679 | ioc->name); | ||
| 6535 | } | 6680 | } |
| 6536 | 6681 | ||
| 6537 | /** | 6682 | /** |
| @@ -6607,10 +6752,14 @@ _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 6607 | u16 handle; | 6752 | u16 handle; |
| 6608 | u8 phys_disk_num; | 6753 | u8 phys_disk_num; |
| 6609 | 6754 | ||
| 6610 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__); | 6755 | if (!ioc->ir_firmware) |
| 6756 | return; | ||
| 6757 | |||
| 6758 | printk(MPT2SAS_INFO_FMT "search for raid volumes: start\n", | ||
| 6759 | ioc->name); | ||
| 6611 | 6760 | ||
| 6612 | if (list_empty(&ioc->raid_device_list)) | 6761 | if (list_empty(&ioc->raid_device_list)) |
| 6613 | return; | 6762 | goto out; |
| 6614 | 6763 | ||
| 6615 | handle = 0xFFFF; | 6764 | handle = 0xFFFF; |
| 6616 | while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, | 6765 | while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, |
| @@ -6649,6 +6798,9 @@ _scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 6649 | set_bit(handle, ioc->pd_handles); | 6798 | set_bit(handle, ioc->pd_handles); |
| 6650 | } | 6799 | } |
| 6651 | } | 6800 | } |
| 6801 | out: | ||
| 6802 | printk(MPT2SAS_INFO_FMT "search for responding raid volumes: " | ||
| 6803 | "complete\n", ioc->name); | ||
| 6652 | } | 6804 | } |
| 6653 | 6805 | ||
| 6654 | /** | 6806 | /** |
| @@ -6708,10 +6860,10 @@ _scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc) | |||
| 6708 | u64 sas_address; | 6860 | u64 sas_address; |
| 6709 | u16 handle; | 6861 | u16 handle; |
| 6710 | 6862 | ||
| 6711 | printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__); | 6863 | printk(MPT2SAS_INFO_FMT "search for expanders: start\n", ioc->name); |
| 6712 | 6864 | ||
| 6713 | if (list_empty(&ioc->sas_expander_list)) | 6865 | if (list_empty(&ioc->sas_expander_list)) |
| 6714 | return; | 6866 | goto out; |
| 6715 | 6867 | ||
| 6716 | handle = 0xFFFF; | 6868 | handle = 0xFFFF; |
| 6717 | while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, | 6869 | while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, |
| @@ -6730,6 +6882,8 @@ _scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc) | |||
| 6730 | _scsih_mark_responding_expander(ioc, sas_address, handle); | 6882 | _scsih_mark_responding_expander(ioc, sas_address, handle); |
| 6731 | } | 6883 | } |
| 6732 | 6884 | ||
| 6885 | out: | ||
| 6886 | printk(MPT2SAS_INFO_FMT "search for expanders: complete\n", ioc->name); | ||
| 6733 | } | 6887 | } |
| 6734 | 6888 | ||
| 6735 | /** | 6889 | /** |
| @@ -6745,6 +6899,8 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 6745 | struct _sas_node *sas_expander; | 6899 | struct _sas_node *sas_expander; |
| 6746 | struct _raid_device *raid_device, *raid_device_next; | 6900 | struct _raid_device *raid_device, *raid_device_next; |
| 6747 | 6901 | ||
| 6902 | printk(MPT2SAS_INFO_FMT "removing unresponding devices: start\n", | ||
| 6903 | ioc->name); | ||
| 6748 | 6904 | ||
| 6749 | list_for_each_entry_safe(sas_device, sas_device_next, | 6905 | list_for_each_entry_safe(sas_device, sas_device_next, |
| 6750 | &ioc->sas_device_list, list) { | 6906 | &ioc->sas_device_list, list) { |
| @@ -6764,6 +6920,9 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 6764 | _scsih_remove_device(ioc, sas_device); | 6920 | _scsih_remove_device(ioc, sas_device); |
| 6765 | } | 6921 | } |
| 6766 | 6922 | ||
| 6923 | if (!ioc->ir_firmware) | ||
| 6924 | goto retry_expander_search; | ||
| 6925 | |||
| 6767 | list_for_each_entry_safe(raid_device, raid_device_next, | 6926 | list_for_each_entry_safe(raid_device, raid_device_next, |
| 6768 | &ioc->raid_device_list, list) { | 6927 | &ioc->raid_device_list, list) { |
| 6769 | if (raid_device->responding) { | 6928 | if (raid_device->responding) { |
| @@ -6790,52 +6949,170 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 6790 | mpt2sas_expander_remove(ioc, sas_expander->sas_address); | 6949 | mpt2sas_expander_remove(ioc, sas_expander->sas_address); |
| 6791 | goto retry_expander_search; | 6950 | goto retry_expander_search; |
| 6792 | } | 6951 | } |
| 6952 | printk(MPT2SAS_INFO_FMT "removing unresponding devices: complete\n", | ||
| 6953 | ioc->name); | ||
| 6954 | /* unblock devices */ | ||
| 6955 | _scsih_ublock_io_all_device(ioc); | ||
| 6956 | } | ||
| 6957 | |||
| 6958 | static void | ||
| 6959 | _scsih_refresh_expander_links(struct MPT2SAS_ADAPTER *ioc, | ||
| 6960 | struct _sas_node *sas_expander, u16 handle) | ||
| 6961 | { | ||
| 6962 | Mpi2ExpanderPage1_t expander_pg1; | ||
| 6963 | Mpi2ConfigReply_t mpi_reply; | ||
| 6964 | int i; | ||
| 6965 | |||
| 6966 | for (i = 0 ; i < sas_expander->num_phys ; i++) { | ||
| 6967 | if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply, | ||
| 6968 | &expander_pg1, i, handle))) { | ||
| 6969 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 6970 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 6971 | return; | ||
| 6972 | } | ||
| 6973 | |||
| 6974 | mpt2sas_transport_update_links(ioc, sas_expander->sas_address, | ||
| 6975 | le16_to_cpu(expander_pg1.AttachedDevHandle), i, | ||
| 6976 | expander_pg1.NegotiatedLinkRate >> 4); | ||
| 6977 | } | ||
| 6793 | } | 6978 | } |
| 6794 | 6979 | ||
| 6795 | /** | 6980 | /** |
| 6796 | * _scsih_hide_unhide_sas_devices - add/remove device to/from OS | 6981 | * _scsih_scan_for_devices_after_reset - scan for devices after host reset |
| 6797 | * @ioc: per adapter object | 6982 | * @ioc: per adapter object |
| 6798 | * | 6983 | * |
| 6799 | * Return nothing. | 6984 | * Return nothing. |
| 6800 | */ | 6985 | */ |
| 6801 | static void | 6986 | static void |
| 6802 | _scsih_hide_unhide_sas_devices(struct MPT2SAS_ADAPTER *ioc) | 6987 | _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) |
| 6803 | { | 6988 | { |
| 6804 | struct _sas_device *sas_device, *sas_device_next; | 6989 | Mpi2ExpanderPage0_t expander_pg0; |
| 6990 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
| 6991 | Mpi2RaidVolPage1_t volume_pg1; | ||
| 6992 | Mpi2RaidVolPage0_t volume_pg0; | ||
| 6993 | Mpi2RaidPhysDiskPage0_t pd_pg0; | ||
| 6994 | Mpi2EventIrConfigElement_t element; | ||
| 6995 | Mpi2ConfigReply_t mpi_reply; | ||
| 6996 | u8 phys_disk_num; | ||
| 6997 | u16 ioc_status; | ||
| 6998 | u16 handle, parent_handle; | ||
| 6999 | u64 sas_address; | ||
| 7000 | struct _sas_device *sas_device; | ||
| 7001 | struct _sas_node *expander_device; | ||
| 7002 | static struct _raid_device *raid_device; | ||
| 6805 | 7003 | ||
| 6806 | if (!ioc->is_warpdrive || ioc->mfg_pg10_hide_flag != | 7004 | printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name); |
| 6807 | MFG_PAGE10_HIDE_IF_VOL_PRESENT) | ||
| 6808 | return; | ||
| 6809 | 7005 | ||
| 6810 | if (ioc->hide_drives) { | 7006 | _scsih_sas_host_refresh(ioc); |
| 6811 | if (_scsih_get_num_volumes(ioc)) | 7007 | |
| 6812 | return; | 7008 | /* expanders */ |
| 6813 | ioc->hide_drives = 0; | 7009 | handle = 0xFFFF; |
| 6814 | list_for_each_entry_safe(sas_device, sas_device_next, | 7010 | while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, |
| 6815 | &ioc->sas_device_list, list) { | 7011 | MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) { |
| 6816 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, | 7012 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & |
| 6817 | sas_device->sas_address_parent)) { | 7013 | MPI2_IOCSTATUS_MASK; |
| 6818 | _scsih_sas_device_remove(ioc, sas_device); | 7014 | if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) |
| 6819 | } else if (!sas_device->starget) { | 7015 | break; |
| 6820 | mpt2sas_transport_port_remove(ioc, | 7016 | handle = le16_to_cpu(expander_pg0.DevHandle); |
| 6821 | sas_device->sas_address, | 7017 | expander_device = mpt2sas_scsih_expander_find_by_sas_address( |
| 6822 | sas_device->sas_address_parent); | 7018 | ioc, le64_to_cpu(expander_pg0.SASAddress)); |
| 6823 | _scsih_sas_device_remove(ioc, sas_device); | 7019 | if (expander_device) |
| 6824 | } | 7020 | _scsih_refresh_expander_links(ioc, expander_device, |
| 7021 | handle); | ||
| 7022 | else | ||
| 7023 | _scsih_expander_add(ioc, handle); | ||
| 7024 | } | ||
| 7025 | |||
| 7026 | if (!ioc->ir_firmware) | ||
| 7027 | goto skip_to_sas; | ||
| 7028 | |||
| 7029 | /* phys disk */ | ||
| 7030 | phys_disk_num = 0xFF; | ||
| 7031 | while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply, | ||
| 7032 | &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM, | ||
| 7033 | phys_disk_num))) { | ||
| 7034 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 7035 | MPI2_IOCSTATUS_MASK; | ||
| 7036 | if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) | ||
| 7037 | break; | ||
| 7038 | phys_disk_num = pd_pg0.PhysDiskNum; | ||
| 7039 | handle = le16_to_cpu(pd_pg0.DevHandle); | ||
| 7040 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | ||
| 7041 | if (sas_device) | ||
| 7042 | continue; | ||
| 7043 | if (mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, | ||
| 7044 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, | ||
| 7045 | handle) != 0) | ||
| 7046 | continue; | ||
| 7047 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); | ||
| 7048 | if (!_scsih_get_sas_address(ioc, parent_handle, | ||
| 7049 | &sas_address)) { | ||
| 7050 | mpt2sas_transport_update_links(ioc, sas_address, | ||
| 7051 | handle, sas_device_pg0.PhyNum, | ||
| 7052 | MPI2_SAS_NEG_LINK_RATE_1_5); | ||
| 7053 | set_bit(handle, ioc->pd_handles); | ||
| 7054 | _scsih_add_device(ioc, handle, 0, 1); | ||
| 6825 | } | 7055 | } |
| 6826 | } else { | 7056 | } |
| 6827 | if (!_scsih_get_num_volumes(ioc)) | 7057 | |
| 6828 | return; | 7058 | /* volumes */ |
| 6829 | ioc->hide_drives = 1; | 7059 | handle = 0xFFFF; |
| 6830 | list_for_each_entry_safe(sas_device, sas_device_next, | 7060 | while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, |
| 6831 | &ioc->sas_device_list, list) { | 7061 | &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { |
| 6832 | mpt2sas_transport_port_remove(ioc, | 7062 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & |
| 6833 | sas_device->sas_address, | 7063 | MPI2_IOCSTATUS_MASK; |
| 6834 | sas_device->sas_address_parent); | 7064 | if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) |
| 7065 | break; | ||
| 7066 | handle = le16_to_cpu(volume_pg1.DevHandle); | ||
| 7067 | raid_device = _scsih_raid_device_find_by_wwid(ioc, | ||
| 7068 | le64_to_cpu(volume_pg1.WWID)); | ||
| 7069 | if (raid_device) | ||
| 7070 | continue; | ||
| 7071 | if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, | ||
| 7072 | &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, | ||
| 7073 | sizeof(Mpi2RaidVolPage0_t))) | ||
| 7074 | continue; | ||
| 7075 | if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL || | ||
| 7076 | volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE || | ||
| 7077 | volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) { | ||
| 7078 | memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t)); | ||
| 7079 | element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED; | ||
| 7080 | element.VolDevHandle = volume_pg1.DevHandle; | ||
| 7081 | _scsih_sas_volume_add(ioc, &element); | ||
| 6835 | } | 7082 | } |
| 6836 | } | 7083 | } |
| 7084 | |||
| 7085 | skip_to_sas: | ||
| 7086 | |||
| 7087 | /* sas devices */ | ||
| 7088 | handle = 0xFFFF; | ||
| 7089 | while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, | ||
| 7090 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, | ||
| 7091 | handle))) { | ||
| 7092 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 7093 | MPI2_IOCSTATUS_MASK; | ||
| 7094 | if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) | ||
| 7095 | break; | ||
| 7096 | handle = le16_to_cpu(sas_device_pg0.DevHandle); | ||
| 7097 | if (!(_scsih_is_end_device( | ||
| 7098 | le32_to_cpu(sas_device_pg0.DeviceInfo)))) | ||
| 7099 | continue; | ||
| 7100 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | ||
| 7101 | le64_to_cpu(sas_device_pg0.SASAddress)); | ||
| 7102 | if (sas_device) | ||
| 7103 | continue; | ||
| 7104 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); | ||
| 7105 | if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) { | ||
| 7106 | mpt2sas_transport_update_links(ioc, sas_address, handle, | ||
| 7107 | sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | ||
| 7108 | _scsih_add_device(ioc, handle, 0, 0); | ||
| 7109 | } | ||
| 7110 | } | ||
| 7111 | |||
| 7112 | printk(MPT2SAS_INFO_FMT "scan devices: complete\n", ioc->name); | ||
| 6837 | } | 7113 | } |
| 6838 | 7114 | ||
| 7115 | |||
| 6839 | /** | 7116 | /** |
| 6840 | * mpt2sas_scsih_reset_handler - reset callback handler (for scsih) | 7117 | * mpt2sas_scsih_reset_handler - reset callback handler (for scsih) |
| 6841 | * @ioc: per adapter object | 7118 | * @ioc: per adapter object |
| @@ -6871,7 +7148,6 @@ mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | |||
| 6871 | } | 7148 | } |
| 6872 | _scsih_fw_event_cleanup_queue(ioc); | 7149 | _scsih_fw_event_cleanup_queue(ioc); |
| 6873 | _scsih_flush_running_cmds(ioc); | 7150 | _scsih_flush_running_cmds(ioc); |
| 6874 | _scsih_queue_rescan(ioc); | ||
| 6875 | break; | 7151 | break; |
| 6876 | case MPT2_IOC_DONE_RESET: | 7152 | case MPT2_IOC_DONE_RESET: |
| 6877 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " | 7153 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " |
| @@ -6881,6 +7157,13 @@ mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | |||
| 6881 | _scsih_search_responding_sas_devices(ioc); | 7157 | _scsih_search_responding_sas_devices(ioc); |
| 6882 | _scsih_search_responding_raid_devices(ioc); | 7158 | _scsih_search_responding_raid_devices(ioc); |
| 6883 | _scsih_search_responding_expanders(ioc); | 7159 | _scsih_search_responding_expanders(ioc); |
| 7160 | if (!ioc->is_driver_loading) { | ||
| 7161 | _scsih_prep_device_scan(ioc); | ||
| 7162 | _scsih_search_responding_sas_devices(ioc); | ||
| 7163 | _scsih_search_responding_raid_devices(ioc); | ||
| 7164 | _scsih_search_responding_expanders(ioc); | ||
| 7165 | _scsih_error_recovery_delete_devices(ioc); | ||
| 7166 | } | ||
| 6884 | break; | 7167 | break; |
| 6885 | } | 7168 | } |
| 6886 | } | 7169 | } |
| @@ -6898,7 +7181,6 @@ _firmware_event_work(struct work_struct *work) | |||
| 6898 | { | 7181 | { |
| 6899 | struct fw_event_work *fw_event = container_of(work, | 7182 | struct fw_event_work *fw_event = container_of(work, |
| 6900 | struct fw_event_work, delayed_work.work); | 7183 | struct fw_event_work, delayed_work.work); |
| 6901 | unsigned long flags; | ||
| 6902 | struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; | 7184 | struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; |
| 6903 | 7185 | ||
| 6904 | /* the queue is being flushed so ignore this event */ | 7186 | /* the queue is being flushed so ignore this event */ |
| @@ -6908,23 +7190,21 @@ _firmware_event_work(struct work_struct *work) | |||
| 6908 | return; | 7190 | return; |
| 6909 | } | 7191 | } |
| 6910 | 7192 | ||
| 6911 | if (fw_event->event == MPT2SAS_RESCAN_AFTER_HOST_RESET) { | 7193 | switch (fw_event->event) { |
| 6912 | _scsih_fw_event_free(ioc, fw_event); | 7194 | case MPT2SAS_REMOVE_UNRESPONDING_DEVICES: |
| 6913 | spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); | 7195 | while (scsi_host_in_recovery(ioc->shost)) |
| 6914 | if (ioc->shost_recovery) { | 7196 | ssleep(1); |
| 6915 | init_completion(&ioc->shost_recovery_done); | ||
| 6916 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, | ||
| 6917 | flags); | ||
| 6918 | wait_for_completion(&ioc->shost_recovery_done); | ||
| 6919 | } else | ||
| 6920 | spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, | ||
| 6921 | flags); | ||
| 6922 | _scsih_remove_unresponding_sas_devices(ioc); | 7197 | _scsih_remove_unresponding_sas_devices(ioc); |
| 6923 | _scsih_hide_unhide_sas_devices(ioc); | 7198 | _scsih_scan_for_devices_after_reset(ioc); |
| 6924 | return; | 7199 | break; |
| 6925 | } | 7200 | case MPT2SAS_PORT_ENABLE_COMPLETE: |
| 7201 | ioc->start_scan = 0; | ||
| 6926 | 7202 | ||
| 6927 | switch (fw_event->event) { | 7203 | |
| 7204 | |||
| 7205 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "port enable: complete " | ||
| 7206 | "from worker thread\n", ioc->name)); | ||
| 7207 | break; | ||
| 6928 | case MPT2SAS_TURN_ON_FAULT_LED: | 7208 | case MPT2SAS_TURN_ON_FAULT_LED: |
| 6929 | _scsih_turn_on_fault_led(ioc, fw_event->device_handle); | 7209 | _scsih_turn_on_fault_led(ioc, fw_event->device_handle); |
| 6930 | break; | 7210 | break; |
| @@ -7121,6 +7401,8 @@ static struct scsi_host_template scsih_driver_template = { | |||
| 7121 | .slave_configure = _scsih_slave_configure, | 7401 | .slave_configure = _scsih_slave_configure, |
| 7122 | .target_destroy = _scsih_target_destroy, | 7402 | .target_destroy = _scsih_target_destroy, |
| 7123 | .slave_destroy = _scsih_slave_destroy, | 7403 | .slave_destroy = _scsih_slave_destroy, |
| 7404 | .scan_finished = _scsih_scan_finished, | ||
| 7405 | .scan_start = _scsih_scan_start, | ||
| 7124 | .change_queue_depth = _scsih_change_queue_depth, | 7406 | .change_queue_depth = _scsih_change_queue_depth, |
| 7125 | .change_queue_type = _scsih_change_queue_type, | 7407 | .change_queue_type = _scsih_change_queue_type, |
| 7126 | .eh_abort_handler = _scsih_abort, | 7408 | .eh_abort_handler = _scsih_abort, |
| @@ -7381,7 +7663,12 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 7381 | unsigned long flags; | 7663 | unsigned long flags; |
| 7382 | int rc; | 7664 | int rc; |
| 7383 | 7665 | ||
| 7666 | /* no Bios, return immediately */ | ||
| 7667 | if (!ioc->bios_pg3.BiosVersion) | ||
| 7668 | return; | ||
| 7669 | |||
| 7384 | device = NULL; | 7670 | device = NULL; |
| 7671 | is_raid = 0; | ||
| 7385 | if (ioc->req_boot_device.device) { | 7672 | if (ioc->req_boot_device.device) { |
| 7386 | device = ioc->req_boot_device.device; | 7673 | device = ioc->req_boot_device.device; |
| 7387 | is_raid = ioc->req_boot_device.is_raid; | 7674 | is_raid = ioc->req_boot_device.is_raid; |
| @@ -7417,8 +7704,9 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 7417 | sas_device->sas_address_parent)) { | 7704 | sas_device->sas_address_parent)) { |
| 7418 | _scsih_sas_device_remove(ioc, sas_device); | 7705 | _scsih_sas_device_remove(ioc, sas_device); |
| 7419 | } else if (!sas_device->starget) { | 7706 | } else if (!sas_device->starget) { |
| 7420 | mpt2sas_transport_port_remove(ioc, sas_address, | 7707 | if (!ioc->is_driver_loading) |
| 7421 | sas_address_parent); | 7708 | mpt2sas_transport_port_remove(ioc, sas_address, |
| 7709 | sas_address_parent); | ||
| 7422 | _scsih_sas_device_remove(ioc, sas_device); | 7710 | _scsih_sas_device_remove(ioc, sas_device); |
| 7423 | } | 7711 | } |
| 7424 | } | 7712 | } |
| @@ -7462,22 +7750,28 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc) | |||
| 7462 | /* SAS Device List */ | 7750 | /* SAS Device List */ |
| 7463 | list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list, | 7751 | list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list, |
| 7464 | list) { | 7752 | list) { |
| 7465 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 7466 | list_move_tail(&sas_device->list, &ioc->sas_device_list); | ||
| 7467 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 7468 | 7753 | ||
| 7469 | if (ioc->hide_drives) | 7754 | if (ioc->hide_drives) |
| 7470 | continue; | 7755 | continue; |
| 7471 | 7756 | ||
| 7472 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, | 7757 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, |
| 7473 | sas_device->sas_address_parent)) { | 7758 | sas_device->sas_address_parent)) { |
| 7474 | _scsih_sas_device_remove(ioc, sas_device); | 7759 | list_del(&sas_device->list); |
| 7760 | kfree(sas_device); | ||
| 7761 | continue; | ||
| 7475 | } else if (!sas_device->starget) { | 7762 | } else if (!sas_device->starget) { |
| 7476 | mpt2sas_transport_port_remove(ioc, | 7763 | if (!ioc->is_driver_loading) |
| 7477 | sas_device->sas_address, | 7764 | mpt2sas_transport_port_remove(ioc, |
| 7478 | sas_device->sas_address_parent); | 7765 | sas_device->sas_address, |
| 7479 | _scsih_sas_device_remove(ioc, sas_device); | 7766 | sas_device->sas_address_parent); |
| 7767 | list_del(&sas_device->list); | ||
| 7768 | kfree(sas_device); | ||
| 7769 | continue; | ||
| 7770 | |||
| 7480 | } | 7771 | } |
| 7772 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 7773 | list_move_tail(&sas_device->list, &ioc->sas_device_list); | ||
| 7774 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 7481 | } | 7775 | } |
| 7482 | } | 7776 | } |
| 7483 | 7777 | ||
| @@ -7490,9 +7784,7 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc) | |||
| 7490 | static void | 7784 | static void |
| 7491 | _scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc) | 7785 | _scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc) |
| 7492 | { | 7786 | { |
| 7493 | u16 volume_mapping_flags = | 7787 | u16 volume_mapping_flags; |
| 7494 | le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) & | ||
| 7495 | MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; | ||
| 7496 | 7788 | ||
| 7497 | if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR)) | 7789 | if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR)) |
| 7498 | return; /* return when IOC doesn't support initiator mode */ | 7790 | return; /* return when IOC doesn't support initiator mode */ |
| @@ -7500,18 +7792,93 @@ _scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 7500 | _scsih_probe_boot_devices(ioc); | 7792 | _scsih_probe_boot_devices(ioc); |
| 7501 | 7793 | ||
| 7502 | if (ioc->ir_firmware) { | 7794 | if (ioc->ir_firmware) { |
| 7503 | if ((volume_mapping_flags & | 7795 | volume_mapping_flags = |
| 7504 | MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING)) { | 7796 | le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) & |
| 7505 | _scsih_probe_sas(ioc); | 7797 | MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; |
| 7798 | if (volume_mapping_flags == | ||
| 7799 | MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) { | ||
| 7506 | _scsih_probe_raid(ioc); | 7800 | _scsih_probe_raid(ioc); |
| 7801 | _scsih_probe_sas(ioc); | ||
| 7507 | } else { | 7802 | } else { |
| 7508 | _scsih_probe_raid(ioc); | ||
| 7509 | _scsih_probe_sas(ioc); | 7803 | _scsih_probe_sas(ioc); |
| 7804 | _scsih_probe_raid(ioc); | ||
| 7510 | } | 7805 | } |
| 7511 | } else | 7806 | } else |
| 7512 | _scsih_probe_sas(ioc); | 7807 | _scsih_probe_sas(ioc); |
| 7513 | } | 7808 | } |
| 7514 | 7809 | ||
| 7810 | |||
| 7811 | /** | ||
| 7812 | * _scsih_scan_start - scsi lld callback for .scan_start | ||
| 7813 | * @shost: SCSI host pointer | ||
| 7814 | * | ||
| 7815 | * The shost has the ability to discover targets on its own instead | ||
| 7816 | * of scanning the entire bus. In our implemention, we will kick off | ||
| 7817 | * firmware discovery. | ||
| 7818 | */ | ||
| 7819 | static void | ||
| 7820 | _scsih_scan_start(struct Scsi_Host *shost) | ||
| 7821 | { | ||
| 7822 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 7823 | int rc; | ||
| 7824 | |||
| 7825 | if (diag_buffer_enable != -1 && diag_buffer_enable != 0) | ||
| 7826 | mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable); | ||
| 7827 | |||
| 7828 | ioc->start_scan = 1; | ||
| 7829 | rc = mpt2sas_port_enable(ioc); | ||
| 7830 | |||
| 7831 | if (rc != 0) | ||
| 7832 | printk(MPT2SAS_INFO_FMT "port enable: FAILED\n", ioc->name); | ||
| 7833 | } | ||
| 7834 | |||
| 7835 | /** | ||
| 7836 | * _scsih_scan_finished - scsi lld callback for .scan_finished | ||
| 7837 | * @shost: SCSI host pointer | ||
| 7838 | * @time: elapsed time of the scan in jiffies | ||
| 7839 | * | ||
| 7840 | * This function will be called periodically until it returns 1 with the | ||
| 7841 | * scsi_host and the elapsed time of the scan in jiffies. In our implemention, | ||
| 7842 | * we wait for firmware discovery to complete, then return 1. | ||
| 7843 | */ | ||
| 7844 | static int | ||
| 7845 | _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time) | ||
| 7846 | { | ||
| 7847 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 7848 | |||
| 7849 | if (time >= (300 * HZ)) { | ||
| 7850 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; | ||
| 7851 | printk(MPT2SAS_INFO_FMT "port enable: FAILED with timeout " | ||
| 7852 | "(timeout=300s)\n", ioc->name); | ||
| 7853 | ioc->is_driver_loading = 0; | ||
| 7854 | return 1; | ||
| 7855 | } | ||
| 7856 | |||
| 7857 | if (ioc->start_scan) | ||
| 7858 | return 0; | ||
| 7859 | |||
| 7860 | if (ioc->start_scan_failed) { | ||
| 7861 | printk(MPT2SAS_INFO_FMT "port enable: FAILED with " | ||
| 7862 | "(ioc_status=0x%08x)\n", ioc->name, ioc->start_scan_failed); | ||
| 7863 | ioc->is_driver_loading = 0; | ||
| 7864 | ioc->wait_for_discovery_to_complete = 0; | ||
| 7865 | ioc->remove_host = 1; | ||
| 7866 | return 1; | ||
| 7867 | } | ||
| 7868 | |||
| 7869 | printk(MPT2SAS_INFO_FMT "port enable: SUCCESS\n", ioc->name); | ||
| 7870 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; | ||
| 7871 | |||
| 7872 | if (ioc->wait_for_discovery_to_complete) { | ||
| 7873 | ioc->wait_for_discovery_to_complete = 0; | ||
| 7874 | _scsih_probe_devices(ioc); | ||
| 7875 | } | ||
| 7876 | mpt2sas_base_start_watchdog(ioc); | ||
| 7877 | ioc->is_driver_loading = 0; | ||
| 7878 | return 1; | ||
| 7879 | } | ||
| 7880 | |||
| 7881 | |||
| 7515 | /** | 7882 | /** |
| 7516 | * _scsih_probe - attach and add scsi host | 7883 | * _scsih_probe - attach and add scsi host |
| 7517 | * @pdev: PCI device struct | 7884 | * @pdev: PCI device struct |
| @@ -7548,6 +7915,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 7548 | ioc->tm_cb_idx = tm_cb_idx; | 7915 | ioc->tm_cb_idx = tm_cb_idx; |
| 7549 | ioc->ctl_cb_idx = ctl_cb_idx; | 7916 | ioc->ctl_cb_idx = ctl_cb_idx; |
| 7550 | ioc->base_cb_idx = base_cb_idx; | 7917 | ioc->base_cb_idx = base_cb_idx; |
| 7918 | ioc->port_enable_cb_idx = port_enable_cb_idx; | ||
| 7551 | ioc->transport_cb_idx = transport_cb_idx; | 7919 | ioc->transport_cb_idx = transport_cb_idx; |
| 7552 | ioc->scsih_cb_idx = scsih_cb_idx; | 7920 | ioc->scsih_cb_idx = scsih_cb_idx; |
| 7553 | ioc->config_cb_idx = config_cb_idx; | 7921 | ioc->config_cb_idx = config_cb_idx; |
| @@ -7620,14 +7988,14 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 7620 | goto out_thread_fail; | 7988 | goto out_thread_fail; |
| 7621 | } | 7989 | } |
| 7622 | 7990 | ||
| 7623 | ioc->wait_for_port_enable_to_complete = 1; | 7991 | ioc->is_driver_loading = 1; |
| 7624 | if ((mpt2sas_base_attach(ioc))) { | 7992 | if ((mpt2sas_base_attach(ioc))) { |
| 7625 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 7993 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
| 7626 | ioc->name, __FILE__, __LINE__, __func__); | 7994 | ioc->name, __FILE__, __LINE__, __func__); |
| 7627 | goto out_attach_fail; | 7995 | goto out_attach_fail; |
| 7628 | } | 7996 | } |
| 7629 | 7997 | ||
| 7630 | ioc->wait_for_port_enable_to_complete = 0; | 7998 | scsi_scan_host(shost); |
| 7631 | if (ioc->is_warpdrive) { | 7999 | if (ioc->is_warpdrive) { |
| 7632 | if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) | 8000 | if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) |
| 7633 | ioc->hide_drives = 0; | 8001 | ioc->hide_drives = 0; |
| @@ -7650,6 +8018,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 7650 | out_thread_fail: | 8018 | out_thread_fail: |
| 7651 | list_del(&ioc->list); | 8019 | list_del(&ioc->list); |
| 7652 | scsi_remove_host(shost); | 8020 | scsi_remove_host(shost); |
| 8021 | scsi_host_put(shost); | ||
| 7653 | out_add_shost_fail: | 8022 | out_add_shost_fail: |
| 7654 | return -ENODEV; | 8023 | return -ENODEV; |
| 7655 | } | 8024 | } |
| @@ -7896,6 +8265,8 @@ _scsih_init(void) | |||
| 7896 | 8265 | ||
| 7897 | /* base internal commands callback handler */ | 8266 | /* base internal commands callback handler */ |
| 7898 | base_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_base_done); | 8267 | base_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_base_done); |
| 8268 | port_enable_cb_idx = mpt2sas_base_register_callback_handler( | ||
| 8269 | mpt2sas_port_enable_done); | ||
| 7899 | 8270 | ||
| 7900 | /* transport internal commands callback handler */ | 8271 | /* transport internal commands callback handler */ |
| 7901 | transport_cb_idx = mpt2sas_base_register_callback_handler( | 8272 | transport_cb_idx = mpt2sas_base_register_callback_handler( |
| @@ -7950,6 +8321,7 @@ _scsih_exit(void) | |||
| 7950 | mpt2sas_base_release_callback_handler(scsi_io_cb_idx); | 8321 | mpt2sas_base_release_callback_handler(scsi_io_cb_idx); |
| 7951 | mpt2sas_base_release_callback_handler(tm_cb_idx); | 8322 | mpt2sas_base_release_callback_handler(tm_cb_idx); |
| 7952 | mpt2sas_base_release_callback_handler(base_cb_idx); | 8323 | mpt2sas_base_release_callback_handler(base_cb_idx); |
| 8324 | mpt2sas_base_release_callback_handler(port_enable_cb_idx); | ||
| 7953 | mpt2sas_base_release_callback_handler(transport_cb_idx); | 8325 | mpt2sas_base_release_callback_handler(transport_cb_idx); |
| 7954 | mpt2sas_base_release_callback_handler(scsih_cb_idx); | 8326 | mpt2sas_base_release_callback_handler(scsih_cb_idx); |
| 7955 | mpt2sas_base_release_callback_handler(config_cb_idx); | 8327 | mpt2sas_base_release_callback_handler(config_cb_idx); |
