diff --git a/include/sys/sunddi.h b/include/sys/sunddi.h index 65df2a053c..c3368083b2 100644 --- a/include/sys/sunddi.h +++ b/include/sys/sunddi.h @@ -31,180 +31,23 @@ #include <sys/mutex.h> #include <sys/u8_textprep.h> #include <sys/vnode.h> -#include <linux/kdev_t.h> -#include <linux/fs.h> -#include <linux/cdev.h> -#include <linux/list.h> #include <spl-device.h> -#define DDI_MAX_NAME_LEN 32 - typedef int ddi_devid_t; -typedef enum { - DDI_INFO_DEVT2DEVINFO = 0, - DDI_INFO_DEVT2INSTANCE = 1 -} ddi_info_cmd_t; +#define DDI_DEV_T_NONE ((dev_t)-1) +#define DDI_DEV_T_ANY ((dev_t)-2) +#define DI_MAJOR_T_UNKNOWN ((major_t)0) -typedef enum { - DDI_ATTACH = 0, - DDI_RESUME = 1, - DDI_PM_RESUME = 2 -} ddi_attach_cmd_t; +#define DDI_PROP_DONTPASS 0x0001 +#define DDI_PROP_CANSLEEP 0x0002 -typedef enum { - DDI_DETACH = 0, - DDI_SUSPEND = 1, - DDI_PM_SUSPEND = 2, - DDI_HOTPLUG_DETACH = 3 -} ddi_detach_cmd_t; +#define DDI_SUCCESS 0 +#define DDI_FAILURE -1 -typedef enum { - DDI_RESET_FORCE = 0 -} ddi_reset_cmd_t; - -typedef enum { - PROP_LEN = 0, - PROP_LEN_AND_VAL_BUF = 1, - PROP_LEN_AND_VAL_ALLOC = 2, - PROP_EXISTS = 3 -} ddi_prop_op_t; - -typedef void *devmap_cookie_t; -typedef struct as { - uchar_t a_flags; -} as_t; - -typedef struct pollhead { - struct polldat *ph_list; -} pollhead_t; - -typedef struct dev_info { - kmutex_t di_lock; - char di_name[DDI_MAX_NAME_LEN]; - struct dev_ops *di_ops; - struct cdev *di_cdev; - spl_class *di_class; - spl_device *di_device; - major_t di_major; - minor_t di_minor; - dev_t di_dev; - unsigned di_minors; - int di_flags; - struct list_head di_list; -} dev_info_t; - -typedef struct cb_ops { - int (*cb_open)(dev_t *devp, int flag, int otyp, cred_t *credp); - int (*cb_close)(dev_t dev, int flag, int otyp, cred_t *credp); - int (*cb_strategy)(void *bp); - int (*cb_print)(dev_t dev, char *str); - int (*cb_dump)(dev_t dev, caddr_t addr, daddr_t blkno, int nblk); - int (*cb_read)(dev_t dev, struct uio *uiop, cred_t *credp); - int (*cb_write)(dev_t dev, struct uio *uiop, cred_t *credp); - int (*cb_ioctl)(dev_t dev, int cmd, intptr_t arg, int mode, - cred_t *credp, int *rvalp); - int (*cb_devmap)(dev_t dev, devmap_cookie_t dhp, offset_t off, - size_t len, size_t *maplen, uint_t model); - int (*cb_mmap)(dev_t dev, off_t off, int prot); - int (*cb_segmap)(dev_t dev, off_t off, struct as *asp, - caddr_t *addrp, off_t len, unsigned int prot, - unsigned int maxprot, unsigned int flags, - cred_t *credp); - int (*cb_chpoll)(dev_t dev, short events, int anyyet, - short *reventsp, struct pollhead **phpp); - int (*cb_prop_op)(dev_t dev, dev_info_t *dip, - ddi_prop_op_t prop_op, int mod_flags, - char *name, caddr_t valuep, int *length); - struct streamtab *cb_str; - int cb_flag; - int cb_rev; - int (*cb_aread)(dev_t dev, struct aio_req *aio, cred_t *credp); - int (*cb_awrite)(dev_t dev, struct aio_req *aio, cred_t *credp); -} cb_ops_t; - -typedef struct dev_ops { - int devo_rev; - int devo_refcnt; - - int (*devo_getinfo)(dev_info_t *dip, - ddi_info_cmd_t infocmd, void *arg, void **result); - int (*devo_identify)(dev_info_t *dip); - int (*devo_probe)(dev_info_t *dip); - int (*devo_attach)(dev_info_t *dip, ddi_attach_cmd_t cmd); - int (*devo_detach)(dev_info_t *dip, ddi_detach_cmd_t cmd); - int (*devo_reset)(dev_info_t *dip, ddi_reset_cmd_t cmd); - - struct cb_ops *devo_cb_ops; - struct bus_ops *devo_bus_ops; - int (*devo_power)(dev_info_t *dip, int component, int level); - int (*devo_quiesce)(dev_info_t *dip); -} dev_ops_t; - -typedef struct mod_ops { - int (*modm_install)(void); - int (*modm_remove)(void); - int (*modm_info)(void); -} mod_ops_t; - -typedef struct modldrv { - struct mod_ops *drv_modops; - char *drv_linkinfo; - struct dev_ops *drv_dev_ops; - struct dev_info *drv_dev_info; -} modldrv_t; - -#define MODREV_1 1 - -#define D_NEW 0x000 -#define D_MP 0x020 -#define D_64BIT 0x200 - -#define DEVO_REV 3 -#define CB_REV 1 - -#define DDI_SUCCESS 0 -#define DDI_FAILURE -1 - -#define DDI_PSEUDO "ddi_pseudo" - -#define nodev NULL -#define nochpoll NULL -#define nulldev NULL -#define mod_driverops NULL -#define ddi_prop_op NULL - -#define getminor(x) (x) -#define getmajor(x) (x) -#define ddi_driver_major(di) getmajor(di->di_dev) - -#define DDI_DEV_T_NONE ((dev_t)-1) -#define DDI_DEV_T_ANY ((dev_t)-2) -#define DDI_MAJOR_T_UNKNOWN ((major_t)0) - -#define DDI_PROP_DONTPASS 0x0001 -#define DDI_PROP_CANSLEEP 0x0002 - -#define GLOBAL_DEV 0x02 -#define NODEBOUND_DEV 0x04 -#define NODESPECIFIC_DEV 0x06 -#define ENUMERATED_DEV 0x08 - -#define ddi_prop_lookup_string(x1,x2,x3,x4,x5) (*x5 = NULL) -#define ddi_prop_free(x) (void)0 -#define ddi_root_node() (void)0 - -#define mod_install(x) 0 -#define mod_remove(x) 0 - -extern int __ddi_create_minor_node(dev_info_t *dip, char *name, int spec_type, - minor_t minor_num, char *node_type, - int flags, struct module *mod); -extern void __ddi_remove_minor_node(dev_info_t *dip, char *name); -extern int ddi_quiesce_not_needed(dev_info_t *dip); -extern int __mod_install(struct modlinkage *modlp); -extern int __mod_remove(struct modlinkage *modlp); -extern int __mod_mknod(char *name, char *type, int major, int minor); +#define ddi_prop_lookup_string(x1,x2,x3,x4,x5) (*x5 = NULL) +#define ddi_prop_free(x) (void)0 +#define ddi_root_node() (void)0 extern int ddi_strtoul(const char *, char **, int, unsigned long *); extern int ddi_strtol(const char *, char **, int, long *); @@ -214,89 +57,4 @@ extern int ddi_strtoll(const char *, char **, int, long long *); extern int ddi_copyin(const void *from, void *to, size_t len, int flags); extern int ddi_copyout(const void *from, void *to, size_t len, int flags); -static __inline__ void ddi_report_dev(dev_info_t *d) { } -static __inline__ void ddi_prop_remove_all(dev_info_t *dip) { } - -static __inline__ void -ddi_remove_minor_node(dev_info_t *di, char *name) -{ -#ifdef HAVE_GPL_ONLY_SYMBOLS - /* Cleanup udev (GPL-only symbols required). This is performed as - * part of an inline function to ensure that these symbols are not - * linked against the SPL which is GPL'ed. But instead they are - * linked against the package building against the SPL to ensure - * its license allows linking with GPL-only symbols. */ - if (di->di_class) { - spl_device_destroy(di->di_class, di->di_device, di->di_dev); - spl_class_destroy(di->di_class); - di->di_class = NULL; - di->di_dev = 0; - } -#else - /* When we do not have access to the GPL-only device interfaces we - * are forced to do something crude. We unlink the special device - * file in /dev/ ourselves from within the kernel. On the upside we - * are already providing this functionality for Solaris, and it is - * easy to leverage the Solaris API to perform the unlink. */ - if (strlen(di->di_name) > 0) - vn_remove(di->di_name, UIO_SYSSPACE, RMFILE); - -#endif /* HAVE_GPL_ONLY_SYMBOLS */ - - __ddi_remove_minor_node(di, name); -} - -static __inline__ int -ddi_create_minor_node(dev_info_t *di, char *name, int spec_type, - minor_t minor_num, char *node_type, int flags) -{ - int rc; - - rc = __ddi_create_minor_node(di, name, spec_type, minor_num, - node_type, flags, THIS_MODULE); - if (rc) - return rc; - -#ifdef HAVE_GPL_ONLY_SYMBOLS - /* Setup udev (GPL-only symbols required). This is performed as - * part of an inline function to ensure that these symbols are not - * linked against the SPL which is GPL'ed. But instead they are - * linked against the package building against the SPL to ensure - * its license allows linking with GPL-only symbols. */ - di->di_class = spl_class_create(THIS_MODULE, name); - if (IS_ERR(di->di_class)) { - rc = PTR_ERR(di->di_class); - di->di_class = NULL; - ddi_remove_minor_node(di, name); - return DDI_FAILURE; - } - - /* Do not append a 0 to devices with minor nums of 0 */ - di->di_device = spl_device_create(di->di_class, NULL, di->di_dev, NULL, - (di->di_minor == 0) ? "%s" : "%s%d", - name, di->di_minor); -#else - /* When we do not have access to the GPL-only device interfaces we - * are forced to do something horible. We use a user mode helper to - * create the special device file in /dev/. By futher extending the - * Solaris vnode implementation we could potentially do a vn_create() - * from within the kernel but that's still a hack. */ - if (name) { - rc = __mod_mknod(di->di_name, "c", di->di_major, di->di_minor); - if (rc) { - ddi_remove_minor_node(di, name); - } - } - -#endif /* HAVE_GPL_ONLY_SYMBOLS */ - - return rc; -} - -#undef mod_install -#undef mod_remove - -#define mod_install __mod_install -#define mod_remove __mod_remove - #endif /* SPL_SUNDDI_H */ diff --git a/module/spl/Makefile.in b/module/spl/Makefile.in index a0211d2db3..4f54f124f5 100644 --- a/module/spl/Makefile.in +++ b/module/spl/Makefile.in @@ -18,7 +18,6 @@ spl-objs += @top_srcdir@/module/spl/spl-vnode.o spl-objs += @top_srcdir@/module/spl/spl-err.o spl-objs += @top_srcdir@/module/spl/spl-time.o spl-objs += @top_srcdir@/module/spl/spl-kobj.o -spl-objs += @top_srcdir@/module/spl/spl-module.o spl-objs += @top_srcdir@/module/spl/spl-generic.o spl-objs += @top_srcdir@/module/spl/spl-atomic.o spl-objs += @top_srcdir@/module/spl/spl-mutex.o diff --git a/module/spl/spl-module.c b/module/spl/spl-module.c deleted file mode 100644 index 7a626ca713..0000000000 --- a/module/spl/spl-module.c +++ /dev/null @@ -1,375 +0,0 @@ -/*****************************************************************************\ - * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. - * Copyright (C) 2007 The Regents of the University of California. - * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). - * Written by Brian Behlendorf <behlendorf1@llnl.gov>. - * UCRL-CODE-235197 - * - * This file is part of the SPL, Solaris Porting Layer. - * For details, see <http://github.com/behlendorf/spl/>. - * - * The SPL is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * The SPL is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with the SPL. If not, see <http://www.gnu.org/licenses/>. - ***************************************************************************** - * Solaris Porting Layer (SPL) Module Implementation. -\*****************************************************************************/ - -#include <sys/sunddi.h> -#include <spl-debug.h> - -#ifdef SS_DEBUG_SUBSYS -#undef SS_DEBUG_SUBSYS -#endif - -#define SS_DEBUG_SUBSYS SS_MODULE - -static DEFINE_SPINLOCK(dev_info_lock); -static LIST_HEAD(dev_info_list); - -static struct dev_info * -get_dev_info(dev_t dev) -{ - struct dev_info *di; - - spin_lock(&dev_info_lock); - - list_for_each_entry(di, &dev_info_list, di_list) - if (di->di_dev == dev) - goto out; - - di = NULL; -out: - spin_unlock(&dev_info_lock); - return di; -} - -static long -mod_generic_unlocked_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct inode *ino = file->f_dentry->d_inode; - struct dev_info *di; - int rc, flags = 0, rvalp = 0; - cred_t *cr = NULL; - - di = get_dev_info(MKDEV(imajor(ino), iminor(ino))); - if (di == NULL) - return -EINVAL; - - rc = di->di_ops->devo_cb_ops->cb_ioctl(di->di_dev, - (int)cmd, (intptr_t)arg, - flags, cr, &rvalp); - /* - * The Solaris the kernel returns positive error codes to indicate - * a failure. Under linux the kernel is expected to return a - * small negative value which is trapped by libc and used to - * set errno correctly. For this reason we negate the Solaris - * return code to ensure errno gets set correctly. - */ - return -rc; -} - -#ifdef CONFIG_COMPAT -/* Compatibility handler for ioctls from 32-bit ELF binaries */ -static long -mod_generic_compat_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - return mod_generic_unlocked_ioctl(file, cmd, arg); -} -#endif /* CONFIG_COMPAT */ - -int -__ddi_create_minor_node(dev_info_t *di, char *name, int spec_type, - minor_t minor_num, char *node_type, - int flags, struct module *mod) -{ - struct cdev *cdev; - struct cb_ops *cb_ops; - struct file_operations *fops; - int rc; - SENTRY; - - ASSERT(spec_type == S_IFCHR); - ASSERT(minor_num < di->di_minors); - ASSERT(!strcmp(node_type, DDI_PSEUDO)); - - fops = kzalloc(sizeof(struct file_operations), GFP_KERNEL); - if (fops == NULL) - SRETURN(DDI_FAILURE); - - cdev = cdev_alloc(); - if (cdev == NULL) { - kfree(fops); - SRETURN(DDI_FAILURE); - } - - cdev->ops = fops; - - mutex_enter(&di->di_lock); - cb_ops = di->di_ops->devo_cb_ops; - ASSERT(cb_ops); - - /* Setup the fops to cb_ops mapping */ - fops->owner = mod; - if (cb_ops->cb_ioctl) { - fops->unlocked_ioctl = mod_generic_unlocked_ioctl; -#ifdef CONFIG_COMPAT - fops->compat_ioctl = mod_generic_compat_ioctl; -#endif - } - -#if 0 - if (cb_ops->cb_open) - fops->open = mod_generic_open; - - if (cb_ops->cb_close) - fops->release = mod_generic_close; - - if (cb_ops->cb_read) - fops->read = mod_generic_read; - - if (cb_ops->cb_write) - fops->write = mod_generic_write; -#endif - /* XXX: Currently unsupported operations */ - ASSERT(cb_ops->cb_open == NULL); - ASSERT(cb_ops->cb_close == NULL); - ASSERT(cb_ops->cb_read == NULL); - ASSERT(cb_ops->cb_write == NULL); - ASSERT(cb_ops->cb_strategy == NULL); - ASSERT(cb_ops->cb_print == NULL); - ASSERT(cb_ops->cb_dump == NULL); - ASSERT(cb_ops->cb_devmap == NULL); - ASSERT(cb_ops->cb_mmap == NULL); - ASSERT(cb_ops->cb_segmap == NULL); - ASSERT(cb_ops->cb_chpoll == NULL); - ASSERT(cb_ops->cb_prop_op == NULL); - ASSERT(cb_ops->cb_str == NULL); - ASSERT(cb_ops->cb_aread == NULL); - ASSERT(cb_ops->cb_awrite == NULL); - - snprintf(di->di_name, DDI_MAX_NAME_LEN-1, "/dev/%s", name); - di->di_cdev = cdev; - di->di_flags = flags; - di->di_minor = minor_num; - di->di_dev = MKDEV(di->di_major, di->di_minor); - - rc = cdev_add(cdev, di->di_dev, 1); - if (rc) { - SERROR("Error adding cdev, %d\n", rc); - kfree(fops); - cdev_del(cdev); - mutex_exit(&di->di_lock); - SRETURN(DDI_FAILURE); - } - - spin_lock(&dev_info_lock); - list_add(&di->di_list, &dev_info_list); - spin_unlock(&dev_info_lock); - - mutex_exit(&di->di_lock); - - SRETURN(DDI_SUCCESS); -} -EXPORT_SYMBOL(__ddi_create_minor_node); - -static void -__ddi_remove_minor_node_locked(dev_info_t *di, char *name) -{ - if (di->di_cdev) { - cdev_del(di->di_cdev); - di->di_cdev = NULL; - } - - spin_lock(&dev_info_lock); - list_del_init(&di->di_list); - spin_unlock(&dev_info_lock); -} - -void -__ddi_remove_minor_node(dev_info_t *di, char *name) -{ - SENTRY; - mutex_enter(&di->di_lock); - __ddi_remove_minor_node_locked(di, name); - mutex_exit(&di->di_lock); - SEXIT; -} -EXPORT_SYMBOL(__ddi_remove_minor_node); - -int -ddi_quiesce_not_needed(dev_info_t *dip) -{ - SRETURN(DDI_SUCCESS); -} -EXPORT_SYMBOL(ddi_quiesce_not_needed); - -#if 0 -static int -mod_generic_open(struct inode *, struct file *) -{ - open(dev_t *devp, int flags, int otyp, cred_t *credp); -} - -static int -mod_generic_close(struct inode *, struct file *) -{ - close(dev_t dev, int flags, int otyp, cred_t *credp); -} - -static ssize_t -mod_generic_read(struct file *, char __user *, size_t, loff_t *) -{ - read(dev_t dev, struct uio *uiop, cred_t *credp); -} - -static ssize_t -mod_generic_write(struct file *, const char __user *, size_t, loff_t *) -{ - write(dev_t dev, struct uio *uiop, cred_t *credp); -} -#endif - -static struct dev_info * -dev_info_alloc(major_t major, minor_t minors, struct dev_ops *ops) { - struct dev_info *di; - - di = kmalloc(sizeof(struct dev_info), GFP_KERNEL); - if (di == NULL) - return NULL; - - mutex_init(&di->di_lock, NULL, MUTEX_DEFAULT, NULL); - INIT_LIST_HEAD(&di->di_list); - di->di_ops = ops; - di->di_class = NULL; - di->di_cdev = NULL; - di->di_major = major; - di->di_minor = 0; - di->di_minors = minors; - di->di_dev = 0; - - return di; -} - -static void -dev_info_free(struct dev_info *di) -{ - mutex_enter(&di->di_lock); - __ddi_remove_minor_node_locked(di, NULL); - mutex_exit(&di->di_lock); - mutex_destroy(&di->di_lock); - kfree(di); -} - -int -__mod_install(struct modlinkage *modlp) -{ - struct modldrv *drv = modlp->ml_modldrv; - struct dev_info *di; - int rc; - SENTRY; - - di = dev_info_alloc(modlp->ml_major, modlp->ml_minors, - drv->drv_dev_ops); - if (di == NULL) - SRETURN(ENOMEM); - - /* XXX: Really we need to be calling devo_probe if it's available - * and then calling devo_attach for each device discovered. However - * for now we just call it once and let the app sort it out. - */ - rc = drv->drv_dev_ops->devo_attach(di, DDI_ATTACH); - if (rc != DDI_SUCCESS) { - dev_info_free(di); - SRETURN(rc); - } - - drv->drv_dev_info = di; - - SRETURN(DDI_SUCCESS); -} -EXPORT_SYMBOL(__mod_install); - -int -__mod_mknod(char *name, char *type, int major, int minor) -{ - char cmd[] = "/bin/mknod"; - char major_str[8]; - char minor_str[8]; - char *argv[] = { cmd, - name, - type, - major_str, - minor_str, - NULL }; - char *envp[] = { "HOME=/", - "TERM=linux", - "PATH=/sbin:/usr/sbin:/bin:/usr/bin", - NULL }; - - snprintf(major_str, 8, "%d", major); - snprintf(minor_str, 8, "%d", minor); - - return call_usermodehelper(cmd, argv, envp, 1); -} -EXPORT_SYMBOL(__mod_mknod); - -int -__mod_remove(struct modlinkage *modlp) -{ - struct modldrv *drv = modlp->ml_modldrv; - struct dev_info *di = drv->drv_dev_info; - int rc; - SENTRY; - - rc = drv->drv_dev_ops->devo_detach(di, DDI_DETACH); - if (rc != DDI_SUCCESS) - SRETURN(rc); - - dev_info_free(di); - drv->drv_dev_info = NULL; - - SRETURN(DDI_SUCCESS); -} -EXPORT_SYMBOL(__mod_remove); - -int -ldi_ident_from_mod(struct modlinkage *modlp, ldi_ident_t *lip) -{ - ldi_ident_t li; - SENTRY; - - ASSERT(modlp); - ASSERT(lip); - - li = kmalloc(sizeof(struct ldi_ident), GFP_KERNEL); - if (li == NULL) - SRETURN(ENOMEM); - - li->li_dev = MKDEV(modlp->ml_major, 0); - *lip = li; - - SRETURN(0); -} -EXPORT_SYMBOL(ldi_ident_from_mod); - -void -ldi_ident_release(ldi_ident_t lip) -{ - SENTRY; - ASSERT(lip); - kfree(lip); - SEXIT; -} -EXPORT_SYMBOL(ldi_ident_release);