diff options
author | Darrick J. Wong <djwong@us.ibm.com> | 2007-01-11 17:14:49 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-01-13 15:23:36 -0500 |
commit | 8880839815265ccc0edaff52ba08d750eea57acb (patch) | |
tree | b98c920cb0cc5bdd90cd3cbf66d4d6a075e37922 /drivers/scsi/libsas | |
parent | befede3dabd204e9c546cbfbe391b29286c57da2 (diff) |
[SCSI] libsas: Clean up rphys/port dev list after a discovery error.
sas_get_port_device assigns a rphy to a domain device in anticipation
of finding a disk. When a discovery error occurs in
sas_discover_{sata,sas,expander}*, however, we need to clean up that
rphy and the port device list so that we don't GPF. In addition, we
need to check the result of the second sas_notify_lldd_dev_found.
This patch seems ok on a x260, x366 and x206m.
Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/libsas')
-rw-r--r-- | drivers/scsi/libsas/sas_discover.c | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index fb7df7b75811..21f538e4a0b5 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c | |||
@@ -548,7 +548,7 @@ int sas_discover_sata(struct domain_device *dev) | |||
548 | 548 | ||
549 | res = sas_notify_lldd_dev_found(dev); | 549 | res = sas_notify_lldd_dev_found(dev); |
550 | if (res) | 550 | if (res) |
551 | return res; | 551 | goto out_err2; |
552 | 552 | ||
553 | switch (dev->dev_type) { | 553 | switch (dev->dev_type) { |
554 | case SATA_DEV: | 554 | case SATA_DEV: |
@@ -560,11 +560,25 @@ int sas_discover_sata(struct domain_device *dev) | |||
560 | default: | 560 | default: |
561 | break; | 561 | break; |
562 | } | 562 | } |
563 | if (res) | ||
564 | goto out_err; | ||
563 | 565 | ||
564 | sas_notify_lldd_dev_gone(dev); | 566 | sas_notify_lldd_dev_gone(dev); |
565 | if (!res) { | 567 | res = sas_notify_lldd_dev_found(dev); |
566 | sas_notify_lldd_dev_found(dev); | 568 | if (res) |
567 | } | 569 | goto out_err2; |
570 | |||
571 | res = sas_rphy_add(dev->rphy); | ||
572 | if (res) | ||
573 | goto out_err; | ||
574 | |||
575 | return res; | ||
576 | |||
577 | out_err: | ||
578 | sas_notify_lldd_dev_gone(dev); | ||
579 | out_err2: | ||
580 | sas_rphy_free(dev->rphy); | ||
581 | dev->rphy = NULL; | ||
568 | return res; | 582 | return res; |
569 | } | 583 | } |
570 | 584 | ||
@@ -580,7 +594,7 @@ int sas_discover_end_dev(struct domain_device *dev) | |||
580 | 594 | ||
581 | res = sas_notify_lldd_dev_found(dev); | 595 | res = sas_notify_lldd_dev_found(dev); |
582 | if (res) | 596 | if (res) |
583 | return res; | 597 | goto out_err2; |
584 | 598 | ||
585 | res = sas_rphy_add(dev->rphy); | 599 | res = sas_rphy_add(dev->rphy); |
586 | if (res) | 600 | if (res) |
@@ -589,12 +603,21 @@ int sas_discover_end_dev(struct domain_device *dev) | |||
589 | /* do this to get the end device port attributes which will have | 603 | /* do this to get the end device port attributes which will have |
590 | * been scanned in sas_rphy_add */ | 604 | * been scanned in sas_rphy_add */ |
591 | sas_notify_lldd_dev_gone(dev); | 605 | sas_notify_lldd_dev_gone(dev); |
592 | sas_notify_lldd_dev_found(dev); | 606 | res = sas_notify_lldd_dev_found(dev); |
607 | if (res) | ||
608 | goto out_err3; | ||
593 | 609 | ||
594 | return 0; | 610 | return 0; |
595 | 611 | ||
596 | out_err: | 612 | out_err: |
597 | sas_notify_lldd_dev_gone(dev); | 613 | sas_notify_lldd_dev_gone(dev); |
614 | out_err2: | ||
615 | sas_rphy_free(dev->rphy); | ||
616 | dev->rphy = NULL; | ||
617 | return res; | ||
618 | out_err3: | ||
619 | sas_rphy_delete(dev->rphy); | ||
620 | dev->rphy = NULL; | ||
598 | return res; | 621 | return res; |
599 | } | 622 | } |
600 | 623 | ||
@@ -686,6 +709,10 @@ static void sas_discover_domain(struct work_struct *work) | |||
686 | } | 709 | } |
687 | 710 | ||
688 | if (error) { | 711 | if (error) { |
712 | spin_lock(&port->dev_list_lock); | ||
713 | list_del_init(&port->port_dev->dev_list_node); | ||
714 | spin_unlock(&port->dev_list_lock); | ||
715 | |||
689 | kfree(port->port_dev); /* not kobject_register-ed yet */ | 716 | kfree(port->port_dev); /* not kobject_register-ed yet */ |
690 | port->port_dev = NULL; | 717 | port->port_dev = NULL; |
691 | } | 718 | } |