aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt2sas
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2009-09-23 07:51:29 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-10-29 13:03:08 -0400
commitc5e039be7e81168a9156e801cfef2adae72e775b (patch)
treedd190bc63c177cf3f20728bc661df4c24a2c763d /drivers/scsi/mpt2sas
parent8d5eb435c3523b15f67c35a5d4defa8d1757f9bd (diff)
[SCSI] mpt2sas: Driver will use sas address instead of handle as a lookup
The device driver was not handling updating device handles in all cases across diag resets. To fix this issue, the driver is converted to using sas address instead of handle as a lookup reference to the parent expander or sas_host. Also, for both expanders and sas host, the phy handle will be one unique handle. In the sas host case, the phy handle can be different for every phy, so the change is to set the handle to the handle of the first phy; every phy will be one single sas address(phy 0) instead of a different sas address for every phy(previous implementation). So making one consistent sas address for all the direct attachedports to the sas host, will make it better user experience when using udev /dev/disk/by-path dev nodes Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com> Signed-off-by: Eric Moore <Eric.moore@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
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