]>
git.proxmox.com Git - mirror_spl.git/blob - modules/spl/spl-module.c
cd3bc88ef6baa8b41840a0dfdd56bc31de90d5f8
1 #include <sys/sysmacros.h>
2 #include <sys/sunddi.h>
9 #define DEBUG_SUBSYSTEM S_MODULE
11 static spinlock_t dev_info_lock
= SPIN_LOCK_UNLOCKED
;
12 static LIST_HEAD(dev_info_list
);
14 static struct dev_info
*
15 get_dev_info(dev_t dev
)
19 spin_lock(&dev_info_lock
);
21 list_for_each_entry(di
, &dev_info_list
, di_list
)
22 if (di
->di_dev
== dev
)
27 spin_unlock(&dev_info_lock
);
32 mod_generic_ioctl(struct inode
*ino
, struct file
*filp
,
33 unsigned int cmd
, unsigned long arg
)
36 int rc
, flag
= 0, rvalp
= 0;
39 di
= get_dev_info(MKDEV(imajor(ino
), iminor(ino
)));
43 rc
= di
->di_ops
->devo_cb_ops
->cb_ioctl(di
->di_dev
,
44 (int)cmd
,(intptr_t)arg
,
50 __ddi_create_minor_node(dev_info_t
*di
, char *name
, int spec_type
,
51 minor_t minor_num
, char *node_type
,
52 int flag
, struct module
*mod
)
55 struct dev_ops
*dev_ops
;
56 struct cb_ops
*cb_ops
;
57 struct file_operations
*fops
;
61 ASSERT(spec_type
== S_IFCHR
);
62 ASSERT(minor_num
< di
->di_minors
);
63 ASSERT(!strcmp(node_type
, DDI_PSEUDO
));
66 fops
= kzalloc(sizeof(struct file_operations
), GFP_KERNEL
);
78 mutex_enter(&di
->di_lock
);
81 cb_ops
= di
->di_ops
->devo_cb_ops
;
84 /* Setup the fops to cb_ops mapping */
87 fops
->ioctl
= mod_generic_ioctl
;
91 fops
->open
= mod_generic_open
;
94 fops
->release
= mod_generic_close
;
97 fops
->read
= mod_generic_read
;
100 fops
->write
= mod_generic_write
;
102 /* XXX: Currently unsupported operations */
103 ASSERT(cb_ops
->cb_open
== NULL
);
104 ASSERT(cb_ops
->cb_close
== NULL
);
105 ASSERT(cb_ops
->cb_read
== NULL
);
106 ASSERT(cb_ops
->cb_write
== NULL
);
107 ASSERT(cb_ops
->cb_strategy
== NULL
);
108 ASSERT(cb_ops
->cb_print
== NULL
);
109 ASSERT(cb_ops
->cb_dump
== NULL
);
110 ASSERT(cb_ops
->cb_devmap
== NULL
);
111 ASSERT(cb_ops
->cb_mmap
== NULL
);
112 ASSERT(cb_ops
->cb_segmap
== NULL
);
113 ASSERT(cb_ops
->cb_chpoll
== NULL
);
114 ASSERT(cb_ops
->cb_prop_op
== NULL
);
115 ASSERT(cb_ops
->cb_str
== NULL
);
116 ASSERT(cb_ops
->cb_aread
== NULL
);
117 ASSERT(cb_ops
->cb_awrite
== NULL
);
119 di
->di_minor
= minor_num
;
120 di
->di_dev
= MKDEV(di
->di_major
, di
->di_minor
);
122 rc
= cdev_add(cdev
, di
->di_dev
, 1);
124 CERROR("Error adding cdev, %d\n", rc
);
127 mutex_exit(&di
->di_lock
);
131 di
->di_class
= class_create(THIS_MODULE
, name
);
132 if (IS_ERR(di
->di_class
)) {
133 rc
= PTR_ERR(di
->di_class
);
134 CERROR("Error creating %s class, %d\n", name
, rc
);
136 cdev_del(di
->di_cdev
);
137 mutex_exit(&di
->di_lock
);
141 /* Do not append a 0 to devices with minor nums of 0 */
142 if (di
->di_minor
== 0) {
143 class_device_create(di
->di_class
, NULL
, di
->di_dev
,
146 class_device_create(di
->di_class
, NULL
, di
->di_dev
,
147 NULL
, "%s%d", name
, di
->di_minor
);
152 spin_lock(&dev_info_lock
);
153 list_add(&di
->di_list
, &dev_info_list
);
154 spin_unlock(&dev_info_lock
);
156 mutex_exit(&di
->di_lock
);
160 EXPORT_SYMBOL(__ddi_create_minor_node
);
163 __ddi_remove_minor_node_locked(dev_info_t
*di
, char *name
)
166 class_device_destroy(di
->di_class
, di
->di_dev
);
167 class_destroy(di
->di_class
);
174 cdev_del(di
->di_cdev
);
178 spin_lock(&dev_info_lock
);
179 list_del_init(&di
->di_list
);
180 spin_unlock(&dev_info_lock
);
184 __ddi_remove_minor_node(dev_info_t
*di
, char *name
)
187 mutex_enter(&di
->di_lock
);
188 __ddi_remove_minor_node_locked(di
, name
);
189 mutex_exit(&di
->di_lock
);
192 EXPORT_SYMBOL(ddi_remove_minor_node
);
196 mod_generic_open(struct inode
*, struct file
*)
198 open(dev_t
*devp
, int flag
, int otyp
, cred_t
*credp
);
202 mod_generic_close(struct inode
*, struct file
*)
204 close(dev_t dev
, int flag
, int otyp
, cred_t
*credp
);
208 mod_generic_read(struct file
*, char __user
*, size_t, loff_t
*)
210 read(dev_t dev
, struct uio
*uiop
, cred_t
*credp
);
214 mod_generic_write(struct file
*, const char __user
*, size_t, loff_t
*)
216 write(dev_t dev
, struct uio
*uiop
, cred_t
*credp
);
220 static struct dev_info
*
221 dev_info_alloc(major_t major
, minor_t minors
, struct dev_ops
*ops
) {
224 di
= kmalloc(sizeof(struct dev_info
), GFP_KERNEL
);
228 mutex_init(&di
->di_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
229 INIT_LIST_HEAD(&di
->di_list
);
233 di
->di_major
= major
;
235 di
->di_minors
= minors
;
242 dev_info_free(struct dev_info
*di
)
244 mutex_enter(&di
->di_lock
);
245 __ddi_remove_minor_node_locked(di
, NULL
);
246 mutex_exit(&di
->di_lock
);
247 mutex_destroy(&di
->di_lock
);
252 __mod_install(struct modlinkage
*modlp
)
254 struct modldrv
*drv
= modlp
->ml_modldrv
;
259 di
= dev_info_alloc(modlp
->ml_major
, modlp
->ml_minors
,
264 /* XXX: Really we need to be calling devo_probe if it's available
265 * and then calling devo_attach for each device discovered. However
266 * for now we just call it once and let the app sort it out.
268 rc
= drv
->drv_dev_ops
->devo_attach(di
, DDI_ATTACH
);
269 if (rc
!= DDI_SUCCESS
) {
274 drv
->drv_dev_info
= di
;
278 EXPORT_SYMBOL(__mod_install
);
281 __mod_remove(struct modlinkage
*modlp
)
283 struct modldrv
*drv
= modlp
->ml_modldrv
;
284 struct dev_info
*di
= drv
->drv_dev_info
;
288 rc
= drv
->drv_dev_ops
->devo_detach(di
, DDI_DETACH
);
289 if (rc
!= DDI_SUCCESS
)
293 drv
->drv_dev_info
= NULL
;
297 EXPORT_SYMBOL(__mod_remove
);
300 ldi_ident_from_mod(struct modlinkage
*modlp
, ldi_ident_t
*lip
)
308 li
= kmalloc(sizeof(struct ldi_ident
), GFP_KERNEL
);
312 li
->li_dev
= MKDEV(modlp
->ml_major
, 0);
317 EXPORT_SYMBOL(ldi_ident_from_mod
);
320 ldi_ident_release(ldi_ident_t lip
)
327 EXPORT_SYMBOL(ldi_ident_release
);