diff options
author | Michael S. Tsirkin <mst@dev.mellanox.co.il> | 2007-04-30 20:30:28 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2007-04-30 20:30:28 -0400 |
commit | 347fcfbed261fdd11f46fa03d524e1bddddab3a6 (patch) | |
tree | 370b7f5f3d0bdb8d344dadbffce4ec4eba0af4a7 /drivers/infiniband/ulp | |
parent | 6b66b2da1e821181a001c00b04a807724ad803cd (diff) |
IPoIB/cm: Fix error handling in ipoib_cm_dev_open()
If skb allocation fails when we start the device, we call
ipoib_cm_dev_stop() even though ipoib_cm_dev_open() did not run to
completion, so we pass an invalid pointer to ib_destroy_cm_id and get
an oops.
Fix by clearing cm.id on error, and testing it in cm_dev_stop().
This fixes <https://bugs.openfabrics.org/show_bug.cgi?id=561>
Signed-off-by: Michael S. Tsirkin <mst@dev.mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/ulp')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_cm.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 0c4e59b906cd..76717410660e 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c | |||
@@ -592,7 +592,9 @@ int ipoib_cm_dev_open(struct net_device *dev) | |||
592 | priv->cm.id = ib_create_cm_id(priv->ca, ipoib_cm_rx_handler, dev); | 592 | priv->cm.id = ib_create_cm_id(priv->ca, ipoib_cm_rx_handler, dev); |
593 | if (IS_ERR(priv->cm.id)) { | 593 | if (IS_ERR(priv->cm.id)) { |
594 | printk(KERN_WARNING "%s: failed to create CM ID\n", priv->ca->name); | 594 | printk(KERN_WARNING "%s: failed to create CM ID\n", priv->ca->name); |
595 | return IS_ERR(priv->cm.id); | 595 | ret = PTR_ERR(priv->cm.id); |
596 | priv->cm.id = NULL; | ||
597 | return ret; | ||
596 | } | 598 | } |
597 | 599 | ||
598 | ret = ib_cm_listen(priv->cm.id, cpu_to_be64(IPOIB_CM_IETF_ID | priv->qp->qp_num), | 600 | ret = ib_cm_listen(priv->cm.id, cpu_to_be64(IPOIB_CM_IETF_ID | priv->qp->qp_num), |
@@ -601,6 +603,7 @@ int ipoib_cm_dev_open(struct net_device *dev) | |||
601 | printk(KERN_WARNING "%s: failed to listen on ID 0x%llx\n", priv->ca->name, | 603 | printk(KERN_WARNING "%s: failed to listen on ID 0x%llx\n", priv->ca->name, |
602 | IPOIB_CM_IETF_ID | priv->qp->qp_num); | 604 | IPOIB_CM_IETF_ID | priv->qp->qp_num); |
603 | ib_destroy_cm_id(priv->cm.id); | 605 | ib_destroy_cm_id(priv->cm.id); |
606 | priv->cm.id = NULL; | ||
604 | return ret; | 607 | return ret; |
605 | } | 608 | } |
606 | return 0; | 609 | return 0; |
@@ -611,10 +614,11 @@ void ipoib_cm_dev_stop(struct net_device *dev) | |||
611 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 614 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
612 | struct ipoib_cm_rx *p; | 615 | struct ipoib_cm_rx *p; |
613 | 616 | ||
614 | if (!IPOIB_CM_SUPPORTED(dev->dev_addr)) | 617 | if (!IPOIB_CM_SUPPORTED(dev->dev_addr) || !priv->cm.id) |
615 | return; | 618 | return; |
616 | 619 | ||
617 | ib_destroy_cm_id(priv->cm.id); | 620 | ib_destroy_cm_id(priv->cm.id); |
621 | priv->cm.id = NULL; | ||
618 | spin_lock_irq(&priv->lock); | 622 | spin_lock_irq(&priv->lock); |
619 | while (!list_empty(&priv->cm.passive_ids)) { | 623 | while (!list_empty(&priv->cm.passive_ids)) { |
620 | p = list_entry(priv->cm.passive_ids.next, typeof(*p), list); | 624 | p = list_entry(priv->cm.passive_ids.next, typeof(*p), list); |