mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: arch/microblaze/include/asm/socket.h
This commit is contained in:
commit
aa11d958d1
1599 changed files with 38098 additions and 25849 deletions
|
|
@ -462,11 +462,18 @@ urbs:
|
|||
|
||||
rcv->buffer = buf;
|
||||
|
||||
usb_fill_bulk_urb(rcv->urb, acm->dev,
|
||||
acm->rx_endpoint,
|
||||
buf->base,
|
||||
acm->readsize,
|
||||
acm_read_bulk, rcv);
|
||||
if (acm->is_int_ep)
|
||||
usb_fill_int_urb(rcv->urb, acm->dev,
|
||||
acm->rx_endpoint,
|
||||
buf->base,
|
||||
acm->readsize,
|
||||
acm_read_bulk, rcv, acm->bInterval);
|
||||
else
|
||||
usb_fill_bulk_urb(rcv->urb, acm->dev,
|
||||
acm->rx_endpoint,
|
||||
buf->base,
|
||||
acm->readsize,
|
||||
acm_read_bulk, rcv);
|
||||
rcv->urb->transfer_dma = buf->dma;
|
||||
rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||
|
||||
|
|
@ -740,7 +747,7 @@ static int acm_tty_chars_in_buffer(struct tty_struct *tty)
|
|||
{
|
||||
struct acm *acm = tty->driver_data;
|
||||
if (!ACM_READY(acm))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
/*
|
||||
* This is inaccurate (overcounts), but it works.
|
||||
*/
|
||||
|
|
@ -1173,6 +1180,9 @@ made_compressed_probe:
|
|||
spin_lock_init(&acm->read_lock);
|
||||
mutex_init(&acm->mutex);
|
||||
acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
|
||||
acm->is_int_ep = usb_endpoint_xfer_int(epread);
|
||||
if (acm->is_int_ep)
|
||||
acm->bInterval = epread->bInterval;
|
||||
tty_port_init(&acm->port);
|
||||
acm->port.ops = &acm_port_ops;
|
||||
|
||||
|
|
@ -1227,9 +1237,14 @@ made_compressed_probe:
|
|||
goto alloc_fail7;
|
||||
}
|
||||
|
||||
usb_fill_bulk_urb(snd->urb, usb_dev,
|
||||
usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
|
||||
NULL, acm->writesize, acm_write_bulk, snd);
|
||||
if (usb_endpoint_xfer_int(epwrite))
|
||||
usb_fill_int_urb(snd->urb, usb_dev,
|
||||
usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
|
||||
NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval);
|
||||
else
|
||||
usb_fill_bulk_urb(snd->urb, usb_dev,
|
||||
usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
|
||||
NULL, acm->writesize, acm_write_bulk, snd);
|
||||
snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||
snd->instance = acm;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,6 +126,8 @@ struct acm {
|
|||
unsigned int ctrl_caps; /* control capabilities from the class specific header */
|
||||
unsigned int susp_count; /* number of suspended interfaces */
|
||||
int combined_interfaces:1; /* control and data collapsed */
|
||||
int is_int_ep:1; /* interrupt endpoints contrary to spec used */
|
||||
u8 bInterval;
|
||||
struct acm_wb *delayed_wb; /* write queued for a device about to be woken */
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
|
|
|
|||
|
|
@ -751,7 +751,7 @@ static int get_capabilities(struct usbtmc_device_data *data)
|
|||
{
|
||||
struct device *dev = &data->usb_dev->dev;
|
||||
char *buffer;
|
||||
int rv;
|
||||
int rv = 0;
|
||||
|
||||
buffer = kmalloc(0x18, GFP_KERNEL);
|
||||
if (!buffer)
|
||||
|
|
@ -763,7 +763,7 @@ static int get_capabilities(struct usbtmc_device_data *data)
|
|||
0, 0, buffer, 0x18, USBTMC_TIMEOUT);
|
||||
if (rv < 0) {
|
||||
dev_err(dev, "usb_control_msg returned %d\n", rv);
|
||||
return rv;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "GET_CAPABILITIES returned %x\n", buffer[0]);
|
||||
|
|
@ -773,7 +773,8 @@ static int get_capabilities(struct usbtmc_device_data *data)
|
|||
dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]);
|
||||
if (buffer[0] != USBTMC_STATUS_SUCCESS) {
|
||||
dev_err(dev, "GET_CAPABILITIES returned %x\n", buffer[0]);
|
||||
return -EPERM;
|
||||
rv = -EPERM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
data->capabilities.interface_capabilities = buffer[4];
|
||||
|
|
@ -781,8 +782,9 @@ static int get_capabilities(struct usbtmc_device_data *data)
|
|||
data->capabilities.usb488_interface_capabilities = buffer[14];
|
||||
data->capabilities.usb488_device_capabilities = buffer[15];
|
||||
|
||||
err_out:
|
||||
kfree(buffer);
|
||||
return 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define capability_attribute(name) \
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ comment "Miscellaneous USB options"
|
|||
depends on USB
|
||||
|
||||
config USB_DEVICEFS
|
||||
bool "USB device filesystem (DEPRECATED)" if EMBEDDED
|
||||
bool "USB device filesystem (DEPRECATED)"
|
||||
depends on USB
|
||||
---help---
|
||||
If you say Y here (and to "/proc file system support" in the "File
|
||||
|
|
|
|||
|
|
@ -80,38 +80,18 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
|
|||
int max_tx;
|
||||
int i;
|
||||
|
||||
/* Allocate space for the SS endpoint companion descriptor */
|
||||
ep->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp),
|
||||
GFP_KERNEL);
|
||||
if (!ep->ss_ep_comp)
|
||||
return -ENOMEM;
|
||||
desc = (struct usb_ss_ep_comp_descriptor *) buffer;
|
||||
if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) {
|
||||
dev_warn(ddev, "No SuperSpeed endpoint companion for config %d "
|
||||
" interface %d altsetting %d ep %d: "
|
||||
"using minimum values\n",
|
||||
cfgno, inum, asnum, ep->desc.bEndpointAddress);
|
||||
ep->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE;
|
||||
ep->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
|
||||
ep->ss_ep_comp->desc.bMaxBurst = 0;
|
||||
/*
|
||||
* Leave bmAttributes as zero, which will mean no streams for
|
||||
* bulk, and isoc won't support multiple bursts of packets.
|
||||
* With bursts of only one packet, and a Mult of 1, the max
|
||||
* amount of data moved per endpoint service interval is one
|
||||
* packet.
|
||||
*/
|
||||
if (usb_endpoint_xfer_isoc(&ep->desc) ||
|
||||
usb_endpoint_xfer_int(&ep->desc))
|
||||
ep->ss_ep_comp->desc.wBytesPerInterval =
|
||||
ep->desc.wMaxPacketSize;
|
||||
/*
|
||||
* The next descriptor is for an Endpoint or Interface,
|
||||
* no extra descriptors to copy into the companion structure,
|
||||
* and we didn't eat up any of the buffer.
|
||||
*/
|
||||
retval = 0;
|
||||
goto valid;
|
||||
return 0;
|
||||
}
|
||||
memcpy(&ep->ss_ep_comp->desc, desc, USB_DT_SS_EP_COMP_SIZE);
|
||||
desc = &ep->ss_ep_comp->desc;
|
||||
|
|
@ -320,6 +300,28 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
|
|||
buffer += i;
|
||||
size -= i;
|
||||
|
||||
/* Allocate space for the SS endpoint companion descriptor */
|
||||
endpoint->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp),
|
||||
GFP_KERNEL);
|
||||
if (!endpoint->ss_ep_comp)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Fill in some default values (may be overwritten later) */
|
||||
endpoint->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE;
|
||||
endpoint->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
|
||||
endpoint->ss_ep_comp->desc.bMaxBurst = 0;
|
||||
/*
|
||||
* Leave bmAttributes as zero, which will mean no streams for
|
||||
* bulk, and isoc won't support multiple bursts of packets.
|
||||
* With bursts of only one packet, and a Mult of 1, the max
|
||||
* amount of data moved per endpoint service interval is one
|
||||
* packet.
|
||||
*/
|
||||
if (usb_endpoint_xfer_isoc(&endpoint->desc) ||
|
||||
usb_endpoint_xfer_int(&endpoint->desc))
|
||||
endpoint->ss_ep_comp->desc.wBytesPerInterval =
|
||||
endpoint->desc.wMaxPacketSize;
|
||||
|
||||
if (size > 0) {
|
||||
retval = usb_parse_ss_endpoint_companion(ddev, cfgno,
|
||||
inum, asnum, endpoint, num_ep, buffer,
|
||||
|
|
@ -329,6 +331,10 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
|
|||
retval = buffer - buffer0;
|
||||
}
|
||||
} else {
|
||||
dev_warn(ddev, "config %d interface %d altsetting %d "
|
||||
"endpoint 0x%X has no "
|
||||
"SuperSpeed companion descriptor\n",
|
||||
cfgno, inum, asnum, d->bEndpointAddress);
|
||||
retval = buffer - buffer0;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -136,17 +136,19 @@ static const struct class_info clas_info[] =
|
|||
{USB_CLASS_AUDIO, "audio"},
|
||||
{USB_CLASS_COMM, "comm."},
|
||||
{USB_CLASS_HID, "HID"},
|
||||
{USB_CLASS_HUB, "hub"},
|
||||
{USB_CLASS_PHYSICAL, "PID"},
|
||||
{USB_CLASS_STILL_IMAGE, "still"},
|
||||
{USB_CLASS_PRINTER, "print"},
|
||||
{USB_CLASS_MASS_STORAGE, "stor."},
|
||||
{USB_CLASS_HUB, "hub"},
|
||||
{USB_CLASS_CDC_DATA, "data"},
|
||||
{USB_CLASS_APP_SPEC, "app."},
|
||||
{USB_CLASS_VENDOR_SPEC, "vend."},
|
||||
{USB_CLASS_STILL_IMAGE, "still"},
|
||||
{USB_CLASS_CSCID, "scard"},
|
||||
{USB_CLASS_CONTENT_SEC, "c-sec"},
|
||||
{USB_CLASS_VIDEO, "video"},
|
||||
{USB_CLASS_WIRELESS_CONTROLLER, "wlcon"},
|
||||
{USB_CLASS_MISC, "misc"},
|
||||
{USB_CLASS_APP_SPEC, "app."},
|
||||
{USB_CLASS_VENDOR_SPEC, "vend."},
|
||||
{-1, "unk."} /* leave as last */
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -325,21 +325,34 @@ static void async_completed(struct urb *urb)
|
|||
struct async *as = urb->context;
|
||||
struct dev_state *ps = as->ps;
|
||||
struct siginfo sinfo;
|
||||
struct pid *pid = NULL;
|
||||
uid_t uid = 0;
|
||||
uid_t euid = 0;
|
||||
u32 secid = 0;
|
||||
int signr;
|
||||
|
||||
spin_lock(&ps->lock);
|
||||
list_move_tail(&as->asynclist, &ps->async_completed);
|
||||
spin_unlock(&ps->lock);
|
||||
as->status = urb->status;
|
||||
if (as->signr) {
|
||||
signr = as->signr;
|
||||
if (signr) {
|
||||
sinfo.si_signo = as->signr;
|
||||
sinfo.si_errno = as->status;
|
||||
sinfo.si_code = SI_ASYNCIO;
|
||||
sinfo.si_addr = as->userurb;
|
||||
kill_pid_info_as_uid(as->signr, &sinfo, as->pid, as->uid,
|
||||
as->euid, as->secid);
|
||||
pid = as->pid;
|
||||
uid = as->uid;
|
||||
euid = as->euid;
|
||||
secid = as->secid;
|
||||
}
|
||||
snoop(&urb->dev->dev, "urb complete\n");
|
||||
snoop_urb(urb, as->userurb);
|
||||
spin_unlock(&ps->lock);
|
||||
|
||||
if (signr)
|
||||
kill_pid_info_as_uid(sinfo.si_signo, &sinfo, pid, uid,
|
||||
euid, secid);
|
||||
|
||||
wake_up(&ps->wait);
|
||||
}
|
||||
|
||||
|
|
@ -582,7 +595,7 @@ static int usbdev_open(struct inode *inode, struct file *file)
|
|||
if (!ps)
|
||||
goto out;
|
||||
|
||||
ret = -ENOENT;
|
||||
ret = -ENODEV;
|
||||
|
||||
/* usbdev device-node */
|
||||
if (imajor(inode) == USB_DEVICE_MAJOR)
|
||||
|
|
@ -982,7 +995,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
|||
USBDEVFS_URB_ZERO_PACKET |
|
||||
USBDEVFS_URB_NO_INTERRUPT))
|
||||
return -EINVAL;
|
||||
if (!uurb->buffer)
|
||||
if (uurb->buffer_length > 0 && !uurb->buffer)
|
||||
return -EINVAL;
|
||||
if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL &&
|
||||
(uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
|
||||
|
|
@ -1038,11 +1051,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
|||
is_in = 0;
|
||||
uurb->endpoint &= ~USB_DIR_IN;
|
||||
}
|
||||
if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
|
||||
uurb->buffer, uurb->buffer_length)) {
|
||||
kfree(dr);
|
||||
return -EFAULT;
|
||||
}
|
||||
snoop(&ps->dev->dev, "control urb: bRequest=%02x "
|
||||
"bRrequestType=%02x wValue=%04x "
|
||||
"wIndex=%04x wLength=%04x\n",
|
||||
|
|
@ -1062,9 +1070,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
|||
uurb->number_of_packets = 0;
|
||||
if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
|
||||
return -EINVAL;
|
||||
if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
|
||||
uurb->buffer, uurb->buffer_length))
|
||||
return -EFAULT;
|
||||
snoop(&ps->dev->dev, "bulk urb\n");
|
||||
break;
|
||||
|
||||
|
|
@ -1106,27 +1111,34 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
|||
return -EINVAL;
|
||||
if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
|
||||
return -EINVAL;
|
||||
if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
|
||||
uurb->buffer, uurb->buffer_length))
|
||||
return -EFAULT;
|
||||
snoop(&ps->dev->dev, "interrupt urb\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (uurb->buffer_length > 0 &&
|
||||
!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
|
||||
uurb->buffer, uurb->buffer_length)) {
|
||||
kfree(isopkt);
|
||||
kfree(dr);
|
||||
return -EFAULT;
|
||||
}
|
||||
as = alloc_async(uurb->number_of_packets);
|
||||
if (!as) {
|
||||
kfree(isopkt);
|
||||
kfree(dr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL);
|
||||
if (!as->urb->transfer_buffer) {
|
||||
kfree(isopkt);
|
||||
kfree(dr);
|
||||
free_async(as);
|
||||
return -ENOMEM;
|
||||
if (uurb->buffer_length > 0) {
|
||||
as->urb->transfer_buffer = kmalloc(uurb->buffer_length,
|
||||
GFP_KERNEL);
|
||||
if (!as->urb->transfer_buffer) {
|
||||
kfree(isopkt);
|
||||
kfree(dr);
|
||||
free_async(as);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
as->urb->dev = ps->dev;
|
||||
as->urb->pipe = (uurb->type << 30) |
|
||||
|
|
@ -1169,7 +1181,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
|||
kfree(isopkt);
|
||||
as->ps = ps;
|
||||
as->userurb = arg;
|
||||
if (uurb->endpoint & USB_DIR_IN)
|
||||
if (is_in && uurb->buffer_length > 0)
|
||||
as->userbuffer = uurb->buffer;
|
||||
else
|
||||
as->userbuffer = NULL;
|
||||
|
|
@ -1179,9 +1191,9 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
|||
as->uid = cred->uid;
|
||||
as->euid = cred->euid;
|
||||
security_task_getsecid(current, &as->secid);
|
||||
if (!is_in) {
|
||||
if (!is_in && uurb->buffer_length > 0) {
|
||||
if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,
|
||||
as->urb->transfer_buffer_length)) {
|
||||
uurb->buffer_length)) {
|
||||
free_async(as);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
|
@ -1231,22 +1243,22 @@ static int processcompl(struct async *as, void __user * __user *arg)
|
|||
if (as->userbuffer)
|
||||
if (copy_to_user(as->userbuffer, urb->transfer_buffer,
|
||||
urb->transfer_buffer_length))
|
||||
return -EFAULT;
|
||||
goto err_out;
|
||||
if (put_user(as->status, &userurb->status))
|
||||
return -EFAULT;
|
||||
goto err_out;
|
||||
if (put_user(urb->actual_length, &userurb->actual_length))
|
||||
return -EFAULT;
|
||||
goto err_out;
|
||||
if (put_user(urb->error_count, &userurb->error_count))
|
||||
return -EFAULT;
|
||||
goto err_out;
|
||||
|
||||
if (usb_endpoint_xfer_isoc(&urb->ep->desc)) {
|
||||
for (i = 0; i < urb->number_of_packets; i++) {
|
||||
if (put_user(urb->iso_frame_desc[i].actual_length,
|
||||
&userurb->iso_frame_desc[i].actual_length))
|
||||
return -EFAULT;
|
||||
goto err_out;
|
||||
if (put_user(urb->iso_frame_desc[i].status,
|
||||
&userurb->iso_frame_desc[i].status))
|
||||
return -EFAULT;
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1255,6 +1267,10 @@ static int processcompl(struct async *as, void __user * __user *arg)
|
|||
if (put_user(addr, (void __user * __user *)arg))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
free_async(as);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static struct async *reap_as(struct dev_state *ps)
|
||||
|
|
@ -1305,7 +1321,8 @@ static int get_urb32(struct usbdevfs_urb *kurb,
|
|||
struct usbdevfs_urb32 __user *uurb)
|
||||
{
|
||||
__u32 uptr;
|
||||
if (get_user(kurb->type, &uurb->type) ||
|
||||
if (!access_ok(VERIFY_READ, uurb, sizeof(*uurb)) ||
|
||||
__get_user(kurb->type, &uurb->type) ||
|
||||
__get_user(kurb->endpoint, &uurb->endpoint) ||
|
||||
__get_user(kurb->status, &uurb->status) ||
|
||||
__get_user(kurb->flags, &uurb->flags) ||
|
||||
|
|
@ -1520,8 +1537,9 @@ static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg)
|
|||
u32 udata;
|
||||
|
||||
uioc = compat_ptr((long)arg);
|
||||
if (get_user(ctrl.ifno, &uioc->ifno) ||
|
||||
get_user(ctrl.ioctl_code, &uioc->ioctl_code) ||
|
||||
if (!access_ok(VERIFY_READ, uioc, sizeof(*uioc)) ||
|
||||
__get_user(ctrl.ifno, &uioc->ifno) ||
|
||||
__get_user(ctrl.ioctl_code, &uioc->ioctl_code) ||
|
||||
__get_user(udata, &uioc->data))
|
||||
return -EFAULT;
|
||||
ctrl.data = compat_ptr(udata);
|
||||
|
|
|
|||
|
|
@ -648,7 +648,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
|
|||
struct urb *urb;
|
||||
int length;
|
||||
unsigned long flags;
|
||||
char buffer[4]; /* Any root hubs with > 31 ports? */
|
||||
char buffer[6]; /* Any root hubs with > 31 ports? */
|
||||
|
||||
if (unlikely(!hcd->rh_registered))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -227,6 +227,10 @@ struct hc_driver {
|
|||
/* has a port been handed over to a companion? */
|
||||
int (*port_handed_over)(struct usb_hcd *, int);
|
||||
|
||||
/* CLEAR_TT_BUFFER completion callback */
|
||||
void (*clear_tt_buffer_complete)(struct usb_hcd *,
|
||||
struct usb_host_endpoint *);
|
||||
|
||||
/* xHCI specific functions */
|
||||
/* Called by usb_alloc_dev to alloc HC device structures */
|
||||
int (*alloc_dev)(struct usb_hcd *, struct usb_device *);
|
||||
|
|
|
|||
|
|
@ -450,10 +450,10 @@ hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt)
|
|||
* talking to TTs must queue control transfers (not just bulk and iso), so
|
||||
* both can talk to the same hub concurrently.
|
||||
*/
|
||||
static void hub_tt_kevent (struct work_struct *work)
|
||||
static void hub_tt_work(struct work_struct *work)
|
||||
{
|
||||
struct usb_hub *hub =
|
||||
container_of(work, struct usb_hub, tt.kevent);
|
||||
container_of(work, struct usb_hub, tt.clear_work);
|
||||
unsigned long flags;
|
||||
int limit = 100;
|
||||
|
||||
|
|
@ -462,6 +462,7 @@ static void hub_tt_kevent (struct work_struct *work)
|
|||
struct list_head *next;
|
||||
struct usb_tt_clear *clear;
|
||||
struct usb_device *hdev = hub->hdev;
|
||||
const struct hc_driver *drv;
|
||||
int status;
|
||||
|
||||
next = hub->tt.clear_list.next;
|
||||
|
|
@ -471,21 +472,25 @@ static void hub_tt_kevent (struct work_struct *work)
|
|||
/* drop lock so HCD can concurrently report other TT errors */
|
||||
spin_unlock_irqrestore (&hub->tt.lock, flags);
|
||||
status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt);
|
||||
spin_lock_irqsave (&hub->tt.lock, flags);
|
||||
|
||||
if (status)
|
||||
dev_err (&hdev->dev,
|
||||
"clear tt %d (%04x) error %d\n",
|
||||
clear->tt, clear->devinfo, status);
|
||||
|
||||
/* Tell the HCD, even if the operation failed */
|
||||
drv = clear->hcd->driver;
|
||||
if (drv->clear_tt_buffer_complete)
|
||||
(drv->clear_tt_buffer_complete)(clear->hcd, clear->ep);
|
||||
|
||||
kfree(clear);
|
||||
spin_lock_irqsave(&hub->tt.lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore (&hub->tt.lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_hub_tt_clear_buffer - clear control/bulk TT state in high speed hub
|
||||
* @udev: the device whose split transaction failed
|
||||
* @pipe: identifies the endpoint of the failed transaction
|
||||
* usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub
|
||||
* @urb: an URB associated with the failed or incomplete split transaction
|
||||
*
|
||||
* High speed HCDs use this to tell the hub driver that some split control or
|
||||
* bulk transaction failed in a way that requires clearing internal state of
|
||||
|
|
@ -495,8 +500,10 @@ static void hub_tt_kevent (struct work_struct *work)
|
|||
* It may not be possible for that hub to handle additional full (or low)
|
||||
* speed transactions until that state is fully cleared out.
|
||||
*/
|
||||
void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
|
||||
int usb_hub_clear_tt_buffer(struct urb *urb)
|
||||
{
|
||||
struct usb_device *udev = urb->dev;
|
||||
int pipe = urb->pipe;
|
||||
struct usb_tt *tt = udev->tt;
|
||||
unsigned long flags;
|
||||
struct usb_tt_clear *clear;
|
||||
|
|
@ -508,7 +515,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
|
|||
if ((clear = kmalloc (sizeof *clear, GFP_ATOMIC)) == NULL) {
|
||||
dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n");
|
||||
/* FIXME recover somehow ... RESET_TT? */
|
||||
return;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* info that CLEAR_TT_BUFFER needs */
|
||||
|
|
@ -520,14 +527,19 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
|
|||
: (USB_ENDPOINT_XFER_BULK << 11);
|
||||
if (usb_pipein (pipe))
|
||||
clear->devinfo |= 1 << 15;
|
||||
|
||||
|
||||
/* info for completion callback */
|
||||
clear->hcd = bus_to_hcd(udev->bus);
|
||||
clear->ep = urb->ep;
|
||||
|
||||
/* tell keventd to clear state for this TT */
|
||||
spin_lock_irqsave (&tt->lock, flags);
|
||||
list_add_tail (&clear->clear_list, &tt->clear_list);
|
||||
schedule_work (&tt->kevent);
|
||||
schedule_work(&tt->clear_work);
|
||||
spin_unlock_irqrestore (&tt->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer);
|
||||
EXPORT_SYMBOL_GPL(usb_hub_clear_tt_buffer);
|
||||
|
||||
/* If do_delay is false, return the number of milliseconds the caller
|
||||
* needs to delay.
|
||||
|
|
@ -818,7 +830,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
|
|||
if (hub->has_indicators)
|
||||
cancel_delayed_work_sync(&hub->leds);
|
||||
if (hub->tt.hub)
|
||||
cancel_work_sync(&hub->tt.kevent);
|
||||
cancel_work_sync(&hub->tt.clear_work);
|
||||
}
|
||||
|
||||
/* caller has locked the hub device */
|
||||
|
|
@ -935,7 +947,7 @@ static int hub_configure(struct usb_hub *hub,
|
|||
|
||||
spin_lock_init (&hub->tt.lock);
|
||||
INIT_LIST_HEAD (&hub->tt.clear_list);
|
||||
INIT_WORK (&hub->tt.kevent, hub_tt_kevent);
|
||||
INIT_WORK(&hub->tt.clear_work, hub_tt_work);
|
||||
switch (hdev->descriptor.bDeviceProtocol) {
|
||||
case 0:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -188,16 +188,18 @@ struct usb_tt {
|
|||
/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
|
||||
spinlock_t lock;
|
||||
struct list_head clear_list; /* of usb_tt_clear */
|
||||
struct work_struct kevent;
|
||||
struct work_struct clear_work;
|
||||
};
|
||||
|
||||
struct usb_tt_clear {
|
||||
struct list_head clear_list;
|
||||
unsigned tt;
|
||||
u16 devinfo;
|
||||
struct usb_hcd *hcd;
|
||||
struct usb_host_endpoint *ep;
|
||||
};
|
||||
|
||||
extern void usb_hub_tt_clear_buffer(struct usb_device *dev, int pipe);
|
||||
extern int usb_hub_clear_tt_buffer(struct urb *urb);
|
||||
extern void usb_ep0_reinit(struct usb_device *);
|
||||
|
||||
#endif /* __LINUX_HUB_H */
|
||||
|
|
|
|||
|
|
@ -806,6 +806,48 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (dev->have_langid)
|
||||
return 0;
|
||||
|
||||
if (dev->string_langid < 0)
|
||||
return -EPIPE;
|
||||
|
||||
err = usb_string_sub(dev, 0, 0, tbuf);
|
||||
|
||||
/* If the string was reported but is malformed, default to english
|
||||
* (0x0409) */
|
||||
if (err == -ENODATA || (err > 0 && err < 4)) {
|
||||
dev->string_langid = 0x0409;
|
||||
dev->have_langid = 1;
|
||||
dev_err(&dev->dev,
|
||||
"string descriptor 0 malformed (err = %d), "
|
||||
"defaulting to 0x%04x\n",
|
||||
err, dev->string_langid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* In case of all other errors, we assume the device is not able to
|
||||
* deal with strings at all. Set string_langid to -1 in order to
|
||||
* prevent any string to be retrieved from the device */
|
||||
if (err < 0) {
|
||||
dev_err(&dev->dev, "string descriptor 0 read error: %d\n",
|
||||
err);
|
||||
dev->string_langid = -1;
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
/* always use the first langid listed */
|
||||
dev->string_langid = tbuf[2] | (tbuf[3] << 8);
|
||||
dev->have_langid = 1;
|
||||
dev_dbg(&dev->dev, "default language 0x%04x\n",
|
||||
dev->string_langid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_string - returns UTF-8 version of a string descriptor
|
||||
* @dev: the device whose string descriptor is being retrieved
|
||||
|
|
@ -837,24 +879,9 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
|
|||
if (!tbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
/* get langid for strings if it's not yet known */
|
||||
if (!dev->have_langid) {
|
||||
err = usb_string_sub(dev, 0, 0, tbuf);
|
||||
if (err < 0) {
|
||||
dev_err(&dev->dev,
|
||||
"string descriptor 0 read error: %d\n",
|
||||
err);
|
||||
} else if (err < 4) {
|
||||
dev_err(&dev->dev, "string descriptor 0 too short\n");
|
||||
} else {
|
||||
dev->string_langid = tbuf[2] | (tbuf[3] << 8);
|
||||
/* always use the first langid listed */
|
||||
dev_dbg(&dev->dev, "default language 0x%04x\n",
|
||||
dev->string_langid);
|
||||
}
|
||||
|
||||
dev->have_langid = 1;
|
||||
}
|
||||
err = usb_get_langid(dev, tbuf);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
err = usb_string_sub(dev, dev->string_langid, index, tbuf);
|
||||
if (err < 0)
|
||||
|
|
|
|||
|
|
@ -286,6 +286,27 @@ config USB_S3C_HSOTG
|
|||
default USB_GADGET
|
||||
select USB_GADGET_SELECTED
|
||||
|
||||
config USB_GADGET_IMX
|
||||
boolean "Freescale IMX USB Peripheral Controller"
|
||||
depends on ARCH_MX1
|
||||
help
|
||||
Freescale's IMX series include an integrated full speed
|
||||
USB 1.1 device controller. The controller in the IMX series
|
||||
is register-compatible.
|
||||
|
||||
It has Six fixed-function endpoints, as well as endpoint
|
||||
zero (for control transfers).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "imx_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_IMX
|
||||
tristate
|
||||
depends on USB_GADGET_IMX
|
||||
default USB_GADGET
|
||||
select USB_GADGET_SELECTED
|
||||
|
||||
config USB_GADGET_S3C2410
|
||||
boolean "S3C2410 USB Device Controller"
|
||||
depends on ARCH_S3C2410
|
||||
|
|
@ -321,27 +342,6 @@ config USB_GADGET_MUSB_HDRC
|
|||
This OTG-capable silicon IP is used in dual designs including
|
||||
the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin
|
||||
|
||||
config USB_GADGET_IMX
|
||||
boolean "Freescale IMX USB Peripheral Controller"
|
||||
depends on ARCH_MX1
|
||||
help
|
||||
Freescale's IMX series include an integrated full speed
|
||||
USB 1.1 device controller. The controller in the IMX series
|
||||
is register-compatible.
|
||||
|
||||
It has Six fixed-function endpoints, as well as endpoint
|
||||
zero (for control transfers).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "imx_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_IMX
|
||||
tristate
|
||||
depends on USB_GADGET_IMX
|
||||
default USB_GADGET
|
||||
select USB_GADGET_SELECTED
|
||||
|
||||
config USB_GADGET_M66592
|
||||
boolean "Renesas M66592 USB Peripheral Controller"
|
||||
select USB_GADGET_DUALSPEED
|
||||
|
|
@ -604,6 +604,7 @@ config USB_ZERO_HNPTEST
|
|||
config USB_AUDIO
|
||||
tristate "Audio Gadget (EXPERIMENTAL)"
|
||||
depends on SND
|
||||
select SND_PCM
|
||||
help
|
||||
Gadget Audio is compatible with USB Audio Class specification 1.0.
|
||||
It will include at least one AudioControl interface, zero or more
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@
|
|||
#include <linux/ioport.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/timer.h>
|
||||
|
|
|
|||
|
|
@ -42,9 +42,9 @@
|
|||
* Instead: allocate your own, using normal USB-IF procedures.
|
||||
*/
|
||||
|
||||
/* Thanks to NetChip Technologies for donating this product ID. */
|
||||
#define AUDIO_VENDOR_NUM 0x0525 /* NetChip */
|
||||
#define AUDIO_PRODUCT_NUM 0xa4a1 /* Linux-USB Audio Gadget */
|
||||
/* Thanks to Linux Foundation for donating this product ID. */
|
||||
#define AUDIO_VENDOR_NUM 0x1d6b /* Linux Foundation */
|
||||
#define AUDIO_PRODUCT_NUM 0x0101 /* Linux-USB Audio Gadget */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
|
|
|||
|
|
@ -293,15 +293,16 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
|
|||
/* CDC Subset */
|
||||
eth_config_driver.label = "CDC Subset/SAFE";
|
||||
|
||||
device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM),
|
||||
device_desc.idProduct = cpu_to_le16(SIMPLE_PRODUCT_NUM),
|
||||
device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
|
||||
device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM);
|
||||
device_desc.idProduct = cpu_to_le16(SIMPLE_PRODUCT_NUM);
|
||||
if (!has_rndis())
|
||||
device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
|
||||
}
|
||||
|
||||
if (has_rndis()) {
|
||||
/* RNDIS plus ECM-or-Subset */
|
||||
device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM),
|
||||
device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM),
|
||||
device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM);
|
||||
device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM);
|
||||
device_desc.bNumConfigurations = 2;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include <linux/ioport.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/timer.h>
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ static int is_vbus_present(void)
|
|||
{
|
||||
struct pxa2xx_udc_mach_info *mach = the_controller->mach;
|
||||
|
||||
if (mach->gpio_vbus) {
|
||||
if (gpio_is_valid(mach->gpio_vbus)) {
|
||||
int value = gpio_get_value(mach->gpio_vbus);
|
||||
|
||||
if (mach->gpio_vbus_inverted)
|
||||
|
|
@ -158,7 +158,7 @@ static void pullup_off(void)
|
|||
struct pxa2xx_udc_mach_info *mach = the_controller->mach;
|
||||
int off_level = mach->gpio_pullup_inverted;
|
||||
|
||||
if (mach->gpio_pullup)
|
||||
if (gpio_is_valid(mach->gpio_pullup))
|
||||
gpio_set_value(mach->gpio_pullup, off_level);
|
||||
else if (mach->udc_command)
|
||||
mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
|
||||
|
|
@ -169,7 +169,7 @@ static void pullup_on(void)
|
|||
struct pxa2xx_udc_mach_info *mach = the_controller->mach;
|
||||
int on_level = !mach->gpio_pullup_inverted;
|
||||
|
||||
if (mach->gpio_pullup)
|
||||
if (gpio_is_valid(mach->gpio_pullup))
|
||||
gpio_set_value(mach->gpio_pullup, on_level);
|
||||
else if (mach->udc_command)
|
||||
mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
|
||||
|
|
@ -1000,7 +1000,7 @@ static int pxa25x_udc_pullup(struct usb_gadget *_gadget, int is_active)
|
|||
udc = container_of(_gadget, struct pxa25x_udc, gadget);
|
||||
|
||||
/* not all boards support pullup control */
|
||||
if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
|
||||
if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
udc->pullup = (is_active != 0);
|
||||
|
|
@ -1802,11 +1802,13 @@ pxa25x_udc_irq(int irq, void *_dev)
|
|||
USIR0 |= tmp;
|
||||
handled = 1;
|
||||
}
|
||||
#ifndef CONFIG_USB_PXA25X_SMALL
|
||||
if (usir1 & tmp) {
|
||||
handle_ep(&dev->ep[i+8]);
|
||||
USIR1 |= tmp;
|
||||
handled = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2160,7 +2162,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
|
|||
dev->dev = &pdev->dev;
|
||||
dev->mach = pdev->dev.platform_data;
|
||||
|
||||
if (dev->mach->gpio_vbus) {
|
||||
if (gpio_is_valid(dev->mach->gpio_vbus)) {
|
||||
if ((retval = gpio_request(dev->mach->gpio_vbus,
|
||||
"pxa25x_udc GPIO VBUS"))) {
|
||||
dev_dbg(&pdev->dev,
|
||||
|
|
@ -2173,7 +2175,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
|
|||
} else
|
||||
vbus_irq = 0;
|
||||
|
||||
if (dev->mach->gpio_pullup) {
|
||||
if (gpio_is_valid(dev->mach->gpio_pullup)) {
|
||||
if ((retval = gpio_request(dev->mach->gpio_pullup,
|
||||
"pca25x_udc GPIO PULLUP"))) {
|
||||
dev_dbg(&pdev->dev,
|
||||
|
|
@ -2256,10 +2258,10 @@ lubbock_fail0:
|
|||
#endif
|
||||
free_irq(irq, dev);
|
||||
err_irq1:
|
||||
if (dev->mach->gpio_pullup)
|
||||
if (gpio_is_valid(dev->mach->gpio_pullup))
|
||||
gpio_free(dev->mach->gpio_pullup);
|
||||
err_gpio_pullup:
|
||||
if (dev->mach->gpio_vbus)
|
||||
if (gpio_is_valid(dev->mach->gpio_vbus))
|
||||
gpio_free(dev->mach->gpio_vbus);
|
||||
err_gpio_vbus:
|
||||
clk_put(dev->clk);
|
||||
|
|
@ -2294,11 +2296,11 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
|
|||
free_irq(LUBBOCK_USB_IRQ, dev);
|
||||
}
|
||||
#endif
|
||||
if (dev->mach->gpio_vbus) {
|
||||
if (gpio_is_valid(dev->mach->gpio_vbus)) {
|
||||
free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev);
|
||||
gpio_free(dev->mach->gpio_vbus);
|
||||
}
|
||||
if (dev->mach->gpio_pullup)
|
||||
if (gpio_is_valid(dev->mach->gpio_pullup))
|
||||
gpio_free(dev->mach->gpio_pullup);
|
||||
|
||||
clk_put(dev->clk);
|
||||
|
|
@ -2329,7 +2331,7 @@ static int pxa25x_udc_suspend(struct platform_device *dev, pm_message_t state)
|
|||
struct pxa25x_udc *udc = platform_get_drvdata(dev);
|
||||
unsigned long flags;
|
||||
|
||||
if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
|
||||
if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command)
|
||||
WARNING("USB host won't detect disconnect!\n");
|
||||
udc->suspended = 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -442,6 +442,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
|
|||
|
||||
case OID_802_3_MAC_OPTIONS:
|
||||
pr_debug("%s: OID_802_3_MAC_OPTIONS\n", __func__);
|
||||
*outbuf = cpu_to_le32(0);
|
||||
retval = 0;
|
||||
break;
|
||||
|
||||
/* ieee802.3 statistics OIDs (table 4-4) */
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
#include <linux/ioport.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/timer.h>
|
||||
|
|
|
|||
|
|
@ -181,26 +181,27 @@ config USB_OHCI_HCD_PPC_SOC
|
|||
Enables support for the USB controller on the MPC52xx or
|
||||
STB03xxx processor chip. If unsure, say Y.
|
||||
|
||||
config USB_OHCI_HCD_PPC_OF
|
||||
bool "OHCI support for PPC USB controller on OF platform bus"
|
||||
depends on USB_OHCI_HCD && PPC_OF
|
||||
default y
|
||||
---help---
|
||||
Enables support for the USB controller PowerPC present on the
|
||||
OpenFirmware platform bus.
|
||||
|
||||
config USB_OHCI_HCD_PPC_OF_BE
|
||||
bool "Support big endian HC"
|
||||
depends on USB_OHCI_HCD_PPC_OF
|
||||
default y
|
||||
bool "OHCI support for OF platform bus (big endian)"
|
||||
depends on USB_OHCI_HCD && PPC_OF
|
||||
select USB_OHCI_BIG_ENDIAN_DESC
|
||||
select USB_OHCI_BIG_ENDIAN_MMIO
|
||||
---help---
|
||||
Enables support for big-endian USB controllers present on the
|
||||
OpenFirmware platform bus.
|
||||
|
||||
config USB_OHCI_HCD_PPC_OF_LE
|
||||
bool "Support little endian HC"
|
||||
depends on USB_OHCI_HCD_PPC_OF
|
||||
default n
|
||||
bool "OHCI support for OF platform bus (little endian)"
|
||||
depends on USB_OHCI_HCD && PPC_OF
|
||||
select USB_OHCI_LITTLE_ENDIAN
|
||||
---help---
|
||||
Enables support for little-endian USB controllers present on the
|
||||
OpenFirmware platform bus.
|
||||
|
||||
config USB_OHCI_HCD_PPC_OF
|
||||
bool
|
||||
depends on USB_OHCI_HCD && PPC_OF
|
||||
default USB_OHCI_HCD_PPC_OF_BE || USB_OHCI_HCD_PPC_OF_LE
|
||||
|
||||
config USB_OHCI_HCD_PCI
|
||||
bool "OHCI support for PCI-bus USB controllers"
|
||||
|
|
@ -337,10 +338,10 @@ config USB_R8A66597_HCD
|
|||
|
||||
config SUPERH_ON_CHIP_R8A66597
|
||||
boolean "Enable SuperH on-chip R8A66597 USB"
|
||||
depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723)
|
||||
depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7724)
|
||||
help
|
||||
This driver enables support for the on-chip R8A66597 in the
|
||||
SH7366 and SH7723 processors.
|
||||
SH7366, SH7723 and SH7724 processors.
|
||||
|
||||
config USB_WHCI_HCD
|
||||
tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)"
|
||||
|
|
|
|||
|
|
@ -113,6 +113,8 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
|
|||
.bus_resume = ehci_bus_resume,
|
||||
.relinquish_port = ehci_relinquish_port,
|
||||
.port_handed_over = ehci_port_handed_over,
|
||||
|
||||
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
|
||||
};
|
||||
|
||||
static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
|
||||
|
|
|
|||
|
|
@ -325,6 +325,8 @@ static const struct hc_driver ehci_fsl_hc_driver = {
|
|||
.bus_resume = ehci_bus_resume,
|
||||
.relinquish_port = ehci_relinquish_port,
|
||||
.port_handed_over = ehci_port_handed_over,
|
||||
|
||||
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
|
||||
};
|
||||
|
||||
static int ehci_fsl_drv_probe(struct platform_device *pdev)
|
||||
|
|
|
|||
|
|
@ -903,7 +903,8 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
|||
/* already started */
|
||||
break;
|
||||
case QH_STATE_IDLE:
|
||||
WARN_ON(1);
|
||||
/* QH might be waiting for a Clear-TT-Buffer */
|
||||
qh_completions(ehci, qh);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1003,6 +1004,8 @@ idle_timeout:
|
|||
schedule_timeout_uninterruptible(1);
|
||||
goto rescan;
|
||||
case QH_STATE_IDLE: /* fully unlinked */
|
||||
if (qh->clearing_tt)
|
||||
goto idle_timeout;
|
||||
if (list_empty (&qh->qtd_list)) {
|
||||
qh_put (qh);
|
||||
break;
|
||||
|
|
@ -1030,12 +1033,14 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
|
|||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
struct ehci_qh *qh;
|
||||
int eptype = usb_endpoint_type(&ep->desc);
|
||||
int epnum = usb_endpoint_num(&ep->desc);
|
||||
int is_out = usb_endpoint_dir_out(&ep->desc);
|
||||
unsigned long flags;
|
||||
|
||||
if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT)
|
||||
return;
|
||||
|
||||
rescan:
|
||||
spin_lock_irq(&ehci->lock);
|
||||
spin_lock_irqsave(&ehci->lock, flags);
|
||||
qh = ep->hcpriv;
|
||||
|
||||
/* For Bulk and Interrupt endpoints we maintain the toggle state
|
||||
|
|
@ -1044,29 +1049,24 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
|
|||
* the toggle bit in the QH.
|
||||
*/
|
||||
if (qh) {
|
||||
usb_settoggle(qh->dev, epnum, is_out, 0);
|
||||
if (!list_empty(&qh->qtd_list)) {
|
||||
WARN_ONCE(1, "clear_halt for a busy endpoint\n");
|
||||
} else if (qh->qh_state == QH_STATE_IDLE) {
|
||||
qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
|
||||
} else {
|
||||
/* It's not safe to write into the overlay area
|
||||
* while the QH is active. Unlink it first and
|
||||
* wait for the unlink to complete.
|
||||
} else if (qh->qh_state == QH_STATE_LINKED) {
|
||||
|
||||
/* The toggle value in the QH can't be updated
|
||||
* while the QH is active. Unlink it now;
|
||||
* re-linking will call qh_refresh().
|
||||
*/
|
||||
if (qh->qh_state == QH_STATE_LINKED) {
|
||||
if (eptype == USB_ENDPOINT_XFER_BULK) {
|
||||
unlink_async(ehci, qh);
|
||||
} else {
|
||||
intr_deschedule(ehci, qh);
|
||||
(void) qh_schedule(ehci, qh);
|
||||
}
|
||||
if (eptype == USB_ENDPOINT_XFER_BULK) {
|
||||
unlink_async(ehci, qh);
|
||||
} else {
|
||||
intr_deschedule(ehci, qh);
|
||||
(void) qh_schedule(ehci, qh);
|
||||
}
|
||||
spin_unlock_irq(&ehci->lock);
|
||||
schedule_timeout_uninterruptible(1);
|
||||
goto rescan;
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(&ehci->lock);
|
||||
spin_unlock_irqrestore(&ehci->lock, flags);
|
||||
}
|
||||
|
||||
static int ehci_get_frame (struct usb_hcd *hcd)
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = {
|
|||
#endif
|
||||
.relinquish_port = ehci_relinquish_port,
|
||||
.port_handed_over = ehci_port_handed_over,
|
||||
|
||||
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
|
||||
};
|
||||
|
||||
static int ixp4xx_ehci_probe(struct platform_device *pdev)
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ static int ehci_orion_setup(struct usb_hcd *hcd)
|
|||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
int retval;
|
||||
|
||||
ehci_reset(ehci);
|
||||
retval = ehci_halt(ehci);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
|
@ -118,7 +119,6 @@ static int ehci_orion_setup(struct usb_hcd *hcd)
|
|||
|
||||
hcd->has_tt = 1;
|
||||
|
||||
ehci_reset(ehci);
|
||||
ehci_port_power(ehci, 0);
|
||||
|
||||
return retval;
|
||||
|
|
@ -165,6 +165,8 @@ static const struct hc_driver ehci_orion_hc_driver = {
|
|||
.bus_resume = ehci_bus_resume,
|
||||
.relinquish_port = ehci_relinquish_port,
|
||||
.port_handed_over = ehci_port_handed_over,
|
||||
|
||||
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
|
||||
};
|
||||
|
||||
static void __init
|
||||
|
|
|
|||
|
|
@ -404,6 +404,8 @@ static const struct hc_driver ehci_pci_hc_driver = {
|
|||
.bus_resume = ehci_bus_resume,
|
||||
.relinquish_port = ehci_relinquish_port,
|
||||
.port_handed_over = ehci_port_handed_over,
|
||||
|
||||
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
|
|||
#endif
|
||||
.relinquish_port = ehci_relinquish_port,
|
||||
.port_handed_over = ehci_port_handed_over,
|
||||
|
||||
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,8 @@ static const struct hc_driver ps3_ehci_hc_driver = {
|
|||
#endif
|
||||
.relinquish_port = ehci_relinquish_port,
|
||||
.port_handed_over = ehci_port_handed_over,
|
||||
|
||||
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
|
||||
};
|
||||
|
||||
static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev)
|
||||
|
|
|
|||
|
|
@ -93,6 +93,22 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
|
|||
qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
|
||||
qh->hw_alt_next = EHCI_LIST_END(ehci);
|
||||
|
||||
/* Except for control endpoints, we make hardware maintain data
|
||||
* toggle (like OHCI) ... here (re)initialize the toggle in the QH,
|
||||
* and set the pseudo-toggle in udev. Only usb_clear_halt() will
|
||||
* ever clear it.
|
||||
*/
|
||||
if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
|
||||
unsigned is_out, epnum;
|
||||
|
||||
is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
|
||||
epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f;
|
||||
if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
|
||||
qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
|
||||
usb_settoggle (qh->dev, epnum, is_out, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
|
||||
wmb ();
|
||||
qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING);
|
||||
|
|
@ -123,6 +139,55 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static void qh_link_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
|
||||
|
||||
static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd,
|
||||
struct usb_host_endpoint *ep)
|
||||
{
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
struct ehci_qh *qh = ep->hcpriv;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ehci->lock, flags);
|
||||
qh->clearing_tt = 0;
|
||||
if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list)
|
||||
&& HC_IS_RUNNING(hcd->state))
|
||||
qh_link_async(ehci, qh);
|
||||
spin_unlock_irqrestore(&ehci->lock, flags);
|
||||
}
|
||||
|
||||
static void ehci_clear_tt_buffer(struct ehci_hcd *ehci, struct ehci_qh *qh,
|
||||
struct urb *urb, u32 token)
|
||||
{
|
||||
|
||||
/* If an async split transaction gets an error or is unlinked,
|
||||
* the TT buffer may be left in an indeterminate state. We
|
||||
* have to clear the TT buffer.
|
||||
*
|
||||
* Note: this routine is never called for Isochronous transfers.
|
||||
*/
|
||||
if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) {
|
||||
#ifdef DEBUG
|
||||
struct usb_device *tt = urb->dev->tt->hub;
|
||||
dev_dbg(&tt->dev,
|
||||
"clear tt buffer port %d, a%d ep%d t%08x\n",
|
||||
urb->dev->ttport, urb->dev->devnum,
|
||||
usb_pipeendpoint(urb->pipe), token);
|
||||
#endif /* DEBUG */
|
||||
if (!ehci_is_TDI(ehci)
|
||||
|| urb->dev->tt->hub !=
|
||||
ehci_to_hcd(ehci)->self.root_hub) {
|
||||
if (usb_hub_clear_tt_buffer(urb) == 0)
|
||||
qh->clearing_tt = 1;
|
||||
} else {
|
||||
|
||||
/* REVISIT ARC-derived cores don't clear the root
|
||||
* hub TT buffer in this way...
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int qtd_copy_status (
|
||||
struct ehci_hcd *ehci,
|
||||
struct urb *urb,
|
||||
|
|
@ -149,6 +214,14 @@ static int qtd_copy_status (
|
|||
if (token & QTD_STS_BABBLE) {
|
||||
/* FIXME "must" disable babbling device's port too */
|
||||
status = -EOVERFLOW;
|
||||
/* CERR nonzero + halt --> stall */
|
||||
} else if (QTD_CERR(token)) {
|
||||
status = -EPIPE;
|
||||
|
||||
/* In theory, more than one of the following bits can be set
|
||||
* since they are sticky and the transaction is retried.
|
||||
* Which to test first is rather arbitrary.
|
||||
*/
|
||||
} else if (token & QTD_STS_MMF) {
|
||||
/* fs/ls interrupt xfer missed the complete-split */
|
||||
status = -EPROTO;
|
||||
|
|
@ -157,21 +230,15 @@ static int qtd_copy_status (
|
|||
? -ENOSR /* hc couldn't read data */
|
||||
: -ECOMM; /* hc couldn't write data */
|
||||
} else if (token & QTD_STS_XACT) {
|
||||
/* timeout, bad crc, wrong PID, etc; retried */
|
||||
if (QTD_CERR (token))
|
||||
status = -EPIPE;
|
||||
else {
|
||||
ehci_dbg (ehci, "devpath %s ep%d%s 3strikes\n",
|
||||
urb->dev->devpath,
|
||||
usb_pipeendpoint (urb->pipe),
|
||||
usb_pipein (urb->pipe) ? "in" : "out");
|
||||
status = -EPROTO;
|
||||
}
|
||||
/* CERR nonzero + no errors + halt --> stall */
|
||||
} else if (QTD_CERR (token))
|
||||
status = -EPIPE;
|
||||
else /* unknown */
|
||||
/* timeout, bad CRC, wrong PID, etc */
|
||||
ehci_dbg(ehci, "devpath %s ep%d%s 3strikes\n",
|
||||
urb->dev->devpath,
|
||||
usb_pipeendpoint(urb->pipe),
|
||||
usb_pipein(urb->pipe) ? "in" : "out");
|
||||
status = -EPROTO;
|
||||
} else { /* unknown */
|
||||
status = -EPROTO;
|
||||
}
|
||||
|
||||
ehci_vdbg (ehci,
|
||||
"dev%d ep%d%s qtd token %08x --> status %d\n",
|
||||
|
|
@ -179,28 +246,6 @@ static int qtd_copy_status (
|
|||
usb_pipeendpoint (urb->pipe),
|
||||
usb_pipein (urb->pipe) ? "in" : "out",
|
||||
token, status);
|
||||
|
||||
/* if async CSPLIT failed, try cleaning out the TT buffer */
|
||||
if (status != -EPIPE
|
||||
&& urb->dev->tt
|
||||
&& !usb_pipeint(urb->pipe)
|
||||
&& ((token & QTD_STS_MMF) != 0
|
||||
|| QTD_CERR(token) == 0)
|
||||
&& (!ehci_is_TDI(ehci)
|
||||
|| urb->dev->tt->hub !=
|
||||
ehci_to_hcd(ehci)->self.root_hub)) {
|
||||
#ifdef DEBUG
|
||||
struct usb_device *tt = urb->dev->tt->hub;
|
||||
dev_dbg (&tt->dev,
|
||||
"clear tt buffer port %d, a%d ep%d t%08x\n",
|
||||
urb->dev->ttport, urb->dev->devnum,
|
||||
usb_pipeendpoint (urb->pipe), token);
|
||||
#endif /* DEBUG */
|
||||
/* REVISIT ARC-derived cores don't clear the root
|
||||
* hub TT buffer in this way...
|
||||
*/
|
||||
usb_hub_tt_clear_buffer (urb->dev, urb->pipe);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
|
|
@ -330,12 +375,11 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
|||
*/
|
||||
if ((token & QTD_STS_XACT) &&
|
||||
QTD_CERR(token) == 0 &&
|
||||
--qh->xacterrs > 0 &&
|
||||
++qh->xacterrs < QH_XACTERR_MAX &&
|
||||
!urb->unlinked) {
|
||||
ehci_dbg(ehci,
|
||||
"detected XactErr len %zu/%zu retry %d\n",
|
||||
qtd->length - QTD_LENGTH(token), qtd->length,
|
||||
QH_XACTERR_MAX - qh->xacterrs);
|
||||
qtd->length - QTD_LENGTH(token), qtd->length, qh->xacterrs);
|
||||
|
||||
/* reset the token in the qtd and the
|
||||
* qh overlay (which still contains
|
||||
|
|
@ -391,9 +435,16 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
|||
/* qh unlinked; token in overlay may be most current */
|
||||
if (state == QH_STATE_IDLE
|
||||
&& cpu_to_hc32(ehci, qtd->qtd_dma)
|
||||
== qh->hw_current)
|
||||
== qh->hw_current) {
|
||||
token = hc32_to_cpu(ehci, qh->hw_token);
|
||||
|
||||
/* An unlink may leave an incomplete
|
||||
* async transaction in the TT buffer.
|
||||
* We have to clear it.
|
||||
*/
|
||||
ehci_clear_tt_buffer(ehci, qh, urb, token);
|
||||
}
|
||||
|
||||
/* force halt for unlinked or blocked qh, so we'll
|
||||
* patch the qh later and so that completions can't
|
||||
* activate it while we "know" it's stopped.
|
||||
|
|
@ -419,6 +470,13 @@ halt:
|
|||
&& (qtd->hw_alt_next
|
||||
& EHCI_LIST_END(ehci)))
|
||||
last_status = -EINPROGRESS;
|
||||
|
||||
/* As part of low/full-speed endpoint-halt processing
|
||||
* we must clear the TT buffer (11.17.5).
|
||||
*/
|
||||
if (unlikely(last_status != -EINPROGRESS &&
|
||||
last_status != -EREMOTEIO))
|
||||
ehci_clear_tt_buffer(ehci, qh, urb, token);
|
||||
}
|
||||
|
||||
/* if we're removing something not at the queue head,
|
||||
|
|
@ -435,7 +493,7 @@ halt:
|
|||
last = qtd;
|
||||
|
||||
/* reinit the xacterr counter for the next qtd */
|
||||
qh->xacterrs = QH_XACTERR_MAX;
|
||||
qh->xacterrs = 0;
|
||||
}
|
||||
|
||||
/* last urb's completion might still need calling */
|
||||
|
|
@ -834,6 +892,7 @@ done:
|
|||
qh->qh_state = QH_STATE_IDLE;
|
||||
qh->hw_info1 = cpu_to_hc32(ehci, info1);
|
||||
qh->hw_info2 = cpu_to_hc32(ehci, info2);
|
||||
usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
|
||||
qh_refresh (ehci, qh);
|
||||
return qh;
|
||||
}
|
||||
|
|
@ -847,6 +906,10 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
|||
__hc32 dma = QH_NEXT(ehci, qh->qh_dma);
|
||||
struct ehci_qh *head;
|
||||
|
||||
/* Don't link a QH if there's a Clear-TT-Buffer pending */
|
||||
if (unlikely(qh->clearing_tt))
|
||||
return;
|
||||
|
||||
/* (re)start the async schedule? */
|
||||
head = ehci->async;
|
||||
timer_action_done (ehci, TIMER_ASYNC_OFF);
|
||||
|
|
@ -864,7 +927,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
|||
}
|
||||
}
|
||||
|
||||
/* clear halt and maybe recover from silicon quirk */
|
||||
/* clear halt and/or toggle; and maybe recover from silicon quirk */
|
||||
if (qh->qh_state == QH_STATE_IDLE)
|
||||
qh_refresh (ehci, qh);
|
||||
|
||||
|
|
@ -876,7 +939,8 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
|||
head->qh_next.qh = qh;
|
||||
head->hw_next = dma;
|
||||
|
||||
qh->xacterrs = QH_XACTERR_MAX;
|
||||
qh_get(qh);
|
||||
qh->xacterrs = 0;
|
||||
qh->qh_state = QH_STATE_LINKED;
|
||||
/* qtd completions reported later by interrupt */
|
||||
}
|
||||
|
|
@ -1016,7 +1080,7 @@ submit_async (
|
|||
* the HC and TT handle it when the TT has a buffer ready.
|
||||
*/
|
||||
if (likely (qh->qh_state == QH_STATE_IDLE))
|
||||
qh_link_async (ehci, qh_get (qh));
|
||||
qh_link_async(ehci, qh);
|
||||
done:
|
||||
spin_unlock_irqrestore (&ehci->lock, flags);
|
||||
if (unlikely (qh == NULL))
|
||||
|
|
@ -1051,8 +1115,6 @@ static void end_unlink_async (struct ehci_hcd *ehci)
|
|||
&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
|
||||
qh_link_async (ehci, qh);
|
||||
else {
|
||||
qh_put (qh); // refcount from async list
|
||||
|
||||
/* it's not free to turn the async schedule on/off; leave it
|
||||
* active but idle for a while once it empties.
|
||||
*/
|
||||
|
|
@ -1060,6 +1122,7 @@ static void end_unlink_async (struct ehci_hcd *ehci)
|
|||
&& ehci->async->qh_next.qh == NULL)
|
||||
timer_action (ehci, TIMER_ASYNC_OFF);
|
||||
}
|
||||
qh_put(qh); /* refcount from async list */
|
||||
|
||||
if (next) {
|
||||
ehci->reclaim = NULL;
|
||||
|
|
|
|||
|
|
@ -542,6 +542,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
|||
}
|
||||
}
|
||||
qh->qh_state = QH_STATE_LINKED;
|
||||
qh->xacterrs = 0;
|
||||
qh_get (qh);
|
||||
|
||||
/* update per-qh bandwidth for usbfs */
|
||||
|
|
@ -1619,11 +1620,14 @@ itd_complete (
|
|||
desc->status = -EPROTO;
|
||||
|
||||
/* HC need not update length with this error */
|
||||
if (!(t & EHCI_ISOC_BABBLE))
|
||||
desc->actual_length = EHCI_ITD_LENGTH (t);
|
||||
if (!(t & EHCI_ISOC_BABBLE)) {
|
||||
desc->actual_length = EHCI_ITD_LENGTH(t);
|
||||
urb->actual_length += desc->actual_length;
|
||||
}
|
||||
} else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) {
|
||||
desc->status = 0;
|
||||
desc->actual_length = EHCI_ITD_LENGTH (t);
|
||||
desc->actual_length = EHCI_ITD_LENGTH(t);
|
||||
urb->actual_length += desc->actual_length;
|
||||
} else {
|
||||
/* URB was too late */
|
||||
desc->status = -EXDEV;
|
||||
|
|
@ -2014,7 +2018,8 @@ sitd_complete (
|
|||
desc->status = -EPROTO;
|
||||
} else {
|
||||
desc->status = 0;
|
||||
desc->actual_length = desc->length - SITD_LENGTH (t);
|
||||
desc->actual_length = desc->length - SITD_LENGTH(t);
|
||||
urb->actual_length += desc->actual_length;
|
||||
}
|
||||
stream->depth -= stream->interval << 3;
|
||||
|
||||
|
|
|
|||
|
|
@ -354,7 +354,9 @@ struct ehci_qh {
|
|||
unsigned short period; /* polling interval */
|
||||
unsigned short start; /* where polling starts */
|
||||
#define NO_FRAME ((unsigned short)~0) /* pick new start */
|
||||
|
||||
struct usb_device *dev; /* access to TT */
|
||||
unsigned clearing_tt:1; /* Clear-TT-Buf in progress */
|
||||
} __attribute__ ((aligned (32)));
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -576,9 +576,7 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd)
|
|||
out_be16(&usb->fhci->regs->usb_event,
|
||||
usb->saved_msk);
|
||||
} else if (usb->port_status == FHCI_PORT_DISABLED) {
|
||||
if (fhci_ioports_check_bus_state(fhci) == 1 &&
|
||||
usb->port_status != FHCI_PORT_LOW &&
|
||||
usb->port_status != FHCI_PORT_FULL)
|
||||
if (fhci_ioports_check_bus_state(fhci) == 1)
|
||||
fhci_device_connected_interrupt(fhci);
|
||||
}
|
||||
usb_er &= ~USB_E_RESET_MASK;
|
||||
|
|
@ -605,9 +603,7 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd)
|
|||
}
|
||||
|
||||
if (usb_er & USB_E_IDLE_MASK) {
|
||||
if (usb->port_status == FHCI_PORT_DISABLED &&
|
||||
usb->port_status != FHCI_PORT_LOW &&
|
||||
usb->port_status != FHCI_PORT_FULL) {
|
||||
if (usb->port_status == FHCI_PORT_DISABLED) {
|
||||
usb_er &= ~USB_E_RESET_MASK;
|
||||
fhci_device_connected_interrupt(fhci);
|
||||
} else if (usb->port_status ==
|
||||
|
|
|
|||
|
|
@ -361,7 +361,7 @@ static int __devexit isp1760_plat_remove(struct platform_device *pdev)
|
|||
|
||||
static struct platform_driver isp1760_plat_driver = {
|
||||
.probe = isp1760_plat_probe,
|
||||
.remove = isp1760_plat_remove,
|
||||
.remove = __devexit_p(isp1760_plat_remove),
|
||||
.driver = {
|
||||
.name = "isp1760",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -282,6 +282,7 @@ static int ohci_omap_init(struct usb_hcd *hcd)
|
|||
static void ohci_omap_stop(struct usb_hcd *hcd)
|
||||
{
|
||||
dev_dbg(hcd->self.controller, "stopping USB Controller\n");
|
||||
ohci_stop(hcd);
|
||||
omap_ohci_clock_power(0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/timer.h>
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int
|
|||
{
|
||||
void *addr;
|
||||
u32 temp;
|
||||
u64 temp_64;
|
||||
|
||||
addr = &ir_set->irq_pending;
|
||||
temp = xhci_readl(xhci, addr);
|
||||
|
|
@ -200,25 +201,15 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int
|
|||
xhci_dbg(xhci, " WARN: %p: ir_set.rsvd = 0x%x\n",
|
||||
addr, (unsigned int)temp);
|
||||
|
||||
addr = &ir_set->erst_base[0];
|
||||
temp = xhci_readl(xhci, addr);
|
||||
xhci_dbg(xhci, " %p: ir_set.erst_base[0] = 0x%x\n",
|
||||
addr, (unsigned int) temp);
|
||||
addr = &ir_set->erst_base;
|
||||
temp_64 = xhci_read_64(xhci, addr);
|
||||
xhci_dbg(xhci, " %p: ir_set.erst_base = @%08llx\n",
|
||||
addr, temp_64);
|
||||
|
||||
addr = &ir_set->erst_base[1];
|
||||
temp = xhci_readl(xhci, addr);
|
||||
xhci_dbg(xhci, " %p: ir_set.erst_base[1] = 0x%x\n",
|
||||
addr, (unsigned int) temp);
|
||||
|
||||
addr = &ir_set->erst_dequeue[0];
|
||||
temp = xhci_readl(xhci, addr);
|
||||
xhci_dbg(xhci, " %p: ir_set.erst_dequeue[0] = 0x%x\n",
|
||||
addr, (unsigned int) temp);
|
||||
|
||||
addr = &ir_set->erst_dequeue[1];
|
||||
temp = xhci_readl(xhci, addr);
|
||||
xhci_dbg(xhci, " %p: ir_set.erst_dequeue[1] = 0x%x\n",
|
||||
addr, (unsigned int) temp);
|
||||
addr = &ir_set->erst_dequeue;
|
||||
temp_64 = xhci_read_64(xhci, addr);
|
||||
xhci_dbg(xhci, " %p: ir_set.erst_dequeue = @%08llx\n",
|
||||
addr, temp_64);
|
||||
}
|
||||
|
||||
void xhci_print_run_regs(struct xhci_hcd *xhci)
|
||||
|
|
@ -268,8 +259,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
|
|||
xhci_dbg(xhci, "Link TRB:\n");
|
||||
xhci_print_trb_offsets(xhci, trb);
|
||||
|
||||
address = trb->link.segment_ptr[0] +
|
||||
(((u64) trb->link.segment_ptr[1]) << 32);
|
||||
address = trb->link.segment_ptr;
|
||||
xhci_dbg(xhci, "Next ring segment DMA address = 0x%llx\n", address);
|
||||
|
||||
xhci_dbg(xhci, "Interrupter target = 0x%x\n",
|
||||
|
|
@ -282,8 +272,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
|
|||
(unsigned int) (trb->link.control & TRB_NO_SNOOP));
|
||||
break;
|
||||
case TRB_TYPE(TRB_TRANSFER):
|
||||
address = trb->trans_event.buffer[0] +
|
||||
(((u64) trb->trans_event.buffer[1]) << 32);
|
||||
address = trb->trans_event.buffer;
|
||||
/*
|
||||
* FIXME: look at flags to figure out if it's an address or if
|
||||
* the data is directly in the buffer field.
|
||||
|
|
@ -291,8 +280,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
|
|||
xhci_dbg(xhci, "DMA address or buffer contents= %llu\n", address);
|
||||
break;
|
||||
case TRB_TYPE(TRB_COMPLETION):
|
||||
address = trb->event_cmd.cmd_trb[0] +
|
||||
(((u64) trb->event_cmd.cmd_trb[1]) << 32);
|
||||
address = trb->event_cmd.cmd_trb;
|
||||
xhci_dbg(xhci, "Command TRB pointer = %llu\n", address);
|
||||
xhci_dbg(xhci, "Completion status = %u\n",
|
||||
(unsigned int) GET_COMP_CODE(trb->event_cmd.status));
|
||||
|
|
@ -328,8 +316,8 @@ void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg)
|
|||
for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
|
||||
trb = &seg->trbs[i];
|
||||
xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n", addr,
|
||||
(unsigned int) trb->link.segment_ptr[0],
|
||||
(unsigned int) trb->link.segment_ptr[1],
|
||||
lower_32_bits(trb->link.segment_ptr),
|
||||
upper_32_bits(trb->link.segment_ptr),
|
||||
(unsigned int) trb->link.intr_target,
|
||||
(unsigned int) trb->link.control);
|
||||
addr += sizeof(*trb);
|
||||
|
|
@ -386,8 +374,8 @@ void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
|
|||
entry = &erst->entries[i];
|
||||
xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n",
|
||||
(unsigned int) addr,
|
||||
(unsigned int) entry->seg_addr[0],
|
||||
(unsigned int) entry->seg_addr[1],
|
||||
lower_32_bits(entry->seg_addr),
|
||||
upper_32_bits(entry->seg_addr),
|
||||
(unsigned int) entry->seg_size,
|
||||
(unsigned int) entry->rsvd);
|
||||
addr += sizeof(*entry);
|
||||
|
|
@ -396,90 +384,147 @@ void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
|
|||
|
||||
void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci)
|
||||
{
|
||||
u32 val;
|
||||
u64 val;
|
||||
|
||||
val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[0]);
|
||||
xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = 0x%x\n", val);
|
||||
val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[1]);
|
||||
xhci_dbg(xhci, "// xHC command ring deq ptr high bits = 0x%x\n", val);
|
||||
val = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
|
||||
xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = @%08x\n",
|
||||
lower_32_bits(val));
|
||||
xhci_dbg(xhci, "// xHC command ring deq ptr high bits = @%08x\n",
|
||||
upper_32_bits(val));
|
||||
}
|
||||
|
||||
void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep)
|
||||
/* Print the last 32 bytes for 64-byte contexts */
|
||||
static void dbg_rsvd64(struct xhci_hcd *xhci, u64 *ctx, dma_addr_t dma)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx "
|
||||
"(dma) %#08llx - rsvd64[%d]\n",
|
||||
&ctx[4 + i], (unsigned long long)dma,
|
||||
ctx[4 + i], i);
|
||||
dma += 8;
|
||||
}
|
||||
}
|
||||
|
||||
void xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx)
|
||||
{
|
||||
/* Fields are 32 bits wide, DMA addresses are in bytes */
|
||||
int field_size = 32 / 8;
|
||||
int i;
|
||||
|
||||
struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
|
||||
dma_addr_t dma = ctx->dma + ((unsigned long)slot_ctx - (unsigned long)ctx);
|
||||
int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
|
||||
|
||||
xhci_dbg(xhci, "Slot Context:\n");
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info\n",
|
||||
&slot_ctx->dev_info,
|
||||
(unsigned long long)dma, slot_ctx->dev_info);
|
||||
dma += field_size;
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info2\n",
|
||||
&slot_ctx->dev_info2,
|
||||
(unsigned long long)dma, slot_ctx->dev_info2);
|
||||
dma += field_size;
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tt_info\n",
|
||||
&slot_ctx->tt_info,
|
||||
(unsigned long long)dma, slot_ctx->tt_info);
|
||||
dma += field_size;
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_state\n",
|
||||
&slot_ctx->dev_state,
|
||||
(unsigned long long)dma, slot_ctx->dev_state);
|
||||
dma += field_size;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
|
||||
&slot_ctx->reserved[i], (unsigned long long)dma,
|
||||
slot_ctx->reserved[i], i);
|
||||
dma += field_size;
|
||||
}
|
||||
|
||||
if (csz)
|
||||
dbg_rsvd64(xhci, (u64 *)slot_ctx, dma);
|
||||
}
|
||||
|
||||
void xhci_dbg_ep_ctx(struct xhci_hcd *xhci,
|
||||
struct xhci_container_ctx *ctx,
|
||||
unsigned int last_ep)
|
||||
{
|
||||
int i, j;
|
||||
int last_ep_ctx = 31;
|
||||
/* Fields are 32 bits wide, DMA addresses are in bytes */
|
||||
int field_size = 32 / 8;
|
||||
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n",
|
||||
&ctx->drop_flags, (unsigned long long)dma,
|
||||
ctx->drop_flags);
|
||||
dma += field_size;
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n",
|
||||
&ctx->add_flags, (unsigned long long)dma,
|
||||
ctx->add_flags);
|
||||
dma += field_size;
|
||||
for (i = 0; i > 6; ++i) {
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
|
||||
&ctx->rsvd[i], (unsigned long long)dma,
|
||||
ctx->rsvd[i], i);
|
||||
dma += field_size;
|
||||
}
|
||||
|
||||
xhci_dbg(xhci, "Slot Context:\n");
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info\n",
|
||||
&ctx->slot.dev_info,
|
||||
(unsigned long long)dma, ctx->slot.dev_info);
|
||||
dma += field_size;
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info2\n",
|
||||
&ctx->slot.dev_info2,
|
||||
(unsigned long long)dma, ctx->slot.dev_info2);
|
||||
dma += field_size;
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tt_info\n",
|
||||
&ctx->slot.tt_info,
|
||||
(unsigned long long)dma, ctx->slot.tt_info);
|
||||
dma += field_size;
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_state\n",
|
||||
&ctx->slot.dev_state,
|
||||
(unsigned long long)dma, ctx->slot.dev_state);
|
||||
dma += field_size;
|
||||
for (i = 0; i > 4; ++i) {
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
|
||||
&ctx->slot.reserved[i], (unsigned long long)dma,
|
||||
ctx->slot.reserved[i], i);
|
||||
dma += field_size;
|
||||
}
|
||||
int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
|
||||
|
||||
if (last_ep < 31)
|
||||
last_ep_ctx = last_ep + 1;
|
||||
for (i = 0; i < last_ep_ctx; ++i) {
|
||||
struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, ctx, i);
|
||||
dma_addr_t dma = ctx->dma +
|
||||
((unsigned long)ep_ctx - (unsigned long)ctx);
|
||||
|
||||
xhci_dbg(xhci, "Endpoint %02d Context:\n", i);
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n",
|
||||
&ctx->ep[i].ep_info,
|
||||
(unsigned long long)dma, ctx->ep[i].ep_info);
|
||||
&ep_ctx->ep_info,
|
||||
(unsigned long long)dma, ep_ctx->ep_info);
|
||||
dma += field_size;
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info2\n",
|
||||
&ctx->ep[i].ep_info2,
|
||||
(unsigned long long)dma, ctx->ep[i].ep_info2);
|
||||
dma += field_size;
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - deq[0]\n",
|
||||
&ctx->ep[i].deq[0],
|
||||
(unsigned long long)dma, ctx->ep[i].deq[0]);
|
||||
dma += field_size;
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - deq[1]\n",
|
||||
&ctx->ep[i].deq[1],
|
||||
(unsigned long long)dma, ctx->ep[i].deq[1]);
|
||||
&ep_ctx->ep_info2,
|
||||
(unsigned long long)dma, ep_ctx->ep_info2);
|
||||
dma += field_size;
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08llx - deq\n",
|
||||
&ep_ctx->deq,
|
||||
(unsigned long long)dma, ep_ctx->deq);
|
||||
dma += 2*field_size;
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tx_info\n",
|
||||
&ctx->ep[i].tx_info,
|
||||
(unsigned long long)dma, ctx->ep[i].tx_info);
|
||||
&ep_ctx->tx_info,
|
||||
(unsigned long long)dma, ep_ctx->tx_info);
|
||||
dma += field_size;
|
||||
for (j = 0; j < 3; ++j) {
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
|
||||
&ctx->ep[i].reserved[j],
|
||||
&ep_ctx->reserved[j],
|
||||
(unsigned long long)dma,
|
||||
ctx->ep[i].reserved[j], j);
|
||||
ep_ctx->reserved[j], j);
|
||||
dma += field_size;
|
||||
}
|
||||
|
||||
if (csz)
|
||||
dbg_rsvd64(xhci, (u64 *)ep_ctx, dma);
|
||||
}
|
||||
}
|
||||
|
||||
void xhci_dbg_ctx(struct xhci_hcd *xhci,
|
||||
struct xhci_container_ctx *ctx,
|
||||
unsigned int last_ep)
|
||||
{
|
||||
int i;
|
||||
/* Fields are 32 bits wide, DMA addresses are in bytes */
|
||||
int field_size = 32 / 8;
|
||||
struct xhci_slot_ctx *slot_ctx;
|
||||
dma_addr_t dma = ctx->dma;
|
||||
int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
|
||||
|
||||
if (ctx->type == XHCI_CTX_TYPE_INPUT) {
|
||||
struct xhci_input_control_ctx *ctrl_ctx =
|
||||
xhci_get_input_control_ctx(xhci, ctx);
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n",
|
||||
&ctrl_ctx->drop_flags, (unsigned long long)dma,
|
||||
ctrl_ctx->drop_flags);
|
||||
dma += field_size;
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n",
|
||||
&ctrl_ctx->add_flags, (unsigned long long)dma,
|
||||
ctrl_ctx->add_flags);
|
||||
dma += field_size;
|
||||
for (i = 0; i < 6; ++i) {
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd2[%d]\n",
|
||||
&ctrl_ctx->rsvd2[i], (unsigned long long)dma,
|
||||
ctrl_ctx->rsvd2[i], i);
|
||||
dma += field_size;
|
||||
}
|
||||
|
||||
if (csz)
|
||||
dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma);
|
||||
}
|
||||
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, ctx);
|
||||
xhci_dbg_slot_ctx(xhci, ctx);
|
||||
xhci_dbg_ep_ctx(xhci, ctx, last_ep);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,10 @@ int xhci_reset(struct xhci_hcd *xhci)
|
|||
u32 state;
|
||||
|
||||
state = xhci_readl(xhci, &xhci->op_regs->status);
|
||||
BUG_ON((state & STS_HALT) == 0);
|
||||
if ((state & STS_HALT) == 0) {
|
||||
xhci_warn(xhci, "Host controller not halted, aborting reset.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
xhci_dbg(xhci, "// Reset the HC\n");
|
||||
command = xhci_readl(xhci, &xhci->op_regs->command);
|
||||
|
|
@ -226,6 +229,7 @@ int xhci_init(struct usb_hcd *hcd)
|
|||
static void xhci_work(struct xhci_hcd *xhci)
|
||||
{
|
||||
u32 temp;
|
||||
u64 temp_64;
|
||||
|
||||
/*
|
||||
* Clear the op reg interrupt status first,
|
||||
|
|
@ -248,9 +252,9 @@ static void xhci_work(struct xhci_hcd *xhci)
|
|||
/* FIXME this should be a delayed service routine that clears the EHB */
|
||||
xhci_handle_event(xhci);
|
||||
|
||||
/* Clear the event handler busy flag; the event ring should be empty. */
|
||||
temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]);
|
||||
xhci_writel(xhci, temp & ~ERST_EHB, &xhci->ir_set->erst_dequeue[0]);
|
||||
/* Clear the event handler busy flag (RW1C); the event ring should be empty. */
|
||||
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
|
||||
xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue);
|
||||
/* Flush posted writes -- FIXME is this necessary? */
|
||||
xhci_readl(xhci, &xhci->ir_set->irq_pending);
|
||||
}
|
||||
|
|
@ -266,19 +270,34 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
|
|||
{
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
u32 temp, temp2;
|
||||
union xhci_trb *trb;
|
||||
|
||||
spin_lock(&xhci->lock);
|
||||
trb = xhci->event_ring->dequeue;
|
||||
/* Check if the xHC generated the interrupt, or the irq is shared */
|
||||
temp = xhci_readl(xhci, &xhci->op_regs->status);
|
||||
temp2 = xhci_readl(xhci, &xhci->ir_set->irq_pending);
|
||||
if (temp == 0xffffffff && temp2 == 0xffffffff)
|
||||
goto hw_died;
|
||||
|
||||
if (!(temp & STS_EINT) && !ER_IRQ_PENDING(temp2)) {
|
||||
spin_unlock(&xhci->lock);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
xhci_dbg(xhci, "op reg status = %08x\n", temp);
|
||||
xhci_dbg(xhci, "ir set irq_pending = %08x\n", temp2);
|
||||
xhci_dbg(xhci, "Event ring dequeue ptr:\n");
|
||||
xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n",
|
||||
(unsigned long long)xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb),
|
||||
lower_32_bits(trb->link.segment_ptr),
|
||||
upper_32_bits(trb->link.segment_ptr),
|
||||
(unsigned int) trb->link.intr_target,
|
||||
(unsigned int) trb->link.control);
|
||||
|
||||
if (temp & STS_FATAL) {
|
||||
xhci_warn(xhci, "WARNING: Host System Error\n");
|
||||
xhci_halt(xhci);
|
||||
hw_died:
|
||||
xhci_to_hcd(xhci)->state = HC_STATE_HALT;
|
||||
spin_unlock(&xhci->lock);
|
||||
return -ESHUTDOWN;
|
||||
|
|
@ -295,6 +314,7 @@ void xhci_event_ring_work(unsigned long arg)
|
|||
{
|
||||
unsigned long flags;
|
||||
int temp;
|
||||
u64 temp_64;
|
||||
struct xhci_hcd *xhci = (struct xhci_hcd *) arg;
|
||||
int i, j;
|
||||
|
||||
|
|
@ -311,9 +331,9 @@ void xhci_event_ring_work(unsigned long arg)
|
|||
xhci_dbg(xhci, "Event ring:\n");
|
||||
xhci_debug_segment(xhci, xhci->event_ring->deq_seg);
|
||||
xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
|
||||
temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]);
|
||||
temp &= ERST_PTR_MASK;
|
||||
xhci_dbg(xhci, "ERST deq = 0x%x\n", temp);
|
||||
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
|
||||
temp_64 &= ~ERST_PTR_MASK;
|
||||
xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64);
|
||||
xhci_dbg(xhci, "Command ring:\n");
|
||||
xhci_debug_segment(xhci, xhci->cmd_ring->deq_seg);
|
||||
xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
|
||||
|
|
@ -356,6 +376,7 @@ void xhci_event_ring_work(unsigned long arg)
|
|||
int xhci_run(struct usb_hcd *hcd)
|
||||
{
|
||||
u32 temp;
|
||||
u64 temp_64;
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
void (*doorbell)(struct xhci_hcd *) = NULL;
|
||||
|
||||
|
|
@ -382,6 +403,20 @@ int xhci_run(struct usb_hcd *hcd)
|
|||
add_timer(&xhci->event_ring_timer);
|
||||
#endif
|
||||
|
||||
xhci_dbg(xhci, "Command ring memory map follows:\n");
|
||||
xhci_debug_ring(xhci, xhci->cmd_ring);
|
||||
xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
|
||||
xhci_dbg_cmd_ptrs(xhci);
|
||||
|
||||
xhci_dbg(xhci, "ERST memory map follows:\n");
|
||||
xhci_dbg_erst(xhci, &xhci->erst);
|
||||
xhci_dbg(xhci, "Event ring:\n");
|
||||
xhci_debug_ring(xhci, xhci->event_ring);
|
||||
xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
|
||||
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
|
||||
temp_64 &= ~ERST_PTR_MASK;
|
||||
xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64);
|
||||
|
||||
xhci_dbg(xhci, "// Set the interrupt modulation register\n");
|
||||
temp = xhci_readl(xhci, &xhci->ir_set->irq_control);
|
||||
temp &= ~ER_IRQ_INTERVAL_MASK;
|
||||
|
|
@ -406,22 +441,6 @@ int xhci_run(struct usb_hcd *hcd)
|
|||
if (NUM_TEST_NOOPS > 0)
|
||||
doorbell = xhci_setup_one_noop(xhci);
|
||||
|
||||
xhci_dbg(xhci, "Command ring memory map follows:\n");
|
||||
xhci_debug_ring(xhci, xhci->cmd_ring);
|
||||
xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
|
||||
xhci_dbg_cmd_ptrs(xhci);
|
||||
|
||||
xhci_dbg(xhci, "ERST memory map follows:\n");
|
||||
xhci_dbg_erst(xhci, &xhci->erst);
|
||||
xhci_dbg(xhci, "Event ring:\n");
|
||||
xhci_debug_ring(xhci, xhci->event_ring);
|
||||
xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
|
||||
temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]);
|
||||
temp &= ERST_PTR_MASK;
|
||||
xhci_dbg(xhci, "ERST deq = 0x%x\n", temp);
|
||||
temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[1]);
|
||||
xhci_dbg(xhci, "ERST deq upper = 0x%x\n", temp);
|
||||
|
||||
temp = xhci_readl(xhci, &xhci->op_regs->command);
|
||||
temp |= (CMD_RUN);
|
||||
xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n",
|
||||
|
|
@ -601,10 +620,13 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
|
|||
goto exit;
|
||||
}
|
||||
if (usb_endpoint_xfer_control(&urb->ep->desc))
|
||||
ret = xhci_queue_ctrl_tx(xhci, mem_flags, urb,
|
||||
/* We have a spinlock and interrupts disabled, so we must pass
|
||||
* atomic context to this function, which may allocate memory.
|
||||
*/
|
||||
ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb,
|
||||
slot_id, ep_index);
|
||||
else if (usb_endpoint_xfer_bulk(&urb->ep->desc))
|
||||
ret = xhci_queue_bulk_tx(xhci, mem_flags, urb,
|
||||
ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
|
||||
slot_id, ep_index);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
|
@ -661,8 +683,12 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
|||
goto done;
|
||||
|
||||
xhci_dbg(xhci, "Cancel URB %p\n", urb);
|
||||
xhci_dbg(xhci, "Event ring:\n");
|
||||
xhci_debug_ring(xhci, xhci->event_ring);
|
||||
ep_index = xhci_get_endpoint_index(&urb->ep->desc);
|
||||
ep_ring = xhci->devs[urb->dev->slot_id]->ep_rings[ep_index];
|
||||
xhci_dbg(xhci, "Endpoint ring:\n");
|
||||
xhci_debug_ring(xhci, ep_ring);
|
||||
td = (struct xhci_td *) urb->hcpriv;
|
||||
|
||||
ep_ring->cancels_pending++;
|
||||
|
|
@ -696,7 +722,9 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
struct usb_host_endpoint *ep)
|
||||
{
|
||||
struct xhci_hcd *xhci;
|
||||
struct xhci_device_control *in_ctx;
|
||||
struct xhci_container_ctx *in_ctx, *out_ctx;
|
||||
struct xhci_input_control_ctx *ctrl_ctx;
|
||||
struct xhci_slot_ctx *slot_ctx;
|
||||
unsigned int last_ctx;
|
||||
unsigned int ep_index;
|
||||
struct xhci_ep_ctx *ep_ctx;
|
||||
|
|
@ -724,31 +752,34 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
}
|
||||
|
||||
in_ctx = xhci->devs[udev->slot_id]->in_ctx;
|
||||
out_ctx = xhci->devs[udev->slot_id]->out_ctx;
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
|
||||
ep_index = xhci_get_endpoint_index(&ep->desc);
|
||||
ep_ctx = &xhci->devs[udev->slot_id]->out_ctx->ep[ep_index];
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
|
||||
/* If the HC already knows the endpoint is disabled,
|
||||
* or the HCD has noted it is disabled, ignore this request
|
||||
*/
|
||||
if ((ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED ||
|
||||
in_ctx->drop_flags & xhci_get_endpoint_flag(&ep->desc)) {
|
||||
ctrl_ctx->drop_flags & xhci_get_endpoint_flag(&ep->desc)) {
|
||||
xhci_warn(xhci, "xHCI %s called with disabled ep %p\n",
|
||||
__func__, ep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
in_ctx->drop_flags |= drop_flag;
|
||||
new_drop_flags = in_ctx->drop_flags;
|
||||
ctrl_ctx->drop_flags |= drop_flag;
|
||||
new_drop_flags = ctrl_ctx->drop_flags;
|
||||
|
||||
in_ctx->add_flags = ~drop_flag;
|
||||
new_add_flags = in_ctx->add_flags;
|
||||
ctrl_ctx->add_flags = ~drop_flag;
|
||||
new_add_flags = ctrl_ctx->add_flags;
|
||||
|
||||
last_ctx = xhci_last_valid_endpoint(in_ctx->add_flags);
|
||||
last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags);
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
|
||||
/* Update the last valid endpoint context, if we deleted the last one */
|
||||
if ((in_ctx->slot.dev_info & LAST_CTX_MASK) > LAST_CTX(last_ctx)) {
|
||||
in_ctx->slot.dev_info &= ~LAST_CTX_MASK;
|
||||
in_ctx->slot.dev_info |= LAST_CTX(last_ctx);
|
||||
if ((slot_ctx->dev_info & LAST_CTX_MASK) > LAST_CTX(last_ctx)) {
|
||||
slot_ctx->dev_info &= ~LAST_CTX_MASK;
|
||||
slot_ctx->dev_info |= LAST_CTX(last_ctx);
|
||||
}
|
||||
new_slot_info = in_ctx->slot.dev_info;
|
||||
new_slot_info = slot_ctx->dev_info;
|
||||
|
||||
xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep);
|
||||
|
||||
|
|
@ -778,17 +809,22 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
struct usb_host_endpoint *ep)
|
||||
{
|
||||
struct xhci_hcd *xhci;
|
||||
struct xhci_device_control *in_ctx;
|
||||
struct xhci_container_ctx *in_ctx, *out_ctx;
|
||||
unsigned int ep_index;
|
||||
struct xhci_ep_ctx *ep_ctx;
|
||||
struct xhci_slot_ctx *slot_ctx;
|
||||
struct xhci_input_control_ctx *ctrl_ctx;
|
||||
u32 added_ctxs;
|
||||
unsigned int last_ctx;
|
||||
u32 new_add_flags, new_drop_flags, new_slot_info;
|
||||
int ret = 0;
|
||||
|
||||
ret = xhci_check_args(hcd, udev, ep, 1, __func__);
|
||||
if (ret <= 0)
|
||||
if (ret <= 0) {
|
||||
/* So we won't queue a reset ep command for a root hub */
|
||||
ep->hcpriv = NULL;
|
||||
return ret;
|
||||
}
|
||||
xhci = hcd_to_xhci(hcd);
|
||||
|
||||
added_ctxs = xhci_get_endpoint_flag(&ep->desc);
|
||||
|
|
@ -810,12 +846,14 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
}
|
||||
|
||||
in_ctx = xhci->devs[udev->slot_id]->in_ctx;
|
||||
out_ctx = xhci->devs[udev->slot_id]->out_ctx;
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
|
||||
ep_index = xhci_get_endpoint_index(&ep->desc);
|
||||
ep_ctx = &xhci->devs[udev->slot_id]->out_ctx->ep[ep_index];
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
|
||||
/* If the HCD has already noted the endpoint is enabled,
|
||||
* ignore this request.
|
||||
*/
|
||||
if (in_ctx->add_flags & xhci_get_endpoint_flag(&ep->desc)) {
|
||||
if (ctrl_ctx->add_flags & xhci_get_endpoint_flag(&ep->desc)) {
|
||||
xhci_warn(xhci, "xHCI %s called with enabled ep %p\n",
|
||||
__func__, ep);
|
||||
return 0;
|
||||
|
|
@ -833,8 +871,8 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
in_ctx->add_flags |= added_ctxs;
|
||||
new_add_flags = in_ctx->add_flags;
|
||||
ctrl_ctx->add_flags |= added_ctxs;
|
||||
new_add_flags = ctrl_ctx->add_flags;
|
||||
|
||||
/* If xhci_endpoint_disable() was called for this endpoint, but the
|
||||
* xHC hasn't been notified yet through the check_bandwidth() call,
|
||||
|
|
@ -842,14 +880,18 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
* descriptors. We must drop and re-add this endpoint, so we leave the
|
||||
* drop flags alone.
|
||||
*/
|
||||
new_drop_flags = in_ctx->drop_flags;
|
||||
new_drop_flags = ctrl_ctx->drop_flags;
|
||||
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
|
||||
/* Update the last valid endpoint context, if we just added one past */
|
||||
if ((in_ctx->slot.dev_info & LAST_CTX_MASK) < LAST_CTX(last_ctx)) {
|
||||
in_ctx->slot.dev_info &= ~LAST_CTX_MASK;
|
||||
in_ctx->slot.dev_info |= LAST_CTX(last_ctx);
|
||||
if ((slot_ctx->dev_info & LAST_CTX_MASK) < LAST_CTX(last_ctx)) {
|
||||
slot_ctx->dev_info &= ~LAST_CTX_MASK;
|
||||
slot_ctx->dev_info |= LAST_CTX(last_ctx);
|
||||
}
|
||||
new_slot_info = in_ctx->slot.dev_info;
|
||||
new_slot_info = slot_ctx->dev_info;
|
||||
|
||||
/* Store the usb_device pointer for later use */
|
||||
ep->hcpriv = udev;
|
||||
|
||||
xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x, new slot info = %#x\n",
|
||||
(unsigned int) ep->desc.bEndpointAddress,
|
||||
|
|
@ -860,9 +902,11 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void xhci_zero_in_ctx(struct xhci_virt_device *virt_dev)
|
||||
static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev)
|
||||
{
|
||||
struct xhci_input_control_ctx *ctrl_ctx;
|
||||
struct xhci_ep_ctx *ep_ctx;
|
||||
struct xhci_slot_ctx *slot_ctx;
|
||||
int i;
|
||||
|
||||
/* When a device's add flag and drop flag are zero, any subsequent
|
||||
|
|
@ -870,17 +914,18 @@ static void xhci_zero_in_ctx(struct xhci_virt_device *virt_dev)
|
|||
* untouched. Make sure we don't leave any old state in the input
|
||||
* endpoint contexts.
|
||||
*/
|
||||
virt_dev->in_ctx->drop_flags = 0;
|
||||
virt_dev->in_ctx->add_flags = 0;
|
||||
virt_dev->in_ctx->slot.dev_info &= ~LAST_CTX_MASK;
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
|
||||
ctrl_ctx->drop_flags = 0;
|
||||
ctrl_ctx->add_flags = 0;
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
|
||||
slot_ctx->dev_info &= ~LAST_CTX_MASK;
|
||||
/* Endpoint 0 is always valid */
|
||||
virt_dev->in_ctx->slot.dev_info |= LAST_CTX(1);
|
||||
slot_ctx->dev_info |= LAST_CTX(1);
|
||||
for (i = 1; i < 31; ++i) {
|
||||
ep_ctx = &virt_dev->in_ctx->ep[i];
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, i);
|
||||
ep_ctx->ep_info = 0;
|
||||
ep_ctx->ep_info2 = 0;
|
||||
ep_ctx->deq[0] = 0;
|
||||
ep_ctx->deq[1] = 0;
|
||||
ep_ctx->deq = 0;
|
||||
ep_ctx->tx_info = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -903,6 +948,8 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
unsigned long flags;
|
||||
struct xhci_hcd *xhci;
|
||||
struct xhci_virt_device *virt_dev;
|
||||
struct xhci_input_control_ctx *ctrl_ctx;
|
||||
struct xhci_slot_ctx *slot_ctx;
|
||||
|
||||
ret = xhci_check_args(hcd, udev, NULL, 0, __func__);
|
||||
if (ret <= 0)
|
||||
|
|
@ -918,16 +965,18 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
virt_dev = xhci->devs[udev->slot_id];
|
||||
|
||||
/* See section 4.6.6 - A0 = 1; A1 = D0 = D1 = 0 */
|
||||
virt_dev->in_ctx->add_flags |= SLOT_FLAG;
|
||||
virt_dev->in_ctx->add_flags &= ~EP0_FLAG;
|
||||
virt_dev->in_ctx->drop_flags &= ~SLOT_FLAG;
|
||||
virt_dev->in_ctx->drop_flags &= ~EP0_FLAG;
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
|
||||
ctrl_ctx->add_flags |= SLOT_FLAG;
|
||||
ctrl_ctx->add_flags &= ~EP0_FLAG;
|
||||
ctrl_ctx->drop_flags &= ~SLOT_FLAG;
|
||||
ctrl_ctx->drop_flags &= ~EP0_FLAG;
|
||||
xhci_dbg(xhci, "New Input Control Context:\n");
|
||||
xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma,
|
||||
LAST_CTX_TO_EP_NUM(virt_dev->in_ctx->slot.dev_info));
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
|
||||
xhci_dbg_ctx(xhci, virt_dev->in_ctx,
|
||||
LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx_dma,
|
||||
ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx->dma,
|
||||
udev->slot_id);
|
||||
if (ret < 0) {
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
|
|
@ -982,10 +1031,10 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
}
|
||||
|
||||
xhci_dbg(xhci, "Output context after successful config ep cmd:\n");
|
||||
xhci_dbg_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma,
|
||||
LAST_CTX_TO_EP_NUM(virt_dev->in_ctx->slot.dev_info));
|
||||
xhci_dbg_ctx(xhci, virt_dev->out_ctx,
|
||||
LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
|
||||
|
||||
xhci_zero_in_ctx(virt_dev);
|
||||
xhci_zero_in_ctx(xhci, virt_dev);
|
||||
/* Free any old rings */
|
||||
for (i = 1; i < 31; ++i) {
|
||||
if (virt_dev->new_ep_rings[i]) {
|
||||
|
|
@ -1023,7 +1072,67 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
virt_dev->new_ep_rings[i] = NULL;
|
||||
}
|
||||
}
|
||||
xhci_zero_in_ctx(virt_dev);
|
||||
xhci_zero_in_ctx(xhci, virt_dev);
|
||||
}
|
||||
|
||||
/* Deal with stalled endpoints. The core should have sent the control message
|
||||
* to clear the halt condition. However, we need to make the xHCI hardware
|
||||
* reset its sequence number, since a device will expect a sequence number of
|
||||
* zero after the halt condition is cleared.
|
||||
* Context: in_interrupt
|
||||
*/
|
||||
void xhci_endpoint_reset(struct usb_hcd *hcd,
|
||||
struct usb_host_endpoint *ep)
|
||||
{
|
||||
struct xhci_hcd *xhci;
|
||||
struct usb_device *udev;
|
||||
unsigned int ep_index;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
struct xhci_dequeue_state deq_state;
|
||||
struct xhci_ring *ep_ring;
|
||||
|
||||
xhci = hcd_to_xhci(hcd);
|
||||
udev = (struct usb_device *) ep->hcpriv;
|
||||
/* Called with a root hub endpoint (or an endpoint that wasn't added
|
||||
* with xhci_add_endpoint()
|
||||
*/
|
||||
if (!ep->hcpriv)
|
||||
return;
|
||||
ep_index = xhci_get_endpoint_index(&ep->desc);
|
||||
ep_ring = xhci->devs[udev->slot_id]->ep_rings[ep_index];
|
||||
if (!ep_ring->stopped_td) {
|
||||
xhci_dbg(xhci, "Endpoint 0x%x not halted, refusing to reset.\n",
|
||||
ep->desc.bEndpointAddress);
|
||||
return;
|
||||
}
|
||||
|
||||
xhci_dbg(xhci, "Queueing reset endpoint command\n");
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
ret = xhci_queue_reset_ep(xhci, udev->slot_id, ep_index);
|
||||
/*
|
||||
* Can't change the ring dequeue pointer until it's transitioned to the
|
||||
* stopped state, which is only upon a successful reset endpoint
|
||||
* command. Better hope that last command worked!
|
||||
*/
|
||||
if (!ret) {
|
||||
xhci_dbg(xhci, "Cleaning up stalled endpoint ring\n");
|
||||
/* We need to move the HW's dequeue pointer past this TD,
|
||||
* or it will attempt to resend it on the next doorbell ring.
|
||||
*/
|
||||
xhci_find_new_dequeue_state(xhci, udev->slot_id,
|
||||
ep_index, ep_ring->stopped_td, &deq_state);
|
||||
xhci_dbg(xhci, "Queueing new dequeue state\n");
|
||||
xhci_queue_new_dequeue_state(xhci, ep_ring,
|
||||
udev->slot_id,
|
||||
ep_index, &deq_state);
|
||||
kfree(ep_ring->stopped_td);
|
||||
xhci_ring_cmd_db(xhci);
|
||||
}
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
|
||||
if (ret)
|
||||
xhci_warn(xhci, "FIXME allocate a new ring segment\n");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1120,7 +1229,9 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
struct xhci_virt_device *virt_dev;
|
||||
int ret = 0;
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
u32 temp;
|
||||
struct xhci_slot_ctx *slot_ctx;
|
||||
struct xhci_input_control_ctx *ctrl_ctx;
|
||||
u64 temp_64;
|
||||
|
||||
if (!udev->slot_id) {
|
||||
xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id);
|
||||
|
|
@ -1133,10 +1244,12 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
if (!udev->config)
|
||||
xhci_setup_addressable_virt_dev(xhci, udev);
|
||||
/* Otherwise, assume the core has the device configured how it wants */
|
||||
xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
|
||||
xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
ret = xhci_queue_address_device(xhci, virt_dev->in_ctx_dma,
|
||||
udev->slot_id);
|
||||
ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma,
|
||||
udev->slot_id);
|
||||
if (ret) {
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
|
||||
|
|
@ -1176,41 +1289,37 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
default:
|
||||
xhci_err(xhci, "ERROR: unexpected command completion "
|
||||
"code 0x%x.\n", virt_dev->cmd_status);
|
||||
xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id);
|
||||
xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
temp = xhci_readl(xhci, &xhci->op_regs->dcbaa_ptr[0]);
|
||||
xhci_dbg(xhci, "Op regs DCBAA ptr[0] = %#08x\n", temp);
|
||||
temp = xhci_readl(xhci, &xhci->op_regs->dcbaa_ptr[1]);
|
||||
xhci_dbg(xhci, "Op regs DCBAA ptr[1] = %#08x\n", temp);
|
||||
xhci_dbg(xhci, "Slot ID %d dcbaa entry[0] @%p = %#08x\n",
|
||||
temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
|
||||
xhci_dbg(xhci, "Op regs DCBAA ptr = %#016llx\n", temp_64);
|
||||
xhci_dbg(xhci, "Slot ID %d dcbaa entry @%p = %#016llx\n",
|
||||
udev->slot_id,
|
||||
&xhci->dcbaa->dev_context_ptrs[2*udev->slot_id],
|
||||
xhci->dcbaa->dev_context_ptrs[2*udev->slot_id]);
|
||||
xhci_dbg(xhci, "Slot ID %d dcbaa entry[1] @%p = %#08x\n",
|
||||
udev->slot_id,
|
||||
&xhci->dcbaa->dev_context_ptrs[2*udev->slot_id+1],
|
||||
xhci->dcbaa->dev_context_ptrs[2*udev->slot_id+1]);
|
||||
&xhci->dcbaa->dev_context_ptrs[udev->slot_id],
|
||||
(unsigned long long)
|
||||
xhci->dcbaa->dev_context_ptrs[udev->slot_id]);
|
||||
xhci_dbg(xhci, "Output Context DMA address = %#08llx\n",
|
||||
(unsigned long long)virt_dev->out_ctx_dma);
|
||||
(unsigned long long)virt_dev->out_ctx->dma);
|
||||
xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
|
||||
xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma, 2);
|
||||
xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
|
||||
xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id);
|
||||
xhci_dbg_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, 2);
|
||||
xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2);
|
||||
/*
|
||||
* USB core uses address 1 for the roothubs, so we add one to the
|
||||
* address given back to us by the HC.
|
||||
*/
|
||||
udev->devnum = (virt_dev->out_ctx->slot.dev_state & DEV_ADDR_MASK) + 1;
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
|
||||
udev->devnum = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1;
|
||||
/* Zero the input context control for later use */
|
||||
virt_dev->in_ctx->add_flags = 0;
|
||||
virt_dev->in_ctx->drop_flags = 0;
|
||||
/* Mirror flags in the output context for future ep enable/disable */
|
||||
virt_dev->out_ctx->add_flags = SLOT_FLAG | EP0_FLAG;
|
||||
virt_dev->out_ctx->drop_flags = 0;
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
|
||||
ctrl_ctx->add_flags = 0;
|
||||
ctrl_ctx->drop_flags = 0;
|
||||
|
||||
xhci_dbg(xhci, "Device address = %d\n", udev->devnum);
|
||||
/* XXX Meh, not sure if anyone else but choose_address uses this. */
|
||||
|
|
@ -1252,7 +1361,6 @@ static int __init xhci_hcd_init(void)
|
|||
/* xhci_device_control has eight fields, and also
|
||||
* embeds one xhci_slot_ctx and 31 xhci_ep_ctx
|
||||
*/
|
||||
BUILD_BUG_ON(sizeof(struct xhci_device_control) != (8+8+8*31)*32/8);
|
||||
BUILD_BUG_ON(sizeof(struct xhci_stream_ctx) != 4*32/8);
|
||||
BUILD_BUG_ON(sizeof(union xhci_trb) != 4*32/8);
|
||||
BUILD_BUG_ON(sizeof(struct xhci_erst_entry) != 4*32/8);
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev,
|
|||
return;
|
||||
prev->next = next;
|
||||
if (link_trbs) {
|
||||
prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr[0] = next->dma;
|
||||
prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = next->dma;
|
||||
|
||||
/* Set the last TRB in the segment to have a TRB type ID of Link TRB */
|
||||
val = prev->trbs[TRBS_PER_SEGMENT-1].link.control;
|
||||
|
|
@ -189,6 +189,63 @@ fail:
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define CTX_SIZE(_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32)
|
||||
|
||||
struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci,
|
||||
int type, gfp_t flags)
|
||||
{
|
||||
struct xhci_container_ctx *ctx = kzalloc(sizeof(*ctx), flags);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
BUG_ON((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT));
|
||||
ctx->type = type;
|
||||
ctx->size = HCC_64BYTE_CONTEXT(xhci->hcc_params) ? 2048 : 1024;
|
||||
if (type == XHCI_CTX_TYPE_INPUT)
|
||||
ctx->size += CTX_SIZE(xhci->hcc_params);
|
||||
|
||||
ctx->bytes = dma_pool_alloc(xhci->device_pool, flags, &ctx->dma);
|
||||
memset(ctx->bytes, 0, ctx->size);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void xhci_free_container_ctx(struct xhci_hcd *xhci,
|
||||
struct xhci_container_ctx *ctx)
|
||||
{
|
||||
dma_pool_free(xhci->device_pool, ctx->bytes, ctx->dma);
|
||||
kfree(ctx);
|
||||
}
|
||||
|
||||
struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci,
|
||||
struct xhci_container_ctx *ctx)
|
||||
{
|
||||
BUG_ON(ctx->type != XHCI_CTX_TYPE_INPUT);
|
||||
return (struct xhci_input_control_ctx *)ctx->bytes;
|
||||
}
|
||||
|
||||
struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci,
|
||||
struct xhci_container_ctx *ctx)
|
||||
{
|
||||
if (ctx->type == XHCI_CTX_TYPE_DEVICE)
|
||||
return (struct xhci_slot_ctx *)ctx->bytes;
|
||||
|
||||
return (struct xhci_slot_ctx *)
|
||||
(ctx->bytes + CTX_SIZE(xhci->hcc_params));
|
||||
}
|
||||
|
||||
struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci,
|
||||
struct xhci_container_ctx *ctx,
|
||||
unsigned int ep_index)
|
||||
{
|
||||
/* increment ep index by offset of start of ep ctx array */
|
||||
ep_index++;
|
||||
if (ctx->type == XHCI_CTX_TYPE_INPUT)
|
||||
ep_index++;
|
||||
|
||||
return (struct xhci_ep_ctx *)
|
||||
(ctx->bytes + (ep_index * CTX_SIZE(xhci->hcc_params)));
|
||||
}
|
||||
|
||||
/* All the xhci_tds in the ring's TD list should be freed at this point */
|
||||
void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
|
||||
{
|
||||
|
|
@ -200,8 +257,7 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
|
|||
return;
|
||||
|
||||
dev = xhci->devs[slot_id];
|
||||
xhci->dcbaa->dev_context_ptrs[2*slot_id] = 0;
|
||||
xhci->dcbaa->dev_context_ptrs[2*slot_id + 1] = 0;
|
||||
xhci->dcbaa->dev_context_ptrs[slot_id] = 0;
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
|
|
@ -210,11 +266,10 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
|
|||
xhci_ring_free(xhci, dev->ep_rings[i]);
|
||||
|
||||
if (dev->in_ctx)
|
||||
dma_pool_free(xhci->device_pool,
|
||||
dev->in_ctx, dev->in_ctx_dma);
|
||||
xhci_free_container_ctx(xhci, dev->in_ctx);
|
||||
if (dev->out_ctx)
|
||||
dma_pool_free(xhci->device_pool,
|
||||
dev->out_ctx, dev->out_ctx_dma);
|
||||
xhci_free_container_ctx(xhci, dev->out_ctx);
|
||||
|
||||
kfree(xhci->devs[slot_id]);
|
||||
xhci->devs[slot_id] = 0;
|
||||
}
|
||||
|
|
@ -222,7 +277,6 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
|
|||
int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
|
||||
struct usb_device *udev, gfp_t flags)
|
||||
{
|
||||
dma_addr_t dma;
|
||||
struct xhci_virt_device *dev;
|
||||
|
||||
/* Slot ID 0 is reserved */
|
||||
|
|
@ -236,23 +290,21 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
|
|||
return 0;
|
||||
dev = xhci->devs[slot_id];
|
||||
|
||||
/* Allocate the (output) device context that will be used in the HC */
|
||||
dev->out_ctx = dma_pool_alloc(xhci->device_pool, flags, &dma);
|
||||
/* Allocate the (output) device context that will be used in the HC. */
|
||||
dev->out_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_DEVICE, flags);
|
||||
if (!dev->out_ctx)
|
||||
goto fail;
|
||||
dev->out_ctx_dma = dma;
|
||||
|
||||
xhci_dbg(xhci, "Slot %d output ctx = 0x%llx (dma)\n", slot_id,
|
||||
(unsigned long long)dma);
|
||||
memset(dev->out_ctx, 0, sizeof(*dev->out_ctx));
|
||||
(unsigned long long)dev->out_ctx->dma);
|
||||
|
||||
/* Allocate the (input) device context for address device command */
|
||||
dev->in_ctx = dma_pool_alloc(xhci->device_pool, flags, &dma);
|
||||
dev->in_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_INPUT, flags);
|
||||
if (!dev->in_ctx)
|
||||
goto fail;
|
||||
dev->in_ctx_dma = dma;
|
||||
|
||||
xhci_dbg(xhci, "Slot %d input ctx = 0x%llx (dma)\n", slot_id,
|
||||
(unsigned long long)dma);
|
||||
memset(dev->in_ctx, 0, sizeof(*dev->in_ctx));
|
||||
(unsigned long long)dev->in_ctx->dma);
|
||||
|
||||
/* Allocate endpoint 0 ring */
|
||||
dev->ep_rings[0] = xhci_ring_alloc(xhci, 1, true, flags);
|
||||
|
|
@ -261,17 +313,12 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
|
|||
|
||||
init_completion(&dev->cmd_completion);
|
||||
|
||||
/*
|
||||
* Point to output device context in dcbaa; skip the output control
|
||||
* context, which is eight 32 bit fields (or 32 bytes long)
|
||||
*/
|
||||
xhci->dcbaa->dev_context_ptrs[2*slot_id] =
|
||||
(u32) dev->out_ctx_dma + (32);
|
||||
/* Point to output device context in dcbaa. */
|
||||
xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma;
|
||||
xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n",
|
||||
slot_id,
|
||||
&xhci->dcbaa->dev_context_ptrs[2*slot_id],
|
||||
(unsigned long long)dev->out_ctx_dma);
|
||||
xhci->dcbaa->dev_context_ptrs[2*slot_id + 1] = 0;
|
||||
&xhci->dcbaa->dev_context_ptrs[slot_id],
|
||||
(unsigned long long) xhci->dcbaa->dev_context_ptrs[slot_id]);
|
||||
|
||||
return 1;
|
||||
fail:
|
||||
|
|
@ -285,6 +332,8 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
|
|||
struct xhci_virt_device *dev;
|
||||
struct xhci_ep_ctx *ep0_ctx;
|
||||
struct usb_device *top_dev;
|
||||
struct xhci_slot_ctx *slot_ctx;
|
||||
struct xhci_input_control_ctx *ctrl_ctx;
|
||||
|
||||
dev = xhci->devs[udev->slot_id];
|
||||
/* Slot ID 0 is reserved */
|
||||
|
|
@ -293,27 +342,29 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
|
|||
udev->slot_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
ep0_ctx = &dev->in_ctx->ep[0];
|
||||
ep0_ctx = xhci_get_ep_ctx(xhci, dev->in_ctx, 0);
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, dev->in_ctx);
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, dev->in_ctx);
|
||||
|
||||
/* 2) New slot context and endpoint 0 context are valid*/
|
||||
dev->in_ctx->add_flags = SLOT_FLAG | EP0_FLAG;
|
||||
ctrl_ctx->add_flags = SLOT_FLAG | EP0_FLAG;
|
||||
|
||||
/* 3) Only the control endpoint is valid - one endpoint context */
|
||||
dev->in_ctx->slot.dev_info |= LAST_CTX(1);
|
||||
slot_ctx->dev_info |= LAST_CTX(1);
|
||||
|
||||
switch (udev->speed) {
|
||||
case USB_SPEED_SUPER:
|
||||
dev->in_ctx->slot.dev_info |= (u32) udev->route;
|
||||
dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_SS;
|
||||
slot_ctx->dev_info |= (u32) udev->route;
|
||||
slot_ctx->dev_info |= (u32) SLOT_SPEED_SS;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_HS;
|
||||
slot_ctx->dev_info |= (u32) SLOT_SPEED_HS;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_FS;
|
||||
slot_ctx->dev_info |= (u32) SLOT_SPEED_FS;
|
||||
break;
|
||||
case USB_SPEED_LOW:
|
||||
dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_LS;
|
||||
slot_ctx->dev_info |= (u32) SLOT_SPEED_LS;
|
||||
break;
|
||||
case USB_SPEED_VARIABLE:
|
||||
xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
|
||||
|
|
@ -327,7 +378,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
|
|||
for (top_dev = udev; top_dev->parent && top_dev->parent->parent;
|
||||
top_dev = top_dev->parent)
|
||||
/* Found device below root hub */;
|
||||
dev->in_ctx->slot.dev_info2 |= (u32) ROOT_HUB_PORT(top_dev->portnum);
|
||||
slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(top_dev->portnum);
|
||||
xhci_dbg(xhci, "Set root hub portnum to %d\n", top_dev->portnum);
|
||||
|
||||
/* Is this a LS/FS device under a HS hub? */
|
||||
|
|
@ -337,8 +388,8 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
|
|||
*/
|
||||
if ((udev->speed == USB_SPEED_LOW || udev->speed == USB_SPEED_FULL) &&
|
||||
udev->tt) {
|
||||
dev->in_ctx->slot.tt_info = udev->tt->hub->slot_id;
|
||||
dev->in_ctx->slot.tt_info |= udev->ttport << 8;
|
||||
slot_ctx->tt_info = udev->tt->hub->slot_id;
|
||||
slot_ctx->tt_info |= udev->ttport << 8;
|
||||
}
|
||||
xhci_dbg(xhci, "udev->tt = %p\n", udev->tt);
|
||||
xhci_dbg(xhci, "udev->ttport = 0x%x\n", udev->ttport);
|
||||
|
|
@ -360,10 +411,9 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
|
|||
ep0_ctx->ep_info2 |= MAX_BURST(0);
|
||||
ep0_ctx->ep_info2 |= ERROR_COUNT(3);
|
||||
|
||||
ep0_ctx->deq[0] =
|
||||
ep0_ctx->deq =
|
||||
dev->ep_rings[0]->first_seg->dma;
|
||||
ep0_ctx->deq[0] |= dev->ep_rings[0]->cycle_state;
|
||||
ep0_ctx->deq[1] = 0;
|
||||
ep0_ctx->deq |= dev->ep_rings[0]->cycle_state;
|
||||
|
||||
/* Steps 7 and 8 were done in xhci_alloc_virt_device() */
|
||||
|
||||
|
|
@ -470,25 +520,26 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
|
|||
unsigned int max_burst;
|
||||
|
||||
ep_index = xhci_get_endpoint_index(&ep->desc);
|
||||
ep_ctx = &virt_dev->in_ctx->ep[ep_index];
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
|
||||
|
||||
/* Set up the endpoint ring */
|
||||
virt_dev->new_ep_rings[ep_index] = xhci_ring_alloc(xhci, 1, true, mem_flags);
|
||||
if (!virt_dev->new_ep_rings[ep_index])
|
||||
return -ENOMEM;
|
||||
ep_ring = virt_dev->new_ep_rings[ep_index];
|
||||
ep_ctx->deq[0] = ep_ring->first_seg->dma | ep_ring->cycle_state;
|
||||
ep_ctx->deq[1] = 0;
|
||||
ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state;
|
||||
|
||||
ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep);
|
||||
|
||||
/* FIXME dig Mult and streams info out of ep companion desc */
|
||||
|
||||
/* Allow 3 retries for everything but isoc */
|
||||
/* Allow 3 retries for everything but isoc;
|
||||
* error count = 0 means infinite retries.
|
||||
*/
|
||||
if (!usb_endpoint_xfer_isoc(&ep->desc))
|
||||
ep_ctx->ep_info2 = ERROR_COUNT(3);
|
||||
else
|
||||
ep_ctx->ep_info2 = ERROR_COUNT(0);
|
||||
ep_ctx->ep_info2 = ERROR_COUNT(1);
|
||||
|
||||
ep_ctx->ep_info2 |= xhci_get_endpoint_type(udev, ep);
|
||||
|
||||
|
|
@ -498,7 +549,12 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
|
|||
max_packet = ep->desc.wMaxPacketSize;
|
||||
ep_ctx->ep_info2 |= MAX_PACKET(max_packet);
|
||||
/* dig out max burst from ep companion desc */
|
||||
max_packet = ep->ss_ep_comp->desc.bMaxBurst;
|
||||
if (!ep->ss_ep_comp) {
|
||||
xhci_warn(xhci, "WARN no SS endpoint companion descriptor.\n");
|
||||
max_packet = 0;
|
||||
} else {
|
||||
max_packet = ep->ss_ep_comp->desc.bMaxBurst;
|
||||
}
|
||||
ep_ctx->ep_info2 |= MAX_BURST(max_packet);
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
|
|
@ -531,18 +587,114 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci,
|
|||
struct xhci_ep_ctx *ep_ctx;
|
||||
|
||||
ep_index = xhci_get_endpoint_index(&ep->desc);
|
||||
ep_ctx = &virt_dev->in_ctx->ep[ep_index];
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
|
||||
|
||||
ep_ctx->ep_info = 0;
|
||||
ep_ctx->ep_info2 = 0;
|
||||
ep_ctx->deq[0] = 0;
|
||||
ep_ctx->deq[1] = 0;
|
||||
ep_ctx->deq = 0;
|
||||
ep_ctx->tx_info = 0;
|
||||
/* Don't free the endpoint ring until the set interface or configuration
|
||||
* request succeeds.
|
||||
*/
|
||||
}
|
||||
|
||||
/* Set up the scratchpad buffer array and scratchpad buffers, if needed. */
|
||||
static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
|
||||
{
|
||||
int i;
|
||||
struct device *dev = xhci_to_hcd(xhci)->self.controller;
|
||||
int num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2);
|
||||
|
||||
xhci_dbg(xhci, "Allocating %d scratchpad buffers\n", num_sp);
|
||||
|
||||
if (!num_sp)
|
||||
return 0;
|
||||
|
||||
xhci->scratchpad = kzalloc(sizeof(*xhci->scratchpad), flags);
|
||||
if (!xhci->scratchpad)
|
||||
goto fail_sp;
|
||||
|
||||
xhci->scratchpad->sp_array =
|
||||
pci_alloc_consistent(to_pci_dev(dev),
|
||||
num_sp * sizeof(u64),
|
||||
&xhci->scratchpad->sp_dma);
|
||||
if (!xhci->scratchpad->sp_array)
|
||||
goto fail_sp2;
|
||||
|
||||
xhci->scratchpad->sp_buffers = kzalloc(sizeof(void *) * num_sp, flags);
|
||||
if (!xhci->scratchpad->sp_buffers)
|
||||
goto fail_sp3;
|
||||
|
||||
xhci->scratchpad->sp_dma_buffers =
|
||||
kzalloc(sizeof(dma_addr_t) * num_sp, flags);
|
||||
|
||||
if (!xhci->scratchpad->sp_dma_buffers)
|
||||
goto fail_sp4;
|
||||
|
||||
xhci->dcbaa->dev_context_ptrs[0] = xhci->scratchpad->sp_dma;
|
||||
for (i = 0; i < num_sp; i++) {
|
||||
dma_addr_t dma;
|
||||
void *buf = pci_alloc_consistent(to_pci_dev(dev),
|
||||
xhci->page_size, &dma);
|
||||
if (!buf)
|
||||
goto fail_sp5;
|
||||
|
||||
xhci->scratchpad->sp_array[i] = dma;
|
||||
xhci->scratchpad->sp_buffers[i] = buf;
|
||||
xhci->scratchpad->sp_dma_buffers[i] = dma;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail_sp5:
|
||||
for (i = i - 1; i >= 0; i--) {
|
||||
pci_free_consistent(to_pci_dev(dev), xhci->page_size,
|
||||
xhci->scratchpad->sp_buffers[i],
|
||||
xhci->scratchpad->sp_dma_buffers[i]);
|
||||
}
|
||||
kfree(xhci->scratchpad->sp_dma_buffers);
|
||||
|
||||
fail_sp4:
|
||||
kfree(xhci->scratchpad->sp_buffers);
|
||||
|
||||
fail_sp3:
|
||||
pci_free_consistent(to_pci_dev(dev), num_sp * sizeof(u64),
|
||||
xhci->scratchpad->sp_array,
|
||||
xhci->scratchpad->sp_dma);
|
||||
|
||||
fail_sp2:
|
||||
kfree(xhci->scratchpad);
|
||||
xhci->scratchpad = NULL;
|
||||
|
||||
fail_sp:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void scratchpad_free(struct xhci_hcd *xhci)
|
||||
{
|
||||
int num_sp;
|
||||
int i;
|
||||
struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
|
||||
|
||||
if (!xhci->scratchpad)
|
||||
return;
|
||||
|
||||
num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2);
|
||||
|
||||
for (i = 0; i < num_sp; i++) {
|
||||
pci_free_consistent(pdev, xhci->page_size,
|
||||
xhci->scratchpad->sp_buffers[i],
|
||||
xhci->scratchpad->sp_dma_buffers[i]);
|
||||
}
|
||||
kfree(xhci->scratchpad->sp_dma_buffers);
|
||||
kfree(xhci->scratchpad->sp_buffers);
|
||||
pci_free_consistent(pdev, num_sp * sizeof(u64),
|
||||
xhci->scratchpad->sp_array,
|
||||
xhci->scratchpad->sp_dma);
|
||||
kfree(xhci->scratchpad);
|
||||
xhci->scratchpad = NULL;
|
||||
}
|
||||
|
||||
void xhci_mem_cleanup(struct xhci_hcd *xhci)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
|
||||
|
|
@ -551,10 +703,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
|
|||
|
||||
/* Free the Event Ring Segment Table and the actual Event Ring */
|
||||
xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
|
||||
xhci_writel(xhci, 0, &xhci->ir_set->erst_base[0]);
|
||||
xhci_writel(xhci, 0, &xhci->ir_set->erst_base[1]);
|
||||
xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[0]);
|
||||
xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[1]);
|
||||
xhci_write_64(xhci, 0, &xhci->ir_set->erst_base);
|
||||
xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue);
|
||||
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
|
||||
if (xhci->erst.entries)
|
||||
pci_free_consistent(pdev, size,
|
||||
|
|
@ -566,8 +716,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
|
|||
xhci->event_ring = NULL;
|
||||
xhci_dbg(xhci, "Freed event ring\n");
|
||||
|
||||
xhci_writel(xhci, 0, &xhci->op_regs->cmd_ring[0]);
|
||||
xhci_writel(xhci, 0, &xhci->op_regs->cmd_ring[1]);
|
||||
xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring);
|
||||
if (xhci->cmd_ring)
|
||||
xhci_ring_free(xhci, xhci->cmd_ring);
|
||||
xhci->cmd_ring = NULL;
|
||||
|
|
@ -586,8 +735,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
|
|||
xhci->device_pool = NULL;
|
||||
xhci_dbg(xhci, "Freed device context pool\n");
|
||||
|
||||
xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[0]);
|
||||
xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[1]);
|
||||
xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr);
|
||||
if (xhci->dcbaa)
|
||||
pci_free_consistent(pdev, sizeof(*xhci->dcbaa),
|
||||
xhci->dcbaa, xhci->dcbaa->dma);
|
||||
|
|
@ -595,6 +743,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
|
|||
|
||||
xhci->page_size = 0;
|
||||
xhci->page_shift = 0;
|
||||
scratchpad_free(xhci);
|
||||
}
|
||||
|
||||
int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
||||
|
|
@ -602,6 +751,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||
dma_addr_t dma;
|
||||
struct device *dev = xhci_to_hcd(xhci)->self.controller;
|
||||
unsigned int val, val2;
|
||||
u64 val_64;
|
||||
struct xhci_segment *seg;
|
||||
u32 page_size;
|
||||
int i;
|
||||
|
|
@ -647,8 +797,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||
xhci->dcbaa->dma = dma;
|
||||
xhci_dbg(xhci, "// Device context base array address = 0x%llx (DMA), %p (virt)\n",
|
||||
(unsigned long long)xhci->dcbaa->dma, xhci->dcbaa);
|
||||
xhci_writel(xhci, dma, &xhci->op_regs->dcbaa_ptr[0]);
|
||||
xhci_writel(xhci, (u32) 0, &xhci->op_regs->dcbaa_ptr[1]);
|
||||
xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr);
|
||||
|
||||
/*
|
||||
* Initialize the ring segment pool. The ring must be a contiguous
|
||||
|
|
@ -658,11 +807,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||
*/
|
||||
xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
|
||||
SEGMENT_SIZE, 64, xhci->page_size);
|
||||
|
||||
/* See Table 46 and Note on Figure 55 */
|
||||
/* FIXME support 64-byte contexts */
|
||||
xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev,
|
||||
sizeof(struct xhci_device_control),
|
||||
64, xhci->page_size);
|
||||
2112, 64, xhci->page_size);
|
||||
if (!xhci->segment_pool || !xhci->device_pool)
|
||||
goto fail;
|
||||
|
||||
|
|
@ -675,14 +823,12 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||
(unsigned long long)xhci->cmd_ring->first_seg->dma);
|
||||
|
||||
/* Set the address in the Command Ring Control register */
|
||||
val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[0]);
|
||||
val = (val & ~CMD_RING_ADDR_MASK) |
|
||||
(xhci->cmd_ring->first_seg->dma & CMD_RING_ADDR_MASK) |
|
||||
val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
|
||||
val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
|
||||
(xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) |
|
||||
xhci->cmd_ring->cycle_state;
|
||||
xhci_dbg(xhci, "// Setting command ring address low bits to 0x%x\n", val);
|
||||
xhci_writel(xhci, val, &xhci->op_regs->cmd_ring[0]);
|
||||
xhci_dbg(xhci, "// Setting command ring address high bits to 0x0\n");
|
||||
xhci_writel(xhci, (u32) 0, &xhci->op_regs->cmd_ring[1]);
|
||||
xhci_dbg(xhci, "// Setting command ring address to 0x%x\n", val);
|
||||
xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
|
||||
xhci_dbg_cmd_ptrs(xhci);
|
||||
|
||||
val = xhci_readl(xhci, &xhci->cap_regs->db_off);
|
||||
|
|
@ -722,8 +868,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||
/* set ring base address and size for each segment table entry */
|
||||
for (val = 0, seg = xhci->event_ring->first_seg; val < ERST_NUM_SEGS; val++) {
|
||||
struct xhci_erst_entry *entry = &xhci->erst.entries[val];
|
||||
entry->seg_addr[0] = seg->dma;
|
||||
entry->seg_addr[1] = 0;
|
||||
entry->seg_addr = seg->dma;
|
||||
entry->seg_size = TRBS_PER_SEGMENT;
|
||||
entry->rsvd = 0;
|
||||
seg = seg->next;
|
||||
|
|
@ -741,11 +886,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||
/* set the segment table base address */
|
||||
xhci_dbg(xhci, "// Set ERST base address for ir_set 0 = 0x%llx\n",
|
||||
(unsigned long long)xhci->erst.erst_dma_addr);
|
||||
val = xhci_readl(xhci, &xhci->ir_set->erst_base[0]);
|
||||
val &= ERST_PTR_MASK;
|
||||
val |= (xhci->erst.erst_dma_addr & ~ERST_PTR_MASK);
|
||||
xhci_writel(xhci, val, &xhci->ir_set->erst_base[0]);
|
||||
xhci_writel(xhci, 0, &xhci->ir_set->erst_base[1]);
|
||||
val_64 = xhci_read_64(xhci, &xhci->ir_set->erst_base);
|
||||
val_64 &= ERST_PTR_MASK;
|
||||
val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK);
|
||||
xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base);
|
||||
|
||||
/* Set the event ring dequeue address */
|
||||
xhci_set_hc_event_deq(xhci);
|
||||
|
|
@ -761,7 +905,11 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||
for (i = 0; i < MAX_HC_SLOTS; ++i)
|
||||
xhci->devs[i] = 0;
|
||||
|
||||
if (scratchpad_alloc(xhci, flags))
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
xhci_warn(xhci, "Couldn't initialize memory\n");
|
||||
xhci_mem_cleanup(xhci);
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ static const struct hc_driver xhci_pci_hc_driver = {
|
|||
.free_dev = xhci_free_dev,
|
||||
.add_endpoint = xhci_add_endpoint,
|
||||
.drop_endpoint = xhci_drop_endpoint,
|
||||
.endpoint_reset = xhci_endpoint_reset,
|
||||
.check_bandwidth = xhci_check_bandwidth,
|
||||
.reset_bandwidth = xhci_reset_bandwidth,
|
||||
.address_device = xhci_address_device,
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ static void next_trb(struct xhci_hcd *xhci,
|
|||
static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer)
|
||||
{
|
||||
union xhci_trb *next = ++(ring->dequeue);
|
||||
unsigned long long addr;
|
||||
|
||||
ring->deq_updates++;
|
||||
/* Update the dequeue pointer further if that was a link TRB or we're at
|
||||
|
|
@ -152,6 +153,13 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
|
|||
ring->dequeue = ring->deq_seg->trbs;
|
||||
next = ring->dequeue;
|
||||
}
|
||||
addr = (unsigned long long) xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue);
|
||||
if (ring == xhci->event_ring)
|
||||
xhci_dbg(xhci, "Event ring deq = 0x%llx (DMA)\n", addr);
|
||||
else if (ring == xhci->cmd_ring)
|
||||
xhci_dbg(xhci, "Command ring deq = 0x%llx (DMA)\n", addr);
|
||||
else
|
||||
xhci_dbg(xhci, "Ring deq = 0x%llx (DMA)\n", addr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -171,6 +179,7 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
|
|||
{
|
||||
u32 chain;
|
||||
union xhci_trb *next;
|
||||
unsigned long long addr;
|
||||
|
||||
chain = ring->enqueue->generic.field[3] & TRB_CHAIN;
|
||||
next = ++(ring->enqueue);
|
||||
|
|
@ -204,6 +213,13 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
|
|||
ring->enqueue = ring->enq_seg->trbs;
|
||||
next = ring->enqueue;
|
||||
}
|
||||
addr = (unsigned long long) xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue);
|
||||
if (ring == xhci->event_ring)
|
||||
xhci_dbg(xhci, "Event ring enq = 0x%llx (DMA)\n", addr);
|
||||
else if (ring == xhci->cmd_ring)
|
||||
xhci_dbg(xhci, "Command ring enq = 0x%llx (DMA)\n", addr);
|
||||
else
|
||||
xhci_dbg(xhci, "Ring enq = 0x%llx (DMA)\n", addr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -237,7 +253,7 @@ static int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
|
|||
|
||||
void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
|
||||
{
|
||||
u32 temp;
|
||||
u64 temp;
|
||||
dma_addr_t deq;
|
||||
|
||||
deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
|
||||
|
|
@ -246,13 +262,15 @@ void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
|
|||
xhci_warn(xhci, "WARN something wrong with SW event ring "
|
||||
"dequeue ptr.\n");
|
||||
/* Update HC event ring dequeue pointer */
|
||||
temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]);
|
||||
temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
|
||||
temp &= ERST_PTR_MASK;
|
||||
if (!in_interrupt())
|
||||
xhci_dbg(xhci, "// Write event ring dequeue pointer\n");
|
||||
xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[1]);
|
||||
xhci_writel(xhci, (deq & ~ERST_PTR_MASK) | temp,
|
||||
&xhci->ir_set->erst_dequeue[0]);
|
||||
/* Don't clear the EHB bit (which is RW1C) because
|
||||
* there might be more events to service.
|
||||
*/
|
||||
temp &= ~ERST_EHB;
|
||||
xhci_dbg(xhci, "// Write event ring dequeue pointer, preserving EHB bit\n");
|
||||
xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
|
||||
&xhci->ir_set->erst_dequeue);
|
||||
}
|
||||
|
||||
/* Ring the host controller doorbell after placing a command on the ring */
|
||||
|
|
@ -279,7 +297,8 @@ static void ring_ep_doorbell(struct xhci_hcd *xhci,
|
|||
/* Don't ring the doorbell for this endpoint if there are pending
|
||||
* cancellations because the we don't want to interrupt processing.
|
||||
*/
|
||||
if (!ep_ring->cancels_pending && !(ep_ring->state & SET_DEQ_PENDING)) {
|
||||
if (!ep_ring->cancels_pending && !(ep_ring->state & SET_DEQ_PENDING)
|
||||
&& !(ep_ring->state & EP_HALTED)) {
|
||||
field = xhci_readl(xhci, db_addr) & DB_MASK;
|
||||
xhci_writel(xhci, field | EPI_TO_DB(ep_index), db_addr);
|
||||
/* Flush PCI posted writes - FIXME Matthew Wilcox says this
|
||||
|
|
@ -316,12 +335,6 @@ static struct xhci_segment *find_trb_seg(
|
|||
return cur_seg;
|
||||
}
|
||||
|
||||
struct dequeue_state {
|
||||
struct xhci_segment *new_deq_seg;
|
||||
union xhci_trb *new_deq_ptr;
|
||||
int new_cycle_state;
|
||||
};
|
||||
|
||||
/*
|
||||
* Move the xHC's endpoint ring dequeue pointer past cur_td.
|
||||
* Record the new state of the xHC's endpoint ring dequeue segment,
|
||||
|
|
@ -336,24 +349,30 @@ struct dequeue_state {
|
|||
* - Finally we move the dequeue state one TRB further, toggling the cycle bit
|
||||
* if we've moved it past a link TRB with the toggle cycle bit set.
|
||||
*/
|
||||
static void find_new_dequeue_state(struct xhci_hcd *xhci,
|
||||
void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
|
||||
unsigned int slot_id, unsigned int ep_index,
|
||||
struct xhci_td *cur_td, struct dequeue_state *state)
|
||||
struct xhci_td *cur_td, struct xhci_dequeue_state *state)
|
||||
{
|
||||
struct xhci_virt_device *dev = xhci->devs[slot_id];
|
||||
struct xhci_ring *ep_ring = dev->ep_rings[ep_index];
|
||||
struct xhci_generic_trb *trb;
|
||||
struct xhci_ep_ctx *ep_ctx;
|
||||
dma_addr_t addr;
|
||||
|
||||
state->new_cycle_state = 0;
|
||||
xhci_dbg(xhci, "Finding segment containing stopped TRB.\n");
|
||||
state->new_deq_seg = find_trb_seg(cur_td->start_seg,
|
||||
ep_ring->stopped_trb,
|
||||
&state->new_cycle_state);
|
||||
if (!state->new_deq_seg)
|
||||
BUG();
|
||||
/* Dig out the cycle state saved by the xHC during the stop ep cmd */
|
||||
state->new_cycle_state = 0x1 & dev->out_ctx->ep[ep_index].deq[0];
|
||||
xhci_dbg(xhci, "Finding endpoint context\n");
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
|
||||
state->new_cycle_state = 0x1 & ep_ctx->deq;
|
||||
|
||||
state->new_deq_ptr = cur_td->last_trb;
|
||||
xhci_dbg(xhci, "Finding segment containing last TRB in TD.\n");
|
||||
state->new_deq_seg = find_trb_seg(state->new_deq_seg,
|
||||
state->new_deq_ptr,
|
||||
&state->new_cycle_state);
|
||||
|
|
@ -367,6 +386,12 @@ static void find_new_dequeue_state(struct xhci_hcd *xhci,
|
|||
next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
|
||||
|
||||
/* Don't update the ring cycle state for the producer (us). */
|
||||
xhci_dbg(xhci, "New dequeue segment = %p (virtual)\n",
|
||||
state->new_deq_seg);
|
||||
addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr);
|
||||
xhci_dbg(xhci, "New dequeue pointer = 0x%llx (DMA)\n",
|
||||
(unsigned long long) addr);
|
||||
xhci_dbg(xhci, "Setting dequeue pointer in internal ring state.\n");
|
||||
ep_ring->dequeue = state->new_deq_ptr;
|
||||
ep_ring->deq_seg = state->new_deq_seg;
|
||||
}
|
||||
|
|
@ -416,6 +441,30 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
|
|||
unsigned int ep_index, struct xhci_segment *deq_seg,
|
||||
union xhci_trb *deq_ptr, u32 cycle_state);
|
||||
|
||||
void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
|
||||
struct xhci_ring *ep_ring, unsigned int slot_id,
|
||||
unsigned int ep_index, struct xhci_dequeue_state *deq_state)
|
||||
{
|
||||
xhci_dbg(xhci, "Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), "
|
||||
"new deq ptr = %p (0x%llx dma), new cycle = %u\n",
|
||||
deq_state->new_deq_seg,
|
||||
(unsigned long long)deq_state->new_deq_seg->dma,
|
||||
deq_state->new_deq_ptr,
|
||||
(unsigned long long)xhci_trb_virt_to_dma(deq_state->new_deq_seg, deq_state->new_deq_ptr),
|
||||
deq_state->new_cycle_state);
|
||||
queue_set_tr_deq(xhci, slot_id, ep_index,
|
||||
deq_state->new_deq_seg,
|
||||
deq_state->new_deq_ptr,
|
||||
(u32) deq_state->new_cycle_state);
|
||||
/* Stop the TD queueing code from ringing the doorbell until
|
||||
* this command completes. The HC won't set the dequeue pointer
|
||||
* if the ring is running, and ringing the doorbell starts the
|
||||
* ring running.
|
||||
*/
|
||||
ep_ring->state |= SET_DEQ_PENDING;
|
||||
xhci_ring_cmd_db(xhci);
|
||||
}
|
||||
|
||||
/*
|
||||
* When we get a command completion for a Stop Endpoint Command, we need to
|
||||
* unlink any cancelled TDs from the ring. There are two ways to do that:
|
||||
|
|
@ -436,7 +485,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
|
|||
struct xhci_td *cur_td = 0;
|
||||
struct xhci_td *last_unlinked_td;
|
||||
|
||||
struct dequeue_state deq_state;
|
||||
struct xhci_dequeue_state deq_state;
|
||||
#ifdef CONFIG_USB_HCD_STAT
|
||||
ktime_t stop_time = ktime_get();
|
||||
#endif
|
||||
|
|
@ -464,7 +513,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
|
|||
* move the xHC endpoint ring dequeue pointer past this TD.
|
||||
*/
|
||||
if (cur_td == ep_ring->stopped_td)
|
||||
find_new_dequeue_state(xhci, slot_id, ep_index, cur_td,
|
||||
xhci_find_new_dequeue_state(xhci, slot_id, ep_index, cur_td,
|
||||
&deq_state);
|
||||
else
|
||||
td_to_noop(xhci, ep_ring, cur_td);
|
||||
|
|
@ -480,24 +529,8 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
|
|||
|
||||
/* If necessary, queue a Set Transfer Ring Dequeue Pointer command */
|
||||
if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
|
||||
xhci_dbg(xhci, "Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), "
|
||||
"new deq ptr = %p (0x%llx dma), new cycle = %u\n",
|
||||
deq_state.new_deq_seg,
|
||||
(unsigned long long)deq_state.new_deq_seg->dma,
|
||||
deq_state.new_deq_ptr,
|
||||
(unsigned long long)xhci_trb_virt_to_dma(deq_state.new_deq_seg, deq_state.new_deq_ptr),
|
||||
deq_state.new_cycle_state);
|
||||
queue_set_tr_deq(xhci, slot_id, ep_index,
|
||||
deq_state.new_deq_seg,
|
||||
deq_state.new_deq_ptr,
|
||||
(u32) deq_state.new_cycle_state);
|
||||
/* Stop the TD queueing code from ringing the doorbell until
|
||||
* this command completes. The HC won't set the dequeue pointer
|
||||
* if the ring is running, and ringing the doorbell starts the
|
||||
* ring running.
|
||||
*/
|
||||
ep_ring->state |= SET_DEQ_PENDING;
|
||||
xhci_ring_cmd_db(xhci);
|
||||
xhci_queue_new_dequeue_state(xhci, ep_ring,
|
||||
slot_id, ep_index, &deq_state);
|
||||
} else {
|
||||
/* Otherwise just ring the doorbell to restart the ring */
|
||||
ring_ep_doorbell(xhci, slot_id, ep_index);
|
||||
|
|
@ -551,11 +584,15 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
|
|||
unsigned int ep_index;
|
||||
struct xhci_ring *ep_ring;
|
||||
struct xhci_virt_device *dev;
|
||||
struct xhci_ep_ctx *ep_ctx;
|
||||
struct xhci_slot_ctx *slot_ctx;
|
||||
|
||||
slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
|
||||
ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
|
||||
dev = xhci->devs[slot_id];
|
||||
ep_ring = dev->ep_rings[ep_index];
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
|
||||
|
||||
if (GET_COMP_CODE(event->status) != COMP_SUCCESS) {
|
||||
unsigned int ep_state;
|
||||
|
|
@ -569,9 +606,9 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
|
|||
case COMP_CTX_STATE:
|
||||
xhci_warn(xhci, "WARN Set TR Deq Ptr cmd failed due "
|
||||
"to incorrect slot or ep state.\n");
|
||||
ep_state = dev->out_ctx->ep[ep_index].ep_info;
|
||||
ep_state = ep_ctx->ep_info;
|
||||
ep_state &= EP_STATE_MASK;
|
||||
slot_state = dev->out_ctx->slot.dev_state;
|
||||
slot_state = slot_ctx->dev_state;
|
||||
slot_state = GET_SLOT_STATE(slot_state);
|
||||
xhci_dbg(xhci, "Slot state = %u, EP state = %u\n",
|
||||
slot_state, ep_state);
|
||||
|
|
@ -593,16 +630,33 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
|
|||
* cancelling URBs, which might not be an error...
|
||||
*/
|
||||
} else {
|
||||
xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq[0] = 0x%x, "
|
||||
"deq[1] = 0x%x.\n",
|
||||
dev->out_ctx->ep[ep_index].deq[0],
|
||||
dev->out_ctx->ep[ep_index].deq[1]);
|
||||
xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n",
|
||||
ep_ctx->deq);
|
||||
}
|
||||
|
||||
ep_ring->state &= ~SET_DEQ_PENDING;
|
||||
ring_ep_doorbell(xhci, slot_id, ep_index);
|
||||
}
|
||||
|
||||
static void handle_reset_ep_completion(struct xhci_hcd *xhci,
|
||||
struct xhci_event_cmd *event,
|
||||
union xhci_trb *trb)
|
||||
{
|
||||
int slot_id;
|
||||
unsigned int ep_index;
|
||||
|
||||
slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
|
||||
ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
|
||||
/* This command will only fail if the endpoint wasn't halted,
|
||||
* but we don't care.
|
||||
*/
|
||||
xhci_dbg(xhci, "Ignoring reset ep completion code of %u\n",
|
||||
(unsigned int) GET_COMP_CODE(event->status));
|
||||
|
||||
/* Clear our internal halted state and restart the ring */
|
||||
xhci->devs[slot_id]->ep_rings[ep_index]->state &= ~EP_HALTED;
|
||||
ring_ep_doorbell(xhci, slot_id, ep_index);
|
||||
}
|
||||
|
||||
static void handle_cmd_completion(struct xhci_hcd *xhci,
|
||||
struct xhci_event_cmd *event)
|
||||
|
|
@ -611,7 +665,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
|
|||
u64 cmd_dma;
|
||||
dma_addr_t cmd_dequeue_dma;
|
||||
|
||||
cmd_dma = (((u64) event->cmd_trb[1]) << 32) + event->cmd_trb[0];
|
||||
cmd_dma = event->cmd_trb;
|
||||
cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
|
||||
xhci->cmd_ring->dequeue);
|
||||
/* Is the command ring deq ptr out of sync with the deq seg ptr? */
|
||||
|
|
@ -653,6 +707,9 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
|
|||
case TRB_TYPE(TRB_CMD_NOOP):
|
||||
++xhci->noops_handled;
|
||||
break;
|
||||
case TRB_TYPE(TRB_RESET_EP):
|
||||
handle_reset_ep_completion(xhci, event, xhci->cmd_ring->dequeue);
|
||||
break;
|
||||
default:
|
||||
/* Skip over unknown commands on the event ring */
|
||||
xhci->error_bitmask |= 1 << 6;
|
||||
|
|
@ -756,7 +813,9 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|||
union xhci_trb *event_trb;
|
||||
struct urb *urb = 0;
|
||||
int status = -EINPROGRESS;
|
||||
struct xhci_ep_ctx *ep_ctx;
|
||||
|
||||
xhci_dbg(xhci, "In %s\n", __func__);
|
||||
xdev = xhci->devs[TRB_TO_SLOT_ID(event->flags)];
|
||||
if (!xdev) {
|
||||
xhci_err(xhci, "ERROR Transfer event pointed to bad slot\n");
|
||||
|
|
@ -765,17 +824,17 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|||
|
||||
/* Endpoint ID is 1 based, our index is zero based */
|
||||
ep_index = TRB_TO_EP_ID(event->flags) - 1;
|
||||
xhci_dbg(xhci, "%s - ep index = %d\n", __func__, ep_index);
|
||||
ep_ring = xdev->ep_rings[ep_index];
|
||||
if (!ep_ring || (xdev->out_ctx->ep[ep_index].ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) {
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
|
||||
if (!ep_ring || (ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) {
|
||||
xhci_err(xhci, "ERROR Transfer event pointed to disabled endpoint\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
event_dma = event->buffer[0];
|
||||
if (event->buffer[1] != 0)
|
||||
xhci_warn(xhci, "WARN ignoring upper 32-bits of 64-bit TRB dma address\n");
|
||||
|
||||
event_dma = event->buffer;
|
||||
/* This TRB should be in the TD at the head of this ring's TD list */
|
||||
xhci_dbg(xhci, "%s - checking for list empty\n", __func__);
|
||||
if (list_empty(&ep_ring->td_list)) {
|
||||
xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
|
||||
TRB_TO_SLOT_ID(event->flags), ep_index);
|
||||
|
|
@ -785,11 +844,14 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|||
urb = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
xhci_dbg(xhci, "%s - getting list entry\n", __func__);
|
||||
td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list);
|
||||
|
||||
/* Is this a TRB in the currently executing TD? */
|
||||
xhci_dbg(xhci, "%s - looking for TD\n", __func__);
|
||||
event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue,
|
||||
td->last_trb, event_dma);
|
||||
xhci_dbg(xhci, "%s - found event_seg = %p\n", __func__, event_seg);
|
||||
if (!event_seg) {
|
||||
/* HC is busted, give up! */
|
||||
xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not part of current TD\n");
|
||||
|
|
@ -798,10 +860,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|||
event_trb = &event_seg->trbs[(event_dma - event_seg->dma) / sizeof(*event_trb)];
|
||||
xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
|
||||
(unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10);
|
||||
xhci_dbg(xhci, "Offset 0x00 (buffer[0]) = 0x%x\n",
|
||||
(unsigned int) event->buffer[0]);
|
||||
xhci_dbg(xhci, "Offset 0x04 (buffer[0]) = 0x%x\n",
|
||||
(unsigned int) event->buffer[1]);
|
||||
xhci_dbg(xhci, "Offset 0x00 (buffer lo) = 0x%x\n",
|
||||
lower_32_bits(event->buffer));
|
||||
xhci_dbg(xhci, "Offset 0x04 (buffer hi) = 0x%x\n",
|
||||
upper_32_bits(event->buffer));
|
||||
xhci_dbg(xhci, "Offset 0x08 (transfer length) = 0x%x\n",
|
||||
(unsigned int) event->transfer_len);
|
||||
xhci_dbg(xhci, "Offset 0x0C (flags) = 0x%x\n",
|
||||
|
|
@ -823,6 +885,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|||
break;
|
||||
case COMP_STALL:
|
||||
xhci_warn(xhci, "WARN: Stalled endpoint\n");
|
||||
ep_ring->state |= EP_HALTED;
|
||||
status = -EPIPE;
|
||||
break;
|
||||
case COMP_TRB_ERR:
|
||||
|
|
@ -833,6 +896,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|||
xhci_warn(xhci, "WARN: transfer error on endpoint\n");
|
||||
status = -EPROTO;
|
||||
break;
|
||||
case COMP_BABBLE:
|
||||
xhci_warn(xhci, "WARN: babble error on endpoint\n");
|
||||
status = -EOVERFLOW;
|
||||
break;
|
||||
case COMP_DB_ERR:
|
||||
xhci_warn(xhci, "WARN: HC couldn't access mem fast enough\n");
|
||||
status = -ENOSR;
|
||||
|
|
@ -874,15 +941,26 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|||
if (event_trb != ep_ring->dequeue) {
|
||||
/* The event was for the status stage */
|
||||
if (event_trb == td->last_trb) {
|
||||
td->urb->actual_length =
|
||||
td->urb->transfer_buffer_length;
|
||||
if (td->urb->actual_length != 0) {
|
||||
/* Don't overwrite a previously set error code */
|
||||
if (status == -EINPROGRESS || status == 0)
|
||||
/* Did we already see a short data stage? */
|
||||
status = -EREMOTEIO;
|
||||
} else {
|
||||
td->urb->actual_length =
|
||||
td->urb->transfer_buffer_length;
|
||||
}
|
||||
} else {
|
||||
/* Maybe the event was for the data stage? */
|
||||
if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL)
|
||||
if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) {
|
||||
/* We didn't stop on a link TRB in the middle */
|
||||
td->urb->actual_length =
|
||||
td->urb->transfer_buffer_length -
|
||||
TRB_LEN(event->transfer_len);
|
||||
xhci_dbg(xhci, "Waiting for status stage event\n");
|
||||
urb = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -929,16 +1007,20 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|||
TRB_LEN(event->transfer_len));
|
||||
td->urb->actual_length = 0;
|
||||
}
|
||||
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
|
||||
status = -EREMOTEIO;
|
||||
else
|
||||
status = 0;
|
||||
/* Don't overwrite a previously set error code */
|
||||
if (status == -EINPROGRESS) {
|
||||
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
|
||||
status = -EREMOTEIO;
|
||||
else
|
||||
status = 0;
|
||||
}
|
||||
} else {
|
||||
td->urb->actual_length = td->urb->transfer_buffer_length;
|
||||
/* Ignore a short packet completion if the
|
||||
* untransferred length was zero.
|
||||
*/
|
||||
status = 0;
|
||||
if (status == -EREMOTEIO)
|
||||
status = 0;
|
||||
}
|
||||
} else {
|
||||
/* Slow path - walk the list, starting from the dequeue
|
||||
|
|
@ -965,19 +1047,30 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|||
TRB_LEN(event->transfer_len);
|
||||
}
|
||||
}
|
||||
/* The Endpoint Stop Command completion will take care of
|
||||
* any stopped TDs. A stopped TD may be restarted, so don't update the
|
||||
* ring dequeue pointer or take this TD off any lists yet.
|
||||
*/
|
||||
if (GET_COMP_CODE(event->transfer_len) == COMP_STOP_INVAL ||
|
||||
GET_COMP_CODE(event->transfer_len) == COMP_STOP) {
|
||||
/* The Endpoint Stop Command completion will take care of any
|
||||
* stopped TDs. A stopped TD may be restarted, so don't update
|
||||
* the ring dequeue pointer or take this TD off any lists yet.
|
||||
*/
|
||||
ep_ring->stopped_td = td;
|
||||
ep_ring->stopped_trb = event_trb;
|
||||
} else {
|
||||
/* Update ring dequeue pointer */
|
||||
while (ep_ring->dequeue != td->last_trb)
|
||||
if (GET_COMP_CODE(event->transfer_len) == COMP_STALL) {
|
||||
/* The transfer is completed from the driver's
|
||||
* perspective, but we need to issue a set dequeue
|
||||
* command for this stalled endpoint to move the dequeue
|
||||
* pointer past the TD. We can't do that here because
|
||||
* the halt condition must be cleared first.
|
||||
*/
|
||||
ep_ring->stopped_td = td;
|
||||
ep_ring->stopped_trb = event_trb;
|
||||
} else {
|
||||
/* Update ring dequeue pointer */
|
||||
while (ep_ring->dequeue != td->last_trb)
|
||||
inc_deq(xhci, ep_ring, false);
|
||||
inc_deq(xhci, ep_ring, false);
|
||||
inc_deq(xhci, ep_ring, false);
|
||||
}
|
||||
|
||||
/* Clean up the endpoint's TD list */
|
||||
urb = td->urb;
|
||||
|
|
@ -987,7 +1080,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
|||
list_del(&td->cancelled_td_list);
|
||||
ep_ring->cancels_pending--;
|
||||
}
|
||||
kfree(td);
|
||||
/* Leave the TD around for the reset endpoint function to use */
|
||||
if (GET_COMP_CODE(event->transfer_len) != COMP_STALL) {
|
||||
kfree(td);
|
||||
}
|
||||
urb->hcpriv = NULL;
|
||||
}
|
||||
cleanup:
|
||||
|
|
@ -997,6 +1093,8 @@ cleanup:
|
|||
/* FIXME for multi-TD URBs (who have buffers bigger than 64MB) */
|
||||
if (urb) {
|
||||
usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb);
|
||||
xhci_dbg(xhci, "Giveback URB %p, len = %d, status = %d\n",
|
||||
urb, td->urb->actual_length, status);
|
||||
spin_unlock(&xhci->lock);
|
||||
usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status);
|
||||
spin_lock(&xhci->lock);
|
||||
|
|
@ -1014,6 +1112,7 @@ void xhci_handle_event(struct xhci_hcd *xhci)
|
|||
int update_ptrs = 1;
|
||||
int ret;
|
||||
|
||||
xhci_dbg(xhci, "In %s\n", __func__);
|
||||
if (!xhci->event_ring || !xhci->event_ring->dequeue) {
|
||||
xhci->error_bitmask |= 1 << 1;
|
||||
return;
|
||||
|
|
@ -1026,18 +1125,25 @@ void xhci_handle_event(struct xhci_hcd *xhci)
|
|||
xhci->error_bitmask |= 1 << 2;
|
||||
return;
|
||||
}
|
||||
xhci_dbg(xhci, "%s - OS owns TRB\n", __func__);
|
||||
|
||||
/* FIXME: Handle more event types. */
|
||||
switch ((event->event_cmd.flags & TRB_TYPE_BITMASK)) {
|
||||
case TRB_TYPE(TRB_COMPLETION):
|
||||
xhci_dbg(xhci, "%s - calling handle_cmd_completion\n", __func__);
|
||||
handle_cmd_completion(xhci, &event->event_cmd);
|
||||
xhci_dbg(xhci, "%s - returned from handle_cmd_completion\n", __func__);
|
||||
break;
|
||||
case TRB_TYPE(TRB_PORT_STATUS):
|
||||
xhci_dbg(xhci, "%s - calling handle_port_status\n", __func__);
|
||||
handle_port_status(xhci, event);
|
||||
xhci_dbg(xhci, "%s - returned from handle_port_status\n", __func__);
|
||||
update_ptrs = 0;
|
||||
break;
|
||||
case TRB_TYPE(TRB_TRANSFER):
|
||||
xhci_dbg(xhci, "%s - calling handle_tx_event\n", __func__);
|
||||
ret = handle_tx_event(xhci, &event->trans_event);
|
||||
xhci_dbg(xhci, "%s - returned from handle_tx_event\n", __func__);
|
||||
if (ret < 0)
|
||||
xhci->error_bitmask |= 1 << 9;
|
||||
else
|
||||
|
|
@ -1093,13 +1199,13 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
|
|||
*/
|
||||
xhci_warn(xhci, "WARN urb submitted to disabled ep\n");
|
||||
return -ENOENT;
|
||||
case EP_STATE_HALTED:
|
||||
case EP_STATE_ERROR:
|
||||
xhci_warn(xhci, "WARN waiting for halt or error on ep "
|
||||
"to be cleared\n");
|
||||
xhci_warn(xhci, "WARN waiting for error on ep to be cleared\n");
|
||||
/* FIXME event handling code for error needs to clear it */
|
||||
/* XXX not sure if this should be -ENOENT or not */
|
||||
return -EINVAL;
|
||||
case EP_STATE_HALTED:
|
||||
xhci_dbg(xhci, "WARN halted endpoint, queueing URB anyway.\n");
|
||||
case EP_STATE_STOPPED:
|
||||
case EP_STATE_RUNNING:
|
||||
break;
|
||||
|
|
@ -1128,9 +1234,9 @@ static int prepare_transfer(struct xhci_hcd *xhci,
|
|||
gfp_t mem_flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
|
||||
ret = prepare_ring(xhci, xdev->ep_rings[ep_index],
|
||||
xdev->out_ctx->ep[ep_index].ep_info & EP_STATE_MASK,
|
||||
ep_ctx->ep_info & EP_STATE_MASK,
|
||||
num_trbs, mem_flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -1285,6 +1391,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
/* Queue the first TRB, even if it's zero-length */
|
||||
do {
|
||||
u32 field = 0;
|
||||
u32 length_field = 0;
|
||||
|
||||
/* Don't change the cycle bit of the first TRB until later */
|
||||
if (first_trb)
|
||||
|
|
@ -1314,10 +1421,13 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
(unsigned int) (addr + TRB_MAX_BUFF_SIZE) & ~(TRB_MAX_BUFF_SIZE - 1),
|
||||
(unsigned int) addr + trb_buff_len);
|
||||
}
|
||||
length_field = TRB_LEN(trb_buff_len) |
|
||||
TD_REMAINDER(urb->transfer_buffer_length - running_total) |
|
||||
TRB_INTR_TARGET(0);
|
||||
queue_trb(xhci, ep_ring, false,
|
||||
(u32) addr,
|
||||
(u32) ((u64) addr >> 32),
|
||||
TRB_LEN(trb_buff_len) | TRB_INTR_TARGET(0),
|
||||
lower_32_bits(addr),
|
||||
upper_32_bits(addr),
|
||||
length_field,
|
||||
/* We always want to know if the TRB was short,
|
||||
* or we won't get an event when it completes.
|
||||
* (Unless we use event data TRBs, which are a
|
||||
|
|
@ -1365,7 +1475,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
struct xhci_generic_trb *start_trb;
|
||||
bool first_trb;
|
||||
int start_cycle;
|
||||
u32 field;
|
||||
u32 field, length_field;
|
||||
|
||||
int running_total, trb_buff_len, ret;
|
||||
u64 addr;
|
||||
|
|
@ -1443,10 +1553,13 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
td->last_trb = ep_ring->enqueue;
|
||||
field |= TRB_IOC;
|
||||
}
|
||||
length_field = TRB_LEN(trb_buff_len) |
|
||||
TD_REMAINDER(urb->transfer_buffer_length - running_total) |
|
||||
TRB_INTR_TARGET(0);
|
||||
queue_trb(xhci, ep_ring, false,
|
||||
(u32) addr,
|
||||
(u32) ((u64) addr >> 32),
|
||||
TRB_LEN(trb_buff_len) | TRB_INTR_TARGET(0),
|
||||
lower_32_bits(addr),
|
||||
upper_32_bits(addr),
|
||||
length_field,
|
||||
/* We always want to know if the TRB was short,
|
||||
* or we won't get an event when it completes.
|
||||
* (Unless we use event data TRBs, which are a
|
||||
|
|
@ -1478,7 +1591,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
struct usb_ctrlrequest *setup;
|
||||
struct xhci_generic_trb *start_trb;
|
||||
int start_cycle;
|
||||
u32 field;
|
||||
u32 field, length_field;
|
||||
struct xhci_td *td;
|
||||
|
||||
ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
|
||||
|
|
@ -1528,13 +1641,16 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
|
||||
/* If there's data, queue data TRBs */
|
||||
field = 0;
|
||||
length_field = TRB_LEN(urb->transfer_buffer_length) |
|
||||
TD_REMAINDER(urb->transfer_buffer_length) |
|
||||
TRB_INTR_TARGET(0);
|
||||
if (urb->transfer_buffer_length > 0) {
|
||||
if (setup->bRequestType & USB_DIR_IN)
|
||||
field |= TRB_DIR_IN;
|
||||
queue_trb(xhci, ep_ring, false,
|
||||
lower_32_bits(urb->transfer_dma),
|
||||
upper_32_bits(urb->transfer_dma),
|
||||
TRB_LEN(urb->transfer_buffer_length) | TRB_INTR_TARGET(0),
|
||||
length_field,
|
||||
/* Event on short tx */
|
||||
field | TRB_ISP | TRB_TYPE(TRB_DATA) | ep_ring->cycle_state);
|
||||
}
|
||||
|
|
@ -1603,7 +1719,8 @@ int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id)
|
|||
int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
|
||||
u32 slot_id)
|
||||
{
|
||||
return queue_command(xhci, in_ctx_ptr, 0, 0,
|
||||
return queue_command(xhci, lower_32_bits(in_ctx_ptr),
|
||||
upper_32_bits(in_ctx_ptr), 0,
|
||||
TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id));
|
||||
}
|
||||
|
||||
|
|
@ -1611,7 +1728,8 @@ int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
|
|||
int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
|
||||
u32 slot_id)
|
||||
{
|
||||
return queue_command(xhci, in_ctx_ptr, 0, 0,
|
||||
return queue_command(xhci, lower_32_bits(in_ctx_ptr),
|
||||
upper_32_bits(in_ctx_ptr), 0,
|
||||
TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id));
|
||||
}
|
||||
|
||||
|
|
@ -1639,10 +1757,23 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
|
|||
u32 type = TRB_TYPE(TRB_SET_DEQ);
|
||||
|
||||
addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr);
|
||||
if (addr == 0)
|
||||
if (addr == 0) {
|
||||
xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n");
|
||||
xhci_warn(xhci, "WARN deq seg = %p, deq pt = %p\n",
|
||||
deq_seg, deq_ptr);
|
||||
return queue_command(xhci, (u32) addr | cycle_state, 0, 0,
|
||||
return 0;
|
||||
}
|
||||
return queue_command(xhci, lower_32_bits(addr) | cycle_state,
|
||||
upper_32_bits(addr), 0,
|
||||
trb_slot_id | trb_ep_index | type);
|
||||
}
|
||||
|
||||
int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
|
||||
unsigned int ep_index)
|
||||
{
|
||||
u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
|
||||
u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
|
||||
u32 type = TRB_TYPE(TRB_RESET_EP);
|
||||
|
||||
return queue_command(xhci, 0, 0, 0, trb_slot_id | trb_ep_index | type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <linux/usb.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "../core/hcd.h"
|
||||
/* Code sharing between pci-quirks and xhci hcd */
|
||||
|
|
@ -42,14 +43,6 @@
|
|||
* xHCI register interface.
|
||||
* This corresponds to the eXtensible Host Controller Interface (xHCI)
|
||||
* Revision 0.95 specification
|
||||
*
|
||||
* Registers should always be accessed with double word or quad word accesses.
|
||||
*
|
||||
* Some xHCI implementations may support 64-bit address pointers. Registers
|
||||
* with 64-bit address pointers should be written to with dword accesses by
|
||||
* writing the low dword first (ptr[0]), then the high dword (ptr[1]) second.
|
||||
* xHCI implementations that do not support 64-bit address pointers will ignore
|
||||
* the high dword, and write order is irrelevant.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -96,6 +89,7 @@ struct xhci_cap_regs {
|
|||
#define HCS_ERST_MAX(p) (((p) >> 4) & 0xf)
|
||||
/* bit 26 Scratchpad restore - for save/restore HW state - not used yet */
|
||||
/* bits 27:31 number of Scratchpad buffers SW must allocate for the HW */
|
||||
#define HCS_MAX_SCRATCHPAD(p) (((p) >> 27) & 0x1f)
|
||||
|
||||
/* HCSPARAMS3 - hcs_params3 - bitmasks */
|
||||
/* bits 0:7, Max U1 to U0 latency for the roothub ports */
|
||||
|
|
@ -166,10 +160,10 @@ struct xhci_op_regs {
|
|||
u32 reserved1;
|
||||
u32 reserved2;
|
||||
u32 dev_notification;
|
||||
u32 cmd_ring[2];
|
||||
u64 cmd_ring;
|
||||
/* rsvd: offset 0x20-2F */
|
||||
u32 reserved3[4];
|
||||
u32 dcbaa_ptr[2];
|
||||
u64 dcbaa_ptr;
|
||||
u32 config_reg;
|
||||
/* rsvd: offset 0x3C-3FF */
|
||||
u32 reserved4[241];
|
||||
|
|
@ -254,7 +248,7 @@ struct xhci_op_regs {
|
|||
#define CMD_RING_RUNNING (1 << 3)
|
||||
/* bits 4:5 reserved and should be preserved */
|
||||
/* Command Ring pointer - bit mask for the lower 32 bits. */
|
||||
#define CMD_RING_ADDR_MASK (0xffffffc0)
|
||||
#define CMD_RING_RSVD_BITS (0x3f)
|
||||
|
||||
/* CONFIG - Configure Register - config_reg bitmasks */
|
||||
/* bits 0:7 - maximum number of device slots enabled (NumSlotsEn) */
|
||||
|
|
@ -382,8 +376,8 @@ struct xhci_intr_reg {
|
|||
u32 irq_control;
|
||||
u32 erst_size;
|
||||
u32 rsvd;
|
||||
u32 erst_base[2];
|
||||
u32 erst_dequeue[2];
|
||||
u64 erst_base;
|
||||
u64 erst_dequeue;
|
||||
};
|
||||
|
||||
/* irq_pending bitmasks */
|
||||
|
|
@ -452,6 +446,27 @@ struct xhci_doorbell_array {
|
|||
#define EPI_TO_DB(p) (((p) + 1) & 0xff)
|
||||
|
||||
|
||||
/**
|
||||
* struct xhci_container_ctx
|
||||
* @type: Type of context. Used to calculated offsets to contained contexts.
|
||||
* @size: Size of the context data
|
||||
* @bytes: The raw context data given to HW
|
||||
* @dma: dma address of the bytes
|
||||
*
|
||||
* Represents either a Device or Input context. Holds a pointer to the raw
|
||||
* memory used for the context (bytes) and dma address of it (dma).
|
||||
*/
|
||||
struct xhci_container_ctx {
|
||||
unsigned type;
|
||||
#define XHCI_CTX_TYPE_DEVICE 0x1
|
||||
#define XHCI_CTX_TYPE_INPUT 0x2
|
||||
|
||||
int size;
|
||||
|
||||
u8 *bytes;
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct xhci_slot_ctx
|
||||
* @dev_info: Route string, device speed, hub info, and last valid endpoint
|
||||
|
|
@ -538,7 +553,7 @@ struct xhci_slot_ctx {
|
|||
struct xhci_ep_ctx {
|
||||
u32 ep_info;
|
||||
u32 ep_info2;
|
||||
u32 deq[2];
|
||||
u64 deq;
|
||||
u32 tx_info;
|
||||
/* offset 0x14 - 0x1f reserved for HC internal use */
|
||||
u32 reserved[3];
|
||||
|
|
@ -589,18 +604,16 @@ struct xhci_ep_ctx {
|
|||
|
||||
|
||||
/**
|
||||
* struct xhci_device_control
|
||||
* Input/Output context; see section 6.2.5.
|
||||
* struct xhci_input_control_context
|
||||
* Input control context; see section 6.2.5.
|
||||
*
|
||||
* @drop_context: set the bit of the endpoint context you want to disable
|
||||
* @add_context: set the bit of the endpoint context you want to enable
|
||||
*/
|
||||
struct xhci_device_control {
|
||||
struct xhci_input_control_ctx {
|
||||
u32 drop_flags;
|
||||
u32 add_flags;
|
||||
u32 rsvd[6];
|
||||
struct xhci_slot_ctx slot;
|
||||
struct xhci_ep_ctx ep[31];
|
||||
u32 rsvd2[6];
|
||||
};
|
||||
|
||||
/* drop context bitmasks */
|
||||
|
|
@ -608,7 +621,6 @@ struct xhci_device_control {
|
|||
/* add context bitmasks */
|
||||
#define ADD_EP(x) (0x1 << x)
|
||||
|
||||
|
||||
struct xhci_virt_device {
|
||||
/*
|
||||
* Commands to the hardware are passed an "input context" that
|
||||
|
|
@ -618,11 +630,10 @@ struct xhci_virt_device {
|
|||
* track of input and output contexts separately because
|
||||
* these commands might fail and we don't trust the hardware.
|
||||
*/
|
||||
struct xhci_device_control *out_ctx;
|
||||
dma_addr_t out_ctx_dma;
|
||||
struct xhci_container_ctx *out_ctx;
|
||||
/* Used for addressing devices and configuration changes */
|
||||
struct xhci_device_control *in_ctx;
|
||||
dma_addr_t in_ctx_dma;
|
||||
struct xhci_container_ctx *in_ctx;
|
||||
|
||||
/* FIXME when stream support is added */
|
||||
struct xhci_ring *ep_rings[31];
|
||||
/* Temporary storage in case the configure endpoint command fails and we
|
||||
|
|
@ -641,7 +652,7 @@ struct xhci_virt_device {
|
|||
*/
|
||||
struct xhci_device_context_array {
|
||||
/* 64-bit device addresses; we only write 32-bit addresses */
|
||||
u32 dev_context_ptrs[2*MAX_HC_SLOTS];
|
||||
u64 dev_context_ptrs[MAX_HC_SLOTS];
|
||||
/* private xHCD pointers */
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
|
@ -654,7 +665,7 @@ struct xhci_device_context_array {
|
|||
|
||||
struct xhci_stream_ctx {
|
||||
/* 64-bit stream ring address, cycle state, and stream type */
|
||||
u32 stream_ring[2];
|
||||
u64 stream_ring;
|
||||
/* offset 0x14 - 0x1f reserved for HC internal use */
|
||||
u32 reserved[2];
|
||||
};
|
||||
|
|
@ -662,7 +673,7 @@ struct xhci_stream_ctx {
|
|||
|
||||
struct xhci_transfer_event {
|
||||
/* 64-bit buffer address, or immediate data */
|
||||
u32 buffer[2];
|
||||
u64 buffer;
|
||||
u32 transfer_len;
|
||||
/* This field is interpreted differently based on the type of TRB */
|
||||
u32 flags;
|
||||
|
|
@ -744,7 +755,7 @@ struct xhci_transfer_event {
|
|||
|
||||
struct xhci_link_trb {
|
||||
/* 64-bit segment pointer*/
|
||||
u32 segment_ptr[2];
|
||||
u64 segment_ptr;
|
||||
u32 intr_target;
|
||||
u32 control;
|
||||
};
|
||||
|
|
@ -755,7 +766,7 @@ struct xhci_link_trb {
|
|||
/* Command completion event TRB */
|
||||
struct xhci_event_cmd {
|
||||
/* Pointer to command TRB, or the value passed by the event data trb */
|
||||
u32 cmd_trb[2];
|
||||
u64 cmd_trb;
|
||||
u32 status;
|
||||
u32 flags;
|
||||
};
|
||||
|
|
@ -848,8 +859,8 @@ union xhci_trb {
|
|||
#define TRB_CONFIG_EP 12
|
||||
/* Evaluate Context Command */
|
||||
#define TRB_EVAL_CONTEXT 13
|
||||
/* Reset Transfer Ring Command */
|
||||
#define TRB_RESET_RING 14
|
||||
/* Reset Endpoint Command */
|
||||
#define TRB_RESET_EP 14
|
||||
/* Stop Transfer Ring Command */
|
||||
#define TRB_STOP_RING 15
|
||||
/* Set Transfer Ring Dequeue Pointer Command */
|
||||
|
|
@ -929,6 +940,7 @@ struct xhci_ring {
|
|||
unsigned int cancels_pending;
|
||||
unsigned int state;
|
||||
#define SET_DEQ_PENDING (1 << 0)
|
||||
#define EP_HALTED (1 << 1)
|
||||
/* The TRB that was last reported in a stopped endpoint ring */
|
||||
union xhci_trb *stopped_trb;
|
||||
struct xhci_td *stopped_td;
|
||||
|
|
@ -940,9 +952,15 @@ struct xhci_ring {
|
|||
u32 cycle_state;
|
||||
};
|
||||
|
||||
struct xhci_dequeue_state {
|
||||
struct xhci_segment *new_deq_seg;
|
||||
union xhci_trb *new_deq_ptr;
|
||||
int new_cycle_state;
|
||||
};
|
||||
|
||||
struct xhci_erst_entry {
|
||||
/* 64-bit event ring segment address */
|
||||
u32 seg_addr[2];
|
||||
u64 seg_addr;
|
||||
u32 seg_size;
|
||||
/* Set to zero */
|
||||
u32 rsvd;
|
||||
|
|
@ -957,6 +975,13 @@ struct xhci_erst {
|
|||
unsigned int erst_size;
|
||||
};
|
||||
|
||||
struct xhci_scratchpad {
|
||||
u64 *sp_array;
|
||||
dma_addr_t sp_dma;
|
||||
void **sp_buffers;
|
||||
dma_addr_t *sp_dma_buffers;
|
||||
};
|
||||
|
||||
/*
|
||||
* Each segment table entry is 4*32bits long. 1K seems like an ok size:
|
||||
* (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table,
|
||||
|
|
@ -1011,6 +1036,9 @@ struct xhci_hcd {
|
|||
struct xhci_ring *cmd_ring;
|
||||
struct xhci_ring *event_ring;
|
||||
struct xhci_erst erst;
|
||||
/* Scratchpad */
|
||||
struct xhci_scratchpad *scratchpad;
|
||||
|
||||
/* slot enabling and address device helpers */
|
||||
struct completion addr_dev;
|
||||
int slot_id;
|
||||
|
|
@ -1071,13 +1099,43 @@ static inline unsigned int xhci_readl(const struct xhci_hcd *xhci,
|
|||
static inline void xhci_writel(struct xhci_hcd *xhci,
|
||||
const unsigned int val, __u32 __iomem *regs)
|
||||
{
|
||||
if (!in_interrupt())
|
||||
xhci_dbg(xhci,
|
||||
"`MEM_WRITE_DWORD(3'b000, 32'h%p, 32'h%0x, 4'hf);\n",
|
||||
regs, val);
|
||||
xhci_dbg(xhci,
|
||||
"`MEM_WRITE_DWORD(3'b000, 32'h%p, 32'h%0x, 4'hf);\n",
|
||||
regs, val);
|
||||
writel(val, regs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Registers should always be accessed with double word or quad word accesses.
|
||||
*
|
||||
* Some xHCI implementations may support 64-bit address pointers. Registers
|
||||
* with 64-bit address pointers should be written to with dword accesses by
|
||||
* writing the low dword first (ptr[0]), then the high dword (ptr[1]) second.
|
||||
* xHCI implementations that do not support 64-bit address pointers will ignore
|
||||
* the high dword, and write order is irrelevant.
|
||||
*/
|
||||
static inline u64 xhci_read_64(const struct xhci_hcd *xhci,
|
||||
__u64 __iomem *regs)
|
||||
{
|
||||
__u32 __iomem *ptr = (__u32 __iomem *) regs;
|
||||
u64 val_lo = readl(ptr);
|
||||
u64 val_hi = readl(ptr + 1);
|
||||
return val_lo + (val_hi << 32);
|
||||
}
|
||||
static inline void xhci_write_64(struct xhci_hcd *xhci,
|
||||
const u64 val, __u64 __iomem *regs)
|
||||
{
|
||||
__u32 __iomem *ptr = (__u32 __iomem *) regs;
|
||||
u32 val_lo = lower_32_bits(val);
|
||||
u32 val_hi = upper_32_bits(val);
|
||||
|
||||
xhci_dbg(xhci,
|
||||
"`MEM_WRITE_DWORD(3'b000, 64'h%p, 64'h%0lx, 4'hf);\n",
|
||||
regs, (long unsigned int) val);
|
||||
writel(val_lo, ptr);
|
||||
writel(val_hi, ptr + 1);
|
||||
}
|
||||
|
||||
/* xHCI debugging */
|
||||
void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num);
|
||||
void xhci_print_registers(struct xhci_hcd *xhci);
|
||||
|
|
@ -1090,7 +1148,7 @@ void xhci_debug_ring(struct xhci_hcd *xhci, struct xhci_ring *ring);
|
|||
void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst);
|
||||
void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci);
|
||||
void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring);
|
||||
void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep);
|
||||
void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int last_ep);
|
||||
|
||||
/* xHCI memory managment */
|
||||
void xhci_mem_cleanup(struct xhci_hcd *xhci);
|
||||
|
|
@ -1128,6 +1186,7 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);
|
|||
int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
|
||||
int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
|
||||
int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
|
||||
void xhci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
|
||||
int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
|
||||
void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
|
||||
|
||||
|
|
@ -1148,10 +1207,23 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
|
|||
int slot_id, unsigned int ep_index);
|
||||
int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
|
||||
u32 slot_id);
|
||||
int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
|
||||
unsigned int ep_index);
|
||||
void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
|
||||
unsigned int slot_id, unsigned int ep_index,
|
||||
struct xhci_td *cur_td, struct xhci_dequeue_state *state);
|
||||
void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
|
||||
struct xhci_ring *ep_ring, unsigned int slot_id,
|
||||
unsigned int ep_index, struct xhci_dequeue_state *deq_state);
|
||||
|
||||
/* xHCI roothub code */
|
||||
int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
|
||||
char *buf, u16 wLength);
|
||||
int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);
|
||||
|
||||
/* xHCI contexts */
|
||||
struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx);
|
||||
struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx);
|
||||
struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int ep_index);
|
||||
|
||||
#endif /* __LINUX_XHCI_HCD_H */
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ config USB_IOWARRIOR
|
|||
|
||||
config USB_TEST
|
||||
tristate "USB testing driver"
|
||||
depends on USB && USB_DEVICEFS
|
||||
depends on USB
|
||||
help
|
||||
This driver is for testing host controller software. It is used
|
||||
with specialized device firmware for regression and stress testing,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/usb/iowarrior.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/poll.h>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
|
|
|||
|
|
@ -1261,7 +1261,7 @@ static int mon_alloc_buff(struct mon_pgmap *map, int npages)
|
|||
return -ENOMEM;
|
||||
}
|
||||
map[n].ptr = (unsigned char *) vaddr;
|
||||
map[n].pg = virt_to_page(vaddr);
|
||||
map[n].pg = virt_to_page((void *) vaddr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ config USB_MUSB_HDRC
|
|||
depends on !SUPERH
|
||||
select NOP_USB_XCEIV if ARCH_DAVINCI
|
||||
select TWL4030_USB if MACH_OMAP_3430SDP
|
||||
select NOP_USB_XCEIV if MACH_OMAP3EVM
|
||||
select USB_OTG_UTILS
|
||||
tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
|
||||
help
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/dmapool.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -35,13 +35,14 @@
|
|||
#include <mach/hardware.h>
|
||||
#include <mach/memory.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/cputype.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include "musb_core.h"
|
||||
|
||||
#ifdef CONFIG_MACH_DAVINCI_EVM
|
||||
#define GPIO_nVBUS_DRV 87
|
||||
#define GPIO_nVBUS_DRV 144
|
||||
#endif
|
||||
|
||||
#include "davinci.h"
|
||||
|
|
@ -329,7 +330,6 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
|
|||
mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
|
||||
WARNING("VBUS error workaround (delay coming)\n");
|
||||
} else if (is_host_enabled(musb) && drvvbus) {
|
||||
musb->is_active = 1;
|
||||
MUSB_HST_MODE(musb);
|
||||
musb->xceiv->default_a = 1;
|
||||
musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
|
||||
|
|
@ -343,7 +343,9 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
|
|||
portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
|
||||
}
|
||||
|
||||
/* NOTE: this must complete poweron within 100 msec */
|
||||
/* NOTE: this must complete poweron within 100 msec
|
||||
* (OTG_TIME_A_WAIT_VRISE) but we don't check for that.
|
||||
*/
|
||||
davinci_source_power(musb, drvvbus, 0);
|
||||
DBG(2, "VBUS %s (%s)%s, devctl %02x\n",
|
||||
drvvbus ? "on" : "off",
|
||||
|
|
@ -411,6 +413,21 @@ int __init musb_platform_init(struct musb *musb)
|
|||
__raw_writel(phy_ctrl, USB_PHY_CTRL);
|
||||
}
|
||||
|
||||
/* On dm355, the default-A state machine needs DRVVBUS control.
|
||||
* If we won't be a host, there's no need to turn it on.
|
||||
*/
|
||||
if (cpu_is_davinci_dm355()) {
|
||||
u32 deepsleep = __raw_readl(DM355_DEEPSLEEP);
|
||||
|
||||
if (is_host_enabled(musb)) {
|
||||
deepsleep &= ~DRVVBUS_OVERRIDE;
|
||||
} else {
|
||||
deepsleep &= ~DRVVBUS_FORCE;
|
||||
deepsleep |= DRVVBUS_OVERRIDE;
|
||||
}
|
||||
__raw_writel(deepsleep, DM355_DEEPSLEEP);
|
||||
}
|
||||
|
||||
/* reset the controller */
|
||||
musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);
|
||||
|
||||
|
|
@ -437,6 +454,15 @@ int musb_platform_exit(struct musb *musb)
|
|||
if (is_host_enabled(musb))
|
||||
del_timer_sync(&otg_workaround);
|
||||
|
||||
/* force VBUS off */
|
||||
if (cpu_is_davinci_dm355()) {
|
||||
u32 deepsleep = __raw_readl(DM355_DEEPSLEEP);
|
||||
|
||||
deepsleep &= ~DRVVBUS_FORCE;
|
||||
deepsleep |= DRVVBUS_OVERRIDE;
|
||||
__raw_writel(deepsleep, DM355_DEEPSLEEP);
|
||||
}
|
||||
|
||||
davinci_source_power(musb, 0 /*off*/, 1);
|
||||
|
||||
/* delay, to avoid problems with module reload */
|
||||
|
|
|
|||
|
|
@ -1326,7 +1326,6 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
|
|||
int i;
|
||||
|
||||
/* log core options (read using indexed model) */
|
||||
musb_ep_select(mbase, 0);
|
||||
reg = musb_read_configdata(mbase);
|
||||
|
||||
strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8");
|
||||
|
|
@ -1990,7 +1989,7 @@ bad_config:
|
|||
if (status < 0)
|
||||
goto fail2;
|
||||
|
||||
#ifdef CONFIG_USB_OTG
|
||||
#ifdef CONFIG_USB_MUSB_OTG
|
||||
setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/clk.h>
|
||||
|
|
|
|||
|
|
@ -407,7 +407,7 @@ stall:
|
|||
csr |= MUSB_RXCSR_P_SENDSTALL
|
||||
| MUSB_RXCSR_FLUSHFIFO
|
||||
| MUSB_RXCSR_CLRDATATOG
|
||||
| MUSB_TXCSR_P_WZC_BITS;
|
||||
| MUSB_RXCSR_P_WZC_BITS;
|
||||
musb_writew(regs, MUSB_RXCSR,
|
||||
csr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -373,7 +373,7 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb,
|
|||
musb_save_toggle(qh, is_in, urb);
|
||||
break;
|
||||
case USB_ENDPOINT_XFER_ISOC:
|
||||
if (urb->error_count)
|
||||
if (status == 0 && urb->error_count)
|
||||
status = -EXDEV;
|
||||
break;
|
||||
}
|
||||
|
|
@ -2235,13 +2235,30 @@ static void musb_h_stop(struct usb_hcd *hcd)
|
|||
static int musb_bus_suspend(struct usb_hcd *hcd)
|
||||
{
|
||||
struct musb *musb = hcd_to_musb(hcd);
|
||||
u8 devctl;
|
||||
|
||||
if (musb->xceiv->state == OTG_STATE_A_SUSPEND)
|
||||
if (!is_host_active(musb))
|
||||
return 0;
|
||||
|
||||
if (is_host_active(musb) && musb->is_active) {
|
||||
WARNING("trying to suspend as %s is_active=%i\n",
|
||||
otg_state_string(musb), musb->is_active);
|
||||
switch (musb->xceiv->state) {
|
||||
case OTG_STATE_A_SUSPEND:
|
||||
return 0;
|
||||
case OTG_STATE_A_WAIT_VRISE:
|
||||
/* ID could be grounded even if there's no device
|
||||
* on the other end of the cable. NOTE that the
|
||||
* A_WAIT_VRISE timers are messy with MUSB...
|
||||
*/
|
||||
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
|
||||
if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
|
||||
musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (musb->is_active) {
|
||||
WARNING("trying to suspend as %s while active\n",
|
||||
otg_state_string(musb));
|
||||
return -EBUSY;
|
||||
} else
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -323,6 +323,7 @@ static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off)
|
|||
|
||||
static inline u8 musb_read_configdata(void __iomem *mbase)
|
||||
{
|
||||
musb_writeb(mbase, MUSB_INDEX, 0);
|
||||
return musb_readb(mbase, 0x10 + MUSB_CONFIGDATA);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,18 +59,4 @@ config NOP_USB_XCEIV
|
|||
built-in with usb ip or which are autonomous and doesn't require any
|
||||
phy programming such as ISP1x04 etc.
|
||||
|
||||
config USB_LANGWELL_OTG
|
||||
tristate "Intel Langwell USB OTG dual-role support"
|
||||
depends on USB && MRST
|
||||
select USB_OTG
|
||||
select USB_OTG_UTILS
|
||||
help
|
||||
Say Y here if you want to build Intel Langwell USB OTG
|
||||
transciever driver in kernel. This driver implements role
|
||||
switch between EHCI host driver and Langwell USB OTG
|
||||
client driver.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called langwell_otg.
|
||||
|
||||
endif # USB || OTG
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg.o
|
|||
obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o
|
||||
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
|
||||
obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o
|
||||
obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o
|
||||
obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o
|
||||
|
||||
ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -53,6 +53,7 @@ EXPORT_SYMBOL(usb_nop_xceiv_register);
|
|||
void usb_nop_xceiv_unregister(void)
|
||||
{
|
||||
platform_device_unregister(pd);
|
||||
pd = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(usb_nop_xceiv_unregister);
|
||||
|
||||
|
|
|
|||
|
|
@ -169,9 +169,11 @@ static int usb_console_setup(struct console *co, char *options)
|
|||
kfree(tty);
|
||||
}
|
||||
}
|
||||
/* So we know not to kill the hardware on a hangup on this
|
||||
port. We have also bumped the use count by one so it won't go
|
||||
idle */
|
||||
/* Now that any required fake tty operations are completed restore
|
||||
* the tty port count */
|
||||
--port->port.count;
|
||||
/* The console is special in terms of closing the device so
|
||||
* indicate this port is now acting as a system console. */
|
||||
port->console = 1;
|
||||
retval = 0;
|
||||
|
||||
|
|
@ -204,7 +206,7 @@ static void usb_console_write(struct console *co,
|
|||
|
||||
dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
|
||||
|
||||
if (!port->port.count) {
|
||||
if (!port->console) {
|
||||
dbg("%s - port not opened", __func__);
|
||||
return;
|
||||
}
|
||||
|
|
@ -300,8 +302,7 @@ void usb_serial_console_exit(void)
|
|||
{
|
||||
if (usbcons_info.port) {
|
||||
unregister_console(&usbcons);
|
||||
if (usbcons_info.port->port.count)
|
||||
usbcons_info.port->port.count--;
|
||||
usbcons_info.port->console = 0;
|
||||
usbcons_info.port = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ static struct usb_device_id id_table [] = {
|
|||
{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
|
||||
{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
|
||||
{ USB_DEVICE(0x10C4, 0x0F91) }, /* Vstabi */
|
||||
{ USB_DEVICE(0x10C4, 0x1101) }, /* Arkham Technology DS101 Bus Monitor */
|
||||
{ USB_DEVICE(0x10C4, 0x1601) }, /* Arkham Technology DS101 Adapter */
|
||||
{ USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */
|
||||
{ USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
|
||||
{ USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
|
||||
|
|
@ -78,6 +80,7 @@ static struct usb_device_id id_table [] = {
|
|||
{ USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
|
||||
{ USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */
|
||||
{ USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */
|
||||
{ USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */
|
||||
{ USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
|
||||
{ USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
|
||||
{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
|
||||
|
|
@ -94,7 +97,9 @@ static struct usb_device_id id_table [] = {
|
|||
{ USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */
|
||||
{ USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */
|
||||
{ USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
|
||||
{ USB_DEVICE(0x10C4, 0x8382) }, /* Cygnal Integrated Products, Inc. */
|
||||
{ USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */
|
||||
{ USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */
|
||||
{ USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
|
||||
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
|
||||
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
|
||||
|
|
|
|||
|
|
@ -1228,8 +1228,8 @@ static void cypress_read_int_callback(struct urb *urb)
|
|||
/* precursor to disconnect so just go away */
|
||||
return;
|
||||
case -EPIPE:
|
||||
usb_clear_halt(port->serial->dev, 0x81);
|
||||
break;
|
||||
/* Can't call usb_clear_halt while in_interrupt */
|
||||
/* FALLS THROUGH */
|
||||
default:
|
||||
/* something ugly is going on... */
|
||||
dev_err(&urb->dev->dev,
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_driver.h>
|
||||
#include <linux/tty_flip.h>
|
||||
|
|
@ -107,6 +108,7 @@ struct ftdi_sio_quirk {
|
|||
|
||||
static int ftdi_jtag_probe(struct usb_serial *serial);
|
||||
static int ftdi_mtxorb_hack_setup(struct usb_serial *serial);
|
||||
static int ftdi_NDI_device_setup(struct usb_serial *serial);
|
||||
static void ftdi_USB_UIRT_setup(struct ftdi_private *priv);
|
||||
static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv);
|
||||
|
||||
|
|
@ -118,6 +120,10 @@ static struct ftdi_sio_quirk ftdi_mtxorb_hack_quirk = {
|
|||
.probe = ftdi_mtxorb_hack_setup,
|
||||
};
|
||||
|
||||
static struct ftdi_sio_quirk ftdi_NDI_device_quirk = {
|
||||
.probe = ftdi_NDI_device_setup,
|
||||
};
|
||||
|
||||
static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
|
||||
.port_probe = ftdi_USB_UIRT_setup,
|
||||
};
|
||||
|
|
@ -191,6 +197,7 @@ static struct usb_device_id id_table_combined [] = {
|
|||
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) },
|
||||
|
|
@ -579,6 +586,9 @@ static struct usb_device_id id_table_combined [] = {
|
|||
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CCSLOAD_N_GO_3_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU64_4_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CCSPRIME8_5_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) },
|
||||
{ USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) },
|
||||
{ USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) },
|
||||
|
|
@ -644,6 +654,16 @@ static struct usb_device_id id_table_combined [] = {
|
|||
{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) },
|
||||
{ USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID),
|
||||
.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NDI_SPECTRA_SCU_PID),
|
||||
.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_2_PID),
|
||||
.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_3_PID),
|
||||
.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID),
|
||||
.driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
|
||||
{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) },
|
||||
|
|
@ -660,6 +680,8 @@ static struct usb_device_id id_table_combined [] = {
|
|||
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
|
||||
{ USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID),
|
||||
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID),
|
||||
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
|
||||
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) },
|
||||
|
|
@ -667,7 +689,6 @@ static struct usb_device_id id_table_combined [] = {
|
|||
{ USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) },
|
||||
{ USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID) },
|
||||
{ USB_DEVICE(ATMEL_VID, STK541_PID) },
|
||||
{ USB_DEVICE(DE_VID, STB_PID) },
|
||||
{ USB_DEVICE(DE_VID, WHT_PID) },
|
||||
|
|
@ -677,6 +698,10 @@ static struct usb_device_id id_table_combined [] = {
|
|||
{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
|
||||
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
|
||||
{ USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) },
|
||||
{ USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) },
|
||||
{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
|
||||
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
|
||||
{ }, /* Optional parameter entry */
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
|
@ -1023,6 +1048,16 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
|
|||
case FT2232C: /* FT2232C chip */
|
||||
case FT232RL:
|
||||
if (baud <= 3000000) {
|
||||
__u16 product_id = le16_to_cpu(
|
||||
port->serial->dev->descriptor.idProduct);
|
||||
if (((FTDI_NDI_HUC_PID == product_id) ||
|
||||
(FTDI_NDI_SPECTRA_SCU_PID == product_id) ||
|
||||
(FTDI_NDI_FUTURE_2_PID == product_id) ||
|
||||
(FTDI_NDI_FUTURE_3_PID == product_id) ||
|
||||
(FTDI_NDI_AURORA_SCU_PID == product_id)) &&
|
||||
(baud == 19200)) {
|
||||
baud = 1200000;
|
||||
}
|
||||
div_value = ftdi_232bm_baud_to_divisor(baud);
|
||||
} else {
|
||||
dbg("%s - Baud rate too high!", __func__);
|
||||
|
|
@ -1553,6 +1588,39 @@ static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv)
|
|||
priv->force_rtscts = 1;
|
||||
} /* ftdi_HE_TIRA1_setup */
|
||||
|
||||
/*
|
||||
* Module parameter to control latency timer for NDI FTDI-based USB devices.
|
||||
* If this value is not set in modprobe.conf.local its value will be set to 1ms.
|
||||
*/
|
||||
static int ndi_latency_timer = 1;
|
||||
|
||||
/* Setup for the NDI FTDI-based USB devices, which requires hardwired
|
||||
* baudrate (19200 gets mapped to 1200000).
|
||||
*
|
||||
* Called from usbserial:serial_probe.
|
||||
*/
|
||||
static int ftdi_NDI_device_setup(struct usb_serial *serial)
|
||||
{
|
||||
struct usb_device *udev = serial->dev;
|
||||
int latency = ndi_latency_timer;
|
||||
int rv = 0;
|
||||
char buf[1];
|
||||
|
||||
if (latency == 0)
|
||||
latency = 1;
|
||||
if (latency > 99)
|
||||
latency = 99;
|
||||
|
||||
dbg("%s setting NDI device latency to %d", __func__, latency);
|
||||
dev_info(&udev->dev, "NDI device with a latency value of %d", latency);
|
||||
|
||||
rv = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
FTDI_SIO_SET_LATENCY_TIMER_REQUEST,
|
||||
FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE,
|
||||
latency, 0, buf, 0, WDR_TIMEOUT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* First port on JTAG adaptors such as Olimex arm-usb-ocd or the FIC/OpenMoko
|
||||
* Neo1973 Debug Board is reserved for JTAG interface and can be accessed from
|
||||
|
|
@ -2121,7 +2189,7 @@ static void ftdi_process_read(struct work_struct *work)
|
|||
/* Note that the error flag is duplicated for
|
||||
every character received since we don't know
|
||||
which character it applied to */
|
||||
if (!usb_serial_handle_sysrq_char(port,
|
||||
if (!usb_serial_handle_sysrq_char(tty, port,
|
||||
data[packet_offset + i]))
|
||||
tty_insert_flip_char(tty,
|
||||
data[packet_offset + i],
|
||||
|
|
@ -2622,3 +2690,5 @@ MODULE_PARM_DESC(vendor, "User specified vendor ID (default="
|
|||
module_param(product, ushort, 0);
|
||||
MODULE_PARM_DESC(product, "User specified product ID");
|
||||
|
||||
module_param(ndi_latency_timer, int, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(ndi_latency_timer, "NDI device latency timer override");
|
||||
|
|
|
|||
|
|
@ -506,6 +506,7 @@
|
|||
*
|
||||
* Armin Laeuger originally sent the PID for the UM 100 module.
|
||||
*/
|
||||
#define FTDI_R2000KU_TRUE_RNG 0xFB80 /* R2000KU TRUE RNG */
|
||||
#define FTDI_ELV_UR100_PID 0xFB58 /* USB-RS232-Umsetzer (UR 100) */
|
||||
#define FTDI_ELV_UM100_PID 0xFB5A /* USB-Modul UM 100 */
|
||||
#define FTDI_ELV_UO100_PID 0xFB5B /* USB-Modul UO 100 */
|
||||
|
|
@ -614,6 +615,9 @@
|
|||
#define FTDI_CCSICDU20_0_PID 0xF9D0
|
||||
#define FTDI_CCSICDU40_1_PID 0xF9D1
|
||||
#define FTDI_CCSMACHX_2_PID 0xF9D2
|
||||
#define FTDI_CCSLOAD_N_GO_3_PID 0xF9D3
|
||||
#define FTDI_CCSICDU64_4_PID 0xF9D4
|
||||
#define FTDI_CCSPRIME8_5_PID 0xF9D5
|
||||
|
||||
/* Inside Accesso contactless reader (http://www.insidefr.com) */
|
||||
#define INSIDE_ACCESSO 0xFAD0
|
||||
|
|
@ -735,6 +739,15 @@
|
|||
/* Pyramid Computer GmbH */
|
||||
#define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */
|
||||
|
||||
/*
|
||||
* NDI (www.ndigital.com) product ids
|
||||
*/
|
||||
#define FTDI_NDI_HUC_PID 0xDA70 /* NDI Host USB Converter */
|
||||
#define FTDI_NDI_SPECTRA_SCU_PID 0xDA71 /* NDI Spectra SCU */
|
||||
#define FTDI_NDI_FUTURE_2_PID 0xDA72 /* NDI future device #2 */
|
||||
#define FTDI_NDI_FUTURE_3_PID 0xDA73 /* NDI future device #3 */
|
||||
#define FTDI_NDI_AURORA_SCU_PID 0xDA74 /* NDI Aurora SCU */
|
||||
|
||||
/*
|
||||
* Posiflex inc retail equipment (http://www.posiflex.com.tw)
|
||||
*/
|
||||
|
|
@ -848,9 +861,6 @@
|
|||
#define TML_VID 0x1B91 /* Vendor ID */
|
||||
#define TML_USB_SERIAL_PID 0x0064 /* USB - Serial Converter */
|
||||
|
||||
/* NDI Polaris System */
|
||||
#define FTDI_NDI_HUC_PID 0xDA70
|
||||
|
||||
/* Propox devices */
|
||||
#define FTDI_PROPOX_JTAGCABLEII_PID 0xD738
|
||||
|
||||
|
|
@ -934,6 +944,29 @@
|
|||
#define MARVELL_VID 0x9e88
|
||||
#define MARVELL_SHEEVAPLUG_PID 0x9e8f
|
||||
|
||||
#define FTDI_TURTELIZER_PID 0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */
|
||||
|
||||
/*
|
||||
* GN Otometrics (http://www.otometrics.com)
|
||||
* Submitted by Ville Sundberg.
|
||||
*/
|
||||
#define GN_OTOMETRICS_VID 0x0c33 /* Vendor ID */
|
||||
#define AURICAL_USB_PID 0x0010 /* Aurical USB Audiometer */
|
||||
|
||||
/*
|
||||
* Bayer Ascensia Contour blood glucose meter USB-converter cable.
|
||||
* http://winglucofacts.com/cables/
|
||||
*/
|
||||
#define BAYER_VID 0x1A79
|
||||
#define BAYER_CONTOUR_CABLE_PID 0x6001
|
||||
|
||||
/*
|
||||
* Marvell OpenRD Base, Client
|
||||
* http://www.open-rd.org
|
||||
* OpenRD Base, Client use VID 0x0403
|
||||
*/
|
||||
#define MARVELL_OPENRD_PID 0x9e90
|
||||
|
||||
/*
|
||||
* BmRequestType: 1100 0000b
|
||||
* bRequest: FTDI_E2_READ
|
||||
|
|
|
|||
|
|
@ -424,10 +424,17 @@ static void flush_and_resubmit_read_urb(struct usb_serial_port *port)
|
|||
if (!tty)
|
||||
goto done;
|
||||
|
||||
/* Push data to tty */
|
||||
for (i = 0; i < urb->actual_length; i++, ch++) {
|
||||
if (!usb_serial_handle_sysrq_char(port, *ch))
|
||||
tty_insert_flip_char(tty, *ch, TTY_NORMAL);
|
||||
/* The per character mucking around with sysrq path it too slow for
|
||||
stuff like 3G modems, so shortcircuit it in the 99.9999999% of cases
|
||||
where the USB serial is not a console anyway */
|
||||
if (!port->console || !port->sysrq)
|
||||
tty_insert_flip_string(tty, ch, urb->actual_length);
|
||||
else {
|
||||
/* Push data to tty */
|
||||
for (i = 0; i < urb->actual_length; i++, ch++) {
|
||||
if (!usb_serial_handle_sysrq_char(tty, port, *ch))
|
||||
tty_insert_flip_char(tty, *ch, TTY_NORMAL);
|
||||
}
|
||||
}
|
||||
tty_flip_buffer_push(tty);
|
||||
tty_kref_put(tty);
|
||||
|
|
@ -527,11 +534,12 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
|
|||
}
|
||||
}
|
||||
|
||||
int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
|
||||
int usb_serial_handle_sysrq_char(struct tty_struct *tty,
|
||||
struct usb_serial_port *port, unsigned int ch)
|
||||
{
|
||||
if (port->sysrq && port->console) {
|
||||
if (ch && time_before(jiffies, port->sysrq)) {
|
||||
handle_sysrq(ch, tty_port_tty_get(&port->port));
|
||||
handle_sysrq(ch, tty);
|
||||
port->sysrq = 0;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -521,7 +521,7 @@ static int mos7720_chars_in_buffer(struct tty_struct *tty)
|
|||
mos7720_port = usb_get_serial_port_data(port);
|
||||
if (mos7720_port == NULL) {
|
||||
dbg("%s:leaving ...........", __func__);
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_URBS; ++i) {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_driver.h>
|
||||
#include <linux/tty_flip.h>
|
||||
|
|
@ -123,10 +124,13 @@
|
|||
#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44
|
||||
#define BANDB_DEVICE_ID_USOPTL4_2 0xAC42
|
||||
|
||||
/* This driver also supports the ATEN UC2324 device since it is mos7840 based
|
||||
* - if I knew the device id it would also support the ATEN UC2322 */
|
||||
/* This driver also supports
|
||||
* ATEN UC2324 device using Moschip MCS7840
|
||||
* ATEN UC2322 device using Moschip MCS7820
|
||||
*/
|
||||
#define USB_VENDOR_ID_ATENINTL 0x0557
|
||||
#define ATENINTL_DEVICE_ID_UC2324 0x2011
|
||||
#define ATENINTL_DEVICE_ID_UC2322 0x7820
|
||||
|
||||
/* Interrupt Routine Defines */
|
||||
|
||||
|
|
@ -176,6 +180,7 @@ static struct usb_device_id moschip_port_id_table[] = {
|
|||
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
|
||||
{} /* terminating entry */
|
||||
};
|
||||
|
||||
|
|
@ -185,6 +190,7 @@ static __devinitdata struct usb_device_id moschip_id_table_combined[] = {
|
|||
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
|
||||
{} /* terminating entry */
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -66,8 +66,10 @@ static int option_tiocmget(struct tty_struct *tty, struct file *file);
|
|||
static int option_tiocmset(struct tty_struct *tty, struct file *file,
|
||||
unsigned int set, unsigned int clear);
|
||||
static int option_send_setup(struct usb_serial_port *port);
|
||||
#ifdef CONFIG_PM
|
||||
static int option_suspend(struct usb_serial *serial, pm_message_t message);
|
||||
static int option_resume(struct usb_serial *serial);
|
||||
#endif
|
||||
|
||||
/* Vendor and product IDs */
|
||||
#define OPTION_VENDOR_ID 0x0AF0
|
||||
|
|
@ -205,7 +207,9 @@ static int option_resume(struct usb_serial *serial);
|
|||
#define NOVATELWIRELESS_PRODUCT_MC727 0x4100
|
||||
#define NOVATELWIRELESS_PRODUCT_MC950D 0x4400
|
||||
#define NOVATELWIRELESS_PRODUCT_U727 0x5010
|
||||
#define NOVATELWIRELESS_PRODUCT_MC727_NEW 0x5100
|
||||
#define NOVATELWIRELESS_PRODUCT_MC760 0x6000
|
||||
#define NOVATELWIRELESS_PRODUCT_OVMC760 0x6002
|
||||
|
||||
/* FUTURE NOVATEL PRODUCTS */
|
||||
#define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED 0X6001
|
||||
|
|
@ -258,11 +262,6 @@ static int option_resume(struct usb_serial *serial);
|
|||
#define AXESSTEL_VENDOR_ID 0x1726
|
||||
#define AXESSTEL_PRODUCT_MV110H 0x1000
|
||||
|
||||
#define ONDA_VENDOR_ID 0x19d2
|
||||
#define ONDA_PRODUCT_MSA501HS 0x0001
|
||||
#define ONDA_PRODUCT_ET502HS 0x0002
|
||||
#define ONDA_PRODUCT_MT503HS 0x2000
|
||||
|
||||
#define BANDRICH_VENDOR_ID 0x1A8D
|
||||
#define BANDRICH_PRODUCT_C100_1 0x1002
|
||||
#define BANDRICH_PRODUCT_C100_2 0x1003
|
||||
|
|
@ -300,6 +299,7 @@ static int option_resume(struct usb_serial *serial);
|
|||
#define ZTE_PRODUCT_MF628 0x0015
|
||||
#define ZTE_PRODUCT_MF626 0x0031
|
||||
#define ZTE_PRODUCT_CDMA_TECH 0xfffe
|
||||
#define ZTE_PRODUCT_AC8710 0xfff1
|
||||
|
||||
#define BENQ_VENDOR_ID 0x04a5
|
||||
#define BENQ_PRODUCT_H10 0x4068
|
||||
|
|
@ -307,11 +307,25 @@ static int option_resume(struct usb_serial *serial);
|
|||
#define DLINK_VENDOR_ID 0x1186
|
||||
#define DLINK_PRODUCT_DWM_652 0x3e04
|
||||
|
||||
#define QISDA_VENDOR_ID 0x1da5
|
||||
#define QISDA_PRODUCT_H21_4512 0x4512
|
||||
#define QISDA_PRODUCT_H21_4523 0x4523
|
||||
#define QISDA_PRODUCT_H20_4515 0x4515
|
||||
#define QISDA_PRODUCT_H20_4519 0x4519
|
||||
|
||||
|
||||
/* TOSHIBA PRODUCTS */
|
||||
#define TOSHIBA_VENDOR_ID 0x0930
|
||||
#define TOSHIBA_PRODUCT_HSDPA_MINICARD 0x1302
|
||||
|
||||
#define ALINK_VENDOR_ID 0x1e0e
|
||||
#define ALINK_PRODUCT_3GU 0x9200
|
||||
|
||||
/* ALCATEL PRODUCTS */
|
||||
#define ALCATEL_VENDOR_ID 0x1bbb
|
||||
#define ALCATEL_PRODUCT_X060S 0x0000
|
||||
|
||||
|
||||
static struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
|
||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
|
||||
|
|
@ -428,8 +442,10 @@ static struct usb_device_id option_ids[] = {
|
|||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */
|
||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */
|
||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */
|
||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727_NEW) }, /* Novatel MC727/U727/USB727 refresh */
|
||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */
|
||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC760) }, /* Novatel MC760/U760/USB760 */
|
||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_OVMC760) }, /* Novatel Ovation MC760 */
|
||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */
|
||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */
|
||||
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, /* Novatel HSPA Embedded product */
|
||||
|
|
@ -463,42 +479,6 @@ static struct usb_device_id option_ids[] = {
|
|||
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
|
||||
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
|
||||
{ USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0003) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0004) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0005) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0006) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0007) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0008) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0009) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x000a) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x000b) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x000c) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x000d) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x000e) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x000f) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0010) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0011) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0012) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0013) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0014) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0015) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0016) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0017) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0018) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0019) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0020) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0021) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0022) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0023) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0024) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0025) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0026) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0027) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0028) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, 0x0029) },
|
||||
{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MT503HS) },
|
||||
{ USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) },
|
||||
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
|
||||
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
|
||||
|
|
@ -523,14 +503,85 @@ static struct usb_device_id option_ids[] = {
|
|||
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
|
||||
{ USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
|
||||
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622) },
|
||||
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) },
|
||||
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) },
|
||||
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0003, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0004, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0005, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0006, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0007, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0008, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0009, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000a, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000b, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000c, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000d, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000e, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000f, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0010, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0011, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0013, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0016, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0018, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0019, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0020, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0021, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0022, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0023, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0024, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0032, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0033, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0037, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0039, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0042, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0043, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0048, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0049, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0051, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0054, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0057, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0061, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0062, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0064, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0066, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0069, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0076, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0078, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0082, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0060, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
|
||||
{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
|
||||
{ USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */
|
||||
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) },
|
||||
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) },
|
||||
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) },
|
||||
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) },
|
||||
{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
|
||||
{ USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
|
||||
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, option_ids);
|
||||
|
|
@ -539,8 +590,10 @@ static struct usb_driver option_driver = {
|
|||
.name = "option",
|
||||
.probe = usb_serial_probe,
|
||||
.disconnect = usb_serial_disconnect,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = usb_serial_suspend,
|
||||
.resume = usb_serial_resume,
|
||||
#endif
|
||||
.id_table = option_ids,
|
||||
.no_dynamic_id = 1,
|
||||
};
|
||||
|
|
@ -572,8 +625,10 @@ static struct usb_serial_driver option_1port_device = {
|
|||
.disconnect = option_disconnect,
|
||||
.release = option_release,
|
||||
.read_int_callback = option_instat_callback,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = option_suspend,
|
||||
.resume = option_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int debug;
|
||||
|
|
@ -732,7 +787,6 @@ static int option_write(struct tty_struct *tty, struct usb_serial_port *port,
|
|||
memcpy(this_urb->transfer_buffer, buf, todo);
|
||||
this_urb->transfer_buffer_length = todo;
|
||||
|
||||
this_urb->dev = port->serial->dev;
|
||||
err = usb_submit_urb(this_urb, GFP_ATOMIC);
|
||||
if (err) {
|
||||
dbg("usb_submit_urb %p (write bulk) failed "
|
||||
|
|
@ -816,7 +870,6 @@ static void option_instat_callback(struct urb *urb)
|
|||
int status = urb->status;
|
||||
struct usb_serial_port *port = urb->context;
|
||||
struct option_port_private *portdata = usb_get_serial_port_data(port);
|
||||
struct usb_serial *serial = port->serial;
|
||||
|
||||
dbg("%s", __func__);
|
||||
dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata);
|
||||
|
|
@ -860,7 +913,6 @@ static void option_instat_callback(struct urb *urb)
|
|||
|
||||
/* Resubmit urb so we continue receiving IRQ data */
|
||||
if (status != -ESHUTDOWN && status != -ENOENT) {
|
||||
urb->dev = serial->dev;
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (err)
|
||||
dbg("%s: resubmit intr urb failed. (%d)",
|
||||
|
|
@ -913,7 +965,6 @@ static int option_open(struct tty_struct *tty,
|
|||
struct usb_serial_port *port, struct file *filp)
|
||||
{
|
||||
struct option_port_private *portdata;
|
||||
struct usb_serial *serial = port->serial;
|
||||
int i, err;
|
||||
struct urb *urb;
|
||||
|
||||
|
|
@ -921,23 +972,11 @@ static int option_open(struct tty_struct *tty,
|
|||
|
||||
dbg("%s", __func__);
|
||||
|
||||
/* Reset low level data toggle and start reading from endpoints */
|
||||
/* Start reading from the IN endpoint */
|
||||
for (i = 0; i < N_IN_URB; i++) {
|
||||
urb = portdata->in_urbs[i];
|
||||
if (!urb)
|
||||
continue;
|
||||
if (urb->dev != serial->dev) {
|
||||
dbg("%s: dev %p != %p", __func__,
|
||||
urb->dev, serial->dev);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* make sure endpoint data toggle is synchronized with the
|
||||
* device
|
||||
*/
|
||||
usb_clear_halt(urb->dev, urb->pipe);
|
||||
|
||||
err = usb_submit_urb(urb, GFP_KERNEL);
|
||||
if (err) {
|
||||
dbg("%s: submit urb %d failed (%d) %d",
|
||||
|
|
@ -946,16 +985,6 @@ static int option_open(struct tty_struct *tty,
|
|||
}
|
||||
}
|
||||
|
||||
/* Reset low level data toggle on out endpoints */
|
||||
for (i = 0; i < N_OUT_URB; i++) {
|
||||
urb = portdata->out_urbs[i];
|
||||
if (!urb)
|
||||
continue;
|
||||
urb->dev = serial->dev;
|
||||
/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
|
||||
usb_pipeout(urb->pipe), 0); */
|
||||
}
|
||||
|
||||
option_send_setup(port);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1195,6 +1224,7 @@ static void option_release(struct usb_serial *serial)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int option_suspend(struct usb_serial *serial, pm_message_t message)
|
||||
{
|
||||
dbg("%s entered", __func__);
|
||||
|
|
@ -1218,7 +1248,6 @@ static int option_resume(struct usb_serial *serial)
|
|||
dbg("%s: No interrupt URB for port %d\n", __func__, i);
|
||||
continue;
|
||||
}
|
||||
port->interrupt_in_urb->dev = serial->dev;
|
||||
err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
|
||||
dbg("Submitted interrupt URB for port %d (result %d)", i, err);
|
||||
if (err < 0) {
|
||||
|
|
@ -1254,6 +1283,7 @@ static int option_resume(struct usb_serial *serial)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
|
|
|
|||
|
|
@ -94,6 +94,8 @@ static struct usb_device_id id_table [] = {
|
|||
{ USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
|
||||
{ USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) },
|
||||
{ USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
|
||||
{ USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
|
||||
{ USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
|
@ -971,18 +973,46 @@ exit:
|
|||
__func__, retval);
|
||||
}
|
||||
|
||||
static void pl2303_push_data(struct tty_struct *tty,
|
||||
struct usb_serial_port *port, struct urb *urb,
|
||||
u8 line_status)
|
||||
{
|
||||
unsigned char *data = urb->transfer_buffer;
|
||||
/* get tty_flag from status */
|
||||
char tty_flag = TTY_NORMAL;
|
||||
/* break takes precedence over parity, */
|
||||
/* which takes precedence over framing errors */
|
||||
if (line_status & UART_BREAK_ERROR)
|
||||
tty_flag = TTY_BREAK;
|
||||
else if (line_status & UART_PARITY_ERROR)
|
||||
tty_flag = TTY_PARITY;
|
||||
else if (line_status & UART_FRAME_ERROR)
|
||||
tty_flag = TTY_FRAME;
|
||||
dbg("%s - tty_flag = %d", __func__, tty_flag);
|
||||
|
||||
tty_buffer_request_room(tty, urb->actual_length + 1);
|
||||
/* overrun is special, not associated with a char */
|
||||
if (line_status & UART_OVERRUN_ERROR)
|
||||
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
|
||||
if (port->console && port->sysrq) {
|
||||
int i;
|
||||
for (i = 0; i < urb->actual_length; ++i)
|
||||
if (!usb_serial_handle_sysrq_char(tty, port, data[i]))
|
||||
tty_insert_flip_char(tty, data[i], tty_flag);
|
||||
} else
|
||||
tty_insert_flip_string(tty, data, urb->actual_length);
|
||||
tty_flip_buffer_push(tty);
|
||||
}
|
||||
|
||||
static void pl2303_read_bulk_callback(struct urb *urb)
|
||||
{
|
||||
struct usb_serial_port *port = urb->context;
|
||||
struct pl2303_private *priv = usb_get_serial_port_data(port);
|
||||
struct tty_struct *tty;
|
||||
unsigned char *data = urb->transfer_buffer;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
int result;
|
||||
int status = urb->status;
|
||||
u8 line_status;
|
||||
char tty_flag;
|
||||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
|
|
@ -1010,10 +1040,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
|
|||
}
|
||||
|
||||
usb_serial_debug_data(debug, &port->dev, __func__,
|
||||
urb->actual_length, data);
|
||||
|
||||
/* get tty_flag from status */
|
||||
tty_flag = TTY_NORMAL;
|
||||
urb->actual_length, urb->transfer_buffer);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
line_status = priv->line_status;
|
||||
|
|
@ -1021,26 +1048,9 @@ static void pl2303_read_bulk_callback(struct urb *urb)
|
|||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
wake_up_interruptible(&priv->delta_msr_wait);
|
||||
|
||||
/* break takes precedence over parity, */
|
||||
/* which takes precedence over framing errors */
|
||||
if (line_status & UART_BREAK_ERROR)
|
||||
tty_flag = TTY_BREAK;
|
||||
else if (line_status & UART_PARITY_ERROR)
|
||||
tty_flag = TTY_PARITY;
|
||||
else if (line_status & UART_FRAME_ERROR)
|
||||
tty_flag = TTY_FRAME;
|
||||
dbg("%s - tty_flag = %d", __func__, tty_flag);
|
||||
|
||||
tty = tty_port_tty_get(&port->port);
|
||||
if (tty && urb->actual_length) {
|
||||
tty_buffer_request_room(tty, urb->actual_length + 1);
|
||||
/* overrun is special, not associated with a char */
|
||||
if (line_status & UART_OVERRUN_ERROR)
|
||||
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
|
||||
for (i = 0; i < urb->actual_length; ++i)
|
||||
if (!usb_serial_handle_sysrq_char(port, data[i]))
|
||||
tty_insert_flip_char(tty, data[i], tty_flag);
|
||||
tty_flip_buffer_push(tty);
|
||||
pl2303_push_data(tty, port, urb, line_status);
|
||||
}
|
||||
tty_kref_put(tty);
|
||||
/* Schedule the next read _if_ we are still open */
|
||||
|
|
|
|||
|
|
@ -122,3 +122,11 @@
|
|||
/* Hewlett-Packard LD220-HP POS Pole Display */
|
||||
#define HP_VENDOR_ID 0x03f0
|
||||
#define HP_LD220_PRODUCT_ID 0x3524
|
||||
|
||||
/* Cressi Edy (diving computer) PC interface */
|
||||
#define CRESSI_VENDOR_ID 0x04b8
|
||||
#define CRESSI_EDY_PRODUCT_ID 0x0521
|
||||
|
||||
/* Sony, USB data cable for CMD-Jxx mobile phones */
|
||||
#define SONY_VENDOR_ID 0x054c
|
||||
#define SONY_QN3USB_PRODUCT_ID 0x0437
|
||||
|
|
|
|||
|
|
@ -181,35 +181,50 @@ static const struct sierra_iface_info direct_ip_interface_blacklist = {
|
|||
};
|
||||
|
||||
static struct usb_device_id id_table [] = {
|
||||
{ USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */
|
||||
{ USB_DEVICE(0x03F0, 0x1B1D) }, /* HP ev2200 a.k.a MC5720 */
|
||||
{ USB_DEVICE(0x03F0, 0x1E1D) }, /* HP hs2300 a.k.a MC8775 */
|
||||
|
||||
{ USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
|
||||
{ USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
|
||||
{ USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
|
||||
{ USB_DEVICE(0x03f0, 0x1b1d) }, /* HP ev2200 a.k.a MC5720 */
|
||||
{ USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
|
||||
{ USB_DEVICE(0x1199, 0x0024) }, /* Sierra Wireless MC5727 */
|
||||
{ USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */
|
||||
{ USB_DEVICE(0x1199, 0x0022) }, /* Sierra Wireless EM5725 */
|
||||
{ USB_DEVICE(0x1199, 0x0024) }, /* Sierra Wireless MC5727 */
|
||||
{ USB_DEVICE(0x1199, 0x0224) }, /* Sierra Wireless MC5727 */
|
||||
{ USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
|
||||
{ USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
|
||||
{ USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
|
||||
{ USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */
|
||||
/* Sierra Wireless C597 */
|
||||
/* Sierra Wireless C597 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) },
|
||||
/* Sierra Wireless Device */
|
||||
/* Sierra Wireless T598 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0025, 0xFF, 0xFF, 0xFF) },
|
||||
{ USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless Device */
|
||||
{ USB_DEVICE(0x1199, 0x0027) }, /* Sierra Wireless Device */
|
||||
{ USB_DEVICE(0x1199, 0x0028) }, /* Sierra Wireless Device */
|
||||
{ USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless T11 */
|
||||
{ USB_DEVICE(0x1199, 0x0027) }, /* Sierra Wireless AC402 */
|
||||
{ USB_DEVICE(0x1199, 0x0028) }, /* Sierra Wireless MC5728 */
|
||||
{ USB_DEVICE(0x1199, 0x0029) }, /* Sierra Wireless Device */
|
||||
|
||||
{ USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
|
||||
{ USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
|
||||
{ USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
|
||||
{ USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
|
||||
{ USB_DEVICE(0x1199, 0x6805) }, /* Sierra Wireless MC8765 */
|
||||
{ USB_DEVICE(0x1199, 0x6808) }, /* Sierra Wireless MC8755 */
|
||||
{ USB_DEVICE(0x1199, 0x6809) }, /* Sierra Wireless MC8765 */
|
||||
{ USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */
|
||||
{ USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Lenovo) */
|
||||
{ USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 */
|
||||
{ USB_DEVICE(0x1199, 0x6815) }, /* Sierra Wireless MC8775 */
|
||||
{ USB_DEVICE(0x03f0, 0x1e1d) }, /* HP hs2300 a.k.a MC8775 */
|
||||
{ USB_DEVICE(0x1199, 0x6816) }, /* Sierra Wireless MC8775 */
|
||||
{ USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
|
||||
{ USB_DEVICE(0x1199, 0x6821) }, /* Sierra Wireless AirCard 875U */
|
||||
{ USB_DEVICE(0x1199, 0x6822) }, /* Sierra Wireless AirCard 875E */
|
||||
{ USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780 */
|
||||
{ USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */
|
||||
{ USB_DEVICE(0x1199, 0x6834) }, /* Sierra Wireless MC8780 */
|
||||
{ USB_DEVICE(0x1199, 0x6835) }, /* Sierra Wireless MC8781 */
|
||||
{ USB_DEVICE(0x1199, 0x6838) }, /* Sierra Wireless MC8780 */
|
||||
{ USB_DEVICE(0x1199, 0x6839) }, /* Sierra Wireless MC8781 */
|
||||
{ USB_DEVICE(0x1199, 0x683A) }, /* Sierra Wireless MC8785 */
|
||||
{ USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */
|
||||
/* Sierra Wireless MC8790, MC8791, MC8792 Composite */
|
||||
|
|
@ -227,16 +242,13 @@ static struct usb_device_id id_table [] = {
|
|||
{ USB_DEVICE(0x1199, 0x685A) }, /* Sierra Wireless AirCard 885 E */
|
||||
/* Sierra Wireless C885 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)},
|
||||
/* Sierra Wireless Device */
|
||||
/* Sierra Wireless C888, Air Card 501, USB 303, USB 304 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6890, 0xFF, 0xFF, 0xFF)},
|
||||
/* Sierra Wireless Device */
|
||||
/* Sierra Wireless C22/C33 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6891, 0xFF, 0xFF, 0xFF)},
|
||||
/* Sierra Wireless Device */
|
||||
/* Sierra Wireless HSPA Non-Composite Device */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
|
||||
|
||||
{ USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
|
||||
{ USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */
|
||||
|
||||
{ USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */
|
||||
{ USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */
|
||||
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
|
||||
},
|
||||
|
|
@ -814,7 +826,7 @@ static int sierra_startup(struct usb_serial *serial)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void sierra_disconnect(struct usb_serial *serial)
|
||||
static void sierra_release(struct usb_serial *serial)
|
||||
{
|
||||
int i;
|
||||
struct usb_serial_port *port;
|
||||
|
|
@ -830,7 +842,6 @@ static void sierra_disconnect(struct usb_serial *serial)
|
|||
if (!portdata)
|
||||
continue;
|
||||
kfree(portdata);
|
||||
usb_set_serial_port_data(port, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -853,7 +864,7 @@ static struct usb_serial_driver sierra_device = {
|
|||
.tiocmget = sierra_tiocmget,
|
||||
.tiocmset = sierra_tiocmset,
|
||||
.attach = sierra_startup,
|
||||
.disconnect = sierra_disconnect,
|
||||
.release = sierra_release,
|
||||
.read_int_callback = sierra_instat_callback,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -191,7 +191,6 @@ static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
|
|||
{ USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },
|
||||
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },
|
||||
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
|
||||
{ USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) },
|
||||
};
|
||||
|
||||
static struct usb_device_id ti_id_table_combined[14+2*TI_EXTRA_VID_PID_COUNT+1] = {
|
||||
|
|
@ -728,7 +727,7 @@ static int ti_write_room(struct tty_struct *tty)
|
|||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
if (tport == NULL)
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&tport->tp_lock, flags);
|
||||
room = ti_buf_space_avail(tport->tp_write_buf);
|
||||
|
|
@ -749,7 +748,7 @@ static int ti_chars_in_buffer(struct tty_struct *tty)
|
|||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
if (tport == NULL)
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&tport->tp_lock, flags);
|
||||
chars = ti_buf_data_avail(tport->tp_write_buf);
|
||||
|
|
@ -1658,7 +1657,7 @@ static int ti_do_download(struct usb_device *dev, int pipe,
|
|||
u8 cs = 0;
|
||||
int done;
|
||||
struct ti_firmware_header *header;
|
||||
int status;
|
||||
int status = 0;
|
||||
int len;
|
||||
|
||||
for (pos = sizeof(struct ti_firmware_header); pos < size; pos++)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_driver.h>
|
||||
#include <linux/tty_flip.h>
|
||||
|
|
@ -31,6 +32,7 @@
|
|||
#include <linux/mutex.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/serial.h>
|
||||
#include "pl2303.h"
|
||||
|
|
@ -183,6 +185,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
|
|||
struct usb_serial_port *port;
|
||||
unsigned int portNumber;
|
||||
int retval = 0;
|
||||
int first = 0;
|
||||
|
||||
dbg("%s", __func__);
|
||||
|
||||
|
|
@ -220,8 +223,9 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
|
|||
tty->driver_data = port;
|
||||
tty_port_tty_set(&port->port, tty);
|
||||
|
||||
if (port->port.count == 1) {
|
||||
|
||||
/* If the console is attached, the device is already open */
|
||||
if (port->port.count == 1 && !port->console) {
|
||||
first = 1;
|
||||
/* lock this module before we call it
|
||||
* this may fail, which means we must bail out,
|
||||
* safe because we are called with BKL held */
|
||||
|
|
@ -244,13 +248,21 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
|
|||
if (retval)
|
||||
goto bailout_interface_put;
|
||||
mutex_unlock(&serial->disc_mutex);
|
||||
set_bit(ASYNCB_INITIALIZED, &port->port.flags);
|
||||
}
|
||||
mutex_unlock(&port->mutex);
|
||||
/* Now do the correct tty layer semantics */
|
||||
retval = tty_port_block_til_ready(&port->port, tty, filp);
|
||||
if (retval == 0)
|
||||
if (retval == 0) {
|
||||
if (!first)
|
||||
usb_serial_put(serial);
|
||||
return 0;
|
||||
|
||||
}
|
||||
mutex_lock(&port->mutex);
|
||||
if (first == 0)
|
||||
goto bailout_mutex_unlock;
|
||||
/* Undo the initial port actions */
|
||||
mutex_lock(&serial->disc_mutex);
|
||||
bailout_interface_put:
|
||||
usb_autopm_put_interface(serial->interface);
|
||||
bailout_module_put:
|
||||
|
|
@ -338,6 +350,22 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
|
|||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
/* FIXME:
|
||||
This leaves a very narrow race. Really we should do the
|
||||
serial_do_free() on tty->shutdown(), but tty->shutdown can
|
||||
be called from IRQ context and serial_do_free can sleep.
|
||||
|
||||
The right fix is probably to make the tty free (which is rare)
|
||||
and thus tty->shutdown() occur via a work queue and simplify all
|
||||
the drivers that use it.
|
||||
*/
|
||||
if (tty_hung_up_p(filp)) {
|
||||
/* serial_hangup already called serial_down at this point.
|
||||
Another user may have already reopened the port but
|
||||
serial_do_free is refcounted */
|
||||
serial_do_free(port);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tty_port_close_start(&port->port, tty, filp) == 0)
|
||||
return;
|
||||
|
|
@ -353,7 +381,8 @@ static void serial_hangup(struct tty_struct *tty)
|
|||
struct usb_serial_port *port = tty->driver_data;
|
||||
serial_do_down(port);
|
||||
tty_port_hangup(&port->port);
|
||||
serial_do_free(port);
|
||||
/* We must not free port yet - the USB serial layer depends on it's
|
||||
continued existence */
|
||||
}
|
||||
|
||||
static int serial_write(struct tty_struct *tty, const unsigned char *buf,
|
||||
|
|
@ -392,7 +421,6 @@ static int serial_chars_in_buffer(struct tty_struct *tty)
|
|||
struct usb_serial_port *port = tty->driver_data;
|
||||
dbg("%s = port %d", __func__, port->number);
|
||||
|
||||
WARN_ON(!port->port.count);
|
||||
/* if the device was unplugged then any remaining characters
|
||||
fell out of the connector ;) */
|
||||
if (port->serial->disconnected)
|
||||
|
|
|
|||
|
|
@ -118,6 +118,9 @@ static int option_inquiry(struct us_data *us)
|
|||
|
||||
result = memcmp(buffer+8, "Option", 6);
|
||||
|
||||
if (result != 0)
|
||||
result = memcmp(buffer+8, "ZCOPTION", 8);
|
||||
|
||||
/* Read the CSW */
|
||||
usb_stor_bulk_transfer_buf(us,
|
||||
us->recv_bulk_pipe,
|
||||
|
|
|
|||
|
|
@ -961,7 +961,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
|
|||
US_BULK_GET_MAX_LUN,
|
||||
USB_DIR_IN | USB_TYPE_CLASS |
|
||||
USB_RECIP_INTERFACE,
|
||||
0, us->ifnum, us->iobuf, 1, HZ);
|
||||
0, us->ifnum, us->iobuf, 1, 10*HZ);
|
||||
|
||||
US_DEBUGP("GetMaxLUN command result is %d, data is %d\n",
|
||||
result, us->iobuf[0]);
|
||||
|
|
|
|||
|
|
@ -838,6 +838,13 @@ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001,
|
|||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_FIX_CAPACITY ),
|
||||
|
||||
/* Reported by Rogerio Brito <[email protected]> */
|
||||
UNUSUAL_DEV( 0x067b, 0x2317, 0x0001, 0x001,
|
||||
"Prolific Technology, Inc.",
|
||||
"Mass Storage Device",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_NOT_LOCKABLE ),
|
||||
|
||||
/* Reported by Richard -=[]=- <[email protected]> */
|
||||
/* Change to bcdDeviceMin (0x0100 to 0x0001) reported by
|
||||
* Thomas Bartosik <tbartdev@gmx-topmail.de> */
|
||||
|
|
|
|||
Loading…
Reference in a new issue