aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt2sas
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/mpt2sas')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h20
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c373
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c72
3 files changed, 255 insertions, 210 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index 0cf6bc236e4d..fa99ff204e46 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -278,7 +278,7 @@ struct _internal_cmd {
278 * @sas_address: device sas address 278 * @sas_address: device sas address
279 * @device_name: retrieved from the SAS IDENTIFY frame. 279 * @device_name: retrieved from the SAS IDENTIFY frame.
280 * @handle: device handle 280 * @handle: device handle
281 * @parent_handle: handle to parent device 281 * @sas_address_parent: sas address of parent expander or sas host
282 * @enclosure_handle: enclosure handle 282 * @enclosure_handle: enclosure handle
283 * @enclosure_logical_id: enclosure logical identifier 283 * @enclosure_logical_id: enclosure logical identifier
284 * @volume_handle: volume handle (valid when hidden raid member) 284 * @volume_handle: volume handle (valid when hidden raid member)
@@ -296,7 +296,7 @@ struct _sas_device {
296 u64 sas_address; 296 u64 sas_address;
297 u64 device_name; 297 u64 device_name;
298 u16 handle; 298 u16 handle;
299 u16 parent_handle; 299 u64 sas_address_parent;
300 u16 enclosure_handle; 300 u16 enclosure_handle;
301 u64 enclosure_logical_id; 301 u64 enclosure_logical_id;
302 u16 volume_handle; 302 u16 volume_handle;
@@ -352,8 +352,6 @@ struct _boot_device {
352/** 352/**
353 * struct _sas_port - wide/narrow sas port information 353 * struct _sas_port - wide/narrow sas port information
354 * @port_list: list of ports belonging to expander 354 * @port_list: list of ports belonging to expander
355 * @handle: device handle for this port
356 * @sas_address: sas address of this port
357 * @num_phys: number of phys belonging to this port 355 * @num_phys: number of phys belonging to this port
358 * @remote_identify: attached device identification 356 * @remote_identify: attached device identification
359 * @rphy: sas transport rphy object 357 * @rphy: sas transport rphy object
@@ -362,8 +360,6 @@ struct _boot_device {
362 */ 360 */
363struct _sas_port { 361struct _sas_port {
364 struct list_head port_list; 362 struct list_head port_list;
365 u16 handle;
366 u64 sas_address;
367 u8 num_phys; 363 u8 num_phys;
368 struct sas_identify remote_identify; 364 struct sas_identify remote_identify;
369 struct sas_rphy *rphy; 365 struct sas_rphy *rphy;
@@ -398,7 +394,7 @@ struct _sas_phy {
398 * @num_phys: number phys belonging to this sas_host/expander 394 * @num_phys: number phys belonging to this sas_host/expander
399 * @sas_address: sas address of this sas_host/expander 395 * @sas_address: sas address of this sas_host/expander
400 * @handle: handle for this sas_host/expander 396 * @handle: handle for this sas_host/expander
401 * @parent_handle: parent handle 397 * @sas_address_parent: sas address of parent expander or sas host
402 * @enclosure_handle: handle for this a member of an enclosure 398 * @enclosure_handle: handle for this a member of an enclosure
403 * @device_info: bitwise defining capabilities of this sas_host/expander 399 * @device_info: bitwise defining capabilities of this sas_host/expander
404 * @responding: used in _scsih_expander_device_mark_responding 400 * @responding: used in _scsih_expander_device_mark_responding
@@ -411,7 +407,7 @@ struct _sas_node {
411 u8 num_phys; 407 u8 num_phys;
412 u64 sas_address; 408 u64 sas_address;
413 u16 handle; 409 u16 handle;
414 u16 parent_handle; 410 u64 sas_address_parent;
415 u16 enclosure_handle; 411 u16 enclosure_handle;
416 u64 enclosure_logical_id; 412 u64 enclosure_logical_id;
417 u8 responding; 413 u8 responding;
@@ -890,15 +886,15 @@ void mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc,
890u8 mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, 886u8 mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
891 u32 reply); 887 u32 reply);
892struct _sas_port *mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, 888struct _sas_port *mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc,
893 u16 handle, u16 parent_handle); 889 u16 handle, u64 sas_address);
894void mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, 890void mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
895 u16 parent_handle); 891 u64 sas_address_parent);
896int mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy 892int mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
897 *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev); 893 *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev);
898int mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy 894int mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
899 *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev); 895 *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev);
900void mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc, u16 handle, 896void mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
901 u16 attached_handle, u8 phy_number, u8 link_rate); 897 u64 sas_address, u16 handle, u8 phy_number, u8 link_rate);
902extern struct sas_function_template mpt2sas_transport_functions; 898extern struct sas_function_template mpt2sas_transport_functions;
903extern struct scsi_transport_template *mpt2sas_transport_template; 899extern struct scsi_transport_template *mpt2sas_transport_template;
904extern int scsi_internal_device_block(struct scsi_device *sdev); 900extern int scsi_internal_device_block(struct scsi_device *sdev);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 86ab32d7ab15..8822cda852ba 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -317,6 +317,47 @@ _scsih_is_boot_device(u64 sas_address, u64 device_name,
317} 317}
318 318
319/** 319/**
320 * _scsih_get_sas_address - set the sas_address for given device handle
321 * @handle: device handle
322 * @sas_address: sas address
323 *
324 * Returns 0 success, non-zero when failure
325 */
326static int
327_scsih_get_sas_address(struct MPT2SAS_ADAPTER *ioc, u16 handle,
328 u64 *sas_address)
329{
330 Mpi2SasDevicePage0_t sas_device_pg0;
331 Mpi2ConfigReply_t mpi_reply;
332 u32 ioc_status;
333
334 if (handle <= ioc->sas_hba.num_phys) {
335 *sas_address = ioc->sas_hba.sas_address;
336 return 0;
337 } else
338 *sas_address = 0;
339
340 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
341 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
342 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
343 ioc->name, __FILE__, __LINE__, __func__);
344 return -ENXIO;
345 }
346
347 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
348 MPI2_IOCSTATUS_MASK;
349 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
350 printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)"
351 "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
352 __FILE__, __LINE__, __func__);
353 return -EIO;
354 }
355
356 *sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
357 return 0;
358}
359
360/**
320 * _scsih_determine_boot_device - determine boot device. 361 * _scsih_determine_boot_device - determine boot device.
321 * @ioc: per adapter object 362 * @ioc: per adapter object
322 * @device: either sas_device or raid_device object 363 * @device: either sas_device or raid_device object
@@ -510,8 +551,6 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc,
510 struct _sas_device *sas_device) 551 struct _sas_device *sas_device)
511{ 552{
512 unsigned long flags; 553 unsigned long flags;
513 u16 handle, parent_handle;
514 u64 sas_address;
515 554
516 dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle" 555 dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle"
517 "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, 556 "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
@@ -521,10 +560,8 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc,
521 list_add_tail(&sas_device->list, &ioc->sas_device_list); 560 list_add_tail(&sas_device->list, &ioc->sas_device_list);
522 spin_unlock_irqrestore(&ioc->sas_device_lock, flags); 561 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
523 562
524 handle = sas_device->handle; 563 if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
525 parent_handle = sas_device->parent_handle; 564 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); 565 _scsih_sas_device_remove(ioc, sas_device);
529} 566}
530 567
@@ -553,31 +590,6 @@ _scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc,
553} 590}
554 591
555/** 592/**
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 */
564struct _sas_node *
565mpt2sas_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 593 * _scsih_raid_device_find_by_id - raid device search
582 * @ioc: per adapter object 594 * @ioc: per adapter object
583 * @id: sas device target id 595 * @id: sas device target id
@@ -699,6 +711,31 @@ _scsih_raid_device_remove(struct MPT2SAS_ADAPTER *ioc,
699} 711}
700 712
701/** 713/**
714 * mpt2sas_scsih_expander_find_by_handle - expander device search
715 * @ioc: per adapter object
716 * @handle: expander handle (assigned by firmware)
717 * Context: Calling function should acquire ioc->sas_device_lock
718 *
719 * This searches for expander device based on handle, then returns the
720 * sas_node object.
721 */
722struct _sas_node *
723mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
724{
725 struct _sas_node *sas_expander, *r;
726
727 r = NULL;
728 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
729 if (sas_expander->handle != handle)
730 continue;
731 r = sas_expander;
732 goto out;
733 }
734 out:
735 return r;
736}
737
738/**
702 * mpt2sas_scsih_expander_find_by_sas_address - expander device search 739 * mpt2sas_scsih_expander_find_by_sas_address - expander device search
703 * @ioc: per adapter object 740 * @ioc: per adapter object
704 * @sas_address: sas address 741 * @sas_address: sas address
@@ -3344,7 +3381,6 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
3344/** 3381/**
3345 * _scsih_sas_host_refresh - refreshing sas host object contents 3382 * _scsih_sas_host_refresh - refreshing sas host object contents
3346 * @ioc: per adapter object 3383 * @ioc: per adapter object
3347 * @update: update link information
3348 * Context: user 3384 * Context: user
3349 * 3385 *
3350 * During port enable, fw will send topology events for every device. Its 3386 * During port enable, fw will send topology events for every device. Its
@@ -3354,13 +3390,14 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
3354 * Return nothing. 3390 * Return nothing.
3355 */ 3391 */
3356static void 3392static void
3357_scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc, u8 update) 3393_scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc)
3358{ 3394{
3359 u16 sz; 3395 u16 sz;
3360 u16 ioc_status; 3396 u16 ioc_status;
3361 int i; 3397 int i;
3362 Mpi2ConfigReply_t mpi_reply; 3398 Mpi2ConfigReply_t mpi_reply;
3363 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; 3399 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
3400 u16 attached_handle;
3364 3401
3365 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT 3402 dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
3366 "updating handles for sas_host(0x%016llx)\n", 3403 "updating handles for sas_host(0x%016llx)\n",
@@ -3374,27 +3411,24 @@ _scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc, u8 update)
3374 ioc->name, __FILE__, __LINE__, __func__); 3411 ioc->name, __FILE__, __LINE__, __func__);
3375 return; 3412 return;
3376 } 3413 }
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 3414
3415 if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
3416 sas_iounit_pg0, sz)) != 0)
3417 goto out;
3418 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
3419 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
3420 goto out;
3421 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
3422 if (i == 0)
3423 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
3424 PhyData[0].ControllerDevHandle);
3425 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
3426 attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
3427 AttachedDevHandle);
3428 mpt2sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
3429 attached_handle, i, sas_iounit_pg0->PhyData[i].
3430 NegotiatedLinkRate >> 4);
3431 }
3398 out: 3432 out:
3399 kfree(sas_iounit_pg0); 3433 kfree(sas_iounit_pg0);
3400} 3434}
@@ -3507,19 +3541,21 @@ _scsih_sas_host_add(struct MPT2SAS_ADAPTER *ioc)
3507 ioc->name, __FILE__, __LINE__, __func__); 3541 ioc->name, __FILE__, __LINE__, __func__);
3508 goto out; 3542 goto out;
3509 } 3543 }
3510 ioc->sas_hba.phy[i].handle = 3544
3511 le16_to_cpu(sas_iounit_pg0->PhyData[i].ControllerDevHandle); 3545 if (i == 0)
3546 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
3547 PhyData[0].ControllerDevHandle);
3548 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
3512 ioc->sas_hba.phy[i].phy_id = i; 3549 ioc->sas_hba.phy[i].phy_id = i;
3513 mpt2sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i], 3550 mpt2sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i],
3514 phy_pg0, ioc->sas_hba.parent_dev); 3551 phy_pg0, ioc->sas_hba.parent_dev);
3515 } 3552 }
3516 if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, 3553 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))) { 3554 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) {
3518 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", 3555 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3519 ioc->name, __FILE__, __LINE__, __func__); 3556 ioc->name, __FILE__, __LINE__, __func__);
3520 goto out; 3557 goto out;
3521 } 3558 }
3522 ioc->sas_hba.handle = le16_to_cpu(sas_device_pg0.DevHandle);
3523 ioc->sas_hba.enclosure_handle = 3559 ioc->sas_hba.enclosure_handle =
3524 le16_to_cpu(sas_device_pg0.EnclosureHandle); 3560 le16_to_cpu(sas_device_pg0.EnclosureHandle);
3525 ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress); 3561 ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
@@ -3562,7 +3598,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3562 Mpi2SasEnclosurePage0_t enclosure_pg0; 3598 Mpi2SasEnclosurePage0_t enclosure_pg0;
3563 u32 ioc_status; 3599 u32 ioc_status;
3564 u16 parent_handle; 3600 u16 parent_handle;
3565 __le64 sas_address; 3601 __le64 sas_address, sas_address_parent = 0;
3566 int i; 3602 int i;
3567 unsigned long flags; 3603 unsigned long flags;
3568 struct _sas_port *mpt2sas_port = NULL; 3604 struct _sas_port *mpt2sas_port = NULL;
@@ -3591,10 +3627,16 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3591 3627
3592 /* handle out of order topology events */ 3628 /* handle out of order topology events */
3593 parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle); 3629 parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle);
3594 if (parent_handle >= ioc->sas_hba.num_phys) { 3630 if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent)
3631 != 0) {
3632 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3633 ioc->name, __FILE__, __LINE__, __func__);
3634 return -1;
3635 }
3636 if (sas_address_parent != ioc->sas_hba.sas_address) {
3595 spin_lock_irqsave(&ioc->sas_node_lock, flags); 3637 spin_lock_irqsave(&ioc->sas_node_lock, flags);
3596 sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, 3638 sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
3597 parent_handle); 3639 sas_address_parent);
3598 spin_unlock_irqrestore(&ioc->sas_node_lock, flags); 3640 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
3599 if (!sas_expander) { 3641 if (!sas_expander) {
3600 rc = _scsih_expander_add(ioc, parent_handle); 3642 rc = _scsih_expander_add(ioc, parent_handle);
@@ -3622,14 +3664,12 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3622 3664
3623 sas_expander->handle = handle; 3665 sas_expander->handle = handle;
3624 sas_expander->num_phys = expander_pg0.NumPhys; 3666 sas_expander->num_phys = expander_pg0.NumPhys;
3625 sas_expander->parent_handle = parent_handle; 3667 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; 3668 sas_expander->sas_address = sas_address;
3629 3669
3630 printk(MPT2SAS_INFO_FMT "expander_add: handle(0x%04x)," 3670 printk(MPT2SAS_INFO_FMT "expander_add: handle(0x%04x),"
3631 " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name, 3671 " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name,
3632 handle, sas_expander->parent_handle, (unsigned long long) 3672 handle, parent_handle, (unsigned long long)
3633 sas_expander->sas_address, sas_expander->num_phys); 3673 sas_expander->sas_address, sas_expander->num_phys);
3634 3674
3635 if (!sas_expander->num_phys) 3675 if (!sas_expander->num_phys)
@@ -3645,7 +3685,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3645 3685
3646 INIT_LIST_HEAD(&sas_expander->sas_port_list); 3686 INIT_LIST_HEAD(&sas_expander->sas_port_list);
3647 mpt2sas_port = mpt2sas_transport_port_add(ioc, handle, 3687 mpt2sas_port = mpt2sas_transport_port_add(ioc, handle,
3648 sas_expander->parent_handle); 3688 sas_address_parent);
3649 if (!mpt2sas_port) { 3689 if (!mpt2sas_port) {
3650 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", 3690 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3651 ioc->name, __FILE__, __LINE__, __func__); 3691 ioc->name, __FILE__, __LINE__, __func__);
@@ -3691,7 +3731,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3691 3731
3692 if (mpt2sas_port) 3732 if (mpt2sas_port)
3693 mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, 3733 mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
3694 sas_expander->parent_handle); 3734 sas_address_parent);
3695 kfree(sas_expander); 3735 kfree(sas_expander);
3696 return rc; 3736 return rc;
3697} 3737}
@@ -3699,12 +3739,12 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3699/** 3739/**
3700 * _scsih_expander_remove - removing expander object 3740 * _scsih_expander_remove - removing expander object
3701 * @ioc: per adapter object 3741 * @ioc: per adapter object
3702 * @handle: expander handle 3742 * @sas_address: expander sas_address
3703 * 3743 *
3704 * Return nothing. 3744 * Return nothing.
3705 */ 3745 */
3706static void 3746static void
3707_scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u16 handle) 3747_scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
3708{ 3748{
3709 struct _sas_node *sas_expander; 3749 struct _sas_node *sas_expander;
3710 unsigned long flags; 3750 unsigned long flags;
@@ -3713,7 +3753,8 @@ _scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3713 return; 3753 return;
3714 3754
3715 spin_lock_irqsave(&ioc->sas_node_lock, flags); 3755 spin_lock_irqsave(&ioc->sas_node_lock, flags);
3716 sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, handle); 3756 sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
3757 sas_address);
3717 spin_unlock_irqrestore(&ioc->sas_node_lock, flags); 3758 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
3718 _scsih_expander_node_remove(ioc, sas_expander); 3759 _scsih_expander_node_remove(ioc, sas_expander);
3719} 3760}
@@ -3805,8 +3846,11 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd)
3805 } 3846 }
3806 3847
3807 sas_device->handle = handle; 3848 sas_device->handle = handle;
3808 sas_device->parent_handle = 3849 if (_scsih_get_sas_address(ioc, le16_to_cpu
3809 le16_to_cpu(sas_device_pg0.ParentDevHandle); 3850 (sas_device_pg0.ParentDevHandle),
3851 &sas_device->sas_address_parent) != 0)
3852 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3853 ioc->name, __FILE__, __LINE__, __func__);
3810 sas_device->enclosure_handle = 3854 sas_device->enclosure_handle =
3811 le16_to_cpu(sas_device_pg0.EnclosureHandle); 3855 le16_to_cpu(sas_device_pg0.EnclosureHandle);
3812 sas_device->slot = 3856 sas_device->slot =
@@ -3836,43 +3880,39 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd)
3836/** 3880/**
3837 * _scsih_remove_device - removing sas device object 3881 * _scsih_remove_device - removing sas device object
3838 * @ioc: per adapter object 3882 * @ioc: per adapter object
3839 * @handle: sas device handle 3883 * @sas_device: the sas_device object
3840 * 3884 *
3841 * Return nothing. 3885 * Return nothing.
3842 */ 3886 */
3843static void 3887static void
3844_scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) 3888_scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, struct _sas_device
3889 *sas_device)
3845{ 3890{
3846 struct MPT2SAS_TARGET *sas_target_priv_data; 3891 struct MPT2SAS_TARGET *sas_target_priv_data;
3847 struct _sas_device *sas_device;
3848 unsigned long flags;
3849 Mpi2SasIoUnitControlReply_t mpi_reply; 3892 Mpi2SasIoUnitControlReply_t mpi_reply;
3850 Mpi2SasIoUnitControlRequest_t mpi_request; 3893 Mpi2SasIoUnitControlRequest_t mpi_request;
3851 u16 device_handle; 3894 u16 device_handle, handle;
3852 3895
3853 /* lookup sas_device */ 3896 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; 3897 return;
3859 }
3860 3898
3861 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: handle" 3899 handle = sas_device->handle;
3862 "(0x%04x)\n", ioc->name, __func__, handle)); 3900 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: handle(0x%04x),"
3901 " sas_addr(0x%016llx)\n", ioc->name, __func__, handle,
3902 (unsigned long long) sas_device->sas_address));
3863 3903
3864 if (sas_device->starget && sas_device->starget->hostdata) { 3904 if (sas_device->starget && sas_device->starget->hostdata) {
3865 sas_target_priv_data = sas_device->starget->hostdata; 3905 sas_target_priv_data = sas_device->starget->hostdata;
3866 sas_target_priv_data->deleted = 1; 3906 sas_target_priv_data->deleted = 1;
3867 } 3907 }
3868 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
3869 3908
3870 if (ioc->remove_host) 3909 if (ioc->remove_host || ioc->shost_recovery || !handle)
3871 goto out; 3910 goto out;
3872 3911
3873 if ((sas_device->state & MPTSAS_STATE_TR_COMPLETE)) { 3912 if ((sas_device->state & MPTSAS_STATE_TR_COMPLETE)) {
3874 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "\tskip " 3913 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "\tskip "
3875 "target_reset handle(0x%04x)\n", ioc->name, handle)); 3914 "target_reset handle(0x%04x)\n", ioc->name,
3915 handle));
3876 goto skip_tr; 3916 goto skip_tr;
3877 } 3917 }
3878 3918
@@ -3925,10 +3965,10 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3925 _scsih_ublock_io_device(ioc, handle); 3965 _scsih_ublock_io_device(ioc, handle);
3926 3966
3927 mpt2sas_transport_port_remove(ioc, sas_device->sas_address, 3967 mpt2sas_transport_port_remove(ioc, sas_device->sas_address,
3928 sas_device->parent_handle); 3968 sas_device->sas_address_parent);
3929 3969
3930 printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr" 3970 printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr"
3931 "(0x%016llx)\n", ioc->name, sas_device->handle, 3971 "(0x%016llx)\n", ioc->name, handle,
3932 (unsigned long long) sas_device->sas_address); 3972 (unsigned long long) sas_device->sas_address);
3933 _scsih_sas_device_remove(ioc, sas_device); 3973 _scsih_sas_device_remove(ioc, sas_device);
3934 3974
@@ -4031,8 +4071,10 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
4031 u16 reason_code; 4071 u16 reason_code;
4032 u8 phy_number; 4072 u8 phy_number;
4033 struct _sas_node *sas_expander; 4073 struct _sas_node *sas_expander;
4074 struct _sas_device *sas_device;
4075 u64 sas_address;
4034 unsigned long flags; 4076 unsigned long flags;
4035 u8 link_rate_; 4077 u8 link_rate;
4036 Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data; 4078 Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data;
4037 4079
4038#ifdef CONFIG_SCSI_MPT2SAS_LOGGING 4080#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
@@ -4040,10 +4082,13 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
4040 _scsih_sas_topology_change_event_debug(ioc, event_data); 4082 _scsih_sas_topology_change_event_debug(ioc, event_data);
4041#endif 4083#endif
4042 4084
4085 if (ioc->shost_recovery)
4086 return;
4087
4043 if (!ioc->sas_hba.num_phys) 4088 if (!ioc->sas_hba.num_phys)
4044 _scsih_sas_host_add(ioc); 4089 _scsih_sas_host_add(ioc);
4045 else 4090 else
4046 _scsih_sas_host_refresh(ioc, 0); 4091 _scsih_sas_host_refresh(ioc);
4047 4092
4048 if (fw_event->ignore) { 4093 if (fw_event->ignore) {
4049 dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ignoring expander " 4094 dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ignoring expander "
@@ -4058,6 +4103,17 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
4058 if (_scsih_expander_add(ioc, parent_handle) != 0) 4103 if (_scsih_expander_add(ioc, parent_handle) != 0)
4059 return; 4104 return;
4060 4105
4106 spin_lock_irqsave(&ioc->sas_node_lock, flags);
4107 sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
4108 parent_handle);
4109 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4110 if (sas_expander)
4111 sas_address = sas_expander->sas_address;
4112 else if (parent_handle < ioc->sas_hba.num_phys)
4113 sas_address = ioc->sas_hba.sas_address;
4114 else
4115 return;
4116
4061 /* handle siblings events */ 4117 /* handle siblings events */
4062 for (i = 0; i < event_data->NumEntries; i++) { 4118 for (i = 0; i < event_data->NumEntries; i++) {
4063 if (fw_event->ignore) { 4119 if (fw_event->ignore) {
@@ -4077,48 +4133,40 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
4077 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); 4133 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
4078 if (!handle) 4134 if (!handle)
4079 continue; 4135 continue;
4080 link_rate_ = event_data->PHY[i].LinkRate >> 4; 4136 link_rate = event_data->PHY[i].LinkRate >> 4;
4081 switch (reason_code) { 4137 switch (reason_code) {
4082 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: 4138 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
4083 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: 4139 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
4084 if (!parent_handle) { 4140
4085 if (phy_number < ioc->sas_hba.num_phys) 4141 mpt2sas_transport_update_links(ioc, sas_address,
4086 mpt2sas_transport_update_links( 4142 handle, phy_number, link_rate);
4087 ioc, 4143
4088 ioc->sas_hba.phy[phy_number].handle, 4144 if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
4089 handle, phy_number, link_rate_); 4145 break;
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) { 4146 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); 4147 _scsih_add_device(ioc, handle, phy_number, 0);
4111 } 4148 }
4112 break; 4149 break;
4113 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: 4150 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
4114 _scsih_remove_device(ioc, handle); 4151
4152 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4153 sas_device = _scsih_sas_device_find_by_handle(ioc,
4154 handle);
4155 if (!sas_device) {
4156 spin_unlock_irqrestore(&ioc->sas_device_lock,
4157 flags);
4158 break;
4159 }
4160 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4161 _scsih_remove_device(ioc, sas_device);
4115 break; 4162 break;
4116 } 4163 }
4117 } 4164 }
4118 4165
4119 /* handle expander removal */ 4166 /* handle expander removal */
4120 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING) 4167 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING &&
4121 _scsih_expander_remove(ioc, parent_handle); 4168 sas_expander)
4169 _scsih_expander_remove(ioc, sas_address);
4122 4170
4123} 4171}
4124 4172
@@ -4570,7 +4618,7 @@ _scsih_sas_pd_delete(struct MPT2SAS_ADAPTER *ioc,
4570 spin_unlock_irqrestore(&ioc->sas_device_lock, flags); 4618 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4571 if (!sas_device) 4619 if (!sas_device)
4572 return; 4620 return;
4573 _scsih_remove_device(ioc, handle); 4621 _scsih_remove_device(ioc, sas_device);
4574} 4622}
4575 4623
4576/** 4624/**
@@ -4591,6 +4639,8 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc,
4591 Mpi2ConfigReply_t mpi_reply; 4639 Mpi2ConfigReply_t mpi_reply;
4592 Mpi2SasDevicePage0_t sas_device_pg0; 4640 Mpi2SasDevicePage0_t sas_device_pg0;
4593 u32 ioc_status; 4641 u32 ioc_status;
4642 u64 sas_address;
4643 u16 parent_handle;
4594 4644
4595 spin_lock_irqsave(&ioc->sas_device_lock, flags); 4645 spin_lock_irqsave(&ioc->sas_device_lock, flags);
4596 sas_device = _scsih_sas_device_find_by_handle(ioc, handle); 4646 sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
@@ -4615,9 +4665,10 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc,
4615 return; 4665 return;
4616 } 4666 }
4617 4667
4618 mpt2sas_transport_update_links(ioc, 4668 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
4619 le16_to_cpu(sas_device_pg0.ParentDevHandle), 4669 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
4620 handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); 4670 mpt2sas_transport_update_links(ioc, sas_address, handle,
4671 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
4621 4672
4622 _scsih_add_device(ioc, handle, 0, 1); 4673 _scsih_add_device(ioc, handle, 0, 1);
4623} 4674}
@@ -4857,7 +4908,7 @@ static void
4857_scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, 4908_scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc,
4858 struct fw_event_work *fw_event) 4909 struct fw_event_work *fw_event)
4859{ 4910{
4860 u16 handle; 4911 u16 handle, parent_handle;
4861 u32 state; 4912 u32 state;
4862 struct _sas_device *sas_device; 4913 struct _sas_device *sas_device;
4863 unsigned long flags; 4914 unsigned long flags;
@@ -4865,6 +4916,7 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc,
4865 Mpi2SasDevicePage0_t sas_device_pg0; 4916 Mpi2SasDevicePage0_t sas_device_pg0;
4866 u32 ioc_status; 4917 u32 ioc_status;
4867 Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; 4918 Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data;
4919 u64 sas_address;
4868 4920
4869 if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) 4921 if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
4870 return; 4922 return;
@@ -4906,9 +4958,10 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc,
4906 return; 4958 return;
4907 } 4959 }
4908 4960
4909 mpt2sas_transport_update_links(ioc, 4961 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
4910 le16_to_cpu(sas_device_pg0.ParentDevHandle), 4962 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
4911 handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); 4963 mpt2sas_transport_update_links(ioc, sas_address, handle,
4964 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
4912 4965
4913 _scsih_add_device(ioc, handle, 0, 1); 4966 _scsih_add_device(ioc, handle, 0, 1);
4914 4967
@@ -5252,18 +5305,23 @@ _scsih_mark_responding_expander(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
5252{ 5305{
5253 struct _sas_node *sas_expander; 5306 struct _sas_node *sas_expander;
5254 unsigned long flags; 5307 unsigned long flags;
5308 int i;
5255 5309
5256 spin_lock_irqsave(&ioc->sas_node_lock, flags); 5310 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5257 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { 5311 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
5258 if (sas_expander->sas_address == sas_address) { 5312 if (sas_expander->sas_address != sas_address)
5259 sas_expander->responding = 1; 5313 continue;
5260 if (sas_expander->handle != handle) { 5314 sas_expander->responding = 1;
5261 printk(KERN_INFO "old handle(0x%04x)\n", 5315 if (sas_expander->handle == handle)
5262 sas_expander->handle);
5263 sas_expander->handle = handle;
5264 }
5265 goto out; 5316 goto out;
5266 } 5317 printk(KERN_INFO "\texpander(0x%016llx): handle changed"
5318 " from(0x%04x) to (0x%04x)!!!\n",
5319 (unsigned long long)sas_expander->sas_address,
5320 sas_expander->handle, handle);
5321 sas_expander->handle = handle;
5322 for (i = 0 ; i < sas_expander->num_phys ; i++)
5323 sas_expander->phy[i].handle = handle;
5324 goto out;
5267 } 5325 }
5268 out: 5326 out:
5269 spin_unlock_irqrestore(&ioc->sas_node_lock, flags); 5327 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
@@ -5340,7 +5398,9 @@ _scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc)
5340 (unsigned long long) 5398 (unsigned long long)
5341 sas_device->enclosure_logical_id, 5399 sas_device->enclosure_logical_id,
5342 sas_device->slot); 5400 sas_device->slot);
5343 _scsih_remove_device(ioc, sas_device->handle); 5401 /* invalidate the device handle */
5402 sas_device->handle = 0;
5403 _scsih_remove_device(ioc, sas_device);
5344 } 5404 }
5345 5405
5346 list_for_each_entry_safe(raid_device, raid_device_next, 5406 list_for_each_entry_safe(raid_device, raid_device_next,
@@ -5366,7 +5426,7 @@ _scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc)
5366 sas_expander->responding = 0; 5426 sas_expander->responding = 0;
5367 continue; 5427 continue;
5368 } 5428 }
5369 _scsih_expander_remove(ioc, sas_expander->handle); 5429 _scsih_expander_remove(ioc, sas_expander->sas_address);
5370 goto retry_expander_search; 5430 goto retry_expander_search;
5371 } 5431 }
5372} 5432}
@@ -5406,7 +5466,7 @@ mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
5406 case MPT2_IOC_DONE_RESET: 5466 case MPT2_IOC_DONE_RESET:
5407 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " 5467 dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
5408 "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); 5468 "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
5409 _scsih_sas_host_refresh(ioc, 0); 5469 _scsih_sas_host_refresh(ioc);
5410 _scsih_search_responding_sas_devices(ioc); 5470 _scsih_search_responding_sas_devices(ioc);
5411 _scsih_search_responding_raid_devices(ioc); 5471 _scsih_search_responding_raid_devices(ioc);
5412 _scsih_search_responding_expanders(ioc); 5472 _scsih_search_responding_expanders(ioc);
@@ -5646,7 +5706,7 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
5646 spin_unlock_irqrestore(&ioc->sas_device_lock, flags); 5706 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5647 if (!sas_device) 5707 if (!sas_device)
5648 continue; 5708 continue;
5649 _scsih_remove_device(ioc, sas_device->handle); 5709 _scsih_remove_device(ioc, sas_device);
5650 if (ioc->shost_recovery) 5710 if (ioc->shost_recovery)
5651 return; 5711 return;
5652 goto retry_device_search; 5712 goto retry_device_search;
@@ -5669,7 +5729,8 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
5669 spin_unlock_irqrestore(&ioc->sas_node_lock, flags); 5729 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5670 if (!expander_sibling) 5730 if (!expander_sibling)
5671 continue; 5731 continue;
5672 _scsih_expander_remove(ioc, expander_sibling->handle); 5732 _scsih_expander_remove(ioc,
5733 expander_sibling->sas_address);
5673 if (ioc->shost_recovery) 5734 if (ioc->shost_recovery)
5674 return; 5735 return;
5675 goto retry_expander_search; 5736 goto retry_expander_search;
@@ -5677,7 +5738,7 @@ _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
5677 } 5738 }
5678 5739
5679 mpt2sas_transport_port_remove(ioc, sas_expander->sas_address, 5740 mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
5680 sas_expander->parent_handle); 5741 sas_expander->sas_address_parent);
5681 5742
5682 printk(MPT2SAS_INFO_FMT "expander_remove: handle" 5743 printk(MPT2SAS_INFO_FMT "expander_remove: handle"
5683 "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, 5744 "(0x%04x), sas_addr(0x%016llx)\n", ioc->name,
@@ -5726,7 +5787,7 @@ _scsih_remove(struct pci_dev *pdev)
5726 mpt2sas_scsih_sas_device_find_by_sas_address(ioc, 5787 mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
5727 mpt2sas_port->remote_identify.sas_address); 5788 mpt2sas_port->remote_identify.sas_address);
5728 if (sas_device) { 5789 if (sas_device) {
5729 _scsih_remove_device(ioc, sas_device->handle); 5790 _scsih_remove_device(ioc, sas_device);
5730 goto retry_again; 5791 goto retry_again;
5731 } 5792 }
5732 } else { 5793 } else {
@@ -5735,7 +5796,7 @@ _scsih_remove(struct pci_dev *pdev)
5735 mpt2sas_port->remote_identify.sas_address); 5796 mpt2sas_port->remote_identify.sas_address);
5736 if (expander_sibling) { 5797 if (expander_sibling) {
5737 _scsih_expander_remove(ioc, 5798 _scsih_expander_remove(ioc,
5738 expander_sibling->handle); 5799 expander_sibling->sas_address);
5739 goto retry_again; 5800 goto retry_again;
5740 } 5801 }
5741 } 5802 }
@@ -5770,7 +5831,8 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
5770 void *device; 5831 void *device;
5771 struct _sas_device *sas_device; 5832 struct _sas_device *sas_device;
5772 struct _raid_device *raid_device; 5833 struct _raid_device *raid_device;
5773 u16 handle, parent_handle; 5834 u16 handle;
5835 u64 sas_address_parent;
5774 u64 sas_address; 5836 u64 sas_address;
5775 unsigned long flags; 5837 unsigned long flags;
5776 int rc; 5838 int rc;
@@ -5799,17 +5861,17 @@ _scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
5799 } else { 5861 } else {
5800 sas_device = device; 5862 sas_device = device;
5801 handle = sas_device->handle; 5863 handle = sas_device->handle;
5802 parent_handle = sas_device->parent_handle; 5864 sas_address_parent = sas_device->sas_address_parent;
5803 sas_address = sas_device->sas_address; 5865 sas_address = sas_device->sas_address;
5804 spin_lock_irqsave(&ioc->sas_device_lock, flags); 5866 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5805 list_move_tail(&sas_device->list, &ioc->sas_device_list); 5867 list_move_tail(&sas_device->list, &ioc->sas_device_list);
5806 spin_unlock_irqrestore(&ioc->sas_device_lock, flags); 5868 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5807 if (!mpt2sas_transport_port_add(ioc, sas_device->handle, 5869 if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
5808 sas_device->parent_handle)) { 5870 sas_device->sas_address_parent)) {
5809 _scsih_sas_device_remove(ioc, sas_device); 5871 _scsih_sas_device_remove(ioc, sas_device);
5810 } else if (!sas_device->starget) { 5872 } else if (!sas_device->starget) {
5811 mpt2sas_transport_port_remove(ioc, sas_address, 5873 mpt2sas_transport_port_remove(ioc, sas_address,
5812 parent_handle); 5874 sas_address_parent);
5813 _scsih_sas_device_remove(ioc, sas_device); 5875 _scsih_sas_device_remove(ioc, sas_device);
5814 } 5876 }
5815 } 5877 }
@@ -5849,8 +5911,6 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
5849{ 5911{
5850 struct _sas_device *sas_device, *next; 5912 struct _sas_device *sas_device, *next;
5851 unsigned long flags; 5913 unsigned long flags;
5852 u16 handle, parent_handle;
5853 u64 sas_address;
5854 5914
5855 /* SAS Device List */ 5915 /* SAS Device List */
5856 list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list, 5916 list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list,
@@ -5859,14 +5919,13 @@ _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
5859 list_move_tail(&sas_device->list, &ioc->sas_device_list); 5919 list_move_tail(&sas_device->list, &ioc->sas_device_list);
5860 spin_unlock_irqrestore(&ioc->sas_device_lock, flags); 5920 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5861 5921
5862 handle = sas_device->handle; 5922 if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
5863 parent_handle = sas_device->parent_handle; 5923 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); 5924 _scsih_sas_device_remove(ioc, sas_device);
5867 } else if (!sas_device->starget) { 5925 } else if (!sas_device->starget) {
5868 mpt2sas_transport_port_remove(ioc, sas_address, 5926 mpt2sas_transport_port_remove(ioc,
5869 parent_handle); 5927 sas_device->sas_address,
5928 sas_device->sas_address_parent);
5870 _scsih_sas_device_remove(ioc, sas_device); 5929 _scsih_sas_device_remove(ioc, sas_device);
5871 } 5930 }
5872 } 5931 }
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index eb98188c7f3f..8030bc2774c8 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -59,24 +59,23 @@
59 59
60#include "mpt2sas_base.h" 60#include "mpt2sas_base.h"
61/** 61/**
62 * _transport_sas_node_find_by_handle - sas node search 62 * _transport_sas_node_find_by_sas_address - sas node search
63 * @ioc: per adapter object 63 * @ioc: per adapter object
64 * @handle: expander or hba handle (assigned by firmware) 64 * @sas_address: sas address of expander or sas host
65 * Context: Calling function should acquire ioc->sas_node_lock. 65 * Context: Calling function should acquire ioc->sas_node_lock.
66 * 66 *
67 * Search for either hba phys or expander device based on handle, then returns 67 * Search for either hba phys or expander device based on handle, then returns
68 * the sas_node object. 68 * the sas_node object.
69 */ 69 */
70static struct _sas_node * 70static struct _sas_node *
71_transport_sas_node_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) 71_transport_sas_node_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
72 u64 sas_address)
72{ 73{
73 int i; 74 if (ioc->sas_hba.sas_address == sas_address)
74 75 return &ioc->sas_hba;
75 for (i = 0; i < ioc->sas_hba.num_phys; i++) 76 else
76 if (ioc->sas_hba.phy[i].handle == handle) 77 return mpt2sas_scsih_expander_find_by_sas_address(ioc,
77 return &ioc->sas_hba; 78 sas_address);
78
79 return mpt2sas_scsih_expander_find_by_handle(ioc, handle);
80} 79}
81 80
82/** 81/**
@@ -469,7 +468,7 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
469 * mpt2sas_transport_port_add - insert port to the list 468 * mpt2sas_transport_port_add - insert port to the list
470 * @ioc: per adapter object 469 * @ioc: per adapter object
471 * @handle: handle of attached device 470 * @handle: handle of attached device
472 * @parent_handle: parent handle(either hba or expander) 471 * @sas_address: sas address of parent expander or sas host
473 * Context: This function will acquire ioc->sas_node_lock. 472 * Context: This function will acquire ioc->sas_node_lock.
474 * 473 *
475 * Adding new port object to the sas_node->sas_port_list. 474 * Adding new port object to the sas_node->sas_port_list.
@@ -478,7 +477,7 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
478 */ 477 */
479struct _sas_port * 478struct _sas_port *
480mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle, 479mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
481 u16 parent_handle) 480 u64 sas_address)
482{ 481{
483 struct _sas_phy *mpt2sas_phy, *next; 482 struct _sas_phy *mpt2sas_phy, *next;
484 struct _sas_port *mpt2sas_port; 483 struct _sas_port *mpt2sas_port;
@@ -488,9 +487,6 @@ mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
488 int i; 487 int i;
489 struct sas_port *port; 488 struct sas_port *port;
490 489
491 if (!parent_handle)
492 return NULL;
493
494 mpt2sas_port = kzalloc(sizeof(struct _sas_port), 490 mpt2sas_port = kzalloc(sizeof(struct _sas_port),
495 GFP_KERNEL); 491 GFP_KERNEL);
496 if (!mpt2sas_port) { 492 if (!mpt2sas_port) {
@@ -502,17 +498,16 @@ mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
502 INIT_LIST_HEAD(&mpt2sas_port->port_list); 498 INIT_LIST_HEAD(&mpt2sas_port->port_list);
503 INIT_LIST_HEAD(&mpt2sas_port->phy_list); 499 INIT_LIST_HEAD(&mpt2sas_port->phy_list);
504 spin_lock_irqsave(&ioc->sas_node_lock, flags); 500 spin_lock_irqsave(&ioc->sas_node_lock, flags);
505 sas_node = _transport_sas_node_find_by_handle(ioc, parent_handle); 501 sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
506 spin_unlock_irqrestore(&ioc->sas_node_lock, flags); 502 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
507 503
508 if (!sas_node) { 504 if (!sas_node) {
509 printk(MPT2SAS_ERR_FMT "%s: Could not find parent(0x%04x)!\n", 505 printk(MPT2SAS_ERR_FMT "%s: Could not find "
510 ioc->name, __func__, parent_handle); 506 "parent sas_address(0x%016llx)!\n", ioc->name,
507 __func__, (unsigned long long)sas_address);
511 goto out_fail; 508 goto out_fail;
512 } 509 }
513 510
514 mpt2sas_port->handle = parent_handle;
515 mpt2sas_port->sas_address = sas_node->sas_address;
516 if ((_transport_set_identify(ioc, handle, 511 if ((_transport_set_identify(ioc, handle,
517 &mpt2sas_port->remote_identify))) { 512 &mpt2sas_port->remote_identify))) {
518 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", 513 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
@@ -604,7 +599,7 @@ mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
604 * mpt2sas_transport_port_remove - remove port from the list 599 * mpt2sas_transport_port_remove - remove port from the list
605 * @ioc: per adapter object 600 * @ioc: per adapter object
606 * @sas_address: sas address of attached device 601 * @sas_address: sas address of attached device
607 * @parent_handle: handle to the upstream parent(either hba or expander) 602 * @sas_address_parent: sas address of parent expander or sas host
608 * Context: This function will acquire ioc->sas_node_lock. 603 * Context: This function will acquire ioc->sas_node_lock.
609 * 604 *
610 * Removing object and freeing associated memory from the 605 * Removing object and freeing associated memory from the
@@ -614,7 +609,7 @@ mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
614 */ 609 */
615void 610void
616mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, 611mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
617 u16 parent_handle) 612 u64 sas_address_parent)
618{ 613{
619 int i; 614 int i;
620 unsigned long flags; 615 unsigned long flags;
@@ -624,7 +619,8 @@ mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
624 struct _sas_phy *mpt2sas_phy, *next_phy; 619 struct _sas_phy *mpt2sas_phy, *next_phy;
625 620
626 spin_lock_irqsave(&ioc->sas_node_lock, flags); 621 spin_lock_irqsave(&ioc->sas_node_lock, flags);
627 sas_node = _transport_sas_node_find_by_handle(ioc, parent_handle); 622 sas_node = _transport_sas_node_find_by_sas_address(ioc,
623 sas_address_parent);
628 spin_unlock_irqrestore(&ioc->sas_node_lock, flags); 624 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
629 if (!sas_node) 625 if (!sas_node)
630 return; 626 return;
@@ -650,8 +646,7 @@ mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
650 &mpt2sas_port->phy_list, port_siblings) { 646 &mpt2sas_port->phy_list, port_siblings) {
651 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) 647 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
652 dev_printk(KERN_INFO, &mpt2sas_port->port->dev, 648 dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
653 "remove: parent_handle(0x%04x), " 649 "remove: sas_addr(0x%016llx), phy(%d)\n",
654 "sas_addr(0x%016llx), phy(%d)\n", parent_handle,
655 (unsigned long long) 650 (unsigned long long)
656 mpt2sas_port->remote_identify.sas_address, 651 mpt2sas_port->remote_identify.sas_address,
657 mpt2sas_phy->phy_id); 652 mpt2sas_phy->phy_id);
@@ -799,8 +794,8 @@ mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
799/** 794/**
800 * mpt2sas_transport_update_links - refreshing phy link changes 795 * mpt2sas_transport_update_links - refreshing phy link changes
801 * @ioc: per adapter object 796 * @ioc: per adapter object
802 * @handle: handle to sas_host or expander 797 * @sas_address: sas address of parent expander or sas host
803 * @attached_handle: attached device handle 798 * @handle: attached device handle
804 * @phy_numberv: phy number 799 * @phy_numberv: phy number
805 * @link_rate: new link rate 800 * @link_rate: new link rate
806 * 801 *
@@ -808,28 +803,25 @@ mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
808 */ 803 */
809void 804void
810mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc, 805mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
811 u16 handle, u16 attached_handle, u8 phy_number, u8 link_rate) 806 u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
812{ 807{
813 unsigned long flags; 808 unsigned long flags;
814 struct _sas_node *sas_node; 809 struct _sas_node *sas_node;
815 struct _sas_phy *mpt2sas_phy; 810 struct _sas_phy *mpt2sas_phy;
816 811
817 if (ioc->shost_recovery) { 812 if (ioc->shost_recovery)
818 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
819 __func__, ioc->name);
820 return; 813 return;
821 }
822 814
823 spin_lock_irqsave(&ioc->sas_node_lock, flags); 815 spin_lock_irqsave(&ioc->sas_node_lock, flags);
824 sas_node = _transport_sas_node_find_by_handle(ioc, handle); 816 sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
825 spin_unlock_irqrestore(&ioc->sas_node_lock, flags); 817 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
826 if (!sas_node) 818 if (!sas_node)
827 return; 819 return;
828 820
829 mpt2sas_phy = &sas_node->phy[phy_number]; 821 mpt2sas_phy = &sas_node->phy[phy_number];
830 mpt2sas_phy->attached_handle = attached_handle; 822 mpt2sas_phy->attached_handle = handle;
831 if (attached_handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) 823 if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5))
832 _transport_set_identify(ioc, mpt2sas_phy->attached_handle, 824 _transport_set_identify(ioc, handle,
833 &mpt2sas_phy->remote_identify); 825 &mpt2sas_phy->remote_identify);
834 else 826 else
835 memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct 827 memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
@@ -841,13 +833,11 @@ mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
841 833
842 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) 834 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
843 dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev, 835 dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
844 "refresh: handle(0x%04x), sas_addr(0x%016llx),\n" 836 "refresh: parent sas_addr(0x%016llx),\n"
845 "\tlink_rate(0x%02x), phy(%d)\n" 837 "\tlink_rate(0x%02x), phy(%d)\n"
846 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n", 838 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
847 handle, (unsigned long long) 839 (unsigned long long)sas_address,
848 mpt2sas_phy->identify.sas_address, link_rate, 840 link_rate, phy_number, handle, (unsigned long long)
849 phy_number, attached_handle,
850 (unsigned long long)
851 mpt2sas_phy->remote_identify.sas_address); 841 mpt2sas_phy->remote_identify.sas_address);
852} 842}
853 843