aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/message/fusion/mptbase.h5
-rw-r--r--drivers/message/fusion/mptsas.c746
2 files changed, 515 insertions, 236 deletions
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index b6efc64e8264..8d1aadb6b4ac 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -704,6 +704,11 @@ typedef struct _MPT_ADAPTER
704 struct mutex sas_discovery_mutex; 704 struct mutex sas_discovery_mutex;
705 u8 sas_discovery_runtime; 705 u8 sas_discovery_runtime;
706 u8 sas_discovery_ignore_events; 706 u8 sas_discovery_ignore_events;
707
708 /* port_info object for the host */
709 struct mptsas_portinfo *hba_port_info;
710 u64 hba_port_sas_addr;
711 u16 hba_port_num_phy;
707 struct list_head sas_device_info_list; 712 struct list_head sas_device_info_list;
708 struct mutex sas_device_info_mutex; 713 struct mutex sas_device_info_mutex;
709 u8 sas_discovery_quiesce_io; 714 u8 sas_discovery_quiesce_io;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 22a027ec9e5d..7f2f76f0db3f 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -113,6 +113,12 @@ static int mptsas_add_end_device(MPT_ADAPTER *ioc,
113 struct mptsas_phyinfo *phy_info); 113 struct mptsas_phyinfo *phy_info);
114static void mptsas_del_end_device(MPT_ADAPTER *ioc, 114static void mptsas_del_end_device(MPT_ADAPTER *ioc,
115 struct mptsas_phyinfo *phy_info); 115 struct mptsas_phyinfo *phy_info);
116static void mptsas_send_link_status_event(struct fw_event_work *fw_event);
117static struct mptsas_portinfo *mptsas_find_portinfo_by_sas_address
118 (MPT_ADAPTER *ioc, u64 sas_address);
119static void mptsas_expander_delete(MPT_ADAPTER *ioc,
120 struct mptsas_portinfo *port_info, u8 force);
121static void mptsas_send_expander_event(struct fw_event_work *fw_event);
116 122
117static void mptsas_print_phy_data(MPT_ADAPTER *ioc, 123static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
118 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) 124 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
@@ -342,20 +348,6 @@ static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
342 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; 348 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
343} 349}
344 350
345static struct mptsas_portinfo *
346mptsas_get_hba_portinfo(MPT_ADAPTER *ioc)
347{
348 struct list_head *head = &ioc->sas_topology;
349 struct mptsas_portinfo *pi = NULL;
350
351 /* always the first entry on sas_topology list */
352
353 if (!list_empty(head))
354 pi = list_entry(head->next, struct mptsas_portinfo, list);
355
356 return pi;
357}
358
359/* 351/*
360 * mptsas_find_portinfo_by_handle 352 * mptsas_find_portinfo_by_handle
361 * 353 *
@@ -377,6 +369,38 @@ mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
377 return rc; 369 return rc;
378} 370}
379 371
372/**
373 * mptsas_find_portinfo_by_sas_address -
374 * @ioc: Pointer to MPT_ADAPTER structure
375 * @handle:
376 *
377 * This function should be called with the sas_topology_mutex already held
378 *
379 **/
380static struct mptsas_portinfo *
381mptsas_find_portinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
382{
383 struct mptsas_portinfo *port_info, *rc = NULL;
384 int i;
385
386 if (sas_address >= ioc->hba_port_sas_addr &&
387 sas_address < (ioc->hba_port_sas_addr +
388 ioc->hba_port_num_phy))
389 return ioc->hba_port_info;
390
391 mutex_lock(&ioc->sas_topology_mutex);
392 list_for_each_entry(port_info, &ioc->sas_topology, list)
393 for (i = 0; i < port_info->num_phys; i++)
394 if (port_info->phy_info[i].identify.sas_address ==
395 sas_address) {
396 rc = port_info;
397 goto out;
398 }
399 out:
400 mutex_unlock(&ioc->sas_topology_mutex);
401 return rc;
402}
403
380/* 404/*
381 * Returns true if there is a scsi end device 405 * Returns true if there is a scsi end device
382 */ 406 */
@@ -940,7 +964,6 @@ mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
940{ 964{
941 MPT_SCSI_HOST *hd = shost_priv(ioc->sh); 965 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
942 struct list_head *head = &hd->target_reset_list; 966 struct list_head *head = &hd->target_reset_list;
943 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
944 u8 id, channel; 967 u8 id, channel;
945 struct mptsas_target_reset_event *target_reset_list; 968 struct mptsas_target_reset_event *target_reset_list;
946 SCSITaskMgmtReply_t *pScsiTmReply; 969 SCSITaskMgmtReply_t *pScsiTmReply;
@@ -995,7 +1018,6 @@ mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
995 ioc->name, jiffies_to_msecs(jiffies - 1018 ioc->name, jiffies_to_msecs(jiffies -
996 target_reset_list->time_count)/1000)); 1019 target_reset_list->time_count)/1000));
997 1020
998 sas_event_data = &target_reset_list->sas_event_data;
999 id = pScsiTmReply->TargetID; 1021 id = pScsiTmReply->TargetID;
1000 channel = pScsiTmReply->Bus; 1022 channel = pScsiTmReply->Bus;
1001 target_reset_list->time_count = jiffies; 1023 target_reset_list->time_count = jiffies;
@@ -1410,6 +1432,12 @@ mptsas_firmware_event_work(struct work_struct *work)
1410 MPI_SAS_OP_CLEAR_NOT_PRESENT); 1432 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1411 mptsas_free_fw_event(ioc, fw_event); 1433 mptsas_free_fw_event(ioc, fw_event);
1412 break; 1434 break;
1435 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
1436 mptsas_send_expander_event(fw_event);
1437 break;
1438 case MPI_EVENT_SAS_PHY_LINK_STATUS:
1439 mptsas_send_link_status_event(fw_event);
1440 break;
1413 } 1441 }
1414} 1442}
1415 1443
@@ -1909,7 +1937,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1909 struct mptsas_portinfo *port_info; 1937 struct mptsas_portinfo *port_info;
1910 1938
1911 mutex_lock(&ioc->sas_topology_mutex); 1939 mutex_lock(&ioc->sas_topology_mutex);
1912 port_info = mptsas_get_hba_portinfo(ioc); 1940 port_info = ioc->hba_port_info;
1913 if (port_info && port_info->phy_info) 1941 if (port_info && port_info->phy_info)
1914 sas_address = 1942 sas_address =
1915 port_info->phy_info[0].phy->identify.sas_address; 1943 port_info->phy_info[0].phy->identify.sas_address;
@@ -2646,9 +2674,7 @@ static int mptsas_probe_one_phy(struct device *dev,
2646 struct mptsas_portinfo *port_info; 2674 struct mptsas_portinfo *port_info;
2647 int i; 2675 int i;
2648 2676
2649 mutex_lock(&ioc->sas_topology_mutex); 2677 port_info = ioc->hba_port_info;
2650 port_info = mptsas_get_hba_portinfo(ioc);
2651 mutex_unlock(&ioc->sas_topology_mutex);
2652 2678
2653 for (i = 0; i < port_info->num_phys; i++) 2679 for (i = 0; i < port_info->num_phys; i++)
2654 if (port_info->phy_info[i].identify.sas_address == 2680 if (port_info->phy_info[i].identify.sas_address ==
@@ -2707,7 +2733,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
2707 struct mptsas_portinfo *port_info, *hba; 2733 struct mptsas_portinfo *port_info, *hba;
2708 int error = -ENOMEM, i; 2734 int error = -ENOMEM, i;
2709 2735
2710 hba = kzalloc(sizeof(*port_info), GFP_KERNEL); 2736 hba = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
2711 if (! hba) 2737 if (! hba)
2712 goto out; 2738 goto out;
2713 2739
@@ -2717,9 +2743,10 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
2717 2743
2718 mptsas_sas_io_unit_pg1(ioc); 2744 mptsas_sas_io_unit_pg1(ioc);
2719 mutex_lock(&ioc->sas_topology_mutex); 2745 mutex_lock(&ioc->sas_topology_mutex);
2720 port_info = mptsas_get_hba_portinfo(ioc); 2746 port_info = ioc->hba_port_info;
2721 if (!port_info) { 2747 if (!port_info) {
2722 port_info = hba; 2748 ioc->hba_port_info = port_info = hba;
2749 ioc->hba_port_num_phy = port_info->num_phys;
2723 list_add_tail(&port_info->list, &ioc->sas_topology); 2750 list_add_tail(&port_info->list, &ioc->sas_topology);
2724 } else { 2751 } else {
2725 for (i = 0; i < hba->num_phys; i++) { 2752 for (i = 0; i < hba->num_phys; i++) {
@@ -2735,15 +2762,22 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
2735 hba = NULL; 2762 hba = NULL;
2736 } 2763 }
2737 mutex_unlock(&ioc->sas_topology_mutex); 2764 mutex_unlock(&ioc->sas_topology_mutex);
2765#if defined(CPQ_CIM)
2766 ioc->num_ports = port_info->num_phys;
2767#endif
2738 for (i = 0; i < port_info->num_phys; i++) { 2768 for (i = 0; i < port_info->num_phys; i++) {
2739 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], 2769 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
2740 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER << 2770 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
2741 MPI_SAS_PHY_PGAD_FORM_SHIFT), i); 2771 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
2742 2772 port_info->phy_info[i].identify.handle =
2773 port_info->phy_info[i].handle;
2743 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify, 2774 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
2744 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << 2775 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2745 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), 2776 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2746 port_info->phy_info[i].handle); 2777 port_info->phy_info[i].identify.handle);
2778 if (!ioc->hba_port_sas_addr)
2779 ioc->hba_port_sas_addr =
2780 port_info->phy_info[i].identify.sas_address;
2747 port_info->phy_info[i].identify.phy_id = 2781 port_info->phy_info[i].identify.phy_id =
2748 port_info->phy_info[i].phy_id = i; 2782 port_info->phy_info[i].phy_id = i;
2749 if (port_info->phy_info[i].attached.handle) 2783 if (port_info->phy_info[i].attached.handle)
@@ -2768,248 +2802,497 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
2768 return error; 2802 return error;
2769} 2803}
2770 2804
2771static int 2805static void
2772mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle) 2806mptsas_expander_refresh(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
2773{ 2807{
2774 struct mptsas_portinfo *port_info, *p, *ex; 2808 struct mptsas_portinfo *parent;
2775 struct device *parent; 2809 struct device *parent_dev;
2776 struct sas_rphy *rphy; 2810 struct sas_rphy *rphy;
2777 int error = -ENOMEM, i, j; 2811 int i;
2778 2812 u64 sas_address; /* expander sas address */
2779 ex = kzalloc(sizeof(*port_info), GFP_KERNEL); 2813 u32 handle;
2780 if (!ex)
2781 goto out;
2782
2783 error = mptsas_sas_expander_pg0(ioc, ex,
2784 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
2785 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
2786 if (error)
2787 goto out_free_port_info;
2788
2789 *handle = ex->phy_info[0].handle;
2790
2791 mutex_lock(&ioc->sas_topology_mutex);
2792 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
2793 if (!port_info) {
2794 port_info = ex;
2795 list_add_tail(&port_info->list, &ioc->sas_topology);
2796 } else {
2797 for (i = 0; i < ex->num_phys; i++) {
2798 port_info->phy_info[i].handle =
2799 ex->phy_info[i].handle;
2800 port_info->phy_info[i].port_id =
2801 ex->phy_info[i].port_id;
2802 }
2803 kfree(ex->phy_info);
2804 kfree(ex);
2805 ex = NULL;
2806 }
2807 mutex_unlock(&ioc->sas_topology_mutex);
2808 2814
2815 handle = port_info->phy_info[0].handle;
2816 sas_address = port_info->phy_info[0].identify.sas_address;
2809 for (i = 0; i < port_info->num_phys; i++) { 2817 for (i = 0; i < port_info->num_phys; i++) {
2810 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i], 2818 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
2811 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM << 2819 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
2812 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle); 2820 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + handle);
2813 2821
2814 if (port_info->phy_info[i].identify.handle) { 2822 mptsas_sas_device_pg0(ioc,
2815 mptsas_sas_device_pg0(ioc, 2823 &port_info->phy_info[i].identify,
2816 &port_info->phy_info[i].identify, 2824 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2817 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << 2825 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2818 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), 2826 port_info->phy_info[i].identify.handle);
2819 port_info->phy_info[i].identify.handle); 2827 port_info->phy_info[i].identify.phy_id =
2820 port_info->phy_info[i].identify.phy_id = 2828 port_info->phy_info[i].phy_id;
2821 port_info->phy_info[i].phy_id;
2822 }
2823 2829
2824 if (port_info->phy_info[i].attached.handle) { 2830 if (port_info->phy_info[i].attached.handle) {
2825 mptsas_sas_device_pg0(ioc, 2831 mptsas_sas_device_pg0(ioc,
2826 &port_info->phy_info[i].attached, 2832 &port_info->phy_info[i].attached,
2827 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << 2833 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2828 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), 2834 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2829 port_info->phy_info[i].attached.handle); 2835 port_info->phy_info[i].attached.handle);
2830 port_info->phy_info[i].attached.phy_id = 2836 port_info->phy_info[i].attached.phy_id =
2831 port_info->phy_info[i].phy_id; 2837 port_info->phy_info[i].phy_id;
2832 } 2838 }
2833 } 2839 }
2834 2840
2835 parent = &ioc->sh->shost_gendev; 2841 mutex_lock(&ioc->sas_topology_mutex);
2836 for (i = 0; i < port_info->num_phys; i++) { 2842 parent = mptsas_find_portinfo_by_handle(ioc,
2837 mutex_lock(&ioc->sas_topology_mutex); 2843 port_info->phy_info[0].identify.handle_parent);
2838 list_for_each_entry(p, &ioc->sas_topology, list) { 2844 if (!parent) {
2839 for (j = 0; j < p->num_phys; j++) {
2840 if (port_info->phy_info[i].identify.handle !=
2841 p->phy_info[j].attached.handle)
2842 continue;
2843 rphy = mptsas_get_rphy(&p->phy_info[j]);
2844 parent = &rphy->dev;
2845 }
2846 }
2847 mutex_unlock(&ioc->sas_topology_mutex); 2845 mutex_unlock(&ioc->sas_topology_mutex);
2846 return;
2847 }
2848 for (i = 0, parent_dev = NULL; i < parent->num_phys && !parent_dev;
2849 i++) {
2850 if (parent->phy_info[i].attached.sas_address == sas_address) {
2851 rphy = mptsas_get_rphy(&parent->phy_info[i]);
2852 parent_dev = &rphy->dev;
2853 }
2848 } 2854 }
2855 mutex_unlock(&ioc->sas_topology_mutex);
2849 2856
2850 mptsas_setup_wide_ports(ioc, port_info); 2857 mptsas_setup_wide_ports(ioc, port_info);
2851
2852 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++) 2858 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
2853 mptsas_probe_one_phy(parent, &port_info->phy_info[i], 2859 mptsas_probe_one_phy(parent_dev, &port_info->phy_info[i],
2854 ioc->sas_index, 0); 2860 ioc->sas_index, 0);
2861}
2855 2862
2856 return 0; 2863static void
2864mptsas_expander_event_add(MPT_ADAPTER *ioc,
2865 MpiEventDataSasExpanderStatusChange_t *expander_data)
2866{
2867 struct mptsas_portinfo *port_info;
2868 int i;
2869 __le64 sas_address;
2857 2870
2858 out_free_port_info: 2871 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
2859 if (ex) { 2872 if (!port_info)
2860 kfree(ex->phy_info); 2873 BUG();
2861 kfree(ex); 2874 port_info->num_phys = (expander_data->NumPhys) ?
2875 expander_data->NumPhys : 1;
2876 port_info->phy_info = kcalloc(port_info->num_phys,
2877 sizeof(struct mptsas_phyinfo), GFP_KERNEL);
2878 if (!port_info->phy_info)
2879 BUG();
2880 memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
2881 for (i = 0; i < port_info->num_phys; i++) {
2882 port_info->phy_info[i].portinfo = port_info;
2883 port_info->phy_info[i].handle =
2884 le16_to_cpu(expander_data->DevHandle);
2885 port_info->phy_info[i].identify.sas_address =
2886 le64_to_cpu(sas_address);
2887 port_info->phy_info[i].identify.handle_parent =
2888 le16_to_cpu(expander_data->ParentDevHandle);
2862 } 2889 }
2863 out: 2890
2864 return error; 2891 mutex_lock(&ioc->sas_topology_mutex);
2892 list_add_tail(&port_info->list, &ioc->sas_topology);
2893 mutex_unlock(&ioc->sas_topology_mutex);
2894
2895 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
2896 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
2897 (unsigned long long)sas_address);
2898
2899 mptsas_expander_refresh(ioc, port_info);
2865} 2900}
2866 2901
2867/* 2902/**
2868 * mptsas_delete_expander_phys 2903 * mptsas_delete_expander_siblings - remove siblings attached to expander
2869 * 2904 * @ioc: Pointer to MPT_ADAPTER structure
2870 * 2905 * @parent: the parent port_info object
2871 * This will traverse topology, and remove expanders 2906 * @expander: the expander port_info object
2872 * that are no longer present 2907 **/
2873 */
2874static void 2908static void
2875mptsas_delete_expander_phys(MPT_ADAPTER *ioc) 2909mptsas_delete_expander_siblings(MPT_ADAPTER *ioc, struct mptsas_portinfo
2910 *parent, struct mptsas_portinfo *expander)
2876{ 2911{
2877 struct mptsas_portinfo buffer;
2878 struct mptsas_portinfo *port_info, *n, *parent;
2879 struct mptsas_phyinfo *phy_info; 2912 struct mptsas_phyinfo *phy_info;
2880 struct sas_port * port; 2913 struct mptsas_portinfo *port_info;
2914 struct sas_rphy *rphy;
2881 int i; 2915 int i;
2882 u64 expander_sas_address;
2883 2916
2884 mutex_lock(&ioc->sas_topology_mutex); 2917 phy_info = expander->phy_info;
2885 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) { 2918 for (i = 0; i < expander->num_phys; i++, phy_info++) {
2919 rphy = mptsas_get_rphy(phy_info);
2920 if (!rphy)
2921 continue;
2922 if (rphy->identify.device_type == SAS_END_DEVICE)
2923 mptsas_del_end_device(ioc, phy_info);
2924 }
2886 2925
2887 if (!(port_info->phy_info[0].identify.device_info & 2926 phy_info = expander->phy_info;
2888 MPI_SAS_DEVICE_INFO_SMP_TARGET)) 2927 for (i = 0; i < expander->num_phys; i++, phy_info++) {
2928 rphy = mptsas_get_rphy(phy_info);
2929 if (!rphy)
2889 continue; 2930 continue;
2931 if (rphy->identify.device_type ==
2932 MPI_SAS_DEVICE_INFO_EDGE_EXPANDER ||
2933 rphy->identify.device_type ==
2934 MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
2935 port_info = mptsas_find_portinfo_by_sas_address(ioc,
2936 rphy->identify.sas_address);
2937 if (!port_info)
2938 continue;
2939 if (port_info == parent) /* backlink rphy */
2940 continue;
2941 /*
2942 Delete this expander even if the expdevpage is exists
2943 because the parent expander is already deleted
2944 */
2945 mptsas_expander_delete(ioc, port_info, 1);
2946 }
2947 }
2948}
2890 2949
2891 if (mptsas_sas_expander_pg0(ioc, &buffer,
2892 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
2893 MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
2894 port_info->phy_info[0].handle)) {
2895 2950
2896 /* 2951/**
2897 * Obtain the port_info instance to the parent port 2952 * mptsas_expander_delete - remove this expander
2898 */ 2953 * @ioc: Pointer to MPT_ADAPTER structure
2899 parent = mptsas_find_portinfo_by_handle(ioc, 2954 * @port_info: expander port_info struct
2900 port_info->phy_info[0].identify.handle_parent); 2955 * @force: Flag to forcefully delete the expander
2956 *
2957 **/
2901 2958
2902 if (!parent) 2959static void mptsas_expander_delete(MPT_ADAPTER *ioc,
2903 goto next_port; 2960 struct mptsas_portinfo *port_info, u8 force)
2961{
2904 2962
2905 expander_sas_address = 2963 struct mptsas_portinfo *parent;
2906 port_info->phy_info[0].identify.sas_address; 2964 int i;
2965 u64 expander_sas_address;
2966 struct mptsas_phyinfo *phy_info;
2967 struct mptsas_portinfo buffer;
2968 struct mptsas_portinfo_details *port_details;
2969 struct sas_port *port;
2907 2970
2908 /* 2971 if (!port_info)
2909 * Delete rphys in the parent that point 2972 return;
2910 * to this expander. The transport layer will
2911 * cleanup all the children.
2912 */
2913 phy_info = parent->phy_info;
2914 for (i = 0; i < parent->num_phys; i++, phy_info++) {
2915 port = mptsas_get_port(phy_info);
2916 if (!port)
2917 continue;
2918 if (phy_info->attached.sas_address !=
2919 expander_sas_address)
2920 continue;
2921 dsaswideprintk(ioc,
2922 dev_printk(KERN_DEBUG, &port->dev,
2923 MYIOC_s_FMT "delete port (%d)\n", ioc->name,
2924 port->port_identifier));
2925 sas_port_delete(port);
2926 mptsas_port_delete(ioc, phy_info->port_details);
2927 }
2928 next_port:
2929 2973
2930 phy_info = port_info->phy_info; 2974 /* see if expander is still there before deleting */
2931 for (i = 0; i < port_info->num_phys; i++, phy_info++) 2975 mptsas_sas_expander_pg0(ioc, &buffer,
2932 mptsas_port_delete(ioc, phy_info->port_details); 2976 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
2977 MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
2978 port_info->phy_info[0].identify.handle);
2933 2979
2934 list_del(&port_info->list); 2980 if (buffer.num_phys) {
2935 kfree(port_info->phy_info);
2936 kfree(port_info);
2937 }
2938 /*
2939 * Free this memory allocated from inside
2940 * mptsas_sas_expander_pg0
2941 */
2942 kfree(buffer.phy_info); 2981 kfree(buffer.phy_info);
2982 if (!force)
2983 return;
2943 } 2984 }
2944 mutex_unlock(&ioc->sas_topology_mutex); 2985
2986
2987 /*
2988 * Obtain the port_info instance to the parent port
2989 */
2990 port_details = NULL;
2991 expander_sas_address =
2992 port_info->phy_info[0].identify.sas_address;
2993 parent = mptsas_find_portinfo_by_handle(ioc,
2994 port_info->phy_info[0].identify.handle_parent);
2995 mptsas_delete_expander_siblings(ioc, parent, port_info);
2996 if (!parent)
2997 goto out;
2998
2999 /*
3000 * Delete rphys in the parent that point
3001 * to this expander.
3002 */
3003 phy_info = parent->phy_info;
3004 port = NULL;
3005 for (i = 0; i < parent->num_phys; i++, phy_info++) {
3006 if (!phy_info->phy)
3007 continue;
3008 if (phy_info->attached.sas_address !=
3009 expander_sas_address)
3010 continue;
3011 if (!port) {
3012 port = mptsas_get_port(phy_info);
3013 port_details = phy_info->port_details;
3014 }
3015 dev_printk(KERN_DEBUG, &phy_info->phy->dev,
3016 MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n", ioc->name,
3017 phy_info->phy_id, phy_info->phy);
3018 sas_port_delete_phy(port, phy_info->phy);
3019 }
3020 if (port) {
3021 dev_printk(KERN_DEBUG, &port->dev,
3022 MYIOC_s_FMT "delete port %d, sas_addr (0x%llx)\n",
3023 ioc->name, port->port_identifier,
3024 (unsigned long long)expander_sas_address);
3025 sas_port_delete(port);
3026 mptsas_port_delete(ioc, port_details);
3027 }
3028 out:
3029
3030 printk(MYIOC_s_INFO_FMT "delete expander: num_phys %d, "
3031 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3032 (unsigned long long)expander_sas_address);
3033
3034 /*
3035 * free link
3036 */
3037 list_del(&port_info->list);
3038 kfree(port_info->phy_info);
3039 kfree(port_info);
2945} 3040}
2946 3041
2947/* 3042
2948 * Start of day discovery 3043/**
3044 * mptsas_send_expander_event - expanders events
3045 * @ioc: Pointer to MPT_ADAPTER structure
3046 * @expander_data: event data
3047 *
3048 *
3049 * This function handles adding, removing, and refreshing
3050 * device handles within the expander objects.
2949 */ 3051 */
2950static void 3052static void
2951mptsas_scan_sas_topology(MPT_ADAPTER *ioc) 3053mptsas_send_expander_event(struct fw_event_work *fw_event)
2952{ 3054{
2953 u32 handle = 0xFFFF; 3055 MPT_ADAPTER *ioc;
3056 MpiEventDataSasExpanderStatusChange_t *expander_data;
3057 struct mptsas_portinfo *port_info;
3058 __le64 sas_address;
2954 int i; 3059 int i;
2955 3060
2956 mutex_lock(&ioc->sas_discovery_mutex); 3061 ioc = fw_event->ioc;
2957 mptsas_probe_hba_phys(ioc); 3062 expander_data = (MpiEventDataSasExpanderStatusChange_t *)
2958 while (!mptsas_probe_expander_phys(ioc, &handle)) 3063 fw_event->event_data;
2959 ; 3064 memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
2960 /* 3065 port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
2961 Reporting RAID volumes. 3066
2962 */ 3067 if (expander_data->ReasonCode == MPI_EVENT_SAS_EXP_RC_ADDED) {
2963 if (!ioc->ir_firmware) 3068 if (port_info) {
2964 goto out; 3069 for (i = 0; i < port_info->num_phys; i++) {
2965 if (!ioc->raid_data.pIocPg2) 3070 port_info->phy_info[i].portinfo = port_info;
2966 goto out; 3071 port_info->phy_info[i].handle =
2967 if (!ioc->raid_data.pIocPg2->NumActiveVolumes) 3072 le16_to_cpu(expander_data->DevHandle);
2968 goto out; 3073 port_info->phy_info[i].identify.sas_address =
2969 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { 3074 le64_to_cpu(sas_address);
2970 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, 3075 port_info->phy_info[i].identify.handle_parent =
2971 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0); 3076 le16_to_cpu(expander_data->ParentDevHandle);
3077 }
3078 mptsas_expander_refresh(ioc, port_info);
3079 } else if (!port_info && expander_data->NumPhys)
3080 mptsas_expander_event_add(ioc, expander_data);
3081 } else if (expander_data->ReasonCode ==
3082 MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING)
3083 mptsas_expander_delete(ioc, port_info, 0);
3084
3085 mptsas_free_fw_event(ioc, fw_event);
3086}
3087
3088
3089/**
3090 * mptsas_expander_add -
3091 * @ioc: Pointer to MPT_ADAPTER structure
3092 * @handle:
3093 *
3094 */
3095struct mptsas_portinfo *
3096mptsas_expander_add(MPT_ADAPTER *ioc, u16 handle)
3097{
3098 struct mptsas_portinfo buffer, *port_info;
3099 int i;
3100
3101 if ((mptsas_sas_expander_pg0(ioc, &buffer,
3102 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
3103 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)))
3104 return NULL;
3105
3106 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_ATOMIC);
3107 if (!port_info) {
3108 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3109 "%s: exit at line=%d\n", ioc->name,
3110 __func__, __LINE__));
3111 return NULL;
3112 }
3113 port_info->num_phys = buffer.num_phys;
3114 port_info->phy_info = buffer.phy_info;
3115 for (i = 0; i < port_info->num_phys; i++)
3116 port_info->phy_info[i].portinfo = port_info;
3117 mutex_lock(&ioc->sas_topology_mutex);
3118 list_add_tail(&port_info->list, &ioc->sas_topology);
3119 mutex_unlock(&ioc->sas_topology_mutex);
3120 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3121 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3122 (unsigned long long)buffer.phy_info[0].identify.sas_address);
3123 mptsas_expander_refresh(ioc, port_info);
3124 return port_info;
3125}
3126
3127static void
3128mptsas_send_link_status_event(struct fw_event_work *fw_event)
3129{
3130 MPT_ADAPTER *ioc;
3131 MpiEventDataSasPhyLinkStatus_t *link_data;
3132 struct mptsas_portinfo *port_info;
3133 struct mptsas_phyinfo *phy_info = NULL;
3134 __le64 sas_address;
3135 u8 phy_num;
3136 u8 link_rate;
3137
3138 ioc = fw_event->ioc;
3139 link_data = (MpiEventDataSasPhyLinkStatus_t *)fw_event->event_data;
3140
3141 memcpy(&sas_address, &link_data->SASAddress, sizeof(__le64));
3142 sas_address = le64_to_cpu(sas_address);
3143 link_rate = link_data->LinkRates >> 4;
3144 phy_num = link_data->PhyNum;
3145
3146 port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
3147 if (port_info) {
3148 phy_info = &port_info->phy_info[phy_num];
3149 if (phy_info)
3150 phy_info->negotiated_link_rate = link_rate;
3151 }
3152
3153 if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 ||
3154 link_rate == MPI_SAS_IOUNIT0_RATE_3_0) {
3155
3156 if (!port_info)
3157 goto out;
3158
3159 if (port_info == ioc->hba_port_info)
3160 mptsas_probe_hba_phys(ioc);
3161 else
3162 mptsas_expander_refresh(ioc, port_info);
3163 } else if (phy_info && phy_info->phy) {
3164 if (link_rate == MPI_SAS_IOUNIT0_RATE_PHY_DISABLED)
3165 phy_info->phy->negotiated_linkrate =
3166 SAS_PHY_DISABLED;
3167 else if (link_rate ==
3168 MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION)
3169 phy_info->phy->negotiated_linkrate =
3170 SAS_LINK_RATE_FAILED;
3171 else
3172 phy_info->phy->negotiated_linkrate =
3173 SAS_LINK_RATE_UNKNOWN;
2972 } 3174 }
2973 out: 3175 out:
2974 mutex_unlock(&ioc->sas_discovery_mutex); 3176 mptsas_free_fw_event(ioc, fw_event);
2975} 3177}
2976 3178
2977/* 3179/**
2978 * Work queue thread to handle Runtime discovery 3180 * mptsas_probe_expanders - adding expanders
2979 * Mere purpose is the hot add/delete of expanders 3181 * @ioc: Pointer to MPT_ADAPTER structure
2980 *(Mutex UNLOCKED) 3182 *
2981 */ 3183 **/
2982static void 3184static void
2983__mptsas_discovery_work(MPT_ADAPTER *ioc) 3185mptsas_probe_expanders(MPT_ADAPTER *ioc)
2984{ 3186{
2985 u32 handle = 0xFFFF; 3187 struct mptsas_portinfo buffer, *port_info;
3188 u32 handle;
3189 int i;
2986 3190
2987 ioc->sas_discovery_runtime=1; 3191 handle = 0xFFFF;
2988 mptsas_delete_expander_phys(ioc); 3192 while (!mptsas_sas_expander_pg0(ioc, &buffer,
2989 mptsas_probe_hba_phys(ioc); 3193 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
2990 while (!mptsas_probe_expander_phys(ioc, &handle)) 3194 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)) {
2991 ; 3195
2992 ioc->sas_discovery_runtime=0; 3196 handle = buffer.phy_info[0].handle;
3197 port_info = mptsas_find_portinfo_by_sas_address(ioc,
3198 buffer.phy_info[0].identify.sas_address);
3199
3200 if (port_info) {
3201 /* refreshing handles */
3202 for (i = 0; i < buffer.num_phys; i++) {
3203 port_info->phy_info[i].handle = handle;
3204 port_info->phy_info[i].identify.handle_parent =
3205 buffer.phy_info[0].identify.handle_parent;
3206 }
3207 mptsas_expander_refresh(ioc, port_info);
3208 kfree(buffer.phy_info);
3209 continue;
3210 }
3211
3212 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3213 if (!port_info) {
3214 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3215 "%s: exit at line=%d\n", ioc->name,
3216 __func__, __LINE__));
3217 return;
3218 }
3219 port_info->num_phys = buffer.num_phys;
3220 port_info->phy_info = buffer.phy_info;
3221 for (i = 0; i < port_info->num_phys; i++)
3222 port_info->phy_info[i].portinfo = port_info;
3223 mutex_lock(&ioc->sas_topology_mutex);
3224 list_add_tail(&port_info->list, &ioc->sas_topology);
3225 mutex_unlock(&ioc->sas_topology_mutex);
3226 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3227 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3228 (unsigned long long)buffer.phy_info[0].identify.sas_address);
3229 mptsas_expander_refresh(ioc, port_info);
3230 }
3231}
3232
3233static void
3234mptsas_probe_devices(MPT_ADAPTER *ioc)
3235{
3236 u16 handle;
3237 struct mptsas_devinfo sas_device;
3238 struct mptsas_phyinfo *phy_info;
3239
3240 handle = 0xFFFF;
3241 while (!(mptsas_sas_device_pg0(ioc, &sas_device,
3242 MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
3243
3244 handle = sas_device.handle;
3245
3246 if ((sas_device.device_info &
3247 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
3248 MPI_SAS_DEVICE_INFO_STP_TARGET |
3249 MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0)
3250 continue;
3251
3252 phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
3253 if (!phy_info)
3254 continue;
3255
3256 if (mptsas_get_rphy(phy_info))
3257 continue;
3258
3259 mptsas_add_end_device(ioc, phy_info);
3260 }
2993} 3261}
2994 3262
2995/* 3263/*
2996 * Work queue thread to handle Runtime discovery 3264 * Start of day discovery
2997 * Mere purpose is the hot add/delete of expanders
2998 *(Mutex LOCKED)
2999 */ 3265 */
3000static void 3266static void
3001mptsas_discovery_work(struct work_struct *work) 3267mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
3002{ 3268{
3003 struct mptsas_discovery_event *ev = 3269 struct scsi_device *sdev;
3004 container_of(work, struct mptsas_discovery_event, work); 3270 int i;
3005 MPT_ADAPTER *ioc = ev->ioc;
3006 3271
3007 mutex_lock(&ioc->sas_discovery_mutex); 3272 mptsas_probe_hba_phys(ioc);
3008 __mptsas_discovery_work(ioc); 3273 mptsas_probe_expanders(ioc);
3009 mutex_unlock(&ioc->sas_discovery_mutex); 3274 mptsas_probe_devices(ioc);
3010 kfree(ev);
3011}
3012 3275
3276 /*
3277 Reporting RAID volumes.
3278 */
3279 if (!ioc->ir_firmware || !ioc->raid_data.pIocPg2 ||
3280 !ioc->raid_data.pIocPg2->NumActiveVolumes)
3281 return;
3282 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
3283 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
3284 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
3285 if (sdev) {
3286 scsi_device_put(sdev);
3287 continue;
3288 }
3289 printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
3290 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
3291 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID);
3292 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
3293 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
3294 }
3295}
3013 3296
3014static struct mptsas_phyinfo * 3297static struct mptsas_phyinfo *
3015mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) 3298mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
@@ -3544,33 +3827,6 @@ mptsas_send_raid_event(struct fw_event_work *fw_event)
3544 mptsas_free_fw_event(ioc, fw_event); 3827 mptsas_free_fw_event(ioc, fw_event);
3545} 3828}
3546 3829
3547static void
3548mptsas_send_discovery_event(MPT_ADAPTER *ioc,
3549 EVENT_DATA_SAS_DISCOVERY *discovery_data)
3550{
3551 struct mptsas_discovery_event *ev;
3552 u32 discovery_status;
3553
3554 /*
3555 * DiscoveryStatus
3556 *
3557 * This flag will be non-zero when firmware
3558 * kicks off discovery, and return to zero
3559 * once its completed.
3560 */
3561 discovery_status = le32_to_cpu(discovery_data->DiscoveryStatus);
3562 ioc->sas_discovery_quiesce_io = discovery_status ? 1 : 0;
3563 if (discovery_status)
3564 return;
3565
3566 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
3567 if (!ev)
3568 return;
3569 INIT_WORK(&ev->work, mptsas_discovery_work);
3570 ev->ioc = ioc;
3571 schedule_work(&ev->work);
3572};
3573
3574/* 3830/*
3575 * mptsas_send_ir2_event - handle exposing hidden disk when 3831 * mptsas_send_ir2_event - handle exposing hidden disk when
3576 * an inactive raid volume is added 3832 * an inactive raid volume is added
@@ -3634,10 +3890,28 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
3634 } 3890 }
3635 break; 3891 break;
3636 } 3892 }
3637 case MPI_EVENT_SAS_DISCOVERY: 3893 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
3638 mptsas_send_discovery_event(ioc, 3894 {
3639 (EVENT_DATA_SAS_DISCOVERY *)reply->Data); 3895 MpiEventDataSasExpanderStatusChange_t *expander_data =
3896 (MpiEventDataSasExpanderStatusChange_t *)reply->Data;
3897
3898
3899 if (expander_data->ReasonCode ==
3900 MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING &&
3901 ioc->device_missing_delay)
3902 delay = HZ * ioc->device_missing_delay;
3640 break; 3903 break;
3904 }
3905 case MPI_EVENT_SAS_DISCOVERY:
3906 {
3907 u32 discovery_status;
3908 EventDataSasDiscovery_t *discovery_data =
3909 (EventDataSasDiscovery_t *)reply->Data;
3910
3911 discovery_status = le32_to_cpu(discovery_data->DiscoveryStatus);
3912 ioc->sas_discovery_quiesce_io = discovery_status ? 1 : 0;
3913 return 0;
3914 }
3641 case MPI_EVENT_INTEGRATED_RAID: 3915 case MPI_EVENT_INTEGRATED_RAID:
3642 case MPI_EVENT_PERSISTENT_TABLE_FULL: 3916 case MPI_EVENT_PERSISTENT_TABLE_FULL:
3643 case MPI_EVENT_IR2: 3917 case MPI_EVENT_IR2:
@@ -3885,7 +4159,7 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
3885 kfree(p); 4159 kfree(p);
3886 } 4160 }
3887 mutex_unlock(&ioc->sas_topology_mutex); 4161 mutex_unlock(&ioc->sas_topology_mutex);
3888 4162 ioc->hba_port_info = NULL;
3889 mptscsih_remove(pdev); 4163 mptscsih_remove(pdev);
3890} 4164}
3891 4165