1 /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
4 * AoE device utility functions; maintains device list.
7 #include <linux/hdreg.h>
8 #include <linux/blkdev.h>
9 #include <linux/netdevice.h>
12 static struct aoedev *devlist;
13 static spinlock_t devlist_lock;
16 aoedev_by_aoeaddr(int maj, int min)
21 spin_lock_irqsave(&devlist_lock, flags);
23 for (d=devlist; d; d=d->next)
24 if (d->aoemajor == maj && d->aoeminor == min)
27 spin_unlock_irqrestore(&devlist_lock, flags);
31 /* called with devlist lock held */
32 static struct aoedev *
33 aoedev_newdev(ulong nframes)
38 d = kzalloc(sizeof *d, GFP_ATOMIC);
41 f = kcalloc(nframes, sizeof *f, GFP_ATOMIC);
53 spin_lock_init(&d->lock);
54 init_timer(&d->timer);
55 d->bufpool = NULL; /* defer to aoeblk_gdalloc */
56 INIT_LIST_HEAD(&d->bufq);
64 aoedev_downdev(struct aoedev *d)
70 d->flags |= DEVFL_TKILL;
75 for (; f<e; f->tag = FREETAG, f->buf = NULL, f++) {
76 if (f->tag == FREETAG || f->buf == NULL)
80 if (--buf->nframesout == 0) {
81 mempool_free(buf, d->bufpool);
82 bio_endio(bio, bio->bi_size, -EIO);
87 while (!list_empty(&d->bufq)) {
88 buf = container_of(d->bufq.next, struct buf, bufs);
89 list_del(d->bufq.next);
91 mempool_free(buf, d->bufpool);
92 bio_endio(bio, bio->bi_size, -EIO);
96 d->flags |= DEVFL_CLOSEWAIT;
100 d->flags &= ~DEVFL_UP;
104 aoedev_set(ulong sysminor, unsigned char *addr, struct net_device *ifp, ulong bufcnt)
109 spin_lock_irqsave(&devlist_lock, flags);
111 for (d=devlist; d; d=d->next)
112 if (d->sysminor == sysminor)
115 if (d == NULL && (d = aoedev_newdev(bufcnt)) == NULL) {
116 spin_unlock_irqrestore(&devlist_lock, flags);
117 printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n");
119 } /* if newdev, (d->flags & DEVFL_UP) == 0 for below */
121 spin_unlock_irqrestore(&devlist_lock, flags);
122 spin_lock_irqsave(&d->lock, flags);
125 memcpy(d->addr, addr, sizeof d->addr);
126 if ((d->flags & DEVFL_UP) == 0) {
127 aoedev_downdev(d); /* flushes outstanding frames */
128 d->sysminor = sysminor;
129 d->aoemajor = AOEMAJOR(sysminor);
130 d->aoeminor = AOEMINOR(sysminor);
133 spin_unlock_irqrestore(&d->lock, flags);
138 aoedev_freedev(struct aoedev *d)
147 mempool_destroy(d->bufpool);
157 flush_scheduled_work();
159 while ((d = devlist)) {
162 spin_lock_irqsave(&d->lock, flags);
164 spin_unlock_irqrestore(&d->lock, flags);
166 del_timer_sync(&d->timer);
174 spin_lock_init(&devlist_lock);