Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc
[sfrench/cifs-2.6.git] / drivers / block / aoe / aoemain.c
1 /* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
2 /*
3  * aoemain.c
4  * Module initialization routines, discover timer
5  */
6
7 #include <linux/hdreg.h>
8 #include <linux/blkdev.h>
9 #include <linux/module.h>
10 #include "aoe.h"
11
12 MODULE_LICENSE("GPL");
13 MODULE_AUTHOR("Sam Hopkins <sah@coraid.com>");
14 MODULE_DESCRIPTION("AoE block/char driver for 2.6.2 and newer 2.6 kernels");
15 MODULE_VERSION(VERSION);
16
17 enum { TINIT, TRUN, TKILL };
18
19 static void
20 discover_timer(ulong vp)
21 {
22         static struct timer_list t;
23         static volatile ulong die;
24         static spinlock_t lock;
25         ulong flags;
26         enum { DTIMERTICK = HZ * 60 }; /* one minute */
27
28         switch (vp) {
29         case TINIT:
30                 init_timer(&t);
31                 spin_lock_init(&lock);
32                 t.data = TRUN;
33                 t.function = discover_timer;
34                 die = 0;
35         case TRUN:
36                 spin_lock_irqsave(&lock, flags);
37                 if (!die) {
38                         t.expires = jiffies + DTIMERTICK;
39                         add_timer(&t);
40                 }
41                 spin_unlock_irqrestore(&lock, flags);
42
43                 aoecmd_cfg(0xffff, 0xff);
44                 return;
45         case TKILL:
46                 spin_lock_irqsave(&lock, flags);
47                 die = 1;
48                 spin_unlock_irqrestore(&lock, flags);
49
50                 del_timer_sync(&t);
51         default:
52                 return;
53         }
54 }
55
56 static void
57 aoe_exit(void)
58 {
59         discover_timer(TKILL);
60
61         aoenet_exit();
62         unregister_blkdev(AOE_MAJOR, DEVICE_NAME);
63         aoechr_exit();
64         aoedev_exit();
65         aoeblk_exit();          /* free cache after de-allocating bufs */
66 }
67
68 static int __init
69 aoe_init(void)
70 {
71         int ret;
72
73         ret = aoedev_init();
74         if (ret)
75                 return ret;
76         ret = aoechr_init();
77         if (ret)
78                 goto chr_fail;
79         ret = aoeblk_init();
80         if (ret)
81                 goto blk_fail;
82         ret = aoenet_init();
83         if (ret)
84                 goto net_fail;
85         ret = register_blkdev(AOE_MAJOR, DEVICE_NAME);
86         if (ret < 0) {
87                 printk(KERN_ERR "aoe: can't register major\n");
88                 goto blkreg_fail;
89         }
90
91         printk(KERN_INFO "aoe: AoE v%s initialised.\n", VERSION);
92         discover_timer(TINIT);
93         return 0;
94
95  blkreg_fail:
96         aoenet_exit();
97  net_fail:
98         aoeblk_exit();
99  blk_fail:
100         aoechr_exit();
101  chr_fail:
102         aoedev_exit();
103         
104         printk(KERN_INFO "aoe: initialisation failure.\n");
105         return ret;
106 }
107
108 module_init(aoe_init);
109 module_exit(aoe_exit);
110