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

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

into kroah.com:/home/greg/linux/BK/usb-2.6
parents 2025eb1f 3e6522b0
......@@ -7,7 +7,7 @@ menu "USB support"
# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
config USB
tristate "Support for Host-side USB"
depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610
depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_LH7A404
---help---
Universal Serial Bus (USB) is a specification for a serial bus
subsystem which offers higher speeds and more features than the
......
......@@ -2008,6 +2008,7 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign
{
struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data;
int i, j, val;
int __user *user_arg = (int __user *)arg;
if (!ms->state->usbdev)
return -ENODEV;
......@@ -2034,7 +2035,7 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign
return 0;
}
if (cmd == OSS_GETVERSION)
return put_user(SOUND_VERSION, (int *)arg);
return put_user(SOUND_VERSION, user_arg);
if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
return -EINVAL;
if (_IOC_DIR(cmd) == _IOC_READ) {
......@@ -2043,27 +2044,27 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign
val = get_rec_src(ms);
if (val < 0)
return val;
return put_user(val, (int *)arg);
return put_user(val, user_arg);
case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */
for (val = i = 0; i < ms->numch; i++)
val |= 1 << ms->ch[i].osschannel;
return put_user(val, (int *)arg);
return put_user(val, user_arg);
case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
for (val = i = 0; i < ms->numch; i++)
if (ms->ch[i].slctunitid)
val |= 1 << ms->ch[i].osschannel;
return put_user(val, (int *)arg);
return put_user(val, user_arg);
case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
for (val = i = 0; i < ms->numch; i++)
if (ms->ch[i].flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))
val |= 1 << ms->ch[i].osschannel;
return put_user(val, (int *)arg);
return put_user(val, user_arg);
case SOUND_MIXER_CAPS:
return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg);
return put_user(SOUND_CAP_EXCL_INPUT, user_arg);
default:
i = _IOC_NR(cmd);
......@@ -2071,7 +2072,7 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign
return -EINVAL;
for (j = 0; j < ms->numch; j++) {
if (ms->ch[j].osschannel == i) {
return put_user(ms->ch[j].value, (int *)arg);
return put_user(ms->ch[j].value, user_arg);
}
}
return -EINVAL;
......@@ -2082,7 +2083,7 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign
ms->modcnt++;
switch (_IOC_NR(cmd)) {
case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
if (get_user(val, (int *)arg))
if (get_user(val, user_arg))
return -EFAULT;
return set_rec_src(ms, val);
......@@ -2093,11 +2094,11 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign
for (j = 0; j < ms->numch && ms->ch[j].osschannel != i; j++);
if (j >= ms->numch)
return -EINVAL;
if (get_user(val, (int *)arg))
if (get_user(val, user_arg))
return -EFAULT;
if (wrmixer(ms, j, val))
return -EIO;
return put_user(ms->ch[j].value, (int *)arg);
return put_user(ms->ch[j].value, user_arg);
}
}
......@@ -2370,6 +2371,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
{
struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
struct usb_audio_state *s = as->state;
int __user *user_arg = (int __user *)arg;
unsigned long flags;
audio_buf_info abinfo;
count_info cinfo;
......@@ -2387,7 +2389,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
#endif
switch (cmd) {
case OSS_GETVERSION:
return put_user(SOUND_VERSION, (int *)arg);
return put_user(SOUND_VERSION, user_arg);
case SNDCTL_DSP_SYNC:
if (file->f_mode & FMODE_WRITE)
......@@ -2399,7 +2401,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
case SNDCTL_DSP_GETCAPS:
return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER |
DSP_CAP_MMAP | DSP_CAP_BATCH, (int *)arg);
DSP_CAP_MMAP | DSP_CAP_BATCH, user_arg);
case SNDCTL_DSP_RESET:
if (file->f_mode & FMODE_WRITE) {
......@@ -2413,7 +2415,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
return 0;
case SNDCTL_DSP_SPEED:
if (get_user(val, (int *)arg))
if (get_user(val, user_arg))
return -EFAULT;
if (val >= 0) {
if (val < 4000)
......@@ -2423,10 +2425,12 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
if (set_format(as, file->f_mode, AFMT_QUERY, val))
return -EIO;
}
return put_user((file->f_mode & FMODE_READ) ? as->usbin.dma.srate : as->usbout.dma.srate, (int *)arg);
return put_user((file->f_mode & FMODE_READ) ?
as->usbin.dma.srate : as->usbout.dma.srate,
user_arg);
case SNDCTL_DSP_STEREO:
if (get_user(val, (int *)arg))
if (get_user(val, user_arg))
return -EFAULT;
val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
if (val)
......@@ -2438,7 +2442,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
return 0;
case SNDCTL_DSP_CHANNELS:
if (get_user(val, (int *)arg))
if (get_user(val, user_arg))
return -EFAULT;
if (val != 0) {
val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
......@@ -2450,14 +2454,14 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
return -EIO;
}
val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, (int *)arg);
return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, user_arg);
case SNDCTL_DSP_GETFMTS: /* Returns a mask */
return put_user(AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE |
AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE, (int *)arg);
AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE, user_arg);
case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
if (get_user(val, (int *)arg))
if (get_user(val, user_arg))
return -EFAULT;
if (val != AFMT_QUERY) {
if (hweight32(val) != 1)
......@@ -2471,7 +2475,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
return -EIO;
}
val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
return put_user(val2 & ~AFMT_STEREO, (int *)arg);
return put_user(val2 & ~AFMT_STEREO, user_arg);
case SNDCTL_DSP_POST:
return 0;
......@@ -2482,10 +2486,10 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
val |= PCM_ENABLE_INPUT;
if (file->f_mode & FMODE_WRITE && as->usbout.flags & FLG_RUNNING)
val |= PCM_ENABLE_OUTPUT;
return put_user(val, (int *)arg);
return put_user(val, user_arg);
case SNDCTL_DSP_SETTRIGGER:
if (get_user(val, (int *)arg))
if (get_user(val, user_arg))
return -EFAULT;
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
......@@ -2543,7 +2547,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
spin_lock_irqsave(&as->lock, flags);
val = as->usbout.dma.count;
spin_unlock_irqrestore(&as->lock, flags);
return put_user(val, (int *)arg);
return put_user(val, user_arg);
case SNDCTL_DSP_GETIPTR:
if (!(file->f_mode & FMODE_READ))
......@@ -2577,14 +2581,14 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
if (file->f_mode & FMODE_WRITE) {
if ((val = prog_dmabuf_out(as)))
return val;
return put_user(as->usbout.dma.fragsize, (int *)arg);
return put_user(as->usbout.dma.fragsize, user_arg);
}
if ((val = prog_dmabuf_in(as)))
return val;
return put_user(as->usbin.dma.fragsize, (int *)arg);
return put_user(as->usbin.dma.fragsize, user_arg);
case SNDCTL_DSP_SETFRAGMENT:
if (get_user(val, (int *)arg))
if (get_user(val, user_arg))
return -EFAULT;
if (file->f_mode & FMODE_READ) {
as->usbin.dma.ossfragshift = val & 0xffff;
......@@ -2612,7 +2616,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
if ((file->f_mode & FMODE_READ && as->usbin.dma.subdivision) ||
(file->f_mode & FMODE_WRITE && as->usbout.dma.subdivision))
return -EINVAL;
if (get_user(val, (int *)arg))
if (get_user(val, user_arg))
return -EFAULT;
if (val != 1 && val != 2 && val != 4)
return -EINVAL;
......@@ -2623,15 +2627,17 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
return 0;
case SOUND_PCM_READ_RATE:
return put_user((file->f_mode & FMODE_READ) ? as->usbin.dma.srate : as->usbout.dma.srate, (int *)arg);
return put_user((file->f_mode & FMODE_READ) ?
as->usbin.dma.srate : as->usbout.dma.srate,
user_arg);
case SOUND_PCM_READ_CHANNELS:
val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, (int *)arg);
return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, user_arg);
case SOUND_PCM_READ_BITS:
val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
return put_user(AFMT_IS16BIT(val2) ? 16 : 8, (int *)arg);
return put_user(AFMT_IS16BIT(val2) ? 16 : 8, user_arg);
case SOUND_PCM_WRITE_FILTER:
case SNDCTL_DSP_SETSYNCRO:
......
This diff is collapsed.
/*
*
* Includes for cdc-acm.c
*
* Mainly take from usbnet's cdc-ether part
*
*/
/*
* CMSPAR, some architectures can't have space and mark parity.
*/
#ifndef CMSPAR
#define CMSPAR 0
#endif
/*
* Major and minor numbers.
*/
#define ACM_TTY_MAJOR 166
#define ACM_TTY_MINORS 32
/*
* Requests.
*/
#define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
#define ACM_REQ_COMMAND 0x00
#define ACM_REQ_RESPONSE 0x01
#define ACM_REQ_SET_FEATURE 0x02
#define ACM_REQ_GET_FEATURE 0x03
#define ACM_REQ_CLEAR_FEATURE 0x04
#define ACM_REQ_SET_LINE 0x20
#define ACM_REQ_GET_LINE 0x21
#define ACM_REQ_SET_CONTROL 0x22
#define ACM_REQ_SEND_BREAK 0x23
/*
* IRQs.
*/
#define ACM_IRQ_NETWORK 0x00
#define ACM_IRQ_LINE_STATE 0x20
/*
* Output control lines.
*/
#define ACM_CTRL_DTR 0x01
#define ACM_CTRL_RTS 0x02
/*
* Input control lines and line errors.
*/
#define ACM_CTRL_DCD 0x01
#define ACM_CTRL_DSR 0x02
#define ACM_CTRL_BRK 0x04
#define ACM_CTRL_RI 0x08
#define ACM_CTRL_FRAMING 0x10
#define ACM_CTRL_PARITY 0x20
#define ACM_CTRL_OVERRUN 0x40
/*
* Line speed and caracter encoding.
*/
struct acm_line {
__u32 speed;
__u8 stopbits;
__u8 parity;
__u8 databits;
} __attribute__ ((packed));
/*
* Internal driver structures.
*/
struct acm {
struct usb_device *dev; /* the corresponding usb device */
struct usb_interface *control; /* control interface */
struct usb_interface *data; /* data interface */
struct tty_struct *tty; /* the corresponding tty */
struct urb *ctrlurb, *readurb, *writeurb; /* urbs */
struct acm_line line; /* line coding (bits, stop, parity) */
struct work_struct work; /* work queue entry for line discipline waking up */
struct tasklet_struct bh; /* rx processing */
unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
unsigned int ctrlout; /* output control lines (DTR, RTS) */
unsigned int writesize; /* max packet size for the output bulk endpoint */
unsigned int used; /* someone has this acm's device open */
unsigned int minor; /* acm minor number */
unsigned char throttle; /* throttled by tty layer */
unsigned char clocal; /* termios CLOCAL */
unsigned char ready_for_write; /* write urb can be used */
};
/* "Union Functional Descriptor" from CDC spec 5.2.3.X */
struct union_desc {
u8 bLength;
u8 bDescriptorType;
u8 bDescriptorSubType;
u8 bMasterInterface0;
u8 bSlaveInterface0;
/* ... and there could be other slave interfaces */
} __attribute__ ((packed));
#define CDC_UNION_TYPE 0x06
#define CDC_DATA_INTERFACE_TYPE 0x0a
......@@ -75,6 +75,7 @@
#define IOCNR_HP_SET_CHANNEL 4
#define IOCNR_GET_BUS_ADDRESS 5
#define IOCNR_GET_VID_PID 6
#define IOCNR_SOFT_RESET 7
/* Get device_id string: */
#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
/* The following ioctls were added for http://hpoj.sourceforge.net: */
......@@ -90,6 +91,8 @@
#define LPIOC_GET_BUS_ADDRESS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_BUS_ADDRESS, len)
/* Get two-int array: [0]=vendor ID, [1]=product ID: */
#define LPIOC_GET_VID_PID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_VID_PID, len)
/* Perform class specific soft reset */
#define LPIOC_SOFT_RESET _IOC(_IOC_NONE, 'P', IOCNR_SOFT_RESET, 0);
/*
* A DEVICE_ID string may include the printer's serial number.
......@@ -587,6 +590,13 @@ static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
usblp->minor, twoints[0], twoints[1]);
break;
case IOCNR_SOFT_RESET:
if (_IOC_DIR(cmd) != _IOC_NONE) {
retval = -EINVAL;
goto done;
}
retval = usblp_reset(usblp);
break;
default:
retval = -ENOTTY;
}
......@@ -761,6 +771,7 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
usblp->minor, usblp->readurb->status);
usblp->readurb->dev = usblp->dev;
usblp->readcount = 0;
usblp->rcomplete = 0;
if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0)
dbg("error submitting urb");
count = -EIO;
......
......@@ -589,6 +589,8 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte
bus = list_entry(buslist, struct usb_bus, bus_list);
/* recurse through all children of the root hub */
if (!bus->root_hub)
continue;
down(&bus->root_hub->serialize);
ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
up(&bus->root_hub->serialize);
......
......@@ -558,7 +558,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
if (usbfs_snoop) {
dev_info(&dev->dev, "control read: data ");
for (j = 0; j < ctrl.wLength; ++j)
printk ("%02x ", (unsigned char)((char *)ctrl.data)[j]);
printk ("%02x ", (unsigned char)(tbuf)[j]);
printk("\n");
}
if (copy_to_user(ctrl.data, tbuf, ctrl.wLength)) {
......@@ -578,7 +578,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
if (usbfs_snoop) {
dev_info(&dev->dev, "control write: data: ");
for (j = 0; j < ctrl.wLength; ++j)
printk ("%02x ", (unsigned char)((char *)ctrl.data)[j]);
printk ("%02x ", (unsigned char)(tbuf)[j]);
printk("\n");
}
i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
......
......@@ -229,7 +229,6 @@ EXPORT_SYMBOL (usb_hcd_pci_probe);
void usb_hcd_pci_remove (struct pci_dev *dev)
{
struct usb_hcd *hcd;
struct usb_device *hub;
hcd = pci_get_drvdata(dev);
if (!hcd)
......@@ -239,12 +238,11 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
if (in_interrupt ())
BUG ();
hub = hcd->self.root_hub;
if (HCD_IS_RUNNING (hcd->state))
hcd->state = USB_STATE_QUIESCING;
dev_dbg (hcd->self.controller, "roothub graceful disconnect\n");
usb_disconnect (&hub);
usb_disconnect (&hcd->self.root_hub);
hcd->driver->stop (hcd);
hcd_buffer_destroy (hcd);
......
......@@ -764,8 +764,9 @@ EXPORT_SYMBOL (usb_deregister_bus);
*
* The USB host controller calls this function to register the root hub
* properly with the USB subsystem. It sets up the device properly in
* the device model tree, and then calls usb_new_device() to register the
* usb device. It also assigns the root hub's USB address (always 1).
* the device tree and stores the root_hub pointer in the bus structure,
* then calls usb_new_device() to register the usb device. It also
* assigns the root hub's USB address (always 1).
*/
int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev)
{
......@@ -777,7 +778,10 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev
memset (&usb_dev->bus->devmap.devicemap, 0,
sizeof usb_dev->bus->devmap.devicemap);
set_bit (devnum, usb_dev->bus->devmap.devicemap);
usb_dev->state = USB_STATE_ADDRESS;
usb_set_device_state(usb_dev, USB_STATE_ADDRESS);
down (&usb_bus_list_lock);
usb_dev->bus->root_hub = usb_dev;
usb_dev->epmaxpacketin[0] = usb_dev->epmaxpacketout[0] = 64;
retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
......@@ -787,14 +791,15 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev
return (retval < 0) ? retval : -EMSGSIZE;
}
(void) usb_get_dev (usb_dev);
down (&usb_dev->serialize);
retval = usb_new_device (usb_dev);
if (retval)
up (&usb_dev->serialize);
if (retval) {
usb_dev->bus->root_hub = NULL;
dev_err (parent_dev, "can't register root hub for %s, %d\n",
usb_dev->dev.bus_id, retval);
up (&usb_dev->serialize);
usb_put_dev (usb_dev);
}
up (&usb_bus_list_lock);
return retval;
}
EXPORT_SYMBOL (usb_register_root_hub);
......@@ -1574,11 +1579,13 @@ static void hcd_panic (void *_hcd)
unsigned i;
/* hc's root hub is removed later removed in hcd->stop() */
hub->state = USB_STATE_NOTATTACHED;
down (&hub->serialize);
usb_set_device_state(hub, USB_STATE_NOTATTACHED);
for (i = 0; i < hub->maxchild; i++) {
if (hub->children [i])
usb_disconnect (&hub->children [i]);
}
up (&hub->serialize);
}
/**
......
......@@ -244,17 +244,10 @@ extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
struct usb_bus *, unsigned port);
extern int usb_new_device(struct usb_device *dev);
extern void usb_disconnect(struct usb_device **);
extern void usb_choose_address(struct usb_device *dev);
extern void usb_release_address(struct usb_device *dev);
/* exported to hub driver ONLY to support usb_reset_device () */
extern int usb_get_configuration(struct usb_device *dev);
extern void usb_destroy_configuration(struct usb_device *dev);
/* use these only before the device's address has been set */
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30))
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | USB_DIR_IN)
/*-------------------------------------------------------------------------*/
/*
......@@ -346,7 +339,8 @@ extern void usb_deregister_bus (struct usb_bus *);
extern int usb_register_root_hub (struct usb_device *usb_dev,
struct device *parent_dev);
static inline int hcd_register_root (struct usb_hcd *hcd)
static inline int hcd_register_root (struct usb_device *usb_dev,
struct usb_hcd *hcd)
{
/* hcd->driver->start() reported can_wakeup, probably with
* assistance from board's boot firmware.
......@@ -356,8 +350,7 @@ static inline int hcd_register_root (struct usb_hcd *hcd)
dev_dbg (hcd->self.controller, "supports USB remote wakeup\n");
hcd->remote_wakeup = hcd->can_wakeup;
return usb_register_root_hub (
hcd_to_bus (hcd)->root_hub, hcd->self.controller);
return usb_register_root_hub (usb_dev, hcd->self.controller);
}
/*-------------------------------------------------------------------------*/
......
This diff is collapsed.
......@@ -202,11 +202,13 @@ struct usb_hub {
int error; /* last reported error */
int nerrors; /* track consecutive errors */
struct list_head hub_list; /* all hubs */
struct list_head event_list; /* hubs w/data or errs ready */
unsigned long event_bits[1]; /* status change bitmask */
#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
#error event_bits[] is too short!
#endif
struct usb_hub_descriptor *descriptor; /* class descriptor */
struct semaphore khubd_sem;
struct usb_tt tt; /* Transaction Translator */
u8 power_budget; /* in 2mA units; or zero */
......@@ -216,4 +218,15 @@ struct usb_hub {
struct work_struct leds;
};
/* use this for low-powered root hubs */
static inline void
hub_set_power_budget (struct usb_device *hubdev, unsigned mA)
{
struct usb_hub *hub;
hub = (struct usb_hub *)
usb_get_intfdata (hubdev->actconfig->interface[0]);
hub->power_budget = min(mA,(unsigned)500)/2;
}
#endif /* __LINUX_HUB_H */
......@@ -566,22 +566,19 @@ void usb_sg_cancel (struct usb_sg_request *io)
*/
int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
{
int i = 5;
int i;
int result;
memset(buf,0,size); // Make sure we parse really received data
while (i--) {
for (i = 0; i < 3; ++i) {
/* retry on length 0 or stall; some devices are flakey */
if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
(type << 8) + index, 0, buf, size,
HZ * USB_CTRL_GET_TIMEOUT)) > 0
|| result != -EPIPE)
result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
(type << 8) + index, 0, buf, size,
HZ * USB_CTRL_GET_TIMEOUT);
if (!(result == 0 || result == -EPIPE))
break;
dev_dbg (&dev->dev, "RETRY descriptor, result %d\n", result);
result = -ENOMSG;
}
return result;
}
......@@ -830,6 +827,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
interface = dev->actconfig->interface[i];
dev_dbg (&dev->dev, "unregistering interface %s\n",
interface->dev.bus_id);
usb_remove_sysfs_intf_files(interface);
device_del (&interface->dev);
}
......@@ -842,7 +840,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
}
dev->actconfig = 0;
if (dev->state == USB_STATE_CONFIGURED)
dev->state = USB_STATE_ADDRESS;
usb_set_device_state(dev, USB_STATE_ADDRESS);
}
}
......@@ -1047,7 +1045,7 @@ int usb_reset_configuration(struct usb_device *dev)
config->desc.bConfigurationValue, 0,
NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
if (retval < 0) {
dev->state = USB_STATE_ADDRESS;
usb_set_device_state(dev, USB_STATE_ADDRESS);
return retval;
}
......@@ -1185,9 +1183,9 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
dev->actconfig = cp;
if (!cp)
dev->state = USB_STATE_ADDRESS;
usb_set_device_state(dev, USB_STATE_ADDRESS);
else {
dev->state = USB_STATE_CONFIGURED;
usb_set_device_state(dev, USB_STATE_CONFIGURED);
/* Initialize the new interface structures and the
* hc/hcd/usbcore interface/endpoint state.
......@@ -1322,7 +1320,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
*/
err = usb_get_string(dev, dev->string_langid, index, tbuf, 2);
if (err == -EPIPE) {
if (err == -EPIPE || err == 0) {
dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, 2);
err = usb_get_string(dev, dev->string_langid, index, tbuf, 2);
}
......@@ -1331,7 +1329,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
len=tbuf[0];
err = usb_get_string(dev, dev->string_langid, index, tbuf, len);
if (err == -EPIPE) {
if (err == -EPIPE || err == 0) {
dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, len);
err = usb_get_string(dev, dev->string_langid, index, tbuf, len);
}
......
......@@ -2,8 +2,8 @@
* drivers/usb/core/sysfs.c
*
* (C) Copyright 2002 David Brownell
* (C) Copyright 2002 Greg Kroah-Hartman
* (C) Copyright 2002 IBM Corp.
* (C) Copyright 2002,2004 Greg Kroah-Hartman
* (C) Copyright 2002,2004 IBM Corp.
*
* All of the sysfs file attributes for usb devices and interfaces.
*
......@@ -162,29 +162,35 @@ usb_descriptor_attr (bDeviceSubClass, "%02x\n")
usb_descriptor_attr (bDeviceProtocol, "%02x\n")
usb_descriptor_attr (bNumConfigurations, "%d\n")
static struct attribute *dev_attrs[] = {
/* current configuration's attributes */
&dev_attr_bNumInterfaces.attr,
&dev_attr_bConfigurationValue.attr,
&dev_attr_bmAttributes.attr,
&dev_attr_bMaxPower.attr,
/* device attributes */
&dev_attr_idVendor.attr,
&dev_attr_idProduct.attr,
&dev_attr_bcdDevice.attr,
&dev_attr_bDeviceClass.attr,
&dev_attr_bDeviceSubClass.attr,
&dev_attr_bDeviceProtocol.attr,
&dev_attr_bNumConfigurations.attr,
&dev_attr_speed.attr,
&dev_attr_devnum.attr,
&dev_attr_version.attr,
&dev_attr_maxchild.attr,
NULL,
};
static struct attribute_group dev_attr_grp = {
.attrs = dev_attrs,
};
void usb_create_sysfs_dev_files (struct usb_device *udev)
{
struct device *dev = &udev->dev;
/* current configuration's attributes */
device_create_file (dev, &dev_attr_bNumInterfaces);
device_create_file (dev, &dev_attr_bConfigurationValue);
device_create_file (dev, &dev_attr_bmAttributes);
device_create_file (dev, &dev_attr_bMaxPower);
/* device attributes */
device_create_file (dev, &dev_attr_idVendor);
device_create_file (dev, &dev_attr_idProduct);
device_create_file (dev, &dev_attr_bcdDevice);
device_create_file (dev, &dev_attr_bDeviceClass);
device_create_file (dev, &dev_attr_bDeviceSubClass);
device_create_file (dev, &dev_attr_bDeviceProtocol);
device_create_file (dev, &dev_attr_bNumConfigurations);
/* speed varies depending on how you connect the device */
device_create_file (dev, &dev_attr_speed);
// FIXME iff there are other speed configs, show how many
sysfs_create_group(&dev->kobj, &dev_attr_grp);
if (udev->descriptor.iManufacturer)
device_create_file (dev, &dev_attr_manufacturer);
......@@ -192,10 +198,20 @@ void usb_create_sysfs_dev_files (struct usb_device *udev)
device_create_file (dev, &dev_attr_product);
if (udev->descriptor.iSerialNumber)
device_create_file (dev, &dev_attr_serial);
}
void usb_remove_sysfs_dev_files (struct usb_device *udev)
{
struct device *dev = &udev->dev;
device_create_file (dev, &dev_attr_devnum);
device_create_file (dev, &dev_attr_version);
device_create_file (dev, &dev_attr_maxchild);
sysfs_remove_group(&dev->kobj, &dev_attr_grp);
if (udev->descriptor.iManufacturer)
device_remove_file(dev, &dev_attr_manufacturer);
if (udev->descriptor.iProduct)
device_remove_file(dev, &dev_attr_product);
if (udev->descriptor.iSerialNumber)
device_remove_file(dev, &dev_attr_serial);
}
/* Interface fields */
......@@ -217,13 +233,26 @@ usb_intf_attr (bInterfaceSubClass, "%02x\n")
usb_intf_attr (bInterfaceProtocol, "%02x\n")
usb_intf_attr (iInterface, "%02x\n")
static struct attribute *intf_attrs[] = {
&dev_attr_bInterfaceNumber.attr,
&dev_attr_bAlternateSetting.attr,
&dev_attr_bNumEndpoints.attr,
&dev_attr_bInterfaceClass.attr,
&dev_attr_bInterfaceSubClass.attr,
&dev_attr_bInterfaceProtocol.attr,
&dev_attr_iInterface.attr,
NULL,
};
static struct attribute_group intf_attr_grp = {
.attrs = intf_attrs,
};
void usb_create_sysfs_intf_files (struct usb_interface *intf)
{
device_create_file (&intf->dev, &dev_attr_bInterfaceNumber);
device_create_file (&intf->dev, &dev_attr_bAlternateSetting);
device_create_file (&intf->dev, &dev_attr_bNumEndpoints);
device_create_file (&intf->dev, &dev_attr_bInterfaceClass);
device_create_file (&intf->dev, &dev_attr_bInterfaceSubClass);
device_create_file (&intf->dev, &dev_attr_bInterfaceProtocol);
device_create_file (&intf->dev, &dev_attr_iInterface);
sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
}
void usb_remove_sysfs_intf_files (struct usb_interface *intf)
{
sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
}
......@@ -883,6 +883,8 @@ struct usb_device *usb_find_device(u16 vendor_id, u16 product_id)
buslist != &usb_bus_list;
buslist = buslist->next) {
bus = container_of(buslist, struct usb_bus, bus_list);
if (!bus->root_hub)
continue;
dev = match_device(bus->root_hub, vendor_id, product_id);
if (dev)
goto exit;
......@@ -944,235 +946,6 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
return -1;
}
/**
* usb_disconnect - disconnect a device (usbcore-internal)
* @pdev: pointer to device being disconnected
* Context: !in_interrupt ()
*
* Something got disconnected. Get rid of it, and all of its children.
*
* Only hub drivers (including virtual root hub drivers for host
* controllers) should ever call this.
*
* This call is synchronous, and may not be used in an interrupt context.
*/
void usb_disconnect(struct usb_device **pdev)
{
struct usb_device *dev = *pdev;
struct usb_bus *bus;
struct usb_operations *ops;
int i;
might_sleep ();
if (!dev) {
pr_debug ("%s nodev\n", __FUNCTION__);
return;
}
bus = dev->bus;
if (!bus) {
pr_debug ("%s nobus\n", __FUNCTION__);
return;
}
ops = bus->op;
*pdev = NULL;
/* mark the device as inactive, so any further urb submissions for
* this device will fail.
*/
dev->state = USB_STATE_NOTATTACHED;
down(&dev->serialize);
dev_info (&dev->dev, "USB disconnect, address %d\n", dev->devnum);
/* Free up all the children before we remove this device */
for (i = 0; i < USB_MAXCHILDREN; i++) {
struct usb_device **child = dev->children + i;
if (*child)
usb_disconnect(child);
}
/* deallocate hcd/hardware state ... nuking all pending urbs and
* cleaning up all state associated with the current configuration
*/
usb_disable_device(dev, 0);
/* Free the device number and remove the /proc/bus/usb entry */
dev_dbg (&dev->dev, "unregistering device\n");
usb_release_address(dev);
usbfs_remove_device(dev);
up(&dev->serialize);
device_unregister(&dev->dev);
}
/**
* usb_choose_address - pick device address (usbcore-internal)
* @dev: newly detected device (in DEFAULT state)
*
* Picks a device address. It's up to the hub (or root hub) driver
* to handle and manage enumeration, starting from the DEFAULT state.
* Only hub drivers (but not virtual root hub drivers for host
* controllers) should ever call this.
*/
void usb_choose_address(struct usb_device *dev)
{
int devnum;
// FIXME needs locking for SMP!!
/* why? this is called only from the hub thread,
* which hopefully doesn't run on multiple CPU's simultaneously 8-)
*/
/* Try to allocate the next devnum beginning at bus->devnum_next. */
devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, dev->bus->devnum_next);
if (devnum >= 128)
devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1);
dev->bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);
if (devnum < 128) {
set_bit(devnum, dev->bus->devmap.devicemap);
dev->devnum = devnum;
}
}
/**
* usb_release_address - deallocate device address (usbcore-internal)
* @dev: newly removed device
*
* Removes and deallocates the address assigned to a device.
* Only hub drivers (but not virtual root hub drivers for host
* controllers) should ever call this.
*/
void usb_release_address(struct usb_device *dev)
{
if (dev->devnum > 0) {
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
dev->devnum = -1;
}
}
static inline void usb_show_string(struct usb_device *dev, char *id, int index)
{
char *buf;
if (!index)
return;
if (!(buf = kmalloc(256, GFP_KERNEL)))
return;
if (usb_string(dev, index, buf, 256) > 0)
dev_printk(KERN_INFO, &dev->dev, "%s: %s\n", id, buf);
kfree(buf);
}
static int usb_choose_configuration(struct usb_device *dev)
{
int c, i;
c = dev->config[0].desc.bConfigurationValue;
if (dev->descriptor.bNumConfigurations != 1) {
for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
struct usb_interface_descriptor *desc;
/* heuristic: Linux is more likely to have class
* drivers, so avoid vendor-specific interfaces.
*/
desc = &dev->config[i].intf_cache[0]
->altsetting->desc;
if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC)
continue;
/* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS */
if (desc->bInterfaceClass == USB_CLASS_COMM
&& desc->bInterfaceSubClass == 2
&& desc->bInterfaceProtocol == 0xff)
continue;
c = dev->config[i].desc.bConfigurationValue;
break;
}
dev_info(&dev->dev,
"configuration #%d chosen from %d choices\n",
c, dev->descriptor.bNumConfigurations);
}
return c;
}
/*
* usb_new_device - perform initial device setup (usbcore-internal)
* @dev: newly addressed device (in ADDRESS state)
*
* This is called with devices which have been enumerated, but not yet
* configured. The device descriptor is available, but not descriptors
* for any device configuration. The caller owns dev->serialize, and
* the device is not visible through sysfs or other filesystem code.
*
* Returns 0 for success (device is configured and listed, with its
* interfaces, in sysfs); else a negative errno value. On error, one
* reference count to the device has been dropped.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Only the hub driver should ever call this; root hub registration
* uses it only indirectly.
*/
int usb_new_device(struct usb_device *dev)
{
int err;
int c;
err = usb_get_configuration(dev);
if (err < 0) {
dev_err(&dev->dev, "can't read configurations, error %d\n",
err);
goto fail;
}
/* Tell the world! */
dev_dbg(&dev->dev, "new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber);
#ifdef DEBUG
if (dev->descriptor.iProduct)
usb_show_string(dev, "Product", dev->descriptor.iProduct);
if (dev->descriptor.iManufacturer)
usb_show_string(dev, "Manufacturer", dev->descriptor.iManufacturer);
if (dev->descriptor.iSerialNumber)
usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
#endif
/* put device-specific files into sysfs */
err = device_add (&dev->dev);
if (err) {
dev_err(&dev->dev, "can't device_add, error %d\n", err);
goto fail;
}
usb_create_sysfs_dev_files (dev);
/* choose and set the configuration. that registers the interfaces
* with the driver core, and lets usb device drivers bind to them.
* NOTE: should interact with hub power budgeting.
*/
c = usb_choose_configuration(dev);
err = usb_set_configuration(dev, c);
if (err) {
dev_err(&dev->dev, "can't set config #%d, error %d\n", c, err);
device_del(&dev->dev);
goto fail;
}
/* USB device state == configured ... usable */
/* add a /proc/bus/usb entry */
usbfs_add_device(dev);
return 0;
fail:
dev->state = USB_STATE_NOTATTACHED;
usb_release_address(dev);
usb_put_dev(dev);
return err;
}
/**
* usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP
* @dev: device the buffer will be used with
......
/* Functions local to drivers/usb/core/ */
extern void usb_create_sysfs_dev_files (struct usb_device *dev);
extern void usb_remove_sysfs_dev_files (struct usb_device *dev);
extern void usb_create_sysfs_intf_files (struct usb_interface *intf);
extern void usb_remove_sysfs_intf_files (struct usb_interface *intf);
extern int usb_probe_interface (struct device *dev);
extern int usb_unbind_interface (struct device *dev);
......@@ -19,5 +21,8 @@ extern int usb_get_device_descriptor(struct usb_device *dev,
unsigned int size);
extern int usb_set_configuration(struct usb_device *dev, int configuration);
extern void usb_set_device_state(struct usb_device *udev,
enum usb_device_state new_state);
/* for labeling diagnostics */
extern const char *usbcore_name;
......@@ -825,8 +825,7 @@ static int dummy_urb_enqueue (
dum = container_of (hcd, struct dummy, hcd);
spin_lock_irqsave (&dum->lock, flags);
if (!dum->hdev)
dum->hdev = urb->dev->hcpriv;
dum->hdev = urb->dev->hcpriv;
urb->hcpriv = dum;
if (usb_pipetype (urb->pipe) == PIPE_CONTROL)
urb->error_count = 1; /* mark as a new urb */
......@@ -994,10 +993,17 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep)
return limit;
}
#define is_active(dum) ((dum->port_status & \
(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE | \
USB_PORT_STAT_SUSPEND)) \
== (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE))
static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
{
int i;
if (!is_active (dum))
return NULL;
if ((address & ~USB_DIR_IN) == 0)
return &dum->ep [0];
for (i = 1; i < DUMMY_ENDPOINTS; i++) {
......@@ -1011,6 +1017,8 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
return NULL;
}
#undef is_active
#define Dev_Request (USB_TYPE_STANDARD | USB_RECIP_DEVICE)
#define Dev_InRequest (Dev_Request | USB_DIR_IN)
#define Intf_Request (USB_TYPE_STANDARD | USB_RECIP_INTERFACE)
......@@ -1152,11 +1160,6 @@ static void dummy_timer (unsigned long _dum)
case USB_REQ_SET_ADDRESS:
if (setup.bRequestType != Dev_Request)
break;
if (dum->address != 0) {
maybe_set_status (urb, -ETIMEDOUT);
urb->actual_length = 0;
goto return_urb;
}
dum->address = setup.wValue;
maybe_set_status (urb, 0);
dev_dbg (hardware, "set_address = %d\n",
......@@ -1404,9 +1407,8 @@ static int dummy_hub_control (
break;
case USB_PORT_FEAT_POWER:
dum->port_status = 0;
dum->address = 0;
dum->hdev = 0;
dum->resuming = 0;
stop_activity(dum, dum->driver);
break;
default:
dum->port_status &= ~(1 << wValue);
......@@ -1657,7 +1659,7 @@ static int dummy_start (struct usb_hcd *hcd)
INIT_LIST_HEAD (&hcd->dev_list);
usb_register_bus (bus);
bus->root_hub = root = usb_alloc_dev (0, bus, 0);
root = usb_alloc_dev (0, bus, 0);
if (!root) {
retval = -ENOMEM;
clean1:
......@@ -1671,14 +1673,16 @@ static int dummy_start (struct usb_hcd *hcd)
root->speed = USB_SPEED_HIGH;
/* ...then configured, so khubd sees us. */
if ((retval = hcd_register_root (&dum->hcd)) != 0) {
bus->root_hub = 0;
if ((retval = hcd_register_root (root, &dum->hcd)) != 0) {
usb_put_dev (root);
clean2:
dum->hcd.state = USB_STATE_QUIESCING;
goto clean1;
}
/* only show a low-power port: just 8mA */
hub_set_power_budget (root, 8);
dum->started = 1;
if ((retval = dummy_register_udc (dum)) != 0) {
......
......@@ -118,6 +118,7 @@ struct eth_dev {
unsigned zlp:1;
unsigned cdc:1;
unsigned rndis:1;
unsigned suspended:1;
u16 cdc_filter;
unsigned long todo;
#define WORK_RX_MEMORY 0
......@@ -1345,24 +1346,23 @@ static void eth_setup_complete (struct usb_ep *ep, struct usb_request *req)
static void rndis_response_complete (struct usb_ep *ep, struct usb_request *req)
{
struct eth_dev *dev = ep->driver_data;
if (req->status || req->actual != req->length)
DEBUG (dev, "rndis response complete --> %d, %d/%d\n",
req->status, req->actual, req->length);
/* done sending after CDC_GET_ENCAPSULATED_RESPONSE */
rndis_free_response (dev->rndis_config, req->buf);
}
static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
{
struct eth_dev *dev = ep->driver_data;
int status;
/* received RNDIS command from CDC_SEND_ENCAPSULATED_COMMAND */
spin_lock(&dev->lock);
if (rndis_msg_parser (dev->rndis_config, (u8 *) req->buf))
ERROR(dev, "%s: rndis parse error\n", __FUNCTION__ );
status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
if (status < 0)
ERROR(dev, "%s: rndis parse error %d\n", __FUNCTION__, status);
spin_unlock(&dev->lock);
}
......@@ -1580,6 +1580,7 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (buf) {
memcpy (req->buf, buf, value);
req->complete = rndis_response_complete;
rndis_free_response(dev->rndis_config, buf);
}
/* else stalls ... spec says to avoid that */
}
......@@ -2064,6 +2065,16 @@ static void rndis_send_media_state (struct eth_dev *dev, int connect)
}
}
static void rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req)
{
if (req->status || req->actual != req->length)
DEBUG (dev, "rndis control ack complete --> %d, %d/%d\n",
req->status, req->actual, req->length);
usb_ep_free_buffer(ep, req->buf, req->dma, 8);
usb_ep_free_request(ep, req);
}
static int rndis_control_ack (struct net_device *net)
{
struct eth_dev *dev = (struct eth_dev *) net->priv;
......@@ -2095,7 +2106,7 @@ static int rndis_control_ack (struct net_device *net)
* CDC_NOTIFY_RESPONSE_AVAILABLE should work too
*/
resp->length = 8;
resp->complete = rndis_response_complete;
resp->complete = rndis_control_ack_complete;
*((u32 *) resp->buf) = __constant_cpu_to_le32 (1);
*((u32 *) resp->buf + 1) = __constant_cpu_to_le32 (0);
......@@ -2103,7 +2114,7 @@ static int rndis_control_ack (struct net_device *net)
length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC);
if (length < 0) {
resp->status = 0;
rndis_response_complete (dev->status_ep, resp);
rndis_control_ack_complete (dev->status_ep, resp);
}
return 0;
......@@ -2302,17 +2313,6 @@ eth_bind (struct usb_gadget *gadget)
UTS_SYSNAME " " UTS_RELEASE "/%s",
gadget->name);
/* CDC subset ... recognized by Linux since 2.4.10, but Windows
* drivers aren't widely available.
*/
if (!cdc) {
device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
device_desc.idVendor =
__constant_cpu_to_le16(SIMPLE_VENDOR_NUM);
device_desc.idProduct =
__constant_cpu_to_le16(SIMPLE_PRODUCT_NUM);
}
/* If there's an RNDIS configuration, that's what Windows wants to
* be using ... so use these product IDs here and in the "linux.inf"
* needed to install MSFT drivers. Current Linux kernels will use
......@@ -2326,6 +2326,16 @@ eth_bind (struct usb_gadget *gadget)
__constant_cpu_to_le16(RNDIS_PRODUCT_NUM);
snprintf (product_desc, sizeof product_desc,
"RNDIS/%s", driver_desc);
/* CDC subset ... recognized by Linux since 2.4.10, but Windows
* drivers aren't widely available.
*/
} else if (!cdc) {
device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
device_desc.idVendor =
__constant_cpu_to_le16(SIMPLE_VENDOR_NUM);
device_desc.idProduct =
__constant_cpu_to_le16(SIMPLE_PRODUCT_NUM);
}
/* support optional vendor/distro customization */
......@@ -2554,6 +2564,26 @@ eth_bind (struct usb_gadget *gadget)
/*-------------------------------------------------------------------------*/
static void
eth_suspend (struct usb_gadget *gadget)
{
struct eth_dev *dev = get_gadget_data (gadget);
DEBUG (dev, "suspend\n");
dev->suspended = 1;
}
static void
eth_resume (struct usb_gadget *gadget)
{
struct eth_dev *dev = get_gadget_data (gadget);
DEBUG (dev, "resume\n");
dev->suspended = 0;
}
/*-------------------------------------------------------------------------*/
static struct usb_gadget_driver eth_driver = {
#ifdef CONFIG_USB_GADGET_DUALSPEED
.speed = USB_SPEED_HIGH,
......@@ -2567,6 +2597,9 @@ static struct usb_gadget_driver eth_driver = {
.setup = eth_setup,
.disconnect = eth_disconnect,
.suspend = eth_suspend,
.resume = eth_resume,
.driver = {
.name = (char *) shortname,
// .shutdown = ...
......
......@@ -2501,7 +2501,7 @@ static int send_status(struct fsg_dev *fsg)
/* Store and send the Bulk-only CSW */
csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG);
csw->Tag = fsg->tag;
csw->Residue = fsg->residue;
csw->Residue = cpu_to_le32(fsg->residue);
csw->Status = status;
bh->inreq->length = USB_BULK_CS_WRAP_LEN;
......@@ -2947,7 +2947,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
fsg->data_dir = DATA_DIR_TO_HOST;
else
fsg->data_dir = DATA_DIR_FROM_HOST;
fsg->data_size = cbw->DataTransferLength;
fsg->data_size = le32_to_cpu(cbw->DataTransferLength);
if (fsg->data_size == 0)
fsg->data_dir = DATA_DIR_NONE;
fsg->lun = cbw->Lun;
......@@ -3834,6 +3834,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
}
/* Find all the endpoints we will use */
usb_ep_autoconfig_reset(gadget);
ep = usb_ep_autoconfig(gadget, &fs_bulk_in_desc);
if (!ep)
goto autoconf_fail;
......
......@@ -26,11 +26,41 @@
#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A
#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B
enum NDIS_DEVICE_POWER_STATE {
NdisDeviceStateUnspecified = 0,
NdisDeviceStateD0,
NdisDeviceStateD1,
NdisDeviceStateD2,
NdisDeviceStateD3,
NdisDeviceStateMaximum
};
struct NDIS_PM_WAKE_UP_CAPABILITIES {
enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp;
enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp;
enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp;
};
/* NDIS_PNP_CAPABILITIES.Flags constants */
#define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001
#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002
#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004
struct NDIS_PNP_CAPABILITIES {
u32 Flags;
struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities;
};
struct NDIS_PM_PACKET_PATTERN {
u32 Priority;
u32 Reserved;
u32 MaskSize;
u32 PatternOffset;
u32 PatternSize;
u32 PatternFlags;
};
/* Required Object IDs (OIDs) */
#define OID_GEN_SUPPORTED_LIST 0x00010101
#define OID_GEN_HARDWARE_STATUS 0x00010102
......
......@@ -1902,6 +1902,8 @@ static void ep0_start (struct net2280 *dev)
, &dev->usb->stdrsp);
writel ( (1 << USB_ROOT_PORT_WAKEUP_ENABLE)
| (1 << SELF_POWERED_USB_DEVICE)
/* erratum 0102 workaround */
| ((dev->chiprev == 0100) ? 0 : 1) << SUSPEND_IMMEDIATELY
| (1 << REMOTE_WAKEUP_SUPPORT)
| (1 << USB_DETECT_ENABLE)
| (1 << SELF_POWERED_STATUS)
......@@ -1917,6 +1919,7 @@ static void ep0_start (struct net2280 *dev)
| (1 << PCI_RETRY_ABORT_INTERRUPT_ENABLE)
| (1 << VBUS_INTERRUPT_ENABLE)
| (1 << ROOT_PORT_RESET_INTERRUPT_ENABLE)
| (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE)
, &dev->regs->pciirqenb1);
/* don't leave any writes posted */
......@@ -2513,19 +2516,24 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
return;
}
/* NOTE: we don't actually suspend the hardware; that starts to
* interact with PCI power management, and needs something like a
* controller->suspend() call to clear SUSPEND_REQUEST_INTERRUPT.
* we shouldn't see resume interrupts.
* for rev 0100, this also avoids erratum 0102.
/* NOTE: chip stays in PCI D0 state for now, but it could
* enter D1 to save more power
*/
tmp = (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT);
if (stat & tmp) {
if (dev->driver->suspend)
dev->driver->suspend (&dev->gadget);
writel (tmp, &dev->regs->irqstat1);
if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
if (dev->driver->suspend)
dev->driver->suspend (&dev->gadget);
/* we use SUSPEND_IMMEDIATELY */
stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
} else {
if (dev->driver->resume)
dev->driver->resume (&dev->gadget);
/* at high speed, note erratum 0133 */
}
stat &= ~tmp;
}
stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
/* clear any other status/irqs */
if (stat)
......@@ -2533,6 +2541,7 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
/* some status we can just ignore */
stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
| (1 << SUSPEND_REQUEST_INTERRUPT)
| (1 << RESUME_INTERRUPT)
| (1 << SOF_INTERRUPT));
if (!stat)
......
This diff is collapsed.
......@@ -59,10 +59,18 @@
#define RNDIS_MEDIUM_802_3 0x00000000U
/* from drivers/net/sk98lin/h/skgepnmi.h */
#define OID_PNP_CAPABILITIES 0xFD010100
#define OID_PNP_SET_POWER 0xFD010101
#define OID_PNP_QUERY_POWER 0xFD010102
#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103
#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104
#define OID_PNP_ENABLE_WAKE_UP 0xFD010106
/* supported OIDs */
static const u32 oid_supported_list [] =
{
/* mandatory general */
/* the general stuff */
OID_GEN_SUPPORTED_LIST,
OID_GEN_HARDWARE_STATUS,
......@@ -70,7 +78,6 @@ static const u32 oid_supported_list [] =
OID_GEN_MEDIA_IN_USE,
OID_GEN_MAXIMUM_FRAME_SIZE,
OID_GEN_LINK_SPEED,
OID_GEN_TRANSMIT_BUFFER_SPACE,
OID_GEN_TRANSMIT_BLOCK_SIZE,
OID_GEN_RECEIVE_BLOCK_SIZE,
OID_GEN_VENDOR_ID,
......@@ -78,10 +85,11 @@ static const u32 oid_supported_list [] =
OID_GEN_VENDOR_DRIVER_VERSION,
OID_GEN_CURRENT_PACKET_FILTER,
OID_GEN_MAXIMUM_TOTAL_SIZE,
OID_GEN_MAC_OPTIONS,
OID_GEN_MEDIA_CONNECT_STATUS,
OID_GEN_PHYSICAL_MEDIUM,
#if 0
OID_GEN_RNDIS_CONFIG_PARAMETER,
#endif
/* the statistical stuff */
OID_GEN_XMIT_OK,
......@@ -89,6 +97,7 @@ static const u32 oid_supported_list [] =
OID_GEN_XMIT_ERROR,
OID_GEN_RCV_ERROR,
OID_GEN_RCV_NO_BUFFER,
#ifdef RNDIS_OPTIONAL_STATS
OID_GEN_DIRECTED_BYTES_XMIT,
OID_GEN_DIRECTED_FRAMES_XMIT,
OID_GEN_MULTICAST_BYTES_XMIT,
......@@ -103,6 +112,7 @@ static const u32 oid_supported_list [] =
OID_GEN_BROADCAST_FRAMES_RCV,
OID_GEN_RCV_CRC_ERROR,
OID_GEN_TRANSMIT_QUEUE_LENGTH,
#endif /* RNDIS_OPTIONAL_STATS */
/* mandatory 802.3 */
/* the general stuff */
......@@ -115,7 +125,30 @@ static const u32 oid_supported_list [] =
/* the statistical stuff */
OID_802_3_RCV_ERROR_ALIGNMENT,
OID_802_3_XMIT_ONE_COLLISION,
OID_802_3_XMIT_MORE_COLLISIONS
OID_802_3_XMIT_MORE_COLLISIONS,
#ifdef RNDIS_OPTIONAL_STATS
OID_802_3_XMIT_DEFERRED,
OID_802_3_XMIT_MAX_COLLISIONS,
OID_802_3_RCV_OVERRUN,
OID_802_3_XMIT_UNDERRUN,
OID_802_3_XMIT_HEARTBEAT_FAILURE,
OID_802_3_XMIT_TIMES_CRS_LOST,
OID_802_3_XMIT_LATE_COLLISIONS,
#endif /* RNDIS_OPTIONAL_STATS */
#ifdef RNDIS_PM
/* PM and wakeup are mandatory for USB: */
/* power management */
OID_PNP_CAPABILITIES,
OID_PNP_QUERY_POWER,
OID_PNP_SET_POWER,
/* wake up host */
OID_PNP_ENABLE_WAKE_UP,
OID_PNP_ADD_WAKE_UP_PATTERN,
OID_PNP_REMOVE_WAKE_UP_PATTERN,
#endif
};
......
......@@ -290,16 +290,17 @@ static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
{
if (cap & (1 << 16)) {
int msec = 500;
struct pci_dev *pdev = to_pci_dev(ehci->hcd.self.controller);
/* request handoff to OS */
cap &= 1 << 24;
pci_write_config_dword (to_pci_dev(ehci->hcd.self.controller), where, cap);
cap |= 1 << 24;
pci_write_config_dword(pdev, where, cap);
/* and wait a while for it to happen */
do {
msleep(10);
msec -= 10;
pci_read_config_dword (to_pci_dev(ehci->hcd.self.controller), where, &cap);
pci_read_config_dword(pdev, where, &cap);
} while ((cap & (1 << 16)) && msec);
if (cap & (1 << 16)) {
ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n",
......@@ -520,7 +521,7 @@ static int ehci_start (struct usb_hcd *hcd)
/* wire up the root hub */
bus = hcd_to_bus (hcd);
bus->root_hub = udev = usb_alloc_dev (NULL, bus, 0);
udev = usb_alloc_dev (NULL, bus, 0);
if (!udev) {
done2:
ehci_mem_cleanup (ehci);
......@@ -553,11 +554,10 @@ static int ehci_start (struct usb_hcd *hcd)
* and device drivers may start it running.
*/
udev->speed = USB_SPEED_HIGH;
if (hcd_register_root (hcd) != 0) {
if (hcd_register_root (udev, hcd) != 0) {
if (hcd->state == USB_STATE_RUNNING)
ehci_ready (ehci);
ehci_reset (ehci);
bus->root_hub = 0;
usb_put_dev (udev);
retval = -ENODEV;
goto done2;
......
......@@ -483,7 +483,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
qh->start = frame;
/* reset S-frame and (maybe) C-frame masks */
qh->hw_info2 &= ~0xffff;
qh->hw_info2 &= ~__constant_cpu_to_le32(0xffff);
qh->hw_info2 |= cpu_to_le32 (1 << uframe) | c_mask;
} else
dbg ("reused previous qh %p schedule", qh);
......
......@@ -557,18 +557,24 @@ static int rh_unlink_urb (struct urb * urb)
static int rh_connect_rh (hci_t * hci)
{
struct usb_device *usb_dev;
int retval;
hci->rh.devnum = 0;
usb_dev = usb_alloc_dev (NULL, hci->bus, 0);
if (!usb_dev)
return -ENOMEM;
hci->bus->root_hub = usb_dev;
usb_dev->devnum = 1;
usb_dev->bus->devnum_next = usb_dev->devnum + 1;
set_bit (usb_dev->devnum, usb_dev->bus->devmap.devicemap);
if (usb_new_device (usb_dev) != 0) {
down (&usb_bus_list_lock);
hci->bus->root_hub = usb_dev;
retval = usb_new_device (usb_dev);
if (retval != 0)
hci->bus->root_hub = NULL;
up (&usb_bus_list_lock);
if (retval != 0) {
usb_put_dev (usb_dev);
return -ENODEV;
}
......
......@@ -134,13 +134,13 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
struct ohci_regs *regs = controller->regs;
u32 temp;
temp = readl (&regs->revision) & 0xff;
temp = ohci_readl (&regs->revision) & 0xff;
ohci_dbg_sw (controller, next, size,
"OHCI %d.%d, %s legacy support registers\n",
0x03 & (temp >> 4), (temp & 0x0f),
(temp & 0x10) ? "with" : "NO");
temp = readl (&regs->control);
temp = ohci_readl (&regs->control);
ohci_dbg_sw (controller, next, size,
"control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n",
temp,
......@@ -155,7 +155,7 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
temp & OHCI_CTRL_CBSR
);
temp = readl (&regs->cmdstatus);
temp = ohci_readl (&regs->cmdstatus);
ohci_dbg_sw (controller, next, size,
"cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp,
(temp & OHCI_SOC) >> 16,
......@@ -166,26 +166,26 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
);
ohci_dump_intr_mask (controller, "intrstatus",
readl (&regs->intrstatus), next, size);
ohci_readl (&regs->intrstatus), next, size);
ohci_dump_intr_mask (controller, "intrenable",
readl (&regs->intrenable), next, size);
ohci_readl (&regs->intrenable), next, size);
// intrdisable always same as intrenable
maybe_print_eds (controller, "ed_periodcurrent",
readl (&regs->ed_periodcurrent), next, size);
ohci_readl (&regs->ed_periodcurrent), next, size);
maybe_print_eds (controller, "ed_controlhead",
readl (&regs->ed_controlhead), next, size);
ohci_readl (&regs->ed_controlhead), next, size);
maybe_print_eds (controller, "ed_controlcurrent",
readl (&regs->ed_controlcurrent), next, size);
ohci_readl (&regs->ed_controlcurrent), next, size);
maybe_print_eds (controller, "ed_bulkhead",
readl (&regs->ed_bulkhead), next, size);
ohci_readl (&regs->ed_bulkhead), next, size);
maybe_print_eds (controller, "ed_bulkcurrent",
readl (&regs->ed_bulkcurrent), next, size);
ohci_readl (&regs->ed_bulkcurrent), next, size);
maybe_print_eds (controller, "donehead",
readl (&regs->donehead), next, size);
ohci_readl (&regs->donehead), next, size);
}
#define dbg_port_sw(hc,num,value,next,size) \
......@@ -637,7 +637,7 @@ show_registers (struct class_device *class_dev, char *buf)
"hcca frame 0x%04x\n", OHCI_FRAME_NO(ohci->hcca));
/* other registers mostly affect frame timings */
rdata = readl (&regs->fminterval);
rdata = ohci_readl (&regs->fminterval);
temp = scnprintf (next, size,
"fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n",
rdata, (rdata >> 31) ? " FIT" : "",
......@@ -645,20 +645,20 @@ show_registers (struct class_device *class_dev, char *buf)
size -= temp;
next += temp;
rdata = readl (&regs->fmremaining);
rdata = ohci_readl (&regs->fmremaining);
temp = scnprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n",
rdata, (rdata >> 31) ? " FRT" : "",
rdata & 0x3fff);
size -= temp;
next += temp;
rdata = readl (&regs->periodicstart);
rdata = ohci_readl (&regs->periodicstart);
temp = scnprintf (next, size, "periodicstart 0x%04x\n",
rdata & 0x3fff);
size -= temp;
next += temp;
rdata = readl (&regs->lsthresh);
rdata = ohci_readl (&regs->lsthresh);
temp = scnprintf (next, size, "lsthresh 0x%04x\n",
rdata & 0x3fff);
size -= temp;
......
......@@ -17,6 +17,7 @@
*
* History:
*
* 2004/03/24 LH7A404 support (Durgesh Pattamatta & Marc Singer)
* 2004/02/04 use generic dma_* functions instead of pci_* (dsaxena@plexity.net)
* 2003/02/24 show registers in sysfs (Kevin Brosius)
*
......@@ -393,7 +394,7 @@ static int hc_reset (struct ohci_hcd *ohci)
/* boot firmware should have set this up (5.1.1.3.1) */
if (!ohci->fminterval) {
temp = readl (&ohci->regs->fminterval);
temp = ohci_readl (&ohci->regs->fminterval);
if (temp & 0x3fff0000)
ohci->fminterval = temp;
else
......@@ -405,7 +406,7 @@ static int hc_reset (struct ohci_hcd *ohci)
* On PA-RISC, PDC can leave IR set incorrectly; ignore it there.
*/
#ifndef __hppa__
if (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
if (ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) {
ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n");
/* this timeout is arbitrary. we make it long, so systems
......@@ -416,7 +417,7 @@ static int hc_reset (struct ohci_hcd *ohci)
writel (OHCI_INTR_OC, &ohci->regs->intrenable);
writel (OHCI_OCR, &ohci->regs->cmdstatus);
while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
while (ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) {
msleep (10);
if (--temp == 0) {
ohci_err (ohci, "USB HC TakeOver failed!\n");
......@@ -430,13 +431,13 @@ static int hc_reset (struct ohci_hcd *ohci)
writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
ohci_dbg (ohci, "reset, control = 0x%x\n",
readl (&ohci->regs->control));
ohci_readl (&ohci->regs->control));
/* Reset USB (needed by some controllers); RemoteWakeupConnected
* saved if boot firmware (BIOS/SMM/...) told us it's connected
* (for OHCI integrated on mainboard, it normally is)
*/
ohci->hc_control = readl (&ohci->regs->control);
ohci->hc_control = ohci_readl (&ohci->regs->control);
ohci->hc_control &= OHCI_CTRL_RWC; /* hcfs 0 = RESET */
if (ohci->hc_control)
ohci->hcd.can_wakeup = 1;
......@@ -450,13 +451,13 @@ static int hc_reset (struct ohci_hcd *ohci)
&ohci->regs->roothub.portstatus [temp]);
}
// flush those pci writes
(void) readl (&ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
msleep (50);
/* HC Reset requires max 10 us delay */
writel (OHCI_HCR, &ohci->regs->cmdstatus);
temp = 30; /* ... allow extra time */
while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
while ((ohci_readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
if (--temp == 0) {
ohci_err (ohci, "USB HC reset timed out!\n");
return -1;
......@@ -473,7 +474,7 @@ static int hc_reset (struct ohci_hcd *ohci)
*/
writel (ohci->hc_control, &ohci->regs->control);
// flush those pci writes
(void) readl (&ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
return 0;
}
......@@ -505,8 +506,8 @@ static int hc_start (struct ohci_hcd *ohci)
/* some OHCI implementations are finicky about how they init.
* bogus values here mean not even enumeration could work.
*/
if ((readl (&ohci->regs->fminterval) & 0x3fff0000) == 0
|| !readl (&ohci->regs->periodicstart)) {
if ((ohci_readl (&ohci->regs->fminterval) & 0x3fff0000) == 0
|| !ohci_readl (&ohci->regs->periodicstart)) {
ohci_err (ohci, "init err\n");
return -EOVERFLOW;
}
......@@ -548,7 +549,7 @@ static int hc_start (struct ohci_hcd *ohci)
writel (RH_HS_LPSC, &ohci->regs->roothub.status);
writel (power_switching ? RH_B_PPCM : 0, &ohci->regs->roothub.b);
// flush those pci writes
(void) readl (&ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
// POTPGT delay is bits 24-31, in 2 ms units.
mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
......@@ -560,7 +561,7 @@ static int hc_start (struct ohci_hcd *ohci)
}
/* connect the virtual root hub */
bus->root_hub = udev = usb_alloc_dev (NULL, bus, 0);
udev = usb_alloc_dev (NULL, bus, 0);
ohci->hcd.state = USB_STATE_RUNNING;
if (!udev) {
disable (ohci);
......@@ -570,9 +571,8 @@ static int hc_start (struct ohci_hcd *ohci)
}
udev->speed = USB_SPEED_FULL;
if (hcd_register_root (&ohci->hcd) != 0) {
if (hcd_register_root (udev, &ohci->hcd) != 0) {
usb_put_dev (udev);
bus->root_hub = NULL;
disable (ohci);
ohci->hc_control &= ~OHCI_CTRL_HCFS;
writel (ohci->hc_control, &ohci->regs->control);
......@@ -592,19 +592,20 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
struct ohci_regs *regs = ohci->regs;
int ints;
/* we can eliminate a (slow) readl() if _only_ WDH caused this irq */
/* we can eliminate a (slow) ohci_readl()
if _only_ WDH caused this irq */
if ((ohci->hcca->done_head != 0)
&& ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
ints = OHCI_INTR_WDH;
/* cardbus/... hardware gone before remove() */
} else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
} else if ((ints = ohci_readl (&regs->intrstatus)) == ~(u32)0) {
disable (ohci);
ohci_dbg (ohci, "device removed!\n");
return IRQ_HANDLED;
/* interrupt for some other device? */
} else if ((ints &= readl (&regs->intrenable)) == 0) {
} else if ((ints &= ohci_readl (&regs->intrenable)) == 0) {
return IRQ_NONE;
}
......@@ -650,7 +651,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
writel (ints, &regs->intrstatus);
writel (OHCI_INTR_MIE, &regs->intrenable);
// flush those pci writes
(void) readl (&ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
}
return IRQ_HANDLED;
......@@ -798,6 +799,14 @@ MODULE_LICENSE ("GPL");
#include "ohci-omap.c"
#endif
#if !(defined(CONFIG_PCI) || defined(CONFIG_SA1111) || defined(CONFIG_ARCH_OMAP))
#ifdef CONFIG_ARCH_LH7A404
#include "ohci-lh7a404.c"
#endif
#if !(defined(CONFIG_PCI) \
|| defined(CONFIG_SA1111) \
|| defined(CONFIG_ARCH_OMAP) \
|| defined (CONFIG_ARCH_LH7A404) \
)
#error "missing bus glue for ohci-hcd"
#endif
......@@ -20,20 +20,20 @@
* till some bits (mostly reserved) are clear; ok for all revs.
*/
#define read_roothub(hc, register, mask) ({ \
u32 temp = readl (&hc->regs->roothub.register); \
u32 temp = ohci_readl (&hc->regs->roothub.register); \
if (temp == -1) \
disable (hc); \
else if (hc->flags & OHCI_QUIRK_AMD756) \
while (temp & mask) \
temp = readl (&hc->regs->roothub.register); \
temp = ohci_readl (&hc->regs->roothub.register); \
temp; })
static u32 roothub_a (struct ohci_hcd *hc)
{ return read_roothub (hc, a, 0xfc0fe000); }
static inline u32 roothub_b (struct ohci_hcd *hc)
{ return readl (&hc->regs->roothub.b); }
{ return ohci_readl (&hc->regs->roothub.b); }
static inline u32 roothub_status (struct ohci_hcd *hc)
{ return readl (&hc->regs->roothub.status); }
{ return ohci_readl (&hc->regs->roothub.status); }
static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
{ return read_roothub (hc, portstatus [i], 0xffe0fce0); }
......@@ -83,14 +83,14 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
spin_lock_irq (&ohci->lock);
ohci->hc_control = readl (&ohci->regs->control);
ohci->hc_control = ohci_readl (&ohci->regs->control);
switch (ohci->hc_control & OHCI_CTRL_HCFS) {
case OHCI_USB_RESUME:
ohci_dbg (ohci, "resume/suspend?\n");
ohci->hc_control &= ~OHCI_CTRL_HCFS;
ohci->hc_control |= OHCI_USB_RESET;
writel (ohci->hc_control, &ohci->regs->control);
(void) readl (&ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
/* FALL THROUGH */
case OHCI_USB_RESET:
status = -EBUSY;
......@@ -109,7 +109,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
ohci->hc_control &= ~OHCI_SCHED_ENABLES;
writel (ohci->hc_control, &ohci->regs->control);
ohci->hc_control = readl (&ohci->regs->control);
ohci->hc_control = ohci_readl (&ohci->regs->control);
writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
/* sched disables take effect on the next frame,
......@@ -120,7 +120,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
while (limit > 0) {
udelay (250);
limit =- 250;
if (readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
if (ohci_readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
break;
}
dl_done_list (ohci, 0);
......@@ -128,7 +128,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
}
dl_done_list (ohci, 0);
finish_unlinks (ohci, OHCI_FRAME_NO(ohci->hcca), 0);
writel (readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus);
writel (ohci_readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus);
/* maybe resume can wake root hub */
if (ohci->hcd.remote_wakeup)
......@@ -140,7 +140,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
ohci->hc_control &= ~OHCI_CTRL_HCFS;
ohci->hc_control |= OHCI_USB_SUSPEND;
writel (ohci->hc_control, &ohci->regs->control);
(void) readl (&ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
/* no resumes until devices finish suspending */
ohci->next_statechange = jiffies + msecs_to_jiffies (5);
......@@ -179,13 +179,13 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
return -EAGAIN;
spin_lock_irq (&ohci->lock);
ohci->hc_control = readl (&ohci->regs->control);
ohci->hc_control = ohci_readl (&ohci->regs->control);
switch (ohci->hc_control & OHCI_CTRL_HCFS) {
case OHCI_USB_SUSPEND:
ohci->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES);
ohci->hc_control |= OHCI_USB_RESUME;
writel (ohci->hc_control, &ohci->regs->control);
(void) readl (&ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
ohci_dbg (ohci, "resume root hub\n");
break;
case OHCI_USB_RESUME:
......@@ -210,7 +210,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
temp = roothub_a (ohci) & RH_A_NDP;
enables = 0;
while (temp--) {
u32 stat = readl (&ohci->regs->roothub.portstatus [temp]);
u32 stat = ohci_readl (&ohci->regs->roothub.portstatus [temp]);
/* force global, not selective, resume */
if (!(stat & RH_PS_PSS))
......@@ -222,7 +222,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
ohci->hcd.state = USB_STATE_RESUMING;
mdelay (20 /* usb 11.5.1.10 */ + 15);
temp = readl (&ohci->regs->control);
temp = ohci_readl (&ohci->regs->control);
temp &= OHCI_CTRL_HCFS;
if (temp != OHCI_USB_RESUME) {
ohci_err (ohci, "controller won't resume\n");
......@@ -243,11 +243,11 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
writel (OHCI_INTR_INIT, &ohci->regs->intrenable);
if (ohci->ed_rm_list)
writel (OHCI_INTR_SF, &ohci->regs->intrenable);
writel (readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus);
writel (ohci_readl (&ohci->regs->intrstatus), &ohci->regs->intrstatus);
/* Then re-enable operations */
writel (OHCI_USB_OPER, &ohci->regs->control);
(void) readl (&ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
msleep (3);
temp = OHCI_CONTROL_INIT | OHCI_USB_OPER;
......@@ -255,7 +255,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
temp |= OHCI_CTRL_RWC;
ohci->hc_control = temp;
writel (temp, &ohci->regs->control);
(void) readl (&ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
/* TRSMRCY */
msleep (10);
......@@ -290,7 +290,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
writel (ohci->hc_control, &ohci->regs->control);
if (temp)
writel (status, &ohci->regs->cmdstatus);
(void) readl (&ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
}
ohci->hcd.state = USB_STATE_RUNNING;
......@@ -332,7 +332,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
if (!HCD_IS_RUNNING(ohci->hcd.state))
return -ESHUTDOWN;
ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n",
ports, readl (&ohci->regs->roothub.a) & RH_A_NDP);
ports, ohci_readl (&ohci->regs->roothub.a) & RH_A_NDP);
/* retry later; "should not happen" */
return 0;
}
......@@ -496,7 +496,7 @@ static int ohci_hub_control (
goto error;
}
writel (temp, &ohci->regs->roothub.portstatus [wIndex]);
// readl (&ohci->regs->roothub.portstatus [wIndex]);
// ohci_readl (&ohci->regs->roothub.portstatus [wIndex]);
break;
case GetHubDescriptor:
ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf);
......@@ -541,7 +541,7 @@ static int ohci_hub_control (
&ohci->regs->roothub.portstatus [wIndex]);
break;
case USB_PORT_FEAT_RESET:
temp = readl (&ohci->regs->roothub.portstatus [wIndex]);
temp = ohci_readl (&ohci->regs->roothub.portstatus [wIndex]);
if (temp & RH_PS_CCS)
writel (RH_PS_PRS,
&ohci->regs->roothub.portstatus [wIndex]);
......
/*
* OHCI HCD (Host Controller Driver) for USB.
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
* (C) Copyright 2002 Hewlett-Packard Company
*
* Bus Glue for Sharp LH7A404
*
* Written by Christopher Hoover <ch@hpl.hp.com>
* Based on fragments of previous driver by Rusell King et al.
*
* Modified for LH7A404 from ohci-sa1111.c
* by Durgesh Pattamatta <pattamattad@sharpsec.com>
*
* This file is licenced under the GPL.
*/
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/arch/hardware.h>
extern int usb_disabled(void);
/*-------------------------------------------------------------------------*/
static void lh7a404_start_hc(struct platform_device *dev)
{
printk(KERN_DEBUG __FILE__
": starting LH7A404 OHCI USB Controller\n");
/*
* Now, carefully enable the USB clock, and take
* the USB host controller out of reset.
*/
CSC_PWRCNT |= CSC_PWRCNT_USBH_EN; /* Enable clock */
udelay(1000);
USBH_CMDSTATUS = OHCI_HCR;
printk(KERN_DEBUG __FILE__
": Clock to USB host has been enabled \n");
}
static void lh7a404_stop_hc(struct platform_device *dev)
{
printk(KERN_DEBUG __FILE__
": stopping LH7A404 OHCI USB Controller\n");
CSC_PWRCNT &= ~CSC_PWRCNT_USBH_EN; /* Disable clock */
}
/*-------------------------------------------------------------------------*/
static irqreturn_t usb_hcd_lh7a404_hcim_irq (int irq, void *__hcd,
struct pt_regs * r)
{
struct usb_hcd *hcd = __hcd;
return usb_hcd_irq(irq, hcd, r);
}
/*-------------------------------------------------------------------------*/
void usb_hcd_lh7a404_remove (struct usb_hcd *, struct platform_device *);
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
/**
* usb_hcd_lh7a404_probe - initialize LH7A404-based HCDs
* Context: !in_interrupt()
*
* Allocates basic resources for this USB host controller, and
* then invokes the start() method for the HCD associated with it
* through the hotplug entry's driver_data.
*
*/
int usb_hcd_lh7a404_probe (const struct hc_driver *driver,
struct usb_hcd **hcd_out,
struct platform_device *dev)
{
int retval;
struct usb_hcd *hcd = 0;
unsigned int *addr = NULL;
if (!request_mem_region(dev->resource[0].start,
dev->resource[0].end
- dev->resource[0].start + 1, hcd_name)) {
pr_debug("request_mem_region failed");
return -EBUSY;
}
lh7a404_start_hc(dev);
addr = ioremap(dev->resource[0].start,
dev->resource[0].end
- dev->resource[0].start + 1);
if (!addr) {
pr_debug("ioremap failed");
retval = -ENOMEM;
goto err1;
}
hcd = driver->hcd_alloc ();
if (hcd == NULL){
pr_debug ("hcd_alloc failed");
retval = -ENOMEM;
goto err1;
}
if(dev->resource[1].flags != IORESOURCE_IRQ){
pr_debug ("resource[1] is not IORESOURCE_IRQ");
retval = -ENOMEM;
goto err1;
}
hcd->driver = (struct hc_driver *) driver;
hcd->description = driver->description;
hcd->irq = dev->resource[1].start;
hcd->regs = addr;
hcd->self.controller = &dev->dev;
retval = hcd_buffer_create (hcd);
if (retval != 0) {
pr_debug ("pool alloc fail");
goto err1;
}
retval = request_irq (hcd->irq, usb_hcd_lh7a404_hcim_irq, SA_INTERRUPT,
hcd->description, hcd);
if (retval != 0) {
pr_debug("request_irq failed");
retval = -EBUSY;
goto err2;
}
pr_debug ("%s (LH7A404) at 0x%p, irq %d",
hcd->description, hcd->regs, hcd->irq);
usb_bus_init (&hcd->self);
hcd->self.op = &usb_hcd_operations;
hcd->self.hcpriv = (void *) hcd;
hcd->self.bus_name = "lh7a404";
hcd->product_desc = "LH7A404 OHCI";
INIT_LIST_HEAD (&hcd->dev_list);
usb_register_bus (&hcd->self);
if ((retval = driver->start (hcd)) < 0)
{
usb_hcd_lh7a404_remove(hcd, dev);
return retval;
}
*hcd_out = hcd;
return 0;
err2:
hcd_buffer_destroy (hcd);
if (hcd)
driver->hcd_free(hcd);
err1:
lh7a404_stop_hc(dev);
release_mem_region(dev->resource[0].start,
dev->resource[0].end
- dev->resource[0].start + 1);
return retval;
}
/* may be called without controller electrically present */
/* may be called with controller, bus, and devices active */
/**
* usb_hcd_lh7a404_remove - shutdown processing for LH7A404-based HCDs
* @dev: USB Host Controller being removed
* Context: !in_interrupt()
*
* Reverses the effect of usb_hcd_lh7a404_probe(), first invoking
* the HCD's stop() method. It is always called from a thread
* context, normally "rmmod", "apmd", or something similar.
*
*/
void usb_hcd_lh7a404_remove (struct usb_hcd *hcd, struct platform_device *dev)
{
void *base;
pr_debug ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
if (in_interrupt ())
BUG ();
hcd->state = USB_STATE_QUIESCING;
pr_debug ("%s: roothub graceful disconnect", hcd->self.bus_name);
usb_disconnect (&hcd->self.root_hub);
hcd->driver->stop (hcd);
hcd->state = USB_STATE_HALT;
free_irq (hcd->irq, hcd);
hcd_buffer_destroy (hcd);
usb_deregister_bus (&hcd->self);
base = hcd->regs;
hcd->driver->hcd_free (hcd);
lh7a404_stop_hc(dev);
release_mem_region(dev->resource[0].start,
dev->resource[0].end
- dev->resource[0].start + 1);
}
/*-------------------------------------------------------------------------*/
static int __devinit
ohci_lh7a404_start (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
int ret;
ohci_dbg (ohci, "ohci_lh7a404_start, ohci:%p", ohci);
ohci->hcca = dma_alloc_coherent (hcd->self.controller,
sizeof *ohci->hcca, &ohci->hcca_dma, 0);
if (!ohci->hcca)
return -ENOMEM;
ohci_dbg (ohci, "ohci_lh7a404_start, ohci->hcca:%p",
ohci->hcca);
memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
if ((ret = ohci_mem_init (ohci)) < 0) {
ohci_stop (hcd);
return ret;
}
ohci->regs = hcd->regs;
if (hc_reset (ohci) < 0) {
ohci_stop (hcd);
return -ENODEV;
}
if (hc_start (ohci) < 0) {
err ("can't start %s", ohci->hcd.self.bus_name);
ohci_stop (hcd);
return -EBUSY;
}
create_debug_files (ohci);
#ifdef DEBUG
ohci_dump (ohci, 1);
#endif /*DEBUG*/
return 0;
}
/*-------------------------------------------------------------------------*/
static const struct hc_driver ohci_lh7a404_hc_driver = {
.description = hcd_name,
/*
* generic hardware linkage
*/
.irq = ohci_irq,
.flags = HCD_USB11,
/*
* basic lifecycle operations
*/
.start = ohci_lh7a404_start,
#ifdef CONFIG_PM
/* suspend: ohci_lh7a404_suspend, -- tbd */
/* resume: ohci_lh7a404_resume, -- tbd */
#endif /*CONFIG_PM*/
.stop = ohci_stop,
/*
* memory lifecycle (except per-request)
*/
.hcd_alloc = ohci_hcd_alloc,
.hcd_free = ohci_hcd_free,
/*
* managing i/o requests and associated device resources
*/
.urb_enqueue = ohci_urb_enqueue,
.urb_dequeue = ohci_urb_dequeue,
.endpoint_disable = ohci_endpoint_disable,
/*
* scheduling support
*/
.get_frame_number = ohci_get_frame,
/*
* root hub support
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
};
/*-------------------------------------------------------------------------*/
static int ohci_hcd_lh7a404_drv_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct usb_hcd *hcd = NULL;
int ret;
pr_debug ("In ohci_hcd_lh7a404_drv_probe");
if (usb_disabled())
return -ENODEV;
ret = usb_hcd_lh7a404_probe(&ohci_lh7a404_hc_driver, &hcd, pdev);
if (ret == 0)
dev_set_drvdata(dev, hcd);
return ret;
}
static int ohci_hcd_lh7a404_drv_remove(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct usb_hcd *hcd = dev_get_drvdata(dev);
usb_hcd_lh7a404_remove(hcd, pdev);
dev_set_drvdata(dev, NULL);
return 0;
}
/*TBD*/
/*static int ohci_hcd_lh7a404_drv_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct usb_hcd *hcd = dev_get_drvdata(dev);
return 0;
}
static int ohci_hcd_lh7a404_drv_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct usb_hcd *hcd = dev_get_drvdata(dev);
return 0;
}
*/
static struct device_driver ohci_hcd_lh7a404_driver = {
.name = "lh7a404-ohci",
.bus = &platform_bus_type,
.probe = ohci_hcd_lh7a404_drv_probe,
.remove = ohci_hcd_lh7a404_drv_remove,
/*.suspend = ohci_hcd_lh7a404_drv_suspend, */
/*.resume = ohci_hcd_lh7a404_drv_resume, */
};
static int __init ohci_hcd_lh7a404_init (void)
{
pr_debug (DRIVER_INFO " (LH7A404)");
pr_debug ("block sizes: ed %d td %d\n",
sizeof (struct ed), sizeof (struct td));
return driver_register(&ohci_hcd_lh7a404_driver);
}
static void __exit ohci_hcd_lh7a404_cleanup (void)
{
driver_unregister(&ohci_hcd_lh7a404_driver);
}
module_init (ohci_hcd_lh7a404_init);
module_exit (ohci_hcd_lh7a404_cleanup);
......@@ -454,7 +454,6 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
*/
void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev)
{
struct usb_device *hub;
void *base;
info ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
......@@ -462,11 +461,10 @@ void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev)
if (in_interrupt ())
BUG ();
hub = hcd->self.root_hub;
hcd->state = USB_STATE_QUIESCING;
dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);
usb_disconnect (&hub);
usb_disconnect (&hcd->self.root_hub);
hcd->driver->stop (hcd);
hcd_buffer_destroy (hcd);
......
......@@ -321,7 +321,7 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
if (!ed->hwNextED) {
ohci->hc_control &= ~OHCI_CTRL_CLE;
writel (ohci->hc_control, &ohci->regs->control);
// a readl() later syncs CLE with the HC
// a ohci_readl() later syncs CLE with the HC
} else
writel (le32_to_cpup (&ed->hwNextED),
&ohci->regs->ed_controlhead);
......@@ -345,7 +345,7 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
if (!ed->hwNextED) {
ohci->hc_control &= ~OHCI_CTRL_BLE;
writel (ohci->hc_control, &ohci->regs->control);
// a readl() later syncs BLE with the HC
// a ohci_readl() later syncs BLE with the HC
} else
writel (le32_to_cpup (&ed->hwNextED),
&ohci->regs->ed_bulkhead);
......@@ -481,7 +481,7 @@ static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed)
writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
writel (OHCI_INTR_SF, &ohci->regs->intrenable);
// flush those writes, and get latest HCCA contents
(void) readl (&ohci->regs->control);
(void) ohci_readl (&ohci->regs->control);
/* SF interrupt might get delayed; record the frame counter value that
* indicates when the HC isn't looking at it, so concurrent unlinks
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -108,7 +108,7 @@ config USB_OV511
config USB_PWC
tristate "USB Philips Cameras"
depends on USB && VIDEO_DEV
depends on USB && VIDEO_DEV && CONFIG_BROKEN
---help---
Say Y or M here if you want to use one of these Philips & OEM
webcams:
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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