]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/commitdiff
cxgb4: Replace arpq_head/arpq_tail with SKB double link-list code
authorHariprasad Shenai <hariprasad@chelsio.com>
Thu, 17 Dec 2015 08:15:10 +0000 (13:45 +0530)
committerDavid S. Miller <davem@davemloft.net>
Thu, 17 Dec 2015 20:51:05 +0000 (15:51 -0500)
Based on original work by Michael Werner <werner@chelsio.com>

Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/chelsio/cxgb4/l2t.c
drivers/net/ethernet/chelsio/cxgb4/l2t.h

index 81af78ee2d7e54abc5472fcd161a88433660aab5..5b0f3ef348e9ed5df5281af595bd0406c743f95b 100644 (file)
@@ -174,14 +174,10 @@ static int write_l2e(struct adapter *adap, struct l2t_entry *e, int sync)
  */
 static void send_pending(struct adapter *adap, struct l2t_entry *e)
 {
-       while (e->arpq_head) {
-               struct sk_buff *skb = e->arpq_head;
+       struct sk_buff *skb;
 
-               e->arpq_head = skb->next;
-               skb->next = NULL;
+       while ((skb = __skb_dequeue(&e->arpq)) != NULL)
                t4_ofld_send(adap, skb);
-       }
-       e->arpq_tail = NULL;
 }
 
 /*
@@ -221,12 +217,7 @@ void do_l2t_write_rpl(struct adapter *adap, const struct cpl_l2t_write_rpl *rpl)
  */
 static inline void arpq_enqueue(struct l2t_entry *e, struct sk_buff *skb)
 {
-       skb->next = NULL;
-       if (e->arpq_head)
-               e->arpq_tail->next = skb;
-       else
-               e->arpq_head = skb;
-       e->arpq_tail = skb;
+       __skb_queue_tail(&e->arpq, skb);
 }
 
 int cxgb4_l2t_send(struct net_device *dev, struct sk_buff *skb,
@@ -258,7 +249,8 @@ again:
                if (e->state == L2T_STATE_RESOLVING &&
                    !neigh_event_send(e->neigh, NULL)) {
                        spin_lock_bh(&e->lock);
-                       if (e->state == L2T_STATE_RESOLVING && e->arpq_head)
+                       if (e->state == L2T_STATE_RESOLVING &&
+                           !skb_queue_empty(&e->arpq))
                                write_l2e(adap, e, 1);
                        spin_unlock_bh(&e->lock);
                }
@@ -360,19 +352,15 @@ exists:
 static void _t4_l2e_free(struct l2t_entry *e)
 {
        struct l2t_data *d;
+       struct sk_buff *skb;
 
        if (atomic_read(&e->refcnt) == 0) {  /* hasn't been recycled */
                if (e->neigh) {
                        neigh_release(e->neigh);
                        e->neigh = NULL;
                }
-               while (e->arpq_head) {
-                       struct sk_buff *skb = e->arpq_head;
-
-                       e->arpq_head = skb->next;
+               while ((skb = __skb_dequeue(&e->arpq)) != NULL)
                        kfree_skb(skb);
-               }
-               e->arpq_tail = NULL;
        }
 
        d = container_of(e, struct l2t_data, l2tab[e->idx]);
@@ -383,6 +371,7 @@ static void _t4_l2e_free(struct l2t_entry *e)
 static void t4_l2e_free(struct l2t_entry *e)
 {
        struct l2t_data *d;
+       struct sk_buff *skb;
 
        spin_lock_bh(&e->lock);
        if (atomic_read(&e->refcnt) == 0) {  /* hasn't been recycled */
@@ -390,13 +379,8 @@ static void t4_l2e_free(struct l2t_entry *e)
                        neigh_release(e->neigh);
                        e->neigh = NULL;
                }
-               while (e->arpq_head) {
-                       struct sk_buff *skb = e->arpq_head;
-
-                       e->arpq_head = skb->next;
+               while ((skb = __skb_dequeue(&e->arpq)) != NULL)
                        kfree_skb(skb);
-               }
-               e->arpq_tail = NULL;
        }
        spin_unlock_bh(&e->lock);
 
@@ -529,18 +513,19 @@ EXPORT_SYMBOL(cxgb4_select_ntuple);
  * on the arpq head.  If a packet specifies a failure handler it is invoked,
  * otherwise the packet is sent to the device.
  */
-static void handle_failed_resolution(struct adapter *adap, struct sk_buff *arpq)
+static void handle_failed_resolution(struct adapter *adap, struct l2t_entry *e)
 {
-       while (arpq) {
-               struct sk_buff *skb = arpq;
+       struct sk_buff *skb;
+
+       while ((skb = __skb_dequeue(&e->arpq)) != NULL) {
                const struct l2t_skb_cb *cb = L2T_SKB_CB(skb);
 
-               arpq = skb->next;
-               skb->next = NULL;
+               spin_unlock(&e->lock);
                if (cb->arp_err_handler)
                        cb->arp_err_handler(cb->handle, skb);
                else
                        t4_ofld_send(adap, skb);
+               spin_lock(&e->lock);
        }
 }
 
@@ -551,7 +536,7 @@ static void handle_failed_resolution(struct adapter *adap, struct sk_buff *arpq)
 void t4_l2t_update(struct adapter *adap, struct neighbour *neigh)
 {
        struct l2t_entry *e;
-       struct sk_buff *arpq = NULL;
+       struct sk_buff_head *arpq = NULL;
        struct l2t_data *d = adap->l2t;
        int addr_len = neigh->tbl->key_len;
        u32 *addr = (u32 *) neigh->primary_key;
@@ -578,10 +563,9 @@ void t4_l2t_update(struct adapter *adap, struct neighbour *neigh)
 
        if (e->state == L2T_STATE_RESOLVING) {
                if (neigh->nud_state & NUD_FAILED) {
-                       arpq = e->arpq_head;
-                       e->arpq_head = e->arpq_tail = NULL;
+                       arpq = &e->arpq;
                } else if ((neigh->nud_state & (NUD_CONNECTED | NUD_STALE)) &&
-                          e->arpq_head) {
+                          !skb_queue_empty(&e->arpq)) {
                        write_l2e(adap, e, 1);
                }
        } else {
@@ -591,10 +575,9 @@ void t4_l2t_update(struct adapter *adap, struct neighbour *neigh)
                        write_l2e(adap, e, 0);
        }
 
-       spin_unlock_bh(&e->lock);
-
        if (arpq)
-               handle_failed_resolution(adap, arpq);
+               handle_failed_resolution(adap, e);
+       spin_unlock_bh(&e->lock);
 }
 
 /* Allocate an L2T entry for use by a switching rule.  Such need to be
@@ -681,6 +664,7 @@ struct l2t_data *t4_init_l2t(unsigned int l2t_start, unsigned int l2t_end)
                d->l2tab[i].state = L2T_STATE_UNUSED;
                spin_lock_init(&d->l2tab[i].lock);
                atomic_set(&d->l2tab[i].refcnt, 0);
+               skb_queue_head_init(&d->l2tab[i].arpq);
        }
        return d;
 }
@@ -715,7 +699,8 @@ static char l2e_state(const struct l2t_entry *e)
        case L2T_STATE_VALID: return 'V';
        case L2T_STATE_STALE: return 'S';
        case L2T_STATE_SYNC_WRITE: return 'W';
-       case L2T_STATE_RESOLVING: return e->arpq_head ? 'A' : 'R';
+       case L2T_STATE_RESOLVING:
+               return skb_queue_empty(&e->arpq) ? 'R' : 'A';
        case L2T_STATE_SWITCHING: return 'X';
        default:
                return 'U';
index 17803a871ae22c9c9e178ead0b3525c952b237d3..4e2d47ac102b5ab32c771772be81a93d243cadfd 100644 (file)
@@ -76,8 +76,7 @@ struct l2t_entry {
        struct neighbour *neigh;    /* associated neighbour */
        struct l2t_entry *first;    /* start of hash chain */
        struct l2t_entry *next;     /* next l2t_entry on chain */
-       struct sk_buff *arpq_head;  /* queue of packets awaiting resolution */
-       struct sk_buff *arpq_tail;
+       struct sk_buff_head arpq;   /* packet queue awaiting resolution */
        spinlock_t lock;
        atomic_t refcnt;            /* entry reference count */
        u16 hash;                   /* hash bucket the entry is on */