Commit e9bb8fb0 authored by David S. Miller's avatar David S. Miller

aoe: Use SKB interfaces for list management instead of home-grown stuff.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 67fed459
...@@ -159,11 +159,8 @@ struct aoedev { ...@@ -159,11 +159,8 @@ struct aoedev {
sector_t ssize; sector_t ssize;
struct timer_list timer; struct timer_list timer;
spinlock_t lock; spinlock_t lock;
struct sk_buff *sendq_hd; /* packets needing to be sent, list head */ struct sk_buff_head sendq;
struct sk_buff *sendq_tl; struct sk_buff_head skbpool;
struct sk_buff *skbpool_hd;
struct sk_buff *skbpool_tl;
int nskbpool;
mempool_t *bufpool; /* for deadlock-free Buf allocation */ mempool_t *bufpool; /* for deadlock-free Buf allocation */
struct list_head bufq; /* queue of bios to work on */ struct list_head bufq; /* queue of bios to work on */
struct buf *inprocess; /* the one we're currently working on */ struct buf *inprocess; /* the one we're currently working on */
...@@ -199,7 +196,7 @@ int aoedev_flush(const char __user *str, size_t size); ...@@ -199,7 +196,7 @@ int aoedev_flush(const char __user *str, size_t size);
int aoenet_init(void); int aoenet_init(void);
void aoenet_exit(void); void aoenet_exit(void);
void aoenet_xmit(struct sk_buff *); void aoenet_xmit(struct sk_buff_head *);
int is_aoe_netif(struct net_device *ifp); int is_aoe_netif(struct net_device *ifp);
int set_aoe_iflist(const char __user *str, size_t size); int set_aoe_iflist(const char __user *str, size_t size);
......
...@@ -158,9 +158,9 @@ aoeblk_release(struct inode *inode, struct file *filp) ...@@ -158,9 +158,9 @@ aoeblk_release(struct inode *inode, struct file *filp)
static int static int
aoeblk_make_request(struct request_queue *q, struct bio *bio) aoeblk_make_request(struct request_queue *q, struct bio *bio)
{ {
struct sk_buff_head queue;
struct aoedev *d; struct aoedev *d;
struct buf *buf; struct buf *buf;
struct sk_buff *sl;
ulong flags; ulong flags;
blk_queue_bounce(q, &bio); blk_queue_bounce(q, &bio);
...@@ -213,11 +213,11 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio) ...@@ -213,11 +213,11 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio)
list_add_tail(&buf->bufs, &d->bufq); list_add_tail(&buf->bufs, &d->bufq);
aoecmd_work(d); aoecmd_work(d);
sl = d->sendq_hd; __skb_queue_head_init(&queue);
d->sendq_hd = d->sendq_tl = NULL; skb_queue_splice_init(&d->sendq, &queue);
spin_unlock_irqrestore(&d->lock, flags); spin_unlock_irqrestore(&d->lock, flags);
aoenet_xmit(sl); aoenet_xmit(&queue);
return 0; return 0;
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/skbuff.h>
#include "aoe.h" #include "aoe.h"
enum { enum {
...@@ -103,7 +104,12 @@ loop: ...@@ -103,7 +104,12 @@ loop:
spin_lock_irqsave(&d->lock, flags); spin_lock_irqsave(&d->lock, flags);
goto loop; goto loop;
} }
aoenet_xmit(skb); if (skb) {
struct sk_buff_head queue;
__skb_queue_head_init(&queue);
__skb_queue_tail(&queue, skb);
aoenet_xmit(&queue);
}
aoecmd_cfg(major, minor); aoecmd_cfg(major, minor);
return 0; return 0;
} }
......
...@@ -114,29 +114,22 @@ ifrotate(struct aoetgt *t) ...@@ -114,29 +114,22 @@ ifrotate(struct aoetgt *t)
static void static void
skb_pool_put(struct aoedev *d, struct sk_buff *skb) skb_pool_put(struct aoedev *d, struct sk_buff *skb)
{ {
if (!d->skbpool_hd) __skb_queue_tail(&d->skbpool, skb);
d->skbpool_hd = skb;
else
d->skbpool_tl->next = skb;
d->skbpool_tl = skb;
} }
static struct sk_buff * static struct sk_buff *
skb_pool_get(struct aoedev *d) skb_pool_get(struct aoedev *d)
{ {
struct sk_buff *skb; struct sk_buff *skb = skb_peek(&d->skbpool);
skb = d->skbpool_hd;
if (skb && atomic_read(&skb_shinfo(skb)->dataref) == 1) { if (skb && atomic_read(&skb_shinfo(skb)->dataref) == 1) {
d->skbpool_hd = skb->next; __skb_unlink(skb, &d->skbpool);
skb->next = NULL;
return skb; return skb;
} }
if (d->nskbpool < NSKBPOOLMAX if (skb_queue_len(&d->skbpool) < NSKBPOOLMAX &&
&& (skb = new_skb(ETH_ZLEN))) { (skb = new_skb(ETH_ZLEN)))
d->nskbpool++;
return skb; return skb;
}
return NULL; return NULL;
} }
...@@ -293,29 +286,22 @@ aoecmd_ata_rw(struct aoedev *d) ...@@ -293,29 +286,22 @@ aoecmd_ata_rw(struct aoedev *d)
skb->dev = t->ifp->nd; skb->dev = t->ifp->nd;
skb = skb_clone(skb, GFP_ATOMIC); skb = skb_clone(skb, GFP_ATOMIC);
if (skb) { if (skb)
if (d->sendq_hd) __skb_queue_tail(&d->sendq, skb);
d->sendq_tl->next = skb;
else
d->sendq_hd = skb;
d->sendq_tl = skb;
}
return 1; return 1;
} }
/* some callers cannot sleep, and they can call this function, /* some callers cannot sleep, and they can call this function,
* transmitting the packets later, when interrupts are on * transmitting the packets later, when interrupts are on
*/ */
static struct sk_buff * static void
aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff_head *queue)
{ {
struct aoe_hdr *h; struct aoe_hdr *h;
struct aoe_cfghdr *ch; struct aoe_cfghdr *ch;
struct sk_buff *skb, *sl, *sl_tail; struct sk_buff *skb;
struct net_device *ifp; struct net_device *ifp;
sl = sl_tail = NULL;
read_lock(&dev_base_lock); read_lock(&dev_base_lock);
for_each_netdev(&init_net, ifp) { for_each_netdev(&init_net, ifp) {
dev_hold(ifp); dev_hold(ifp);
...@@ -329,8 +315,7 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) ...@@ -329,8 +315,7 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
} }
skb_put(skb, sizeof *h + sizeof *ch); skb_put(skb, sizeof *h + sizeof *ch);
skb->dev = ifp; skb->dev = ifp;
if (sl_tail == NULL) __skb_queue_tail(queue, skb);
sl_tail = skb;
h = (struct aoe_hdr *) skb_mac_header(skb); h = (struct aoe_hdr *) skb_mac_header(skb);
memset(h, 0, sizeof *h + sizeof *ch); memset(h, 0, sizeof *h + sizeof *ch);
...@@ -342,16 +327,10 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) ...@@ -342,16 +327,10 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
h->minor = aoeminor; h->minor = aoeminor;
h->cmd = AOECMD_CFG; h->cmd = AOECMD_CFG;
skb->next = sl;
sl = skb;
cont: cont:
dev_put(ifp); dev_put(ifp);
} }
read_unlock(&dev_base_lock); read_unlock(&dev_base_lock);
if (tail != NULL)
*tail = sl_tail;
return sl;
} }
static void static void
...@@ -406,11 +385,7 @@ resend(struct aoedev *d, struct aoetgt *t, struct frame *f) ...@@ -406,11 +385,7 @@ resend(struct aoedev *d, struct aoetgt *t, struct frame *f)
skb = skb_clone(skb, GFP_ATOMIC); skb = skb_clone(skb, GFP_ATOMIC);
if (skb == NULL) if (skb == NULL)
return; return;
if (d->sendq_hd) __skb_queue_tail(&d->sendq, skb);
d->sendq_tl->next = skb;
else
d->sendq_hd = skb;
d->sendq_tl = skb;
} }
static int static int
...@@ -508,16 +483,15 @@ ata_scnt(unsigned char *packet) { ...@@ -508,16 +483,15 @@ ata_scnt(unsigned char *packet) {
static void static void
rexmit_timer(ulong vp) rexmit_timer(ulong vp)
{ {
struct sk_buff_head queue;
struct aoedev *d; struct aoedev *d;
struct aoetgt *t, **tt, **te; struct aoetgt *t, **tt, **te;
struct aoeif *ifp; struct aoeif *ifp;
struct frame *f, *e; struct frame *f, *e;
struct sk_buff *sl;
register long timeout; register long timeout;
ulong flags, n; ulong flags, n;
d = (struct aoedev *) vp; d = (struct aoedev *) vp;
sl = NULL;
/* timeout is always ~150% of the moving average */ /* timeout is always ~150% of the moving average */
timeout = d->rttavg; timeout = d->rttavg;
...@@ -589,7 +563,7 @@ rexmit_timer(ulong vp) ...@@ -589,7 +563,7 @@ rexmit_timer(ulong vp)
} }
} }
if (d->sendq_hd) { if (!skb_queue_empty(&d->sendq)) {
n = d->rttavg <<= 1; n = d->rttavg <<= 1;
if (n > MAXTIMER) if (n > MAXTIMER)
d->rttavg = MAXTIMER; d->rttavg = MAXTIMER;
...@@ -600,15 +574,15 @@ rexmit_timer(ulong vp) ...@@ -600,15 +574,15 @@ rexmit_timer(ulong vp)
aoecmd_work(d); aoecmd_work(d);
} }
sl = d->sendq_hd; __skb_queue_head_init(&queue);
d->sendq_hd = d->sendq_tl = NULL; skb_queue_splice_init(&d->sendq, &queue);
d->timer.expires = jiffies + TIMERTICK; d->timer.expires = jiffies + TIMERTICK;
add_timer(&d->timer); add_timer(&d->timer);
spin_unlock_irqrestore(&d->lock, flags); spin_unlock_irqrestore(&d->lock, flags);
aoenet_xmit(sl); aoenet_xmit(&queue);
} }
/* enters with d->lock held */ /* enters with d->lock held */
...@@ -767,12 +741,12 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector ...@@ -767,12 +741,12 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector
void void
aoecmd_ata_rsp(struct sk_buff *skb) aoecmd_ata_rsp(struct sk_buff *skb)
{ {
struct sk_buff_head queue;
struct aoedev *d; struct aoedev *d;
struct aoe_hdr *hin, *hout; struct aoe_hdr *hin, *hout;
struct aoe_atahdr *ahin, *ahout; struct aoe_atahdr *ahin, *ahout;
struct frame *f; struct frame *f;
struct buf *buf; struct buf *buf;
struct sk_buff *sl;
struct aoetgt *t; struct aoetgt *t;
struct aoeif *ifp; struct aoeif *ifp;
register long n; register long n;
...@@ -893,21 +867,21 @@ aoecmd_ata_rsp(struct sk_buff *skb) ...@@ -893,21 +867,21 @@ aoecmd_ata_rsp(struct sk_buff *skb)
aoecmd_work(d); aoecmd_work(d);
xmit: xmit:
sl = d->sendq_hd; __skb_queue_head_init(&queue);
d->sendq_hd = d->sendq_tl = NULL; skb_queue_splice_init(&d->sendq, &queue);
spin_unlock_irqrestore(&d->lock, flags); spin_unlock_irqrestore(&d->lock, flags);
aoenet_xmit(sl); aoenet_xmit(&queue);
} }
void void
aoecmd_cfg(ushort aoemajor, unsigned char aoeminor) aoecmd_cfg(ushort aoemajor, unsigned char aoeminor)
{ {
struct sk_buff *sl; struct sk_buff_head queue;
sl = aoecmd_cfg_pkts(aoemajor, aoeminor, NULL);
aoenet_xmit(sl); __skb_queue_head_init(&queue);
aoecmd_cfg_pkts(aoemajor, aoeminor, &queue);
aoenet_xmit(&queue);
} }
struct sk_buff * struct sk_buff *
...@@ -1076,7 +1050,12 @@ aoecmd_cfg_rsp(struct sk_buff *skb) ...@@ -1076,7 +1050,12 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
spin_unlock_irqrestore(&d->lock, flags); spin_unlock_irqrestore(&d->lock, flags);
aoenet_xmit(sl); if (sl) {
struct sk_buff_head queue;
__skb_queue_head_init(&queue);
__skb_queue_tail(&queue, sl);
aoenet_xmit(&queue);
}
} }
void void
......
...@@ -188,14 +188,12 @@ skbfree(struct sk_buff *skb) ...@@ -188,14 +188,12 @@ skbfree(struct sk_buff *skb)
static void static void
skbpoolfree(struct aoedev *d) skbpoolfree(struct aoedev *d)
{ {
struct sk_buff *skb; struct sk_buff *skb, *tmp;
while ((skb = d->skbpool_hd)) { skb_queue_walk_safe(&d->skbpool, skb, tmp)
d->skbpool_hd = skb->next;
skb->next = NULL;
skbfree(skb); skbfree(skb);
}
d->skbpool_tl = NULL; __skb_queue_head_init(&d->skbpool);
} }
/* find it or malloc it */ /* find it or malloc it */
...@@ -217,6 +215,8 @@ aoedev_by_sysminor_m(ulong sysminor) ...@@ -217,6 +215,8 @@ aoedev_by_sysminor_m(ulong sysminor)
goto out; goto out;
INIT_WORK(&d->work, aoecmd_sleepwork); INIT_WORK(&d->work, aoecmd_sleepwork);
spin_lock_init(&d->lock); spin_lock_init(&d->lock);
skb_queue_head_init(&d->sendq);
skb_queue_head_init(&d->skbpool);
init_timer(&d->timer); init_timer(&d->timer);
d->timer.data = (ulong) d; d->timer.data = (ulong) d;
d->timer.function = dummy_timer; d->timer.function = dummy_timer;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/hdreg.h> #include <linux/hdreg.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/skbuff.h>
#include "aoe.h" #include "aoe.h"
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -95,15 +95,12 @@ mac_addr(char addr[6]) ...@@ -95,15 +95,12 @@ mac_addr(char addr[6])
} }
void void
aoenet_xmit(struct sk_buff *sl) aoenet_xmit(struct sk_buff_head *queue)
{ {
struct sk_buff *skb; struct sk_buff *skb, *tmp;
while ((skb = sl)) { skb_queue_walk_safe(queue, skb, tmp)
sl = sl->next;
skb->next = skb->prev = NULL;
dev_queue_xmit(skb); dev_queue_xmit(skb);
}
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment