Commit 347fcfbe authored by Michael S. Tsirkin's avatar Michael S. Tsirkin Committed by Roland Dreier

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: default avatarMichael S. Tsirkin <mst@dev.mellanox.co.il>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 6b66b2da
...@@ -592,7 +592,9 @@ int ipoib_cm_dev_open(struct net_device *dev) ...@@ -592,7 +592,9 @@ int ipoib_cm_dev_open(struct net_device *dev)
priv->cm.id = ib_create_cm_id(priv->ca, ipoib_cm_rx_handler, dev); priv->cm.id = ib_create_cm_id(priv->ca, ipoib_cm_rx_handler, dev);
if (IS_ERR(priv->cm.id)) { if (IS_ERR(priv->cm.id)) {
printk(KERN_WARNING "%s: failed to create CM ID\n", priv->ca->name); printk(KERN_WARNING "%s: failed to create CM ID\n", priv->ca->name);
return IS_ERR(priv->cm.id); ret = PTR_ERR(priv->cm.id);
priv->cm.id = NULL;
return ret;
} }
ret = ib_cm_listen(priv->cm.id, cpu_to_be64(IPOIB_CM_IETF_ID | priv->qp->qp_num), 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,6 +603,7 @@ int ipoib_cm_dev_open(struct net_device *dev)
printk(KERN_WARNING "%s: failed to listen on ID 0x%llx\n", priv->ca->name, printk(KERN_WARNING "%s: failed to listen on ID 0x%llx\n", priv->ca->name,
IPOIB_CM_IETF_ID | priv->qp->qp_num); IPOIB_CM_IETF_ID | priv->qp->qp_num);
ib_destroy_cm_id(priv->cm.id); ib_destroy_cm_id(priv->cm.id);
priv->cm.id = NULL;
return ret; return ret;
} }
return 0; return 0;
...@@ -611,10 +614,11 @@ void ipoib_cm_dev_stop(struct net_device *dev) ...@@ -611,10 +614,11 @@ void ipoib_cm_dev_stop(struct net_device *dev)
struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_cm_rx *p; struct ipoib_cm_rx *p;
if (!IPOIB_CM_SUPPORTED(dev->dev_addr)) if (!IPOIB_CM_SUPPORTED(dev->dev_addr) || !priv->cm.id)
return; return;
ib_destroy_cm_id(priv->cm.id); ib_destroy_cm_id(priv->cm.id);
priv->cm.id = NULL;
spin_lock_irq(&priv->lock); spin_lock_irq(&priv->lock);
while (!list_empty(&priv->cm.passive_ids)) { while (!list_empty(&priv->cm.passive_ids)) {
p = list_entry(priv->cm.passive_ids.next, typeof(*p), list); p = list_entry(priv->cm.passive_ids.next, typeof(*p), list);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment