summaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/ulp/ipoib
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2007-05-08 13:37:51 +1000
committerPaul Mackerras <paulus@samba.org>2007-05-08 13:37:51 +1000
commit02bbc0f09c90cefdb2837605c96a66c5ce4ba2e1 (patch)
tree04ef573cd4de095c500c9fc3477f4278c0b36300 /drivers/infiniband/ulp/ipoib
parent7487a2245b8841c77ba9db406cf99a483b9334e9 (diff)
parent5b94f675f57e4ff16c8fda09088d7480a84dcd91 (diff)
downloadblackbird-obmc-linux-02bbc0f09c90cefdb2837605c96a66c5ce4ba2e1.tar.gz
blackbird-obmc-linux-02bbc0f09c90cefdb2837605c96a66c5ce4ba2e1.zip
Merge branch 'linux-2.6'
Diffstat (limited to 'drivers/infiniband/ulp/ipoib')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c14
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c89
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c2
5 files changed, 83 insertions, 26 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index fd558267d1cb..87310eeb6df0 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -41,7 +41,6 @@
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/workqueue.h>
-#include <linux/pci.h>
#include <linux/kref.h>
#include <linux/if_infiniband.h>
#include <linux/mutex.h>
@@ -311,6 +310,7 @@ extern struct workqueue_struct *ipoib_workqueue;
/* functions */
+int ipoib_poll(struct net_device *dev, int *budget);
void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr);
struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 0c4e59b906cd..785bc8505f2a 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -370,7 +370,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
if (!likely(wr_id & IPOIB_CM_RX_UPDATE_MASK)) {
p = wc->qp->qp_context;
- if (time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_UPDATE_TIME)) {
+ if (p && time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_UPDATE_TIME)) {
spin_lock_irqsave(&priv->lock, flags);
p->jiffies = jiffies;
/* Move this entry to list head, but do
@@ -416,7 +416,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
skb->dev = dev;
/* XXX get correct PACKET_ type here */
skb->pkt_type = PACKET_HOST;
- netif_rx_ni(skb);
+ netif_receive_skb(skb);
repost:
if (unlikely(ipoib_cm_post_receive(dev, wr_id)))
@@ -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);
if (IS_ERR(priv->cm.id)) {
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),
@@ -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,
IPOIB_CM_IETF_ID | priv->qp->qp_num);
ib_destroy_cm_id(priv->cm.id);
+ priv->cm.id = NULL;
return ret;
}
return 0;
@@ -611,10 +614,11 @@ void ipoib_cm_dev_stop(struct net_device *dev)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_cm_rx *p;
- if (!IPOIB_CM_SUPPORTED(dev->dev_addr))
+ if (!IPOIB_CM_SUPPORTED(dev->dev_addr) || !priv->cm.id)
return;
ib_destroy_cm_id(priv->cm.id);
+ priv->cm.id = NULL;
spin_lock_irq(&priv->lock);
while (!list_empty(&priv->cm.passive_ids)) {
p = list_entry(priv->cm.passive_ids.next, typeof(*p), list);
@@ -789,7 +793,7 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn,
}
p->cq = ib_create_cq(priv->ca, ipoib_cm_tx_completion, NULL, p,
- ipoib_sendq_size + 1);
+ ipoib_sendq_size + 1, 0);
if (IS_ERR(p->cq)) {
ret = PTR_ERR(p->cq);
ipoib_warn(priv, "failed to allocate tx cq: %d\n", ret);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 1bdb9101911a..68d72c6f7ffb 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -226,7 +226,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
skb->dev = dev;
/* XXX get correct PACKET_ type here */
skb->pkt_type = PACKET_HOST;
- netif_rx_ni(skb);
+ netif_receive_skb(skb);
} else {
ipoib_dbg_data(priv, "dropping loopback packet\n");
dev_kfree_skb_any(skb);
@@ -280,28 +280,63 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
wc->status, wr_id, wc->vendor_err);
}
-static void ipoib_ib_handle_wc(struct net_device *dev, struct ib_wc *wc)
+int ipoib_poll(struct net_device *dev, int *budget)
{
- if (wc->wr_id & IPOIB_CM_OP_SRQ)
- ipoib_cm_handle_rx_wc(dev, wc);
- else if (wc->wr_id & IPOIB_OP_RECV)
- ipoib_ib_handle_rx_wc(dev, wc);
- else
- ipoib_ib_handle_tx_wc(dev, wc);
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ int max = min(*budget, dev->quota);
+ int done;
+ int t;
+ int empty;
+ int n, i;
+
+ done = 0;
+ empty = 0;
+
+ while (max) {
+ t = min(IPOIB_NUM_WC, max);
+ n = ib_poll_cq(priv->cq, t, priv->ibwc);
+
+ for (i = 0; i < n; ++i) {
+ struct ib_wc *wc = priv->ibwc + i;
+
+ if (wc->wr_id & IPOIB_CM_OP_SRQ) {
+ ++done;
+ --max;
+ ipoib_cm_handle_rx_wc(dev, wc);
+ } else if (wc->wr_id & IPOIB_OP_RECV) {
+ ++done;
+ --max;
+ ipoib_ib_handle_rx_wc(dev, wc);
+ } else
+ ipoib_ib_handle_tx_wc(dev, wc);
+ }
+
+ if (n != t) {
+ empty = 1;
+ break;
+ }
+ }
+
+ dev->quota -= done;
+ *budget -= done;
+
+ if (empty) {
+ netif_rx_complete(dev);
+ if (unlikely(ib_req_notify_cq(priv->cq,
+ IB_CQ_NEXT_COMP |
+ IB_CQ_REPORT_MISSED_EVENTS)) &&
+ netif_rx_reschedule(dev, 0))
+ return 1;
+
+ return 0;
+ }
+
+ return 1;
}
void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
{
- struct net_device *dev = (struct net_device *) dev_ptr;
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- int n, i;
-
- ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
- do {
- n = ib_poll_cq(cq, IPOIB_NUM_WC, priv->ibwc);
- for (i = 0; i < n; ++i)
- ipoib_ib_handle_wc(dev, priv->ibwc + i);
- } while (n == IPOIB_NUM_WC);
+ netif_rx_schedule(dev_ptr);
}
static inline int post_send(struct ipoib_dev_priv *priv,
@@ -514,9 +549,10 @@ int ipoib_ib_dev_stop(struct net_device *dev)
struct ib_qp_attr qp_attr;
unsigned long begin;
struct ipoib_tx_buf *tx_req;
- int i;
+ int i, n;
clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
+ netif_poll_disable(dev);
ipoib_cm_dev_stop(dev);
@@ -568,6 +604,18 @@ int ipoib_ib_dev_stop(struct net_device *dev)
goto timeout;
}
+ do {
+ n = ib_poll_cq(priv->cq, IPOIB_NUM_WC, priv->ibwc);
+ for (i = 0; i < n; ++i) {
+ if (priv->ibwc[i].wr_id & IPOIB_CM_OP_SRQ)
+ ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);
+ else if (priv->ibwc[i].wr_id & IPOIB_OP_RECV)
+ ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);
+ else
+ ipoib_ib_handle_tx_wc(dev, priv->ibwc + i);
+ }
+ } while (n == IPOIB_NUM_WC);
+
msleep(1);
}
@@ -596,6 +644,9 @@ timeout:
msleep(1);
}
+ netif_poll_enable(dev);
+ ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP);
+
return 0;
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index b4c380c5a3ba..0a428f2b05c7 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -948,6 +948,8 @@ static void ipoib_setup(struct net_device *dev)
dev->hard_header = ipoib_hard_header;
dev->set_multicast_list = ipoib_set_mcast_list;
dev->neigh_setup = ipoib_neigh_setup_dev;
+ dev->poll = ipoib_poll;
+ dev->weight = 100;
dev->watchdog_timeo = HZ;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 7f3ec205e35f..5c3c6a43a52b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -187,7 +187,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
if (!ret)
size += ipoib_recvq_size;
- priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size);
+ priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0);
if (IS_ERR(priv->cq)) {
printk(KERN_WARNING "%s: failed to create CQ\n", ca->name);
goto out_free_mr;
OpenPOWER on IntegriCloud