Skip to content

Commit

Permalink
cxgb3: Rework t3_l2t_get to take a dst_entry instead of a neighbour.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David Miller committed Dec 5, 2011
1 parent 51d4597 commit a475712
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 23 deletions.
15 changes: 2 additions & 13 deletions drivers/infiniband/hw/cxgb3/iwch_cm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1338,7 +1338,6 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
struct iwch_ep *child_ep, *parent_ep = ctx;
struct cpl_pass_accept_req *req = cplhdr(skb);
unsigned int hwtid = GET_TID(req);
struct neighbour *neigh;
struct dst_entry *dst;
struct l2t_entry *l2t;
struct rtable *rt;
Expand Down Expand Up @@ -1375,10 +1374,7 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
goto reject;
}
dst = &rt->dst;
rcu_read_lock();
neigh = dst_get_neighbour_noref(dst);
l2t = t3_l2t_get(tdev, neigh, neigh->dev);
rcu_read_unlock();
l2t = t3_l2t_get(tdev, dst, NULL);
if (!l2t) {
printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
__func__);
Expand Down Expand Up @@ -1889,7 +1885,6 @@ static int is_loopback_dst(struct iw_cm_id *cm_id)
int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
{
struct iwch_dev *h = to_iwch_dev(cm_id->device);
struct neighbour *neigh;
struct iwch_ep *ep;
struct rtable *rt;
int err = 0;
Expand Down Expand Up @@ -1947,13 +1942,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
goto fail3;
}
ep->dst = &rt->dst;

rcu_read_lock();
neigh = dst_get_neighbour_noref(ep->dst);

/* get a l2t entry */
ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev);
rcu_read_unlock();
ep->l2t = t3_l2t_get(ep->com.tdev, ep->dst, NULL);
if (!ep->l2t) {
printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
err = -ENOMEM;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -1132,7 +1132,7 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
}

/* Add new L2T entry */
e = t3_l2t_get(tdev, dst_get_neighbour_noref(new), newdev);
e = t3_l2t_get(tdev, new, newdev);
if (!e) {
printk(KERN_ERR "%s: couldn't allocate new l2t entry!\n",
__func__);
Expand Down
27 changes: 20 additions & 7 deletions drivers/net/ethernet/chelsio/cxgb3/l2t.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,18 +298,31 @@ static inline void reuse_entry(struct l2t_entry *e, struct neighbour *neigh)
spin_unlock(&e->lock);
}

struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh,
struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct dst_entry *dst,
struct net_device *dev)
{
struct l2t_entry *e = NULL;
struct neighbour *neigh;
struct port_info *p;
struct l2t_data *d;
int hash;
u32 addr = *(u32 *) neigh->primary_key;
int ifidx = neigh->dev->ifindex;
struct port_info *p = netdev_priv(dev);
int smt_idx = p->port_id;
u32 addr;
int ifidx;
int smt_idx;

rcu_read_lock();
neigh = dst_get_neighbour_noref(dst);
if (!neigh)
goto done_rcu;

addr = *(u32 *) neigh->primary_key;
ifidx = neigh->dev->ifindex;

if (!dev)
dev = neigh->dev;
p = netdev_priv(dev);
smt_idx = p->port_id;

d = L2DATA(cdev);
if (!d)
goto done_rcu;
Expand All @@ -323,7 +336,7 @@ struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh,
l2t_hold(d, e);
if (atomic_read(&e->refcnt) == 1)
reuse_entry(e, neigh);
goto done;
goto done_unlock;
}

/* Need to allocate a new entry */
Expand All @@ -344,7 +357,7 @@ struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh,
e->vlan = VLAN_NONE;
spin_unlock(&e->lock);
}
done:
done_unlock:
write_unlock_bh(&d->lock);
done_rcu:
rcu_read_unlock();
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/chelsio/cxgb3/l2t.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ static inline void set_arp_failure_handler(struct sk_buff *skb,

void t3_l2e_free(struct l2t_data *d, struct l2t_entry *e);
void t3_l2t_update(struct t3cdev *dev, struct neighbour *neigh);
struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh,
struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct dst_entry *dst,
struct net_device *dev);
int t3_l2t_send_slow(struct t3cdev *dev, struct sk_buff *skb,
struct l2t_entry *e);
Expand Down
2 changes: 1 addition & 1 deletion drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ static int init_act_open(struct cxgbi_sock *csk)
csk->saddr.sin_addr.s_addr = chba->ipv4addr;

csk->rss_qid = 0;
csk->l2t = t3_l2t_get(t3dev, dst_get_neighbour_noref(dst), ndev);
csk->l2t = t3_l2t_get(t3dev, dst, ndev);
if (!csk->l2t) {
pr_err("NO l2t available.\n");
return -EINVAL;
Expand Down

0 comments on commit a475712

Please sign in to comment.