aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptsas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/message/fusion/mptsas.c')
-rw-r--r--drivers/message/fusion/mptsas.c196
1 files changed, 161 insertions, 35 deletions
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 2512d0e6155e..74f4368c79ab 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -117,6 +117,8 @@ struct mptsas_hotplug_event {
117struct mptsas_devinfo { 117struct mptsas_devinfo {
118 u16 handle; /* unique id to address this device */ 118 u16 handle; /* unique id to address this device */
119 u16 handle_parent; /* unique id to address parent device */ 119 u16 handle_parent; /* unique id to address parent device */
120 u16 handle_enclosure; /* enclosure identifier of the enclosure */
121 u16 slot; /* physical slot in enclosure */
120 u8 phy_id; /* phy number of parent device */ 122 u8 phy_id; /* phy number of parent device */
121 u8 port_id; /* sas physical port this device 123 u8 port_id; /* sas physical port this device
122 is assoc'd with */ 124 is assoc'd with */
@@ -146,6 +148,18 @@ struct mptsas_portinfo {
146 struct mptsas_phyinfo *phy_info; 148 struct mptsas_phyinfo *phy_info;
147}; 149};
148 150
151struct mptsas_enclosure {
152 u64 enclosure_logical_id; /* The WWN for the enclosure */
153 u16 enclosure_handle; /* unique id to address this */
154 u16 flags; /* details enclosure management */
155 u16 num_slot; /* num slots */
156 u16 start_slot; /* first slot */
157 u8 start_id; /* starting logical target id */
158 u8 start_channel; /* starting logical channel id */
159 u8 sep_id; /* SEP device logical target id */
160 u8 sep_channel; /* SEP channel logical channel id */
161};
162
149 163
150#ifdef SASDEBUG 164#ifdef SASDEBUG
151static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) 165static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
@@ -205,6 +219,7 @@ static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
205 219
206 printk("---- SAS DEVICE PAGE 0 ---------\n"); 220 printk("---- SAS DEVICE PAGE 0 ---------\n");
207 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle)); 221 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
222 printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle));
208 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle)); 223 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
209 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot)); 224 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
210 printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address)); 225 printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
@@ -243,6 +258,82 @@ static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
243#define mptsas_print_expander_pg1(pg1) do { } while (0) 258#define mptsas_print_expander_pg1(pg1) do { } while (0)
244#endif 259#endif
245 260
261static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
262{
263 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
264 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
265}
266
267static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
268{
269 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
270 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
271}
272
273static int
274mptsas_sas_exclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
275 u32 form, u32 form_specific)
276{
277 ConfigExtendedPageHeader_t hdr;
278 CONFIGPARMS cfg;
279 SasEnclosurePage0_t *buffer;
280 dma_addr_t dma_handle;
281 int error;
282 __le64 le_identifier;
283
284 memset(&hdr, 0, sizeof(hdr));
285 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
286 hdr.PageNumber = 0;
287 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
288 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
289
290 cfg.cfghdr.ehdr = &hdr;
291 cfg.physAddr = -1;
292 cfg.pageAddr = form + form_specific;
293 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
294 cfg.dir = 0; /* read */
295 cfg.timeout = 10;
296
297 error = mpt_config(ioc, &cfg);
298 if (error)
299 goto out;
300 if (!hdr.ExtPageLength) {
301 error = -ENXIO;
302 goto out;
303 }
304
305 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
306 &dma_handle);
307 if (!buffer) {
308 error = -ENOMEM;
309 goto out;
310 }
311
312 cfg.physAddr = dma_handle;
313 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
314
315 error = mpt_config(ioc, &cfg);
316 if (error)
317 goto out_free_consistent;
318
319 /* save config data */
320 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
321 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
322 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
323 enclosure->flags = le16_to_cpu(buffer->Flags);
324 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
325 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
326 enclosure->start_id = buffer->StartTargetID;
327 enclosure->start_channel = buffer->StartBus;
328 enclosure->sep_id = buffer->SEPTargetID;
329 enclosure->sep_channel = buffer->SEPBus;
330
331 out_free_consistent:
332 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
333 buffer, dma_handle);
334 out:
335 return error;
336}
246 337
247/* 338/*
248 * This is pretty ugly. We will be able to seriously clean it up 339 * This is pretty ugly. We will be able to seriously clean it up
@@ -399,12 +490,6 @@ static struct scsi_host_template mptsas_driver_template = {
399 .use_clustering = ENABLE_CLUSTERING, 490 .use_clustering = ENABLE_CLUSTERING,
400}; 491};
401 492
402static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
403{
404 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
405 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
406}
407
408static int mptsas_get_linkerrors(struct sas_phy *phy) 493static int mptsas_get_linkerrors(struct sas_phy *phy)
409{ 494{
410 MPT_ADAPTER *ioc = phy_to_ioc(phy); 495 MPT_ADAPTER *ioc = phy_to_ioc(phy);
@@ -546,8 +631,67 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
546 return error; 631 return error;
547} 632}
548 633
634static int
635mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
636{
637 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
638 int i, error;
639 struct mptsas_portinfo *p;
640 struct mptsas_enclosure enclosure_info;
641 u64 enclosure_handle;
642
643 mutex_lock(&ioc->sas_topology_mutex);
644 list_for_each_entry(p, &ioc->sas_topology, list) {
645 for (i = 0; i < p->num_phys; i++) {
646 if (p->phy_info[i].attached.sas_address ==
647 rphy->identify.sas_address) {
648 enclosure_handle = p->phy_info[i].
649 attached.handle_enclosure;
650 goto found_info;
651 }
652 }
653 }
654 mutex_unlock(&ioc->sas_topology_mutex);
655 return -ENXIO;
656
657 found_info:
658 mutex_unlock(&ioc->sas_topology_mutex);
659 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
660 error = mptsas_sas_exclosure_pg0(ioc, &enclosure_info,
661 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
662 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
663 if (!error)
664 *identifier = enclosure_info.enclosure_logical_id;
665 return error;
666}
667
668static int
669mptsas_get_bay_identifier(struct sas_rphy *rphy)
670{
671 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
672 struct mptsas_portinfo *p;
673 int i, rc;
674
675 mutex_lock(&ioc->sas_topology_mutex);
676 list_for_each_entry(p, &ioc->sas_topology, list) {
677 for (i = 0; i < p->num_phys; i++) {
678 if (p->phy_info[i].attached.sas_address ==
679 rphy->identify.sas_address) {
680 rc = p->phy_info[i].attached.slot;
681 goto out;
682 }
683 }
684 }
685 rc = -ENXIO;
686 out:
687 mutex_unlock(&ioc->sas_topology_mutex);
688 return rc;
689}
690
549static struct sas_function_template mptsas_transport_functions = { 691static struct sas_function_template mptsas_transport_functions = {
550 .get_linkerrors = mptsas_get_linkerrors, 692 .get_linkerrors = mptsas_get_linkerrors,
693 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
694 .get_bay_identifier = mptsas_get_bay_identifier,
551 .phy_reset = mptsas_phy_reset, 695 .phy_reset = mptsas_phy_reset,
552}; 696};
553 697
@@ -739,6 +883,9 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
739 883
740 device_info->handle = le16_to_cpu(buffer->DevHandle); 884 device_info->handle = le16_to_cpu(buffer->DevHandle);
741 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle); 885 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
886 device_info->handle_enclosure =
887 le16_to_cpu(buffer->EnclosureHandle);
888 device_info->slot = le16_to_cpu(buffer->Slot);
742 device_info->phy_id = buffer->PhyNum; 889 device_info->phy_id = buffer->PhyNum;
743 device_info->port_id = buffer->PhysicalPort; 890 device_info->port_id = buffer->PhysicalPort;
744 device_info->id = buffer->TargetID; 891 device_info->id = buffer->TargetID;
@@ -1335,29 +1482,15 @@ mptsas_hotplug_work(void *arg)
1335 case MPTSAS_ADD_DEVICE: 1482 case MPTSAS_ADD_DEVICE:
1336 1483
1337 /* 1484 /*
1338 * When there is no sas address, 1485 * Refresh sas device pg0 data
1339 * RAID volumes are being deleted,
1340 * and hidden phy disk are being added.
1341 * We don't know the SAS data yet,
1342 * so lookup sas device page to get
1343 * pertaining info
1344 */ 1486 */
1345 if (!ev->sas_address) { 1487 if (mptsas_sas_device_pg0(ioc, &sas_device,
1346 if (mptsas_sas_device_pg0(ioc, 1488 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
1347 &sas_device, ev->id, 1489 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id))
1348 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << 1490 break;
1349 MPI_SAS_DEVICE_PGAD_FORM_SHIFT)))
1350 break;
1351 ev->handle = sas_device.handle;
1352 ev->parent_handle = sas_device.handle_parent;
1353 ev->channel = sas_device.channel;
1354 ev->phy_id = sas_device.phy_id;
1355 ev->sas_address = sas_device.sas_address;
1356 ev->device_info = sas_device.device_info;
1357 }
1358 1491
1359 phy_info = mptsas_find_phyinfo_by_parent(ioc, 1492 phy_info = mptsas_find_phyinfo_by_parent(ioc,
1360 ev->parent_handle, ev->phy_id); 1493 sas_device.handle_parent, sas_device.phy_id);
1361 if (!phy_info) { 1494 if (!phy_info) {
1362 printk("mptsas: add event for non-existant PHY.\n"); 1495 printk("mptsas: add event for non-existant PHY.\n");
1363 break; 1496 break;
@@ -1368,14 +1501,8 @@ mptsas_hotplug_work(void *arg)
1368 break; 1501 break;
1369 } 1502 }
1370 1503
1371 /* fill attached info */ 1504 memcpy(&phy_info->attached, &sas_device,
1372 phy_info->attached.handle = ev->handle; 1505 sizeof(struct mptsas_devinfo));
1373 phy_info->attached.phy_id = ev->phy_id;
1374 phy_info->attached.port_id = phy_info->identify.port_id;
1375 phy_info->attached.id = ev->id;
1376 phy_info->attached.channel = ev->channel;
1377 phy_info->attached.sas_address = ev->sas_address;
1378 phy_info->attached.device_info = ev->device_info;
1379 1506
1380 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) 1507 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1381 ds = "ssp"; 1508 ds = "ssp";
@@ -1393,7 +1520,6 @@ mptsas_hotplug_work(void *arg)
1393 if (!rphy) 1520 if (!rphy)
1394 break; /* non-fatal: an rphy can be added later */ 1521 break; /* non-fatal: an rphy can be added later */
1395 1522
1396 rphy->scsi_target_id = phy_info->attached.id;
1397 mptsas_parse_device_info(&rphy->identify, &phy_info->attached); 1523 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1398 if (sas_rphy_add(rphy)) { 1524 if (sas_rphy_add(rphy)) {
1399 sas_rphy_free(rphy); 1525 sas_rphy_free(rphy);