diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_scsih.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 819 |
1 files changed, 559 insertions, 260 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 86ab32d7ab15..55ee014a7e08 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
@@ -76,6 +76,7 @@ static u8 tm_cb_idx = -1; | |||
76 | static u8 ctl_cb_idx = -1; | 76 | static u8 ctl_cb_idx = -1; |
77 | static u8 base_cb_idx = -1; | 77 | static u8 base_cb_idx = -1; |
78 | static u8 transport_cb_idx = -1; | 78 | static u8 transport_cb_idx = -1; |
79 | static u8 scsih_cb_idx = -1; | ||
79 | static u8 config_cb_idx = -1; | 80 | static u8 config_cb_idx = -1; |
80 | static int mpt_ids; | 81 | static int mpt_ids; |
81 | 82 | ||
@@ -196,10 +197,28 @@ static struct pci_device_id scsih_pci_table[] = { | |||
196 | PCI_ANY_ID, PCI_ANY_ID }, | 197 | PCI_ANY_ID, PCI_ANY_ID }, |
197 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3, | 198 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3, |
198 | PCI_ANY_ID, PCI_ANY_ID }, | 199 | PCI_ANY_ID, PCI_ANY_ID }, |
200 | /* Meteor ~ 2116 */ | ||
199 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1, | 201 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1, |
200 | PCI_ANY_ID, PCI_ANY_ID }, | 202 | PCI_ANY_ID, PCI_ANY_ID }, |
201 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2, | 203 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2, |
202 | PCI_ANY_ID, PCI_ANY_ID }, | 204 | PCI_ANY_ID, PCI_ANY_ID }, |
205 | /* Thunderbolt ~ 2208 */ | ||
206 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1, | ||
207 | PCI_ANY_ID, PCI_ANY_ID }, | ||
208 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2, | ||
209 | PCI_ANY_ID, PCI_ANY_ID }, | ||
210 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3, | ||
211 | PCI_ANY_ID, PCI_ANY_ID }, | ||
212 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4, | ||
213 | PCI_ANY_ID, PCI_ANY_ID }, | ||
214 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5, | ||
215 | PCI_ANY_ID, PCI_ANY_ID }, | ||
216 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6, | ||
217 | PCI_ANY_ID, PCI_ANY_ID }, | ||
218 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_7, | ||
219 | PCI_ANY_ID, PCI_ANY_ID }, | ||
220 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_8, | ||
221 | PCI_ANY_ID, PCI_ANY_ID }, | ||
203 | {0} /* Terminating entry */ | 222 | {0} /* Terminating entry */ |
204 | }; | 223 | }; |
205 | MODULE_DEVICE_TABLE(pci, scsih_pci_table); | 224 | MODULE_DEVICE_TABLE(pci, scsih_pci_table); |
@@ -317,6 +336,47 @@ _scsih_is_boot_device(u64 sas_address, u64 device_name, | |||
317 | } | 336 | } |
318 | 337 | ||
319 | /** | 338 | /** |
339 | * _scsih_get_sas_address - set the sas_address for given device handle | ||
340 | * @handle: device handle | ||
341 | * @sas_address: sas address | ||
342 | * | ||
343 | * Returns 0 success, non-zero when failure | ||
344 | */ | ||
345 | static int | ||
346 | _scsih_get_sas_address(struct MPT2SAS_ADAPTER *ioc, u16 handle, | ||
347 | u64 *sas_address) | ||
348 | { | ||
349 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
350 | Mpi2ConfigReply_t mpi_reply; | ||
351 | u32 ioc_status; | ||
352 | |||
353 | if (handle <= ioc->sas_hba.num_phys) { | ||
354 | *sas_address = ioc->sas_hba.sas_address; | ||
355 | return 0; | ||
356 | } else | ||
357 | *sas_address = 0; | ||
358 | |||
359 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | ||
360 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { | ||
361 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
362 | ioc->name, __FILE__, __LINE__, __func__); | ||
363 | return -ENXIO; | ||
364 | } | ||
365 | |||
366 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
367 | MPI2_IOCSTATUS_MASK; | ||
368 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
369 | printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)" | ||
370 | "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status, | ||
371 | __FILE__, __LINE__, __func__); | ||
372 | return -EIO; | ||
373 | } | ||
374 | |||
375 | *sas_address = le64_to_cpu(sas_device_pg0.SASAddress); | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | /** | ||
320 | * _scsih_determine_boot_device - determine boot device. | 380 | * _scsih_determine_boot_device - determine boot device. |
321 | * @ioc: per adapter object | 381 | * @ioc: per adapter object |
322 | * @device: either sas_device or raid_device object | 382 | * @device: either sas_device or raid_device object |
@@ -510,8 +570,6 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc, | |||
510 | struct _sas_device *sas_device) | 570 | struct _sas_device *sas_device) |
511 | { | 571 | { |
512 | unsigned long flags; | 572 | unsigned long flags; |
513 | u16 handle, parent_handle; | ||
514 | u64 sas_address; | ||
515 | 573 | ||
516 | dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle" | 574 | dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle" |
517 | "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, | 575 | "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, |
@@ -521,10 +579,8 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc, | |||
521 | list_add_tail(&sas_device->list, &ioc->sas_device_list); | 579 | list_add_tail(&sas_device->list, &ioc->sas_device_list); |
522 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 580 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
523 | 581 | ||
524 | handle = sas_device->handle; | 582 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, |
525 | parent_handle = sas_device->parent_handle; | 583 | sas_device->sas_address_parent)) |
526 | sas_address = sas_device->sas_address; | ||
527 | if (!mpt2sas_transport_port_add(ioc, handle, parent_handle)) | ||
528 | _scsih_sas_device_remove(ioc, sas_device); | 584 | _scsih_sas_device_remove(ioc, sas_device); |
529 | } | 585 | } |
530 | 586 | ||
@@ -553,31 +609,6 @@ _scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc, | |||
553 | } | 609 | } |
554 | 610 | ||
555 | /** | 611 | /** |
556 | * mpt2sas_scsih_expander_find_by_handle - expander device search | ||
557 | * @ioc: per adapter object | ||
558 | * @handle: expander handle (assigned by firmware) | ||
559 | * Context: Calling function should acquire ioc->sas_device_lock | ||
560 | * | ||
561 | * This searches for expander device based on handle, then returns the | ||
562 | * sas_node object. | ||
563 | */ | ||
564 | struct _sas_node * | ||
565 | mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
566 | { | ||
567 | struct _sas_node *sas_expander, *r; | ||
568 | |||
569 | r = NULL; | ||
570 | list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { | ||
571 | if (sas_expander->handle != handle) | ||
572 | continue; | ||
573 | r = sas_expander; | ||
574 | goto out; | ||
575 | } | ||
576 | out: | ||
577 | return r; | ||
578 | } | ||
579 | |||
580 | /** | ||
581 | * _scsih_raid_device_find_by_id - raid device search | 612 | * _scsih_raid_device_find_by_id - raid device search |
582 | * @ioc: per adapter object | 613 | * @ioc: per adapter object |
583 | * @id: sas device target id | 614 | * @id: sas device target id |
@@ -699,6 +730,31 @@ _scsih_raid_device_remove(struct MPT2SAS_ADAPTER *ioc, | |||
699 | } | 730 | } |
700 | 731 | ||
701 | /** | 732 | /** |
733 | * mpt2sas_scsih_expander_find_by_handle - expander device search | ||
734 | * @ioc: per adapter object | ||
735 | * @handle: expander handle (assigned by firmware) | ||
736 | * Context: Calling function should acquire ioc->sas_device_lock | ||
737 | * | ||
738 | * This searches for expander device based on handle, then returns the | ||
739 | * sas_node object. | ||
740 | */ | ||
741 | struct _sas_node * | ||
742 | mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
743 | { | ||
744 | struct _sas_node *sas_expander, *r; | ||
745 | |||
746 | r = NULL; | ||
747 | list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { | ||
748 | if (sas_expander->handle != handle) | ||
749 | continue; | ||
750 | r = sas_expander; | ||
751 | goto out; | ||
752 | } | ||
753 | out: | ||
754 | return r; | ||
755 | } | ||
756 | |||
757 | /** | ||
702 | * mpt2sas_scsih_expander_find_by_sas_address - expander device search | 758 | * mpt2sas_scsih_expander_find_by_sas_address - expander device search |
703 | * @ioc: per adapter object | 759 | * @ioc: per adapter object |
704 | * @sas_address: sas address | 760 | * @sas_address: sas address |
@@ -1043,17 +1099,46 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc, | |||
1043 | * _scsih_change_queue_depth - setting device queue depth | 1099 | * _scsih_change_queue_depth - setting device queue depth |
1044 | * @sdev: scsi device struct | 1100 | * @sdev: scsi device struct |
1045 | * @qdepth: requested queue depth | 1101 | * @qdepth: requested queue depth |
1102 | * @reason: calling context | ||
1046 | * | 1103 | * |
1047 | * Returns queue depth. | 1104 | * Returns queue depth. |
1048 | */ | 1105 | */ |
1049 | static int | 1106 | static int |
1050 | _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) | 1107 | _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) |
1051 | { | 1108 | { |
1052 | struct Scsi_Host *shost = sdev->host; | 1109 | struct Scsi_Host *shost = sdev->host; |
1053 | int max_depth; | 1110 | int max_depth; |
1054 | int tag_type; | 1111 | int tag_type; |
1112 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
1113 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
1114 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
1115 | struct _sas_device *sas_device; | ||
1116 | unsigned long flags; | ||
1117 | |||
1118 | if (reason != SCSI_QDEPTH_DEFAULT) | ||
1119 | return -EOPNOTSUPP; | ||
1055 | 1120 | ||
1056 | max_depth = shost->can_queue; | 1121 | max_depth = shost->can_queue; |
1122 | |||
1123 | /* limit max device queue for SATA to 32 */ | ||
1124 | sas_device_priv_data = sdev->hostdata; | ||
1125 | if (!sas_device_priv_data) | ||
1126 | goto not_sata; | ||
1127 | sas_target_priv_data = sas_device_priv_data->sas_target; | ||
1128 | if (!sas_target_priv_data) | ||
1129 | goto not_sata; | ||
1130 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) | ||
1131 | goto not_sata; | ||
1132 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
1133 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | ||
1134 | sas_device_priv_data->sas_target->sas_address); | ||
1135 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
1136 | if (sas_device && sas_device->device_info & | ||
1137 | MPI2_SAS_DEVICE_INFO_SATA_DEVICE) | ||
1138 | max_depth = MPT2SAS_SATA_QUEUE_DEPTH; | ||
1139 | |||
1140 | not_sata: | ||
1141 | |||
1057 | if (!sdev->tagged_supported) | 1142 | if (!sdev->tagged_supported) |
1058 | max_depth = 1; | 1143 | max_depth = 1; |
1059 | if (qdepth > max_depth) | 1144 | if (qdepth > max_depth) |
@@ -1488,7 +1573,7 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
1488 | r_level, raid_device->handle, | 1573 | r_level, raid_device->handle, |
1489 | (unsigned long long)raid_device->wwid, | 1574 | (unsigned long long)raid_device->wwid, |
1490 | raid_device->num_pds, ds); | 1575 | raid_device->num_pds, ds); |
1491 | _scsih_change_queue_depth(sdev, qdepth); | 1576 | _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); |
1492 | return 0; | 1577 | return 0; |
1493 | } | 1578 | } |
1494 | 1579 | ||
@@ -1534,7 +1619,7 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
1534 | _scsih_display_sata_capabilities(ioc, sas_device, sdev); | 1619 | _scsih_display_sata_capabilities(ioc, sas_device, sdev); |
1535 | } | 1620 | } |
1536 | 1621 | ||
1537 | _scsih_change_queue_depth(sdev, qdepth); | 1622 | _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); |
1538 | 1623 | ||
1539 | if (ssp_target) | 1624 | if (ssp_target) |
1540 | sas_read_port_mode_page(sdev); | 1625 | sas_read_port_mode_page(sdev); |
@@ -1874,6 +1959,8 @@ _scsih_abort(struct scsi_cmnd *scmd) | |||
1874 | goto out; | 1959 | goto out; |
1875 | } | 1960 | } |
1876 | 1961 | ||
1962 | mpt2sas_halt_firmware(ioc); | ||
1963 | |||
1877 | mutex_lock(&ioc->tm_cmds.mutex); | 1964 | mutex_lock(&ioc->tm_cmds.mutex); |
1878 | handle = sas_device_priv_data->sas_target->handle; | 1965 | handle = sas_device_priv_data->sas_target->handle; |
1879 | mpt2sas_scsih_issue_tm(ioc, handle, sas_device_priv_data->lun, | 1966 | mpt2sas_scsih_issue_tm(ioc, handle, sas_device_priv_data->lun, |
@@ -2297,7 +2384,6 @@ _scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc, | |||
2297 | u16 handle; | 2384 | u16 handle; |
2298 | u16 reason_code; | 2385 | u16 reason_code; |
2299 | u8 phy_number; | 2386 | u8 phy_number; |
2300 | u8 link_rate; | ||
2301 | 2387 | ||
2302 | for (i = 0; i < event_data->NumEntries; i++) { | 2388 | for (i = 0; i < event_data->NumEntries; i++) { |
2303 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); | 2389 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); |
@@ -2308,11 +2394,6 @@ _scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc, | |||
2308 | MPI2_EVENT_SAS_TOPO_RC_MASK; | 2394 | MPI2_EVENT_SAS_TOPO_RC_MASK; |
2309 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING) | 2395 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING) |
2310 | _scsih_block_io_device(ioc, handle); | 2396 | _scsih_block_io_device(ioc, handle); |
2311 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED) { | ||
2312 | link_rate = event_data->PHY[i].LinkRate >> 4; | ||
2313 | if (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5) | ||
2314 | _scsih_ublock_io_device(ioc, handle); | ||
2315 | } | ||
2316 | } | 2397 | } |
2317 | } | 2398 | } |
2318 | 2399 | ||
@@ -2349,16 +2430,10 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
2349 | 2430 | ||
2350 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2431 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
2351 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 2432 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); |
2352 | if (!sas_device) { | ||
2353 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2354 | printk(MPT2SAS_ERR_FMT "%s: failed finding sas_device\n", | ||
2355 | ioc->name, __func__); | ||
2356 | return; | ||
2357 | } | ||
2358 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 2433 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
2359 | 2434 | ||
2360 | /* skip is hidden raid component */ | 2435 | /* skip is hidden raid component */ |
2361 | if (sas_device->hidden_raid_component) | 2436 | if (sas_device && sas_device->hidden_raid_component) |
2362 | return; | 2437 | return; |
2363 | 2438 | ||
2364 | smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx); | 2439 | smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx); |
@@ -2371,18 +2446,31 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
2371 | delayed_tr->state = MPT2SAS_REQ_SAS_CNTRL; | 2446 | delayed_tr->state = MPT2SAS_REQ_SAS_CNTRL; |
2372 | list_add_tail(&delayed_tr->list, | 2447 | list_add_tail(&delayed_tr->list, |
2373 | &ioc->delayed_tr_list); | 2448 | &ioc->delayed_tr_list); |
2374 | if (sas_device->starget) | 2449 | if (sas_device && sas_device->starget) { |
2375 | dewtprintk(ioc, starget_printk(KERN_INFO, | 2450 | dewtprintk(ioc, starget_printk(KERN_INFO, |
2376 | sas_device->starget, "DELAYED:tr:handle(0x%04x), " | 2451 | sas_device->starget, "DELAYED:tr:handle(0x%04x), " |
2377 | "(open)\n", sas_device->handle)); | 2452 | "(open)\n", handle)); |
2453 | } else { | ||
2454 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
2455 | "DELAYED:tr:handle(0x%04x), (open)\n", | ||
2456 | ioc->name, handle)); | ||
2457 | } | ||
2378 | return; | 2458 | return; |
2379 | } | 2459 | } |
2380 | 2460 | ||
2381 | if (sas_device->starget && sas_device->starget->hostdata) { | 2461 | if (sas_device) { |
2382 | sas_target_priv_data = sas_device->starget->hostdata; | 2462 | sas_device->state |= MPTSAS_STATE_TR_SEND; |
2383 | sas_target_priv_data->tm_busy = 1; | 2463 | sas_device->state |= MPT2SAS_REQ_SAS_CNTRL; |
2384 | dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget, | 2464 | if (sas_device->starget && sas_device->starget->hostdata) { |
2385 | "tr:handle(0x%04x), (open)\n", sas_device->handle)); | 2465 | sas_target_priv_data = sas_device->starget->hostdata; |
2466 | sas_target_priv_data->tm_busy = 1; | ||
2467 | dewtprintk(ioc, starget_printk(KERN_INFO, | ||
2468 | sas_device->starget, "tr:handle(0x%04x), (open)\n", | ||
2469 | handle)); | ||
2470 | } | ||
2471 | } else { | ||
2472 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
2473 | "tr:handle(0x%04x), (open)\n", ioc->name, handle)); | ||
2386 | } | 2474 | } |
2387 | 2475 | ||
2388 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | 2476 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); |
@@ -2390,8 +2478,6 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
2390 | mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; | 2478 | mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; |
2391 | mpi_request->DevHandle = cpu_to_le16(handle); | 2479 | mpi_request->DevHandle = cpu_to_le16(handle); |
2392 | mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; | 2480 | mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; |
2393 | sas_device->state |= MPTSAS_STATE_TR_SEND; | ||
2394 | sas_device->state |= MPT2SAS_REQ_SAS_CNTRL; | ||
2395 | mpt2sas_base_put_smid_hi_priority(ioc, smid); | 2481 | mpt2sas_base_put_smid_hi_priority(ioc, smid); |
2396 | } | 2482 | } |
2397 | 2483 | ||
@@ -2426,21 +2512,25 @@ _scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, | |||
2426 | 2512 | ||
2427 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2513 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
2428 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 2514 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); |
2429 | if (!sas_device) { | ||
2430 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2431 | printk(MPT2SAS_ERR_FMT "%s: failed finding sas_device\n", | ||
2432 | ioc->name, __func__); | ||
2433 | return 1; | ||
2434 | } | ||
2435 | sas_device->state |= MPTSAS_STATE_CNTRL_COMPLETE; | ||
2436 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 2515 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
2437 | 2516 | ||
2438 | if (sas_device->starget) | 2517 | if (sas_device) { |
2439 | dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget, | 2518 | sas_device->state |= MPTSAS_STATE_CNTRL_COMPLETE; |
2519 | if (sas_device->starget) | ||
2520 | dewtprintk(ioc, starget_printk(KERN_INFO, | ||
2521 | sas_device->starget, | ||
2522 | "sc_complete:handle(0x%04x), " | ||
2523 | "ioc_status(0x%04x), loginfo(0x%08x)\n", | ||
2524 | handle, le16_to_cpu(mpi_reply->IOCStatus), | ||
2525 | le32_to_cpu(mpi_reply->IOCLogInfo))); | ||
2526 | } else { | ||
2527 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
2440 | "sc_complete:handle(0x%04x), " | 2528 | "sc_complete:handle(0x%04x), " |
2441 | "ioc_status(0x%04x), loginfo(0x%08x)\n", | 2529 | "ioc_status(0x%04x), loginfo(0x%08x)\n", |
2442 | handle, le16_to_cpu(mpi_reply->IOCStatus), | 2530 | ioc->name, handle, le16_to_cpu(mpi_reply->IOCStatus), |
2443 | le32_to_cpu(mpi_reply->IOCLogInfo))); | 2531 | le32_to_cpu(mpi_reply->IOCLogInfo))); |
2532 | } | ||
2533 | |||
2444 | return 1; | 2534 | return 1; |
2445 | } | 2535 | } |
2446 | 2536 | ||
@@ -2478,28 +2568,33 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
2478 | handle = le16_to_cpu(mpi_reply->DevHandle); | 2568 | handle = le16_to_cpu(mpi_reply->DevHandle); |
2479 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2569 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
2480 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 2570 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); |
2481 | if (!sas_device) { | ||
2482 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2483 | printk(MPT2SAS_ERR_FMT "%s: failed finding sas_device\n", | ||
2484 | ioc->name, __func__); | ||
2485 | return 1; | ||
2486 | } | ||
2487 | sas_device->state |= MPTSAS_STATE_TR_COMPLETE; | ||
2488 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 2571 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
2489 | 2572 | ||
2490 | if (sas_device->starget) | 2573 | if (sas_device) { |
2491 | dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget, | 2574 | sas_device->state |= MPTSAS_STATE_TR_COMPLETE; |
2492 | "tr_complete:handle(0x%04x), (%s) ioc_status(0x%04x), " | 2575 | if (sas_device->starget) { |
2493 | "loginfo(0x%08x), completed(%d)\n", | 2576 | dewtprintk(ioc, starget_printk(KERN_INFO, |
2494 | sas_device->handle, (sas_device->state & | 2577 | sas_device->starget, "tr_complete:handle(0x%04x), " |
2495 | MPT2SAS_REQ_SAS_CNTRL) ? "open" : "active", | 2578 | "(%s) ioc_status(0x%04x), loginfo(0x%08x), " |
2496 | le16_to_cpu(mpi_reply->IOCStatus), | 2579 | "completed(%d)\n", sas_device->handle, |
2580 | (sas_device->state & MPT2SAS_REQ_SAS_CNTRL) ? | ||
2581 | "open" : "active", | ||
2582 | le16_to_cpu(mpi_reply->IOCStatus), | ||
2583 | le32_to_cpu(mpi_reply->IOCLogInfo), | ||
2584 | le32_to_cpu(mpi_reply->TerminationCount))); | ||
2585 | if (sas_device->starget->hostdata) { | ||
2586 | sas_target_priv_data = | ||
2587 | sas_device->starget->hostdata; | ||
2588 | sas_target_priv_data->tm_busy = 0; | ||
2589 | } | ||
2590 | } | ||
2591 | } else { | ||
2592 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
2593 | "tr_complete:handle(0x%04x), (open) ioc_status(0x%04x), " | ||
2594 | "loginfo(0x%08x), completed(%d)\n", ioc->name, | ||
2595 | handle, le16_to_cpu(mpi_reply->IOCStatus), | ||
2497 | le32_to_cpu(mpi_reply->IOCLogInfo), | 2596 | le32_to_cpu(mpi_reply->IOCLogInfo), |
2498 | le32_to_cpu(mpi_reply->TerminationCount))); | 2597 | le32_to_cpu(mpi_reply->TerminationCount))); |
2499 | |||
2500 | if (sas_device->starget && sas_device->starget->hostdata) { | ||
2501 | sas_target_priv_data = sas_device->starget->hostdata; | ||
2502 | sas_target_priv_data->tm_busy = 0; | ||
2503 | } | 2598 | } |
2504 | 2599 | ||
2505 | if (!list_empty(&ioc->delayed_tr_list)) { | 2600 | if (!list_empty(&ioc->delayed_tr_list)) { |
@@ -2514,8 +2609,7 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
2514 | } else | 2609 | } else |
2515 | rc = 1; | 2610 | rc = 1; |
2516 | 2611 | ||
2517 | 2612 | if (sas_device && !(sas_device->state & MPT2SAS_REQ_SAS_CNTRL)) | |
2518 | if (!(sas_device->state & MPT2SAS_REQ_SAS_CNTRL)) | ||
2519 | return rc; | 2613 | return rc; |
2520 | 2614 | ||
2521 | if (ioc->shost_recovery) { | 2615 | if (ioc->shost_recovery) { |
@@ -2531,12 +2625,14 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
2531 | return rc; | 2625 | return rc; |
2532 | } | 2626 | } |
2533 | 2627 | ||
2628 | if (sas_device) | ||
2629 | sas_device->state |= MPTSAS_STATE_CNTRL_SEND; | ||
2630 | |||
2534 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid_sas_ctrl); | 2631 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid_sas_ctrl); |
2535 | memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t)); | 2632 | memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t)); |
2536 | mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; | 2633 | mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; |
2537 | mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE; | 2634 | mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE; |
2538 | mpi_request->DevHandle = mpi_reply->DevHandle; | 2635 | mpi_request->DevHandle = mpi_reply->DevHandle; |
2539 | sas_device->state |= MPTSAS_STATE_CNTRL_SEND; | ||
2540 | mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl); | 2636 | mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl); |
2541 | return rc; | 2637 | return rc; |
2542 | } | 2638 | } |
@@ -2678,8 +2774,6 @@ _scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request) | |||
2678 | else | 2774 | else |
2679 | return; | 2775 | return; |
2680 | 2776 | ||
2681 | mpi_request->EEDPBlockSize = scmd->device->sector_size; | ||
2682 | |||
2683 | switch (prot_type) { | 2777 | switch (prot_type) { |
2684 | case SCSI_PROT_DIF_TYPE1: | 2778 | case SCSI_PROT_DIF_TYPE1: |
2685 | 2779 | ||
@@ -2687,8 +2781,7 @@ _scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request) | |||
2687 | * enable ref/guard checking | 2781 | * enable ref/guard checking |
2688 | * auto increment ref tag | 2782 | * auto increment ref tag |
2689 | */ | 2783 | */ |
2690 | mpi_request->EEDPFlags = eedp_flags | | 2784 | eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | |
2691 | MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | | ||
2692 | MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | | 2785 | MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | |
2693 | MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; | 2786 | MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; |
2694 | mpi_request->CDB.EEDP32.PrimaryReferenceTag = | 2787 | mpi_request->CDB.EEDP32.PrimaryReferenceTag = |
@@ -2701,11 +2794,11 @@ _scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request) | |||
2701 | /* | 2794 | /* |
2702 | * enable guard checking | 2795 | * enable guard checking |
2703 | */ | 2796 | */ |
2704 | mpi_request->EEDPFlags = eedp_flags | | 2797 | eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; |
2705 | MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; | ||
2706 | |||
2707 | break; | 2798 | break; |
2708 | } | 2799 | } |
2800 | mpi_request->EEDPBlockSize = cpu_to_le32(scmd->device->sector_size); | ||
2801 | mpi_request->EEDPFlags = cpu_to_le16(eedp_flags); | ||
2709 | } | 2802 | } |
2710 | 2803 | ||
2711 | /** | 2804 | /** |
@@ -2788,7 +2881,7 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) | |||
2788 | } | 2881 | } |
2789 | 2882 | ||
2790 | /* see if we are busy with task managment stuff */ | 2883 | /* see if we are busy with task managment stuff */ |
2791 | if (sas_target_priv_data->tm_busy) | 2884 | if (sas_device_priv_data->block || sas_target_priv_data->tm_busy) |
2792 | return SCSI_MLQUEUE_DEVICE_BUSY; | 2885 | return SCSI_MLQUEUE_DEVICE_BUSY; |
2793 | else if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress) | 2886 | else if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress) |
2794 | return SCSI_MLQUEUE_HOST_BUSY; | 2887 | return SCSI_MLQUEUE_HOST_BUSY; |
@@ -2842,7 +2935,7 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) | |||
2842 | mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR; | 2935 | mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR; |
2843 | mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; | 2936 | mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; |
2844 | mpi_request->SenseBufferLowAddress = | 2937 | mpi_request->SenseBufferLowAddress = |
2845 | (u32)mpt2sas_base_get_sense_buffer_dma(ioc, smid); | 2938 | mpt2sas_base_get_sense_buffer_dma(ioc, smid); |
2846 | mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4; | 2939 | mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4; |
2847 | mpi_request->SGLFlags = cpu_to_le16(MPI2_SCSIIO_SGLFLAGS_TYPE_MPI + | 2940 | mpi_request->SGLFlags = cpu_to_le16(MPI2_SCSIIO_SGLFLAGS_TYPE_MPI + |
2848 | MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR); | 2941 | MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR); |
@@ -3059,7 +3152,7 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
3059 | if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { | 3152 | if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { |
3060 | response_info = le32_to_cpu(mpi_reply->ResponseInfo); | 3153 | response_info = le32_to_cpu(mpi_reply->ResponseInfo); |
3061 | response_bytes = (u8 *)&response_info; | 3154 | response_bytes = (u8 *)&response_info; |
3062 | _scsih_response_code(ioc, response_bytes[3]); | 3155 | _scsih_response_code(ioc, response_bytes[0]); |
3063 | } | 3156 | } |
3064 | } | 3157 | } |
3065 | #endif | 3158 | #endif |
@@ -3177,7 +3270,7 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
3177 | u8 scsi_status; | 3270 | u8 scsi_status; |
3178 | u32 log_info; | 3271 | u32 log_info; |
3179 | struct MPT2SAS_DEVICE *sas_device_priv_data; | 3272 | struct MPT2SAS_DEVICE *sas_device_priv_data; |
3180 | u32 response_code; | 3273 | u32 response_code = 0; |
3181 | 3274 | ||
3182 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 3275 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
3183 | scmd = _scsih_scsi_lookup_get(ioc, smid); | 3276 | scmd = _scsih_scsi_lookup_get(ioc, smid); |
@@ -3199,16 +3292,16 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
3199 | } | 3292 | } |
3200 | 3293 | ||
3201 | /* turning off TLR */ | 3294 | /* turning off TLR */ |
3295 | scsi_state = mpi_reply->SCSIState; | ||
3296 | if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) | ||
3297 | response_code = | ||
3298 | le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF; | ||
3202 | if (!sas_device_priv_data->tlr_snoop_check) { | 3299 | if (!sas_device_priv_data->tlr_snoop_check) { |
3203 | sas_device_priv_data->tlr_snoop_check++; | 3300 | sas_device_priv_data->tlr_snoop_check++; |
3204 | if (sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) { | 3301 | if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) && |
3205 | response_code = (le32_to_cpu(mpi_reply->ResponseInfo) | 3302 | response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) |
3206 | >> 24); | 3303 | sas_device_priv_data->flags &= |
3207 | if (response_code == | 3304 | ~MPT_DEVICE_TLR_ON; |
3208 | MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) | ||
3209 | sas_device_priv_data->flags &= | ||
3210 | ~MPT_DEVICE_TLR_ON; | ||
3211 | } | ||
3212 | } | 3305 | } |
3213 | 3306 | ||
3214 | xfer_cnt = le32_to_cpu(mpi_reply->TransferCount); | 3307 | xfer_cnt = le32_to_cpu(mpi_reply->TransferCount); |
@@ -3219,7 +3312,6 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
3219 | else | 3312 | else |
3220 | log_info = 0; | 3313 | log_info = 0; |
3221 | ioc_status &= MPI2_IOCSTATUS_MASK; | 3314 | ioc_status &= MPI2_IOCSTATUS_MASK; |
3222 | scsi_state = mpi_reply->SCSIState; | ||
3223 | scsi_status = mpi_reply->SCSIStatus; | 3315 | scsi_status = mpi_reply->SCSIStatus; |
3224 | 3316 | ||
3225 | if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 && | 3317 | if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 && |
@@ -3255,10 +3347,9 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
3255 | 3347 | ||
3256 | case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: | 3348 | case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: |
3257 | if (sas_device_priv_data->block) { | 3349 | if (sas_device_priv_data->block) { |
3258 | scmd->result = (DID_BUS_BUSY << 16); | 3350 | scmd->result = DID_TRANSPORT_DISRUPTED << 16; |
3259 | break; | 3351 | goto out; |
3260 | } | 3352 | } |
3261 | |||
3262 | case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: | 3353 | case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: |
3263 | case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: | 3354 | case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: |
3264 | scmd->result = DID_RESET << 16; | 3355 | scmd->result = DID_RESET << 16; |
@@ -3304,8 +3395,10 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
3304 | case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: | 3395 | case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: |
3305 | case MPI2_IOCSTATUS_SUCCESS: | 3396 | case MPI2_IOCSTATUS_SUCCESS: |
3306 | scmd->result = (DID_OK << 16) | scsi_status; | 3397 | scmd->result = (DID_OK << 16) | scsi_status; |
3307 | if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED | | 3398 | if (response_code == |
3308 | MPI2_SCSI_STATE_NO_SCSI_STATUS)) | 3399 | MPI2_SCSITASKMGMT_RSP_INVALID_FRAME || |
3400 | (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED | | ||
3401 | MPI2_SCSI_STATE_NO_SCSI_STATUS))) | ||
3309 | scmd->result = DID_SOFT_ERROR << 16; | 3402 | scmd->result = DID_SOFT_ERROR << 16; |
3310 | else if (scsi_state & MPI2_SCSI_STATE_TERMINATED) | 3403 | else if (scsi_state & MPI2_SCSI_STATE_TERMINATED) |
3311 | scmd->result = DID_RESET << 16; | 3404 | scmd->result = DID_RESET << 16; |
@@ -3344,7 +3437,6 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
3344 | /** | 3437 | /** |
3345 | * _scsih_sas_host_refresh - refreshing sas host object contents | 3438 | * _scsih_sas_host_refresh - refreshing sas host object contents |
3346 | * @ioc: per adapter object | 3439 | * @ioc: per adapter object |
3347 | * @update: update link information | ||
3348 | * Context: user | 3440 | * Context: user |
3349 | * | 3441 | * |
3350 | * During port enable, fw will send topology events for every device. Its | 3442 | * During port enable, fw will send topology events for every device. Its |
@@ -3354,13 +3446,14 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
3354 | * Return nothing. | 3446 | * Return nothing. |
3355 | */ | 3447 | */ |
3356 | static void | 3448 | static void |
3357 | _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc, u8 update) | 3449 | _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc) |
3358 | { | 3450 | { |
3359 | u16 sz; | 3451 | u16 sz; |
3360 | u16 ioc_status; | 3452 | u16 ioc_status; |
3361 | int i; | 3453 | int i; |
3362 | Mpi2ConfigReply_t mpi_reply; | 3454 | Mpi2ConfigReply_t mpi_reply; |
3363 | Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; | 3455 | Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; |
3456 | u16 attached_handle; | ||
3364 | 3457 | ||
3365 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT | 3458 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT |
3366 | "updating handles for sas_host(0x%016llx)\n", | 3459 | "updating handles for sas_host(0x%016llx)\n", |
@@ -3374,27 +3467,24 @@ _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc, u8 update) | |||
3374 | ioc->name, __FILE__, __LINE__, __func__); | 3467 | ioc->name, __FILE__, __LINE__, __func__); |
3375 | return; | 3468 | return; |
3376 | } | 3469 | } |
3377 | if (!(mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, | ||
3378 | sas_iounit_pg0, sz))) { | ||
3379 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
3380 | MPI2_IOCSTATUS_MASK; | ||
3381 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | ||
3382 | goto out; | ||
3383 | for (i = 0; i < ioc->sas_hba.num_phys ; i++) { | ||
3384 | ioc->sas_hba.phy[i].handle = | ||
3385 | le16_to_cpu(sas_iounit_pg0->PhyData[i]. | ||
3386 | ControllerDevHandle); | ||
3387 | if (update) | ||
3388 | mpt2sas_transport_update_links( | ||
3389 | ioc, | ||
3390 | ioc->sas_hba.phy[i].handle, | ||
3391 | le16_to_cpu(sas_iounit_pg0->PhyData[i]. | ||
3392 | AttachedDevHandle), i, | ||
3393 | sas_iounit_pg0->PhyData[i]. | ||
3394 | NegotiatedLinkRate >> 4); | ||
3395 | } | ||
3396 | } | ||
3397 | 3470 | ||
3471 | if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, | ||
3472 | sas_iounit_pg0, sz)) != 0) | ||
3473 | goto out; | ||
3474 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
3475 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | ||
3476 | goto out; | ||
3477 | for (i = 0; i < ioc->sas_hba.num_phys ; i++) { | ||
3478 | if (i == 0) | ||
3479 | ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> | ||
3480 | PhyData[0].ControllerDevHandle); | ||
3481 | ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; | ||
3482 | attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i]. | ||
3483 | AttachedDevHandle); | ||
3484 | mpt2sas_transport_update_links(ioc, ioc->sas_hba.sas_address, | ||
3485 | attached_handle, i, sas_iounit_pg0->PhyData[i]. | ||
3486 | NegotiatedLinkRate >> 4); | ||
3487 | } | ||
3398 | out: | 3488 | out: |
3399 | kfree(sas_iounit_pg0); | 3489 | kfree(sas_iounit_pg0); |
3400 | } | 3490 | } |
@@ -3507,19 +3597,21 @@ _scsih_sas_host_add(struct MPT2SAS_ADAPTER *ioc) | |||
3507 | ioc->name, __FILE__, __LINE__, __func__); | 3597 | ioc->name, __FILE__, __LINE__, __func__); |
3508 | goto out; | 3598 | goto out; |
3509 | } | 3599 | } |
3510 | ioc->sas_hba.phy[i].handle = | 3600 | |
3511 | le16_to_cpu(sas_iounit_pg0->PhyData[i].ControllerDevHandle); | 3601 | if (i == 0) |
3602 | ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> | ||
3603 | PhyData[0].ControllerDevHandle); | ||
3604 | ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; | ||
3512 | ioc->sas_hba.phy[i].phy_id = i; | 3605 | ioc->sas_hba.phy[i].phy_id = i; |
3513 | mpt2sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i], | 3606 | mpt2sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i], |
3514 | phy_pg0, ioc->sas_hba.parent_dev); | 3607 | phy_pg0, ioc->sas_hba.parent_dev); |
3515 | } | 3608 | } |
3516 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | 3609 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, |
3517 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.phy[0].handle))) { | 3610 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) { |
3518 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 3611 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
3519 | ioc->name, __FILE__, __LINE__, __func__); | 3612 | ioc->name, __FILE__, __LINE__, __func__); |
3520 | goto out; | 3613 | goto out; |
3521 | } | 3614 | } |
3522 | ioc->sas_hba.handle = le16_to_cpu(sas_device_pg0.DevHandle); | ||
3523 | ioc->sas_hba.enclosure_handle = | 3615 | ioc->sas_hba.enclosure_handle = |
3524 | le16_to_cpu(sas_device_pg0.EnclosureHandle); | 3616 | le16_to_cpu(sas_device_pg0.EnclosureHandle); |
3525 | ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress); | 3617 | ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress); |
@@ -3562,7 +3654,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3562 | Mpi2SasEnclosurePage0_t enclosure_pg0; | 3654 | Mpi2SasEnclosurePage0_t enclosure_pg0; |
3563 | u32 ioc_status; | 3655 | u32 ioc_status; |
3564 | u16 parent_handle; | 3656 | u16 parent_handle; |
3565 | __le64 sas_address; | 3657 | __le64 sas_address, sas_address_parent = 0; |
3566 | int i; | 3658 | int i; |
3567 | unsigned long flags; | 3659 | unsigned long flags; |
3568 | struct _sas_port *mpt2sas_port = NULL; | 3660 | struct _sas_port *mpt2sas_port = NULL; |
@@ -3591,10 +3683,16 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3591 | 3683 | ||
3592 | /* handle out of order topology events */ | 3684 | /* handle out of order topology events */ |
3593 | parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle); | 3685 | parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle); |
3594 | if (parent_handle >= ioc->sas_hba.num_phys) { | 3686 | if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent) |
3687 | != 0) { | ||
3688 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
3689 | ioc->name, __FILE__, __LINE__, __func__); | ||
3690 | return -1; | ||
3691 | } | ||
3692 | if (sas_address_parent != ioc->sas_hba.sas_address) { | ||
3595 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | 3693 | spin_lock_irqsave(&ioc->sas_node_lock, flags); |
3596 | sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, | 3694 | sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, |
3597 | parent_handle); | 3695 | sas_address_parent); |
3598 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | 3696 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); |
3599 | if (!sas_expander) { | 3697 | if (!sas_expander) { |
3600 | rc = _scsih_expander_add(ioc, parent_handle); | 3698 | rc = _scsih_expander_add(ioc, parent_handle); |
@@ -3622,14 +3720,12 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3622 | 3720 | ||
3623 | sas_expander->handle = handle; | 3721 | sas_expander->handle = handle; |
3624 | sas_expander->num_phys = expander_pg0.NumPhys; | 3722 | sas_expander->num_phys = expander_pg0.NumPhys; |
3625 | sas_expander->parent_handle = parent_handle; | 3723 | sas_expander->sas_address_parent = sas_address_parent; |
3626 | sas_expander->enclosure_handle = | ||
3627 | le16_to_cpu(expander_pg0.EnclosureHandle); | ||
3628 | sas_expander->sas_address = sas_address; | 3724 | sas_expander->sas_address = sas_address; |
3629 | 3725 | ||
3630 | printk(MPT2SAS_INFO_FMT "expander_add: handle(0x%04x)," | 3726 | printk(MPT2SAS_INFO_FMT "expander_add: handle(0x%04x)," |
3631 | " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name, | 3727 | " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name, |
3632 | handle, sas_expander->parent_handle, (unsigned long long) | 3728 | handle, parent_handle, (unsigned long long) |
3633 | sas_expander->sas_address, sas_expander->num_phys); | 3729 | sas_expander->sas_address, sas_expander->num_phys); |
3634 | 3730 | ||
3635 | if (!sas_expander->num_phys) | 3731 | if (!sas_expander->num_phys) |
@@ -3645,7 +3741,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3645 | 3741 | ||
3646 | INIT_LIST_HEAD(&sas_expander->sas_port_list); | 3742 | INIT_LIST_HEAD(&sas_expander->sas_port_list); |
3647 | mpt2sas_port = mpt2sas_transport_port_add(ioc, handle, | 3743 | mpt2sas_port = mpt2sas_transport_port_add(ioc, handle, |
3648 | sas_expander->parent_handle); | 3744 | sas_address_parent); |
3649 | if (!mpt2sas_port) { | 3745 | if (!mpt2sas_port) { |
3650 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 3746 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
3651 | ioc->name, __FILE__, __LINE__, __func__); | 3747 | ioc->name, __FILE__, __LINE__, __func__); |
@@ -3691,20 +3787,54 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3691 | 3787 | ||
3692 | if (mpt2sas_port) | 3788 | if (mpt2sas_port) |
3693 | mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, | 3789 | mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, |
3694 | sas_expander->parent_handle); | 3790 | sas_address_parent); |
3695 | kfree(sas_expander); | 3791 | kfree(sas_expander); |
3696 | return rc; | 3792 | return rc; |
3697 | } | 3793 | } |
3698 | 3794 | ||
3699 | /** | 3795 | /** |
3796 | * _scsih_done - scsih callback handler. | ||
3797 | * @ioc: per adapter object | ||
3798 | * @smid: system request message index | ||
3799 | * @msix_index: MSIX table index supplied by the OS | ||
3800 | * @reply: reply message frame(lower 32bit addr) | ||
3801 | * | ||
3802 | * Callback handler when sending internal generated message frames. | ||
3803 | * The callback index passed is `ioc->scsih_cb_idx` | ||
3804 | * | ||
3805 | * Return 1 meaning mf should be freed from _base_interrupt | ||
3806 | * 0 means the mf is freed from this function. | ||
3807 | */ | ||
3808 | static u8 | ||
3809 | _scsih_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | ||
3810 | { | ||
3811 | MPI2DefaultReply_t *mpi_reply; | ||
3812 | |||
3813 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
3814 | if (ioc->scsih_cmds.status == MPT2_CMD_NOT_USED) | ||
3815 | return 1; | ||
3816 | if (ioc->scsih_cmds.smid != smid) | ||
3817 | return 1; | ||
3818 | ioc->scsih_cmds.status |= MPT2_CMD_COMPLETE; | ||
3819 | if (mpi_reply) { | ||
3820 | memcpy(ioc->scsih_cmds.reply, mpi_reply, | ||
3821 | mpi_reply->MsgLength*4); | ||
3822 | ioc->scsih_cmds.status |= MPT2_CMD_REPLY_VALID; | ||
3823 | } | ||
3824 | ioc->scsih_cmds.status &= ~MPT2_CMD_PENDING; | ||
3825 | complete(&ioc->scsih_cmds.done); | ||
3826 | return 1; | ||
3827 | } | ||
3828 | |||
3829 | /** | ||
3700 | * _scsih_expander_remove - removing expander object | 3830 | * _scsih_expander_remove - removing expander object |
3701 | * @ioc: per adapter object | 3831 | * @ioc: per adapter object |
3702 | * @handle: expander handle | 3832 | * @sas_address: expander sas_address |
3703 | * | 3833 | * |
3704 | * Return nothing. | 3834 | * Return nothing. |
3705 | */ | 3835 | */ |
3706 | static void | 3836 | static void |
3707 | _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u16 handle) | 3837 | _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address) |
3708 | { | 3838 | { |
3709 | struct _sas_node *sas_expander; | 3839 | struct _sas_node *sas_expander; |
3710 | unsigned long flags; | 3840 | unsigned long flags; |
@@ -3713,7 +3843,8 @@ _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3713 | return; | 3843 | return; |
3714 | 3844 | ||
3715 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | 3845 | spin_lock_irqsave(&ioc->sas_node_lock, flags); |
3716 | sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, handle); | 3846 | sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, |
3847 | sas_address); | ||
3717 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | 3848 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); |
3718 | _scsih_expander_node_remove(ioc, sas_expander); | 3849 | _scsih_expander_node_remove(ioc, sas_expander); |
3719 | } | 3850 | } |
@@ -3805,8 +3936,11 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
3805 | } | 3936 | } |
3806 | 3937 | ||
3807 | sas_device->handle = handle; | 3938 | sas_device->handle = handle; |
3808 | sas_device->parent_handle = | 3939 | if (_scsih_get_sas_address(ioc, le16_to_cpu |
3809 | le16_to_cpu(sas_device_pg0.ParentDevHandle); | 3940 | (sas_device_pg0.ParentDevHandle), |
3941 | &sas_device->sas_address_parent) != 0) | ||
3942 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
3943 | ioc->name, __FILE__, __LINE__, __func__); | ||
3810 | sas_device->enclosure_handle = | 3944 | sas_device->enclosure_handle = |
3811 | le16_to_cpu(sas_device_pg0.EnclosureHandle); | 3945 | le16_to_cpu(sas_device_pg0.EnclosureHandle); |
3812 | sas_device->slot = | 3946 | sas_device->slot = |
@@ -3836,43 +3970,39 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
3836 | /** | 3970 | /** |
3837 | * _scsih_remove_device - removing sas device object | 3971 | * _scsih_remove_device - removing sas device object |
3838 | * @ioc: per adapter object | 3972 | * @ioc: per adapter object |
3839 | * @handle: sas device handle | 3973 | * @sas_device: the sas_device object |
3840 | * | 3974 | * |
3841 | * Return nothing. | 3975 | * Return nothing. |
3842 | */ | 3976 | */ |
3843 | static void | 3977 | static void |
3844 | _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | 3978 | _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, struct _sas_device |
3979 | *sas_device) | ||
3845 | { | 3980 | { |
3846 | struct MPT2SAS_TARGET *sas_target_priv_data; | 3981 | struct MPT2SAS_TARGET *sas_target_priv_data; |
3847 | struct _sas_device *sas_device; | ||
3848 | unsigned long flags; | ||
3849 | Mpi2SasIoUnitControlReply_t mpi_reply; | 3982 | Mpi2SasIoUnitControlReply_t mpi_reply; |
3850 | Mpi2SasIoUnitControlRequest_t mpi_request; | 3983 | Mpi2SasIoUnitControlRequest_t mpi_request; |
3851 | u16 device_handle; | 3984 | u16 device_handle, handle; |
3852 | 3985 | ||
3853 | /* lookup sas_device */ | 3986 | if (!sas_device) |
3854 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
3855 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | ||
3856 | if (!sas_device) { | ||
3857 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
3858 | return; | 3987 | return; |
3859 | } | ||
3860 | 3988 | ||
3861 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: handle" | 3989 | handle = sas_device->handle; |
3862 | "(0x%04x)\n", ioc->name, __func__, handle)); | 3990 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: handle(0x%04x)," |
3991 | " sas_addr(0x%016llx)\n", ioc->name, __func__, handle, | ||
3992 | (unsigned long long) sas_device->sas_address)); | ||
3863 | 3993 | ||
3864 | if (sas_device->starget && sas_device->starget->hostdata) { | 3994 | if (sas_device->starget && sas_device->starget->hostdata) { |
3865 | sas_target_priv_data = sas_device->starget->hostdata; | 3995 | sas_target_priv_data = sas_device->starget->hostdata; |
3866 | sas_target_priv_data->deleted = 1; | 3996 | sas_target_priv_data->deleted = 1; |
3867 | } | 3997 | } |
3868 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
3869 | 3998 | ||
3870 | if (ioc->remove_host) | 3999 | if (ioc->remove_host || ioc->shost_recovery || !handle) |
3871 | goto out; | 4000 | goto out; |
3872 | 4001 | ||
3873 | if ((sas_device->state & MPTSAS_STATE_TR_COMPLETE)) { | 4002 | if ((sas_device->state & MPTSAS_STATE_TR_COMPLETE)) { |
3874 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "\tskip " | 4003 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "\tskip " |
3875 | "target_reset handle(0x%04x)\n", ioc->name, handle)); | 4004 | "target_reset handle(0x%04x)\n", ioc->name, |
4005 | handle)); | ||
3876 | goto skip_tr; | 4006 | goto skip_tr; |
3877 | } | 4007 | } |
3878 | 4008 | ||
@@ -3925,10 +4055,10 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3925 | _scsih_ublock_io_device(ioc, handle); | 4055 | _scsih_ublock_io_device(ioc, handle); |
3926 | 4056 | ||
3927 | mpt2sas_transport_port_remove(ioc, sas_device->sas_address, | 4057 | mpt2sas_transport_port_remove(ioc, sas_device->sas_address, |
3928 | sas_device->parent_handle); | 4058 | sas_device->sas_address_parent); |
3929 | 4059 | ||
3930 | printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr" | 4060 | printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr" |
3931 | "(0x%016llx)\n", ioc->name, sas_device->handle, | 4061 | "(0x%016llx)\n", ioc->name, handle, |
3932 | (unsigned long long) sas_device->sas_address); | 4062 | (unsigned long long) sas_device->sas_address); |
3933 | _scsih_sas_device_remove(ioc, sas_device); | 4063 | _scsih_sas_device_remove(ioc, sas_device); |
3934 | 4064 | ||
@@ -3952,7 +4082,7 @@ _scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | |||
3952 | u16 reason_code; | 4082 | u16 reason_code; |
3953 | u8 phy_number; | 4083 | u8 phy_number; |
3954 | char *status_str = NULL; | 4084 | char *status_str = NULL; |
3955 | char link_rate[25]; | 4085 | u8 link_rate, prev_link_rate; |
3956 | 4086 | ||
3957 | switch (event_data->ExpStatus) { | 4087 | switch (event_data->ExpStatus) { |
3958 | case MPI2_EVENT_SAS_TOPO_ES_ADDED: | 4088 | case MPI2_EVENT_SAS_TOPO_ES_ADDED: |
@@ -3962,6 +4092,7 @@ _scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | |||
3962 | status_str = "remove"; | 4092 | status_str = "remove"; |
3963 | break; | 4093 | break; |
3964 | case MPI2_EVENT_SAS_TOPO_ES_RESPONDING: | 4094 | case MPI2_EVENT_SAS_TOPO_ES_RESPONDING: |
4095 | case 0: | ||
3965 | status_str = "responding"; | 4096 | status_str = "responding"; |
3966 | break; | 4097 | break; |
3967 | case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING: | 4098 | case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING: |
@@ -3987,30 +4118,30 @@ _scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | |||
3987 | MPI2_EVENT_SAS_TOPO_RC_MASK; | 4118 | MPI2_EVENT_SAS_TOPO_RC_MASK; |
3988 | switch (reason_code) { | 4119 | switch (reason_code) { |
3989 | case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: | 4120 | case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: |
3990 | snprintf(link_rate, 25, ": add, link(0x%02x)", | 4121 | status_str = "target add"; |
3991 | (event_data->PHY[i].LinkRate >> 4)); | ||
3992 | status_str = link_rate; | ||
3993 | break; | 4122 | break; |
3994 | case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: | 4123 | case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: |
3995 | status_str = ": remove"; | 4124 | status_str = "target remove"; |
3996 | break; | 4125 | break; |
3997 | case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING: | 4126 | case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING: |
3998 | status_str = ": remove_delay"; | 4127 | status_str = "delay target remove"; |
3999 | break; | 4128 | break; |
4000 | case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: | 4129 | case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: |
4001 | snprintf(link_rate, 25, ": link(0x%02x)", | 4130 | status_str = "link rate change"; |
4002 | (event_data->PHY[i].LinkRate >> 4)); | ||
4003 | status_str = link_rate; | ||
4004 | break; | 4131 | break; |
4005 | case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE: | 4132 | case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE: |
4006 | status_str = ": responding"; | 4133 | status_str = "target responding"; |
4007 | break; | 4134 | break; |
4008 | default: | 4135 | default: |
4009 | status_str = ": unknown"; | 4136 | status_str = "unknown"; |
4010 | break; | 4137 | break; |
4011 | } | 4138 | } |
4012 | printk(KERN_DEBUG "\tphy(%02d), attached_handle(0x%04x)%s\n", | 4139 | link_rate = event_data->PHY[i].LinkRate >> 4; |
4013 | phy_number, handle, status_str); | 4140 | prev_link_rate = event_data->PHY[i].LinkRate & 0xF; |
4141 | printk(KERN_DEBUG "\tphy(%02d), attached_handle(0x%04x): %s:" | ||
4142 | " link rate: new(0x%02x), old(0x%02x)\n", phy_number, | ||
4143 | handle, status_str, link_rate, prev_link_rate); | ||
4144 | |||
4014 | } | 4145 | } |
4015 | } | 4146 | } |
4016 | #endif | 4147 | #endif |
@@ -4031,8 +4162,10 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
4031 | u16 reason_code; | 4162 | u16 reason_code; |
4032 | u8 phy_number; | 4163 | u8 phy_number; |
4033 | struct _sas_node *sas_expander; | 4164 | struct _sas_node *sas_expander; |
4165 | struct _sas_device *sas_device; | ||
4166 | u64 sas_address; | ||
4034 | unsigned long flags; | 4167 | unsigned long flags; |
4035 | u8 link_rate_; | 4168 | u8 link_rate, prev_link_rate; |
4036 | Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data; | 4169 | Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data; |
4037 | 4170 | ||
4038 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4171 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
@@ -4040,10 +4173,13 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
4040 | _scsih_sas_topology_change_event_debug(ioc, event_data); | 4173 | _scsih_sas_topology_change_event_debug(ioc, event_data); |
4041 | #endif | 4174 | #endif |
4042 | 4175 | ||
4176 | if (ioc->shost_recovery) | ||
4177 | return; | ||
4178 | |||
4043 | if (!ioc->sas_hba.num_phys) | 4179 | if (!ioc->sas_hba.num_phys) |
4044 | _scsih_sas_host_add(ioc); | 4180 | _scsih_sas_host_add(ioc); |
4045 | else | 4181 | else |
4046 | _scsih_sas_host_refresh(ioc, 0); | 4182 | _scsih_sas_host_refresh(ioc); |
4047 | 4183 | ||
4048 | if (fw_event->ignore) { | 4184 | if (fw_event->ignore) { |
4049 | dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ignoring expander " | 4185 | dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ignoring expander " |
@@ -4058,6 +4194,17 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
4058 | if (_scsih_expander_add(ioc, parent_handle) != 0) | 4194 | if (_scsih_expander_add(ioc, parent_handle) != 0) |
4059 | return; | 4195 | return; |
4060 | 4196 | ||
4197 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
4198 | sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, | ||
4199 | parent_handle); | ||
4200 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
4201 | if (sas_expander) | ||
4202 | sas_address = sas_expander->sas_address; | ||
4203 | else if (parent_handle < ioc->sas_hba.num_phys) | ||
4204 | sas_address = ioc->sas_hba.sas_address; | ||
4205 | else | ||
4206 | return; | ||
4207 | |||
4061 | /* handle siblings events */ | 4208 | /* handle siblings events */ |
4062 | for (i = 0; i < event_data->NumEntries; i++) { | 4209 | for (i = 0; i < event_data->NumEntries; i++) { |
4063 | if (fw_event->ignore) { | 4210 | if (fw_event->ignore) { |
@@ -4077,48 +4224,47 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
4077 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); | 4224 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); |
4078 | if (!handle) | 4225 | if (!handle) |
4079 | continue; | 4226 | continue; |
4080 | link_rate_ = event_data->PHY[i].LinkRate >> 4; | 4227 | link_rate = event_data->PHY[i].LinkRate >> 4; |
4228 | prev_link_rate = event_data->PHY[i].LinkRate & 0xF; | ||
4081 | switch (reason_code) { | 4229 | switch (reason_code) { |
4082 | case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: | 4230 | case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: |
4231 | |||
4232 | if (link_rate == prev_link_rate) | ||
4233 | break; | ||
4234 | |||
4235 | mpt2sas_transport_update_links(ioc, sas_address, | ||
4236 | handle, phy_number, link_rate); | ||
4237 | |||
4238 | if (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5) | ||
4239 | _scsih_ublock_io_device(ioc, handle); | ||
4240 | break; | ||
4083 | case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: | 4241 | case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: |
4084 | if (!parent_handle) { | 4242 | |
4085 | if (phy_number < ioc->sas_hba.num_phys) | 4243 | mpt2sas_transport_update_links(ioc, sas_address, |
4086 | mpt2sas_transport_update_links( | 4244 | handle, phy_number, link_rate); |
4087 | ioc, | 4245 | |
4088 | ioc->sas_hba.phy[phy_number].handle, | 4246 | _scsih_add_device(ioc, handle, phy_number, 0); |
4089 | handle, phy_number, link_rate_); | ||
4090 | } else { | ||
4091 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
4092 | sas_expander = | ||
4093 | mpt2sas_scsih_expander_find_by_handle(ioc, | ||
4094 | parent_handle); | ||
4095 | spin_unlock_irqrestore(&ioc->sas_node_lock, | ||
4096 | flags); | ||
4097 | if (sas_expander) { | ||
4098 | if (phy_number < sas_expander->num_phys) | ||
4099 | mpt2sas_transport_update_links( | ||
4100 | ioc, | ||
4101 | sas_expander-> | ||
4102 | phy[phy_number].handle, | ||
4103 | handle, phy_number, | ||
4104 | link_rate_); | ||
4105 | } | ||
4106 | } | ||
4107 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED) { | ||
4108 | if (link_rate_ < MPI2_SAS_NEG_LINK_RATE_1_5) | ||
4109 | break; | ||
4110 | _scsih_add_device(ioc, handle, phy_number, 0); | ||
4111 | } | ||
4112 | break; | 4247 | break; |
4113 | case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: | 4248 | case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: |
4114 | _scsih_remove_device(ioc, handle); | 4249 | |
4250 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
4251 | sas_device = _scsih_sas_device_find_by_handle(ioc, | ||
4252 | handle); | ||
4253 | if (!sas_device) { | ||
4254 | spin_unlock_irqrestore(&ioc->sas_device_lock, | ||
4255 | flags); | ||
4256 | break; | ||
4257 | } | ||
4258 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
4259 | _scsih_remove_device(ioc, sas_device); | ||
4115 | break; | 4260 | break; |
4116 | } | 4261 | } |
4117 | } | 4262 | } |
4118 | 4263 | ||
4119 | /* handle expander removal */ | 4264 | /* handle expander removal */ |
4120 | if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING) | 4265 | if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING && |
4121 | _scsih_expander_remove(ioc, parent_handle); | 4266 | sas_expander) |
4267 | _scsih_expander_remove(ioc, sas_address); | ||
4122 | 4268 | ||
4123 | } | 4269 | } |
4124 | 4270 | ||
@@ -4170,6 +4316,12 @@ _scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | |||
4170 | case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION: | 4316 | case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION: |
4171 | reason_str = "internal async notification"; | 4317 | reason_str = "internal async notification"; |
4172 | break; | 4318 | break; |
4319 | case MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY: | ||
4320 | reason_str = "expander reduced functionality"; | ||
4321 | break; | ||
4322 | case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY: | ||
4323 | reason_str = "expander reduced functionality complete"; | ||
4324 | break; | ||
4173 | default: | 4325 | default: |
4174 | reason_str = "unknown reason"; | 4326 | reason_str = "unknown reason"; |
4175 | break; | 4327 | break; |
@@ -4197,11 +4349,43 @@ static void | |||
4197 | _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, | 4349 | _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, |
4198 | struct fw_event_work *fw_event) | 4350 | struct fw_event_work *fw_event) |
4199 | { | 4351 | { |
4352 | struct MPT2SAS_TARGET *target_priv_data; | ||
4353 | struct _sas_device *sas_device; | ||
4354 | __le64 sas_address; | ||
4355 | unsigned long flags; | ||
4356 | Mpi2EventDataSasDeviceStatusChange_t *event_data = | ||
4357 | fw_event->event_data; | ||
4358 | |||
4200 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4359 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
4201 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | 4360 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) |
4202 | _scsih_sas_device_status_change_event_debug(ioc, | 4361 | _scsih_sas_device_status_change_event_debug(ioc, |
4203 | fw_event->event_data); | 4362 | event_data); |
4204 | #endif | 4363 | #endif |
4364 | |||
4365 | if (!(event_data->ReasonCode == | ||
4366 | MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET && | ||
4367 | event_data->ReasonCode == | ||
4368 | MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET)) | ||
4369 | return; | ||
4370 | |||
4371 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
4372 | sas_address = le64_to_cpu(event_data->SASAddress); | ||
4373 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | ||
4374 | sas_address); | ||
4375 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
4376 | |||
4377 | if (!sas_device || !sas_device->starget) | ||
4378 | return; | ||
4379 | |||
4380 | target_priv_data = sas_device->starget->hostdata; | ||
4381 | if (!target_priv_data) | ||
4382 | return; | ||
4383 | |||
4384 | if (event_data->ReasonCode == | ||
4385 | MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET) | ||
4386 | target_priv_data->tm_busy = 1; | ||
4387 | else | ||
4388 | target_priv_data->tm_busy = 0; | ||
4205 | } | 4389 | } |
4206 | 4390 | ||
4207 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4391 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
@@ -4281,6 +4465,7 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, | |||
4281 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4465 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
4282 | Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data; | 4466 | Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data; |
4283 | #endif | 4467 | #endif |
4468 | u16 ioc_status; | ||
4284 | dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "broadcast primative: " | 4469 | dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "broadcast primative: " |
4285 | "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum, | 4470 | "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum, |
4286 | event_data->PortWidth)); | 4471 | event_data->PortWidth)); |
@@ -4314,8 +4499,9 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, | |||
4314 | mpt2sas_scsih_issue_tm(ioc, handle, lun, | 4499 | mpt2sas_scsih_issue_tm(ioc, handle, lun, |
4315 | MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30); | 4500 | MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30); |
4316 | ioc->tm_cmds.status = MPT2_CMD_NOT_USED; | 4501 | ioc->tm_cmds.status = MPT2_CMD_NOT_USED; |
4317 | 4502 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus) | |
4318 | if ((mpi_reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) && | 4503 | & MPI2_IOCSTATUS_MASK; |
4504 | if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) && | ||
4319 | (mpi_reply->ResponseCode == | 4505 | (mpi_reply->ResponseCode == |
4320 | MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED || | 4506 | MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED || |
4321 | mpi_reply->ResponseCode == | 4507 | mpi_reply->ResponseCode == |
@@ -4570,7 +4756,7 @@ _scsih_sas_pd_delete(struct MPT2SAS_ADAPTER *ioc, | |||
4570 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4756 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
4571 | if (!sas_device) | 4757 | if (!sas_device) |
4572 | return; | 4758 | return; |
4573 | _scsih_remove_device(ioc, handle); | 4759 | _scsih_remove_device(ioc, sas_device); |
4574 | } | 4760 | } |
4575 | 4761 | ||
4576 | /** | 4762 | /** |
@@ -4591,6 +4777,8 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, | |||
4591 | Mpi2ConfigReply_t mpi_reply; | 4777 | Mpi2ConfigReply_t mpi_reply; |
4592 | Mpi2SasDevicePage0_t sas_device_pg0; | 4778 | Mpi2SasDevicePage0_t sas_device_pg0; |
4593 | u32 ioc_status; | 4779 | u32 ioc_status; |
4780 | u64 sas_address; | ||
4781 | u16 parent_handle; | ||
4594 | 4782 | ||
4595 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 4783 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
4596 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 4784 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); |
@@ -4615,9 +4803,10 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, | |||
4615 | return; | 4803 | return; |
4616 | } | 4804 | } |
4617 | 4805 | ||
4618 | mpt2sas_transport_update_links(ioc, | 4806 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); |
4619 | le16_to_cpu(sas_device_pg0.ParentDevHandle), | 4807 | if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) |
4620 | handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | 4808 | mpt2sas_transport_update_links(ioc, sas_address, handle, |
4809 | sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | ||
4621 | 4810 | ||
4622 | _scsih_add_device(ioc, handle, 0, 1); | 4811 | _scsih_add_device(ioc, handle, 0, 1); |
4623 | } | 4812 | } |
@@ -4857,7 +5046,7 @@ static void | |||
4857 | _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, | 5046 | _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, |
4858 | struct fw_event_work *fw_event) | 5047 | struct fw_event_work *fw_event) |
4859 | { | 5048 | { |
4860 | u16 handle; | 5049 | u16 handle, parent_handle; |
4861 | u32 state; | 5050 | u32 state; |
4862 | struct _sas_device *sas_device; | 5051 | struct _sas_device *sas_device; |
4863 | unsigned long flags; | 5052 | unsigned long flags; |
@@ -4865,6 +5054,7 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, | |||
4865 | Mpi2SasDevicePage0_t sas_device_pg0; | 5054 | Mpi2SasDevicePage0_t sas_device_pg0; |
4866 | u32 ioc_status; | 5055 | u32 ioc_status; |
4867 | Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; | 5056 | Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; |
5057 | u64 sas_address; | ||
4868 | 5058 | ||
4869 | if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) | 5059 | if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) |
4870 | return; | 5060 | return; |
@@ -4906,9 +5096,10 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, | |||
4906 | return; | 5096 | return; |
4907 | } | 5097 | } |
4908 | 5098 | ||
4909 | mpt2sas_transport_update_links(ioc, | 5099 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); |
4910 | le16_to_cpu(sas_device_pg0.ParentDevHandle), | 5100 | if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) |
4911 | handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | 5101 | mpt2sas_transport_update_links(ioc, sas_address, handle, |
5102 | sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | ||
4912 | 5103 | ||
4913 | _scsih_add_device(ioc, handle, 0, 1); | 5104 | _scsih_add_device(ioc, handle, 0, 1); |
4914 | 5105 | ||
@@ -4948,11 +5139,17 @@ _scsih_sas_ir_operation_status_event_debug(struct MPT2SAS_ADAPTER *ioc, | |||
4948 | case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK: | 5139 | case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK: |
4949 | reason_str = "consistency check"; | 5140 | reason_str = "consistency check"; |
4950 | break; | 5141 | break; |
4951 | default: | 5142 | case MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT: |
4952 | reason_str = "unknown reason"; | 5143 | reason_str = "background init"; |
5144 | break; | ||
5145 | case MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT: | ||
5146 | reason_str = "make data consistent"; | ||
4953 | break; | 5147 | break; |
4954 | } | 5148 | } |
4955 | 5149 | ||
5150 | if (!reason_str) | ||
5151 | return; | ||
5152 | |||
4956 | printk(MPT2SAS_INFO_FMT "raid operational status: (%s)" | 5153 | printk(MPT2SAS_INFO_FMT "raid operational status: (%s)" |
4957 | "\thandle(0x%04x), percent complete(%d)\n", | 5154 | "\thandle(0x%04x), percent complete(%d)\n", |
4958 | ioc->name, reason_str, | 5155 | ioc->name, reason_str, |
@@ -5252,18 +5449,23 @@ _scsih_mark_responding_expander(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, | |||
5252 | { | 5449 | { |
5253 | struct _sas_node *sas_expander; | 5450 | struct _sas_node *sas_expander; |
5254 | unsigned long flags; | 5451 | unsigned long flags; |
5452 | int i; | ||
5255 | 5453 | ||
5256 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | 5454 | spin_lock_irqsave(&ioc->sas_node_lock, flags); |
5257 | list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { | 5455 | list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { |
5258 | if (sas_expander->sas_address == sas_address) { | 5456 | if (sas_expander->sas_address != sas_address) |
5259 | sas_expander->responding = 1; | 5457 | continue; |
5260 | if (sas_expander->handle != handle) { | 5458 | sas_expander->responding = 1; |
5261 | printk(KERN_INFO "old handle(0x%04x)\n", | 5459 | if (sas_expander->handle == handle) |
5262 | sas_expander->handle); | ||
5263 | sas_expander->handle = handle; | ||
5264 | } | ||
5265 | goto out; | 5460 | goto out; |
5266 | } | 5461 | printk(KERN_INFO "\texpander(0x%016llx): handle changed" |
5462 | " from(0x%04x) to (0x%04x)!!!\n", | ||
5463 | (unsigned long long)sas_expander->sas_address, | ||
5464 | sas_expander->handle, handle); | ||
5465 | sas_expander->handle = handle; | ||
5466 | for (i = 0 ; i < sas_expander->num_phys ; i++) | ||
5467 | sas_expander->phy[i].handle = handle; | ||
5468 | goto out; | ||
5267 | } | 5469 | } |
5268 | out: | 5470 | out: |
5269 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | 5471 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); |
@@ -5340,7 +5542,9 @@ _scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc) | |||
5340 | (unsigned long long) | 5542 | (unsigned long long) |
5341 | sas_device->enclosure_logical_id, | 5543 | sas_device->enclosure_logical_id, |
5342 | sas_device->slot); | 5544 | sas_device->slot); |
5343 | _scsih_remove_device(ioc, sas_device->handle); | 5545 | /* invalidate the device handle */ |
5546 | sas_device->handle = 0; | ||
5547 | _scsih_remove_device(ioc, sas_device); | ||
5344 | } | 5548 | } |
5345 | 5549 | ||
5346 | list_for_each_entry_safe(raid_device, raid_device_next, | 5550 | list_for_each_entry_safe(raid_device, raid_device_next, |
@@ -5366,7 +5570,7 @@ _scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc) | |||
5366 | sas_expander->responding = 0; | 5570 | sas_expander->responding = 0; |
5367 | continue; | 5571 | continue; |
5368 | } | 5572 | } |
5369 | _scsih_expander_remove(ioc, sas_expander->handle); | 5573 | _scsih_expander_remove(ioc, sas_expander->sas_address); |
5370 | goto retry_expander_search; | 5574 | goto retry_expander_search; |
5371 | } | 5575 | } |
5372 | } | 5576 | } |
@@ -5406,7 +5610,7 @@ mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | |||
5406 | case MPT2_IOC_DONE_RESET: | 5610 | case MPT2_IOC_DONE_RESET: |
5407 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | 5611 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " |
5408 | "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); | 5612 | "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); |
5409 | _scsih_sas_host_refresh(ioc, 0); | 5613 | _scsih_sas_host_refresh(ioc); |
5410 | _scsih_search_responding_sas_devices(ioc); | 5614 | _scsih_search_responding_sas_devices(ioc); |
5411 | _scsih_search_responding_raid_devices(ioc); | 5615 | _scsih_search_responding_raid_devices(ioc); |
5412 | _scsih_search_responding_expanders(ioc); | 5616 | _scsih_search_responding_expanders(ioc); |
@@ -5646,7 +5850,7 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, | |||
5646 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5850 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
5647 | if (!sas_device) | 5851 | if (!sas_device) |
5648 | continue; | 5852 | continue; |
5649 | _scsih_remove_device(ioc, sas_device->handle); | 5853 | _scsih_remove_device(ioc, sas_device); |
5650 | if (ioc->shost_recovery) | 5854 | if (ioc->shost_recovery) |
5651 | return; | 5855 | return; |
5652 | goto retry_device_search; | 5856 | goto retry_device_search; |
@@ -5669,7 +5873,8 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, | |||
5669 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | 5873 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); |
5670 | if (!expander_sibling) | 5874 | if (!expander_sibling) |
5671 | continue; | 5875 | continue; |
5672 | _scsih_expander_remove(ioc, expander_sibling->handle); | 5876 | _scsih_expander_remove(ioc, |
5877 | expander_sibling->sas_address); | ||
5673 | if (ioc->shost_recovery) | 5878 | if (ioc->shost_recovery) |
5674 | return; | 5879 | return; |
5675 | goto retry_expander_search; | 5880 | goto retry_expander_search; |
@@ -5677,7 +5882,7 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, | |||
5677 | } | 5882 | } |
5678 | 5883 | ||
5679 | mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, | 5884 | mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, |
5680 | sas_expander->parent_handle); | 5885 | sas_expander->sas_address_parent); |
5681 | 5886 | ||
5682 | printk(MPT2SAS_INFO_FMT "expander_remove: handle" | 5887 | printk(MPT2SAS_INFO_FMT "expander_remove: handle" |
5683 | "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, | 5888 | "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, |
@@ -5690,9 +5895,99 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, | |||
5690 | } | 5895 | } |
5691 | 5896 | ||
5692 | /** | 5897 | /** |
5898 | * _scsih_ir_shutdown - IR shutdown notification | ||
5899 | * @ioc: per adapter object | ||
5900 | * | ||
5901 | * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that | ||
5902 | * the host system is shutting down. | ||
5903 | * | ||
5904 | * Return nothing. | ||
5905 | */ | ||
5906 | static void | ||
5907 | _scsih_ir_shutdown(struct MPT2SAS_ADAPTER *ioc) | ||
5908 | { | ||
5909 | Mpi2RaidActionRequest_t *mpi_request; | ||
5910 | Mpi2RaidActionReply_t *mpi_reply; | ||
5911 | u16 smid; | ||
5912 | |||
5913 | /* is IR firmware build loaded ? */ | ||
5914 | if (!ioc->ir_firmware) | ||
5915 | return; | ||
5916 | |||
5917 | /* are there any volumes ? */ | ||
5918 | if (list_empty(&ioc->raid_device_list)) | ||
5919 | return; | ||
5920 | |||
5921 | mutex_lock(&ioc->scsih_cmds.mutex); | ||
5922 | |||
5923 | if (ioc->scsih_cmds.status != MPT2_CMD_NOT_USED) { | ||
5924 | printk(MPT2SAS_ERR_FMT "%s: scsih_cmd in use\n", | ||
5925 | ioc->name, __func__); | ||
5926 | goto out; | ||
5927 | } | ||
5928 | ioc->scsih_cmds.status = MPT2_CMD_PENDING; | ||
5929 | |||
5930 | smid = mpt2sas_base_get_smid(ioc, ioc->scsih_cb_idx); | ||
5931 | if (!smid) { | ||
5932 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
5933 | ioc->name, __func__); | ||
5934 | ioc->scsih_cmds.status = MPT2_CMD_NOT_USED; | ||
5935 | goto out; | ||
5936 | } | ||
5937 | |||
5938 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
5939 | ioc->scsih_cmds.smid = smid; | ||
5940 | memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t)); | ||
5941 | |||
5942 | mpi_request->Function = MPI2_FUNCTION_RAID_ACTION; | ||
5943 | mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; | ||
5944 | |||
5945 | printk(MPT2SAS_INFO_FMT "IR shutdown (sending)\n", ioc->name); | ||
5946 | init_completion(&ioc->scsih_cmds.done); | ||
5947 | mpt2sas_base_put_smid_default(ioc, smid); | ||
5948 | wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ); | ||
5949 | |||
5950 | if (!(ioc->scsih_cmds.status & MPT2_CMD_COMPLETE)) { | ||
5951 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | ||
5952 | ioc->name, __func__); | ||
5953 | goto out; | ||
5954 | } | ||
5955 | |||
5956 | if (ioc->scsih_cmds.status & MPT2_CMD_REPLY_VALID) { | ||
5957 | mpi_reply = ioc->scsih_cmds.reply; | ||
5958 | |||
5959 | printk(MPT2SAS_INFO_FMT "IR shutdown (complete): " | ||
5960 | "ioc_status(0x%04x), loginfo(0x%08x)\n", | ||
5961 | ioc->name, le16_to_cpu(mpi_reply->IOCStatus), | ||
5962 | le32_to_cpu(mpi_reply->IOCLogInfo)); | ||
5963 | } | ||
5964 | |||
5965 | out: | ||
5966 | ioc->scsih_cmds.status = MPT2_CMD_NOT_USED; | ||
5967 | mutex_unlock(&ioc->scsih_cmds.mutex); | ||
5968 | } | ||
5969 | |||
5970 | /** | ||
5971 | * _scsih_shutdown - routine call during system shutdown | ||
5972 | * @pdev: PCI device struct | ||
5973 | * | ||
5974 | * Return nothing. | ||
5975 | */ | ||
5976 | static void | ||
5977 | _scsih_shutdown(struct pci_dev *pdev) | ||
5978 | { | ||
5979 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | ||
5980 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
5981 | |||
5982 | _scsih_ir_shutdown(ioc); | ||
5983 | mpt2sas_base_detach(ioc); | ||
5984 | } | ||
5985 | |||
5986 | /** | ||
5693 | * _scsih_remove - detach and remove add host | 5987 | * _scsih_remove - detach and remove add host |
5694 | * @pdev: PCI device struct | 5988 | * @pdev: PCI device struct |
5695 | * | 5989 | * |
5990 | * Routine called when unloading the driver. | ||
5696 | * Return nothing. | 5991 | * Return nothing. |
5697 | */ | 5992 | */ |
5698 | static void __devexit | 5993 | static void __devexit |
@@ -5726,7 +6021,7 @@ _scsih_remove(struct pci_dev *pdev) | |||
5726 | mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 6021 | mpt2sas_scsih_sas_device_find_by_sas_address(ioc, |
5727 | mpt2sas_port->remote_identify.sas_address); | 6022 | mpt2sas_port->remote_identify.sas_address); |
5728 | if (sas_device) { | 6023 | if (sas_device) { |
5729 | _scsih_remove_device(ioc, sas_device->handle); | 6024 | _scsih_remove_device(ioc, sas_device); |
5730 | goto retry_again; | 6025 | goto retry_again; |
5731 | } | 6026 | } |
5732 | } else { | 6027 | } else { |
@@ -5735,7 +6030,7 @@ _scsih_remove(struct pci_dev *pdev) | |||
5735 | mpt2sas_port->remote_identify.sas_address); | 6030 | mpt2sas_port->remote_identify.sas_address); |
5736 | if (expander_sibling) { | 6031 | if (expander_sibling) { |
5737 | _scsih_expander_remove(ioc, | 6032 | _scsih_expander_remove(ioc, |
5738 | expander_sibling->handle); | 6033 | expander_sibling->sas_address); |
5739 | goto retry_again; | 6034 | goto retry_again; |
5740 | } | 6035 | } |
5741 | } | 6036 | } |
@@ -5749,7 +6044,7 @@ _scsih_remove(struct pci_dev *pdev) | |||
5749 | } | 6044 | } |
5750 | 6045 | ||
5751 | sas_remove_host(shost); | 6046 | sas_remove_host(shost); |
5752 | mpt2sas_base_detach(ioc); | 6047 | _scsih_shutdown(pdev); |
5753 | list_del(&ioc->list); | 6048 | list_del(&ioc->list); |
5754 | scsi_remove_host(shost); | 6049 | scsi_remove_host(shost); |
5755 | scsi_host_put(shost); | 6050 | scsi_host_put(shost); |
@@ -5770,7 +6065,8 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc) | |||
5770 | void *device; | 6065 | void *device; |
5771 | struct _sas_device *sas_device; | 6066 | struct _sas_device *sas_device; |
5772 | struct _raid_device *raid_device; | 6067 | struct _raid_device *raid_device; |
5773 | u16 handle, parent_handle; | 6068 | u16 handle; |
6069 | u64 sas_address_parent; | ||
5774 | u64 sas_address; | 6070 | u64 sas_address; |
5775 | unsigned long flags; | 6071 | unsigned long flags; |
5776 | int rc; | 6072 | int rc; |
@@ -5799,17 +6095,17 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc) | |||
5799 | } else { | 6095 | } else { |
5800 | sas_device = device; | 6096 | sas_device = device; |
5801 | handle = sas_device->handle; | 6097 | handle = sas_device->handle; |
5802 | parent_handle = sas_device->parent_handle; | 6098 | sas_address_parent = sas_device->sas_address_parent; |
5803 | sas_address = sas_device->sas_address; | 6099 | sas_address = sas_device->sas_address; |
5804 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6100 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
5805 | list_move_tail(&sas_device->list, &ioc->sas_device_list); | 6101 | list_move_tail(&sas_device->list, &ioc->sas_device_list); |
5806 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 6102 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
5807 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, | 6103 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, |
5808 | sas_device->parent_handle)) { | 6104 | sas_device->sas_address_parent)) { |
5809 | _scsih_sas_device_remove(ioc, sas_device); | 6105 | _scsih_sas_device_remove(ioc, sas_device); |
5810 | } else if (!sas_device->starget) { | 6106 | } else if (!sas_device->starget) { |
5811 | mpt2sas_transport_port_remove(ioc, sas_address, | 6107 | mpt2sas_transport_port_remove(ioc, sas_address, |
5812 | parent_handle); | 6108 | sas_address_parent); |
5813 | _scsih_sas_device_remove(ioc, sas_device); | 6109 | _scsih_sas_device_remove(ioc, sas_device); |
5814 | } | 6110 | } |
5815 | } | 6111 | } |
@@ -5849,8 +6145,6 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc) | |||
5849 | { | 6145 | { |
5850 | struct _sas_device *sas_device, *next; | 6146 | struct _sas_device *sas_device, *next; |
5851 | unsigned long flags; | 6147 | unsigned long flags; |
5852 | u16 handle, parent_handle; | ||
5853 | u64 sas_address; | ||
5854 | 6148 | ||
5855 | /* SAS Device List */ | 6149 | /* SAS Device List */ |
5856 | list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list, | 6150 | list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list, |
@@ -5859,14 +6153,13 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc) | |||
5859 | list_move_tail(&sas_device->list, &ioc->sas_device_list); | 6153 | list_move_tail(&sas_device->list, &ioc->sas_device_list); |
5860 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 6154 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
5861 | 6155 | ||
5862 | handle = sas_device->handle; | 6156 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, |
5863 | parent_handle = sas_device->parent_handle; | 6157 | sas_device->sas_address_parent)) { |
5864 | sas_address = sas_device->sas_address; | ||
5865 | if (!mpt2sas_transport_port_add(ioc, handle, parent_handle)) { | ||
5866 | _scsih_sas_device_remove(ioc, sas_device); | 6158 | _scsih_sas_device_remove(ioc, sas_device); |
5867 | } else if (!sas_device->starget) { | 6159 | } else if (!sas_device->starget) { |
5868 | mpt2sas_transport_port_remove(ioc, sas_address, | 6160 | mpt2sas_transport_port_remove(ioc, |
5869 | parent_handle); | 6161 | sas_device->sas_address, |
6162 | sas_device->sas_address_parent); | ||
5870 | _scsih_sas_device_remove(ioc, sas_device); | 6163 | _scsih_sas_device_remove(ioc, sas_device); |
5871 | } | 6164 | } |
5872 | } | 6165 | } |
@@ -5935,6 +6228,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
5935 | ioc->ctl_cb_idx = ctl_cb_idx; | 6228 | ioc->ctl_cb_idx = ctl_cb_idx; |
5936 | ioc->base_cb_idx = base_cb_idx; | 6229 | ioc->base_cb_idx = base_cb_idx; |
5937 | ioc->transport_cb_idx = transport_cb_idx; | 6230 | ioc->transport_cb_idx = transport_cb_idx; |
6231 | ioc->scsih_cb_idx = scsih_cb_idx; | ||
5938 | ioc->config_cb_idx = config_cb_idx; | 6232 | ioc->config_cb_idx = config_cb_idx; |
5939 | ioc->tm_tr_cb_idx = tm_tr_cb_idx; | 6233 | ioc->tm_tr_cb_idx = tm_tr_cb_idx; |
5940 | ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; | 6234 | ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; |
@@ -6072,6 +6366,7 @@ static struct pci_driver scsih_driver = { | |||
6072 | .id_table = scsih_pci_table, | 6366 | .id_table = scsih_pci_table, |
6073 | .probe = _scsih_probe, | 6367 | .probe = _scsih_probe, |
6074 | .remove = __devexit_p(_scsih_remove), | 6368 | .remove = __devexit_p(_scsih_remove), |
6369 | .shutdown = _scsih_shutdown, | ||
6075 | #ifdef CONFIG_PM | 6370 | #ifdef CONFIG_PM |
6076 | .suspend = _scsih_suspend, | 6371 | .suspend = _scsih_suspend, |
6077 | .resume = _scsih_resume, | 6372 | .resume = _scsih_resume, |
@@ -6113,6 +6408,9 @@ _scsih_init(void) | |||
6113 | transport_cb_idx = mpt2sas_base_register_callback_handler( | 6408 | transport_cb_idx = mpt2sas_base_register_callback_handler( |
6114 | mpt2sas_transport_done); | 6409 | mpt2sas_transport_done); |
6115 | 6410 | ||
6411 | /* scsih internal commands callback handler */ | ||
6412 | scsih_cb_idx = mpt2sas_base_register_callback_handler(_scsih_done); | ||
6413 | |||
6116 | /* configuration page API internal commands callback handler */ | 6414 | /* configuration page API internal commands callback handler */ |
6117 | config_cb_idx = mpt2sas_base_register_callback_handler( | 6415 | config_cb_idx = mpt2sas_base_register_callback_handler( |
6118 | mpt2sas_config_done); | 6416 | mpt2sas_config_done); |
@@ -6152,6 +6450,7 @@ _scsih_exit(void) | |||
6152 | mpt2sas_base_release_callback_handler(tm_cb_idx); | 6450 | mpt2sas_base_release_callback_handler(tm_cb_idx); |
6153 | mpt2sas_base_release_callback_handler(base_cb_idx); | 6451 | mpt2sas_base_release_callback_handler(base_cb_idx); |
6154 | mpt2sas_base_release_callback_handler(transport_cb_idx); | 6452 | mpt2sas_base_release_callback_handler(transport_cb_idx); |
6453 | mpt2sas_base_release_callback_handler(scsih_cb_idx); | ||
6155 | mpt2sas_base_release_callback_handler(config_cb_idx); | 6454 | mpt2sas_base_release_callback_handler(config_cb_idx); |
6156 | mpt2sas_base_release_callback_handler(ctl_cb_idx); | 6455 | mpt2sas_base_release_callback_handler(ctl_cb_idx); |
6157 | 6456 | ||