aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@steeleye.com>2006-11-15 19:03:07 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-12-03 13:29:46 -0500
commit024879ead9594acab30ce9e23c955086e2d967a0 (patch)
tree74936c283777d7bdcd0c722a33a23eb323cabf8d /drivers/scsi
parentba8d55048ae08c442a27944e8beb76e73c3cce03 (diff)
[SCSI] libsas: better error handling in sas_expander.c
With async scanning, we're now tripping the BUG_ON in sas_ex_discover_end_dev(), so make the error handling here correct. Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/libsas/sas_expander.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index e34a9343549..d31e6fa466f 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -597,10 +597,15 @@ static struct domain_device *sas_ex_discover_end_dev(
597 child->iproto = phy->attached_iproto; 597 child->iproto = phy->attached_iproto;
598 memcpy(child->sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); 598 memcpy(child->sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
599 sas_hash_addr(child->hashed_sas_addr, child->sas_addr); 599 sas_hash_addr(child->hashed_sas_addr, child->sas_addr);
600 phy->port = sas_port_alloc(&parent->rphy->dev, phy_id); 600 if (!phy->port) {
601 BUG_ON(!phy->port); 601 phy->port = sas_port_alloc(&parent->rphy->dev, phy_id);
602 /* FIXME: better error handling*/ 602 if (unlikely(!phy->port))
603 BUG_ON(sas_port_add(phy->port) != 0); 603 goto out_err;
604 if (unlikely(sas_port_add(phy->port) != 0)) {
605 sas_port_free(phy->port);
606 goto out_err;
607 }
608 }
604 sas_ex_get_linkrate(parent, child, phy); 609 sas_ex_get_linkrate(parent, child, phy);
605 610
606 if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { 611 if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) {
@@ -615,8 +620,7 @@ static struct domain_device *sas_ex_discover_end_dev(
615 SAS_DPRINTK("report phy sata to %016llx:0x%x returned " 620 SAS_DPRINTK("report phy sata to %016llx:0x%x returned "
616 "0x%x\n", SAS_ADDR(parent->sas_addr), 621 "0x%x\n", SAS_ADDR(parent->sas_addr),
617 phy_id, res); 622 phy_id, res);
618 kfree(child); 623 goto out_free;
619 return NULL;
620 } 624 }
621 memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis, 625 memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis,
622 sizeof(struct dev_to_host_fis)); 626 sizeof(struct dev_to_host_fis));
@@ -627,14 +631,14 @@ static struct domain_device *sas_ex_discover_end_dev(
627 "%016llx:0x%x returned 0x%x\n", 631 "%016llx:0x%x returned 0x%x\n",
628 SAS_ADDR(child->sas_addr), 632 SAS_ADDR(child->sas_addr),
629 SAS_ADDR(parent->sas_addr), phy_id, res); 633 SAS_ADDR(parent->sas_addr), phy_id, res);
630 kfree(child); 634 goto out_free;
631 return NULL;
632 } 635 }
633 } else if (phy->attached_tproto & SAS_PROTO_SSP) { 636 } else if (phy->attached_tproto & SAS_PROTO_SSP) {
634 child->dev_type = SAS_END_DEV; 637 child->dev_type = SAS_END_DEV;
635 rphy = sas_end_device_alloc(phy->port); 638 rphy = sas_end_device_alloc(phy->port);
636 /* FIXME: error handling */ 639 /* FIXME: error handling */
637 BUG_ON(!rphy); 640 if (unlikely(!rphy))
641 goto out_free;
638 child->tproto = phy->attached_tproto; 642 child->tproto = phy->attached_tproto;
639 sas_init_dev(child); 643 sas_init_dev(child);
640 644
@@ -651,9 +655,7 @@ static struct domain_device *sas_ex_discover_end_dev(
651 "at %016llx:0x%x returned 0x%x\n", 655 "at %016llx:0x%x returned 0x%x\n",
652 SAS_ADDR(child->sas_addr), 656 SAS_ADDR(child->sas_addr),
653 SAS_ADDR(parent->sas_addr), phy_id, res); 657 SAS_ADDR(parent->sas_addr), phy_id, res);
654 /* FIXME: this kfrees list elements without removing them */ 658 goto out_list_del;
655 //kfree(child);
656 return NULL;
657 } 659 }
658 } else { 660 } else {
659 SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", 661 SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n",
@@ -663,6 +665,16 @@ static struct domain_device *sas_ex_discover_end_dev(
663 665
664 list_add_tail(&child->siblings, &parent_ex->children); 666 list_add_tail(&child->siblings, &parent_ex->children);
665 return child; 667 return child;
668
669 out_list_del:
670 list_del(&child->dev_list_node);
671 sas_rphy_free(rphy);
672 out_free:
673 sas_port_delete(phy->port);
674 out_err:
675 phy->port = NULL;
676 kfree(child);
677 return NULL;
666} 678}
667 679
668static struct domain_device *sas_ex_discover_expander( 680static struct domain_device *sas_ex_discover_expander(