aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2006-01-13 12:04:41 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2006-01-14 11:54:56 -0500
commit9a28f49adbe4955af8a1306fd36ddae15136dde7 (patch)
treeff161da935cf2a14408b9040f685b9e9a530fd82 /drivers
parent9638d89a75776abc614c29cdeece0cc874ea2a4c (diff)
[SCSI] mptsas: support basic hotplug
Adds hotplug support for SAS end devices. Unfortunately the fusion firmware doesn't generate similar events for expanders addition/removal so we can't support them yet. Eric has an idea about a clever scheme to find out about expander changes so that'll be added later on. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/message/fusion/mptbase.h1
-rw-r--r--drivers/message/fusion/mptsas.c338
2 files changed, 308 insertions, 31 deletions
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 6c48d1f54ac9..af9007d498ee 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -612,6 +612,7 @@ typedef struct _MPT_ADAPTER
612 struct list_head list; 612 struct list_head list;
613 struct net_device *netdev; 613 struct net_device *netdev;
614 struct list_head sas_topology; 614 struct list_head sas_topology;
615 struct mutex sas_topology_mutex;
615 MPT_SAS_MGMT sas_mgmt; 616 MPT_SAS_MGMT sas_mgmt;
616} MPT_ADAPTER; 617} MPT_ADAPTER;
617 618
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 17e9757e728b..b2c682fe634f 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -5,7 +5,7 @@
5 * 5 *
6 * Copyright (c) 1999-2005 LSI Logic Corporation 6 * Copyright (c) 1999-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com) 7 * (mailto:mpt_linux_developer@lsil.com)
8 * Copyright (c) 2005 Dell 8 * Copyright (c) 2005-2006 Dell
9 */ 9 */
10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11/* 11/*
@@ -86,6 +86,24 @@ static int mptsasInternalCtx = -1; /* Used only for internal commands */
86static int mptsasMgmtCtx = -1; 86static int mptsasMgmtCtx = -1;
87 87
88 88
89enum mptsas_hotplug_action {
90 MPTSAS_ADD_DEVICE,
91 MPTSAS_DEL_DEVICE,
92};
93
94struct mptsas_hotplug_event {
95 struct work_struct work;
96 MPT_ADAPTER *ioc;
97 enum mptsas_hotplug_action event_type;
98 u64 sas_address;
99 u32 channel;
100 u32 id;
101 u32 device_info;
102 u16 handle;
103 u16 parent_handle;
104 u8 phy_id;
105};
106
89/* 107/*
90 * SAS topology structures 108 * SAS topology structures
91 * 109 *
@@ -99,8 +117,8 @@ struct mptsas_devinfo {
99 u8 phy_id; /* phy number of parent device */ 117 u8 phy_id; /* phy number of parent device */
100 u8 port_id; /* sas physical port this device 118 u8 port_id; /* sas physical port this device
101 is assoc'd with */ 119 is assoc'd with */
102 u8 target; /* logical target id of this device */ 120 u8 id; /* logical target id of this device */
103 u8 bus; /* logical bus number of this device */ 121 u8 channel; /* logical bus number of this device */
104 u64 sas_address; /* WWN of this device, 122 u64 sas_address; /* WWN of this device,
105 SATA is assigned by HBA,expander */ 123 SATA is assigned by HBA,expander */
106 u32 device_info; /* bitfield detailed info about this device */ 124 u32 device_info; /* bitfield detailed info about this device */
@@ -114,6 +132,7 @@ struct mptsas_phyinfo {
114 u8 programmed_link_rate; /* programmed max/min phy link rate */ 132 u8 programmed_link_rate; /* programmed max/min phy link rate */
115 struct mptsas_devinfo identify; /* point to phy device info */ 133 struct mptsas_devinfo identify; /* point to phy device info */
116 struct mptsas_devinfo attached; /* point to attached device info */ 134 struct mptsas_devinfo attached; /* point to attached device info */
135 struct sas_phy *phy;
117 struct sas_rphy *rphy; 136 struct sas_rphy *rphy;
118}; 137};
119 138
@@ -257,24 +276,27 @@ mptsas_slave_alloc(struct scsi_device *sdev)
257 } 276 }
258 277
259 rphy = dev_to_rphy(sdev->sdev_target->dev.parent); 278 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
279 mutex_lock(&hd->ioc->sas_topology_mutex);
260 list_for_each_entry(p, &hd->ioc->sas_topology, list) { 280 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
261 for (i = 0; i < p->num_phys; i++) { 281 for (i = 0; i < p->num_phys; i++) {
262 if (p->phy_info[i].attached.sas_address == 282 if (p->phy_info[i].attached.sas_address ==
263 rphy->identify.sas_address) { 283 rphy->identify.sas_address) {
264 vdev->target_id = 284 vdev->target_id =
265 p->phy_info[i].attached.target; 285 p->phy_info[i].attached.id;
266 vdev->bus_id = p->phy_info[i].attached.bus; 286 vdev->bus_id = p->phy_info[i].attached.channel;
267 vdev->lun = sdev->lun; 287 vdev->lun = sdev->lun;
268 goto out; 288 goto out;
269 } 289 }
270 } 290 }
271 } 291 }
292 mutex_unlock(&hd->ioc->sas_topology_mutex);
272 293
273 printk("No matching SAS device found!!\n"); 294 printk("No matching SAS device found!!\n");
274 kfree(vdev); 295 kfree(vdev);
275 return -ENODEV; 296 return -ENODEV;
276 297
277 out: 298 out:
299 mutex_unlock(&hd->ioc->sas_topology_mutex);
278 vtarget->ioc_id = vdev->ioc_id; 300 vtarget->ioc_id = vdev->ioc_id;
279 vtarget->target_id = vdev->target_id; 301 vtarget->target_id = vdev->target_id;
280 vtarget->bus_id = vdev->bus_id; 302 vtarget->bus_id = vdev->bus_id;
@@ -282,6 +304,42 @@ mptsas_slave_alloc(struct scsi_device *sdev)
282 return 0; 304 return 0;
283} 305}
284 306
307static void
308mptsas_slave_destroy(struct scsi_device *sdev)
309{
310 struct Scsi_Host *host = sdev->host;
311 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
312 struct sas_rphy *rphy;
313 struct mptsas_portinfo *p;
314 int i;
315
316 /*
317 * Handle hotplug removal case.
318 * We need to clear out attached data structure.
319 */
320 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
321
322 mutex_lock(&hd->ioc->sas_topology_mutex);
323 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
324 for (i = 0; i < p->num_phys; i++) {
325 if (p->phy_info[i].attached.sas_address ==
326 rphy->identify.sas_address) {
327 memset(&p->phy_info[i].attached, 0,
328 sizeof(struct mptsas_devinfo));
329 p->phy_info[i].rphy = NULL;
330 goto out;
331 }
332 }
333 }
334
335 out:
336 mutex_unlock(&hd->ioc->sas_topology_mutex);
337 /*
338 * TODO: Issue target reset to flush firmware outstanding commands.
339 */
340 mptscsih_slave_destroy(sdev);
341}
342
285static struct scsi_host_template mptsas_driver_template = { 343static struct scsi_host_template mptsas_driver_template = {
286 .module = THIS_MODULE, 344 .module = THIS_MODULE,
287 .proc_name = "mptsas", 345 .proc_name = "mptsas",
@@ -293,7 +351,7 @@ static struct scsi_host_template mptsas_driver_template = {
293 .slave_alloc = mptsas_slave_alloc, 351 .slave_alloc = mptsas_slave_alloc,
294 .slave_configure = mptscsih_slave_configure, 352 .slave_configure = mptscsih_slave_configure,
295 .target_destroy = mptscsih_target_destroy, 353 .target_destroy = mptscsih_target_destroy,
296 .slave_destroy = mptscsih_slave_destroy, 354 .slave_destroy = mptsas_slave_destroy,
297 .change_queue_depth = mptscsih_change_queue_depth, 355 .change_queue_depth = mptscsih_change_queue_depth,
298 .eh_abort_handler = mptscsih_abort, 356 .eh_abort_handler = mptscsih_abort,
299 .eh_device_reset_handler = mptscsih_dev_reset, 357 .eh_device_reset_handler = mptscsih_dev_reset,
@@ -649,8 +707,8 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
649 device_info->handle = le16_to_cpu(buffer->DevHandle); 707 device_info->handle = le16_to_cpu(buffer->DevHandle);
650 device_info->phy_id = buffer->PhyNum; 708 device_info->phy_id = buffer->PhyNum;
651 device_info->port_id = buffer->PhysicalPort; 709 device_info->port_id = buffer->PhysicalPort;
652 device_info->target = buffer->TargetID; 710 device_info->id = buffer->TargetID;
653 device_info->bus = buffer->Bus; 711 device_info->channel = buffer->Bus;
654 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); 712 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
655 device_info->sas_address = le64_to_cpu(sas_address); 713 device_info->sas_address = le64_to_cpu(sas_address);
656 device_info->device_info = 714 device_info->device_info =
@@ -858,36 +916,36 @@ mptsas_parse_device_info(struct sas_identify *identify,
858static int mptsas_probe_one_phy(struct device *dev, 916static int mptsas_probe_one_phy(struct device *dev,
859 struct mptsas_phyinfo *phy_info, int index, int local) 917 struct mptsas_phyinfo *phy_info, int index, int local)
860{ 918{
861 struct sas_phy *port; 919 struct sas_phy *phy;
862 int error; 920 int error;
863 921
864 port = sas_phy_alloc(dev, index); 922 phy = sas_phy_alloc(dev, index);
865 if (!port) 923 if (!phy)
866 return -ENOMEM; 924 return -ENOMEM;
867 925
868 port->port_identifier = phy_info->port_id; 926 phy->port_identifier = phy_info->port_id;
869 mptsas_parse_device_info(&port->identify, &phy_info->identify); 927 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
870 928
871 /* 929 /*
872 * Set Negotiated link rate. 930 * Set Negotiated link rate.
873 */ 931 */
874 switch (phy_info->negotiated_link_rate) { 932 switch (phy_info->negotiated_link_rate) {
875 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED: 933 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
876 port->negotiated_linkrate = SAS_PHY_DISABLED; 934 phy->negotiated_linkrate = SAS_PHY_DISABLED;
877 break; 935 break;
878 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION: 936 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
879 port->negotiated_linkrate = SAS_LINK_RATE_FAILED; 937 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
880 break; 938 break;
881 case MPI_SAS_IOUNIT0_RATE_1_5: 939 case MPI_SAS_IOUNIT0_RATE_1_5:
882 port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS; 940 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
883 break; 941 break;
884 case MPI_SAS_IOUNIT0_RATE_3_0: 942 case MPI_SAS_IOUNIT0_RATE_3_0:
885 port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS; 943 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
886 break; 944 break;
887 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE: 945 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
888 case MPI_SAS_IOUNIT0_RATE_UNKNOWN: 946 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
889 default: 947 default:
890 port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; 948 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
891 break; 949 break;
892 } 950 }
893 951
@@ -896,10 +954,10 @@ static int mptsas_probe_one_phy(struct device *dev,
896 */ 954 */
897 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { 955 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
898 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5: 956 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
899 port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; 957 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
900 break; 958 break;
901 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: 959 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
902 port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; 960 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
903 break; 961 break;
904 default: 962 default:
905 break; 963 break;
@@ -911,10 +969,10 @@ static int mptsas_probe_one_phy(struct device *dev,
911 switch (phy_info->programmed_link_rate & 969 switch (phy_info->programmed_link_rate &
912 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { 970 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
913 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5: 971 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
914 port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS; 972 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
915 break; 973 break;
916 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: 974 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
917 port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS; 975 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
918 break; 976 break;
919 default: 977 default:
920 break; 978 break;
@@ -925,10 +983,10 @@ static int mptsas_probe_one_phy(struct device *dev,
925 */ 983 */
926 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) { 984 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
927 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5: 985 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
928 port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; 986 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
929 break; 987 break;
930 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: 988 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
931 port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; 989 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
932 break; 990 break;
933 default: 991 default:
934 break; 992 break;
@@ -940,28 +998,29 @@ static int mptsas_probe_one_phy(struct device *dev,
940 switch (phy_info->programmed_link_rate & 998 switch (phy_info->programmed_link_rate &
941 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) { 999 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
942 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5: 1000 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
943 port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS; 1001 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
944 break; 1002 break;
945 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: 1003 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
946 port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS; 1004 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
947 break; 1005 break;
948 default: 1006 default:
949 break; 1007 break;
950 } 1008 }
951 1009
952 if (local) 1010 if (local)
953 port->local_attached = 1; 1011 phy->local_attached = 1;
954 1012
955 error = sas_phy_add(port); 1013 error = sas_phy_add(phy);
956 if (error) { 1014 if (error) {
957 sas_phy_free(port); 1015 sas_phy_free(phy);
958 return error; 1016 return error;
959 } 1017 }
1018 phy_info->phy = phy;
960 1019
961 if (phy_info->attached.handle) { 1020 if (phy_info->attached.handle) {
962 struct sas_rphy *rphy; 1021 struct sas_rphy *rphy;
963 1022
964 rphy = sas_rphy_alloc(port); 1023 rphy = sas_rphy_alloc(phy);
965 if (!rphy) 1024 if (!rphy)
966 return 0; /* non-fatal: an rphy can be added later */ 1025 return 0; /* non-fatal: an rphy can be added later */
967 1026
@@ -994,7 +1053,10 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
994 if (error) 1053 if (error)
995 goto out_free_port_info; 1054 goto out_free_port_info;
996 1055
1056 mutex_lock(&ioc->sas_topology_mutex);
997 list_add_tail(&port_info->list, &ioc->sas_topology); 1057 list_add_tail(&port_info->list, &ioc->sas_topology);
1058 mutex_unlock(&ioc->sas_topology_mutex);
1059
998 for (i = 0; i < port_info->num_phys; i++) { 1060 for (i = 0; i < port_info->num_phys; i++) {
999 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], 1061 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1000 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER << 1062 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
@@ -1047,7 +1109,10 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
1047 1109
1048 *handle = port_info->handle; 1110 *handle = port_info->handle;
1049 1111
1112 mutex_lock(&ioc->sas_topology_mutex);
1050 list_add_tail(&port_info->list, &ioc->sas_topology); 1113 list_add_tail(&port_info->list, &ioc->sas_topology);
1114 mutex_unlock(&ioc->sas_topology_mutex);
1115
1051 for (i = 0; i < port_info->num_phys; i++) { 1116 for (i = 0; i < port_info->num_phys; i++) {
1052 struct device *parent; 1117 struct device *parent;
1053 1118
@@ -1079,6 +1144,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
1079 * HBA phys. 1144 * HBA phys.
1080 */ 1145 */
1081 parent = &ioc->sh->shost_gendev; 1146 parent = &ioc->sh->shost_gendev;
1147 mutex_lock(&ioc->sas_topology_mutex);
1082 list_for_each_entry(p, &ioc->sas_topology, list) { 1148 list_for_each_entry(p, &ioc->sas_topology, list) {
1083 for (j = 0; j < p->num_phys; j++) { 1149 for (j = 0; j < p->num_phys; j++) {
1084 if (port_info->phy_info[i].identify.handle == 1150 if (port_info->phy_info[i].identify.handle ==
@@ -1086,6 +1152,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
1086 parent = &p->phy_info[j].rphy->dev; 1152 parent = &p->phy_info[j].rphy->dev;
1087 } 1153 }
1088 } 1154 }
1155 mutex_unlock(&ioc->sas_topology_mutex);
1089 1156
1090 mptsas_probe_one_phy(parent, &port_info->phy_info[i], 1157 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
1091 *index, 0); 1158 *index, 0);
@@ -1111,6 +1178,211 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1111 ; 1178 ;
1112} 1179}
1113 1180
1181static struct mptsas_phyinfo *
1182mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
1183{
1184 struct mptsas_portinfo *port_info;
1185 struct mptsas_devinfo device_info;
1186 struct mptsas_phyinfo *phy_info = NULL;
1187 int i, error;
1188
1189 /*
1190 * Retrieve the parent sas_address
1191 */
1192 error = mptsas_sas_device_pg0(ioc, &device_info,
1193 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1194 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1195 parent_handle);
1196 if (error) {
1197 printk("mptsas: failed to retrieve device page\n");
1198 return NULL;
1199 }
1200
1201 /*
1202 * The phy_info structures are never deallocated during lifetime of
1203 * a host, so the code below is safe without additional refcounting.
1204 */
1205 mutex_lock(&ioc->sas_topology_mutex);
1206 list_for_each_entry(port_info, &ioc->sas_topology, list) {
1207 for (i = 0; i < port_info->num_phys; i++) {
1208 if (port_info->phy_info[i].identify.sas_address ==
1209 device_info.sas_address &&
1210 port_info->phy_info[i].phy_id == phy_id) {
1211 phy_info = &port_info->phy_info[i];
1212 break;
1213 }
1214 }
1215 }
1216 mutex_unlock(&ioc->sas_topology_mutex);
1217
1218 return phy_info;
1219}
1220
1221static struct mptsas_phyinfo *
1222mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
1223{
1224 struct mptsas_portinfo *port_info;
1225 struct mptsas_phyinfo *phy_info = NULL;
1226 int i;
1227
1228 /*
1229 * The phy_info structures are never deallocated during lifetime of
1230 * a host, so the code below is safe without additional refcounting.
1231 */
1232 mutex_lock(&ioc->sas_topology_mutex);
1233 list_for_each_entry(port_info, &ioc->sas_topology, list) {
1234 for (i = 0; i < port_info->num_phys; i++) {
1235 if (port_info->phy_info[i].attached.handle == handle) {
1236 phy_info = &port_info->phy_info[i];
1237 break;
1238 }
1239 }
1240 }
1241 mutex_unlock(&ioc->sas_topology_mutex);
1242
1243 return phy_info;
1244}
1245
1246static void
1247mptsas_hotplug_work(void *arg)
1248{
1249 struct mptsas_hotplug_event *ev = arg;
1250 MPT_ADAPTER *ioc = ev->ioc;
1251 struct mptsas_phyinfo *phy_info;
1252 struct sas_rphy *rphy;
1253 char *ds = NULL;
1254
1255 if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1256 ds = "ssp";
1257 if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1258 ds = "stp";
1259 if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1260 ds = "sata";
1261
1262 switch (ev->event_type) {
1263 case MPTSAS_DEL_DEVICE:
1264 printk(MYIOC_s_INFO_FMT
1265 "removing %s device, channel %d, id %d, phy %d\n",
1266 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1267
1268 phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle);
1269 if (!phy_info) {
1270 printk("mptsas: remove event for non-existant PHY.\n");
1271 break;
1272 }
1273
1274 if (phy_info->rphy) {
1275 sas_rphy_delete(phy_info->rphy);
1276 phy_info->rphy = NULL;
1277 }
1278 break;
1279 case MPTSAS_ADD_DEVICE:
1280 printk(MYIOC_s_INFO_FMT
1281 "attaching %s device, channel %d, id %d, phy %d\n",
1282 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1283
1284 phy_info = mptsas_find_phyinfo_by_parent(ioc,
1285 ev->parent_handle, ev->phy_id);
1286 if (!phy_info) {
1287 printk("mptsas: add event for non-existant PHY.\n");
1288 break;
1289 }
1290
1291 if (phy_info->rphy) {
1292 printk("mptsas: trying to add existing device.\n");
1293 break;
1294 }
1295
1296 /* fill attached info */
1297 phy_info->attached.handle = ev->handle;
1298 phy_info->attached.phy_id = ev->phy_id;
1299 phy_info->attached.port_id = phy_info->identify.port_id;
1300 phy_info->attached.id = ev->id;
1301 phy_info->attached.channel = ev->channel;
1302 phy_info->attached.sas_address = ev->sas_address;
1303 phy_info->attached.device_info = ev->device_info;
1304
1305 rphy = sas_rphy_alloc(phy_info->phy);
1306 if (!rphy)
1307 break; /* non-fatal: an rphy can be added later */
1308
1309 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1310 if (sas_rphy_add(rphy)) {
1311 sas_rphy_free(rphy);
1312 break;
1313 }
1314
1315 phy_info->rphy = rphy;
1316 break;
1317 }
1318
1319 kfree(ev);
1320}
1321
1322static void
1323mptscsih_send_sas_event(MPT_ADAPTER *ioc,
1324 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
1325{
1326 struct mptsas_hotplug_event *ev;
1327 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
1328 __le64 sas_address;
1329
1330 if ((device_info &
1331 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
1332 MPI_SAS_DEVICE_INFO_STP_TARGET |
1333 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
1334 return;
1335
1336 if ((sas_event_data->ReasonCode &
1337 (MPI_EVENT_SAS_DEV_STAT_RC_ADDED |
1338 MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0)
1339 return;
1340
1341 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1342 if (!ev) {
1343 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1344 return;
1345 }
1346
1347
1348 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1349 ev->ioc = ioc;
1350 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
1351 ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);
1352 ev->channel = sas_event_data->Bus;
1353 ev->id = sas_event_data->TargetID;
1354 ev->phy_id = sas_event_data->PhyNum;
1355 memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64));
1356 ev->sas_address = le64_to_cpu(sas_address);
1357 ev->device_info = device_info;
1358
1359 if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
1360 ev->event_type = MPTSAS_ADD_DEVICE;
1361 else
1362 ev->event_type = MPTSAS_DEL_DEVICE;
1363
1364 schedule_work(&ev->work);
1365}
1366
1367static int
1368mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
1369{
1370 u8 event = le32_to_cpu(reply->Event) & 0xFF;
1371
1372 if (!ioc->sh)
1373 return 1;
1374
1375 switch (event) {
1376 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1377 mptscsih_send_sas_event(ioc,
1378 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
1379 return 1; /* currently means nothing really */
1380
1381 default:
1382 return mptscsih_event_process(ioc, reply);
1383 }
1384}
1385
1114static int 1386static int
1115mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) 1387mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1116{ 1388{
@@ -1203,6 +1475,8 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1203 sh->unique_id = ioc->id; 1475 sh->unique_id = ioc->id;
1204 1476
1205 INIT_LIST_HEAD(&ioc->sas_topology); 1477 INIT_LIST_HEAD(&ioc->sas_topology);
1478 mutex_init(&ioc->sas_topology_mutex);
1479
1206 init_MUTEX(&ioc->sas_mgmt.mutex); 1480 init_MUTEX(&ioc->sas_mgmt.mutex);
1207 init_completion(&ioc->sas_mgmt.done); 1481 init_completion(&ioc->sas_mgmt.done);
1208 1482
@@ -1339,10 +1613,12 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
1339 1613
1340 sas_remove_host(ioc->sh); 1614 sas_remove_host(ioc->sh);
1341 1615
1616 mutex_lock(&ioc->sas_topology_mutex);
1342 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) { 1617 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
1343 list_del(&p->list); 1618 list_del(&p->list);
1344 kfree(p); 1619 kfree(p);
1345 } 1620 }
1621 mutex_unlock(&ioc->sas_topology_mutex);
1346 1622
1347 mptscsih_remove(pdev); 1623 mptscsih_remove(pdev);
1348} 1624}
@@ -1393,7 +1669,7 @@ mptsas_init(void)
1393 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); 1669 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
1394 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); 1670 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
1395 1671
1396 if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) { 1672 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
1397 devtprintk((KERN_INFO MYNAM 1673 devtprintk((KERN_INFO MYNAM
1398 ": Registered for IOC event notifications\n")); 1674 ": Registered for IOC event notifications\n"));
1399 } 1675 }