1*4882a593Smuzhiyun /* Copyright (c) 2013 Coraid, Inc. See COPYING for GPL terms. */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * aoedev.c
4*4882a593Smuzhiyun * AoE device utility functions; maintains device list.
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/hdreg.h>
8*4882a593Smuzhiyun #include <linux/blk-mq.h>
9*4882a593Smuzhiyun #include <linux/netdevice.h>
10*4882a593Smuzhiyun #include <linux/delay.h>
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun #include <linux/bitmap.h>
13*4882a593Smuzhiyun #include <linux/kdev_t.h>
14*4882a593Smuzhiyun #include <linux/moduleparam.h>
15*4882a593Smuzhiyun #include <linux/string.h>
16*4882a593Smuzhiyun #include "aoe.h"
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun static void freetgt(struct aoedev *d, struct aoetgt *t);
19*4882a593Smuzhiyun static void skbpoolfree(struct aoedev *d);
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun static int aoe_dyndevs = 1;
22*4882a593Smuzhiyun module_param(aoe_dyndevs, int, 0644);
23*4882a593Smuzhiyun MODULE_PARM_DESC(aoe_dyndevs, "Use dynamic minor numbers for devices.");
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun static struct aoedev *devlist;
26*4882a593Smuzhiyun static DEFINE_SPINLOCK(devlist_lock);
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /* Because some systems will have one, many, or no
29*4882a593Smuzhiyun * - partitions,
30*4882a593Smuzhiyun * - slots per shelf,
31*4882a593Smuzhiyun * - or shelves,
32*4882a593Smuzhiyun * we need some flexibility in the way the minor numbers
33*4882a593Smuzhiyun * are allocated. So they are dynamic.
34*4882a593Smuzhiyun */
35*4882a593Smuzhiyun #define N_DEVS ((1U<<MINORBITS)/AOE_PARTITIONS)
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun static DEFINE_SPINLOCK(used_minors_lock);
38*4882a593Smuzhiyun static DECLARE_BITMAP(used_minors, N_DEVS);
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun static int
minor_get_dyn(ulong * sysminor)41*4882a593Smuzhiyun minor_get_dyn(ulong *sysminor)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun ulong flags;
44*4882a593Smuzhiyun ulong n;
45*4882a593Smuzhiyun int error = 0;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun spin_lock_irqsave(&used_minors_lock, flags);
48*4882a593Smuzhiyun n = find_first_zero_bit(used_minors, N_DEVS);
49*4882a593Smuzhiyun if (n < N_DEVS)
50*4882a593Smuzhiyun set_bit(n, used_minors);
51*4882a593Smuzhiyun else
52*4882a593Smuzhiyun error = -1;
53*4882a593Smuzhiyun spin_unlock_irqrestore(&used_minors_lock, flags);
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun *sysminor = n * AOE_PARTITIONS;
56*4882a593Smuzhiyun return error;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun static int
minor_get_static(ulong * sysminor,ulong aoemaj,int aoemin)60*4882a593Smuzhiyun minor_get_static(ulong *sysminor, ulong aoemaj, int aoemin)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun ulong flags;
63*4882a593Smuzhiyun ulong n;
64*4882a593Smuzhiyun int error = 0;
65*4882a593Smuzhiyun enum {
66*4882a593Smuzhiyun /* for backwards compatibility when !aoe_dyndevs,
67*4882a593Smuzhiyun * a static number of supported slots per shelf */
68*4882a593Smuzhiyun NPERSHELF = 16,
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun if (aoemin >= NPERSHELF) {
72*4882a593Smuzhiyun pr_err("aoe: %s %d slots per shelf\n",
73*4882a593Smuzhiyun "static minor device numbers support only",
74*4882a593Smuzhiyun NPERSHELF);
75*4882a593Smuzhiyun error = -1;
76*4882a593Smuzhiyun goto out;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun n = aoemaj * NPERSHELF + aoemin;
80*4882a593Smuzhiyun if (n >= N_DEVS) {
81*4882a593Smuzhiyun pr_err("aoe: %s with e%ld.%d\n",
82*4882a593Smuzhiyun "cannot use static minor device numbers",
83*4882a593Smuzhiyun aoemaj, aoemin);
84*4882a593Smuzhiyun error = -1;
85*4882a593Smuzhiyun goto out;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun spin_lock_irqsave(&used_minors_lock, flags);
89*4882a593Smuzhiyun if (test_bit(n, used_minors)) {
90*4882a593Smuzhiyun pr_err("aoe: %s %lu\n",
91*4882a593Smuzhiyun "existing device already has static minor number",
92*4882a593Smuzhiyun n);
93*4882a593Smuzhiyun error = -1;
94*4882a593Smuzhiyun } else
95*4882a593Smuzhiyun set_bit(n, used_minors);
96*4882a593Smuzhiyun spin_unlock_irqrestore(&used_minors_lock, flags);
97*4882a593Smuzhiyun *sysminor = n * AOE_PARTITIONS;
98*4882a593Smuzhiyun out:
99*4882a593Smuzhiyun return error;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun static int
minor_get(ulong * sysminor,ulong aoemaj,int aoemin)103*4882a593Smuzhiyun minor_get(ulong *sysminor, ulong aoemaj, int aoemin)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun if (aoe_dyndevs)
106*4882a593Smuzhiyun return minor_get_dyn(sysminor);
107*4882a593Smuzhiyun else
108*4882a593Smuzhiyun return minor_get_static(sysminor, aoemaj, aoemin);
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun static void
minor_free(ulong minor)112*4882a593Smuzhiyun minor_free(ulong minor)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun ulong flags;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun minor /= AOE_PARTITIONS;
117*4882a593Smuzhiyun BUG_ON(minor >= N_DEVS);
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun spin_lock_irqsave(&used_minors_lock, flags);
120*4882a593Smuzhiyun BUG_ON(!test_bit(minor, used_minors));
121*4882a593Smuzhiyun clear_bit(minor, used_minors);
122*4882a593Smuzhiyun spin_unlock_irqrestore(&used_minors_lock, flags);
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun /*
126*4882a593Smuzhiyun * Users who grab a pointer to the device with aoedev_by_aoeaddr
127*4882a593Smuzhiyun * automatically get a reference count and must be responsible
128*4882a593Smuzhiyun * for performing a aoedev_put. With the addition of async
129*4882a593Smuzhiyun * kthread processing I'm no longer confident that we can
130*4882a593Smuzhiyun * guarantee consistency in the face of device flushes.
131*4882a593Smuzhiyun *
132*4882a593Smuzhiyun * For the time being, we only bother to add extra references for
133*4882a593Smuzhiyun * frames sitting on the iocq. When the kthreads finish processing
134*4882a593Smuzhiyun * these frames, they will aoedev_put the device.
135*4882a593Smuzhiyun */
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun void
aoedev_put(struct aoedev * d)138*4882a593Smuzhiyun aoedev_put(struct aoedev *d)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun ulong flags;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun spin_lock_irqsave(&devlist_lock, flags);
143*4882a593Smuzhiyun d->ref--;
144*4882a593Smuzhiyun spin_unlock_irqrestore(&devlist_lock, flags);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun static void
dummy_timer(struct timer_list * t)148*4882a593Smuzhiyun dummy_timer(struct timer_list *t)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun struct aoedev *d;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun d = from_timer(d, t, timer);
153*4882a593Smuzhiyun if (d->flags & DEVFL_TKILL)
154*4882a593Smuzhiyun return;
155*4882a593Smuzhiyun d->timer.expires = jiffies + HZ;
156*4882a593Smuzhiyun add_timer(&d->timer);
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun static void
aoe_failip(struct aoedev * d)160*4882a593Smuzhiyun aoe_failip(struct aoedev *d)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun struct request *rq;
163*4882a593Smuzhiyun struct aoe_req *req;
164*4882a593Smuzhiyun struct bio *bio;
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun aoe_failbuf(d, d->ip.buf);
167*4882a593Smuzhiyun rq = d->ip.rq;
168*4882a593Smuzhiyun if (rq == NULL)
169*4882a593Smuzhiyun return;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun req = blk_mq_rq_to_pdu(rq);
172*4882a593Smuzhiyun while ((bio = d->ip.nxbio)) {
173*4882a593Smuzhiyun bio->bi_status = BLK_STS_IOERR;
174*4882a593Smuzhiyun d->ip.nxbio = bio->bi_next;
175*4882a593Smuzhiyun req->nr_bios--;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun if (!req->nr_bios)
179*4882a593Smuzhiyun aoe_end_request(d, rq, 0);
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun static void
downdev_frame(struct list_head * pos)183*4882a593Smuzhiyun downdev_frame(struct list_head *pos)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun struct frame *f;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun f = list_entry(pos, struct frame, head);
188*4882a593Smuzhiyun list_del(pos);
189*4882a593Smuzhiyun if (f->buf) {
190*4882a593Smuzhiyun f->buf->nframesout--;
191*4882a593Smuzhiyun aoe_failbuf(f->t->d, f->buf);
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun aoe_freetframe(f);
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun void
aoedev_downdev(struct aoedev * d)197*4882a593Smuzhiyun aoedev_downdev(struct aoedev *d)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun struct aoetgt *t, **tt, **te;
200*4882a593Smuzhiyun struct list_head *head, *pos, *nx;
201*4882a593Smuzhiyun int i;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun d->flags &= ~DEVFL_UP;
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun /* clean out active and to-be-retransmitted buffers */
206*4882a593Smuzhiyun for (i = 0; i < NFACTIVE; i++) {
207*4882a593Smuzhiyun head = &d->factive[i];
208*4882a593Smuzhiyun list_for_each_safe(pos, nx, head)
209*4882a593Smuzhiyun downdev_frame(pos);
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun head = &d->rexmitq;
212*4882a593Smuzhiyun list_for_each_safe(pos, nx, head)
213*4882a593Smuzhiyun downdev_frame(pos);
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun /* reset window dressings */
216*4882a593Smuzhiyun tt = d->targets;
217*4882a593Smuzhiyun te = tt + d->ntargets;
218*4882a593Smuzhiyun for (; tt < te && (t = *tt); tt++) {
219*4882a593Smuzhiyun aoecmd_wreset(t);
220*4882a593Smuzhiyun t->nout = 0;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun /* clean out the in-process request (if any) */
224*4882a593Smuzhiyun aoe_failip(d);
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun /* fast fail all pending I/O */
227*4882a593Smuzhiyun if (d->blkq) {
228*4882a593Smuzhiyun /* UP is cleared, freeze+quiesce to insure all are errored */
229*4882a593Smuzhiyun blk_mq_freeze_queue(d->blkq);
230*4882a593Smuzhiyun blk_mq_quiesce_queue(d->blkq);
231*4882a593Smuzhiyun blk_mq_unquiesce_queue(d->blkq);
232*4882a593Smuzhiyun blk_mq_unfreeze_queue(d->blkq);
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun if (d->gd)
236*4882a593Smuzhiyun set_capacity(d->gd, 0);
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun /* return whether the user asked for this particular
240*4882a593Smuzhiyun * device to be flushed
241*4882a593Smuzhiyun */
242*4882a593Smuzhiyun static int
user_req(char * s,size_t slen,struct aoedev * d)243*4882a593Smuzhiyun user_req(char *s, size_t slen, struct aoedev *d)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun const char *p;
246*4882a593Smuzhiyun size_t lim;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun if (!d->gd)
249*4882a593Smuzhiyun return 0;
250*4882a593Smuzhiyun p = kbasename(d->gd->disk_name);
251*4882a593Smuzhiyun lim = sizeof(d->gd->disk_name);
252*4882a593Smuzhiyun lim -= p - d->gd->disk_name;
253*4882a593Smuzhiyun if (slen < lim)
254*4882a593Smuzhiyun lim = slen;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun return !strncmp(s, p, lim);
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun static void
freedev(struct aoedev * d)260*4882a593Smuzhiyun freedev(struct aoedev *d)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun struct aoetgt **t, **e;
263*4882a593Smuzhiyun int freeing = 0;
264*4882a593Smuzhiyun unsigned long flags;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun spin_lock_irqsave(&d->lock, flags);
267*4882a593Smuzhiyun if (d->flags & DEVFL_TKILL
268*4882a593Smuzhiyun && !(d->flags & DEVFL_FREEING)) {
269*4882a593Smuzhiyun d->flags |= DEVFL_FREEING;
270*4882a593Smuzhiyun freeing = 1;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun spin_unlock_irqrestore(&d->lock, flags);
273*4882a593Smuzhiyun if (!freeing)
274*4882a593Smuzhiyun return;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun del_timer_sync(&d->timer);
277*4882a593Smuzhiyun if (d->gd) {
278*4882a593Smuzhiyun aoedisk_rm_debugfs(d);
279*4882a593Smuzhiyun del_gendisk(d->gd);
280*4882a593Smuzhiyun put_disk(d->gd);
281*4882a593Smuzhiyun blk_mq_free_tag_set(&d->tag_set);
282*4882a593Smuzhiyun blk_cleanup_queue(d->blkq);
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun t = d->targets;
285*4882a593Smuzhiyun e = t + d->ntargets;
286*4882a593Smuzhiyun for (; t < e && *t; t++)
287*4882a593Smuzhiyun freetgt(d, *t);
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun mempool_destroy(d->bufpool);
290*4882a593Smuzhiyun skbpoolfree(d);
291*4882a593Smuzhiyun minor_free(d->sysminor);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun spin_lock_irqsave(&d->lock, flags);
294*4882a593Smuzhiyun d->flags |= DEVFL_FREED;
295*4882a593Smuzhiyun spin_unlock_irqrestore(&d->lock, flags);
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun enum flush_parms {
299*4882a593Smuzhiyun NOT_EXITING = 0,
300*4882a593Smuzhiyun EXITING = 1,
301*4882a593Smuzhiyun };
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun static int
flush(const char __user * str,size_t cnt,int exiting)304*4882a593Smuzhiyun flush(const char __user *str, size_t cnt, int exiting)
305*4882a593Smuzhiyun {
306*4882a593Smuzhiyun ulong flags;
307*4882a593Smuzhiyun struct aoedev *d, **dd;
308*4882a593Smuzhiyun char buf[16];
309*4882a593Smuzhiyun int all = 0;
310*4882a593Smuzhiyun int specified = 0; /* flush a specific device */
311*4882a593Smuzhiyun unsigned int skipflags;
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun skipflags = DEVFL_GDALLOC | DEVFL_NEWSIZE | DEVFL_TKILL;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun if (!exiting && cnt >= 3) {
316*4882a593Smuzhiyun if (cnt > sizeof buf)
317*4882a593Smuzhiyun cnt = sizeof buf;
318*4882a593Smuzhiyun if (copy_from_user(buf, str, cnt))
319*4882a593Smuzhiyun return -EFAULT;
320*4882a593Smuzhiyun all = !strncmp(buf, "all", 3);
321*4882a593Smuzhiyun if (!all)
322*4882a593Smuzhiyun specified = 1;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun flush_scheduled_work();
326*4882a593Smuzhiyun /* pass one: do aoedev_downdev, which might sleep */
327*4882a593Smuzhiyun restart1:
328*4882a593Smuzhiyun spin_lock_irqsave(&devlist_lock, flags);
329*4882a593Smuzhiyun for (d = devlist; d; d = d->next) {
330*4882a593Smuzhiyun spin_lock(&d->lock);
331*4882a593Smuzhiyun if (d->flags & DEVFL_TKILL)
332*4882a593Smuzhiyun goto cont;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun if (exiting) {
335*4882a593Smuzhiyun /* unconditionally take each device down */
336*4882a593Smuzhiyun } else if (specified) {
337*4882a593Smuzhiyun if (!user_req(buf, cnt, d))
338*4882a593Smuzhiyun goto cont;
339*4882a593Smuzhiyun } else if ((!all && (d->flags & DEVFL_UP))
340*4882a593Smuzhiyun || d->flags & skipflags
341*4882a593Smuzhiyun || d->nopen
342*4882a593Smuzhiyun || d->ref)
343*4882a593Smuzhiyun goto cont;
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun spin_unlock(&d->lock);
346*4882a593Smuzhiyun spin_unlock_irqrestore(&devlist_lock, flags);
347*4882a593Smuzhiyun aoedev_downdev(d);
348*4882a593Smuzhiyun d->flags |= DEVFL_TKILL;
349*4882a593Smuzhiyun goto restart1;
350*4882a593Smuzhiyun cont:
351*4882a593Smuzhiyun spin_unlock(&d->lock);
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun spin_unlock_irqrestore(&devlist_lock, flags);
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun /* pass two: call freedev, which might sleep,
356*4882a593Smuzhiyun * for aoedevs marked with DEVFL_TKILL
357*4882a593Smuzhiyun */
358*4882a593Smuzhiyun restart2:
359*4882a593Smuzhiyun spin_lock_irqsave(&devlist_lock, flags);
360*4882a593Smuzhiyun for (d = devlist; d; d = d->next) {
361*4882a593Smuzhiyun spin_lock(&d->lock);
362*4882a593Smuzhiyun if (d->flags & DEVFL_TKILL
363*4882a593Smuzhiyun && !(d->flags & DEVFL_FREEING)) {
364*4882a593Smuzhiyun spin_unlock(&d->lock);
365*4882a593Smuzhiyun spin_unlock_irqrestore(&devlist_lock, flags);
366*4882a593Smuzhiyun freedev(d);
367*4882a593Smuzhiyun goto restart2;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun spin_unlock(&d->lock);
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun /* pass three: remove aoedevs marked with DEVFL_FREED */
373*4882a593Smuzhiyun for (dd = &devlist, d = *dd; d; d = *dd) {
374*4882a593Smuzhiyun struct aoedev *doomed = NULL;
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun spin_lock(&d->lock);
377*4882a593Smuzhiyun if (d->flags & DEVFL_FREED) {
378*4882a593Smuzhiyun *dd = d->next;
379*4882a593Smuzhiyun doomed = d;
380*4882a593Smuzhiyun } else {
381*4882a593Smuzhiyun dd = &d->next;
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun spin_unlock(&d->lock);
384*4882a593Smuzhiyun if (doomed)
385*4882a593Smuzhiyun kfree(doomed->targets);
386*4882a593Smuzhiyun kfree(doomed);
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun spin_unlock_irqrestore(&devlist_lock, flags);
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun return 0;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun int
aoedev_flush(const char __user * str,size_t cnt)394*4882a593Smuzhiyun aoedev_flush(const char __user *str, size_t cnt)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun return flush(str, cnt, NOT_EXITING);
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun /* This has been confirmed to occur once with Tms=3*1000 due to the
400*4882a593Smuzhiyun * driver changing link and not processing its transmit ring. The
401*4882a593Smuzhiyun * problem is hard enough to solve by returning an error that I'm
402*4882a593Smuzhiyun * still punting on "solving" this.
403*4882a593Smuzhiyun */
404*4882a593Smuzhiyun static void
skbfree(struct sk_buff * skb)405*4882a593Smuzhiyun skbfree(struct sk_buff *skb)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun enum { Sms = 250, Tms = 30 * 1000};
408*4882a593Smuzhiyun int i = Tms / Sms;
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun if (skb == NULL)
411*4882a593Smuzhiyun return;
412*4882a593Smuzhiyun while (atomic_read(&skb_shinfo(skb)->dataref) != 1 && i-- > 0)
413*4882a593Smuzhiyun msleep(Sms);
414*4882a593Smuzhiyun if (i < 0) {
415*4882a593Smuzhiyun printk(KERN_ERR
416*4882a593Smuzhiyun "aoe: %s holds ref: %s\n",
417*4882a593Smuzhiyun skb->dev ? skb->dev->name : "netif",
418*4882a593Smuzhiyun "cannot free skb -- memory leaked.");
419*4882a593Smuzhiyun return;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun skb->truesize -= skb->data_len;
422*4882a593Smuzhiyun skb_shinfo(skb)->nr_frags = skb->data_len = 0;
423*4882a593Smuzhiyun skb_trim(skb, 0);
424*4882a593Smuzhiyun dev_kfree_skb(skb);
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun static void
skbpoolfree(struct aoedev * d)428*4882a593Smuzhiyun skbpoolfree(struct aoedev *d)
429*4882a593Smuzhiyun {
430*4882a593Smuzhiyun struct sk_buff *skb, *tmp;
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun skb_queue_walk_safe(&d->skbpool, skb, tmp)
433*4882a593Smuzhiyun skbfree(skb);
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun __skb_queue_head_init(&d->skbpool);
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun /* find it or allocate it */
439*4882a593Smuzhiyun struct aoedev *
aoedev_by_aoeaddr(ulong maj,int min,int do_alloc)440*4882a593Smuzhiyun aoedev_by_aoeaddr(ulong maj, int min, int do_alloc)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun struct aoedev *d;
443*4882a593Smuzhiyun int i;
444*4882a593Smuzhiyun ulong flags;
445*4882a593Smuzhiyun ulong sysminor = 0;
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun spin_lock_irqsave(&devlist_lock, flags);
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun for (d=devlist; d; d=d->next)
450*4882a593Smuzhiyun if (d->aoemajor == maj && d->aoeminor == min) {
451*4882a593Smuzhiyun spin_lock(&d->lock);
452*4882a593Smuzhiyun if (d->flags & DEVFL_TKILL) {
453*4882a593Smuzhiyun spin_unlock(&d->lock);
454*4882a593Smuzhiyun d = NULL;
455*4882a593Smuzhiyun goto out;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun d->ref++;
458*4882a593Smuzhiyun spin_unlock(&d->lock);
459*4882a593Smuzhiyun break;
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun if (d || !do_alloc || minor_get(&sysminor, maj, min) < 0)
462*4882a593Smuzhiyun goto out;
463*4882a593Smuzhiyun d = kcalloc(1, sizeof *d, GFP_ATOMIC);
464*4882a593Smuzhiyun if (!d)
465*4882a593Smuzhiyun goto out;
466*4882a593Smuzhiyun d->targets = kcalloc(NTARGETS, sizeof(*d->targets), GFP_ATOMIC);
467*4882a593Smuzhiyun if (!d->targets) {
468*4882a593Smuzhiyun kfree(d);
469*4882a593Smuzhiyun d = NULL;
470*4882a593Smuzhiyun goto out;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun d->ntargets = NTARGETS;
473*4882a593Smuzhiyun INIT_WORK(&d->work, aoecmd_sleepwork);
474*4882a593Smuzhiyun spin_lock_init(&d->lock);
475*4882a593Smuzhiyun INIT_LIST_HEAD(&d->rq_list);
476*4882a593Smuzhiyun skb_queue_head_init(&d->skbpool);
477*4882a593Smuzhiyun timer_setup(&d->timer, dummy_timer, 0);
478*4882a593Smuzhiyun d->timer.expires = jiffies + HZ;
479*4882a593Smuzhiyun add_timer(&d->timer);
480*4882a593Smuzhiyun d->bufpool = NULL; /* defer to aoeblk_gdalloc */
481*4882a593Smuzhiyun d->tgt = d->targets;
482*4882a593Smuzhiyun d->ref = 1;
483*4882a593Smuzhiyun for (i = 0; i < NFACTIVE; i++)
484*4882a593Smuzhiyun INIT_LIST_HEAD(&d->factive[i]);
485*4882a593Smuzhiyun INIT_LIST_HEAD(&d->rexmitq);
486*4882a593Smuzhiyun d->sysminor = sysminor;
487*4882a593Smuzhiyun d->aoemajor = maj;
488*4882a593Smuzhiyun d->aoeminor = min;
489*4882a593Smuzhiyun d->rttavg = RTTAVG_INIT;
490*4882a593Smuzhiyun d->rttdev = RTTDEV_INIT;
491*4882a593Smuzhiyun d->next = devlist;
492*4882a593Smuzhiyun devlist = d;
493*4882a593Smuzhiyun out:
494*4882a593Smuzhiyun spin_unlock_irqrestore(&devlist_lock, flags);
495*4882a593Smuzhiyun return d;
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun static void
freetgt(struct aoedev * d,struct aoetgt * t)499*4882a593Smuzhiyun freetgt(struct aoedev *d, struct aoetgt *t)
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun struct frame *f;
502*4882a593Smuzhiyun struct list_head *pos, *nx, *head;
503*4882a593Smuzhiyun struct aoeif *ifp;
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun for (ifp = t->ifs; ifp < &t->ifs[NAOEIFS]; ++ifp) {
506*4882a593Smuzhiyun if (!ifp->nd)
507*4882a593Smuzhiyun break;
508*4882a593Smuzhiyun dev_put(ifp->nd);
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun head = &t->ffree;
512*4882a593Smuzhiyun list_for_each_safe(pos, nx, head) {
513*4882a593Smuzhiyun list_del(pos);
514*4882a593Smuzhiyun f = list_entry(pos, struct frame, head);
515*4882a593Smuzhiyun skbfree(f->skb);
516*4882a593Smuzhiyun kfree(f);
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun kfree(t);
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun void
aoedev_exit(void)522*4882a593Smuzhiyun aoedev_exit(void)
523*4882a593Smuzhiyun {
524*4882a593Smuzhiyun flush_scheduled_work();
525*4882a593Smuzhiyun flush(NULL, 0, EXITING);
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun int __init
aoedev_init(void)529*4882a593Smuzhiyun aoedev_init(void)
530*4882a593Smuzhiyun {
531*4882a593Smuzhiyun return 0;
532*4882a593Smuzhiyun }
533