diff options
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_scsih.c')
| -rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 1078 |
1 files changed, 797 insertions, 281 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 86ab32d7ab15..be171ed682e0 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
| @@ -52,6 +52,8 @@ | |||
| 52 | #include <linux/delay.h> | 52 | #include <linux/delay.h> |
| 53 | #include <linux/pci.h> | 53 | #include <linux/pci.h> |
| 54 | #include <linux/interrupt.h> | 54 | #include <linux/interrupt.h> |
| 55 | #include <linux/raid_class.h> | ||
| 56 | #include <linux/slab.h> | ||
| 55 | 57 | ||
| 56 | #include "mpt2sas_base.h" | 58 | #include "mpt2sas_base.h" |
| 57 | 59 | ||
| @@ -76,6 +78,7 @@ static u8 tm_cb_idx = -1; | |||
| 76 | static u8 ctl_cb_idx = -1; | 78 | static u8 ctl_cb_idx = -1; |
| 77 | static u8 base_cb_idx = -1; | 79 | static u8 base_cb_idx = -1; |
| 78 | static u8 transport_cb_idx = -1; | 80 | static u8 transport_cb_idx = -1; |
| 81 | static u8 scsih_cb_idx = -1; | ||
| 79 | static u8 config_cb_idx = -1; | 82 | static u8 config_cb_idx = -1; |
| 80 | static int mpt_ids; | 83 | static int mpt_ids; |
| 81 | 84 | ||
| @@ -132,6 +135,9 @@ struct fw_event_work { | |||
| 132 | void *event_data; | 135 | void *event_data; |
| 133 | }; | 136 | }; |
| 134 | 137 | ||
| 138 | /* raid transport support */ | ||
| 139 | static struct raid_template *mpt2sas_raid_template; | ||
| 140 | |||
| 135 | /** | 141 | /** |
| 136 | * struct _scsi_io_transfer - scsi io transfer | 142 | * struct _scsi_io_transfer - scsi io transfer |
| 137 | * @handle: sas device handle (assigned by firmware) | 143 | * @handle: sas device handle (assigned by firmware) |
| @@ -196,10 +202,28 @@ static struct pci_device_id scsih_pci_table[] = { | |||
| 196 | PCI_ANY_ID, PCI_ANY_ID }, | 202 | PCI_ANY_ID, PCI_ANY_ID }, |
| 197 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3, | 203 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3, |
| 198 | PCI_ANY_ID, PCI_ANY_ID }, | 204 | PCI_ANY_ID, PCI_ANY_ID }, |
| 205 | /* Meteor ~ 2116 */ | ||
| 199 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1, | 206 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1, |
| 200 | PCI_ANY_ID, PCI_ANY_ID }, | 207 | PCI_ANY_ID, PCI_ANY_ID }, |
| 201 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2, | 208 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2, |
| 202 | PCI_ANY_ID, PCI_ANY_ID }, | 209 | PCI_ANY_ID, PCI_ANY_ID }, |
| 210 | /* Thunderbolt ~ 2208 */ | ||
| 211 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1, | ||
| 212 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 213 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2, | ||
| 214 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 215 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3, | ||
| 216 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 217 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4, | ||
| 218 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 219 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5, | ||
| 220 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 221 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6, | ||
| 222 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 223 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_7, | ||
| 224 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 225 | { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_8, | ||
| 226 | PCI_ANY_ID, PCI_ANY_ID }, | ||
| 203 | {0} /* Terminating entry */ | 227 | {0} /* Terminating entry */ |
| 204 | }; | 228 | }; |
| 205 | MODULE_DEVICE_TABLE(pci, scsih_pci_table); | 229 | MODULE_DEVICE_TABLE(pci, scsih_pci_table); |
| @@ -317,6 +341,47 @@ _scsih_is_boot_device(u64 sas_address, u64 device_name, | |||
| 317 | } | 341 | } |
| 318 | 342 | ||
| 319 | /** | 343 | /** |
| 344 | * _scsih_get_sas_address - set the sas_address for given device handle | ||
| 345 | * @handle: device handle | ||
| 346 | * @sas_address: sas address | ||
| 347 | * | ||
| 348 | * Returns 0 success, non-zero when failure | ||
| 349 | */ | ||
| 350 | static int | ||
| 351 | _scsih_get_sas_address(struct MPT2SAS_ADAPTER *ioc, u16 handle, | ||
| 352 | u64 *sas_address) | ||
| 353 | { | ||
| 354 | Mpi2SasDevicePage0_t sas_device_pg0; | ||
| 355 | Mpi2ConfigReply_t mpi_reply; | ||
| 356 | u32 ioc_status; | ||
| 357 | |||
| 358 | if (handle <= ioc->sas_hba.num_phys) { | ||
| 359 | *sas_address = ioc->sas_hba.sas_address; | ||
| 360 | return 0; | ||
| 361 | } else | ||
| 362 | *sas_address = 0; | ||
| 363 | |||
| 364 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | ||
| 365 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { | ||
| 366 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 367 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 368 | return -ENXIO; | ||
| 369 | } | ||
| 370 | |||
| 371 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & | ||
| 372 | MPI2_IOCSTATUS_MASK; | ||
| 373 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { | ||
| 374 | printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)" | ||
| 375 | "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status, | ||
| 376 | __FILE__, __LINE__, __func__); | ||
| 377 | return -EIO; | ||
| 378 | } | ||
| 379 | |||
| 380 | *sas_address = le64_to_cpu(sas_device_pg0.SASAddress); | ||
| 381 | return 0; | ||
| 382 | } | ||
| 383 | |||
| 384 | /** | ||
| 320 | * _scsih_determine_boot_device - determine boot device. | 385 | * _scsih_determine_boot_device - determine boot device. |
| 321 | * @ioc: per adapter object | 386 | * @ioc: per adapter object |
| 322 | * @device: either sas_device or raid_device object | 387 | * @device: either sas_device or raid_device object |
| @@ -510,8 +575,6 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc, | |||
| 510 | struct _sas_device *sas_device) | 575 | struct _sas_device *sas_device) |
| 511 | { | 576 | { |
| 512 | unsigned long flags; | 577 | unsigned long flags; |
| 513 | u16 handle, parent_handle; | ||
| 514 | u64 sas_address; | ||
| 515 | 578 | ||
| 516 | dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle" | 579 | dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle" |
| 517 | "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, | 580 | "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, |
| @@ -521,10 +584,8 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc, | |||
| 521 | list_add_tail(&sas_device->list, &ioc->sas_device_list); | 584 | list_add_tail(&sas_device->list, &ioc->sas_device_list); |
| 522 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 585 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 523 | 586 | ||
| 524 | handle = sas_device->handle; | 587 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, |
| 525 | parent_handle = sas_device->parent_handle; | 588 | 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); | 589 | _scsih_sas_device_remove(ioc, sas_device); |
| 529 | } | 590 | } |
| 530 | 591 | ||
| @@ -553,31 +614,6 @@ _scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc, | |||
| 553 | } | 614 | } |
| 554 | 615 | ||
| 555 | /** | 616 | /** |
| 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 | 617 | * _scsih_raid_device_find_by_id - raid device search |
| 582 | * @ioc: per adapter object | 618 | * @ioc: per adapter object |
| 583 | * @id: sas device target id | 619 | * @id: sas device target id |
| @@ -699,6 +735,31 @@ _scsih_raid_device_remove(struct MPT2SAS_ADAPTER *ioc, | |||
| 699 | } | 735 | } |
| 700 | 736 | ||
| 701 | /** | 737 | /** |
| 738 | * mpt2sas_scsih_expander_find_by_handle - expander device search | ||
| 739 | * @ioc: per adapter object | ||
| 740 | * @handle: expander handle (assigned by firmware) | ||
| 741 | * Context: Calling function should acquire ioc->sas_device_lock | ||
| 742 | * | ||
| 743 | * This searches for expander device based on handle, then returns the | ||
| 744 | * sas_node object. | ||
| 745 | */ | ||
| 746 | struct _sas_node * | ||
| 747 | mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 748 | { | ||
| 749 | struct _sas_node *sas_expander, *r; | ||
| 750 | |||
| 751 | r = NULL; | ||
| 752 | list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { | ||
| 753 | if (sas_expander->handle != handle) | ||
| 754 | continue; | ||
| 755 | r = sas_expander; | ||
| 756 | goto out; | ||
| 757 | } | ||
| 758 | out: | ||
| 759 | return r; | ||
| 760 | } | ||
| 761 | |||
| 762 | /** | ||
| 702 | * mpt2sas_scsih_expander_find_by_sas_address - expander device search | 763 | * mpt2sas_scsih_expander_find_by_sas_address - expander device search |
| 703 | * @ioc: per adapter object | 764 | * @ioc: per adapter object |
| 704 | * @sas_address: sas address | 765 | * @sas_address: sas address |
| @@ -1043,17 +1104,46 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc, | |||
| 1043 | * _scsih_change_queue_depth - setting device queue depth | 1104 | * _scsih_change_queue_depth - setting device queue depth |
| 1044 | * @sdev: scsi device struct | 1105 | * @sdev: scsi device struct |
| 1045 | * @qdepth: requested queue depth | 1106 | * @qdepth: requested queue depth |
| 1107 | * @reason: calling context | ||
| 1046 | * | 1108 | * |
| 1047 | * Returns queue depth. | 1109 | * Returns queue depth. |
| 1048 | */ | 1110 | */ |
| 1049 | static int | 1111 | static int |
| 1050 | _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) | 1112 | _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) |
| 1051 | { | 1113 | { |
| 1052 | struct Scsi_Host *shost = sdev->host; | 1114 | struct Scsi_Host *shost = sdev->host; |
| 1053 | int max_depth; | 1115 | int max_depth; |
| 1054 | int tag_type; | 1116 | int tag_type; |
| 1117 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 1118 | struct MPT2SAS_DEVICE *sas_device_priv_data; | ||
| 1119 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 1120 | struct _sas_device *sas_device; | ||
| 1121 | unsigned long flags; | ||
| 1122 | |||
| 1123 | if (reason != SCSI_QDEPTH_DEFAULT) | ||
| 1124 | return -EOPNOTSUPP; | ||
| 1055 | 1125 | ||
| 1056 | max_depth = shost->can_queue; | 1126 | max_depth = shost->can_queue; |
| 1127 | |||
| 1128 | /* limit max device queue for SATA to 32 */ | ||
| 1129 | sas_device_priv_data = sdev->hostdata; | ||
| 1130 | if (!sas_device_priv_data) | ||
| 1131 | goto not_sata; | ||
| 1132 | sas_target_priv_data = sas_device_priv_data->sas_target; | ||
| 1133 | if (!sas_target_priv_data) | ||
| 1134 | goto not_sata; | ||
| 1135 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) | ||
| 1136 | goto not_sata; | ||
| 1137 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 1138 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | ||
| 1139 | sas_device_priv_data->sas_target->sas_address); | ||
| 1140 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 1141 | if (sas_device && sas_device->device_info & | ||
| 1142 | MPI2_SAS_DEVICE_INFO_SATA_DEVICE) | ||
| 1143 | max_depth = MPT2SAS_SATA_QUEUE_DEPTH; | ||
| 1144 | |||
| 1145 | not_sata: | ||
| 1146 | |||
| 1057 | if (!sdev->tagged_supported) | 1147 | if (!sdev->tagged_supported) |
| 1058 | max_depth = 1; | 1148 | max_depth = 1; |
| 1059 | if (qdepth > max_depth) | 1149 | if (qdepth > max_depth) |
| @@ -1220,7 +1310,6 @@ _scsih_slave_alloc(struct scsi_device *sdev) | |||
| 1220 | struct MPT2SAS_DEVICE *sas_device_priv_data; | 1310 | struct MPT2SAS_DEVICE *sas_device_priv_data; |
| 1221 | struct scsi_target *starget; | 1311 | struct scsi_target *starget; |
| 1222 | struct _raid_device *raid_device; | 1312 | struct _raid_device *raid_device; |
| 1223 | struct _sas_device *sas_device; | ||
| 1224 | unsigned long flags; | 1313 | unsigned long flags; |
| 1225 | 1314 | ||
| 1226 | sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL); | 1315 | sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL); |
| @@ -1247,21 +1336,8 @@ _scsih_slave_alloc(struct scsi_device *sdev) | |||
| 1247 | if (raid_device) | 1336 | if (raid_device) |
| 1248 | raid_device->sdev = sdev; /* raid is single lun */ | 1337 | raid_device->sdev = sdev; /* raid is single lun */ |
| 1249 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | 1338 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); |
| 1250 | } else { | ||
| 1251 | /* set TLR bit for SSP devices */ | ||
| 1252 | if (!(ioc->facts.IOCCapabilities & | ||
| 1253 | MPI2_IOCFACTS_CAPABILITY_TLR)) | ||
| 1254 | goto out; | ||
| 1255 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 1256 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | ||
| 1257 | sas_device_priv_data->sas_target->sas_address); | ||
| 1258 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 1259 | if (sas_device && sas_device->device_info & | ||
| 1260 | MPI2_SAS_DEVICE_INFO_SSP_TARGET) | ||
| 1261 | sas_device_priv_data->flags |= MPT_DEVICE_TLR_ON; | ||
| 1262 | } | 1339 | } |
| 1263 | 1340 | ||
| 1264 | out: | ||
| 1265 | return 0; | 1341 | return 0; |
| 1266 | } | 1342 | } |
| 1267 | 1343 | ||
| @@ -1334,6 +1410,140 @@ _scsih_display_sata_capabilities(struct MPT2SAS_ADAPTER *ioc, | |||
| 1334 | } | 1410 | } |
| 1335 | 1411 | ||
| 1336 | /** | 1412 | /** |
| 1413 | * _scsih_is_raid - return boolean indicating device is raid volume | ||
| 1414 | * @dev the device struct object | ||
| 1415 | */ | ||
| 1416 | static int | ||
| 1417 | _scsih_is_raid(struct device *dev) | ||
| 1418 | { | ||
| 1419 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 1420 | |||
| 1421 | return (sdev->channel == RAID_CHANNEL) ? 1 : 0; | ||
| 1422 | } | ||
| 1423 | |||
| 1424 | /** | ||
| 1425 | * _scsih_get_resync - get raid volume resync percent complete | ||
| 1426 | * @dev the device struct object | ||
| 1427 | */ | ||
| 1428 | static void | ||
| 1429 | _scsih_get_resync(struct device *dev) | ||
| 1430 | { | ||
| 1431 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 1432 | struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host); | ||
| 1433 | static struct _raid_device *raid_device; | ||
| 1434 | unsigned long flags; | ||
| 1435 | Mpi2RaidVolPage0_t vol_pg0; | ||
| 1436 | Mpi2ConfigReply_t mpi_reply; | ||
| 1437 | u32 volume_status_flags; | ||
| 1438 | u8 percent_complete = 0; | ||
| 1439 | |||
| 1440 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 1441 | raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id, | ||
| 1442 | sdev->channel); | ||
| 1443 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 1444 | |||
| 1445 | if (!raid_device) | ||
| 1446 | goto out; | ||
| 1447 | |||
| 1448 | if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0, | ||
| 1449 | MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, | ||
| 1450 | sizeof(Mpi2RaidVolPage0_t))) { | ||
| 1451 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1452 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1453 | goto out; | ||
| 1454 | } | ||
| 1455 | |||
| 1456 | volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags); | ||
| 1457 | if (volume_status_flags & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) | ||
| 1458 | percent_complete = raid_device->percent_complete; | ||
| 1459 | out: | ||
| 1460 | raid_set_resync(mpt2sas_raid_template, dev, percent_complete); | ||
| 1461 | } | ||
| 1462 | |||
| 1463 | /** | ||
| 1464 | * _scsih_get_state - get raid volume level | ||
| 1465 | * @dev the device struct object | ||
| 1466 | */ | ||
| 1467 | static void | ||
| 1468 | _scsih_get_state(struct device *dev) | ||
| 1469 | { | ||
| 1470 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 1471 | struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host); | ||
| 1472 | static struct _raid_device *raid_device; | ||
| 1473 | unsigned long flags; | ||
| 1474 | Mpi2RaidVolPage0_t vol_pg0; | ||
| 1475 | Mpi2ConfigReply_t mpi_reply; | ||
| 1476 | u32 volstate; | ||
| 1477 | enum raid_state state = RAID_STATE_UNKNOWN; | ||
| 1478 | |||
| 1479 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 1480 | raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id, | ||
| 1481 | sdev->channel); | ||
| 1482 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 1483 | |||
| 1484 | if (!raid_device) | ||
| 1485 | goto out; | ||
| 1486 | |||
| 1487 | if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0, | ||
| 1488 | MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, | ||
| 1489 | sizeof(Mpi2RaidVolPage0_t))) { | ||
| 1490 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 1491 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 1492 | goto out; | ||
| 1493 | } | ||
| 1494 | |||
| 1495 | volstate = le32_to_cpu(vol_pg0.VolumeStatusFlags); | ||
| 1496 | if (volstate & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) { | ||
| 1497 | state = RAID_STATE_RESYNCING; | ||
| 1498 | goto out; | ||
| 1499 | } | ||
| 1500 | |||
| 1501 | switch (vol_pg0.VolumeState) { | ||
| 1502 | case MPI2_RAID_VOL_STATE_OPTIMAL: | ||
| 1503 | case MPI2_RAID_VOL_STATE_ONLINE: | ||
| 1504 | state = RAID_STATE_ACTIVE; | ||
| 1505 | break; | ||
| 1506 | case MPI2_RAID_VOL_STATE_DEGRADED: | ||
| 1507 | state = RAID_STATE_DEGRADED; | ||
| 1508 | break; | ||
| 1509 | case MPI2_RAID_VOL_STATE_FAILED: | ||
| 1510 | case MPI2_RAID_VOL_STATE_MISSING: | ||
| 1511 | state = RAID_STATE_OFFLINE; | ||
| 1512 | break; | ||
| 1513 | } | ||
| 1514 | out: | ||
| 1515 | raid_set_state(mpt2sas_raid_template, dev, state); | ||
| 1516 | } | ||
| 1517 | |||
| 1518 | /** | ||
| 1519 | * _scsih_set_level - set raid level | ||
| 1520 | * @sdev: scsi device struct | ||
| 1521 | * @raid_device: raid_device object | ||
| 1522 | */ | ||
| 1523 | static void | ||
| 1524 | _scsih_set_level(struct scsi_device *sdev, struct _raid_device *raid_device) | ||
| 1525 | { | ||
| 1526 | enum raid_level level = RAID_LEVEL_UNKNOWN; | ||
| 1527 | |||
| 1528 | switch (raid_device->volume_type) { | ||
| 1529 | case MPI2_RAID_VOL_TYPE_RAID0: | ||
| 1530 | level = RAID_LEVEL_0; | ||
| 1531 | break; | ||
| 1532 | case MPI2_RAID_VOL_TYPE_RAID10: | ||
| 1533 | level = RAID_LEVEL_10; | ||
| 1534 | break; | ||
| 1535 | case MPI2_RAID_VOL_TYPE_RAID1E: | ||
| 1536 | level = RAID_LEVEL_1E; | ||
| 1537 | break; | ||
| 1538 | case MPI2_RAID_VOL_TYPE_RAID1: | ||
| 1539 | level = RAID_LEVEL_1; | ||
| 1540 | break; | ||
| 1541 | } | ||
| 1542 | |||
| 1543 | raid_set_level(mpt2sas_raid_template, &sdev->sdev_gendev, level); | ||
| 1544 | } | ||
| 1545 | |||
| 1546 | /** | ||
| 1337 | * _scsih_get_volume_capabilities - volume capabilities | 1547 | * _scsih_get_volume_capabilities - volume capabilities |
| 1338 | * @ioc: per adapter object | 1548 | * @ioc: per adapter object |
| 1339 | * @sas_device: the raid_device object | 1549 | * @sas_device: the raid_device object |
| @@ -1394,6 +1604,32 @@ _scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc, | |||
| 1394 | } | 1604 | } |
| 1395 | 1605 | ||
| 1396 | /** | 1606 | /** |
| 1607 | * _scsih_enable_tlr - setting TLR flags | ||
| 1608 | * @ioc: per adapter object | ||
| 1609 | * @sdev: scsi device struct | ||
| 1610 | * | ||
| 1611 | * Enabling Transaction Layer Retries for tape devices when | ||
| 1612 | * vpd page 0x90 is present | ||
| 1613 | * | ||
| 1614 | */ | ||
| 1615 | static void | ||
| 1616 | _scsih_enable_tlr(struct MPT2SAS_ADAPTER *ioc, struct scsi_device *sdev) | ||
| 1617 | { | ||
| 1618 | /* only for TAPE */ | ||
| 1619 | if (sdev->type != TYPE_TAPE) | ||
| 1620 | return; | ||
| 1621 | |||
| 1622 | if (!(ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR)) | ||
| 1623 | return; | ||
| 1624 | |||
| 1625 | sas_enable_tlr(sdev); | ||
| 1626 | sdev_printk(KERN_INFO, sdev, "TLR %s\n", | ||
| 1627 | sas_is_tlr_enabled(sdev) ? "Enabled" : "Disabled"); | ||
| 1628 | return; | ||
| 1629 | |||
| 1630 | } | ||
| 1631 | |||
| 1632 | /** | ||
| 1397 | * _scsih_slave_configure - device configure routine. | 1633 | * _scsih_slave_configure - device configure routine. |
| 1398 | * @sdev: scsi device struct | 1634 | * @sdev: scsi device struct |
| 1399 | * | 1635 | * |
| @@ -1488,7 +1724,9 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 1488 | r_level, raid_device->handle, | 1724 | r_level, raid_device->handle, |
| 1489 | (unsigned long long)raid_device->wwid, | 1725 | (unsigned long long)raid_device->wwid, |
| 1490 | raid_device->num_pds, ds); | 1726 | raid_device->num_pds, ds); |
| 1491 | _scsih_change_queue_depth(sdev, qdepth); | 1727 | _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); |
| 1728 | /* raid transport support */ | ||
| 1729 | _scsih_set_level(sdev, raid_device); | ||
| 1492 | return 0; | 1730 | return 0; |
| 1493 | } | 1731 | } |
| 1494 | 1732 | ||
| @@ -1534,10 +1772,12 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 1534 | _scsih_display_sata_capabilities(ioc, sas_device, sdev); | 1772 | _scsih_display_sata_capabilities(ioc, sas_device, sdev); |
| 1535 | } | 1773 | } |
| 1536 | 1774 | ||
| 1537 | _scsih_change_queue_depth(sdev, qdepth); | 1775 | _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); |
| 1538 | 1776 | ||
| 1539 | if (ssp_target) | 1777 | if (ssp_target) { |
| 1540 | sas_read_port_mode_page(sdev); | 1778 | sas_read_port_mode_page(sdev); |
| 1779 | _scsih_enable_tlr(ioc, sdev); | ||
| 1780 | } | ||
| 1541 | return 0; | 1781 | return 0; |
| 1542 | } | 1782 | } |
| 1543 | 1783 | ||
| @@ -1874,6 +2114,8 @@ _scsih_abort(struct scsi_cmnd *scmd) | |||
| 1874 | goto out; | 2114 | goto out; |
| 1875 | } | 2115 | } |
| 1876 | 2116 | ||
| 2117 | mpt2sas_halt_firmware(ioc); | ||
| 2118 | |||
| 1877 | mutex_lock(&ioc->tm_cmds.mutex); | 2119 | mutex_lock(&ioc->tm_cmds.mutex); |
| 1878 | handle = sas_device_priv_data->sas_target->handle; | 2120 | handle = sas_device_priv_data->sas_target->handle; |
| 1879 | mpt2sas_scsih_issue_tm(ioc, handle, sas_device_priv_data->lun, | 2121 | mpt2sas_scsih_issue_tm(ioc, handle, sas_device_priv_data->lun, |
| @@ -2297,7 +2539,6 @@ _scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc, | |||
| 2297 | u16 handle; | 2539 | u16 handle; |
| 2298 | u16 reason_code; | 2540 | u16 reason_code; |
| 2299 | u8 phy_number; | 2541 | u8 phy_number; |
| 2300 | u8 link_rate; | ||
| 2301 | 2542 | ||
| 2302 | for (i = 0; i < event_data->NumEntries; i++) { | 2543 | for (i = 0; i < event_data->NumEntries; i++) { |
| 2303 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); | 2544 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); |
| @@ -2308,11 +2549,6 @@ _scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc, | |||
| 2308 | MPI2_EVENT_SAS_TOPO_RC_MASK; | 2549 | MPI2_EVENT_SAS_TOPO_RC_MASK; |
| 2309 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING) | 2550 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING) |
| 2310 | _scsih_block_io_device(ioc, handle); | 2551 | _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 | } | 2552 | } |
| 2317 | } | 2553 | } |
| 2318 | 2554 | ||
| @@ -2349,16 +2585,10 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 2349 | 2585 | ||
| 2350 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2586 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 2351 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 2587 | 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); | 2588 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 2359 | 2589 | ||
| 2360 | /* skip is hidden raid component */ | 2590 | /* skip is hidden raid component */ |
| 2361 | if (sas_device->hidden_raid_component) | 2591 | if (sas_device && sas_device->hidden_raid_component) |
| 2362 | return; | 2592 | return; |
| 2363 | 2593 | ||
| 2364 | smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx); | 2594 | smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx); |
| @@ -2371,18 +2601,31 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 2371 | delayed_tr->state = MPT2SAS_REQ_SAS_CNTRL; | 2601 | delayed_tr->state = MPT2SAS_REQ_SAS_CNTRL; |
| 2372 | list_add_tail(&delayed_tr->list, | 2602 | list_add_tail(&delayed_tr->list, |
| 2373 | &ioc->delayed_tr_list); | 2603 | &ioc->delayed_tr_list); |
| 2374 | if (sas_device->starget) | 2604 | if (sas_device && sas_device->starget) { |
| 2375 | dewtprintk(ioc, starget_printk(KERN_INFO, | 2605 | dewtprintk(ioc, starget_printk(KERN_INFO, |
| 2376 | sas_device->starget, "DELAYED:tr:handle(0x%04x), " | 2606 | sas_device->starget, "DELAYED:tr:handle(0x%04x), " |
| 2377 | "(open)\n", sas_device->handle)); | 2607 | "(open)\n", handle)); |
| 2608 | } else { | ||
| 2609 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 2610 | "DELAYED:tr:handle(0x%04x), (open)\n", | ||
| 2611 | ioc->name, handle)); | ||
| 2612 | } | ||
| 2378 | return; | 2613 | return; |
| 2379 | } | 2614 | } |
| 2380 | 2615 | ||
| 2381 | if (sas_device->starget && sas_device->starget->hostdata) { | 2616 | if (sas_device) { |
| 2382 | sas_target_priv_data = sas_device->starget->hostdata; | 2617 | sas_device->state |= MPTSAS_STATE_TR_SEND; |
| 2383 | sas_target_priv_data->tm_busy = 1; | 2618 | sas_device->state |= MPT2SAS_REQ_SAS_CNTRL; |
| 2384 | dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget, | 2619 | if (sas_device->starget && sas_device->starget->hostdata) { |
| 2385 | "tr:handle(0x%04x), (open)\n", sas_device->handle)); | 2620 | sas_target_priv_data = sas_device->starget->hostdata; |
| 2621 | sas_target_priv_data->tm_busy = 1; | ||
| 2622 | dewtprintk(ioc, starget_printk(KERN_INFO, | ||
| 2623 | sas_device->starget, "tr:handle(0x%04x), (open)\n", | ||
| 2624 | handle)); | ||
| 2625 | } | ||
| 2626 | } else { | ||
| 2627 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 2628 | "tr:handle(0x%04x), (open)\n", ioc->name, handle)); | ||
| 2386 | } | 2629 | } |
| 2387 | 2630 | ||
| 2388 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | 2631 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); |
| @@ -2390,8 +2633,6 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 2390 | mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; | 2633 | mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; |
| 2391 | mpi_request->DevHandle = cpu_to_le16(handle); | 2634 | mpi_request->DevHandle = cpu_to_le16(handle); |
| 2392 | mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; | 2635 | 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); | 2636 | mpt2sas_base_put_smid_hi_priority(ioc, smid); |
| 2396 | } | 2637 | } |
| 2397 | 2638 | ||
| @@ -2426,21 +2667,25 @@ _scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, | |||
| 2426 | 2667 | ||
| 2427 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2668 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 2428 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 2669 | 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); | 2670 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 2437 | 2671 | ||
| 2438 | if (sas_device->starget) | 2672 | if (sas_device) { |
| 2439 | dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget, | 2673 | sas_device->state |= MPTSAS_STATE_CNTRL_COMPLETE; |
| 2674 | if (sas_device->starget) | ||
| 2675 | dewtprintk(ioc, starget_printk(KERN_INFO, | ||
| 2676 | sas_device->starget, | ||
| 2677 | "sc_complete:handle(0x%04x), " | ||
| 2678 | "ioc_status(0x%04x), loginfo(0x%08x)\n", | ||
| 2679 | handle, le16_to_cpu(mpi_reply->IOCStatus), | ||
| 2680 | le32_to_cpu(mpi_reply->IOCLogInfo))); | ||
| 2681 | } else { | ||
| 2682 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 2440 | "sc_complete:handle(0x%04x), " | 2683 | "sc_complete:handle(0x%04x), " |
| 2441 | "ioc_status(0x%04x), loginfo(0x%08x)\n", | 2684 | "ioc_status(0x%04x), loginfo(0x%08x)\n", |
| 2442 | handle, le16_to_cpu(mpi_reply->IOCStatus), | 2685 | ioc->name, handle, le16_to_cpu(mpi_reply->IOCStatus), |
| 2443 | le32_to_cpu(mpi_reply->IOCLogInfo))); | 2686 | le32_to_cpu(mpi_reply->IOCLogInfo))); |
| 2687 | } | ||
| 2688 | |||
| 2444 | return 1; | 2689 | return 1; |
| 2445 | } | 2690 | } |
| 2446 | 2691 | ||
| @@ -2478,28 +2723,33 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
| 2478 | handle = le16_to_cpu(mpi_reply->DevHandle); | 2723 | handle = le16_to_cpu(mpi_reply->DevHandle); |
| 2479 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2724 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 2480 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 2725 | 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); | 2726 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 2489 | 2727 | ||
| 2490 | if (sas_device->starget) | 2728 | if (sas_device) { |
| 2491 | dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget, | 2729 | sas_device->state |= MPTSAS_STATE_TR_COMPLETE; |
| 2492 | "tr_complete:handle(0x%04x), (%s) ioc_status(0x%04x), " | 2730 | if (sas_device->starget) { |
| 2493 | "loginfo(0x%08x), completed(%d)\n", | 2731 | dewtprintk(ioc, starget_printk(KERN_INFO, |
| 2494 | sas_device->handle, (sas_device->state & | 2732 | sas_device->starget, "tr_complete:handle(0x%04x), " |
| 2495 | MPT2SAS_REQ_SAS_CNTRL) ? "open" : "active", | 2733 | "(%s) ioc_status(0x%04x), loginfo(0x%08x), " |
| 2496 | le16_to_cpu(mpi_reply->IOCStatus), | 2734 | "completed(%d)\n", sas_device->handle, |
| 2735 | (sas_device->state & MPT2SAS_REQ_SAS_CNTRL) ? | ||
| 2736 | "open" : "active", | ||
| 2737 | le16_to_cpu(mpi_reply->IOCStatus), | ||
| 2738 | le32_to_cpu(mpi_reply->IOCLogInfo), | ||
| 2739 | le32_to_cpu(mpi_reply->TerminationCount))); | ||
| 2740 | if (sas_device->starget->hostdata) { | ||
| 2741 | sas_target_priv_data = | ||
| 2742 | sas_device->starget->hostdata; | ||
| 2743 | sas_target_priv_data->tm_busy = 0; | ||
| 2744 | } | ||
| 2745 | } | ||
| 2746 | } else { | ||
| 2747 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | ||
| 2748 | "tr_complete:handle(0x%04x), (open) ioc_status(0x%04x), " | ||
| 2749 | "loginfo(0x%08x), completed(%d)\n", ioc->name, | ||
| 2750 | handle, le16_to_cpu(mpi_reply->IOCStatus), | ||
| 2497 | le32_to_cpu(mpi_reply->IOCLogInfo), | 2751 | le32_to_cpu(mpi_reply->IOCLogInfo), |
| 2498 | le32_to_cpu(mpi_reply->TerminationCount))); | 2752 | 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 | } | 2753 | } |
| 2504 | 2754 | ||
| 2505 | if (!list_empty(&ioc->delayed_tr_list)) { | 2755 | if (!list_empty(&ioc->delayed_tr_list)) { |
| @@ -2514,8 +2764,7 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
| 2514 | } else | 2764 | } else |
| 2515 | rc = 1; | 2765 | rc = 1; |
| 2516 | 2766 | ||
| 2517 | 2767 | if (sas_device && !(sas_device->state & MPT2SAS_REQ_SAS_CNTRL)) | |
| 2518 | if (!(sas_device->state & MPT2SAS_REQ_SAS_CNTRL)) | ||
| 2519 | return rc; | 2768 | return rc; |
| 2520 | 2769 | ||
| 2521 | if (ioc->shost_recovery) { | 2770 | if (ioc->shost_recovery) { |
| @@ -2531,12 +2780,14 @@ _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
| 2531 | return rc; | 2780 | return rc; |
| 2532 | } | 2781 | } |
| 2533 | 2782 | ||
| 2783 | if (sas_device) | ||
| 2784 | sas_device->state |= MPTSAS_STATE_CNTRL_SEND; | ||
| 2785 | |||
| 2534 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid_sas_ctrl); | 2786 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid_sas_ctrl); |
| 2535 | memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t)); | 2787 | memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t)); |
| 2536 | mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; | 2788 | mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; |
| 2537 | mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE; | 2789 | mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE; |
| 2538 | mpi_request->DevHandle = mpi_reply->DevHandle; | 2790 | mpi_request->DevHandle = mpi_reply->DevHandle; |
| 2539 | sas_device->state |= MPTSAS_STATE_CNTRL_SEND; | ||
| 2540 | mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl); | 2791 | mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl); |
| 2541 | return rc; | 2792 | return rc; |
| 2542 | } | 2793 | } |
| @@ -2678,8 +2929,6 @@ _scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request) | |||
| 2678 | else | 2929 | else |
| 2679 | return; | 2930 | return; |
| 2680 | 2931 | ||
| 2681 | mpi_request->EEDPBlockSize = scmd->device->sector_size; | ||
| 2682 | |||
| 2683 | switch (prot_type) { | 2932 | switch (prot_type) { |
| 2684 | case SCSI_PROT_DIF_TYPE1: | 2933 | case SCSI_PROT_DIF_TYPE1: |
| 2685 | 2934 | ||
| @@ -2687,8 +2936,7 @@ _scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request) | |||
| 2687 | * enable ref/guard checking | 2936 | * enable ref/guard checking |
| 2688 | * auto increment ref tag | 2937 | * auto increment ref tag |
| 2689 | */ | 2938 | */ |
| 2690 | mpi_request->EEDPFlags = eedp_flags | | 2939 | eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | |
| 2691 | MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | | ||
| 2692 | MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | | 2940 | MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | |
| 2693 | MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; | 2941 | MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; |
| 2694 | mpi_request->CDB.EEDP32.PrimaryReferenceTag = | 2942 | mpi_request->CDB.EEDP32.PrimaryReferenceTag = |
| @@ -2701,11 +2949,11 @@ _scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request) | |||
| 2701 | /* | 2949 | /* |
| 2702 | * enable guard checking | 2950 | * enable guard checking |
| 2703 | */ | 2951 | */ |
| 2704 | mpi_request->EEDPFlags = eedp_flags | | 2952 | eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; |
| 2705 | MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; | ||
| 2706 | |||
| 2707 | break; | 2953 | break; |
| 2708 | } | 2954 | } |
| 2955 | mpi_request->EEDPBlockSize = cpu_to_le32(scmd->device->sector_size); | ||
| 2956 | mpi_request->EEDPFlags = cpu_to_le16(eedp_flags); | ||
| 2709 | } | 2957 | } |
| 2710 | 2958 | ||
| 2711 | /** | 2959 | /** |
| @@ -2788,7 +3036,7 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) | |||
| 2788 | } | 3036 | } |
| 2789 | 3037 | ||
| 2790 | /* see if we are busy with task managment stuff */ | 3038 | /* see if we are busy with task managment stuff */ |
| 2791 | if (sas_target_priv_data->tm_busy) | 3039 | if (sas_device_priv_data->block || sas_target_priv_data->tm_busy) |
| 2792 | return SCSI_MLQUEUE_DEVICE_BUSY; | 3040 | return SCSI_MLQUEUE_DEVICE_BUSY; |
| 2793 | else if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress) | 3041 | else if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress) |
| 2794 | return SCSI_MLQUEUE_HOST_BUSY; | 3042 | return SCSI_MLQUEUE_HOST_BUSY; |
| @@ -2815,8 +3063,9 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) | |||
| 2815 | 3063 | ||
| 2816 | } else | 3064 | } else |
| 2817 | mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; | 3065 | mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; |
| 2818 | 3066 | /* Make sure Device is not raid volume */ | |
| 2819 | if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON)) | 3067 | if (!_scsih_is_raid(&scmd->device->sdev_gendev) && |
| 3068 | sas_is_tlr_enabled(scmd->device)) | ||
| 2820 | mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON; | 3069 | mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON; |
| 2821 | 3070 | ||
| 2822 | smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd); | 3071 | smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd); |
| @@ -2842,7 +3091,7 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) | |||
| 2842 | mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR; | 3091 | mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR; |
| 2843 | mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; | 3092 | mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; |
| 2844 | mpi_request->SenseBufferLowAddress = | 3093 | mpi_request->SenseBufferLowAddress = |
| 2845 | (u32)mpt2sas_base_get_sense_buffer_dma(ioc, smid); | 3094 | mpt2sas_base_get_sense_buffer_dma(ioc, smid); |
| 2846 | mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4; | 3095 | mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4; |
| 2847 | mpi_request->SGLFlags = cpu_to_le16(MPI2_SCSIIO_SGLFLAGS_TYPE_MPI + | 3096 | mpi_request->SGLFlags = cpu_to_le16(MPI2_SCSIIO_SGLFLAGS_TYPE_MPI + |
| 2848 | MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR); | 3097 | MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR); |
| @@ -2894,7 +3143,7 @@ _scsih_normalize_sense(char *sense_buffer, struct sense_info *data) | |||
| 2894 | 3143 | ||
| 2895 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 3144 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
| 2896 | /** | 3145 | /** |
| 2897 | * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request | 3146 | * _scsih_scsi_ioc_info - translated non-successfull SCSI_IO request |
| 2898 | * @ioc: per adapter object | 3147 | * @ioc: per adapter object |
| 2899 | * @scmd: pointer to scsi command object | 3148 | * @scmd: pointer to scsi command object |
| 2900 | * @mpi_reply: reply mf payload returned from firmware | 3149 | * @mpi_reply: reply mf payload returned from firmware |
| @@ -3059,7 +3308,7 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
| 3059 | if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { | 3308 | if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { |
| 3060 | response_info = le32_to_cpu(mpi_reply->ResponseInfo); | 3309 | response_info = le32_to_cpu(mpi_reply->ResponseInfo); |
| 3061 | response_bytes = (u8 *)&response_info; | 3310 | response_bytes = (u8 *)&response_info; |
| 3062 | _scsih_response_code(ioc, response_bytes[3]); | 3311 | _scsih_response_code(ioc, response_bytes[0]); |
| 3063 | } | 3312 | } |
| 3064 | } | 3313 | } |
| 3065 | #endif | 3314 | #endif |
| @@ -3177,7 +3426,7 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
| 3177 | u8 scsi_status; | 3426 | u8 scsi_status; |
| 3178 | u32 log_info; | 3427 | u32 log_info; |
| 3179 | struct MPT2SAS_DEVICE *sas_device_priv_data; | 3428 | struct MPT2SAS_DEVICE *sas_device_priv_data; |
| 3180 | u32 response_code; | 3429 | u32 response_code = 0; |
| 3181 | 3430 | ||
| 3182 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 3431 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
| 3183 | scmd = _scsih_scsi_lookup_get(ioc, smid); | 3432 | scmd = _scsih_scsi_lookup_get(ioc, smid); |
| @@ -3199,15 +3448,17 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
| 3199 | } | 3448 | } |
| 3200 | 3449 | ||
| 3201 | /* turning off TLR */ | 3450 | /* turning off TLR */ |
| 3451 | scsi_state = mpi_reply->SCSIState; | ||
| 3452 | if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) | ||
| 3453 | response_code = | ||
| 3454 | le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF; | ||
| 3202 | if (!sas_device_priv_data->tlr_snoop_check) { | 3455 | if (!sas_device_priv_data->tlr_snoop_check) { |
| 3203 | sas_device_priv_data->tlr_snoop_check++; | 3456 | sas_device_priv_data->tlr_snoop_check++; |
| 3204 | if (sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) { | 3457 | if (!_scsih_is_raid(&scmd->device->sdev_gendev) && |
| 3205 | response_code = (le32_to_cpu(mpi_reply->ResponseInfo) | 3458 | sas_is_tlr_enabled(scmd->device) && |
| 3206 | >> 24); | 3459 | response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) { |
| 3207 | if (response_code == | 3460 | sas_disable_tlr(scmd->device); |
| 3208 | MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) | 3461 | sdev_printk(KERN_INFO, scmd->device, "TLR disabled\n"); |
| 3209 | sas_device_priv_data->flags &= | ||
| 3210 | ~MPT_DEVICE_TLR_ON; | ||
| 3211 | } | 3462 | } |
| 3212 | } | 3463 | } |
| 3213 | 3464 | ||
| @@ -3219,7 +3470,6 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
| 3219 | else | 3470 | else |
| 3220 | log_info = 0; | 3471 | log_info = 0; |
| 3221 | ioc_status &= MPI2_IOCSTATUS_MASK; | 3472 | ioc_status &= MPI2_IOCSTATUS_MASK; |
| 3222 | scsi_state = mpi_reply->SCSIState; | ||
| 3223 | scsi_status = mpi_reply->SCSIStatus; | 3473 | scsi_status = mpi_reply->SCSIStatus; |
| 3224 | 3474 | ||
| 3225 | if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 && | 3475 | if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 && |
| @@ -3255,10 +3505,9 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
| 3255 | 3505 | ||
| 3256 | case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: | 3506 | case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: |
| 3257 | if (sas_device_priv_data->block) { | 3507 | if (sas_device_priv_data->block) { |
| 3258 | scmd->result = (DID_BUS_BUSY << 16); | 3508 | scmd->result = DID_TRANSPORT_DISRUPTED << 16; |
| 3259 | break; | 3509 | goto out; |
| 3260 | } | 3510 | } |
| 3261 | |||
| 3262 | case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: | 3511 | case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: |
| 3263 | case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: | 3512 | case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: |
| 3264 | scmd->result = DID_RESET << 16; | 3513 | scmd->result = DID_RESET << 16; |
| @@ -3304,8 +3553,10 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
| 3304 | case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: | 3553 | case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: |
| 3305 | case MPI2_IOCSTATUS_SUCCESS: | 3554 | case MPI2_IOCSTATUS_SUCCESS: |
| 3306 | scmd->result = (DID_OK << 16) | scsi_status; | 3555 | scmd->result = (DID_OK << 16) | scsi_status; |
| 3307 | if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED | | 3556 | if (response_code == |
| 3308 | MPI2_SCSI_STATE_NO_SCSI_STATUS)) | 3557 | MPI2_SCSITASKMGMT_RSP_INVALID_FRAME || |
| 3558 | (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED | | ||
| 3559 | MPI2_SCSI_STATE_NO_SCSI_STATUS))) | ||
| 3309 | scmd->result = DID_SOFT_ERROR << 16; | 3560 | scmd->result = DID_SOFT_ERROR << 16; |
| 3310 | else if (scsi_state & MPI2_SCSI_STATE_TERMINATED) | 3561 | else if (scsi_state & MPI2_SCSI_STATE_TERMINATED) |
| 3311 | scmd->result = DID_RESET << 16; | 3562 | scmd->result = DID_RESET << 16; |
| @@ -3344,7 +3595,6 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
| 3344 | /** | 3595 | /** |
| 3345 | * _scsih_sas_host_refresh - refreshing sas host object contents | 3596 | * _scsih_sas_host_refresh - refreshing sas host object contents |
| 3346 | * @ioc: per adapter object | 3597 | * @ioc: per adapter object |
| 3347 | * @update: update link information | ||
| 3348 | * Context: user | 3598 | * Context: user |
| 3349 | * | 3599 | * |
| 3350 | * During port enable, fw will send topology events for every device. Its | 3600 | * During port enable, fw will send topology events for every device. Its |
| @@ -3354,13 +3604,14 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
| 3354 | * Return nothing. | 3604 | * Return nothing. |
| 3355 | */ | 3605 | */ |
| 3356 | static void | 3606 | static void |
| 3357 | _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc, u8 update) | 3607 | _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc) |
| 3358 | { | 3608 | { |
| 3359 | u16 sz; | 3609 | u16 sz; |
| 3360 | u16 ioc_status; | 3610 | u16 ioc_status; |
| 3361 | int i; | 3611 | int i; |
| 3362 | Mpi2ConfigReply_t mpi_reply; | 3612 | Mpi2ConfigReply_t mpi_reply; |
| 3363 | Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; | 3613 | Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; |
| 3614 | u16 attached_handle; | ||
| 3364 | 3615 | ||
| 3365 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT | 3616 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT |
| 3366 | "updating handles for sas_host(0x%016llx)\n", | 3617 | "updating handles for sas_host(0x%016llx)\n", |
| @@ -3374,27 +3625,24 @@ _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc, u8 update) | |||
| 3374 | ioc->name, __FILE__, __LINE__, __func__); | 3625 | ioc->name, __FILE__, __LINE__, __func__); |
| 3375 | return; | 3626 | return; |
| 3376 | } | 3627 | } |
| 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 | 3628 | ||
| 3629 | if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, | ||
| 3630 | sas_iounit_pg0, sz)) != 0) | ||
| 3631 | goto out; | ||
| 3632 | ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
| 3633 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | ||
| 3634 | goto out; | ||
| 3635 | for (i = 0; i < ioc->sas_hba.num_phys ; i++) { | ||
| 3636 | if (i == 0) | ||
| 3637 | ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> | ||
| 3638 | PhyData[0].ControllerDevHandle); | ||
| 3639 | ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; | ||
| 3640 | attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i]. | ||
| 3641 | AttachedDevHandle); | ||
| 3642 | mpt2sas_transport_update_links(ioc, ioc->sas_hba.sas_address, | ||
| 3643 | attached_handle, i, sas_iounit_pg0->PhyData[i]. | ||
| 3644 | NegotiatedLinkRate >> 4); | ||
| 3645 | } | ||
| 3398 | out: | 3646 | out: |
| 3399 | kfree(sas_iounit_pg0); | 3647 | kfree(sas_iounit_pg0); |
| 3400 | } | 3648 | } |
| @@ -3507,19 +3755,21 @@ _scsih_sas_host_add(struct MPT2SAS_ADAPTER *ioc) | |||
| 3507 | ioc->name, __FILE__, __LINE__, __func__); | 3755 | ioc->name, __FILE__, __LINE__, __func__); |
| 3508 | goto out; | 3756 | goto out; |
| 3509 | } | 3757 | } |
| 3510 | ioc->sas_hba.phy[i].handle = | 3758 | |
| 3511 | le16_to_cpu(sas_iounit_pg0->PhyData[i].ControllerDevHandle); | 3759 | if (i == 0) |
| 3760 | ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> | ||
| 3761 | PhyData[0].ControllerDevHandle); | ||
| 3762 | ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; | ||
| 3512 | ioc->sas_hba.phy[i].phy_id = i; | 3763 | ioc->sas_hba.phy[i].phy_id = i; |
| 3513 | mpt2sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i], | 3764 | mpt2sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i], |
| 3514 | phy_pg0, ioc->sas_hba.parent_dev); | 3765 | phy_pg0, ioc->sas_hba.parent_dev); |
| 3515 | } | 3766 | } |
| 3516 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | 3767 | 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))) { | 3768 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) { |
| 3518 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 3769 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
| 3519 | ioc->name, __FILE__, __LINE__, __func__); | 3770 | ioc->name, __FILE__, __LINE__, __func__); |
| 3520 | goto out; | 3771 | goto out; |
| 3521 | } | 3772 | } |
| 3522 | ioc->sas_hba.handle = le16_to_cpu(sas_device_pg0.DevHandle); | ||
| 3523 | ioc->sas_hba.enclosure_handle = | 3773 | ioc->sas_hba.enclosure_handle = |
| 3524 | le16_to_cpu(sas_device_pg0.EnclosureHandle); | 3774 | le16_to_cpu(sas_device_pg0.EnclosureHandle); |
| 3525 | ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress); | 3775 | ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress); |
| @@ -3562,7 +3812,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 3562 | Mpi2SasEnclosurePage0_t enclosure_pg0; | 3812 | Mpi2SasEnclosurePage0_t enclosure_pg0; |
| 3563 | u32 ioc_status; | 3813 | u32 ioc_status; |
| 3564 | u16 parent_handle; | 3814 | u16 parent_handle; |
| 3565 | __le64 sas_address; | 3815 | __le64 sas_address, sas_address_parent = 0; |
| 3566 | int i; | 3816 | int i; |
| 3567 | unsigned long flags; | 3817 | unsigned long flags; |
| 3568 | struct _sas_port *mpt2sas_port = NULL; | 3818 | struct _sas_port *mpt2sas_port = NULL; |
| @@ -3591,10 +3841,16 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 3591 | 3841 | ||
| 3592 | /* handle out of order topology events */ | 3842 | /* handle out of order topology events */ |
| 3593 | parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle); | 3843 | parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle); |
| 3594 | if (parent_handle >= ioc->sas_hba.num_phys) { | 3844 | if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent) |
| 3845 | != 0) { | ||
| 3846 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 3847 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 3848 | return -1; | ||
| 3849 | } | ||
| 3850 | if (sas_address_parent != ioc->sas_hba.sas_address) { | ||
| 3595 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | 3851 | spin_lock_irqsave(&ioc->sas_node_lock, flags); |
| 3596 | sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, | 3852 | sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, |
| 3597 | parent_handle); | 3853 | sas_address_parent); |
| 3598 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | 3854 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); |
| 3599 | if (!sas_expander) { | 3855 | if (!sas_expander) { |
| 3600 | rc = _scsih_expander_add(ioc, parent_handle); | 3856 | rc = _scsih_expander_add(ioc, parent_handle); |
| @@ -3622,14 +3878,12 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 3622 | 3878 | ||
| 3623 | sas_expander->handle = handle; | 3879 | sas_expander->handle = handle; |
| 3624 | sas_expander->num_phys = expander_pg0.NumPhys; | 3880 | sas_expander->num_phys = expander_pg0.NumPhys; |
| 3625 | sas_expander->parent_handle = parent_handle; | 3881 | 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; | 3882 | sas_expander->sas_address = sas_address; |
| 3629 | 3883 | ||
| 3630 | printk(MPT2SAS_INFO_FMT "expander_add: handle(0x%04x)," | 3884 | printk(MPT2SAS_INFO_FMT "expander_add: handle(0x%04x)," |
| 3631 | " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name, | 3885 | " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name, |
| 3632 | handle, sas_expander->parent_handle, (unsigned long long) | 3886 | handle, parent_handle, (unsigned long long) |
| 3633 | sas_expander->sas_address, sas_expander->num_phys); | 3887 | sas_expander->sas_address, sas_expander->num_phys); |
| 3634 | 3888 | ||
| 3635 | if (!sas_expander->num_phys) | 3889 | if (!sas_expander->num_phys) |
| @@ -3645,7 +3899,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 3645 | 3899 | ||
| 3646 | INIT_LIST_HEAD(&sas_expander->sas_port_list); | 3900 | INIT_LIST_HEAD(&sas_expander->sas_port_list); |
| 3647 | mpt2sas_port = mpt2sas_transport_port_add(ioc, handle, | 3901 | mpt2sas_port = mpt2sas_transport_port_add(ioc, handle, |
| 3648 | sas_expander->parent_handle); | 3902 | sas_address_parent); |
| 3649 | if (!mpt2sas_port) { | 3903 | if (!mpt2sas_port) { |
| 3650 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 3904 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
| 3651 | ioc->name, __FILE__, __LINE__, __func__); | 3905 | ioc->name, __FILE__, __LINE__, __func__); |
| @@ -3691,20 +3945,54 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 3691 | 3945 | ||
| 3692 | if (mpt2sas_port) | 3946 | if (mpt2sas_port) |
| 3693 | mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, | 3947 | mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, |
| 3694 | sas_expander->parent_handle); | 3948 | sas_address_parent); |
| 3695 | kfree(sas_expander); | 3949 | kfree(sas_expander); |
| 3696 | return rc; | 3950 | return rc; |
| 3697 | } | 3951 | } |
| 3698 | 3952 | ||
| 3699 | /** | 3953 | /** |
| 3954 | * _scsih_done - scsih callback handler. | ||
| 3955 | * @ioc: per adapter object | ||
| 3956 | * @smid: system request message index | ||
| 3957 | * @msix_index: MSIX table index supplied by the OS | ||
| 3958 | * @reply: reply message frame(lower 32bit addr) | ||
| 3959 | * | ||
| 3960 | * Callback handler when sending internal generated message frames. | ||
| 3961 | * The callback index passed is `ioc->scsih_cb_idx` | ||
| 3962 | * | ||
| 3963 | * Return 1 meaning mf should be freed from _base_interrupt | ||
| 3964 | * 0 means the mf is freed from this function. | ||
| 3965 | */ | ||
| 3966 | static u8 | ||
| 3967 | _scsih_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | ||
| 3968 | { | ||
| 3969 | MPI2DefaultReply_t *mpi_reply; | ||
| 3970 | |||
| 3971 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
| 3972 | if (ioc->scsih_cmds.status == MPT2_CMD_NOT_USED) | ||
| 3973 | return 1; | ||
| 3974 | if (ioc->scsih_cmds.smid != smid) | ||
| 3975 | return 1; | ||
| 3976 | ioc->scsih_cmds.status |= MPT2_CMD_COMPLETE; | ||
| 3977 | if (mpi_reply) { | ||
| 3978 | memcpy(ioc->scsih_cmds.reply, mpi_reply, | ||
| 3979 | mpi_reply->MsgLength*4); | ||
| 3980 | ioc->scsih_cmds.status |= MPT2_CMD_REPLY_VALID; | ||
| 3981 | } | ||
| 3982 | ioc->scsih_cmds.status &= ~MPT2_CMD_PENDING; | ||
| 3983 | complete(&ioc->scsih_cmds.done); | ||
| 3984 | return 1; | ||
| 3985 | } | ||
| 3986 | |||
| 3987 | /** | ||
| 3700 | * _scsih_expander_remove - removing expander object | 3988 | * _scsih_expander_remove - removing expander object |
| 3701 | * @ioc: per adapter object | 3989 | * @ioc: per adapter object |
| 3702 | * @handle: expander handle | 3990 | * @sas_address: expander sas_address |
| 3703 | * | 3991 | * |
| 3704 | * Return nothing. | 3992 | * Return nothing. |
| 3705 | */ | 3993 | */ |
| 3706 | static void | 3994 | static void |
| 3707 | _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u16 handle) | 3995 | _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address) |
| 3708 | { | 3996 | { |
| 3709 | struct _sas_node *sas_expander; | 3997 | struct _sas_node *sas_expander; |
| 3710 | unsigned long flags; | 3998 | unsigned long flags; |
| @@ -3713,7 +4001,8 @@ _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 3713 | return; | 4001 | return; |
| 3714 | 4002 | ||
| 3715 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | 4003 | spin_lock_irqsave(&ioc->sas_node_lock, flags); |
| 3716 | sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, handle); | 4004 | sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, |
| 4005 | sas_address); | ||
| 3717 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | 4006 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); |
| 3718 | _scsih_expander_node_remove(ioc, sas_expander); | 4007 | _scsih_expander_node_remove(ioc, sas_expander); |
| 3719 | } | 4008 | } |
| @@ -3805,8 +4094,11 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
| 3805 | } | 4094 | } |
| 3806 | 4095 | ||
| 3807 | sas_device->handle = handle; | 4096 | sas_device->handle = handle; |
| 3808 | sas_device->parent_handle = | 4097 | if (_scsih_get_sas_address(ioc, le16_to_cpu |
| 3809 | le16_to_cpu(sas_device_pg0.ParentDevHandle); | 4098 | (sas_device_pg0.ParentDevHandle), |
| 4099 | &sas_device->sas_address_parent) != 0) | ||
| 4100 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
| 4101 | ioc->name, __FILE__, __LINE__, __func__); | ||
| 3810 | sas_device->enclosure_handle = | 4102 | sas_device->enclosure_handle = |
| 3811 | le16_to_cpu(sas_device_pg0.EnclosureHandle); | 4103 | le16_to_cpu(sas_device_pg0.EnclosureHandle); |
| 3812 | sas_device->slot = | 4104 | sas_device->slot = |
| @@ -3836,43 +4128,39 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
| 3836 | /** | 4128 | /** |
| 3837 | * _scsih_remove_device - removing sas device object | 4129 | * _scsih_remove_device - removing sas device object |
| 3838 | * @ioc: per adapter object | 4130 | * @ioc: per adapter object |
| 3839 | * @handle: sas device handle | 4131 | * @sas_device: the sas_device object |
| 3840 | * | 4132 | * |
| 3841 | * Return nothing. | 4133 | * Return nothing. |
| 3842 | */ | 4134 | */ |
| 3843 | static void | 4135 | static void |
| 3844 | _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | 4136 | _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, struct _sas_device |
| 4137 | *sas_device) | ||
| 3845 | { | 4138 | { |
| 3846 | struct MPT2SAS_TARGET *sas_target_priv_data; | 4139 | struct MPT2SAS_TARGET *sas_target_priv_data; |
| 3847 | struct _sas_device *sas_device; | ||
| 3848 | unsigned long flags; | ||
| 3849 | Mpi2SasIoUnitControlReply_t mpi_reply; | 4140 | Mpi2SasIoUnitControlReply_t mpi_reply; |
| 3850 | Mpi2SasIoUnitControlRequest_t mpi_request; | 4141 | Mpi2SasIoUnitControlRequest_t mpi_request; |
| 3851 | u16 device_handle; | 4142 | u16 device_handle, handle; |
| 3852 | 4143 | ||
| 3853 | /* lookup sas_device */ | 4144 | 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; | 4145 | return; |
| 3859 | } | ||
| 3860 | 4146 | ||
| 3861 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: handle" | 4147 | handle = sas_device->handle; |
| 3862 | "(0x%04x)\n", ioc->name, __func__, handle)); | 4148 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: handle(0x%04x)," |
| 4149 | " sas_addr(0x%016llx)\n", ioc->name, __func__, handle, | ||
| 4150 | (unsigned long long) sas_device->sas_address)); | ||
| 3863 | 4151 | ||
| 3864 | if (sas_device->starget && sas_device->starget->hostdata) { | 4152 | if (sas_device->starget && sas_device->starget->hostdata) { |
| 3865 | sas_target_priv_data = sas_device->starget->hostdata; | 4153 | sas_target_priv_data = sas_device->starget->hostdata; |
| 3866 | sas_target_priv_data->deleted = 1; | 4154 | sas_target_priv_data->deleted = 1; |
| 3867 | } | 4155 | } |
| 3868 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 3869 | 4156 | ||
| 3870 | if (ioc->remove_host) | 4157 | if (ioc->remove_host || ioc->shost_recovery || !handle) |
| 3871 | goto out; | 4158 | goto out; |
| 3872 | 4159 | ||
| 3873 | if ((sas_device->state & MPTSAS_STATE_TR_COMPLETE)) { | 4160 | if ((sas_device->state & MPTSAS_STATE_TR_COMPLETE)) { |
| 3874 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "\tskip " | 4161 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "\tskip " |
| 3875 | "target_reset handle(0x%04x)\n", ioc->name, handle)); | 4162 | "target_reset handle(0x%04x)\n", ioc->name, |
| 4163 | handle)); | ||
| 3876 | goto skip_tr; | 4164 | goto skip_tr; |
| 3877 | } | 4165 | } |
| 3878 | 4166 | ||
| @@ -3925,10 +4213,10 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 3925 | _scsih_ublock_io_device(ioc, handle); | 4213 | _scsih_ublock_io_device(ioc, handle); |
| 3926 | 4214 | ||
| 3927 | mpt2sas_transport_port_remove(ioc, sas_device->sas_address, | 4215 | mpt2sas_transport_port_remove(ioc, sas_device->sas_address, |
| 3928 | sas_device->parent_handle); | 4216 | sas_device->sas_address_parent); |
| 3929 | 4217 | ||
| 3930 | printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr" | 4218 | printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr" |
| 3931 | "(0x%016llx)\n", ioc->name, sas_device->handle, | 4219 | "(0x%016llx)\n", ioc->name, handle, |
| 3932 | (unsigned long long) sas_device->sas_address); | 4220 | (unsigned long long) sas_device->sas_address); |
| 3933 | _scsih_sas_device_remove(ioc, sas_device); | 4221 | _scsih_sas_device_remove(ioc, sas_device); |
| 3934 | 4222 | ||
| @@ -3952,7 +4240,7 @@ _scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | |||
| 3952 | u16 reason_code; | 4240 | u16 reason_code; |
| 3953 | u8 phy_number; | 4241 | u8 phy_number; |
| 3954 | char *status_str = NULL; | 4242 | char *status_str = NULL; |
| 3955 | char link_rate[25]; | 4243 | u8 link_rate, prev_link_rate; |
| 3956 | 4244 | ||
| 3957 | switch (event_data->ExpStatus) { | 4245 | switch (event_data->ExpStatus) { |
| 3958 | case MPI2_EVENT_SAS_TOPO_ES_ADDED: | 4246 | case MPI2_EVENT_SAS_TOPO_ES_ADDED: |
| @@ -3962,6 +4250,7 @@ _scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | |||
| 3962 | status_str = "remove"; | 4250 | status_str = "remove"; |
| 3963 | break; | 4251 | break; |
| 3964 | case MPI2_EVENT_SAS_TOPO_ES_RESPONDING: | 4252 | case MPI2_EVENT_SAS_TOPO_ES_RESPONDING: |
| 4253 | case 0: | ||
| 3965 | status_str = "responding"; | 4254 | status_str = "responding"; |
| 3966 | break; | 4255 | break; |
| 3967 | case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING: | 4256 | case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING: |
| @@ -3987,30 +4276,30 @@ _scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | |||
| 3987 | MPI2_EVENT_SAS_TOPO_RC_MASK; | 4276 | MPI2_EVENT_SAS_TOPO_RC_MASK; |
| 3988 | switch (reason_code) { | 4277 | switch (reason_code) { |
| 3989 | case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: | 4278 | case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: |
| 3990 | snprintf(link_rate, 25, ": add, link(0x%02x)", | 4279 | status_str = "target add"; |
| 3991 | (event_data->PHY[i].LinkRate >> 4)); | ||
| 3992 | status_str = link_rate; | ||
| 3993 | break; | 4280 | break; |
| 3994 | case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: | 4281 | case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: |
| 3995 | status_str = ": remove"; | 4282 | status_str = "target remove"; |
| 3996 | break; | 4283 | break; |
| 3997 | case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING: | 4284 | case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING: |
| 3998 | status_str = ": remove_delay"; | 4285 | status_str = "delay target remove"; |
| 3999 | break; | 4286 | break; |
| 4000 | case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: | 4287 | case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: |
| 4001 | snprintf(link_rate, 25, ": link(0x%02x)", | 4288 | status_str = "link rate change"; |
| 4002 | (event_data->PHY[i].LinkRate >> 4)); | ||
| 4003 | status_str = link_rate; | ||
| 4004 | break; | 4289 | break; |
| 4005 | case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE: | 4290 | case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE: |
| 4006 | status_str = ": responding"; | 4291 | status_str = "target responding"; |
| 4007 | break; | 4292 | break; |
| 4008 | default: | 4293 | default: |
| 4009 | status_str = ": unknown"; | 4294 | status_str = "unknown"; |
| 4010 | break; | 4295 | break; |
| 4011 | } | 4296 | } |
| 4012 | printk(KERN_DEBUG "\tphy(%02d), attached_handle(0x%04x)%s\n", | 4297 | link_rate = event_data->PHY[i].LinkRate >> 4; |
| 4013 | phy_number, handle, status_str); | 4298 | prev_link_rate = event_data->PHY[i].LinkRate & 0xF; |
| 4299 | printk(KERN_DEBUG "\tphy(%02d), attached_handle(0x%04x): %s:" | ||
| 4300 | " link rate: new(0x%02x), old(0x%02x)\n", phy_number, | ||
| 4301 | handle, status_str, link_rate, prev_link_rate); | ||
| 4302 | |||
| 4014 | } | 4303 | } |
| 4015 | } | 4304 | } |
| 4016 | #endif | 4305 | #endif |
| @@ -4031,8 +4320,10 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 4031 | u16 reason_code; | 4320 | u16 reason_code; |
| 4032 | u8 phy_number; | 4321 | u8 phy_number; |
| 4033 | struct _sas_node *sas_expander; | 4322 | struct _sas_node *sas_expander; |
| 4323 | struct _sas_device *sas_device; | ||
| 4324 | u64 sas_address; | ||
| 4034 | unsigned long flags; | 4325 | unsigned long flags; |
| 4035 | u8 link_rate_; | 4326 | u8 link_rate, prev_link_rate; |
| 4036 | Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data; | 4327 | Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data; |
| 4037 | 4328 | ||
| 4038 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4329 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
| @@ -4040,10 +4331,13 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 4040 | _scsih_sas_topology_change_event_debug(ioc, event_data); | 4331 | _scsih_sas_topology_change_event_debug(ioc, event_data); |
| 4041 | #endif | 4332 | #endif |
| 4042 | 4333 | ||
| 4334 | if (ioc->shost_recovery) | ||
| 4335 | return; | ||
| 4336 | |||
| 4043 | if (!ioc->sas_hba.num_phys) | 4337 | if (!ioc->sas_hba.num_phys) |
| 4044 | _scsih_sas_host_add(ioc); | 4338 | _scsih_sas_host_add(ioc); |
| 4045 | else | 4339 | else |
| 4046 | _scsih_sas_host_refresh(ioc, 0); | 4340 | _scsih_sas_host_refresh(ioc); |
| 4047 | 4341 | ||
| 4048 | if (fw_event->ignore) { | 4342 | if (fw_event->ignore) { |
| 4049 | dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ignoring expander " | 4343 | dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ignoring expander " |
| @@ -4058,6 +4352,17 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 4058 | if (_scsih_expander_add(ioc, parent_handle) != 0) | 4352 | if (_scsih_expander_add(ioc, parent_handle) != 0) |
| 4059 | return; | 4353 | return; |
| 4060 | 4354 | ||
| 4355 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | ||
| 4356 | sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, | ||
| 4357 | parent_handle); | ||
| 4358 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | ||
| 4359 | if (sas_expander) | ||
| 4360 | sas_address = sas_expander->sas_address; | ||
| 4361 | else if (parent_handle < ioc->sas_hba.num_phys) | ||
| 4362 | sas_address = ioc->sas_hba.sas_address; | ||
| 4363 | else | ||
| 4364 | return; | ||
| 4365 | |||
| 4061 | /* handle siblings events */ | 4366 | /* handle siblings events */ |
| 4062 | for (i = 0; i < event_data->NumEntries; i++) { | 4367 | for (i = 0; i < event_data->NumEntries; i++) { |
| 4063 | if (fw_event->ignore) { | 4368 | if (fw_event->ignore) { |
| @@ -4077,48 +4382,47 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 4077 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); | 4382 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); |
| 4078 | if (!handle) | 4383 | if (!handle) |
| 4079 | continue; | 4384 | continue; |
| 4080 | link_rate_ = event_data->PHY[i].LinkRate >> 4; | 4385 | link_rate = event_data->PHY[i].LinkRate >> 4; |
| 4386 | prev_link_rate = event_data->PHY[i].LinkRate & 0xF; | ||
| 4081 | switch (reason_code) { | 4387 | switch (reason_code) { |
| 4082 | case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: | 4388 | case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: |
| 4389 | |||
| 4390 | if (link_rate == prev_link_rate) | ||
| 4391 | break; | ||
| 4392 | |||
| 4393 | mpt2sas_transport_update_links(ioc, sas_address, | ||
| 4394 | handle, phy_number, link_rate); | ||
| 4395 | |||
| 4396 | if (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5) | ||
| 4397 | _scsih_ublock_io_device(ioc, handle); | ||
| 4398 | break; | ||
| 4083 | case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: | 4399 | case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: |
| 4084 | if (!parent_handle) { | 4400 | |
| 4085 | if (phy_number < ioc->sas_hba.num_phys) | 4401 | mpt2sas_transport_update_links(ioc, sas_address, |
| 4086 | mpt2sas_transport_update_links( | 4402 | handle, phy_number, link_rate); |
| 4087 | ioc, | 4403 | |
| 4088 | ioc->sas_hba.phy[phy_number].handle, | 4404 | _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; | 4405 | break; |
| 4113 | case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: | 4406 | case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: |
| 4114 | _scsih_remove_device(ioc, handle); | 4407 | |
| 4408 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 4409 | sas_device = _scsih_sas_device_find_by_handle(ioc, | ||
| 4410 | handle); | ||
| 4411 | if (!sas_device) { | ||
| 4412 | spin_unlock_irqrestore(&ioc->sas_device_lock, | ||
| 4413 | flags); | ||
| 4414 | break; | ||
| 4415 | } | ||
| 4416 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 4417 | _scsih_remove_device(ioc, sas_device); | ||
| 4115 | break; | 4418 | break; |
| 4116 | } | 4419 | } |
| 4117 | } | 4420 | } |
| 4118 | 4421 | ||
| 4119 | /* handle expander removal */ | 4422 | /* handle expander removal */ |
| 4120 | if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING) | 4423 | if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING && |
| 4121 | _scsih_expander_remove(ioc, parent_handle); | 4424 | sas_expander) |
| 4425 | _scsih_expander_remove(ioc, sas_address); | ||
| 4122 | 4426 | ||
| 4123 | } | 4427 | } |
| 4124 | 4428 | ||
| @@ -4170,6 +4474,12 @@ _scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | |||
| 4170 | case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION: | 4474 | case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION: |
| 4171 | reason_str = "internal async notification"; | 4475 | reason_str = "internal async notification"; |
| 4172 | break; | 4476 | break; |
| 4477 | case MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY: | ||
| 4478 | reason_str = "expander reduced functionality"; | ||
| 4479 | break; | ||
| 4480 | case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY: | ||
| 4481 | reason_str = "expander reduced functionality complete"; | ||
| 4482 | break; | ||
| 4173 | default: | 4483 | default: |
| 4174 | reason_str = "unknown reason"; | 4484 | reason_str = "unknown reason"; |
| 4175 | break; | 4485 | break; |
| @@ -4197,11 +4507,43 @@ static void | |||
| 4197 | _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, | 4507 | _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, |
| 4198 | struct fw_event_work *fw_event) | 4508 | struct fw_event_work *fw_event) |
| 4199 | { | 4509 | { |
| 4510 | struct MPT2SAS_TARGET *target_priv_data; | ||
| 4511 | struct _sas_device *sas_device; | ||
| 4512 | __le64 sas_address; | ||
| 4513 | unsigned long flags; | ||
| 4514 | Mpi2EventDataSasDeviceStatusChange_t *event_data = | ||
| 4515 | fw_event->event_data; | ||
| 4516 | |||
| 4200 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4517 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
| 4201 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | 4518 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) |
| 4202 | _scsih_sas_device_status_change_event_debug(ioc, | 4519 | _scsih_sas_device_status_change_event_debug(ioc, |
| 4203 | fw_event->event_data); | 4520 | event_data); |
| 4204 | #endif | 4521 | #endif |
| 4522 | |||
| 4523 | if (!(event_data->ReasonCode == | ||
| 4524 | MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET && | ||
| 4525 | event_data->ReasonCode == | ||
| 4526 | MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET)) | ||
| 4527 | return; | ||
| 4528 | |||
| 4529 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 4530 | sas_address = le64_to_cpu(event_data->SASAddress); | ||
| 4531 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | ||
| 4532 | sas_address); | ||
| 4533 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 4534 | |||
| 4535 | if (!sas_device || !sas_device->starget) | ||
| 4536 | return; | ||
| 4537 | |||
| 4538 | target_priv_data = sas_device->starget->hostdata; | ||
| 4539 | if (!target_priv_data) | ||
| 4540 | return; | ||
| 4541 | |||
| 4542 | if (event_data->ReasonCode == | ||
| 4543 | MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET) | ||
| 4544 | target_priv_data->tm_busy = 1; | ||
| 4545 | else | ||
| 4546 | target_priv_data->tm_busy = 0; | ||
| 4205 | } | 4547 | } |
| 4206 | 4548 | ||
| 4207 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4549 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
| @@ -4281,6 +4623,7 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 4281 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4623 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
| 4282 | Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data; | 4624 | Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data; |
| 4283 | #endif | 4625 | #endif |
| 4626 | u16 ioc_status; | ||
| 4284 | dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "broadcast primative: " | 4627 | dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "broadcast primative: " |
| 4285 | "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum, | 4628 | "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum, |
| 4286 | event_data->PortWidth)); | 4629 | event_data->PortWidth)); |
| @@ -4314,8 +4657,9 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 4314 | mpt2sas_scsih_issue_tm(ioc, handle, lun, | 4657 | mpt2sas_scsih_issue_tm(ioc, handle, lun, |
| 4315 | MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30); | 4658 | MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30); |
| 4316 | ioc->tm_cmds.status = MPT2_CMD_NOT_USED; | 4659 | ioc->tm_cmds.status = MPT2_CMD_NOT_USED; |
| 4317 | 4660 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus) | |
| 4318 | if ((mpi_reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) && | 4661 | & MPI2_IOCSTATUS_MASK; |
| 4662 | if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) && | ||
| 4319 | (mpi_reply->ResponseCode == | 4663 | (mpi_reply->ResponseCode == |
| 4320 | MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED || | 4664 | MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED || |
| 4321 | mpi_reply->ResponseCode == | 4665 | mpi_reply->ResponseCode == |
| @@ -4570,7 +4914,7 @@ _scsih_sas_pd_delete(struct MPT2SAS_ADAPTER *ioc, | |||
| 4570 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4914 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 4571 | if (!sas_device) | 4915 | if (!sas_device) |
| 4572 | return; | 4916 | return; |
| 4573 | _scsih_remove_device(ioc, handle); | 4917 | _scsih_remove_device(ioc, sas_device); |
| 4574 | } | 4918 | } |
| 4575 | 4919 | ||
| 4576 | /** | 4920 | /** |
| @@ -4591,6 +4935,8 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, | |||
| 4591 | Mpi2ConfigReply_t mpi_reply; | 4935 | Mpi2ConfigReply_t mpi_reply; |
| 4592 | Mpi2SasDevicePage0_t sas_device_pg0; | 4936 | Mpi2SasDevicePage0_t sas_device_pg0; |
| 4593 | u32 ioc_status; | 4937 | u32 ioc_status; |
| 4938 | u64 sas_address; | ||
| 4939 | u16 parent_handle; | ||
| 4594 | 4940 | ||
| 4595 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 4941 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 4596 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 4942 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); |
| @@ -4615,9 +4961,10 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, | |||
| 4615 | return; | 4961 | return; |
| 4616 | } | 4962 | } |
| 4617 | 4963 | ||
| 4618 | mpt2sas_transport_update_links(ioc, | 4964 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); |
| 4619 | le16_to_cpu(sas_device_pg0.ParentDevHandle), | 4965 | if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) |
| 4620 | handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | 4966 | mpt2sas_transport_update_links(ioc, sas_address, handle, |
| 4967 | sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | ||
| 4621 | 4968 | ||
| 4622 | _scsih_add_device(ioc, handle, 0, 1); | 4969 | _scsih_add_device(ioc, handle, 0, 1); |
| 4623 | } | 4970 | } |
| @@ -4857,7 +5204,7 @@ static void | |||
| 4857 | _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, | 5204 | _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, |
| 4858 | struct fw_event_work *fw_event) | 5205 | struct fw_event_work *fw_event) |
| 4859 | { | 5206 | { |
| 4860 | u16 handle; | 5207 | u16 handle, parent_handle; |
| 4861 | u32 state; | 5208 | u32 state; |
| 4862 | struct _sas_device *sas_device; | 5209 | struct _sas_device *sas_device; |
| 4863 | unsigned long flags; | 5210 | unsigned long flags; |
| @@ -4865,6 +5212,7 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 4865 | Mpi2SasDevicePage0_t sas_device_pg0; | 5212 | Mpi2SasDevicePage0_t sas_device_pg0; |
| 4866 | u32 ioc_status; | 5213 | u32 ioc_status; |
| 4867 | Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; | 5214 | Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; |
| 5215 | u64 sas_address; | ||
| 4868 | 5216 | ||
| 4869 | if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) | 5217 | if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) |
| 4870 | return; | 5218 | return; |
| @@ -4906,9 +5254,10 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 4906 | return; | 5254 | return; |
| 4907 | } | 5255 | } |
| 4908 | 5256 | ||
| 4909 | mpt2sas_transport_update_links(ioc, | 5257 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); |
| 4910 | le16_to_cpu(sas_device_pg0.ParentDevHandle), | 5258 | if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) |
| 4911 | handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | 5259 | mpt2sas_transport_update_links(ioc, sas_address, handle, |
| 5260 | sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); | ||
| 4912 | 5261 | ||
| 4913 | _scsih_add_device(ioc, handle, 0, 1); | 5262 | _scsih_add_device(ioc, handle, 0, 1); |
| 4914 | 5263 | ||
| @@ -4948,11 +5297,17 @@ _scsih_sas_ir_operation_status_event_debug(struct MPT2SAS_ADAPTER *ioc, | |||
| 4948 | case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK: | 5297 | case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK: |
| 4949 | reason_str = "consistency check"; | 5298 | reason_str = "consistency check"; |
| 4950 | break; | 5299 | break; |
| 4951 | default: | 5300 | case MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT: |
| 4952 | reason_str = "unknown reason"; | 5301 | reason_str = "background init"; |
| 5302 | break; | ||
| 5303 | case MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT: | ||
| 5304 | reason_str = "make data consistent"; | ||
| 4953 | break; | 5305 | break; |
| 4954 | } | 5306 | } |
| 4955 | 5307 | ||
| 5308 | if (!reason_str) | ||
| 5309 | return; | ||
| 5310 | |||
| 4956 | printk(MPT2SAS_INFO_FMT "raid operational status: (%s)" | 5311 | printk(MPT2SAS_INFO_FMT "raid operational status: (%s)" |
| 4957 | "\thandle(0x%04x), percent complete(%d)\n", | 5312 | "\thandle(0x%04x), percent complete(%d)\n", |
| 4958 | ioc->name, reason_str, | 5313 | ioc->name, reason_str, |
| @@ -4973,11 +5328,33 @@ static void | |||
| 4973 | _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc, | 5328 | _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc, |
| 4974 | struct fw_event_work *fw_event) | 5329 | struct fw_event_work *fw_event) |
| 4975 | { | 5330 | { |
| 5331 | Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data; | ||
| 5332 | static struct _raid_device *raid_device; | ||
| 5333 | unsigned long flags; | ||
| 5334 | u16 handle; | ||
| 5335 | |||
| 4976 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 5336 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
| 4977 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | 5337 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) |
| 4978 | _scsih_sas_ir_operation_status_event_debug(ioc, | 5338 | _scsih_sas_ir_operation_status_event_debug(ioc, |
| 4979 | fw_event->event_data); | 5339 | event_data); |
| 4980 | #endif | 5340 | #endif |
| 5341 | |||
| 5342 | /* code added for raid transport support */ | ||
| 5343 | if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) { | ||
| 5344 | |||
| 5345 | handle = le16_to_cpu(event_data->VolDevHandle); | ||
| 5346 | |||
| 5347 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
| 5348 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | ||
| 5349 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
| 5350 | |||
| 5351 | if (!raid_device) | ||
| 5352 | return; | ||
| 5353 | |||
| 5354 | if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) | ||
| 5355 | raid_device->percent_complete = | ||
| 5356 | event_data->PercentComplete; | ||
| 5357 | } | ||
| 4981 | } | 5358 | } |
| 4982 | 5359 | ||
| 4983 | /** | 5360 | /** |
| @@ -5252,18 +5629,23 @@ _scsih_mark_responding_expander(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, | |||
| 5252 | { | 5629 | { |
| 5253 | struct _sas_node *sas_expander; | 5630 | struct _sas_node *sas_expander; |
| 5254 | unsigned long flags; | 5631 | unsigned long flags; |
| 5632 | int i; | ||
| 5255 | 5633 | ||
| 5256 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | 5634 | spin_lock_irqsave(&ioc->sas_node_lock, flags); |
| 5257 | list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { | 5635 | list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { |
| 5258 | if (sas_expander->sas_address == sas_address) { | 5636 | if (sas_expander->sas_address != sas_address) |
| 5259 | sas_expander->responding = 1; | 5637 | continue; |
| 5260 | if (sas_expander->handle != handle) { | 5638 | sas_expander->responding = 1; |
| 5261 | printk(KERN_INFO "old handle(0x%04x)\n", | 5639 | if (sas_expander->handle == handle) |
| 5262 | sas_expander->handle); | ||
| 5263 | sas_expander->handle = handle; | ||
| 5264 | } | ||
| 5265 | goto out; | 5640 | goto out; |
| 5266 | } | 5641 | printk(KERN_INFO "\texpander(0x%016llx): handle changed" |
| 5642 | " from(0x%04x) to (0x%04x)!!!\n", | ||
| 5643 | (unsigned long long)sas_expander->sas_address, | ||
| 5644 | sas_expander->handle, handle); | ||
| 5645 | sas_expander->handle = handle; | ||
| 5646 | for (i = 0 ; i < sas_expander->num_phys ; i++) | ||
| 5647 | sas_expander->phy[i].handle = handle; | ||
| 5648 | goto out; | ||
| 5267 | } | 5649 | } |
| 5268 | out: | 5650 | out: |
| 5269 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | 5651 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); |
| @@ -5340,7 +5722,9 @@ _scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 5340 | (unsigned long long) | 5722 | (unsigned long long) |
| 5341 | sas_device->enclosure_logical_id, | 5723 | sas_device->enclosure_logical_id, |
| 5342 | sas_device->slot); | 5724 | sas_device->slot); |
| 5343 | _scsih_remove_device(ioc, sas_device->handle); | 5725 | /* invalidate the device handle */ |
| 5726 | sas_device->handle = 0; | ||
| 5727 | _scsih_remove_device(ioc, sas_device); | ||
| 5344 | } | 5728 | } |
| 5345 | 5729 | ||
| 5346 | list_for_each_entry_safe(raid_device, raid_device_next, | 5730 | list_for_each_entry_safe(raid_device, raid_device_next, |
| @@ -5366,7 +5750,7 @@ _scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 5366 | sas_expander->responding = 0; | 5750 | sas_expander->responding = 0; |
| 5367 | continue; | 5751 | continue; |
| 5368 | } | 5752 | } |
| 5369 | _scsih_expander_remove(ioc, sas_expander->handle); | 5753 | _scsih_expander_remove(ioc, sas_expander->sas_address); |
| 5370 | goto retry_expander_search; | 5754 | goto retry_expander_search; |
| 5371 | } | 5755 | } |
| 5372 | } | 5756 | } |
| @@ -5406,7 +5790,7 @@ mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | |||
| 5406 | case MPT2_IOC_DONE_RESET: | 5790 | case MPT2_IOC_DONE_RESET: |
| 5407 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " | 5791 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " |
| 5408 | "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); | 5792 | "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); |
| 5409 | _scsih_sas_host_refresh(ioc, 0); | 5793 | _scsih_sas_host_refresh(ioc); |
| 5410 | _scsih_search_responding_sas_devices(ioc); | 5794 | _scsih_search_responding_sas_devices(ioc); |
| 5411 | _scsih_search_responding_raid_devices(ioc); | 5795 | _scsih_search_responding_raid_devices(ioc); |
| 5412 | _scsih_search_responding_expanders(ioc); | 5796 | _scsih_search_responding_expanders(ioc); |
| @@ -5646,7 +6030,7 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, | |||
| 5646 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 6030 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 5647 | if (!sas_device) | 6031 | if (!sas_device) |
| 5648 | continue; | 6032 | continue; |
| 5649 | _scsih_remove_device(ioc, sas_device->handle); | 6033 | _scsih_remove_device(ioc, sas_device); |
| 5650 | if (ioc->shost_recovery) | 6034 | if (ioc->shost_recovery) |
| 5651 | return; | 6035 | return; |
| 5652 | goto retry_device_search; | 6036 | goto retry_device_search; |
| @@ -5669,7 +6053,8 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, | |||
| 5669 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | 6053 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); |
| 5670 | if (!expander_sibling) | 6054 | if (!expander_sibling) |
| 5671 | continue; | 6055 | continue; |
| 5672 | _scsih_expander_remove(ioc, expander_sibling->handle); | 6056 | _scsih_expander_remove(ioc, |
| 6057 | expander_sibling->sas_address); | ||
| 5673 | if (ioc->shost_recovery) | 6058 | if (ioc->shost_recovery) |
| 5674 | return; | 6059 | return; |
| 5675 | goto retry_expander_search; | 6060 | goto retry_expander_search; |
| @@ -5677,7 +6062,7 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, | |||
| 5677 | } | 6062 | } |
| 5678 | 6063 | ||
| 5679 | mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, | 6064 | mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, |
| 5680 | sas_expander->parent_handle); | 6065 | sas_expander->sas_address_parent); |
| 5681 | 6066 | ||
| 5682 | printk(MPT2SAS_INFO_FMT "expander_remove: handle" | 6067 | printk(MPT2SAS_INFO_FMT "expander_remove: handle" |
| 5683 | "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, | 6068 | "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, |
| @@ -5690,9 +6075,99 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc, | |||
| 5690 | } | 6075 | } |
| 5691 | 6076 | ||
| 5692 | /** | 6077 | /** |
| 6078 | * _scsih_ir_shutdown - IR shutdown notification | ||
| 6079 | * @ioc: per adapter object | ||
| 6080 | * | ||
| 6081 | * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that | ||
| 6082 | * the host system is shutting down. | ||
| 6083 | * | ||
| 6084 | * Return nothing. | ||
| 6085 | */ | ||
| 6086 | static void | ||
| 6087 | _scsih_ir_shutdown(struct MPT2SAS_ADAPTER *ioc) | ||
| 6088 | { | ||
| 6089 | Mpi2RaidActionRequest_t *mpi_request; | ||
| 6090 | Mpi2RaidActionReply_t *mpi_reply; | ||
| 6091 | u16 smid; | ||
| 6092 | |||
| 6093 | /* is IR firmware build loaded ? */ | ||
| 6094 | if (!ioc->ir_firmware) | ||
| 6095 | return; | ||
| 6096 | |||
| 6097 | /* are there any volumes ? */ | ||
| 6098 | if (list_empty(&ioc->raid_device_list)) | ||
| 6099 | return; | ||
| 6100 | |||
| 6101 | mutex_lock(&ioc->scsih_cmds.mutex); | ||
| 6102 | |||
| 6103 | if (ioc->scsih_cmds.status != MPT2_CMD_NOT_USED) { | ||
| 6104 | printk(MPT2SAS_ERR_FMT "%s: scsih_cmd in use\n", | ||
| 6105 | ioc->name, __func__); | ||
| 6106 | goto out; | ||
| 6107 | } | ||
| 6108 | ioc->scsih_cmds.status = MPT2_CMD_PENDING; | ||
| 6109 | |||
| 6110 | smid = mpt2sas_base_get_smid(ioc, ioc->scsih_cb_idx); | ||
| 6111 | if (!smid) { | ||
| 6112 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
| 6113 | ioc->name, __func__); | ||
| 6114 | ioc->scsih_cmds.status = MPT2_CMD_NOT_USED; | ||
| 6115 | goto out; | ||
| 6116 | } | ||
| 6117 | |||
| 6118 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
| 6119 | ioc->scsih_cmds.smid = smid; | ||
| 6120 | memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t)); | ||
| 6121 | |||
| 6122 | mpi_request->Function = MPI2_FUNCTION_RAID_ACTION; | ||
| 6123 | mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; | ||
| 6124 | |||
| 6125 | printk(MPT2SAS_INFO_FMT "IR shutdown (sending)\n", ioc->name); | ||
| 6126 | init_completion(&ioc->scsih_cmds.done); | ||
| 6127 | mpt2sas_base_put_smid_default(ioc, smid); | ||
| 6128 | wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ); | ||
| 6129 | |||
| 6130 | if (!(ioc->scsih_cmds.status & MPT2_CMD_COMPLETE)) { | ||
| 6131 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | ||
| 6132 | ioc->name, __func__); | ||
| 6133 | goto out; | ||
| 6134 | } | ||
| 6135 | |||
| 6136 | if (ioc->scsih_cmds.status & MPT2_CMD_REPLY_VALID) { | ||
| 6137 | mpi_reply = ioc->scsih_cmds.reply; | ||
| 6138 | |||
| 6139 | printk(MPT2SAS_INFO_FMT "IR shutdown (complete): " | ||
| 6140 | "ioc_status(0x%04x), loginfo(0x%08x)\n", | ||
| 6141 | ioc->name, le16_to_cpu(mpi_reply->IOCStatus), | ||
| 6142 | le32_to_cpu(mpi_reply->IOCLogInfo)); | ||
| 6143 | } | ||
| 6144 | |||
| 6145 | out: | ||
| 6146 | ioc->scsih_cmds.status = MPT2_CMD_NOT_USED; | ||
| 6147 | mutex_unlock(&ioc->scsih_cmds.mutex); | ||
| 6148 | } | ||
| 6149 | |||
| 6150 | /** | ||
| 6151 | * _scsih_shutdown - routine call during system shutdown | ||
| 6152 | * @pdev: PCI device struct | ||
| 6153 | * | ||
| 6154 | * Return nothing. | ||
| 6155 | */ | ||
| 6156 | static void | ||
| 6157 | _scsih_shutdown(struct pci_dev *pdev) | ||
| 6158 | { | ||
| 6159 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | ||
| 6160 | struct MPT2SAS_ADAPTER *ioc = shost_priv(shost); | ||
| 6161 | |||
| 6162 | _scsih_ir_shutdown(ioc); | ||
| 6163 | mpt2sas_base_detach(ioc); | ||
| 6164 | } | ||
| 6165 | |||
| 6166 | /** | ||
| 5693 | * _scsih_remove - detach and remove add host | 6167 | * _scsih_remove - detach and remove add host |
| 5694 | * @pdev: PCI device struct | 6168 | * @pdev: PCI device struct |
| 5695 | * | 6169 | * |
| 6170 | * Routine called when unloading the driver. | ||
| 5696 | * Return nothing. | 6171 | * Return nothing. |
| 5697 | */ | 6172 | */ |
| 5698 | static void __devexit | 6173 | static void __devexit |
| @@ -5703,6 +6178,8 @@ _scsih_remove(struct pci_dev *pdev) | |||
| 5703 | struct _sas_port *mpt2sas_port; | 6178 | struct _sas_port *mpt2sas_port; |
| 5704 | struct _sas_device *sas_device; | 6179 | struct _sas_device *sas_device; |
| 5705 | struct _sas_node *expander_sibling; | 6180 | struct _sas_node *expander_sibling; |
| 6181 | struct _raid_device *raid_device, *next; | ||
| 6182 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
| 5706 | struct workqueue_struct *wq; | 6183 | struct workqueue_struct *wq; |
| 5707 | unsigned long flags; | 6184 | unsigned long flags; |
| 5708 | 6185 | ||
| @@ -5716,6 +6193,21 @@ _scsih_remove(struct pci_dev *pdev) | |||
| 5716 | if (wq) | 6193 | if (wq) |
| 5717 | destroy_workqueue(wq); | 6194 | destroy_workqueue(wq); |
| 5718 | 6195 | ||
| 6196 | /* release all the volumes */ | ||
| 6197 | list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list, | ||
| 6198 | list) { | ||
| 6199 | if (raid_device->starget) { | ||
| 6200 | sas_target_priv_data = | ||
| 6201 | raid_device->starget->hostdata; | ||
| 6202 | sas_target_priv_data->deleted = 1; | ||
| 6203 | scsi_remove_target(&raid_device->starget->dev); | ||
| 6204 | } | ||
| 6205 | printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid" | ||
| 6206 | "(0x%016llx)\n", ioc->name, raid_device->handle, | ||
| 6207 | (unsigned long long) raid_device->wwid); | ||
| 6208 | _scsih_raid_device_remove(ioc, raid_device); | ||
| 6209 | } | ||
| 6210 | |||
| 5719 | /* free ports attached to the sas_host */ | 6211 | /* free ports attached to the sas_host */ |
| 5720 | retry_again: | 6212 | retry_again: |
| 5721 | list_for_each_entry(mpt2sas_port, | 6213 | list_for_each_entry(mpt2sas_port, |
| @@ -5726,7 +6218,7 @@ _scsih_remove(struct pci_dev *pdev) | |||
| 5726 | mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 6218 | mpt2sas_scsih_sas_device_find_by_sas_address(ioc, |
| 5727 | mpt2sas_port->remote_identify.sas_address); | 6219 | mpt2sas_port->remote_identify.sas_address); |
| 5728 | if (sas_device) { | 6220 | if (sas_device) { |
| 5729 | _scsih_remove_device(ioc, sas_device->handle); | 6221 | _scsih_remove_device(ioc, sas_device); |
| 5730 | goto retry_again; | 6222 | goto retry_again; |
| 5731 | } | 6223 | } |
| 5732 | } else { | 6224 | } else { |
| @@ -5735,7 +6227,7 @@ _scsih_remove(struct pci_dev *pdev) | |||
| 5735 | mpt2sas_port->remote_identify.sas_address); | 6227 | mpt2sas_port->remote_identify.sas_address); |
| 5736 | if (expander_sibling) { | 6228 | if (expander_sibling) { |
| 5737 | _scsih_expander_remove(ioc, | 6229 | _scsih_expander_remove(ioc, |
| 5738 | expander_sibling->handle); | 6230 | expander_sibling->sas_address); |
| 5739 | goto retry_again; | 6231 | goto retry_again; |
| 5740 | } | 6232 | } |
| 5741 | } | 6233 | } |
| @@ -5749,7 +6241,7 @@ _scsih_remove(struct pci_dev *pdev) | |||
| 5749 | } | 6241 | } |
| 5750 | 6242 | ||
| 5751 | sas_remove_host(shost); | 6243 | sas_remove_host(shost); |
| 5752 | mpt2sas_base_detach(ioc); | 6244 | _scsih_shutdown(pdev); |
| 5753 | list_del(&ioc->list); | 6245 | list_del(&ioc->list); |
| 5754 | scsi_remove_host(shost); | 6246 | scsi_remove_host(shost); |
| 5755 | scsi_host_put(shost); | 6247 | scsi_host_put(shost); |
| @@ -5770,7 +6262,8 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 5770 | void *device; | 6262 | void *device; |
| 5771 | struct _sas_device *sas_device; | 6263 | struct _sas_device *sas_device; |
| 5772 | struct _raid_device *raid_device; | 6264 | struct _raid_device *raid_device; |
| 5773 | u16 handle, parent_handle; | 6265 | u16 handle; |
| 6266 | u64 sas_address_parent; | ||
| 5774 | u64 sas_address; | 6267 | u64 sas_address; |
| 5775 | unsigned long flags; | 6268 | unsigned long flags; |
| 5776 | int rc; | 6269 | int rc; |
| @@ -5799,17 +6292,17 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 5799 | } else { | 6292 | } else { |
| 5800 | sas_device = device; | 6293 | sas_device = device; |
| 5801 | handle = sas_device->handle; | 6294 | handle = sas_device->handle; |
| 5802 | parent_handle = sas_device->parent_handle; | 6295 | sas_address_parent = sas_device->sas_address_parent; |
| 5803 | sas_address = sas_device->sas_address; | 6296 | sas_address = sas_device->sas_address; |
| 5804 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6297 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 5805 | list_move_tail(&sas_device->list, &ioc->sas_device_list); | 6298 | list_move_tail(&sas_device->list, &ioc->sas_device_list); |
| 5806 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 6299 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 5807 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, | 6300 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, |
| 5808 | sas_device->parent_handle)) { | 6301 | sas_device->sas_address_parent)) { |
| 5809 | _scsih_sas_device_remove(ioc, sas_device); | 6302 | _scsih_sas_device_remove(ioc, sas_device); |
| 5810 | } else if (!sas_device->starget) { | 6303 | } else if (!sas_device->starget) { |
| 5811 | mpt2sas_transport_port_remove(ioc, sas_address, | 6304 | mpt2sas_transport_port_remove(ioc, sas_address, |
| 5812 | parent_handle); | 6305 | sas_address_parent); |
| 5813 | _scsih_sas_device_remove(ioc, sas_device); | 6306 | _scsih_sas_device_remove(ioc, sas_device); |
| 5814 | } | 6307 | } |
| 5815 | } | 6308 | } |
| @@ -5849,8 +6342,6 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc) | |||
| 5849 | { | 6342 | { |
| 5850 | struct _sas_device *sas_device, *next; | 6343 | struct _sas_device *sas_device, *next; |
| 5851 | unsigned long flags; | 6344 | unsigned long flags; |
| 5852 | u16 handle, parent_handle; | ||
| 5853 | u64 sas_address; | ||
| 5854 | 6345 | ||
| 5855 | /* SAS Device List */ | 6346 | /* SAS Device List */ |
| 5856 | list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list, | 6347 | list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list, |
| @@ -5859,14 +6350,13 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc) | |||
| 5859 | list_move_tail(&sas_device->list, &ioc->sas_device_list); | 6350 | list_move_tail(&sas_device->list, &ioc->sas_device_list); |
| 5860 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 6351 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 5861 | 6352 | ||
| 5862 | handle = sas_device->handle; | 6353 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, |
| 5863 | parent_handle = sas_device->parent_handle; | 6354 | 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); | 6355 | _scsih_sas_device_remove(ioc, sas_device); |
| 5867 | } else if (!sas_device->starget) { | 6356 | } else if (!sas_device->starget) { |
| 5868 | mpt2sas_transport_port_remove(ioc, sas_address, | 6357 | mpt2sas_transport_port_remove(ioc, |
| 5869 | parent_handle); | 6358 | sas_device->sas_address, |
| 6359 | sas_device->sas_address_parent); | ||
| 5870 | _scsih_sas_device_remove(ioc, sas_device); | 6360 | _scsih_sas_device_remove(ioc, sas_device); |
| 5871 | } | 6361 | } |
| 5872 | } | 6362 | } |
| @@ -5935,6 +6425,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 5935 | ioc->ctl_cb_idx = ctl_cb_idx; | 6425 | ioc->ctl_cb_idx = ctl_cb_idx; |
| 5936 | ioc->base_cb_idx = base_cb_idx; | 6426 | ioc->base_cb_idx = base_cb_idx; |
| 5937 | ioc->transport_cb_idx = transport_cb_idx; | 6427 | ioc->transport_cb_idx = transport_cb_idx; |
| 6428 | ioc->scsih_cb_idx = scsih_cb_idx; | ||
| 5938 | ioc->config_cb_idx = config_cb_idx; | 6429 | ioc->config_cb_idx = config_cb_idx; |
| 5939 | ioc->tm_tr_cb_idx = tm_tr_cb_idx; | 6430 | ioc->tm_tr_cb_idx = tm_tr_cb_idx; |
| 5940 | ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; | 6431 | ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; |
| @@ -6072,12 +6563,20 @@ static struct pci_driver scsih_driver = { | |||
| 6072 | .id_table = scsih_pci_table, | 6563 | .id_table = scsih_pci_table, |
| 6073 | .probe = _scsih_probe, | 6564 | .probe = _scsih_probe, |
| 6074 | .remove = __devexit_p(_scsih_remove), | 6565 | .remove = __devexit_p(_scsih_remove), |
| 6566 | .shutdown = _scsih_shutdown, | ||
| 6075 | #ifdef CONFIG_PM | 6567 | #ifdef CONFIG_PM |
| 6076 | .suspend = _scsih_suspend, | 6568 | .suspend = _scsih_suspend, |
| 6077 | .resume = _scsih_resume, | 6569 | .resume = _scsih_resume, |
| 6078 | #endif | 6570 | #endif |
| 6079 | }; | 6571 | }; |
| 6080 | 6572 | ||
| 6573 | /* raid transport support */ | ||
| 6574 | static struct raid_function_template mpt2sas_raid_functions = { | ||
| 6575 | .cookie = &scsih_driver_template, | ||
| 6576 | .is_raid = _scsih_is_raid, | ||
| 6577 | .get_resync = _scsih_get_resync, | ||
| 6578 | .get_state = _scsih_get_state, | ||
| 6579 | }; | ||
| 6081 | 6580 | ||
| 6082 | /** | 6581 | /** |
| 6083 | * _scsih_init - main entry point for this driver. | 6582 | * _scsih_init - main entry point for this driver. |
| @@ -6097,6 +6596,12 @@ _scsih_init(void) | |||
| 6097 | sas_attach_transport(&mpt2sas_transport_functions); | 6596 | sas_attach_transport(&mpt2sas_transport_functions); |
| 6098 | if (!mpt2sas_transport_template) | 6597 | if (!mpt2sas_transport_template) |
| 6099 | return -ENODEV; | 6598 | return -ENODEV; |
| 6599 | /* raid transport support */ | ||
| 6600 | mpt2sas_raid_template = raid_class_attach(&mpt2sas_raid_functions); | ||
| 6601 | if (!mpt2sas_raid_template) { | ||
| 6602 | sas_release_transport(mpt2sas_transport_template); | ||
| 6603 | return -ENODEV; | ||
| 6604 | } | ||
| 6100 | 6605 | ||
| 6101 | mpt2sas_base_initialize_callback_handler(); | 6606 | mpt2sas_base_initialize_callback_handler(); |
| 6102 | 6607 | ||
| @@ -6113,6 +6618,9 @@ _scsih_init(void) | |||
| 6113 | transport_cb_idx = mpt2sas_base_register_callback_handler( | 6618 | transport_cb_idx = mpt2sas_base_register_callback_handler( |
| 6114 | mpt2sas_transport_done); | 6619 | mpt2sas_transport_done); |
| 6115 | 6620 | ||
| 6621 | /* scsih internal commands callback handler */ | ||
| 6622 | scsih_cb_idx = mpt2sas_base_register_callback_handler(_scsih_done); | ||
| 6623 | |||
| 6116 | /* configuration page API internal commands callback handler */ | 6624 | /* configuration page API internal commands callback handler */ |
| 6117 | config_cb_idx = mpt2sas_base_register_callback_handler( | 6625 | config_cb_idx = mpt2sas_base_register_callback_handler( |
| 6118 | mpt2sas_config_done); | 6626 | mpt2sas_config_done); |
| @@ -6128,8 +6636,11 @@ _scsih_init(void) | |||
| 6128 | mpt2sas_ctl_init(); | 6636 | mpt2sas_ctl_init(); |
| 6129 | 6637 | ||
| 6130 | error = pci_register_driver(&scsih_driver); | 6638 | error = pci_register_driver(&scsih_driver); |
| 6131 | if (error) | 6639 | if (error) { |
| 6640 | /* raid transport support */ | ||
| 6641 | raid_class_release(mpt2sas_raid_template); | ||
| 6132 | sas_release_transport(mpt2sas_transport_template); | 6642 | sas_release_transport(mpt2sas_transport_template); |
| 6643 | } | ||
| 6133 | 6644 | ||
| 6134 | return error; | 6645 | return error; |
| 6135 | } | 6646 | } |
| @@ -6147,18 +6658,23 @@ _scsih_exit(void) | |||
| 6147 | 6658 | ||
| 6148 | pci_unregister_driver(&scsih_driver); | 6659 | pci_unregister_driver(&scsih_driver); |
| 6149 | 6660 | ||
| 6150 | sas_release_transport(mpt2sas_transport_template); | 6661 | mpt2sas_ctl_exit(); |
| 6662 | |||
| 6151 | mpt2sas_base_release_callback_handler(scsi_io_cb_idx); | 6663 | mpt2sas_base_release_callback_handler(scsi_io_cb_idx); |
| 6152 | mpt2sas_base_release_callback_handler(tm_cb_idx); | 6664 | mpt2sas_base_release_callback_handler(tm_cb_idx); |
| 6153 | mpt2sas_base_release_callback_handler(base_cb_idx); | 6665 | mpt2sas_base_release_callback_handler(base_cb_idx); |
| 6154 | mpt2sas_base_release_callback_handler(transport_cb_idx); | 6666 | mpt2sas_base_release_callback_handler(transport_cb_idx); |
| 6667 | mpt2sas_base_release_callback_handler(scsih_cb_idx); | ||
| 6155 | mpt2sas_base_release_callback_handler(config_cb_idx); | 6668 | mpt2sas_base_release_callback_handler(config_cb_idx); |
| 6156 | mpt2sas_base_release_callback_handler(ctl_cb_idx); | 6669 | mpt2sas_base_release_callback_handler(ctl_cb_idx); |
| 6157 | 6670 | ||
| 6158 | mpt2sas_base_release_callback_handler(tm_tr_cb_idx); | 6671 | mpt2sas_base_release_callback_handler(tm_tr_cb_idx); |
| 6159 | mpt2sas_base_release_callback_handler(tm_sas_control_cb_idx); | 6672 | mpt2sas_base_release_callback_handler(tm_sas_control_cb_idx); |
| 6160 | 6673 | ||
| 6161 | mpt2sas_ctl_exit(); | 6674 | /* raid transport support */ |
| 6675 | raid_class_release(mpt2sas_raid_template); | ||
| 6676 | sas_release_transport(mpt2sas_transport_template); | ||
| 6677 | |||
| 6162 | } | 6678 | } |
| 6163 | 6679 | ||
| 6164 | module_init(_scsih_init); | 6680 | module_init(_scsih_init); |
