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" ...@@ -7,7 +7,7 @@ menu "USB support"
# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
config USB config USB
tristate "Support for Host-side 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--- ---help---
Universal Serial Bus (USB) is a specification for a serial bus Universal Serial Bus (USB) is a specification for a serial bus
subsystem which offers higher speeds and more features than the 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 ...@@ -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; struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data;
int i, j, val; int i, j, val;
int __user *user_arg = (int __user *)arg;
if (!ms->state->usbdev) if (!ms->state->usbdev)
return -ENODEV; return -ENODEV;
...@@ -2034,7 +2035,7 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign ...@@ -2034,7 +2035,7 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign
return 0; return 0;
} }
if (cmd == OSS_GETVERSION) 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)) if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
return -EINVAL; return -EINVAL;
if (_IOC_DIR(cmd) == _IOC_READ) { if (_IOC_DIR(cmd) == _IOC_READ) {
...@@ -2043,27 +2044,27 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign ...@@ -2043,27 +2044,27 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign
val = get_rec_src(ms); val = get_rec_src(ms);
if (val < 0) if (val < 0)
return val; 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 */ case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */
for (val = i = 0; i < ms->numch; i++) for (val = i = 0; i < ms->numch; i++)
val |= 1 << ms->ch[i].osschannel; 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 */ case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
for (val = i = 0; i < ms->numch; i++) for (val = i = 0; i < ms->numch; i++)
if (ms->ch[i].slctunitid) if (ms->ch[i].slctunitid)
val |= 1 << ms->ch[i].osschannel; 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 */ case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
for (val = i = 0; i < ms->numch; i++) for (val = i = 0; i < ms->numch; i++)
if (ms->ch[i].flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) if (ms->ch[i].flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))
val |= 1 << ms->ch[i].osschannel; val |= 1 << ms->ch[i].osschannel;
return put_user(val, (int *)arg); return put_user(val, user_arg);
case SOUND_MIXER_CAPS: case SOUND_MIXER_CAPS:
return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg); return put_user(SOUND_CAP_EXCL_INPUT, user_arg);
default: default:
i = _IOC_NR(cmd); i = _IOC_NR(cmd);
...@@ -2071,7 +2072,7 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign ...@@ -2071,7 +2072,7 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign
return -EINVAL; return -EINVAL;
for (j = 0; j < ms->numch; j++) { for (j = 0; j < ms->numch; j++) {
if (ms->ch[j].osschannel == i) { 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; return -EINVAL;
...@@ -2082,7 +2083,7 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign ...@@ -2082,7 +2083,7 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign
ms->modcnt++; ms->modcnt++;
switch (_IOC_NR(cmd)) { switch (_IOC_NR(cmd)) {
case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ 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 -EFAULT;
return set_rec_src(ms, val); return set_rec_src(ms, val);
...@@ -2093,11 +2094,11 @@ static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsign ...@@ -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++); for (j = 0; j < ms->numch && ms->ch[j].osschannel != i; j++);
if (j >= ms->numch) if (j >= ms->numch)
return -EINVAL; return -EINVAL;
if (get_user(val, (int *)arg)) if (get_user(val, user_arg))
return -EFAULT; return -EFAULT;
if (wrmixer(ms, j, val)) if (wrmixer(ms, j, val))
return -EIO; 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 ...@@ -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_audiodev *as = (struct usb_audiodev *)file->private_data;
struct usb_audio_state *s = as->state; struct usb_audio_state *s = as->state;
int __user *user_arg = (int __user *)arg;
unsigned long flags; unsigned long flags;
audio_buf_info abinfo; audio_buf_info abinfo;
count_info cinfo; count_info cinfo;
...@@ -2387,7 +2389,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -2387,7 +2389,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
#endif #endif
switch (cmd) { switch (cmd) {
case OSS_GETVERSION: case OSS_GETVERSION:
return put_user(SOUND_VERSION, (int *)arg); return put_user(SOUND_VERSION, user_arg);
case SNDCTL_DSP_SYNC: case SNDCTL_DSP_SYNC:
if (file->f_mode & FMODE_WRITE) if (file->f_mode & FMODE_WRITE)
...@@ -2399,7 +2401,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -2399,7 +2401,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
case SNDCTL_DSP_GETCAPS: case SNDCTL_DSP_GETCAPS:
return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | 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: case SNDCTL_DSP_RESET:
if (file->f_mode & FMODE_WRITE) { if (file->f_mode & FMODE_WRITE) {
...@@ -2413,7 +2415,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -2413,7 +2415,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
return 0; return 0;
case SNDCTL_DSP_SPEED: case SNDCTL_DSP_SPEED:
if (get_user(val, (int *)arg)) if (get_user(val, user_arg))
return -EFAULT; return -EFAULT;
if (val >= 0) { if (val >= 0) {
if (val < 4000) if (val < 4000)
...@@ -2423,10 +2425,12 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -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)) if (set_format(as, file->f_mode, AFMT_QUERY, val))
return -EIO; 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: case SNDCTL_DSP_STEREO:
if (get_user(val, (int *)arg)) if (get_user(val, user_arg))
return -EFAULT; return -EFAULT;
val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
if (val) if (val)
...@@ -2438,7 +2442,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -2438,7 +2442,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
return 0; return 0;
case SNDCTL_DSP_CHANNELS: case SNDCTL_DSP_CHANNELS:
if (get_user(val, (int *)arg)) if (get_user(val, user_arg))
return -EFAULT; return -EFAULT;
if (val != 0) { if (val != 0) {
val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; 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 ...@@ -2450,14 +2454,14 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
return -EIO; return -EIO;
} }
val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; 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 */ case SNDCTL_DSP_GETFMTS: /* Returns a mask */
return put_user(AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE | 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*/ case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
if (get_user(val, (int *)arg)) if (get_user(val, user_arg))
return -EFAULT; return -EFAULT;
if (val != AFMT_QUERY) { if (val != AFMT_QUERY) {
if (hweight32(val) != 1) if (hweight32(val) != 1)
...@@ -2471,7 +2475,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -2471,7 +2475,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
return -EIO; return -EIO;
} }
val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; 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: case SNDCTL_DSP_POST:
return 0; return 0;
...@@ -2482,10 +2486,10 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -2482,10 +2486,10 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
val |= PCM_ENABLE_INPUT; val |= PCM_ENABLE_INPUT;
if (file->f_mode & FMODE_WRITE && as->usbout.flags & FLG_RUNNING) if (file->f_mode & FMODE_WRITE && as->usbout.flags & FLG_RUNNING)
val |= PCM_ENABLE_OUTPUT; val |= PCM_ENABLE_OUTPUT;
return put_user(val, (int *)arg); return put_user(val, user_arg);
case SNDCTL_DSP_SETTRIGGER: case SNDCTL_DSP_SETTRIGGER:
if (get_user(val, (int *)arg)) if (get_user(val, user_arg))
return -EFAULT; return -EFAULT;
if (file->f_mode & FMODE_READ) { if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) { if (val & PCM_ENABLE_INPUT) {
...@@ -2543,7 +2547,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -2543,7 +2547,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
spin_lock_irqsave(&as->lock, flags); spin_lock_irqsave(&as->lock, flags);
val = as->usbout.dma.count; val = as->usbout.dma.count;
spin_unlock_irqrestore(&as->lock, flags); spin_unlock_irqrestore(&as->lock, flags);
return put_user(val, (int *)arg); return put_user(val, user_arg);
case SNDCTL_DSP_GETIPTR: case SNDCTL_DSP_GETIPTR:
if (!(file->f_mode & FMODE_READ)) if (!(file->f_mode & FMODE_READ))
...@@ -2577,14 +2581,14 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -2577,14 +2581,14 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
if (file->f_mode & FMODE_WRITE) { if (file->f_mode & FMODE_WRITE) {
if ((val = prog_dmabuf_out(as))) if ((val = prog_dmabuf_out(as)))
return val; 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))) if ((val = prog_dmabuf_in(as)))
return val; return val;
return put_user(as->usbin.dma.fragsize, (int *)arg); return put_user(as->usbin.dma.fragsize, user_arg);
case SNDCTL_DSP_SETFRAGMENT: case SNDCTL_DSP_SETFRAGMENT:
if (get_user(val, (int *)arg)) if (get_user(val, user_arg))
return -EFAULT; return -EFAULT;
if (file->f_mode & FMODE_READ) { if (file->f_mode & FMODE_READ) {
as->usbin.dma.ossfragshift = val & 0xffff; as->usbin.dma.ossfragshift = val & 0xffff;
...@@ -2612,7 +2616,7 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -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) || if ((file->f_mode & FMODE_READ && as->usbin.dma.subdivision) ||
(file->f_mode & FMODE_WRITE && as->usbout.dma.subdivision)) (file->f_mode & FMODE_WRITE && as->usbout.dma.subdivision))
return -EINVAL; return -EINVAL;
if (get_user(val, (int *)arg)) if (get_user(val, user_arg))
return -EFAULT; return -EFAULT;
if (val != 1 && val != 2 && val != 4) if (val != 1 && val != 2 && val != 4)
return -EINVAL; return -EINVAL;
...@@ -2623,15 +2627,17 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int ...@@ -2623,15 +2627,17 @@ static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int
return 0; return 0;
case SOUND_PCM_READ_RATE: 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: case SOUND_PCM_READ_CHANNELS:
val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; 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: case SOUND_PCM_READ_BITS:
val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; 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 SOUND_PCM_WRITE_FILTER:
case SNDCTL_DSP_SETSYNCRO: 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 @@ ...@@ -75,6 +75,7 @@
#define IOCNR_HP_SET_CHANNEL 4 #define IOCNR_HP_SET_CHANNEL 4
#define IOCNR_GET_BUS_ADDRESS 5 #define IOCNR_GET_BUS_ADDRESS 5
#define IOCNR_GET_VID_PID 6 #define IOCNR_GET_VID_PID 6
#define IOCNR_SOFT_RESET 7
/* Get device_id string: */ /* Get device_id string: */
#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len) #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: */ /* The following ioctls were added for http://hpoj.sourceforge.net: */
...@@ -90,6 +91,8 @@ ...@@ -90,6 +91,8 @@
#define LPIOC_GET_BUS_ADDRESS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_BUS_ADDRESS, len) #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: */ /* 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) #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. * 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, ...@@ -587,6 +590,13 @@ static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
usblp->minor, twoints[0], twoints[1]); usblp->minor, twoints[0], twoints[1]);
break; break;
case IOCNR_SOFT_RESET:
if (_IOC_DIR(cmd) != _IOC_NONE) {
retval = -EINVAL;
goto done;
}
retval = usblp_reset(usblp);
break;
default: default:
retval = -ENOTTY; retval = -ENOTTY;
} }
...@@ -761,6 +771,7 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, ...@@ -761,6 +771,7 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
usblp->minor, usblp->readurb->status); usblp->minor, usblp->readurb->status);
usblp->readurb->dev = usblp->dev; usblp->readurb->dev = usblp->dev;
usblp->readcount = 0; usblp->readcount = 0;
usblp->rcomplete = 0;
if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0)
dbg("error submitting urb"); dbg("error submitting urb");
count = -EIO; count = -EIO;
......
...@@ -589,6 +589,8 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte ...@@ -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); bus = list_entry(buslist, struct usb_bus, bus_list);
/* recurse through all children of the root hub */ /* recurse through all children of the root hub */
if (!bus->root_hub)
continue;
down(&bus->root_hub->serialize); down(&bus->root_hub->serialize);
ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0); ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
up(&bus->root_hub->serialize); up(&bus->root_hub->serialize);
......
...@@ -558,7 +558,7 @@ static int proc_control(struct dev_state *ps, void __user *arg) ...@@ -558,7 +558,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
if (usbfs_snoop) { if (usbfs_snoop) {
dev_info(&dev->dev, "control read: data "); dev_info(&dev->dev, "control read: data ");
for (j = 0; j < ctrl.wLength; ++j) for (j = 0; j < ctrl.wLength; ++j)
printk ("%02x ", (unsigned char)((char *)ctrl.data)[j]); printk ("%02x ", (unsigned char)(tbuf)[j]);
printk("\n"); printk("\n");
} }
if (copy_to_user(ctrl.data, tbuf, ctrl.wLength)) { if (copy_to_user(ctrl.data, tbuf, ctrl.wLength)) {
...@@ -578,7 +578,7 @@ static int proc_control(struct dev_state *ps, void __user *arg) ...@@ -578,7 +578,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
if (usbfs_snoop) { if (usbfs_snoop) {
dev_info(&dev->dev, "control write: data: "); dev_info(&dev->dev, "control write: data: ");
for (j = 0; j < ctrl.wLength; ++j) for (j = 0; j < ctrl.wLength; ++j)
printk ("%02x ", (unsigned char)((char *)ctrl.data)[j]); printk ("%02x ", (unsigned char)(tbuf)[j]);
printk("\n"); printk("\n");
} }
i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType, i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
......
...@@ -229,7 +229,6 @@ EXPORT_SYMBOL (usb_hcd_pci_probe); ...@@ -229,7 +229,6 @@ EXPORT_SYMBOL (usb_hcd_pci_probe);
void usb_hcd_pci_remove (struct pci_dev *dev) void usb_hcd_pci_remove (struct pci_dev *dev)
{ {
struct usb_hcd *hcd; struct usb_hcd *hcd;
struct usb_device *hub;
hcd = pci_get_drvdata(dev); hcd = pci_get_drvdata(dev);
if (!hcd) if (!hcd)
...@@ -239,12 +238,11 @@ void usb_hcd_pci_remove (struct pci_dev *dev) ...@@ -239,12 +238,11 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
if (in_interrupt ()) if (in_interrupt ())
BUG (); BUG ();
hub = hcd->self.root_hub;
if (HCD_IS_RUNNING (hcd->state)) if (HCD_IS_RUNNING (hcd->state))
hcd->state = USB_STATE_QUIESCING; hcd->state = USB_STATE_QUIESCING;
dev_dbg (hcd->self.controller, "roothub graceful disconnect\n"); dev_dbg (hcd->self.controller, "roothub graceful disconnect\n");
usb_disconnect (&hub); usb_disconnect (&hcd->self.root_hub);
hcd->driver->stop (hcd); hcd->driver->stop (hcd);
hcd_buffer_destroy (hcd); hcd_buffer_destroy (hcd);
......
...@@ -764,8 +764,9 @@ EXPORT_SYMBOL (usb_deregister_bus); ...@@ -764,8 +764,9 @@ EXPORT_SYMBOL (usb_deregister_bus);
* *
* The USB host controller calls this function to register the root hub * The USB host controller calls this function to register the root hub
* properly with the USB subsystem. It sets up the device properly in * 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 * the device tree and stores the root_hub pointer in the bus structure,
* usb device. It also assigns the root hub's USB address (always 1). * 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) 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 ...@@ -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, memset (&usb_dev->bus->devmap.devicemap, 0,
sizeof usb_dev->bus->devmap.devicemap); sizeof usb_dev->bus->devmap.devicemap);
set_bit (devnum, 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; usb_dev->epmaxpacketin[0] = usb_dev->epmaxpacketout[0] = 64;
retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); 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 ...@@ -787,14 +791,15 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev
return (retval < 0) ? retval : -EMSGSIZE; return (retval < 0) ? retval : -EMSGSIZE;
} }
(void) usb_get_dev (usb_dev);
down (&usb_dev->serialize); down (&usb_dev->serialize);
retval = usb_new_device (usb_dev); 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", dev_err (parent_dev, "can't register root hub for %s, %d\n",
usb_dev->dev.bus_id, retval); usb_dev->dev.bus_id, retval);
up (&usb_dev->serialize); }
usb_put_dev (usb_dev); up (&usb_bus_list_lock);
return retval; return retval;
} }
EXPORT_SYMBOL (usb_register_root_hub); EXPORT_SYMBOL (usb_register_root_hub);
...@@ -1574,11 +1579,13 @@ static void hcd_panic (void *_hcd) ...@@ -1574,11 +1579,13 @@ static void hcd_panic (void *_hcd)
unsigned i; unsigned i;
/* hc's root hub is removed later removed in hcd->stop() */ /* 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++) { for (i = 0; i < hub->maxchild; i++) {
if (hub->children [i]) if (hub->children [i])
usb_disconnect (&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, ...@@ -244,17 +244,10 @@ extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
struct usb_bus *, unsigned port); struct usb_bus *, unsigned port);
extern int usb_new_device(struct usb_device *dev); extern int usb_new_device(struct usb_device *dev);
extern void usb_disconnect(struct usb_device **); 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 int usb_get_configuration(struct usb_device *dev);
extern void usb_destroy_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 *); ...@@ -346,7 +339,8 @@ extern void usb_deregister_bus (struct usb_bus *);
extern int usb_register_root_hub (struct usb_device *usb_dev, extern int usb_register_root_hub (struct usb_device *usb_dev,
struct device *parent_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 /* hcd->driver->start() reported can_wakeup, probably with
* assistance from board's boot firmware. * assistance from board's boot firmware.
...@@ -356,8 +350,7 @@ static inline int hcd_register_root (struct usb_hcd *hcd) ...@@ -356,8 +350,7 @@ static inline int hcd_register_root (struct usb_hcd *hcd)
dev_dbg (hcd->self.controller, "supports USB remote wakeup\n"); dev_dbg (hcd->self.controller, "supports USB remote wakeup\n");
hcd->remote_wakeup = hcd->can_wakeup; hcd->remote_wakeup = hcd->can_wakeup;
return usb_register_root_hub ( return usb_register_root_hub (usb_dev, hcd->self.controller);
hcd_to_bus (hcd)->root_hub, hcd->self.controller);
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
......
This diff is collapsed.
...@@ -202,11 +202,13 @@ struct usb_hub { ...@@ -202,11 +202,13 @@ struct usb_hub {
int error; /* last reported error */ int error; /* last reported error */
int nerrors; /* track consecutive errors */ int nerrors; /* track consecutive errors */
struct list_head hub_list; /* all hubs */
struct list_head event_list; /* hubs w/data or errs ready */ 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 usb_hub_descriptor *descriptor; /* class descriptor */
struct semaphore khubd_sem;
struct usb_tt tt; /* Transaction Translator */ struct usb_tt tt; /* Transaction Translator */
u8 power_budget; /* in 2mA units; or zero */ u8 power_budget; /* in 2mA units; or zero */
...@@ -216,4 +218,15 @@ struct usb_hub { ...@@ -216,4 +218,15 @@ struct usb_hub {
struct work_struct leds; 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 */ #endif /* __LINUX_HUB_H */
...@@ -566,22 +566,19 @@ void usb_sg_cancel (struct usb_sg_request *io) ...@@ -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 usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
{ {
int i = 5; int i;
int result; int result;
memset(buf,0,size); // Make sure we parse really received data 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 */ /* retry on length 0 or stall; some devices are flakey */
if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
(type << 8) + index, 0, buf, size, (type << 8) + index, 0, buf, size,
HZ * USB_CTRL_GET_TIMEOUT)) > 0 HZ * USB_CTRL_GET_TIMEOUT);
|| result != -EPIPE) if (!(result == 0 || result == -EPIPE))
break; break;
dev_dbg (&dev->dev, "RETRY descriptor, result %d\n", result);
result = -ENOMSG;
} }
return result; return result;
} }
...@@ -830,6 +827,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) ...@@ -830,6 +827,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
interface = dev->actconfig->interface[i]; interface = dev->actconfig->interface[i];
dev_dbg (&dev->dev, "unregistering interface %s\n", dev_dbg (&dev->dev, "unregistering interface %s\n",
interface->dev.bus_id); interface->dev.bus_id);
usb_remove_sysfs_intf_files(interface);
device_del (&interface->dev); device_del (&interface->dev);
} }
...@@ -842,7 +840,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) ...@@ -842,7 +840,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
} }
dev->actconfig = 0; dev->actconfig = 0;
if (dev->state == USB_STATE_CONFIGURED) 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) ...@@ -1047,7 +1045,7 @@ int usb_reset_configuration(struct usb_device *dev)
config->desc.bConfigurationValue, 0, config->desc.bConfigurationValue, 0,
NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
if (retval < 0) { if (retval < 0) {
dev->state = USB_STATE_ADDRESS; usb_set_device_state(dev, USB_STATE_ADDRESS);
return retval; return retval;
} }
...@@ -1185,9 +1183,9 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1185,9 +1183,9 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
dev->actconfig = cp; dev->actconfig = cp;
if (!cp) if (!cp)
dev->state = USB_STATE_ADDRESS; usb_set_device_state(dev, USB_STATE_ADDRESS);
else { else {
dev->state = USB_STATE_CONFIGURED; usb_set_device_state(dev, USB_STATE_CONFIGURED);
/* Initialize the new interface structures and the /* Initialize the new interface structures and the
* hc/hcd/usbcore interface/endpoint state. * hc/hcd/usbcore interface/endpoint state.
...@@ -1322,7 +1320,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) ...@@ -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); 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); dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, 2);
err = usb_get_string(dev, dev->string_langid, index, tbuf, 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) ...@@ -1331,7 +1329,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
len=tbuf[0]; len=tbuf[0];
err = usb_get_string(dev, dev->string_langid, index, tbuf, len); 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); dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, len);
err = usb_get_string(dev, dev->string_langid, index, tbuf, len); err = usb_get_string(dev, dev->string_langid, index, tbuf, len);
} }
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
* drivers/usb/core/sysfs.c * drivers/usb/core/sysfs.c
* *
* (C) Copyright 2002 David Brownell * (C) Copyright 2002 David Brownell
* (C) Copyright 2002 Greg Kroah-Hartman * (C) Copyright 2002,2004 Greg Kroah-Hartman
* (C) Copyright 2002 IBM Corp. * (C) Copyright 2002,2004 IBM Corp.
* *
* All of the sysfs file attributes for usb devices and interfaces. * All of the sysfs file attributes for usb devices and interfaces.
* *
...@@ -162,29 +162,35 @@ usb_descriptor_attr (bDeviceSubClass, "%02x\n") ...@@ -162,29 +162,35 @@ usb_descriptor_attr (bDeviceSubClass, "%02x\n")
usb_descriptor_attr (bDeviceProtocol, "%02x\n") usb_descriptor_attr (bDeviceProtocol, "%02x\n")
usb_descriptor_attr (bNumConfigurations, "%d\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) void usb_create_sysfs_dev_files (struct usb_device *udev)
{ {
struct device *dev = &udev->dev; struct device *dev = &udev->dev;
/* current configuration's attributes */ sysfs_create_group(&dev->kobj, &dev_attr_grp);
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
if (udev->descriptor.iManufacturer) if (udev->descriptor.iManufacturer)
device_create_file (dev, &dev_attr_manufacturer); device_create_file (dev, &dev_attr_manufacturer);
...@@ -192,10 +198,20 @@ void usb_create_sysfs_dev_files (struct usb_device *udev) ...@@ -192,10 +198,20 @@ void usb_create_sysfs_dev_files (struct usb_device *udev)
device_create_file (dev, &dev_attr_product); device_create_file (dev, &dev_attr_product);
if (udev->descriptor.iSerialNumber) if (udev->descriptor.iSerialNumber)
device_create_file (dev, &dev_attr_serial); 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); sysfs_remove_group(&dev->kobj, &dev_attr_grp);
device_create_file (dev, &dev_attr_version);
device_create_file (dev, &dev_attr_maxchild); 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 */ /* Interface fields */
...@@ -217,13 +233,26 @@ usb_intf_attr (bInterfaceSubClass, "%02x\n") ...@@ -217,13 +233,26 @@ usb_intf_attr (bInterfaceSubClass, "%02x\n")
usb_intf_attr (bInterfaceProtocol, "%02x\n") usb_intf_attr (bInterfaceProtocol, "%02x\n")
usb_intf_attr (iInterface, "%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) void usb_create_sysfs_intf_files (struct usb_interface *intf)
{ {
device_create_file (&intf->dev, &dev_attr_bInterfaceNumber); sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
device_create_file (&intf->dev, &dev_attr_bAlternateSetting); }
device_create_file (&intf->dev, &dev_attr_bNumEndpoints);
device_create_file (&intf->dev, &dev_attr_bInterfaceClass); void usb_remove_sysfs_intf_files (struct usb_interface *intf)
device_create_file (&intf->dev, &dev_attr_bInterfaceSubClass); {
device_create_file (&intf->dev, &dev_attr_bInterfaceProtocol); sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
device_create_file (&intf->dev, &dev_attr_iInterface);
} }
...@@ -883,6 +883,8 @@ struct usb_device *usb_find_device(u16 vendor_id, u16 product_id) ...@@ -883,6 +883,8 @@ struct usb_device *usb_find_device(u16 vendor_id, u16 product_id)
buslist != &usb_bus_list; buslist != &usb_bus_list;
buslist = buslist->next) { buslist = buslist->next) {
bus = container_of(buslist, struct usb_bus, bus_list); bus = container_of(buslist, struct usb_bus, bus_list);
if (!bus->root_hub)
continue;
dev = match_device(bus->root_hub, vendor_id, product_id); dev = match_device(bus->root_hub, vendor_id, product_id);
if (dev) if (dev)
goto exit; goto exit;
...@@ -944,235 +946,6 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size, ...@@ -944,235 +946,6 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
return -1; 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 * usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP
* @dev: device the buffer will be used with * @dev: device the buffer will be used with
......
/* Functions local to drivers/usb/core/ */ /* Functions local to drivers/usb/core/ */
extern void usb_create_sysfs_dev_files (struct usb_device *dev); 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_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_probe_interface (struct device *dev);
extern int usb_unbind_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, ...@@ -19,5 +21,8 @@ extern int usb_get_device_descriptor(struct usb_device *dev,
unsigned int size); unsigned int size);
extern int usb_set_configuration(struct usb_device *dev, int configuration); 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 */ /* for labeling diagnostics */
extern const char *usbcore_name; extern const char *usbcore_name;
...@@ -825,7 +825,6 @@ static int dummy_urb_enqueue ( ...@@ -825,7 +825,6 @@ static int dummy_urb_enqueue (
dum = container_of (hcd, struct dummy, hcd); dum = container_of (hcd, struct dummy, hcd);
spin_lock_irqsave (&dum->lock, flags); spin_lock_irqsave (&dum->lock, flags);
if (!dum->hdev)
dum->hdev = urb->dev->hcpriv; dum->hdev = urb->dev->hcpriv;
urb->hcpriv = dum; urb->hcpriv = dum;
if (usb_pipetype (urb->pipe) == PIPE_CONTROL) if (usb_pipetype (urb->pipe) == PIPE_CONTROL)
...@@ -994,10 +993,17 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep) ...@@ -994,10 +993,17 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep)
return limit; 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) static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
{ {
int i; int i;
if (!is_active (dum))
return NULL;
if ((address & ~USB_DIR_IN) == 0) if ((address & ~USB_DIR_IN) == 0)
return &dum->ep [0]; return &dum->ep [0];
for (i = 1; i < DUMMY_ENDPOINTS; i++) { for (i = 1; i < DUMMY_ENDPOINTS; i++) {
...@@ -1011,6 +1017,8 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address) ...@@ -1011,6 +1017,8 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
return NULL; return NULL;
} }
#undef is_active
#define Dev_Request (USB_TYPE_STANDARD | USB_RECIP_DEVICE) #define Dev_Request (USB_TYPE_STANDARD | USB_RECIP_DEVICE)
#define Dev_InRequest (Dev_Request | USB_DIR_IN) #define Dev_InRequest (Dev_Request | USB_DIR_IN)
#define Intf_Request (USB_TYPE_STANDARD | USB_RECIP_INTERFACE) #define Intf_Request (USB_TYPE_STANDARD | USB_RECIP_INTERFACE)
...@@ -1152,11 +1160,6 @@ static void dummy_timer (unsigned long _dum) ...@@ -1152,11 +1160,6 @@ static void dummy_timer (unsigned long _dum)
case USB_REQ_SET_ADDRESS: case USB_REQ_SET_ADDRESS:
if (setup.bRequestType != Dev_Request) if (setup.bRequestType != Dev_Request)
break; break;
if (dum->address != 0) {
maybe_set_status (urb, -ETIMEDOUT);
urb->actual_length = 0;
goto return_urb;
}
dum->address = setup.wValue; dum->address = setup.wValue;
maybe_set_status (urb, 0); maybe_set_status (urb, 0);
dev_dbg (hardware, "set_address = %d\n", dev_dbg (hardware, "set_address = %d\n",
...@@ -1404,9 +1407,8 @@ static int dummy_hub_control ( ...@@ -1404,9 +1407,8 @@ static int dummy_hub_control (
break; break;
case USB_PORT_FEAT_POWER: case USB_PORT_FEAT_POWER:
dum->port_status = 0; dum->port_status = 0;
dum->address = 0;
dum->hdev = 0;
dum->resuming = 0; dum->resuming = 0;
stop_activity(dum, dum->driver);
break; break;
default: default:
dum->port_status &= ~(1 << wValue); dum->port_status &= ~(1 << wValue);
...@@ -1657,7 +1659,7 @@ static int dummy_start (struct usb_hcd *hcd) ...@@ -1657,7 +1659,7 @@ static int dummy_start (struct usb_hcd *hcd)
INIT_LIST_HEAD (&hcd->dev_list); INIT_LIST_HEAD (&hcd->dev_list);
usb_register_bus (bus); usb_register_bus (bus);
bus->root_hub = root = usb_alloc_dev (0, bus, 0); root = usb_alloc_dev (0, bus, 0);
if (!root) { if (!root) {
retval = -ENOMEM; retval = -ENOMEM;
clean1: clean1:
...@@ -1671,14 +1673,16 @@ static int dummy_start (struct usb_hcd *hcd) ...@@ -1671,14 +1673,16 @@ static int dummy_start (struct usb_hcd *hcd)
root->speed = USB_SPEED_HIGH; root->speed = USB_SPEED_HIGH;
/* ...then configured, so khubd sees us. */ /* ...then configured, so khubd sees us. */
if ((retval = hcd_register_root (&dum->hcd)) != 0) { if ((retval = hcd_register_root (root, &dum->hcd)) != 0) {
bus->root_hub = 0;
usb_put_dev (root); usb_put_dev (root);
clean2: clean2:
dum->hcd.state = USB_STATE_QUIESCING; dum->hcd.state = USB_STATE_QUIESCING;
goto clean1; goto clean1;
} }
/* only show a low-power port: just 8mA */
hub_set_power_budget (root, 8);
dum->started = 1; dum->started = 1;
if ((retval = dummy_register_udc (dum)) != 0) { if ((retval = dummy_register_udc (dum)) != 0) {
......
...@@ -118,6 +118,7 @@ struct eth_dev { ...@@ -118,6 +118,7 @@ struct eth_dev {
unsigned zlp:1; unsigned zlp:1;
unsigned cdc:1; unsigned cdc:1;
unsigned rndis:1; unsigned rndis:1;
unsigned suspended:1;
u16 cdc_filter; u16 cdc_filter;
unsigned long todo; unsigned long todo;
#define WORK_RX_MEMORY 0 #define WORK_RX_MEMORY 0
...@@ -1345,24 +1346,23 @@ static void eth_setup_complete (struct usb_ep *ep, struct usb_request *req) ...@@ -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) 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) if (req->status || req->actual != req->length)
DEBUG (dev, "rndis response complete --> %d, %d/%d\n", DEBUG (dev, "rndis response complete --> %d, %d/%d\n",
req->status, req->actual, req->length); req->status, req->actual, req->length);
/* done sending after CDC_GET_ENCAPSULATED_RESPONSE */ /* 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) static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
{ {
struct eth_dev *dev = ep->driver_data; struct eth_dev *dev = ep->driver_data;
int status;
/* received RNDIS command from CDC_SEND_ENCAPSULATED_COMMAND */ /* received RNDIS command from CDC_SEND_ENCAPSULATED_COMMAND */
spin_lock(&dev->lock); spin_lock(&dev->lock);
if (rndis_msg_parser (dev->rndis_config, (u8 *) req->buf)) status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
ERROR(dev, "%s: rndis parse error\n", __FUNCTION__ ); if (status < 0)
ERROR(dev, "%s: rndis parse error %d\n", __FUNCTION__, status);
spin_unlock(&dev->lock); spin_unlock(&dev->lock);
} }
...@@ -1580,6 +1580,7 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1580,6 +1580,7 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (buf) { if (buf) {
memcpy (req->buf, buf, value); memcpy (req->buf, buf, value);
req->complete = rndis_response_complete; req->complete = rndis_response_complete;
rndis_free_response(dev->rndis_config, buf);
} }
/* else stalls ... spec says to avoid that */ /* else stalls ... spec says to avoid that */
} }
...@@ -2064,6 +2065,16 @@ static void rndis_send_media_state (struct eth_dev *dev, int connect) ...@@ -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) static int rndis_control_ack (struct net_device *net)
{ {
struct eth_dev *dev = (struct eth_dev *) net->priv; struct eth_dev *dev = (struct eth_dev *) net->priv;
...@@ -2095,7 +2106,7 @@ static int rndis_control_ack (struct net_device *net) ...@@ -2095,7 +2106,7 @@ static int rndis_control_ack (struct net_device *net)
* CDC_NOTIFY_RESPONSE_AVAILABLE should work too * CDC_NOTIFY_RESPONSE_AVAILABLE should work too
*/ */
resp->length = 8; 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) = __constant_cpu_to_le32 (1);
*((u32 *) resp->buf + 1) = __constant_cpu_to_le32 (0); *((u32 *) resp->buf + 1) = __constant_cpu_to_le32 (0);
...@@ -2103,7 +2114,7 @@ static int rndis_control_ack (struct net_device *net) ...@@ -2103,7 +2114,7 @@ static int rndis_control_ack (struct net_device *net)
length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC); length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC);
if (length < 0) { if (length < 0) {
resp->status = 0; resp->status = 0;
rndis_response_complete (dev->status_ep, resp); rndis_control_ack_complete (dev->status_ep, resp);
} }
return 0; return 0;
...@@ -2302,17 +2313,6 @@ eth_bind (struct usb_gadget *gadget) ...@@ -2302,17 +2313,6 @@ eth_bind (struct usb_gadget *gadget)
UTS_SYSNAME " " UTS_RELEASE "/%s", UTS_SYSNAME " " UTS_RELEASE "/%s",
gadget->name); 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 /* 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" * be using ... so use these product IDs here and in the "linux.inf"
* needed to install MSFT drivers. Current Linux kernels will use * needed to install MSFT drivers. Current Linux kernels will use
...@@ -2326,6 +2326,16 @@ eth_bind (struct usb_gadget *gadget) ...@@ -2326,6 +2326,16 @@ eth_bind (struct usb_gadget *gadget)
__constant_cpu_to_le16(RNDIS_PRODUCT_NUM); __constant_cpu_to_le16(RNDIS_PRODUCT_NUM);
snprintf (product_desc, sizeof product_desc, snprintf (product_desc, sizeof product_desc,
"RNDIS/%s", driver_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 */ /* support optional vendor/distro customization */
...@@ -2554,6 +2564,26 @@ eth_bind (struct usb_gadget *gadget) ...@@ -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 = { static struct usb_gadget_driver eth_driver = {
#ifdef CONFIG_USB_GADGET_DUALSPEED #ifdef CONFIG_USB_GADGET_DUALSPEED
.speed = USB_SPEED_HIGH, .speed = USB_SPEED_HIGH,
...@@ -2567,6 +2597,9 @@ static struct usb_gadget_driver eth_driver = { ...@@ -2567,6 +2597,9 @@ static struct usb_gadget_driver eth_driver = {
.setup = eth_setup, .setup = eth_setup,
.disconnect = eth_disconnect, .disconnect = eth_disconnect,
.suspend = eth_suspend,
.resume = eth_resume,
.driver = { .driver = {
.name = (char *) shortname, .name = (char *) shortname,
// .shutdown = ... // .shutdown = ...
......
...@@ -2501,7 +2501,7 @@ static int send_status(struct fsg_dev *fsg) ...@@ -2501,7 +2501,7 @@ static int send_status(struct fsg_dev *fsg)
/* Store and send the Bulk-only CSW */ /* Store and send the Bulk-only CSW */
csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG); csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG);
csw->Tag = fsg->tag; csw->Tag = fsg->tag;
csw->Residue = fsg->residue; csw->Residue = cpu_to_le32(fsg->residue);
csw->Status = status; csw->Status = status;
bh->inreq->length = USB_BULK_CS_WRAP_LEN; bh->inreq->length = USB_BULK_CS_WRAP_LEN;
...@@ -2947,7 +2947,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) ...@@ -2947,7 +2947,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
fsg->data_dir = DATA_DIR_TO_HOST; fsg->data_dir = DATA_DIR_TO_HOST;
else else
fsg->data_dir = DATA_DIR_FROM_HOST; 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) if (fsg->data_size == 0)
fsg->data_dir = DATA_DIR_NONE; fsg->data_dir = DATA_DIR_NONE;
fsg->lun = cbw->Lun; fsg->lun = cbw->Lun;
...@@ -3834,6 +3834,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) ...@@ -3834,6 +3834,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
} }
/* Find all the endpoints we will use */ /* Find all the endpoints we will use */
usb_ep_autoconfig_reset(gadget);
ep = usb_ep_autoconfig(gadget, &fs_bulk_in_desc); ep = usb_ep_autoconfig(gadget, &fs_bulk_in_desc);
if (!ep) if (!ep)
goto autoconf_fail; goto autoconf_fail;
......
...@@ -26,11 +26,41 @@ ...@@ -26,11 +26,41 @@
#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A #define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A
#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B #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 */ /* NDIS_PNP_CAPABILITIES.Flags constants */
#define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001 #define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001
#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002 #define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002
#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 #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) */ /* Required Object IDs (OIDs) */
#define OID_GEN_SUPPORTED_LIST 0x00010101 #define OID_GEN_SUPPORTED_LIST 0x00010101
#define OID_GEN_HARDWARE_STATUS 0x00010102 #define OID_GEN_HARDWARE_STATUS 0x00010102
......
...@@ -1902,6 +1902,8 @@ static void ep0_start (struct net2280 *dev) ...@@ -1902,6 +1902,8 @@ static void ep0_start (struct net2280 *dev)
, &dev->usb->stdrsp); , &dev->usb->stdrsp);
writel ( (1 << USB_ROOT_PORT_WAKEUP_ENABLE) writel ( (1 << USB_ROOT_PORT_WAKEUP_ENABLE)
| (1 << SELF_POWERED_USB_DEVICE) | (1 << SELF_POWERED_USB_DEVICE)
/* erratum 0102 workaround */
| ((dev->chiprev == 0100) ? 0 : 1) << SUSPEND_IMMEDIATELY
| (1 << REMOTE_WAKEUP_SUPPORT) | (1 << REMOTE_WAKEUP_SUPPORT)
| (1 << USB_DETECT_ENABLE) | (1 << USB_DETECT_ENABLE)
| (1 << SELF_POWERED_STATUS) | (1 << SELF_POWERED_STATUS)
...@@ -1917,6 +1919,7 @@ static void ep0_start (struct net2280 *dev) ...@@ -1917,6 +1919,7 @@ static void ep0_start (struct net2280 *dev)
| (1 << PCI_RETRY_ABORT_INTERRUPT_ENABLE) | (1 << PCI_RETRY_ABORT_INTERRUPT_ENABLE)
| (1 << VBUS_INTERRUPT_ENABLE) | (1 << VBUS_INTERRUPT_ENABLE)
| (1 << ROOT_PORT_RESET_INTERRUPT_ENABLE) | (1 << ROOT_PORT_RESET_INTERRUPT_ENABLE)
| (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE)
, &dev->regs->pciirqenb1); , &dev->regs->pciirqenb1);
/* don't leave any writes posted */ /* don't leave any writes posted */
...@@ -2513,19 +2516,24 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat) ...@@ -2513,19 +2516,24 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
return; return;
} }
/* NOTE: we don't actually suspend the hardware; that starts to /* NOTE: chip stays in PCI D0 state for now, but it could
* interact with PCI power management, and needs something like a * enter D1 to save more power
* controller->suspend() call to clear SUSPEND_REQUEST_INTERRUPT.
* we shouldn't see resume interrupts.
* for rev 0100, this also avoids erratum 0102.
*/ */
tmp = (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT); tmp = (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT);
if (stat & tmp) { if (stat & tmp) {
writel (tmp, &dev->regs->irqstat1);
if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
if (dev->driver->suspend) if (dev->driver->suspend)
dev->driver->suspend (&dev->gadget); 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 &= ~tmp;
} }
stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
/* clear any other status/irqs */ /* clear any other status/irqs */
if (stat) if (stat)
...@@ -2533,6 +2541,7 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat) ...@@ -2533,6 +2541,7 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
/* some status we can just ignore */ /* some status we can just ignore */
stat &= ~((1 << CONTROL_STATUS_INTERRUPT) stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
| (1 << SUSPEND_REQUEST_INTERRUPT)
| (1 << RESUME_INTERRUPT) | (1 << RESUME_INTERRUPT)
| (1 << SOF_INTERRUPT)); | (1 << SOF_INTERRUPT));
if (!stat) if (!stat)
......
This diff is collapsed.
...@@ -59,10 +59,18 @@ ...@@ -59,10 +59,18 @@
#define RNDIS_MEDIUM_802_3 0x00000000U #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 */ /* supported OIDs */
static const u32 oid_supported_list [] = static const u32 oid_supported_list [] =
{ {
/* mandatory general */
/* the general stuff */ /* the general stuff */
OID_GEN_SUPPORTED_LIST, OID_GEN_SUPPORTED_LIST,
OID_GEN_HARDWARE_STATUS, OID_GEN_HARDWARE_STATUS,
...@@ -70,7 +78,6 @@ static const u32 oid_supported_list [] = ...@@ -70,7 +78,6 @@ static const u32 oid_supported_list [] =
OID_GEN_MEDIA_IN_USE, OID_GEN_MEDIA_IN_USE,
OID_GEN_MAXIMUM_FRAME_SIZE, OID_GEN_MAXIMUM_FRAME_SIZE,
OID_GEN_LINK_SPEED, OID_GEN_LINK_SPEED,
OID_GEN_TRANSMIT_BUFFER_SPACE,
OID_GEN_TRANSMIT_BLOCK_SIZE, OID_GEN_TRANSMIT_BLOCK_SIZE,
OID_GEN_RECEIVE_BLOCK_SIZE, OID_GEN_RECEIVE_BLOCK_SIZE,
OID_GEN_VENDOR_ID, OID_GEN_VENDOR_ID,
...@@ -78,10 +85,11 @@ static const u32 oid_supported_list [] = ...@@ -78,10 +85,11 @@ static const u32 oid_supported_list [] =
OID_GEN_VENDOR_DRIVER_VERSION, OID_GEN_VENDOR_DRIVER_VERSION,
OID_GEN_CURRENT_PACKET_FILTER, OID_GEN_CURRENT_PACKET_FILTER,
OID_GEN_MAXIMUM_TOTAL_SIZE, OID_GEN_MAXIMUM_TOTAL_SIZE,
OID_GEN_MAC_OPTIONS,
OID_GEN_MEDIA_CONNECT_STATUS, OID_GEN_MEDIA_CONNECT_STATUS,
OID_GEN_PHYSICAL_MEDIUM, OID_GEN_PHYSICAL_MEDIUM,
#if 0
OID_GEN_RNDIS_CONFIG_PARAMETER, OID_GEN_RNDIS_CONFIG_PARAMETER,
#endif
/* the statistical stuff */ /* the statistical stuff */
OID_GEN_XMIT_OK, OID_GEN_XMIT_OK,
...@@ -89,6 +97,7 @@ static const u32 oid_supported_list [] = ...@@ -89,6 +97,7 @@ static const u32 oid_supported_list [] =
OID_GEN_XMIT_ERROR, OID_GEN_XMIT_ERROR,
OID_GEN_RCV_ERROR, OID_GEN_RCV_ERROR,
OID_GEN_RCV_NO_BUFFER, OID_GEN_RCV_NO_BUFFER,
#ifdef RNDIS_OPTIONAL_STATS
OID_GEN_DIRECTED_BYTES_XMIT, OID_GEN_DIRECTED_BYTES_XMIT,
OID_GEN_DIRECTED_FRAMES_XMIT, OID_GEN_DIRECTED_FRAMES_XMIT,
OID_GEN_MULTICAST_BYTES_XMIT, OID_GEN_MULTICAST_BYTES_XMIT,
...@@ -103,6 +112,7 @@ static const u32 oid_supported_list [] = ...@@ -103,6 +112,7 @@ static const u32 oid_supported_list [] =
OID_GEN_BROADCAST_FRAMES_RCV, OID_GEN_BROADCAST_FRAMES_RCV,
OID_GEN_RCV_CRC_ERROR, OID_GEN_RCV_CRC_ERROR,
OID_GEN_TRANSMIT_QUEUE_LENGTH, OID_GEN_TRANSMIT_QUEUE_LENGTH,
#endif /* RNDIS_OPTIONAL_STATS */
/* mandatory 802.3 */ /* mandatory 802.3 */
/* the general stuff */ /* the general stuff */
...@@ -115,7 +125,30 @@ static const u32 oid_supported_list [] = ...@@ -115,7 +125,30 @@ static const u32 oid_supported_list [] =
/* the statistical stuff */ /* the statistical stuff */
OID_802_3_RCV_ERROR_ALIGNMENT, OID_802_3_RCV_ERROR_ALIGNMENT,
OID_802_3_XMIT_ONE_COLLISION, 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) ...@@ -290,16 +290,17 @@ static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
{ {
if (cap & (1 << 16)) { if (cap & (1 << 16)) {
int msec = 500; int msec = 500;
struct pci_dev *pdev = to_pci_dev(ehci->hcd.self.controller);
/* request handoff to OS */ /* request handoff to OS */
cap &= 1 << 24; cap |= 1 << 24;
pci_write_config_dword (to_pci_dev(ehci->hcd.self.controller), where, cap); pci_write_config_dword(pdev, where, cap);
/* and wait a while for it to happen */ /* and wait a while for it to happen */
do { do {
msleep(10); msleep(10);
msec -= 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); } while ((cap & (1 << 16)) && msec);
if (cap & (1 << 16)) { if (cap & (1 << 16)) {
ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n", ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n",
...@@ -520,7 +521,7 @@ static int ehci_start (struct usb_hcd *hcd) ...@@ -520,7 +521,7 @@ static int ehci_start (struct usb_hcd *hcd)
/* wire up the root hub */ /* wire up the root hub */
bus = hcd_to_bus (hcd); bus = hcd_to_bus (hcd);
bus->root_hub = udev = usb_alloc_dev (NULL, bus, 0); udev = usb_alloc_dev (NULL, bus, 0);
if (!udev) { if (!udev) {
done2: done2:
ehci_mem_cleanup (ehci); ehci_mem_cleanup (ehci);
...@@ -553,11 +554,10 @@ static int ehci_start (struct usb_hcd *hcd) ...@@ -553,11 +554,10 @@ static int ehci_start (struct usb_hcd *hcd)
* and device drivers may start it running. * and device drivers may start it running.
*/ */
udev->speed = USB_SPEED_HIGH; udev->speed = USB_SPEED_HIGH;
if (hcd_register_root (hcd) != 0) { if (hcd_register_root (udev, hcd) != 0) {
if (hcd->state == USB_STATE_RUNNING) if (hcd->state == USB_STATE_RUNNING)
ehci_ready (ehci); ehci_ready (ehci);
ehci_reset (ehci); ehci_reset (ehci);
bus->root_hub = 0;
usb_put_dev (udev); usb_put_dev (udev);
retval = -ENODEV; retval = -ENODEV;
goto done2; goto done2;
......
...@@ -483,7 +483,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) ...@@ -483,7 +483,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
qh->start = frame; qh->start = frame;
/* reset S-frame and (maybe) C-frame masks */ /* 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; qh->hw_info2 |= cpu_to_le32 (1 << uframe) | c_mask;
} else } else
dbg ("reused previous qh %p schedule", qh); dbg ("reused previous qh %p schedule", qh);
......
...@@ -557,18 +557,24 @@ static int rh_unlink_urb (struct urb * urb) ...@@ -557,18 +557,24 @@ static int rh_unlink_urb (struct urb * urb)
static int rh_connect_rh (hci_t * hci) static int rh_connect_rh (hci_t * hci)
{ {
struct usb_device *usb_dev; struct usb_device *usb_dev;
int retval;
hci->rh.devnum = 0; hci->rh.devnum = 0;
usb_dev = usb_alloc_dev (NULL, hci->bus, 0); usb_dev = usb_alloc_dev (NULL, hci->bus, 0);
if (!usb_dev) if (!usb_dev)
return -ENOMEM; return -ENOMEM;
hci->bus->root_hub = usb_dev;
usb_dev->devnum = 1; usb_dev->devnum = 1;
usb_dev->bus->devnum_next = usb_dev->devnum + 1; usb_dev->bus->devnum_next = usb_dev->devnum + 1;
set_bit (usb_dev->devnum, usb_dev->bus->devmap.devicemap); 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); usb_put_dev (usb_dev);
return -ENODEV; return -ENODEV;
} }
......
...@@ -134,13 +134,13 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) ...@@ -134,13 +134,13 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
struct ohci_regs *regs = controller->regs; struct ohci_regs *regs = controller->regs;
u32 temp; u32 temp;
temp = readl (&regs->revision) & 0xff; temp = ohci_readl (&regs->revision) & 0xff;
ohci_dbg_sw (controller, next, size, ohci_dbg_sw (controller, next, size,
"OHCI %d.%d, %s legacy support registers\n", "OHCI %d.%d, %s legacy support registers\n",
0x03 & (temp >> 4), (temp & 0x0f), 0x03 & (temp >> 4), (temp & 0x0f),
(temp & 0x10) ? "with" : "NO"); (temp & 0x10) ? "with" : "NO");
temp = readl (&regs->control); temp = ohci_readl (&regs->control);
ohci_dbg_sw (controller, next, size, ohci_dbg_sw (controller, next, size,
"control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n", "control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n",
temp, temp,
...@@ -155,7 +155,7 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) ...@@ -155,7 +155,7 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
temp & OHCI_CTRL_CBSR temp & OHCI_CTRL_CBSR
); );
temp = readl (&regs->cmdstatus); temp = ohci_readl (&regs->cmdstatus);
ohci_dbg_sw (controller, next, size, ohci_dbg_sw (controller, next, size,
"cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp, "cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp,
(temp & OHCI_SOC) >> 16, (temp & OHCI_SOC) >> 16,
...@@ -166,26 +166,26 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) ...@@ -166,26 +166,26 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
); );
ohci_dump_intr_mask (controller, "intrstatus", ohci_dump_intr_mask (controller, "intrstatus",
readl (&regs->intrstatus), next, size); ohci_readl (&regs->intrstatus), next, size);
ohci_dump_intr_mask (controller, "intrenable", ohci_dump_intr_mask (controller, "intrenable",
readl (&regs->intrenable), next, size); ohci_readl (&regs->intrenable), next, size);
// intrdisable always same as intrenable // intrdisable always same as intrenable
maybe_print_eds (controller, "ed_periodcurrent", 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", 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", 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", 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", maybe_print_eds (controller, "ed_bulkcurrent",
readl (&regs->ed_bulkcurrent), next, size); ohci_readl (&regs->ed_bulkcurrent), next, size);
maybe_print_eds (controller, "donehead", 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) \ #define dbg_port_sw(hc,num,value,next,size) \
...@@ -637,7 +637,7 @@ show_registers (struct class_device *class_dev, char *buf) ...@@ -637,7 +637,7 @@ show_registers (struct class_device *class_dev, char *buf)
"hcca frame 0x%04x\n", OHCI_FRAME_NO(ohci->hcca)); "hcca frame 0x%04x\n", OHCI_FRAME_NO(ohci->hcca));
/* other registers mostly affect frame timings */ /* other registers mostly affect frame timings */
rdata = readl (&regs->fminterval); rdata = ohci_readl (&regs->fminterval);
temp = scnprintf (next, size, temp = scnprintf (next, size,
"fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n", "fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n",
rdata, (rdata >> 31) ? " FIT" : "", rdata, (rdata >> 31) ? " FIT" : "",
...@@ -645,20 +645,20 @@ show_registers (struct class_device *class_dev, char *buf) ...@@ -645,20 +645,20 @@ show_registers (struct class_device *class_dev, char *buf)
size -= temp; size -= temp;
next += temp; next += temp;
rdata = readl (&regs->fmremaining); rdata = ohci_readl (&regs->fmremaining);
temp = scnprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n", temp = scnprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n",
rdata, (rdata >> 31) ? " FRT" : "", rdata, (rdata >> 31) ? " FRT" : "",
rdata & 0x3fff); rdata & 0x3fff);
size -= temp; size -= temp;
next += temp; next += temp;
rdata = readl (&regs->periodicstart); rdata = ohci_readl (&regs->periodicstart);
temp = scnprintf (next, size, "periodicstart 0x%04x\n", temp = scnprintf (next, size, "periodicstart 0x%04x\n",
rdata & 0x3fff); rdata & 0x3fff);
size -= temp; size -= temp;
next += temp; next += temp;
rdata = readl (&regs->lsthresh); rdata = ohci_readl (&regs->lsthresh);
temp = scnprintf (next, size, "lsthresh 0x%04x\n", temp = scnprintf (next, size, "lsthresh 0x%04x\n",
rdata & 0x3fff); rdata & 0x3fff);
size -= temp; size -= temp;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
* *
* History: * History:
* *
* 2004/03/24 LH7A404 support (Durgesh Pattamatta & Marc Singer)
* 2004/02/04 use generic dma_* functions instead of pci_* (dsaxena@plexity.net) * 2004/02/04 use generic dma_* functions instead of pci_* (dsaxena@plexity.net)
* 2003/02/24 show registers in sysfs (Kevin Brosius) * 2003/02/24 show registers in sysfs (Kevin Brosius)
* *
...@@ -393,7 +394,7 @@ static int hc_reset (struct ohci_hcd *ohci) ...@@ -393,7 +394,7 @@ static int hc_reset (struct ohci_hcd *ohci)
/* boot firmware should have set this up (5.1.1.3.1) */ /* boot firmware should have set this up (5.1.1.3.1) */
if (!ohci->fminterval) { if (!ohci->fminterval) {
temp = readl (&ohci->regs->fminterval); temp = ohci_readl (&ohci->regs->fminterval);
if (temp & 0x3fff0000) if (temp & 0x3fff0000)
ohci->fminterval = temp; ohci->fminterval = temp;
else else
...@@ -405,7 +406,7 @@ static int hc_reset (struct ohci_hcd *ohci) ...@@ -405,7 +406,7 @@ static int hc_reset (struct ohci_hcd *ohci)
* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. * On PA-RISC, PDC can leave IR set incorrectly; ignore it there.
*/ */
#ifndef __hppa__ #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"); ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n");
/* this timeout is arbitrary. we make it long, so systems /* this timeout is arbitrary. we make it long, so systems
...@@ -416,7 +417,7 @@ static int hc_reset (struct ohci_hcd *ohci) ...@@ -416,7 +417,7 @@ static int hc_reset (struct ohci_hcd *ohci)
writel (OHCI_INTR_OC, &ohci->regs->intrenable); writel (OHCI_INTR_OC, &ohci->regs->intrenable);
writel (OHCI_OCR, &ohci->regs->cmdstatus); 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); msleep (10);
if (--temp == 0) { if (--temp == 0) {
ohci_err (ohci, "USB HC TakeOver failed!\n"); ohci_err (ohci, "USB HC TakeOver failed!\n");
...@@ -430,13 +431,13 @@ static int hc_reset (struct ohci_hcd *ohci) ...@@ -430,13 +431,13 @@ static int hc_reset (struct ohci_hcd *ohci)
writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
ohci_dbg (ohci, "reset, control = 0x%x\n", ohci_dbg (ohci, "reset, control = 0x%x\n",
readl (&ohci->regs->control)); ohci_readl (&ohci->regs->control));
/* Reset USB (needed by some controllers); RemoteWakeupConnected /* Reset USB (needed by some controllers); RemoteWakeupConnected
* saved if boot firmware (BIOS/SMM/...) told us it's connected * saved if boot firmware (BIOS/SMM/...) told us it's connected
* (for OHCI integrated on mainboard, it normally is) * (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 */ ohci->hc_control &= OHCI_CTRL_RWC; /* hcfs 0 = RESET */
if (ohci->hc_control) if (ohci->hc_control)
ohci->hcd.can_wakeup = 1; ohci->hcd.can_wakeup = 1;
...@@ -450,13 +451,13 @@ static int hc_reset (struct ohci_hcd *ohci) ...@@ -450,13 +451,13 @@ static int hc_reset (struct ohci_hcd *ohci)
&ohci->regs->roothub.portstatus [temp]); &ohci->regs->roothub.portstatus [temp]);
} }
// flush those pci writes // flush those pci writes
(void) readl (&ohci->regs->control); (void) ohci_readl (&ohci->regs->control);
msleep (50); msleep (50);
/* HC Reset requires max 10 us delay */ /* HC Reset requires max 10 us delay */
writel (OHCI_HCR, &ohci->regs->cmdstatus); writel (OHCI_HCR, &ohci->regs->cmdstatus);
temp = 30; /* ... allow extra time */ 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) { if (--temp == 0) {
ohci_err (ohci, "USB HC reset timed out!\n"); ohci_err (ohci, "USB HC reset timed out!\n");
return -1; return -1;
...@@ -473,7 +474,7 @@ static int hc_reset (struct ohci_hcd *ohci) ...@@ -473,7 +474,7 @@ static int hc_reset (struct ohci_hcd *ohci)
*/ */
writel (ohci->hc_control, &ohci->regs->control); writel (ohci->hc_control, &ohci->regs->control);
// flush those pci writes // flush those pci writes
(void) readl (&ohci->regs->control); (void) ohci_readl (&ohci->regs->control);
return 0; return 0;
} }
...@@ -505,8 +506,8 @@ static int hc_start (struct ohci_hcd *ohci) ...@@ -505,8 +506,8 @@ static int hc_start (struct ohci_hcd *ohci)
/* some OHCI implementations are finicky about how they init. /* some OHCI implementations are finicky about how they init.
* bogus values here mean not even enumeration could work. * bogus values here mean not even enumeration could work.
*/ */
if ((readl (&ohci->regs->fminterval) & 0x3fff0000) == 0 if ((ohci_readl (&ohci->regs->fminterval) & 0x3fff0000) == 0
|| !readl (&ohci->regs->periodicstart)) { || !ohci_readl (&ohci->regs->periodicstart)) {
ohci_err (ohci, "init err\n"); ohci_err (ohci, "init err\n");
return -EOVERFLOW; return -EOVERFLOW;
} }
...@@ -548,7 +549,7 @@ static int hc_start (struct ohci_hcd *ohci) ...@@ -548,7 +549,7 @@ static int hc_start (struct ohci_hcd *ohci)
writel (RH_HS_LPSC, &ohci->regs->roothub.status); writel (RH_HS_LPSC, &ohci->regs->roothub.status);
writel (power_switching ? RH_B_PPCM : 0, &ohci->regs->roothub.b); writel (power_switching ? RH_B_PPCM : 0, &ohci->regs->roothub.b);
// flush those pci writes // 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. // POTPGT delay is bits 24-31, in 2 ms units.
mdelay ((roothub_a (ohci) >> 23) & 0x1fe); mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
...@@ -560,7 +561,7 @@ static int hc_start (struct ohci_hcd *ohci) ...@@ -560,7 +561,7 @@ static int hc_start (struct ohci_hcd *ohci)
} }
/* connect the virtual root hub */ /* 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; ohci->hcd.state = USB_STATE_RUNNING;
if (!udev) { if (!udev) {
disable (ohci); disable (ohci);
...@@ -570,9 +571,8 @@ static int hc_start (struct ohci_hcd *ohci) ...@@ -570,9 +571,8 @@ static int hc_start (struct ohci_hcd *ohci)
} }
udev->speed = USB_SPEED_FULL; udev->speed = USB_SPEED_FULL;
if (hcd_register_root (&ohci->hcd) != 0) { if (hcd_register_root (udev, &ohci->hcd) != 0) {
usb_put_dev (udev); usb_put_dev (udev);
bus->root_hub = NULL;
disable (ohci); disable (ohci);
ohci->hc_control &= ~OHCI_CTRL_HCFS; ohci->hc_control &= ~OHCI_CTRL_HCFS;
writel (ohci->hc_control, &ohci->regs->control); writel (ohci->hc_control, &ohci->regs->control);
...@@ -592,19 +592,20 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) ...@@ -592,19 +592,20 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
struct ohci_regs *regs = ohci->regs; struct ohci_regs *regs = ohci->regs;
int ints; 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) if ((ohci->hcca->done_head != 0)
&& ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) { && ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
ints = OHCI_INTR_WDH; ints = OHCI_INTR_WDH;
/* cardbus/... hardware gone before remove() */ /* cardbus/... hardware gone before remove() */
} else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) { } else if ((ints = ohci_readl (&regs->intrstatus)) == ~(u32)0) {
disable (ohci); disable (ohci);
ohci_dbg (ohci, "device removed!\n"); ohci_dbg (ohci, "device removed!\n");
return IRQ_HANDLED; return IRQ_HANDLED;
/* interrupt for some other device? */ /* interrupt for some other device? */
} else if ((ints &= readl (&regs->intrenable)) == 0) { } else if ((ints &= ohci_readl (&regs->intrenable)) == 0) {
return IRQ_NONE; return IRQ_NONE;
} }
...@@ -650,7 +651,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) ...@@ -650,7 +651,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
writel (ints, &regs->intrstatus); writel (ints, &regs->intrstatus);
writel (OHCI_INTR_MIE, &regs->intrenable); writel (OHCI_INTR_MIE, &regs->intrenable);
// flush those pci writes // flush those pci writes
(void) readl (&ohci->regs->control); (void) ohci_readl (&ohci->regs->control);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -798,6 +799,14 @@ MODULE_LICENSE ("GPL"); ...@@ -798,6 +799,14 @@ MODULE_LICENSE ("GPL");
#include "ohci-omap.c" #include "ohci-omap.c"
#endif #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" #error "missing bus glue for ohci-hcd"
#endif #endif
...@@ -20,20 +20,20 @@ ...@@ -20,20 +20,20 @@
* till some bits (mostly reserved) are clear; ok for all revs. * till some bits (mostly reserved) are clear; ok for all revs.
*/ */
#define read_roothub(hc, register, mask) ({ \ #define read_roothub(hc, register, mask) ({ \
u32 temp = readl (&hc->regs->roothub.register); \ u32 temp = ohci_readl (&hc->regs->roothub.register); \
if (temp == -1) \ if (temp == -1) \
disable (hc); \ disable (hc); \
else if (hc->flags & OHCI_QUIRK_AMD756) \ else if (hc->flags & OHCI_QUIRK_AMD756) \
while (temp & mask) \ while (temp & mask) \
temp = readl (&hc->regs->roothub.register); \ temp = ohci_readl (&hc->regs->roothub.register); \
temp; }) temp; })
static u32 roothub_a (struct ohci_hcd *hc) static u32 roothub_a (struct ohci_hcd *hc)
{ return read_roothub (hc, a, 0xfc0fe000); } { return read_roothub (hc, a, 0xfc0fe000); }
static inline u32 roothub_b (struct ohci_hcd *hc) 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) 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) static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
{ return read_roothub (hc, portstatus [i], 0xffe0fce0); } { return read_roothub (hc, portstatus [i], 0xffe0fce0); }
...@@ -83,14 +83,14 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) ...@@ -83,14 +83,14 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
spin_lock_irq (&ohci->lock); 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) { switch (ohci->hc_control & OHCI_CTRL_HCFS) {
case OHCI_USB_RESUME: case OHCI_USB_RESUME:
ohci_dbg (ohci, "resume/suspend?\n"); ohci_dbg (ohci, "resume/suspend?\n");
ohci->hc_control &= ~OHCI_CTRL_HCFS; ohci->hc_control &= ~OHCI_CTRL_HCFS;
ohci->hc_control |= OHCI_USB_RESET; ohci->hc_control |= OHCI_USB_RESET;
writel (ohci->hc_control, &ohci->regs->control); writel (ohci->hc_control, &ohci->regs->control);
(void) readl (&ohci->regs->control); (void) ohci_readl (&ohci->regs->control);
/* FALL THROUGH */ /* FALL THROUGH */
case OHCI_USB_RESET: case OHCI_USB_RESET:
status = -EBUSY; status = -EBUSY;
...@@ -109,7 +109,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) ...@@ -109,7 +109,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
ohci->hc_control &= ~OHCI_SCHED_ENABLES; ohci->hc_control &= ~OHCI_SCHED_ENABLES;
writel (ohci->hc_control, &ohci->regs->control); 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); writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
/* sched disables take effect on the next frame, /* sched disables take effect on the next frame,
...@@ -120,7 +120,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) ...@@ -120,7 +120,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
while (limit > 0) { while (limit > 0) {
udelay (250); udelay (250);
limit =- 250; limit =- 250;
if (readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) if (ohci_readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
break; break;
} }
dl_done_list (ohci, 0); dl_done_list (ohci, 0);
...@@ -128,7 +128,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) ...@@ -128,7 +128,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
} }
dl_done_list (ohci, 0); dl_done_list (ohci, 0);
finish_unlinks (ohci, OHCI_FRAME_NO(ohci->hcca), 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 */ /* maybe resume can wake root hub */
if (ohci->hcd.remote_wakeup) if (ohci->hcd.remote_wakeup)
...@@ -140,7 +140,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) ...@@ -140,7 +140,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
ohci->hc_control &= ~OHCI_CTRL_HCFS; ohci->hc_control &= ~OHCI_CTRL_HCFS;
ohci->hc_control |= OHCI_USB_SUSPEND; ohci->hc_control |= OHCI_USB_SUSPEND;
writel (ohci->hc_control, &ohci->regs->control); writel (ohci->hc_control, &ohci->regs->control);
(void) readl (&ohci->regs->control); (void) ohci_readl (&ohci->regs->control);
/* no resumes until devices finish suspending */ /* no resumes until devices finish suspending */
ohci->next_statechange = jiffies + msecs_to_jiffies (5); ohci->next_statechange = jiffies + msecs_to_jiffies (5);
...@@ -179,13 +179,13 @@ static int ohci_hub_resume (struct usb_hcd *hcd) ...@@ -179,13 +179,13 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
return -EAGAIN; return -EAGAIN;
spin_lock_irq (&ohci->lock); 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) { switch (ohci->hc_control & OHCI_CTRL_HCFS) {
case OHCI_USB_SUSPEND: case OHCI_USB_SUSPEND:
ohci->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES); ohci->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES);
ohci->hc_control |= OHCI_USB_RESUME; ohci->hc_control |= OHCI_USB_RESUME;
writel (ohci->hc_control, &ohci->regs->control); 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"); ohci_dbg (ohci, "resume root hub\n");
break; break;
case OHCI_USB_RESUME: case OHCI_USB_RESUME:
...@@ -210,7 +210,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd) ...@@ -210,7 +210,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
temp = roothub_a (ohci) & RH_A_NDP; temp = roothub_a (ohci) & RH_A_NDP;
enables = 0; enables = 0;
while (temp--) { while (temp--) {
u32 stat = readl (&ohci->regs->roothub.portstatus [temp]); u32 stat = ohci_readl (&ohci->regs->roothub.portstatus [temp]);
/* force global, not selective, resume */ /* force global, not selective, resume */
if (!(stat & RH_PS_PSS)) if (!(stat & RH_PS_PSS))
...@@ -222,7 +222,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd) ...@@ -222,7 +222,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
ohci->hcd.state = USB_STATE_RESUMING; ohci->hcd.state = USB_STATE_RESUMING;
mdelay (20 /* usb 11.5.1.10 */ + 15); mdelay (20 /* usb 11.5.1.10 */ + 15);
temp = readl (&ohci->regs->control); temp = ohci_readl (&ohci->regs->control);
temp &= OHCI_CTRL_HCFS; temp &= OHCI_CTRL_HCFS;
if (temp != OHCI_USB_RESUME) { if (temp != OHCI_USB_RESUME) {
ohci_err (ohci, "controller won't resume\n"); ohci_err (ohci, "controller won't resume\n");
...@@ -243,11 +243,11 @@ static int ohci_hub_resume (struct usb_hcd *hcd) ...@@ -243,11 +243,11 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
writel (OHCI_INTR_INIT, &ohci->regs->intrenable); writel (OHCI_INTR_INIT, &ohci->regs->intrenable);
if (ohci->ed_rm_list) if (ohci->ed_rm_list)
writel (OHCI_INTR_SF, &ohci->regs->intrenable); 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 */ /* Then re-enable operations */
writel (OHCI_USB_OPER, &ohci->regs->control); writel (OHCI_USB_OPER, &ohci->regs->control);
(void) readl (&ohci->regs->control); (void) ohci_readl (&ohci->regs->control);
msleep (3); msleep (3);
temp = OHCI_CONTROL_INIT | OHCI_USB_OPER; temp = OHCI_CONTROL_INIT | OHCI_USB_OPER;
...@@ -255,7 +255,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd) ...@@ -255,7 +255,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
temp |= OHCI_CTRL_RWC; temp |= OHCI_CTRL_RWC;
ohci->hc_control = temp; ohci->hc_control = temp;
writel (temp, &ohci->regs->control); writel (temp, &ohci->regs->control);
(void) readl (&ohci->regs->control); (void) ohci_readl (&ohci->regs->control);
/* TRSMRCY */ /* TRSMRCY */
msleep (10); msleep (10);
...@@ -290,7 +290,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd) ...@@ -290,7 +290,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
writel (ohci->hc_control, &ohci->regs->control); writel (ohci->hc_control, &ohci->regs->control);
if (temp) if (temp)
writel (status, &ohci->regs->cmdstatus); writel (status, &ohci->regs->cmdstatus);
(void) readl (&ohci->regs->control); (void) ohci_readl (&ohci->regs->control);
} }
ohci->hcd.state = USB_STATE_RUNNING; ohci->hcd.state = USB_STATE_RUNNING;
...@@ -332,7 +332,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) ...@@ -332,7 +332,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
if (!HCD_IS_RUNNING(ohci->hcd.state)) if (!HCD_IS_RUNNING(ohci->hcd.state))
return -ESHUTDOWN; return -ESHUTDOWN;
ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", 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" */ /* retry later; "should not happen" */
return 0; return 0;
} }
...@@ -496,7 +496,7 @@ static int ohci_hub_control ( ...@@ -496,7 +496,7 @@ static int ohci_hub_control (
goto error; goto error;
} }
writel (temp, &ohci->regs->roothub.portstatus [wIndex]); writel (temp, &ohci->regs->roothub.portstatus [wIndex]);
// readl (&ohci->regs->roothub.portstatus [wIndex]); // ohci_readl (&ohci->regs->roothub.portstatus [wIndex]);
break; break;
case GetHubDescriptor: case GetHubDescriptor:
ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf); ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf);
...@@ -541,7 +541,7 @@ static int ohci_hub_control ( ...@@ -541,7 +541,7 @@ static int ohci_hub_control (
&ohci->regs->roothub.portstatus [wIndex]); &ohci->regs->roothub.portstatus [wIndex]);
break; break;
case USB_PORT_FEAT_RESET: 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) if (temp & RH_PS_CCS)
writel (RH_PS_PRS, writel (RH_PS_PRS,
&ohci->regs->roothub.portstatus [wIndex]); &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, ...@@ -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) void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev)
{ {
struct usb_device *hub;
void *base; void *base;
info ("remove: %s, state %x", hcd->self.bus_name, hcd->state); 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) ...@@ -462,11 +461,10 @@ void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev)
if (in_interrupt ()) if (in_interrupt ())
BUG (); BUG ();
hub = hcd->self.root_hub;
hcd->state = USB_STATE_QUIESCING; hcd->state = USB_STATE_QUIESCING;
dbg ("%s: roothub graceful disconnect", hcd->self.bus_name); dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);
usb_disconnect (&hub); usb_disconnect (&hcd->self.root_hub);
hcd->driver->stop (hcd); hcd->driver->stop (hcd);
hcd_buffer_destroy (hcd); hcd_buffer_destroy (hcd);
......
...@@ -321,7 +321,7 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) ...@@ -321,7 +321,7 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
if (!ed->hwNextED) { if (!ed->hwNextED) {
ohci->hc_control &= ~OHCI_CTRL_CLE; ohci->hc_control &= ~OHCI_CTRL_CLE;
writel (ohci->hc_control, &ohci->regs->control); 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 } else
writel (le32_to_cpup (&ed->hwNextED), writel (le32_to_cpup (&ed->hwNextED),
&ohci->regs->ed_controlhead); &ohci->regs->ed_controlhead);
...@@ -345,7 +345,7 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) ...@@ -345,7 +345,7 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
if (!ed->hwNextED) { if (!ed->hwNextED) {
ohci->hc_control &= ~OHCI_CTRL_BLE; ohci->hc_control &= ~OHCI_CTRL_BLE;
writel (ohci->hc_control, &ohci->regs->control); 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 } else
writel (le32_to_cpup (&ed->hwNextED), writel (le32_to_cpup (&ed->hwNextED),
&ohci->regs->ed_bulkhead); &ohci->regs->ed_bulkhead);
...@@ -481,7 +481,7 @@ static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed) ...@@ -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->intrstatus);
writel (OHCI_INTR_SF, &ohci->regs->intrenable); writel (OHCI_INTR_SF, &ohci->regs->intrenable);
// flush those writes, and get latest HCCA contents // 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 /* SF interrupt might get delayed; record the frame counter value that
* indicates when the HC isn't looking at it, so concurrent unlinks * indicates when the HC isn't looking at it, so concurrent unlinks
......
...@@ -237,7 +237,6 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, ...@@ -237,7 +237,6 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver,
*/ */
void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev) void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev)
{ {
struct usb_device *hub;
void *base; void *base;
info ("remove: %s, state %x", hcd->self.bus_name, hcd->state); info ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
...@@ -245,11 +244,10 @@ void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev) ...@@ -245,11 +244,10 @@ void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev)
if (in_interrupt ()) if (in_interrupt ())
BUG (); BUG ();
hub = hcd->self.root_hub;
hcd->state = USB_STATE_QUIESCING; hcd->state = USB_STATE_QUIESCING;
dbg ("%s: roothub graceful disconnect", hcd->self.bus_name); dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);
usb_disconnect (&hub); usb_disconnect (&hcd->self.root_hub);
hcd->driver->stop (hcd); hcd->driver->stop (hcd);
hcd->state = USB_STATE_HALT; hcd->state = USB_STATE_HALT;
......
...@@ -429,3 +429,22 @@ static inline void periodic_reinit (struct ohci_hcd *ohci) ...@@ -429,3 +429,22 @@ static inline void periodic_reinit (struct ohci_hcd *ohci)
# define ohci_vdbg(ohci, fmt, args...) do { } while (0) # define ohci_vdbg(ohci, fmt, args...) do { } while (0)
#endif #endif
#ifdef CONFIG_ARCH_LH7A404
/* Marc Singer: at the time this code was written, the LH7A404
* had a problem reading the USB host registers. This
* implementation of the ohci_readl function performs the read
* twice as a work-around.
*/
static inline unsigned int ohci_readl (void* regs)
{
*(volatile unsigned int*) regs;
return *(volatile unsigned int*) regs;
}
#else
/* Standard version of ohci_readl uses standard, platform
* specific implementation. */
static inline unsigned int ohci_readl (void* regs)
{
return readl (regs);
}
#endif
This diff is collapsed.
...@@ -667,10 +667,10 @@ static int mdc800_device_release (struct inode* inode, struct file *file) ...@@ -667,10 +667,10 @@ static int mdc800_device_release (struct inode* inode, struct file *file)
/* /*
* The Device read callback Function * The Device read callback Function
*/ */
static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, loff_t *pos) static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t len, loff_t *pos)
{ {
size_t left=len, sts=len; /* single transfer size */ size_t left=len, sts=len; /* single transfer size */
char* ptr=buf; char __user *ptr = buf;
long timeout; long timeout;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
...@@ -767,7 +767,7 @@ static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, lof ...@@ -767,7 +767,7 @@ static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, lof
* After this the driver initiates the request for the answer or * After this the driver initiates the request for the answer or
* just waits until the camera becomes ready. * just waits until the camera becomes ready.
*/ */
static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t len, loff_t *pos) static ssize_t mdc800_device_write (struct file *file, const char __user *buf, size_t len, loff_t *pos)
{ {
size_t i=0; size_t i=0;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
......
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.
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