struct aoedev * aoedev_set(ulong sysminor, unsigned char *addr, struct net_device *ifp, ulong bufcnt) { struct aoedev *d; ulong flags; spin_lock_irqsave(&devlist_lock, flags); for (d=devlist; d; d=d->next) if (d->sysminor == sysminor) break; if (d == NULL && (d = aoedev_newdev(bufcnt)) == NULL) { spin_unlock_irqrestore(&devlist_lock, flags); printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n"); return NULL; } /* if newdev, (d->flags & DEVFL_UP) == 0 for below */ spin_unlock_irqrestore(&devlist_lock, flags); spin_lock_irqsave(&d->lock, flags); d->ifp = ifp; memcpy(d->addr, addr, sizeof d->addr); if ((d->flags & DEVFL_UP) == 0) { aoedev_downdev(d); /* flushes outstanding frames */ d->sysminor = sysminor; d->aoemajor = AOEMAJOR(sysminor); d->aoeminor = AOEMINOR(sysminor); } spin_unlock_irqrestore(&d->lock, flags); return d; }
/* find it or malloc it */ struct aoedev * aoedev_by_sysminor_m(ulong sysminor) { struct aoedev *d; ulong flags; spin_lock_irqsave(&devlist_lock, flags); for (d=devlist; d; d=d->next) if (d->sysminor == sysminor) break; if (d) goto out; d = kcalloc(1, sizeof *d, GFP_ATOMIC); if (!d) goto out; INIT_WORK(&d->work, aoecmd_sleepwork); spin_lock_init(&d->lock); skb_queue_head_init(&d->sendq); skb_queue_head_init(&d->skbpool); init_timer(&d->timer); d->timer.data = (ulong) d; d->timer.function = dummy_timer; d->timer.expires = jiffies + HZ; add_timer(&d->timer); d->bufpool = NULL; /* defer to aoeblk_gdalloc */ d->tgt = d->targets; INIT_LIST_HEAD(&d->bufq); d->sysminor = sysminor; d->aoemajor = AOEMAJOR(sysminor); d->aoeminor = AOEMINOR(sysminor); d->mintimer = MINTIMER; d->next = devlist; devlist = d; out: spin_unlock_irqrestore(&devlist_lock, flags); return d; }