aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptsas.c
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2009-05-29 07:19:36 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-06-09 18:42:06 -0400
commitf9c34022eae9c76465dc2ec8805b9905e171ef40 (patch)
tree57d028bb38e739c38e2f1d2c65515ddfae7f0140 /drivers/message/fusion/mptsas.c
parent3eb0822c6740c5564c37a2fe56449cdb4f3d800c (diff)
[SCSI] mpt fusion: SAS topology scan changes, expander events
SAS topology scan is restructured. HBA firmware is generating more events. Expander Events are added, Link status events are also added with respect to SAS topology scan optimization. Signed-off-by: Kashyap Desai <kadesai@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/message/fusion/mptsas.c')
-rw-r--r--drivers/message/fusion/mptsas.c746
1 files changed, 510 insertions, 236 deletions
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