Commit a07335eb authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/greg/linux/BK/bleed-2.5

into kroah.com:/home/greg/linux/BK/gregkh-2.6
parents 6cf73674 caa6e213
......@@ -111,12 +111,12 @@
</para>
<programlisting>
static struct usb_driver skel_driver = {
name: "skeleton",
probe: skel_probe,
disconnect: skel_disconnect,
fops: &amp;skel_fops,
minor: USB_SKEL_MINOR_BASE,
id_table: skel_table,
.name = "skeleton",
.probe = skel_probe,
.disconnect = skel_disconnect,
.fops = &amp;skel_fops,
.minor = USB_SKEL_MINOR_BASE,
.id_table = skel_table,
};
</programlisting>
<para>
......@@ -202,41 +202,21 @@ MODULE_DEVICE_TABLE (usb, skel_table);
are passed to the function:
</para>
<programlisting>
static void * skel_probe(struct usb_device *dev,
unsigned int ifnum, const struct usb_device_id *id)
static int skel_probe(struct usb_interface *interface,
const struct usb_device_id *id)
</programlisting>
<para>
The driver now needs to verify that this device is actually one that it
can accept. If not, or if any error occurs during initialization, a NULL
value is returned from the probe function. Otherwise a pointer to a
private data structure containing the driver's state for this device is
returned. That pointer is stored in the usb_device structure, and all
callbacks to the driver pass that pointer.
can accept. If so, it returns 0.
If not, or if any error occurs during initialization, an errorcode
(such as <literal>-ENOMEM<literal> or <literal>-ENODEV<literal>)
is returned from the probe function.
</para>
<para>
In the skeleton driver, we determine what end points are marked as bulk-in
and bulk-out. We create buffers to hold the data that will be sent and
received from the device, and a USB urb to write data to the device is
initialized. Also, we register the device with the devfs subsystem,
allowing users of devfs to access our device. That registration looks like
the following:
</para>
<programlisting>
/* initialize the devfs node for this device and register it */
sprintf(name, &quot;skel%d&quot;, skel->minor);
skel->devfs = devfs_register (usb_devfs_handle,
name,
DEVFS_FL_DEFAULT,
USB_MAJOR,
USB_SKEL_MINOR_BASE + skel->minor,
S_IFCHR | S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP | S_IROTH,
&amp;skel_fops,
NULL);
</programlisting>
<para>
If the devfs_register function fails, we do not care, as the devfs
subsystem will report this to the user.
initialized.
</para>
<para>
Conversely, when the device is removed from the USB bus, the disconnect
......@@ -254,23 +234,18 @@ devfs_unregister(skel->devfs);
the device, any of the functions in the file_operations structure that
were passed to the USB subsystem will be called from a user program trying
to talk to the device. The first function called will be open, as the
program tries to open the device for I/O. Within the skeleton driver's
open function we increment the driver's usage count if it is a module with
a call to MODULE_INC_USE_COUNT. With this macro call, if the driver is
compiled as a module, the driver cannot be unloaded until a corresponding
MODULE_DEC_USE_COUNT macro is called. We also increment our private usage
program tries to open the device for I/O. We increment our private usage
count and save off a pointer to our internal structure in the file
structure. This is done so that future calls to file operations will
enable the driver to determine which device the user is addressing. All of
this is done with the following code:
enable the driver to determine which device the user is addressing. All
of this is done with the following code:
</para>
<programlisting>
/* increment our usage count for the module */
MOD_INC_USE_COUNT;
++skel->open_count;
/* save our object in the file's private structure */
file->private_data = skel;
file->private_data = dev;
</programlisting>
<para>
After the open function is called, the read and write functions are called
......@@ -350,24 +325,11 @@ if (!retval) {
<para>
When the user program releases the file handle that it has been using to
talk to the device, the release function in the driver is called. In this
function we decrement the module usage count with a call to
MOD_DEC_USE_COUNT (to match our previous call to MOD_INC_USE_COUNT). We
also determine if there are any other programs that are currently talking
to the device (a device may be opened by more than one program at one
time). If this is the last user of the device, then we shut down any
possible pending writes that might be currently occurring. This is all
done with:
</para>
function we decrement our private usage count and wait for possible
pending writes:
<programlisting>
/* decrement our usage count for the device */
--skel->open_count;
if (skel->open_count &lt;= 0) {
/* shutdown any bulk writes that might be going on */
usb_unlink_urb (skel->write_urb);
skel->open_count = 0;
}
/* decrement our usage count for the module */
MOD_DEC_USE_COUNT;
</programlisting>
<para>
One of the more difficult problems that USB drivers must be able to handle
......@@ -375,49 +337,34 @@ MOD_DEC_USE_COUNT;
any point in time, even if a program is currently talking to it. It needs
to be able to shut down any current reads and writes and notify the
user-space programs that the device is no longer there. The following
code is an example of how to do this: </para>
code (function <function>skel_delete</function>)
is an example of how to do this: </para>
<programlisting>
/* if the device is not opened, then we clean right now */
if (skel->open_count) {
minor_table[skel->minor] = NULL;
if (skel->bulk_in_buffer != NULL)
kfree (skel->bulk_in_buffer);
if (skel->bulk_out_buffer != NULL)
kfree (skel->bulk_out_buffer);
if (skel->write_urb != NULL)
usb_free_urb (skel->write_urb);
kfree (skel);
} else {
skel->dev = NULL;
up (&amp;skel->sem);
static inline void skel_delete (struct usb_skel *dev)
{
if (dev->bulk_in_buffer != NULL)
kfree (dev->bulk_in_buffer);
if (dev->bulk_out_buffer != NULL)
usb_buffer_free (dev->udev, dev->bulk_out_size,
dev->bulk_out_buffer,
dev->write_urb->transfer_dma);
if (dev->write_urb != NULL)
usb_free_urb (dev->write_urb);
kfree (dev);
}
</programlisting>
<para>
If a program currently has an open handle to the device, we only null the
usb_device structure in our local structure, as it has now gone away. For
If a program currently has an open handle to the device, we reset the flag
<literal>device_present</literal>. For
every read, write, release and other functions that expect a device to be
present, the driver first checks to see if this usb_device structure is
present, the driver first checks this flag to see if the device is
still present. If not, it releases that the device has disappeared, and a
-ENODEV error is returned to the user-space program. When the release
function is eventually called, it determines if there is no usb_device
structure and if not, it does the cleanup that the skel_disconnect
function is eventually called, it determines if there is no device
and if not, it does the cleanup that the skel_disconnect
function normally does if there are no open files on the device (see
Listing 5).
</para>
<programlisting>
if (skel->dev == NULL) {
/* the device was unplugged before the file was released */
minor_table[skel->minor] = NULL;
if (skel->bulk_in_buffer != NULL)
kfree (skel->bulk_in_buffer);
if (skel->bulk_out_buffer != NULL)
kfree (skel->bulk_out_buffer);
if (skel->write_urb != NULL)
usb_free_urb (skel->write_urb);
kfree (skel);
goto exit;
}
</programlisting>
</chapter>
<chapter id="iso">
......
......@@ -122,17 +122,17 @@ Drivers that connect directly to the USB subsystem should be declared
something like this:
static struct usb_driver mydriver = {
name: "mydriver",
id_table: mydriver_id_table,
probe: my_probe,
disconnect: my_disconnect,
.name = "mydriver",
.id_table = mydriver_id_table,
.probe = my_probe,
.disconnect = my_disconnect,
/*
if using the usb chardev framework:
minor: MY_USB_MINOR_START,
fops: my_file_ops,
.minor = MY_USB_MINOR_START,
.fops = my_file_ops,
if exposing any operations through usbdevfs:
ioctl: my_ioctl,
.ioctl = my_ioctl,
*/
}
......
......@@ -349,9 +349,9 @@ void video_unregister_device(struct video_device *vfd)
if(video_device[vfd->minor]!=vfd)
panic("videodev: bad unregister");
class_device_unregister(&vfd->class_dev);
devfs_remove(vfd->devfs_name);
video_device[vfd->minor]=NULL;
class_device_unregister(&vfd->class_dev);
up(&videodev_lock);
}
......
......@@ -483,7 +483,7 @@ static void rh_report_status (unsigned long ptr)
{
struct urb *urb;
struct usb_hcd *hcd;
int length;
int length = 0;
unsigned long flags;
urb = (struct urb *) ptr;
......@@ -499,7 +499,9 @@ static void rh_report_status (unsigned long ptr)
return;
}
length = hcd->driver->hub_status_data (hcd, urb->transfer_buffer);
if (!HCD_IS_SUSPENDED (hcd->state))
length = hcd->driver->hub_status_data (
hcd, urb->transfer_buffer);
/* complete the status urb, or retrigger the timer */
spin_lock (&hcd_data_lock);
......
......@@ -246,21 +246,22 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs)
io->status = urb->status;
/* the previous urbs, and this one, completed already.
* unlink the later ones so they won't rx/tx bad data,
*
* FIXME don't bother unlinking urbs that haven't yet been
* submitted; those non-error cases shouldn't be syslogged
* unlink pending urbs so they won't rx/tx bad data.
*/
for (i = 0, found = 0; i < io->entries; i++) {
if (!io->urbs [i])
continue;
if (found) {
status = usb_unlink_urb (io->urbs [i]);
if (status && status != -EINPROGRESS)
err ("sg_complete, unlink --> %d",
status);
if (status != -EINPROGRESS && status != -EBUSY)
dev_err (&io->dev->dev,
"%s, unlink --> %d\n",
__FUNCTION__, status);
} else if (urb == io->urbs [i])
found = 1;
}
}
urb->dev = 0;
/* on the last completion, signal usb_sg_wait() */
io->bytes += urb->actual_length;
......@@ -356,7 +357,7 @@ int usb_sg_init (
goto nomem;
}
io->urbs [i]->dev = dev;
io->urbs [i]->dev = 0;
io->urbs [i]->pipe = pipe;
io->urbs [i]->interval = period;
io->urbs [i]->transfer_flags = urb_flags;
......@@ -448,6 +449,7 @@ void usb_sg_wait (struct usb_sg_request *io)
for (i = 0; i < io->entries && !io->status; i++) {
int retval;
io->urbs [i]->dev = io->dev;
retval = usb_submit_urb (io->urbs [i], SLAB_ATOMIC);
/* after we submit, let completions or cancelations fire;
......@@ -459,9 +461,9 @@ void usb_sg_wait (struct usb_sg_request *io)
case -ENXIO: // hc didn't queue this one
case -EAGAIN:
case -ENOMEM:
io->urbs [i]->dev = 0;
retval = 0;
i--;
// FIXME: should it usb_sg_cancel() on INTERRUPT?
yield ();
break;
......@@ -477,8 +479,10 @@ void usb_sg_wait (struct usb_sg_request *io)
/* fail any uncompleted urbs */
default:
io->urbs [i]->dev = 0;
io->urbs [i]->status = retval;
dbg ("usb_sg_msg, submit --> %d", retval);
dev_dbg (&io->dev->dev, "%s, submit --> %d\n",
__FUNCTION__, retval);
usb_sg_cancel (io);
}
spin_lock_irqsave (&io->lock, flags);
......@@ -521,9 +525,9 @@ void usb_sg_cancel (struct usb_sg_request *io)
if (!io->urbs [i]->dev)
continue;
retval = usb_unlink_urb (io->urbs [i]);
if (retval && retval != -EINPROGRESS)
warn ("usb_sg_cancel, unlink --> %d", retval);
// FIXME don't warn on "not yet submitted" error
if (retval != -EINPROGRESS && retval != -EBUSY)
dev_warn (&io->dev->dev, "%s, unlink --> %d\n",
__FUNCTION__, retval);
}
}
spin_unlock_irqrestore (&io->lock, flags);
......
......@@ -49,6 +49,7 @@
#define DEBUG 1
// #define VERBOSE /* extra debug messages (success too) */
#include <linux/version.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
......
......@@ -41,7 +41,6 @@
#include <linux/usb.h>
#include <linux/moduleparam.h>
#include <linux/version.h>
#include "../core/hcd.h"
#include <asm/byteorder.h>
......@@ -979,21 +978,12 @@ static const struct hc_driver ehci_driver = {
/* EHCI spec says PCI is required. */
/* PCI driver selection metadata; PCI hotplugging uses this */
static struct pci_device_id pci_ids [] = { {
static const struct pci_device_id pci_ids [] = { {
/* handle any USB 2.0 EHCI controller */
.class = ((PCI_CLASS_SERIAL_USB << 8) | 0x20),
.class_mask = ~0,
PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0),
.driver_data = (unsigned long) &ehci_driver,
/* no matter who makes it */
.vendor = PCI_ANY_ID,
.device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
}, { /* end: all zeroes */ }
},
{ /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE (pci, pci_ids);
......
......@@ -351,18 +351,9 @@ static const struct hc_driver ohci_pci_hc_driver = {
static const struct pci_device_id pci_ids [] = { {
/* handle any USB OHCI controller */
.class = (PCI_CLASS_SERIAL_USB << 8) | 0x10,
.class_mask = ~0,
PCI_DEVICE_CLASS((PCI_CLASS_SERIAL_USB << 8) | 0x10, ~0),
.driver_data = (unsigned long) &ohci_pci_hc_driver,
/* no matter who makes it */
.vendor = PCI_ANY_ID,
.device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
}, { /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE (pci, pci_ids);
......
......@@ -2504,18 +2504,9 @@ static const struct hc_driver uhci_driver = {
};
static const struct pci_device_id uhci_pci_ids[] = { {
/* handle any USB UHCI controller */
.class = ((PCI_CLASS_SERIAL_USB << 8) | 0x00),
.class_mask = ~0,
PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x00), ~0),
.driver_data = (unsigned long) &uhci_driver,
/* no matter who makes it */
.vendor = PCI_ANY_ID,
.device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
}, { /* end: all zeroes */ }
};
......
......@@ -29,7 +29,6 @@
#include <linux/module.h>
#include <linux/socket.h>
#include <linux/miscdevice.h>
#include <linux/list.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
......
This diff is collapsed.
......@@ -89,7 +89,7 @@ struct stv680_frame {
/* this is almost the video structure uvd_t, with extra parameters for stv */
struct usb_stv {
struct video_device vdev;
struct video_device *vdev;
struct usb_device *udev;
......@@ -142,7 +142,6 @@ struct usb_stv {
wait_queue_head_t wq; /* Processes waiting */
struct proc_dir_entry *proc_entry; /* /proc/stv680/videoX */
int nullpackets;
};
......
......@@ -33,7 +33,6 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
......
......@@ -24,7 +24,6 @@
#include <linux/module.h>
#include <linux/socket.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <asm/uaccess.h>
......
......@@ -435,7 +435,7 @@ static int is_good_config (char *buf, int len)
return 0;
}
le32_to_cpus (&config->wTotalLength);
le16_to_cpus (&config->wTotalLength);
if (config->wTotalLength == len) /* read it all */
return 1;
return config->wTotalLength >= TBUF_SIZE; /* max partial read */
......
......@@ -75,7 +75,6 @@
#include <linux/mii.h>
#include <linux/crc32.h>
#include <asm/uaccess.h>
#include <linux/version.h>
/* Version Information */
#define DRIVER_VERSION "v2.0.2"
......
......@@ -2,6 +2,8 @@
* USB Host-to-Host Links
* Copyright (C) 2000-2002 by David Brownell <dbrownell@users.sourceforge.net>
* Copyright (C) 2002 Pavel Machek <pavel@ucw.cz>
* Copyright (C) 2003 David Hollis <dhollis@davehollis.com>
* Copyright (c) 2002-2003 TiVo Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -142,6 +144,14 @@
#include <asm/uaccess.h>
#include <asm/unaligned.h>
#ifdef CONFIG_USB_AX8817X
#define NEED_MII
#endif
#ifdef NEED_MII
#include <linux/mii.h>
#endif
// #define DEBUG // error path messages, extra info
// #define VERBOSE // more; success messages
#define REALLY_QUEUE
......@@ -218,6 +228,10 @@ struct usbnet {
int msg_level;
unsigned long data [5];
#ifdef NEED_MII
struct mii_if_info mii;
#endif
// various kinds of pending driver work
struct sk_buff_head rxq;
struct sk_buff_head txq;
......@@ -399,6 +413,274 @@ static const struct driver_info an2720_info = {
#endif /* CONFIG_USB_AN2720 */
#ifdef CONFIG_USB_AX8817X
/* ASIX AX8817X based USB 2.0 Ethernet Devices */
#define HAVE_HARDWARE
#include <linux/crc32.h>
#define AX_CMD_SET_SW_MII 0x06
#define AX_CMD_READ_MII_REG 0x07
#define AX_CMD_WRITE_MII_REG 0x08
#define AX_CMD_SET_HW_MII 0x0a
#define AX_CMD_WRITE_RX_CTL 0x10
#define AX_CMD_READ_IPG012 0x11
#define AX_CMD_WRITE_IPG0 0x12
#define AX_CMD_WRITE_IPG1 0x13
#define AX_CMD_WRITE_IPG2 0x14
#define AX_CMD_WRITE_MULTI_FILTER 0x16
#define AX_CMD_READ_NODE_ID 0x17
#define AX_CMD_READ_PHY_ID 0x19
#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
#define AX_CMD_WRITE_GPIOS 0x1f
#define AX_MCAST_FILTER_SIZE 8
#define AX_MAX_MCAST 64
static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
return usb_control_msg(
dev->udev,
usb_rcvctrlpipe(dev->udev, 0),
cmd,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value,
index,
data,
size,
CONTROL_TIMEOUT_JIFFIES);
}
static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
return usb_control_msg(
dev->udev,
usb_sndctrlpipe(dev->udev, 0),
cmd,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value,
index,
data,
size,
CONTROL_TIMEOUT_JIFFIES);
}
static void ax8817x_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
{
struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
if (urb->status < 0)
printk(KERN_DEBUG "ax8817x_async_cmd_callback() failed with %d",
urb->status);
kfree(req);
usb_free_urb(urb);
}
static void ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
u16 size, void *data)
{
struct usb_ctrlrequest *req;
int status;
struct urb *urb;
if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) {
devdbg(dev, "Error allocating URB in write_cmd_async!");
return;
}
if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) {
deverr(dev, "Failed to allocate memory for control request");
usb_free_urb(urb);
return;
}
req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
req->bRequest = cmd;
req->wValue = cpu_to_le16(value);
req->wIndex = cpu_to_le16(index);
req->wLength = cpu_to_le16(size);
usb_fill_control_urb(urb, dev->udev,
usb_sndctrlpipe(dev->udev, 0),
(void *)req, data, size,
ax8817x_async_cmd_callback, req);
if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0)
deverr(dev, "Error submitting the control message: status=%d", status);
}
static void ax8817x_set_multicast(struct net_device *net)
{
struct usbnet *dev = (struct usbnet *) net->priv;
u8 rx_ctl = 0x8c;
if (net->flags & IFF_PROMISC) {
rx_ctl |= 0x01;
} else if (net->flags & IFF_ALLMULTI
|| net->mc_count > AX_MAX_MCAST) {
rx_ctl |= 0x02;
} else if (net->mc_count == 0) {
/* just broadcast and directed */
} else {
struct dev_mc_list *mc_list = net->mc_list;
u8 *multi_filter;
u32 crc_bits;
int i;
multi_filter = kmalloc(AX_MCAST_FILTER_SIZE, GFP_ATOMIC);
if (multi_filter == NULL) {
/* Oops, couldn't allocate a buffer for setting the multicast
filter. Try all multi mode. */
rx_ctl |= 0x02;
} else {
memset(multi_filter, 0, AX_MCAST_FILTER_SIZE);
/* Build the multicast hash filter. */
for (i = 0; i < net->mc_count; i++) {
crc_bits =
ether_crc(ETH_ALEN,
mc_list->dmi_addr) >> 26;
multi_filter[crc_bits >> 3] |=
1 << (crc_bits & 7);
mc_list = mc_list->next;
}
ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
AX_MCAST_FILTER_SIZE, multi_filter);
rx_ctl |= 0x10;
}
}
ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
}
static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc)
{
struct usbnet *dev = netdev->priv;
u16 res;
u8 buf[4];
ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf);
ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, (u16 *)&res);
ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
return res & 0xffff;
}
static void ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
{
struct usbnet *dev = netdev->priv;
u16 res = val;
u8 buf[4];
ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf);
ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, (u16 *)&res);
ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf);
}
static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
{
int ret;
u8 buf[6];
u16 *buf16 = (u16 *) buf;
int i;
dev->in = usb_rcvbulkpipe(dev->udev, 3);
dev->out = usb_sndbulkpipe(dev->udev, 2);
if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x80, 0, 0, buf)) < 0) {
dbg("send AX_CMD_WRITE_RX_CTL failed: %d", ret);
return ret;
}
/* Get the MAC address */
memset(buf, 0, ETH_ALEN);
if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, 6, buf)) < 0) {
dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
return ret;
}
memcpy(dev->net->dev_addr, buf, ETH_ALEN);
/* Get IPG values */
if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_IPG012, 0, 0, 3, buf)) < 0) {
dbg("Error reading IPG values: %d", ret);
return ret;
}
for(i = 0;i < 3;i++) {
ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0 + i, 0, 0, 1, &buf[i]);
}
/* Get the PHY id */
if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret);
return ret;
} else if (ret < 2) {
/* this should always return 2 bytes */
dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x", ret);
return -EIO;
}
/* Initialize MII structure */
dev->mii.dev = dev->net;
dev->mii.mdio_read = ax8817x_mdio_read;
dev->mii.mdio_write = ax8817x_mdio_write;
dev->mii.phy_id_mask = 0x3f;
dev->mii.reg_num_mask = 0x1f;
dev->mii.phy_id = buf[1];
if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf)) < 0) {
dbg("Failed to go to software MII mode: %02x", ret);
return ret;
}
*buf16 = cpu_to_le16(BMCR_RESET);
if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG,
dev->mii.phy_id, MII_BMCR, 2, buf16)) < 0) {
dbg("Failed to write MII reg - MII_BMCR: %02x", ret);
return ret;
}
/* Advertise that we can do full-duplex pause */
*buf16 = cpu_to_le16(ADVERTISE_ALL | ADVERTISE_CSMA | 0x0400);
if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG,
dev->mii.phy_id, MII_ADVERTISE,
2, buf16)) < 0) {
dbg("Failed to write MII_REG advertisement: %02x", ret);
return ret;
}
*buf16 = cpu_to_le16(BMCR_ANENABLE | BMCR_ANRESTART);
if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG,
dev->mii.phy_id, MII_BMCR,
2, buf16)) < 0) {
dbg("Failed to write MII reg autonegotiate: %02x", ret);
return ret;
}
if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf)) < 0) {
dbg("Failed to set hardware MII: %02x", ret);
return ret;
}
dev->net->set_multicast_list = ax8817x_set_multicast;
return 0;
}
static const struct driver_info ax8817x_info = {
.description = "ASIX AX8817x USB 2.0 Ethernet",
.bind = ax8817x_bind,
.flags = FLAG_ETHER,
};
#endif /* CONFIG_USB_AX8817X */
#ifdef CONFIG_USB_BELKIN
......@@ -2173,12 +2455,16 @@ usbnet_ethtool_ioctl (struct net_device *net, void __user *useraddr)
static int usbnet_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
{
switch (cmd) {
case SIOCETHTOOL:
if (cmd == SIOCETHTOOL)
return usbnet_ethtool_ioctl (net, (void __user *)rq->ifr_data);
default:
#ifdef NEED_MII
struct usbnet *dev = (struct usbnet *)net->priv;
if (dev->mii.mdio_read != NULL && dev->mii.mdio_write != NULL)
return generic_mii_ioctl(&dev->mii, (struct mii_ioctl_data *) &rq->ifr_data, cmd, NULL);
#endif
return -EOPNOTSUPP;
}
}
/*-------------------------------------------------------------------------*/
......@@ -2670,6 +2956,30 @@ static const struct usb_device_id products [] = {
},
#endif
#ifdef CONFIG_USB_AX8817X
{
// Linksys USB200M
USB_DEVICE (0x077b, 0x2226),
.driver_info = (unsigned long) &ax8817x_info,
}, {
// Netgear FA120
USB_DEVICE (0x0846, 0x1040),
.driver_info = (unsigned long) &ax8817x_info,
}, {
// DLink DUB-E100
USB_DEVICE (0x2001, 0x1a00),
.driver_info = (unsigned long) &ax8817x_info,
}, {
// Intellinet, ST Lab USB Ethernet
USB_DEVICE (0x0b95, 0x1720),
.driver_info = (unsigned long) &ax8817x_info,
}, {
// Hawking UF200, TrendNet TU2-ET100
USB_DEVICE (0x07b8, 0x420a),
.driver_info = (unsigned long) &ax8817x_info,
},
#endif
#ifdef CONFIG_USB_EPSON2888
{
USB_DEVICE (0x0525, 0x2888), // EPSON USB client
......
......@@ -602,10 +602,19 @@ static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, un
static int __init belkin_sa_init (void)
{
usb_serial_register (&belkin_device);
usb_register (&belkin_driver);
int retval;
retval = usb_serial_register(&belkin_device);
if (retval)
goto failed_usb_serial_register;
retval = usb_register(&belkin_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
failed_usb_register:
usb_serial_deregister(&belkin_device);
failed_usb_serial_register:
return retval;
}
......
......@@ -464,13 +464,22 @@ static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs
static int __init cyberjack_init (void)
{
usb_serial_register (&cyberjack_device);
usb_register (&cyberjack_driver);
int retval;
retval = usb_serial_register(&cyberjack_device);
if (retval)
goto failed_usb_serial_register;
retval = usb_register(&cyberjack_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_VERSION " " DRIVER_AUTHOR);
info(DRIVER_DESC);
return 0;
failed_usb_register:
usb_serial_deregister(&cyberjack_device);
failed_usb_serial_register:
return retval;
}
static void __exit cyberjack_exit (void)
......
......@@ -2045,11 +2045,24 @@ opcode, line, status, val );
static int __init digi_init (void)
{
usb_serial_register (&digi_acceleport_2_device);
usb_serial_register (&digi_acceleport_4_device);
usb_register (&digi_driver);
int retval;
retval = usb_serial_register(&digi_acceleport_2_device);
if (retval)
goto failed_acceleport_2_device;
retval = usb_serial_register(&digi_acceleport_4_device);
if (retval)
goto failed_acceleport_4_device;
retval = usb_register(&digi_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
failed_usb_register:
usb_serial_deregister(&digi_acceleport_4_device);
failed_acceleport_4_device:
usb_serial_deregister(&digi_acceleport_2_device);
failed_acceleport_2_device:
return retval;
}
......
......@@ -558,7 +558,7 @@ static void empeg_set_termios (struct usb_serial_port *port, struct termios *old
static int __init empeg_init (void)
{
struct urb *urb;
int i;
int i, retval;
/* create our write urb pool and transfer buffers */
spin_lock_init (&write_urb_pool_lock);
......@@ -570,7 +570,6 @@ static int __init empeg_init (void)
continue;
}
urb->transfer_buffer = NULL;
urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
if (!urb->transfer_buffer) {
err("%s - out of memory for urb buffers.",
......@@ -579,12 +578,27 @@ static int __init empeg_init (void)
}
}
usb_serial_register (&empeg_device);
usb_register (&empeg_driver);
retval = usb_serial_register(&empeg_device);
if (retval)
goto failed_usb_serial_register;
retval = usb_register(&empeg_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
failed_usb_register:
usb_serial_deregister(&empeg_device);
failed_usb_serial_register:
for (i = 0; i < NUM_URBS; ++i) {
if (write_urb_pool[i]) {
if (write_urb_pool[i]->transfer_buffer)
kfree(write_urb_pool[i]->transfer_buffer);
usb_free_urb(write_urb_pool[i]);
}
}
return retval;
}
......@@ -593,7 +607,7 @@ static void __exit empeg_exit (void)
int i;
unsigned long flags;
usb_register (&empeg_driver);
usb_deregister(&empeg_driver);
usb_serial_deregister (&empeg_device);
spin_lock_irqsave (&write_urb_pool_lock, flags);
......
......@@ -17,6 +17,11 @@
* See http://ftdi-usb-sio.sourceforge.net for upto date testing info
* and extra documentation
*
* (19/Aug/2003) Ian Abbott
* Freed urb's transfer buffer in write bulk callback.
* Omitted some paranoid checks in write bulk callback that don't matter.
* Scheduled work in write bulk callback regardless of port's open count.
*
* (05/Aug/2003) Ian Abbott
* Added VID/PID for ID TECH IDT1221U USB to RS-232 adapter.
* VID/PID provided by Steve Briggs.
......@@ -1391,31 +1396,21 @@ static int ftdi_write (struct usb_serial_port *port, int from_user,
static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
dbg("%s", __FUNCTION__);
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree (urb->transfer_buffer);
if (port_paranoia_check (port, __FUNCTION__))
return;
dbg("%s - port %d", __FUNCTION__, port->number);
if (urb->status) {
dbg("nonzero write bulk status received: %d", urb->status);
return;
}
if (!serial) {
dbg("%s - bad serial pointer, exiting", __FUNCTION__);
return;
}
/* Have to check for validity of queueing up the tasks */
dbg("%s - port->open_count = %d", __FUNCTION__, port->open_count);
if (port->open_count > 0){
schedule_work(&port->work);
}
return;
} /* ftdi_write_bulk_callback */
......@@ -1999,17 +1994,42 @@ static void ftdi_unthrottle (struct usb_serial_port *port)
static int __init ftdi_init (void)
{
int retval;
dbg("%s", __FUNCTION__);
usb_serial_register (&ftdi_SIO_device);
usb_serial_register (&ftdi_8U232AM_device);
usb_serial_register (&ftdi_FT232BM_device);
usb_serial_register (&ftdi_USB_UIRT_device);
usb_serial_register (&ftdi_HE_TIRA1_device);
usb_register (&ftdi_driver);
retval = usb_serial_register(&ftdi_SIO_device);
if (retval)
goto failed_SIO_register;
retval = usb_serial_register(&ftdi_8U232AM_device);
if (retval)
goto failed_8U232AM_register;
retval = usb_serial_register(&ftdi_FT232BM_device);
if (retval)
goto failed_FT232BM_register;
retval = usb_serial_register(&ftdi_USB_UIRT_device);
if (retval)
goto failed_USB_UIRT_register;
retval = usb_serial_register(&ftdi_HE_TIRA1_device);
if (retval)
goto failed_HE_TIRA1_register;
retval = usb_register(&ftdi_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
failed_usb_register:
usb_serial_deregister(&ftdi_HE_TIRA1_device);
failed_HE_TIRA1_register:
usb_serial_deregister(&ftdi_USB_UIRT_device);
failed_USB_UIRT_register:
usb_serial_deregister(&ftdi_FT232BM_device);
failed_FT232BM_register:
usb_serial_deregister(&ftdi_8U232AM_device);
failed_8U232AM_register:
usb_serial_deregister(&ftdi_SIO_device);
failed_SIO_register:
return retval;
}
......
......@@ -3051,15 +3051,36 @@ static void edge_shutdown (struct usb_serial *serial)
* edgeport_init
* This is called by the module subsystem, or on startup to initialize us
****************************************************************************/
int __init edgeport_init(void)
static int __init edgeport_init(void)
{
usb_serial_register (&edgeport_1port_device);
usb_serial_register (&edgeport_2port_device);
usb_serial_register (&edgeport_4port_device);
usb_serial_register (&edgeport_8port_device);
usb_register (&io_driver);
int retval;
retval = usb_serial_register(&edgeport_1port_device);
if (retval)
goto failed_1port_device_register;
retval = usb_serial_register(&edgeport_2port_device);
if (retval)
goto failed_2port_device_register;
retval = usb_serial_register(&edgeport_4port_device);
if (retval)
goto failed_4port_device_register;
retval = usb_serial_register(&edgeport_8port_device);
if (retval)
goto failed_8port_device_register;
retval = usb_register(&io_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
failed_usb_register:
usb_serial_deregister(&edgeport_8port_device);
failed_8port_device_register:
usb_serial_deregister(&edgeport_4port_device);
failed_4port_device_register:
usb_serial_deregister(&edgeport_2port_device);
failed_2port_device_register:
usb_serial_deregister(&edgeport_1port_device);
failed_1port_device_register:
return retval;
}
......@@ -3068,7 +3089,7 @@ int __init edgeport_init(void)
* edgeport_exit
* Called when the driver is about to be unloaded.
****************************************************************************/
void __exit edgeport_exit (void)
static void __exit edgeport_exit (void)
{
usb_deregister (&io_driver);
usb_serial_deregister (&edgeport_1port_device);
......
......@@ -127,6 +127,7 @@ static struct usb_device_id edgeport_1port_id_table [] = {
static struct usb_device_id edgeport_2port_id_table [] = {
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) },
......@@ -145,6 +146,7 @@ static struct usb_device_id edgeport_2port_id_table [] = {
static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) },
......@@ -2679,11 +2681,24 @@ static struct usb_serial_device_type edgeport_2port_device = {
static int __init edgeport_init(void)
{
usb_serial_register (&edgeport_1port_device);
usb_serial_register (&edgeport_2port_device);
usb_register (&io_driver);
int retval;
retval = usb_serial_register(&edgeport_1port_device);
if (retval)
goto failed_1port_device_register;
retval = usb_serial_register(&edgeport_2port_device);
if (retval)
goto failed_2port_device_register;
retval = usb_register(&io_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
failed_usb_register:
usb_serial_deregister(&edgeport_2port_device);
failed_2port_device_register:
usb_serial_deregister(&edgeport_1port_device);
failed_1port_device_register:
return retval;
}
static void __exit edgeport_exit (void)
......
......@@ -118,6 +118,7 @@
#define ION_DEVICE_ID_TI_EDGEPORT_1 0x0215 /* Edgeport/1 RS232 */
#define ION_DEVICE_ID_TI_EDGEPORT_42 0x0217 /* Edgeport/42 4 hub 2 RS232 */
#define ION_DEVICE_ID_TI_EDGEPORT_22 0x021A /* Edgeport/22 Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232 */
#define ION_DEVICE_ID_TI_EDGEPORT_2C 0x021B /* Edgeport/2c RS232 */
#define ION_DEVICE_ID_TI_EDGEPORT_421_BOOT 0x0240 /* Edgeport/421 in boot mode */
#define ION_DEVICE_ID_TI_EDGEPORT_421_DOWN 0x0241 /* Edgeport/421 in download mode first interface is 2 RS232 (Note that the second interface of this multi interface device should be a standard USB class 7 printer port) */
......
......@@ -570,16 +570,25 @@ static void ipaq_shutdown(struct usb_serial *serial)
static int __init ipaq_init(void)
{
int retval;
spin_lock_init(&write_list_lock);
usb_serial_register(&ipaq_device);
retval = usb_serial_register(&ipaq_device);
if (retval)
goto failed_usb_serial_register;
info(DRIVER_DESC " " DRIVER_VERSION);
if (vendor) {
ipaq_id_table[0].idVendor = vendor;
ipaq_id_table[0].idProduct = product;
}
usb_register(&ipaq_driver);
retval = usb_register(&ipaq_driver);
if (retval)
goto failed_usb_register;
return 0;
failed_usb_register:
usb_serial_deregister(&ipaq_device);
failed_usb_serial_register:
return retval;
}
......
......@@ -609,10 +609,19 @@ static void ir_set_termios (struct usb_serial_port *port, struct termios *old_te
static int __init ir_init (void)
{
usb_serial_register (&ir_device);
usb_register (&ir_driver);
int retval;
retval = usb_serial_register(&ir_device);
if (retval)
goto failed_usb_serial_register;
retval = usb_register(&ir_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
failed_usb_register:
usb_serial_deregister(&ir_device);
failed_usb_serial_register:
return retval;
}
......
......@@ -197,15 +197,36 @@ struct keyspan_port_private {
/* Functions used by new usb-serial code. */
static int __init keyspan_init (void)
{
usb_serial_register (&keyspan_pre_device);
usb_serial_register (&keyspan_1port_device);
usb_serial_register (&keyspan_2port_device);
usb_serial_register (&keyspan_4port_device);
usb_register (&keyspan_driver);
int retval;
retval = usb_serial_register(&keyspan_pre_device);
if (retval)
goto failed_pre_device_register;
retval = usb_serial_register(&keyspan_1port_device);
if (retval)
goto failed_1port_device_register;
retval = usb_serial_register(&keyspan_2port_device);
if (retval)
goto failed_2port_device_register;
retval = usb_serial_register(&keyspan_4port_device);
if (retval)
goto failed_4port_device_register;
retval = usb_register(&keyspan_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
failed_usb_register:
usb_serial_deregister(&keyspan_4port_device);
failed_4port_device_register:
usb_serial_deregister(&keyspan_2port_device);
failed_2port_device_register:
usb_serial_deregister(&keyspan_1port_device);
failed_1port_device_register:
usb_serial_deregister(&keyspan_pre_device);
failed_pre_device_register:
return retval;
}
static void __exit keyspan_exit (void)
......
......@@ -876,16 +876,39 @@ static struct usb_serial_device_type keyspan_pda_device = {
static int __init keyspan_pda_init (void)
{
usb_serial_register (&keyspan_pda_device);
int retval;
retval = usb_serial_register(&keyspan_pda_device);
if (retval)
goto failed_pda_register;
#ifdef KEYSPAN
usb_serial_register (&keyspan_pda_fake_device);
retval = usb_serial_register(&keyspan_pda_fake_device);
if (retval)
goto failed_pda_fake_register;
#endif
#ifdef XIRCOM
usb_serial_register (&xircom_pgs_fake_device);
retval = usb_serial_register(&xircom_pgs_fake_device);
if (retval)
goto failed_xircom_register;
#endif
usb_register (&keyspan_pda_driver);
retval = usb_register(&keyspan_pda_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
failed_usb_register:
#ifdef XIRCOM
usb_serial_deregister(&xircom_pgs_fake_device);
failed_xircom_register:
#endif /* XIRCOM */
#ifdef KEYSPAN
usb_serial_deregister(&keyspan_pda_fake_device);
#endif
#ifdef KEYSPAN
failed_pda_fake_register:
#endif
usb_serial_deregister(&keyspan_pda_device);
failed_pda_register:
return retval;
}
......
......@@ -1037,11 +1037,20 @@ static void klsi_105_unthrottle (struct usb_serial_port *port)
static int __init klsi_105_init (void)
{
usb_serial_register (&kl5kusb105d_device);
usb_register (&kl5kusb105d_driver);
int retval;
retval = usb_serial_register(&kl5kusb105d_device);
if (retval)
goto failed_usb_serial_register;
retval = usb_register(&kl5kusb105d_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
failed_usb_register:
usb_serial_deregister(&kl5kusb105d_device);
failed_usb_serial_register:
return retval;
}
......
......@@ -743,13 +743,22 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
static int __init kobil_init (void)
{
usb_serial_register (&kobil_device);
usb_register (&kobil_driver);
int retval;
retval = usb_serial_register(&kobil_device);
if (retval)
goto failed_usb_serial_register;
retval = usb_register(&kobil_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_VERSION " " DRIVER_AUTHOR);
info(DRIVER_DESC);
return 0;
failed_usb_register:
usb_serial_deregister(&kobil_device);
failed_usb_serial_register:
return retval;
}
......
......@@ -850,10 +850,19 @@ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
static int __init mct_u232_init (void)
{
usb_serial_register (&mct_u232_device);
usb_register (&mct_u232_driver);
int retval;
retval = usb_serial_register(&mct_u232_device);
if (retval)
goto failed_usb_serial_register;
retval = usb_register(&mct_u232_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
failed_usb_register:
usb_serial_deregister(&mct_u232_device);
failed_usb_serial_register:
return retval;
}
......
......@@ -375,10 +375,19 @@ static void omninet_shutdown (struct usb_serial *serial)
static int __init omninet_init (void)
{
usb_serial_register (&zyxel_omninet_device);
usb_register (&omninet_driver);
int retval;
retval = usb_serial_register(&zyxel_omninet_device);
if (retval)
goto failed_usb_serial_register;
retval = usb_register(&omninet_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
failed_usb_register:
usb_serial_deregister(&zyxel_omninet_device);
failed_usb_serial_register:
return retval;
}
......
......@@ -768,10 +768,19 @@ static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
static int __init pl2303_init (void)
{
usb_serial_register (&pl2303_device);
usb_register (&pl2303_driver);
int retval;
retval = usb_serial_register(&pl2303_device);
if (retval)
goto failed_usb_serial_register;
retval = usb_register(&pl2303_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
failed_usb_register:
usb_serial_deregister(&pl2303_device);
failed_usb_serial_register:
return retval;
}
......
......@@ -422,7 +422,7 @@ static struct usb_serial_device_type safe_device = {
static int __init safe_init (void)
{
int i;
int i, retval;
info (DRIVER_VERSION " " DRIVER_AUTHOR);
info (DRIVER_DESC);
......@@ -441,10 +441,18 @@ static int __init safe_init (void)
}
}
usb_serial_register (&safe_device);
usb_register (&safe_driver);
retval = usb_serial_register(&safe_device);
if (retval)
goto failed_usb_serial_register;
retval = usb_register(&safe_driver);
if (retval)
goto failed_usb_register;
return 0;
failed_usb_register:
usb_serial_deregister(&safe_device);
failed_usb_serial_register:
return retval;
}
static void __exit safe_exit (void)
......
......@@ -956,7 +956,7 @@ static void visor_set_termios (struct usb_serial_port *port, struct termios *old
static int __init visor_init (void)
{
int i;
int i, retval;
/* Only if parameters were passed to us */
if ((vendor>0) && (product>0)) {
struct usb_device_id usb_dev_temp[]=
......@@ -983,12 +983,24 @@ static int __init visor_init (void)
info("Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x",
vendor, product);
}
usb_serial_register (&handspring_device);
usb_serial_register (&clie_3_5_device);
usb_register (&visor_driver);
retval = usb_serial_register(&handspring_device);
if (retval)
goto failed_handspring_register;
retval = usb_serial_register(&clie_3_5_device);
if (retval)
goto failed_clie_3_5_register;
retval = usb_register(&visor_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
failed_usb_register:
usb_serial_deregister(&clie_3_5_device);
failed_clie_3_5_register:
usb_serial_deregister(&handspring_device);
failed_handspring_register:
return retval;
}
......
......@@ -1486,11 +1486,24 @@ static void rx_data_softint(void *private)
*****************************************************************************/
static int __init whiteheat_init (void)
{
usb_serial_register (&whiteheat_fake_device);
usb_serial_register (&whiteheat_device);
usb_register (&whiteheat_driver);
int retval;
retval = usb_serial_register(&whiteheat_fake_device);
if (retval)
goto failed_fake_register;
retval = usb_serial_register(&whiteheat_device);
if (retval)
goto failed_device_register;
retval = usb_register(&whiteheat_driver);
if (retval)
goto failed_usb_register;
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
failed_usb_register:
usb_serial_deregister(&whiteheat_device);
failed_device_register:
usb_serial_deregister(&whiteheat_fake_device);
failed_fake_register:
return retval;
}
......
......@@ -34,6 +34,7 @@
#include "debug.h"
#include "sddr09.h"
#include <linux/version.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/slab.h>
......
......@@ -48,7 +48,6 @@
#include <linux/blkdev.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
#include <linux/version.h>
#include "scsi.h"
#include "hosts.h"
......
......@@ -63,6 +63,12 @@ video_device_create_file(struct video_device *vfd,
{
class_device_create_file(&vfd->class_dev, attr);
}
static inline void
video_device_remove_file(struct video_device *vfd,
struct class_device_attribute *attr)
{
class_device_remove_file(&vfd->class_dev, attr);
}
/* helper functions to alloc / release struct video_device, the
later can be used for video_device->release() */
......
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