Commit 112b9631 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

USB: removed file ops from usb device structure

Moved the file ops and minor number stuff out of the usb structure,
Now usb_register_dev() and usb_deregister_dev() must be called if 
you want to use the USB major number.
parent 9cfc20f1
......@@ -2,17 +2,17 @@
# Makefile for USB Core files and filesystem
#
export-objs := usb.o hcd.o hcd-pci.o urb.o message.o config.o
export-objs := usb.o hcd.o hcd-pci.o urb.o message.o config.o file.o
usbcore-objs := usb.o usb-debug.o hub.o hcd.o urb.o message.o \
config.o
config.o file.o
ifeq ($(CONFIG_PCI),y)
usbcore-objs += hcd-pci.o
endif
ifeq ($(CONFIG_USB_DEVICEFS),y)
usbcore-objs += devio.o inode.o drivers.o devices.o
usbcore-objs += devio.o inode.o devices.o
endif
obj-$(CONFIG_USB) += usbcore.o
......
/*
* drivers/usb/file.c
*
* (C) Copyright Linus Torvalds 1999
* (C) Copyright Johannes Erdfelt 1999-2001
* (C) Copyright Andreas Gal 1999
* (C) Copyright Gregory P. Smith 1999
* (C) Copyright Deti Fliegl 1999 (new USB architecture)
* (C) Copyright Randy Dunlap 2000
* (C) Copyright David Brownell 2000-2001 (kernel hotplug, usb_device_id,
more docs, etc)
* (C) Copyright Yggdrasil Computing, Inc. 2000
* (usb_device_id matching changes by Adam J. Richter)
* (C) Copyright Greg Kroah-Hartman 2002
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/usb.h>
devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
EXPORT_SYMBOL(usb_devfs_handle);
#define MAX_USB_MINORS 256
static struct file_operations *usb_minors[MAX_USB_MINORS];
static spinlock_t minor_lock = SPIN_LOCK_UNLOCKED;
static int usb_open(struct inode * inode, struct file * file)
{
int minor = minor(inode->i_rdev);
struct file_operations *c;
int err = -ENODEV;
struct file_operations *old_fops, *new_fops = NULL;
spin_lock (&minor_lock);
c = usb_minors[minor];
spin_unlock (&minor_lock);
if (!c || !(new_fops = fops_get(c)))
return err;
old_fops = file->f_op;
file->f_op = new_fops;
/* Curiouser and curiouser... NULL ->open() as "no device" ? */
if (file->f_op->open)
err = file->f_op->open(inode,file);
if (err) {
fops_put(file->f_op);
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
return err;
}
static struct file_operations usb_fops = {
owner: THIS_MODULE,
open: usb_open,
};
int usb_major_init(void)
{
if (devfs_register_chrdev(USB_MAJOR, "usb", &usb_fops)) {
err("unable to get major %d for usb devices", USB_MAJOR);
return -EBUSY;
}
usb_devfs_handle = devfs_mk_dir(NULL, "usb", NULL);
return 0;
}
void usb_major_cleanup(void)
{
devfs_unregister(usb_devfs_handle);
devfs_unregister_chrdev(USB_MAJOR, "usb");
}
/**
* usb_register_dev - register a USB device, and ask for a minor number
* @fops: the file operations for this USB device
* @minor: the requested starting minor for this device.
* @num_minors: number of minor numbers requested for this device
* @start_minor: place to put the new starting minor number
*
* This should be called by all USB drivers that use the USB major number.
* If CONFIG_USB_DYNAMIC_MINORS is enabled, the minor number will be
* dynamically allocated out of the list of available ones. If it is not
* enabled, the minor number will be based on the next available free minor,
* starting at the requested @minor.
*
* usb_deregister_dev() must be called when the driver is done with
* the minor numbers given out by this function.
*
* Returns -EINVAL if something bad happens with trying to register a
* device, and 0 on success, alone with a value that the driver should
* use in start_minor.
*/
int usb_register_dev (struct file_operations *fops, int minor, int num_minors, int *start_minor)
{
int i;
int j;
int good_spot;
int retval = -EINVAL;
#ifdef CONFIG_USB_DYNAMIC_MINORS
/*
* We don't care what the device tries to start at, we want to start
* at zero to pack the devices into the smallest available space with
* no holes in the minor range.
*/
minor = 0;
#endif
dbg ("asking for %d minors, starting at %d", num_minors, minor);
if (fops == NULL)
goto exit;
*start_minor = 0;
spin_lock (&minor_lock);
for (i = minor; i < MAX_USB_MINORS; ++i) {
if (usb_minors[i])
continue;
good_spot = 1;
for (j = 1; j <= num_minors-1; ++j)
if (usb_minors[i+j]) {
good_spot = 0;
break;
}
if (good_spot == 0)
continue;
*start_minor = i;
dbg("found a minor chunk free, starting at %d", i);
for (i = *start_minor; i < (*start_minor + num_minors); ++i)
usb_minors[i] = fops;
retval = 0;
goto exit;
}
exit:
spin_unlock (&minor_lock);
return retval;
}
EXPORT_SYMBOL(usb_register_dev);
/**
* usb_deregister_dev - deregister a USB device's dynamic minor.
* @num_minors: number of minor numbers to put back.
* @start_minor: the starting minor number
*
* Used in conjunction with usb_register_dev(). This function is called
* when the USB driver is finished with the minor numbers gotten from a
* call to usb_register_dev() (usually when the device is disconnected
* from the system.)
*
* This should be called by all drivers that use the USB major number.
*/
void usb_deregister_dev (int num_minors, int start_minor)
{
int i;
dbg ("removing %d minors starting at %d", num_minors, start_minor);
spin_lock (&minor_lock);
for (i = start_minor; i < (start_minor + num_minors); ++i)
usb_minors[i] = NULL;
spin_unlock (&minor_lock);
}
EXPORT_SYMBOL(usb_deregister_dev);
......@@ -48,7 +48,6 @@ static spinlock_t mount_lock = SPIN_LOCK_UNLOCKED;
static int mount_count; /* = 0 */
static struct dentry *devices_dentry;
static struct dentry *drivers_dentry;
static int num_buses; /* = 0 */
static uid_t devuid; /* = 0 */
......@@ -548,16 +547,6 @@ static int create_special_files (void)
return -ENODEV;
}
drivers_dentry = fs_create_file ("drivers",
listmode | S_IFREG,
NULL, NULL,
&usbdevfs_drivers_fops,
listuid, listgid);
if (drivers_dentry == NULL) {
err ("Unable to create drivers usbfs file");
return -ENODEV;
}
return 0;
}
......@@ -565,10 +554,7 @@ static void remove_special_files (void)
{
if (devices_dentry)
fs_remove_file (devices_dentry);
if (drivers_dentry)
fs_remove_file (drivers_dentry);
devices_dentry = NULL;
drivers_dentry = NULL;
remove_mount();
}
......@@ -581,11 +567,6 @@ void usbfs_update_special (void)
if (inode)
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
}
if (drivers_dentry) {
inode = devices_dentry->d_inode;
if (inode)
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
}
}
void usbfs_add_bus(struct usb_bus *bus)
......
......@@ -30,7 +30,6 @@
#include <linux/interrupt.h> /* for in_interrupt() */
#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
......@@ -45,6 +44,8 @@
extern int usb_hub_init(void);
extern void usb_hub_cleanup(void);
extern int usb_major_init(void);
extern void usb_major_cleanup(void);
/*
* Prototypes for the device driver probing/loading functions
......@@ -58,75 +59,23 @@ static void usb_check_support(struct usb_device *);
*/
LIST_HEAD(usb_driver_list);
devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
#define MAX_USB_MINORS 256
static struct usb_driver *usb_minors[MAX_USB_MINORS];
static spinlock_t minor_lock = SPIN_LOCK_UNLOCKED;
static int usb_register_minors (struct usb_driver *driver, int num_minors, int start_minor)
{
int i;
dbg("registering %d minors, starting at %d", num_minors, start_minor);
if (start_minor + num_minors >= MAX_USB_MINORS)
return -EINVAL;
spin_lock (&minor_lock);
for (i = start_minor; i < (start_minor + num_minors); ++i)
if (usb_minors[i]) {
spin_unlock (&minor_lock);
err("minor %d is already in use, error registering %s driver",
i, driver->name);
return -EINVAL;
}
for (i = start_minor; i < (start_minor + num_minors); ++i)
usb_minors[i] = driver;
spin_unlock (&minor_lock);
return 0;
}
static void usb_deregister_minors (struct usb_driver *driver, int num_minors, int start_minor)
{
int i;
dbg ("%s is removing %d minors starting at %d", driver->name,
num_minors, start_minor);
spin_lock (&minor_lock);
for (i = start_minor; i < (start_minor + num_minors); ++i)
usb_minors[i] = NULL;
spin_unlock (&minor_lock);
}
/**
* usb_register - register a USB driver
* @new_driver: USB operations for the driver
* usb_register - register a USB driver
* @new_driver: USB operations for the driver
*
* Registers a USB driver with the USB core. The list of unattached
* interfaces will be rescanned whenever a new driver is added, allowing
* the new driver to attach to any recognized devices.
* Returns a negative error code on failure and 0 on success.
* Registers a USB driver with the USB core. The list of unattached
* interfaces will be rescanned whenever a new driver is added, allowing
* the new driver to attach to any recognized devices.
* Returns a negative error code on failure and 0 on success.
*
* NOTE: if you want your driver to use the USB major number, you must call
* usb_register_dev() to enable that functionality. This function no longer
* takes care of that.
*/
int usb_register(struct usb_driver *new_driver)
{
int retval = 0;
if ((new_driver->fops) && (new_driver->num_minors == 0)) {
err ("%s driver must specify num_minors", new_driver->name);
return -EINVAL;
}
#ifndef CONFIG_USB_DYNAMIC_MINORS
if (new_driver->fops != NULL) {
retval = usb_register_minors (new_driver, new_driver->num_minors, new_driver->minor);
if (retval)
return retval;
}
#endif
info("registered new driver %s", new_driver->name);
......@@ -143,92 +92,6 @@ int usb_register(struct usb_driver *new_driver)
}
/**
* usb_register_dev - register a USB device, and ask for a minor number
* @new_driver: USB operations for the driver
* @num_minors: number of minor numbers requested for this device
* @start_minor: place to put the new starting minor number
*
* Used to ask the USB core for a new minor number for a device that has
* just showed up. This is used to dynamically allocate minor numbers
* from the pool of USB reserved minor numbers.
*
* This should be called by all drivers that use the USB major number.
* This only returns a good value of CONFIG_USB_DYNAMIC_MINORS is
* selected by the user.
*
* usb_deregister_dev() should be called when the driver is done with
* the minor numbers given out by this function.
*
* Returns -ENODEV if CONFIG_USB_DYNAMIC_MINORS is not enabled in this
* kernel, -EINVAL if something bad happens with trying to register a
* device, and 0 on success, alone with a value that the driver should
* use in start_minor.
*/
#ifdef CONFIG_USB_DYNAMIC_MINORS
int usb_register_dev (struct usb_driver *new_driver, int num_minors, int *start_minor)
{
int i;
int j;
int good_spot;
int retval = -EINVAL;
dbg ("%s is asking for %d minors", new_driver->name, num_minors);
if (new_driver->fops == NULL)
goto exit;
*start_minor = 0;
spin_lock (&minor_lock);
for (i = 0; i < MAX_USB_MINORS; ++i) {
if (usb_minors[i])
continue;
good_spot = 1;
for (j = 1; j <= num_minors-1; ++j)
if (usb_minors[i+j]) {
good_spot = 0;
break;
}
if (good_spot == 0)
continue;
*start_minor = i;
spin_unlock (&minor_lock);
retval = usb_register_minors (new_driver, num_minors, *start_minor);
if (retval) {
/* someone snuck in here, so let's start looking all over again */
spin_lock (&minor_lock);
i = 0;
continue;
}
goto exit;
}
spin_unlock (&minor_lock);
exit:
return retval;
}
/**
* usb_deregister_dev - deregister a USB device's dynamic minor.
* @driver: USB operations for the driver
* @num_minors: number of minor numbers to put back.
* @start_minor: the starting minor number
*
* Used in conjunction with usb_register_dev(). This function is called
* when the USB driver is finished with the minor numbers gotten from a
* call to usb_register_dev() (usually when the device is disconnected
* from the system.)
*
* This should be called by all drivers that use the USB major number.
*/
void usb_deregister_dev (struct usb_driver *driver, int num_minors, int start_minor)
{
usb_deregister_minors (driver, num_minors, start_minor);
}
#endif /* CONFIG_USB_DYNAMIC_MINORS */
/**
* usb_scan_devices - scans all unclaimed USB interfaces
* Context: !in_interrupt ()
......@@ -298,11 +161,15 @@ static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev)
}
/**
* usb_deregister - unregister a USB driver
* @driver: USB operations of the driver to unregister
* Context: !in_interrupt ()
* usb_deregister - unregister a USB driver
* @driver: USB operations of the driver to unregister
* Context: !in_interrupt ()
*
* Unlinks the specified driver from the internal USB driver list.
* Unlinks the specified driver from the internal USB driver list.
*
* NOTE: If you called usb_register_dev(), you still need to call
* usb_deregister_dev() to clean up your driver's allocated minor numbers,
* this * call will no longer do it for you.
*/
void usb_deregister(struct usb_driver *driver)
{
......@@ -310,11 +177,6 @@ void usb_deregister(struct usb_driver *driver)
info("deregistering driver %s", driver->name);
#ifndef CONFIG_USB_DYNAMIC_MINORS
if (driver->fops != NULL)
usb_deregister_minors (driver, driver->num_minors, driver->minor);
#endif
/*
* first we remove the driver, to be sure it doesn't get used by
* another thread while we are stepping through removing entries
......@@ -1357,55 +1219,6 @@ int usb_new_device(struct usb_device *dev)
return 0;
}
static int usb_open(struct inode * inode, struct file * file)
{
int minor = minor(inode->i_rdev);
struct usb_driver *c;
int err = -ENODEV;
struct file_operations *old_fops, *new_fops = NULL;
spin_lock (&minor_lock);
c = usb_minors[minor];
spin_unlock (&minor_lock);
if (!c || !(new_fops = fops_get(c->fops)))
return err;
old_fops = file->f_op;
file->f_op = new_fops;
/* Curiouser and curiouser... NULL ->open() as "no device" ? */
if (file->f_op->open)
err = file->f_op->open(inode,file);
if (err) {
fops_put(file->f_op);
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
return err;
}
static struct file_operations usb_fops = {
owner: THIS_MODULE,
open: usb_open,
};
int usb_major_init(void)
{
if (devfs_register_chrdev(USB_MAJOR, "usb", &usb_fops)) {
err("unable to get major %d for usb devices", USB_MAJOR);
return -EBUSY;
}
usb_devfs_handle = devfs_mk_dir(NULL, "usb", NULL);
return 0;
}
void usb_major_cleanup(void)
{
devfs_unregister(usb_devfs_handle);
devfs_unregister_chrdev(USB_MAJOR, "usb");
}
#ifdef CONFIG_PROC_FS
struct list_head *usb_driver_get_list(void)
......@@ -1463,11 +1276,6 @@ EXPORT_SYMBOL(usb_register);
EXPORT_SYMBOL(usb_deregister);
EXPORT_SYMBOL(usb_scan_devices);
#ifdef CONFIG_USB_DYNAMIC_MINORS
EXPORT_SYMBOL(usb_register_dev);
EXPORT_SYMBOL(usb_deregister_dev);
#endif
EXPORT_SYMBOL(usb_alloc_dev);
EXPORT_SYMBOL(usb_free_dev);
EXPORT_SYMBOL(usb_get_dev);
......@@ -1489,5 +1297,4 @@ EXPORT_SYMBOL(__usb_get_extra_descriptor);
EXPORT_SYMBOL(usb_get_current_frame_number);
EXPORT_SYMBOL(usb_devfs_handle);
MODULE_LICENSE("GPL");
......@@ -104,6 +104,7 @@
#include <linux/interrupt.h> /* for in_interrupt() */
#include <linux/list.h> /* for struct list_head */
#include <linux/device.h> /* for struct device */
#include <linux/fs.h> /* for struct file_operations */
static __inline__ void wait_ms(unsigned int ms)
......@@ -648,14 +649,6 @@ struct usb_device_id {
* because its device has been (or is being) disconnected. The
* handle passed is what was returned by probe(), or was provided
* to usb_driver_claim_interface().
* @fops: USB drivers can reuse some character device framework in
* the USB subsystem by providing a file operations vector and
* a minor number.
* @minor: Used with fops to simplify creating USB character devices.
* Such drivers have sixteen character devices, using the USB
* major number and starting with this minor number.
* @num_minors: Used with minor to specify how many minors are used by
* this driver.
* @ioctl: Used for drivers that want to talk to userspace through
* the "usbfs" filesystem. This lets devices provide ways to
* expose information to user space regardless of where they
......@@ -694,11 +687,6 @@ struct usb_driver {
);
struct list_head driver_list;
struct file_operations *fops;
int minor;
int num_minors;
struct semaphore serialize;
/* ioctl -- userspace apps can talk to drivers through usbfs */
......@@ -722,13 +710,8 @@ extern struct bus_type usb_bus_type;
extern int usb_register(struct usb_driver *);
extern void usb_deregister(struct usb_driver *);
#ifndef CONFIG_USB_DYNAMIC_MINORS
static inline int usb_register_dev(struct usb_driver *new_driver, int num_minors, int *start_minor) { return -ENODEV; }
static inline void usb_deregister_dev(struct usb_driver *driver, int num_minors, int start_minor) {}
#else
extern int usb_register_dev(struct usb_driver *new_driver, int num_minors, int *start_minor);
extern void usb_deregister_dev(struct usb_driver *driver, int num_minors, int start_minor);
#endif
extern int usb_register_dev(struct file_operations *fops, int minor, int num_minors, int *start_minor);
extern void usb_deregister_dev(int num_minors, int start_minor);
/* -------------------------------------------------------------------------- */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment