Commit 10313cbb authored by Roland Dreier's avatar Roland Dreier

IPoIB: Allocate priv->tx_ring with vmalloc()

Commit 7143740d ("IPoIB: Add send gather support") made struct
ipoib_tx_buf significantly larger, since the mapping member changed
from a single u64 to an array with MAX_SKB_FRAGS + 1 entries.  This
means that allocating tx_rings with kzalloc() may fail because there
is not enough contiguous memory for the new, much bigger size.  Fix
this regression by allocating the rings with vmalloc() instead.
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 4200406b
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <net/icmp.h> #include <net/icmp.h>
#include <linux/icmpv6.h> #include <linux/icmpv6.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/vmalloc.h>
#include "ipoib.h" #include "ipoib.h"
...@@ -1031,13 +1032,13 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn, ...@@ -1031,13 +1032,13 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn,
struct ipoib_dev_priv *priv = netdev_priv(p->dev); struct ipoib_dev_priv *priv = netdev_priv(p->dev);
int ret; int ret;
p->tx_ring = kzalloc(ipoib_sendq_size * sizeof *p->tx_ring, p->tx_ring = vmalloc(ipoib_sendq_size * sizeof *p->tx_ring);
GFP_KERNEL);
if (!p->tx_ring) { if (!p->tx_ring) {
ipoib_warn(priv, "failed to allocate tx ring\n"); ipoib_warn(priv, "failed to allocate tx ring\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err_tx; goto err_tx;
} }
memset(p->tx_ring, 0, ipoib_sendq_size * sizeof *p->tx_ring);
p->qp = ipoib_cm_create_tx_qp(p->dev, p); p->qp = ipoib_cm_create_tx_qp(p->dev, p);
if (IS_ERR(p->qp)) { if (IS_ERR(p->qp)) {
...@@ -1078,6 +1079,7 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn, ...@@ -1078,6 +1079,7 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn,
ib_destroy_qp(p->qp); ib_destroy_qp(p->qp);
err_qp: err_qp:
p->qp = NULL; p->qp = NULL;
vfree(p->tx_ring);
err_tx: err_tx:
return ret; return ret;
} }
...@@ -1128,7 +1130,7 @@ static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p) ...@@ -1128,7 +1130,7 @@ static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p)
if (p->qp) if (p->qp)
ib_destroy_qp(p->qp); ib_destroy_qp(p->qp);
kfree(p->tx_ring); vfree(p->tx_ring);
kfree(p); kfree(p);
} }
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/vmalloc.h>
#include <linux/if_arp.h> /* For ARPHRD_xxx */ #include <linux/if_arp.h> /* For ARPHRD_xxx */
...@@ -887,13 +888,13 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) ...@@ -887,13 +888,13 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
goto out; goto out;
} }
priv->tx_ring = kzalloc(ipoib_sendq_size * sizeof *priv->tx_ring, priv->tx_ring = vmalloc(ipoib_sendq_size * sizeof *priv->tx_ring);
GFP_KERNEL);
if (!priv->tx_ring) { if (!priv->tx_ring) {
printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n", printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n",
ca->name, ipoib_sendq_size); ca->name, ipoib_sendq_size);
goto out_rx_ring_cleanup; goto out_rx_ring_cleanup;
} }
memset(priv->tx_ring, 0, ipoib_sendq_size * sizeof *priv->tx_ring);
/* priv->tx_head, tx_tail & tx_outstanding are already 0 */ /* priv->tx_head, tx_tail & tx_outstanding are already 0 */
...@@ -903,7 +904,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) ...@@ -903,7 +904,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
return 0; return 0;
out_tx_ring_cleanup: out_tx_ring_cleanup:
kfree(priv->tx_ring); vfree(priv->tx_ring);
out_rx_ring_cleanup: out_rx_ring_cleanup:
kfree(priv->rx_ring); kfree(priv->rx_ring);
...@@ -928,7 +929,7 @@ void ipoib_dev_cleanup(struct net_device *dev) ...@@ -928,7 +929,7 @@ void ipoib_dev_cleanup(struct net_device *dev)
ipoib_ib_dev_cleanup(dev); ipoib_ib_dev_cleanup(dev);
kfree(priv->rx_ring); kfree(priv->rx_ring);
kfree(priv->tx_ring); vfree(priv->tx_ring);
priv->rx_ring = NULL; priv->rx_ring = NULL;
priv->tx_ring = NULL; priv->tx_ring = NULL;
......
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