aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Miller <davem@davemloft.net>2011-12-02 11:52:18 -0500
committerDavid S. Miller <davem@davemloft.net>2011-12-05 15:20:19 -0500
commita4757123aeadf450b5b3c5f51f214660e20477f3 (patch)
tree075d43113136926357be2863b2efb3b6a099e553
parent51d45974515c35cd401f6194a6e728a2d1c3e3c6 (diff)
cxgb3: Rework t3_l2t_get to take a dst_entry instead of a neighbour.
This way we consolidate the RCU locking down into the place where it actually matters, and also we can make the code handle dst_get_neighbour_noref() returning NULL properly. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c15
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/l2t.c27
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/l2t.h2
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/cxgb3i.c2
5 files changed, 25 insertions, 23 deletions
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 23686df0517c..740dcc065cf2 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -1338,7 +1338,6 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
1338 struct iwch_ep *child_ep, *parent_ep = ctx; 1338 struct iwch_ep *child_ep, *parent_ep = ctx;
1339 struct cpl_pass_accept_req *req = cplhdr(skb); 1339 struct cpl_pass_accept_req *req = cplhdr(skb);
1340 unsigned int hwtid = GET_TID(req); 1340 unsigned int hwtid = GET_TID(req);
1341 struct neighbour *neigh;
1342 struct dst_entry *dst; 1341 struct dst_entry *dst;
1343 struct l2t_entry *l2t; 1342 struct l2t_entry *l2t;
1344 struct rtable *rt; 1343 struct rtable *rt;
@@ -1375,10 +1374,7 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
1375 goto reject; 1374 goto reject;
1376 } 1375 }
1377 dst = &rt->dst; 1376 dst = &rt->dst;
1378 rcu_read_lock(); 1377 l2t = t3_l2t_get(tdev, dst, NULL);
1379 neigh = dst_get_neighbour_noref(dst);
1380 l2t = t3_l2t_get(tdev, neigh, neigh->dev);
1381 rcu_read_unlock();
1382 if (!l2t) { 1378 if (!l2t) {
1383 printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", 1379 printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
1384 __func__); 1380 __func__);
@@ -1889,7 +1885,6 @@ static int is_loopback_dst(struct iw_cm_id *cm_id)
1889int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 1885int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
1890{ 1886{
1891 struct iwch_dev *h = to_iwch_dev(cm_id->device); 1887 struct iwch_dev *h = to_iwch_dev(cm_id->device);
1892 struct neighbour *neigh;
1893 struct iwch_ep *ep; 1888 struct iwch_ep *ep;
1894 struct rtable *rt; 1889 struct rtable *rt;
1895 int err = 0; 1890 int err = 0;
@@ -1947,13 +1942,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
1947 goto fail3; 1942 goto fail3;
1948 } 1943 }
1949 ep->dst = &rt->dst; 1944 ep->dst = &rt->dst;
1950 1945 ep->l2t = t3_l2t_get(ep->com.tdev, ep->dst, NULL);
1951 rcu_read_lock();
1952 neigh = dst_get_neighbour_noref(ep->dst);
1953
1954 /* get a l2t entry */
1955 ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev);
1956 rcu_read_unlock();
1957 if (!ep->l2t) { 1946 if (!ep->l2t) {
1958 printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); 1947 printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
1959 err = -ENOMEM; 1948 err = -ENOMEM;
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
index 6ed9f87db8ea..596cfe32d79e 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
@@ -1132,7 +1132,7 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
1132 } 1132 }
1133 1133
1134 /* Add new L2T entry */ 1134 /* Add new L2T entry */
1135 e = t3_l2t_get(tdev, dst_get_neighbour_noref(new), newdev); 1135 e = t3_l2t_get(tdev, new, newdev);
1136 if (!e) { 1136 if (!e) {
1137 printk(KERN_ERR "%s: couldn't allocate new l2t entry!\n", 1137 printk(KERN_ERR "%s: couldn't allocate new l2t entry!\n",
1138 __func__); 1138 __func__);
diff --git a/drivers/net/ethernet/chelsio/cxgb3/l2t.c b/drivers/net/ethernet/chelsio/cxgb3/l2t.c
index 70fec8b1140f..3fa3c8833ed7 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/l2t.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/l2t.c
@@ -298,18 +298,31 @@ static inline void reuse_entry(struct l2t_entry *e, struct neighbour *neigh)
298 spin_unlock(&e->lock); 298 spin_unlock(&e->lock);
299} 299}
300 300
301struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh, 301struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct dst_entry *dst,
302 struct net_device *dev) 302 struct net_device *dev)
303{ 303{
304 struct l2t_entry *e = NULL; 304 struct l2t_entry *e = NULL;
305 struct neighbour *neigh;
306 struct port_info *p;
305 struct l2t_data *d; 307 struct l2t_data *d;
306 int hash; 308 int hash;
307 u32 addr = *(u32 *) neigh->primary_key; 309 u32 addr;
308 int ifidx = neigh->dev->ifindex; 310 int ifidx;
309 struct port_info *p = netdev_priv(dev); 311 int smt_idx;
310 int smt_idx = p->port_id;
311 312
312 rcu_read_lock(); 313 rcu_read_lock();
314 neigh = dst_get_neighbour_noref(dst);
315 if (!neigh)
316 goto done_rcu;
317
318 addr = *(u32 *) neigh->primary_key;
319 ifidx = neigh->dev->ifindex;
320
321 if (!dev)
322 dev = neigh->dev;
323 p = netdev_priv(dev);
324 smt_idx = p->port_id;
325
313 d = L2DATA(cdev); 326 d = L2DATA(cdev);
314 if (!d) 327 if (!d)
315 goto done_rcu; 328 goto done_rcu;
@@ -323,7 +336,7 @@ struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh,
323 l2t_hold(d, e); 336 l2t_hold(d, e);
324 if (atomic_read(&e->refcnt) == 1) 337 if (atomic_read(&e->refcnt) == 1)
325 reuse_entry(e, neigh); 338 reuse_entry(e, neigh);
326 goto done; 339 goto done_unlock;
327 } 340 }
328 341
329 /* Need to allocate a new entry */ 342 /* Need to allocate a new entry */
@@ -344,7 +357,7 @@ struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh,
344 e->vlan = VLAN_NONE; 357 e->vlan = VLAN_NONE;
345 spin_unlock(&e->lock); 358 spin_unlock(&e->lock);
346 } 359 }
347done: 360done_unlock:
348 write_unlock_bh(&d->lock); 361 write_unlock_bh(&d->lock);
349done_rcu: 362done_rcu:
350 rcu_read_unlock(); 363 rcu_read_unlock();
diff --git a/drivers/net/ethernet/chelsio/cxgb3/l2t.h b/drivers/net/ethernet/chelsio/cxgb3/l2t.h
index c5f54796e2cb..c4e864369751 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/l2t.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/l2t.h
@@ -109,7 +109,7 @@ static inline void set_arp_failure_handler(struct sk_buff *skb,
109 109
110void t3_l2e_free(struct l2t_data *d, struct l2t_entry *e); 110void t3_l2e_free(struct l2t_data *d, struct l2t_entry *e);
111void t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh); 111void t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh);
112struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh, 112struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct dst_entry *dst,
113 struct net_device *dev); 113 struct net_device *dev);
114int t3_l2t_send_slow(struct t3cdev *dev, struct sk_buff *skb, 114int t3_l2t_send_slow(struct t3cdev *dev, struct sk_buff *skb,
115 struct l2t_entry *e); 115 struct l2t_entry *e);
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
index 88902d380f88..36739da8bc15 100644
--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -966,7 +966,7 @@ static int init_act_open(struct cxgbi_sock *csk)
966 csk->saddr.sin_addr.s_addr = chba->ipv4addr; 966 csk->saddr.sin_addr.s_addr = chba->ipv4addr;
967 967
968 csk->rss_qid = 0; 968 csk->rss_qid = 0;
969 csk->l2t = t3_l2t_get(t3dev, dst_get_neighbour_noref(dst), ndev); 969 csk->l2t = t3_l2t_get(t3dev, dst, ndev);
970 if (!csk->l2t) { 970 if (!csk->l2t) {
971 pr_err("NO l2t available.\n"); 971 pr_err("NO l2t available.\n");
972 return -EINVAL; 972 return -EINVAL;