aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2008-03-12 10:51:03 -0400
committerRoland Dreier <rolandd@cisco.com>2008-03-12 10:51:03 -0400
commit10313cbb92206450b450e14f2b3f6ccde42d9a34 (patch)
tree6e10b1066fcb3f3a699960c62535f0cbea240738
parent4200406b8fbbf309f4fffb339bd16c4553ae0c30 (diff)
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: Roland Dreier <rolandd@cisco.com>
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c8
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c9
2 files changed, 10 insertions, 7 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 4e8d0281f8bc..2490b2d79dbb 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -38,6 +38,7 @@
38#include <net/icmp.h> 38#include <net/icmp.h>
39#include <linux/icmpv6.h> 39#include <linux/icmpv6.h>
40#include <linux/delay.h> 40#include <linux/delay.h>
41#include <linux/vmalloc.h>
41 42
42#include "ipoib.h" 43#include "ipoib.h"
43 44
@@ -1031,13 +1032,13 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn,
1031 struct ipoib_dev_priv *priv = netdev_priv(p->dev); 1032 struct ipoib_dev_priv *priv = netdev_priv(p->dev);
1032 int ret; 1033 int ret;
1033 1034
1034 p->tx_ring = kzalloc(ipoib_sendq_size * sizeof *p->tx_ring, 1035 p->tx_ring = vmalloc(ipoib_sendq_size * sizeof *p->tx_ring);
1035 GFP_KERNEL);
1036 if (!p->tx_ring) { 1036 if (!p->tx_ring) {
1037 ipoib_warn(priv, "failed to allocate tx ring\n"); 1037 ipoib_warn(priv, "failed to allocate tx ring\n");
1038 ret = -ENOMEM; 1038 ret = -ENOMEM;
1039 goto err_tx; 1039 goto err_tx;
1040 } 1040 }
1041 memset(p->tx_ring, 0, ipoib_sendq_size * sizeof *p->tx_ring);
1041 1042
1042 p->qp = ipoib_cm_create_tx_qp(p->dev, p); 1043 p->qp = ipoib_cm_create_tx_qp(p->dev, p);
1043 if (IS_ERR(p->qp)) { 1044 if (IS_ERR(p->qp)) {
@@ -1078,6 +1079,7 @@ err_id:
1078 ib_destroy_qp(p->qp); 1079 ib_destroy_qp(p->qp);
1079err_qp: 1080err_qp:
1080 p->qp = NULL; 1081 p->qp = NULL;
1082 vfree(p->tx_ring);
1081err_tx: 1083err_tx:
1082 return ret; 1084 return ret;
1083} 1085}
@@ -1128,7 +1130,7 @@ timeout:
1128 if (p->qp) 1130 if (p->qp)
1129 ib_destroy_qp(p->qp); 1131 ib_destroy_qp(p->qp);
1130 1132
1131 kfree(p->tx_ring); 1133 vfree(p->tx_ring);
1132 kfree(p); 1134 kfree(p);
1133} 1135}
1134 1136
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index f96477a8ca5a..57282048865c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -41,6 +41,7 @@
41#include <linux/init.h> 41#include <linux/init.h>
42#include <linux/slab.h> 42#include <linux/slab.h>
43#include <linux/kernel.h> 43#include <linux/kernel.h>
44#include <linux/vmalloc.h>
44 45
45#include <linux/if_arp.h> /* For ARPHRD_xxx */ 46#include <linux/if_arp.h> /* For ARPHRD_xxx */
46 47
@@ -887,13 +888,13 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
887 goto out; 888 goto out;
888 } 889 }
889 890
890 priv->tx_ring = kzalloc(ipoib_sendq_size * sizeof *priv->tx_ring, 891 priv->tx_ring = vmalloc(ipoib_sendq_size * sizeof *priv->tx_ring);
891 GFP_KERNEL);
892 if (!priv->tx_ring) { 892 if (!priv->tx_ring) {
893 printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n", 893 printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n",
894 ca->name, ipoib_sendq_size); 894 ca->name, ipoib_sendq_size);
895 goto out_rx_ring_cleanup; 895 goto out_rx_ring_cleanup;
896 } 896 }
897 memset(priv->tx_ring, 0, ipoib_sendq_size * sizeof *priv->tx_ring);
897 898
898 /* priv->tx_head, tx_tail & tx_outstanding are already 0 */ 899 /* priv->tx_head, tx_tail & tx_outstanding are already 0 */
899 900
@@ -903,7 +904,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
903 return 0; 904 return 0;
904 905
905out_tx_ring_cleanup: 906out_tx_ring_cleanup:
906 kfree(priv->tx_ring); 907 vfree(priv->tx_ring);
907 908
908out_rx_ring_cleanup: 909out_rx_ring_cleanup:
909 kfree(priv->rx_ring); 910 kfree(priv->rx_ring);
@@ -928,7 +929,7 @@ void ipoib_dev_cleanup(struct net_device *dev)
928 ipoib_ib_dev_cleanup(dev); 929 ipoib_ib_dev_cleanup(dev);
929 930
930 kfree(priv->rx_ring); 931 kfree(priv->rx_ring);
931 kfree(priv->tx_ring); 932 vfree(priv->tx_ring);
932 933
933 priv->rx_ring = NULL; 934 priv->rx_ring = NULL;
934 priv->tx_ring = NULL; 935 priv->tx_ring = NULL;