Commit 12f75c41 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

merge between the usb and driver model trees.

parents cdca2b1c 5d127a7f
...@@ -25,6 +25,46 @@ spinlock_t device_lock = SPIN_LOCK_UNLOCKED; ...@@ -25,6 +25,46 @@ spinlock_t device_lock = SPIN_LOCK_UNLOCKED;
#define to_dev(node) container_of(node,struct device,driver_list) #define to_dev(node) container_of(node,struct device,driver_list)
}
int driver_attach(struct device_driver * drv)
{
return bus_for_each_dev(drv->bus,drv,do_driver_attach);
}
void driver_detach(struct device_driver * drv)
{
struct list_head * node;
struct device * prev = NULL;
spin_lock(&device_lock);
list_for_each(node,&drv->devices) {
struct device * dev = get_device_locked(to_dev(node));
if (dev) {
if (prev)
list_del_init(&prev->driver_list);
spin_unlock(&device_lock);
device_detach(dev);
if (prev)
put_device(prev);
prev = dev;
spin_lock(&device_lock);
}
}
spin_unlock(&device_lock);
}
/**
* device_register - register a device
* @dev: pointer to the device structure
*
* First, make sure that the device has a parent, create
* a directory for it, then add it to the parent's list of
* children.
*
* Maintains a global list of all devices, in depth-first ordering.
* The head for that list is device_root.g_list.
*/
int device_add(struct device *dev) int device_add(struct device *dev)
{ {
int error; int error;
......
...@@ -1077,7 +1077,7 @@ static int proc_ioctl (struct dev_state *ps, void *arg) ...@@ -1077,7 +1077,7 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
driver->name, ps->dev->devnum, ctrl.ifno); driver->name, ps->dev->devnum, ctrl.ifno);
usb_device_remove(&ifp->dev); usb_device_remove(&ifp->dev);
} else } else
retval = -EINVAL; retval = -ENODATA;
break; break;
/* let kernel drivers try to (re)bind to the interface */ /* let kernel drivers try to (re)bind to the interface */
......
...@@ -847,7 +847,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) ...@@ -847,7 +847,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
ep &= USB_ENDPOINT_NUMBER_MASK; ep &= USB_ENDPOINT_NUMBER_MASK;
usb_settoggle (dev, ep, out, 0); usb_settoggle (dev, ep, out, 0);
(out ? dev->epmaxpacketout : dev->epmaxpacketin) [ep] (out ? dev->epmaxpacketout : dev->epmaxpacketin) [ep]
= iface_as->endpoint [ep].wMaxPacketSize; = iface_as->endpoint [i].wMaxPacketSize;
} }
return 0; return 0;
......
...@@ -34,17 +34,6 @@ static void inline lprintk(char *buf) ...@@ -34,17 +34,6 @@ static void inline lprintk(char *buf)
} }
} }
static int inline uhci_is_skeleton_td(struct uhci_hcd *uhci, struct uhci_td *td)
{
int i;
for (i = 0; i < UHCI_NUM_SKELTD; i++)
if (td == uhci->skeltd[i])
return 1;
return 0;
}
static int inline uhci_is_skeleton_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) static int inline uhci_is_skeleton_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
{ {
int i; int i;
...@@ -285,13 +274,14 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) ...@@ -285,13 +274,14 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
return out - buf; return out - buf;
} }
static const char *td_names[] = {"skel_int1_td", "skel_int2_td", static const char *qh_names[] = {
"skel_int4_td", "skel_int8_td", "skel_int128_qh", "skel_int64_qh",
"skel_int16_td", "skel_int32_td", "skel_int32_qh", "skel_int16_qh",
"skel_int64_td", "skel_int128_td", "skel_int8_qh", "skel_int4_qh",
"skel_int256_td", "skel_term_td" }; "skel_int2_qh", "skel_int1_qh",
static const char *qh_names[] = { "skel_ls_control_qh", "skel_hs_control_qh", "skel_ls_control_qh", "skel_hs_control_qh",
"skel_bulk_qh", "skel_term_qh" }; "skel_bulk_qh", "skel_term_qh"
};
#define show_frame_num() \ #define show_frame_num() \
if (!shown) { \ if (!shown) { \
...@@ -299,26 +289,141 @@ static const char *qh_names[] = { "skel_ls_control_qh", "skel_hs_control_qh", ...@@ -299,26 +289,141 @@ static const char *qh_names[] = { "skel_ls_control_qh", "skel_hs_control_qh",
out += sprintf(out, "- Frame %d\n", i); \ out += sprintf(out, "- Frame %d\n", i); \
} }
#define show_td_name() \
if (!shown) { \
shown = 1; \
out += sprintf(out, "- %s\n", td_names[i]); \
}
#define show_qh_name() \ #define show_qh_name() \
if (!shown) { \ if (!shown) { \
shown = 1; \ shown = 1; \
out += sprintf(out, "- %s\n", qh_names[i]); \ out += sprintf(out, "- %s\n", qh_names[i]); \
} }
static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *buf, int len)
{
struct list_head *tmp;
char *out = buf;
int count = 0;
if (len < 200)
return 0;
out += sprintf(out, "urb_priv [%p] ", urbp);
out += sprintf(out, "urb [%p] ", urbp->urb);
out += sprintf(out, "qh [%p] ", urbp->qh);
out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe));
out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe), (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT"));
switch (usb_pipetype(urbp->urb->pipe)) {
case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO "); break;
case PIPE_INTERRUPT: out += sprintf(out, "INT "); break;
case PIPE_BULK: out += sprintf(out, "BLK "); break;
case PIPE_CONTROL: out += sprintf(out, "CTL "); break;
}
out += sprintf(out, "%s", (urbp->fsbr ? "FSBR " : ""));
out += sprintf(out, "%s", (urbp->fsbr_timeout ? "FSBR_TO " : ""));
if (urbp->status != -EINPROGRESS)
out += sprintf(out, "Status=%d ", urbp->status);
//out += sprintf(out, "Inserttime=%lx ",urbp->inserttime);
//out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime);
spin_lock(&urbp->urb->lock);
count = 0;
list_for_each(tmp, &urbp->td_list)
count++;
spin_unlock(&urbp->urb->lock);
out += sprintf(out, "TDs=%d ",count);
if (urbp->queued)
out += sprintf(out, "queued\n");
else {
spin_lock(&uhci->frame_list_lock);
count = 0;
list_for_each(tmp, &urbp->queue_list)
count++;
spin_unlock(&uhci->frame_list_lock);
out += sprintf(out, "queued URBs=%d\n", count);
}
return out - buf;
}
static int uhci_show_lists(struct uhci_hcd *uhci, char *buf, int len)
{
char *out = buf;
unsigned long flags;
struct list_head *head, *tmp;
int count;
out += sprintf(out, "Main list URBs:");
spin_lock_irqsave(&uhci->urb_list_lock, flags);
if (list_empty(&uhci->urb_list))
out += sprintf(out, " Empty\n");
else {
out += sprintf(out, "\n");
count = 0;
head = &uhci->urb_list;
tmp = head->next;
while (tmp != head) {
struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
out += sprintf(out, " %d: ", ++count);
out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
tmp = tmp->next;
}
}
spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
out += sprintf(out, "Remove list URBs:");
spin_lock_irqsave(&uhci->urb_remove_list_lock, flags);
if (list_empty(&uhci->urb_remove_list))
out += sprintf(out, " Empty\n");
else {
out += sprintf(out, "\n");
count = 0;
head = &uhci->urb_remove_list;
tmp = head->next;
while (tmp != head) {
struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
out += sprintf(out, " %d: ", ++count);
out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
tmp = tmp->next;
}
}
spin_unlock_irqrestore(&uhci->urb_remove_list_lock, flags);
out += sprintf(out, "Complete list URBs:");
spin_lock_irqsave(&uhci->complete_list_lock, flags);
if (list_empty(&uhci->complete_list))
out += sprintf(out, " Empty\n");
else {
out += sprintf(out, "\n");
count = 0;
head = &uhci->complete_list;
tmp = head->next;
while (tmp != head) {
struct urb_priv *urbp = list_entry(tmp, struct urb_priv, complete_list);
out += sprintf(out, " %d: ", ++count);
out += uhci_show_urbp(uhci, urbp, out, len - (out - buf));
tmp = tmp->next;
}
}
spin_unlock_irqrestore(&uhci->complete_list_lock, flags);
return out - buf;
}
static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
{ {
unsigned long flags;
char *out = buf; char *out = buf;
int i; int i;
struct uhci_qh *qh; struct uhci_qh *qh;
struct uhci_td *td; struct uhci_td *td;
struct list_head *tmp, *head; struct list_head *tmp, *head;
spin_lock_irqsave(&uhci->frame_list_lock, flags);
out += sprintf(out, "HC status\n"); out += sprintf(out, "HC status\n");
out += uhci_show_status(uhci, out, len - (out - buf)); out += uhci_show_status(uhci, out, len - (out - buf));
...@@ -333,8 +438,6 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) ...@@ -333,8 +438,6 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
show_frame_num(); show_frame_num();
out += sprintf(out, " frame list does not match td->dma_handle!\n"); out += sprintf(out, " frame list does not match td->dma_handle!\n");
} }
if (uhci_is_skeleton_td(uhci, td))
continue;
show_frame_num(); show_frame_num();
head = &td->fl_list; head = &td->fl_list;
...@@ -346,67 +449,6 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) ...@@ -346,67 +449,6 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
} while (tmp != head); } while (tmp != head);
} }
out += sprintf(out, "Skeleton TD's\n");
for (i = UHCI_NUM_SKELTD - 1; i >= 0; i--) {
int shown = 0;
td = uhci->skeltd[i];
if (debug > 1) {
show_td_name();
out += uhci_show_td(td, out, len - (out - buf), 4);
}
if (list_empty(&td->fl_list)) {
/* TD 0 is the int1 TD and links to control_ls_qh */
if (!i) {
if (td->link !=
(cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH)) {
show_td_name();
out += sprintf(out, " skeleton TD not linked to ls_control QH!\n");
}
} else if (i < 9) {
if (td->link != cpu_to_le32(uhci->skeltd[i - 1]->dma_handle)) {
show_td_name();
out += sprintf(out, " skeleton TD not linked to next skeleton TD!\n");
}
} else {
show_td_name();
if (td->link != cpu_to_le32(td->dma_handle))
out += sprintf(out, " skel_term_td does not link to self\n");
/* Don't show it twice */
if (debug <= 1)
out += uhci_show_td(td, out, len - (out - buf), 4);
}
continue;
}
show_td_name();
head = &td->fl_list;
tmp = head->next;
while (tmp != head) {
td = list_entry(tmp, struct uhci_td, fl_list);
tmp = tmp->next;
out += uhci_show_td(td, out, len - (out - buf), 4);
}
if (!i) {
if (td->link !=
(cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH))
out += sprintf(out, " last TD not linked to ls_control QH!\n");
} else if (i < 9) {
if (td->link != cpu_to_le32(uhci->skeltd[i - 1]->dma_handle))
out += sprintf(out, " last TD not linked to next skeleton!\n");
}
}
out += sprintf(out, "Skeleton QH's\n"); out += sprintf(out, "Skeleton QH's\n");
for (i = 0; i < UHCI_NUM_SKELQH; ++i) { for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
...@@ -419,21 +461,19 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) ...@@ -419,21 +461,19 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
out += uhci_show_qh(qh, out, len - (out - buf), 4); out += uhci_show_qh(qh, out, len - (out - buf), 4);
} }
/* QH 3 is the Terminating QH, it's different */ /* Last QH is the Terminating QH, it's different */
if (i == 3) { if (i == UHCI_NUM_SKELQH - 1) {
if (qh->link != UHCI_PTR_TERM) { if (qh->link != UHCI_PTR_TERM)
show_qh_name();
out += sprintf(out, " bandwidth reclamation on!\n"); out += sprintf(out, " bandwidth reclamation on!\n");
}
if (qh->element != cpu_to_le32(uhci->skel_term_td->dma_handle)) { if (qh->element != cpu_to_le32(uhci->term_td->dma_handle))
show_qh_name(); out += sprintf(out, " skel_term_qh element is not set to term_td!\n");
out += sprintf(out, " skel_term_qh element is not set to skel_term_td\n");
} continue;
} }
if (list_empty(&qh->list)) { if (list_empty(&qh->list)) {
if (i < 3) { if (i < UHCI_NUM_SKELQH - 1) {
if (qh->link != if (qh->link !=
(cpu_to_le32(uhci->skelqh[i + 1]->dma_handle) | UHCI_PTR_QH)) { (cpu_to_le32(uhci->skelqh[i + 1]->dma_handle) | UHCI_PTR_QH)) {
show_qh_name(); show_qh_name();
...@@ -457,18 +497,23 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) ...@@ -457,18 +497,23 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
out += uhci_show_qh(qh, out, len - (out - buf), 4); out += uhci_show_qh(qh, out, len - (out - buf), 4);
} }
if (i < 3) { if (i < UHCI_NUM_SKELQH - 1) {
if (qh->link != if (qh->link !=
(cpu_to_le32(uhci->skelqh[i + 1]->dma_handle) | UHCI_PTR_QH)) (cpu_to_le32(uhci->skelqh[i + 1]->dma_handle) | UHCI_PTR_QH))
out += sprintf(out, " last QH not linked to next skeleton!\n"); out += sprintf(out, " last QH not linked to next skeleton!\n");
} }
} }
spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
if (debug > 2)
out += uhci_show_lists(uhci, out, len - (out - buf));
return out - buf; return out - buf;
} }
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
#define MAX_OUTPUT (PAGE_SIZE * 8) #define MAX_OUTPUT (PAGE_SIZE * 16)
static struct proc_dir_entry *uhci_proc_root = NULL; static struct proc_dir_entry *uhci_proc_root = NULL;
...@@ -483,7 +528,6 @@ static int uhci_proc_open(struct inode *inode, struct file *file) ...@@ -483,7 +528,6 @@ static int uhci_proc_open(struct inode *inode, struct file *file)
const struct proc_dir_entry *dp = PDE(inode); const struct proc_dir_entry *dp = PDE(inode);
struct uhci_hcd *uhci = dp->data; struct uhci_hcd *uhci = dp->data;
struct uhci_proc *up; struct uhci_proc *up;
unsigned long flags;
int ret = -ENOMEM; int ret = -ENOMEM;
lock_kernel(); lock_kernel();
...@@ -497,9 +541,7 @@ static int uhci_proc_open(struct inode *inode, struct file *file) ...@@ -497,9 +541,7 @@ static int uhci_proc_open(struct inode *inode, struct file *file)
goto out; goto out;
} }
spin_lock_irqsave(&uhci->frame_list_lock, flags);
up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT); up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
file->private_data = up; file->private_data = up;
......
This diff is collapsed.
...@@ -81,7 +81,8 @@ struct uhci_frame_list { ...@@ -81,7 +81,8 @@ struct uhci_frame_list {
struct urb_priv; struct urb_priv;
/* One role of a QH is to hold a queue of TDs for some endpoint. Each QH is /*
* One role of a QH is to hold a queue of TDs for some endpoint. Each QH is
* used with one URB, and qh->element (updated by the HC) is either: * used with one URB, and qh->element (updated by the HC) is either:
* - the next unprocessed TD for the URB, or * - the next unprocessed TD for the URB, or
* - UHCI_PTR_TERM (when there's no more traffic for this endpoint), or * - UHCI_PTR_TERM (when there's no more traffic for this endpoint), or
...@@ -194,85 +195,63 @@ struct uhci_td { ...@@ -194,85 +195,63 @@ struct uhci_td {
} __attribute__((aligned(16))); } __attribute__((aligned(16)));
/* /*
* There are various standard queues. We set up several different * The UHCI driver places Interrupt, Control and Bulk into QH's both
* queues for each of the three basic queue types: interrupt, * to group together TD's for one transfer, and also to faciliate queuing
* control, and bulk. * of URB's. To make it easy to insert entries into the schedule, we have
* * a skeleton of QH's for each predefined Interrupt latency, low speed
* - There are various different interrupt latencies: ranging from * control, high speed control and terminating QH (see explanation for
* every other USB frame (2 ms apart) to every 256 USB frames (ie * the terminating QH below).
* 256 ms apart). Make your choice according to how obnoxious you
* want to be on the wire, vs how critical latency is for you.
* - The control list is done every frame.
* - There are 4 bulk lists, so that up to four devices can have a
* bulk list of their own and when run concurrently all four lists
* will be be serviced.
*
* This is a bit misleading, there are various interrupt latencies, but they
* vary a bit, interrupt2 isn't exactly 2ms, it can vary up to 4ms since the
* other queues can "override" it. interrupt4 can vary up to 8ms, etc. Minor
* problem
*
* In the case of the root hub, these QH's are just head's of qh's. Don't
* be scared, it kinda makes sense. Look at this wonderful picture care of
* Linus:
* *
* generic- -> dev1- -> generic- -> dev1- -> control- -> bulk- -> ... * When we want to add a new QH, we add it to the end of the list for the
* iso-QH iso-QH irq-QH irq-QH QH QH * skeleton QH.
* | | | | | |
* End dev1-iso-TD1 End dev1-irq-TD1 ... ...
* |
* dev1-iso-TD2
* |
* ....
* *
* This may vary a bit (the UHCI docs don't explicitly say you can put iso * For instance, the queue can look like this:
* transfers in QH's and all of their pictures don't have that either) but
* other than that, that is what we're doing now
* *
* And now we don't put Iso transfers in QH's, so we don't waste one on it * skel int128 QH
* --jerdfelt * dev 1 interrupt QH
* dev 5 interrupt QH
* skel int64 QH
* skel int32 QH
* ...
* skel int1 QH
* skel low speed control QH
* dev 5 control QH
* skel high speed control QH
* skel bulk QH
* dev 1 bulk QH
* dev 2 bulk QH
* skel terminating QH
* *
* To keep with Linus' nomenclature, this is called the QH skeleton. These * The terminating QH is used for 2 reasons:
* labels (below) are only signficant to the root hub's QH's * - To place a terminating TD which is used to workaround a PIIX bug
* (see Intel errata for explanation)
* - To loop back to the high speed control queue for full speed bandwidth
* reclamation
* *
* * Isochronous transfers are stored before the start of the skeleton
* NOTE: That ASCII art doesn't match the current (August 2002) code, in * schedule and don't use QH's. While the UHCI spec doesn't forbid the
* more ways than just not using QHs for ISO. * use of QH's for Isochronous, it doesn't use them either. Since we don't
* * need to use them either, we follow the spec diagrams in hope that it'll
* NOTE: Another way to look at the UHCI schedules is to compare them to what * be more compatible with future UHCI implementations.
* other host controller interfaces use. EHCI, OHCI, and UHCI all have tables
* of transfers that the controller scans, frame by frame, and which hold the
* scheduled periodic transfers. The key differences are that UHCI
*
* (a) puts control and bulk transfers into that same table; the others
* have separate data structures for non-periodic transfers.
* (b) lets QHs be linked from TDs, not just other QHs, since they don't
* hold endpoint data. this driver chooses to use one QH per URB.
* (c) needs more TDs, since it uses one per packet. the data toggle
* is stored in those TDs, along with all other endpoint state.
*/ */
#define UHCI_NUM_SKELTD 10 #define UHCI_NUM_SKELQH 12
#define skel_int1_td skeltd[0] #define skel_int128_qh skelqh[0]
#define skel_int2_td skeltd[1] #define skel_int64_qh skelqh[1]
#define skel_int4_td skeltd[2] #define skel_int32_qh skelqh[2]
#define skel_int8_td skeltd[3] #define skel_int16_qh skelqh[3]
#define skel_int16_td skeltd[4] #define skel_int8_qh skelqh[4]
#define skel_int32_td skeltd[5] #define skel_int4_qh skelqh[5]
#define skel_int64_td skeltd[6] #define skel_int2_qh skelqh[6]
#define skel_int128_td skeltd[7] #define skel_int1_qh skelqh[7]
#define skel_int256_td skeltd[8] #define skel_ls_control_qh skelqh[8]
#define skel_term_td skeltd[9] /* To work around PIIX UHCI bug */ #define skel_hs_control_qh skelqh[9]
#define skel_bulk_qh skelqh[10]
#define UHCI_NUM_SKELQH 4 #define skel_term_qh skelqh[11]
#define skel_ls_control_qh skelqh[0]
#define skel_hs_control_qh skelqh[1]
#define skel_bulk_qh skelqh[2]
#define skel_term_qh skelqh[3]
/* /*
* Search tree for determining where <interval> fits in the * Search tree for determining where <interval> fits in the skelqh[]
* skelqh[] skeleton. * skeleton.
* *
* An interrupt request should be placed into the slowest skelqh[] * An interrupt request should be placed into the slowest skelqh[]
* which meets the interval/period/frequency requirement. * which meets the interval/period/frequency requirement.
...@@ -280,32 +259,27 @@ struct uhci_td { ...@@ -280,32 +259,27 @@ struct uhci_td {
* *
* For a given <interval>, this function returns the appropriate/matching * For a given <interval>, this function returns the appropriate/matching
* skelqh[] index value. * skelqh[] index value.
*
* NOTE: For UHCI, we don't really need int256_qh since the maximum interval
* is 255 ms. However, we do need an int1_qh since 1 is a valid interval
* and we should meet that frequency when requested to do so.
* This will require some change(s) to the UHCI skeleton.
*/ */
static inline int __interval_to_skel(int interval) static inline int __interval_to_skel(int interval)
{ {
if (interval < 16) { if (interval < 16) {
if (interval < 4) { if (interval < 4) {
if (interval < 2) if (interval < 2)
return 0; /* int1 for 0-1 ms */ return 7; /* int1 for 0-1 ms */
return 1; /* int2 for 2-3 ms */ return 6; /* int2 for 2-3 ms */
} }
if (interval < 8) if (interval < 8)
return 2; /* int4 for 4-7 ms */ return 5; /* int4 for 4-7 ms */
return 3; /* int8 for 8-15 ms */ return 4; /* int8 for 8-15 ms */
} }
if (interval < 64) { if (interval < 64) {
if (interval < 32) if (interval < 32)
return 4; /* int16 for 16-31 ms */ return 3; /* int16 for 16-31 ms */
return 5; /* int32 for 32-63 ms */ return 2; /* int32 for 32-63 ms */
} }
if (interval < 128) if (interval < 128)
return 6; /* int64 for 64-127 ms */ return 1; /* int64 for 64-127 ms */
return 7; /* int128 for 128-255 ms (Max.) */ return 0; /* int128 for 128-255 ms (Max.) */
} }
#define hcd_to_uhci(hcd_ptr) container_of(hcd_ptr, struct uhci_hcd, hcd) #define hcd_to_uhci(hcd_ptr) container_of(hcd_ptr, struct uhci_hcd, hcd)
...@@ -332,7 +306,7 @@ struct uhci_hcd { ...@@ -332,7 +306,7 @@ struct uhci_hcd {
struct usb_bus *bus; struct usb_bus *bus;
struct uhci_td *skeltd[UHCI_NUM_SKELTD]; /* Skeleton TD's */ struct uhci_td *term_td; /* Terminating TD, see UHCI bug */
struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */
spinlock_t frame_list_lock; spinlock_t frame_list_lock;
......
...@@ -63,7 +63,8 @@ CONFIG_USB_KBD ...@@ -63,7 +63,8 @@ CONFIG_USB_KBD
to use the generic HID driver for your USB keyboard and prefer to use the generic HID driver for your USB keyboard and prefer
to use the keyboard in its limited Boot Protocol mode instead. to use the keyboard in its limited Boot Protocol mode instead.
This is almost certainly not what you want. This is almost certainly not what you want. This is mostly
useful for embedded applications or simple keyboards.
This code is also available as a module ( = code which can be This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want). inserted in and removed from the running kernel whenever you want).
...@@ -77,7 +78,8 @@ CONFIG_USB_MOUSE ...@@ -77,7 +78,8 @@ CONFIG_USB_MOUSE
to use the generic HID driver for your USB keyboard and prefer to use the generic HID driver for your USB keyboard and prefer
to use the keyboard in its limited Boot Protocol mode instead. to use the keyboard in its limited Boot Protocol mode instead.
This is almost certainly not what you want. This is almost certainly not what you want. This is mostly
useful for embedded applications or simple mice.
This code is also available as a module ( = code which can be This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want). inserted in and removed from the running kernel whenever you want).
......
...@@ -15,8 +15,11 @@ dep_mbool ' Logitech WingMan *3D support' CONFIG_LOGITECH_FF $CONFIG_USB_ ...@@ -15,8 +15,11 @@ dep_mbool ' Logitech WingMan *3D support' CONFIG_LOGITECH_FF $CONFIG_USB_
dep_mbool ' /dev/hiddev raw HID device support' CONFIG_USB_HIDDEV $CONFIG_USB_HID dep_mbool ' /dev/hiddev raw HID device support' CONFIG_USB_HIDDEV $CONFIG_USB_HID
if [ "$CONFIG_USB_HID" != "y" ]; then if [ "$CONFIG_USB_HID" != "y" ]; then
dep_tristate ' USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT mainmenu_option next_comment
dep_tristate ' USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT comment 'USB HID Boot Protocol drivers'
dep_tristate ' USB HIDBP Keyboard (simple Boot) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
dep_tristate ' USB HIDBP Mouse (simple Boot) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
endmenu
fi fi
dep_tristate ' Aiptek 6000U/8000U tablet support' CONFIG_USB_AIPTEK $CONFIG_USB $CONFIG_INPUT dep_tristate ' Aiptek 6000U/8000U tablet support' CONFIG_USB_AIPTEK $CONFIG_USB $CONFIG_INPUT
......
...@@ -109,7 +109,7 @@ static struct urb *simple_alloc_urb ( ...@@ -109,7 +109,7 @@ static struct urb *simple_alloc_urb (
usb_fill_bulk_urb (urb, udev, pipe, 0, bytes, simple_callback, 0); usb_fill_bulk_urb (urb, udev, pipe, 0, bytes, simple_callback, 0);
urb->interval = (udev->speed == USB_SPEED_HIGH) urb->interval = (udev->speed == USB_SPEED_HIGH)
? (INTERRUPT_RATE << 3) ? (INTERRUPT_RATE << 3)
: INTERRUPT_RATE, : INTERRUPT_RATE;
urb->transfer_flags = URB_NO_DMA_MAP; urb->transfer_flags = URB_NO_DMA_MAP;
if (usb_pipein (pipe)) if (usb_pipein (pipe))
urb->transfer_flags |= URB_SHORT_NOT_OK; urb->transfer_flags |= URB_SHORT_NOT_OK;
...@@ -142,7 +142,7 @@ static int simple_io ( ...@@ -142,7 +142,7 @@ static int simple_io (
int retval = 0; int retval = 0;
urb->context = &completion; urb->context = &completion;
while (iterations-- > 0 && retval == 0) { while (retval == 0 && iterations-- > 0) {
init_completion (&completion); init_completion (&completion);
if ((retval = usb_submit_urb (urb, SLAB_KERNEL)) != 0) if ((retval = usb_submit_urb (urb, SLAB_KERNEL)) != 0)
break; break;
...@@ -155,7 +155,7 @@ static int simple_io ( ...@@ -155,7 +155,7 @@ static int simple_io (
if (vary) { if (vary) {
int len = urb->transfer_buffer_length; int len = urb->transfer_buffer_length;
len += max; len += vary;
len %= max; len %= max;
if (len == 0) if (len == 0)
len = (vary < max) ? vary : max; len = (vary < max) ? vary : max;
...@@ -347,7 +347,7 @@ static int set_altsetting (struct usbtest_dev *dev, int alternate) ...@@ -347,7 +347,7 @@ static int set_altsetting (struct usbtest_dev *dev, int alternate)
ep &= USB_ENDPOINT_NUMBER_MASK; ep &= USB_ENDPOINT_NUMBER_MASK;
usb_settoggle (udev, ep, out, 0); usb_settoggle (udev, ep, out, 0);
(out ? udev->epmaxpacketout : udev->epmaxpacketin ) [ep] (out ? udev->epmaxpacketout : udev->epmaxpacketin ) [ep]
= iface_as->endpoint [ep].wMaxPacketSize; = iface_as->endpoint [i].wMaxPacketSize;
} }
return 0; return 0;
...@@ -659,7 +659,7 @@ static int usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *b ...@@ -659,7 +659,7 @@ static int usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *b
break; break;
dbg ("%s TEST 4: read/%d 0..%d bytes %u times", dev->id, dbg ("%s TEST 4: read/%d 0..%d bytes %u times", dev->id,
param->vary, param->length, param->iterations); param->vary, param->length, param->iterations);
urb = simple_alloc_urb (udev, dev->out_pipe, param->length); urb = simple_alloc_urb (udev, dev->in_pipe, param->length);
if (!urb) { if (!urb) {
retval = -ENOMEM; retval = -ENOMEM;
break; break;
...@@ -907,6 +907,14 @@ static struct usbtest_info ez2_info = { ...@@ -907,6 +907,14 @@ static struct usbtest_info ez2_info = {
.alt = 1, .alt = 1,
}; };
/* ezusb family device with dedicated usb test firmware*/
static struct usbtest_info fw_info = {
.name = "usb test device",
.ep_in = 2,
.ep_out = 2,
.alt = 0,
};
#ifdef IBOT2 #ifdef IBOT2
/* this is a nice source of high speed bulk data; /* this is a nice source of high speed bulk data;
* uses an FX2, with firmware provided in the device * uses an FX2, with firmware provided in the device
...@@ -962,6 +970,11 @@ static struct usb_device_id id_table [] = { ...@@ -962,6 +970,11 @@ static struct usb_device_id id_table [] = {
.driver_info = (unsigned long) &ez2_info, .driver_info = (unsigned long) &ez2_info,
}, },
/* re-enumerated usb test device firmware */
{ USB_DEVICE (0xfff0, 0xfff0),
.driver_info = (unsigned long) &fw_info,
},
#ifdef KEYSPAN_19Qi #ifdef KEYSPAN_19Qi
/* Keyspan 19qi uses an21xx (original EZ-USB) */ /* Keyspan 19qi uses an21xx (original EZ-USB) */
// this does not coexist with the real Keyspan 19qi driver! // this does not coexist with the real Keyspan 19qi driver!
......
...@@ -135,6 +135,7 @@ struct usb_eth_dev { ...@@ -135,6 +135,7 @@ struct usb_eth_dev {
#define VENDOR_SMC 0x0707 #define VENDOR_SMC 0x0707
#define VENDOR_SOHOWARE 0x15e8 #define VENDOR_SOHOWARE 0x15e8
#define VENDOR_SIEMENS 0x067c #define VENDOR_SIEMENS 0x067c
#define VENDOR_JTEC 0x11ad
#else /* PEGASUS_DEV */ #else /* PEGASUS_DEV */
...@@ -257,6 +258,8 @@ PEGASUS_DEV( "SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110, ...@@ -257,6 +258,8 @@ PEGASUS_DEV( "SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110,
DEFAULT_GPIO_RESET | PEGASUS_II ) DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001, PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001,
DEFAULT_GPIO_RESET | PEGASUS_II ) DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "FA8101 USB To ETHERNET", VENDOR_JTEC, 0x8101,
DEFAULT_GPIO_RESET | PEGASUS_II )
#endif /* PEGASUS_DEV */ #endif /* PEGASUS_DEV */
...@@ -647,6 +647,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, ...@@ -647,6 +647,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
/* no error code, so we must have transferred some data, /* no error code, so we must have transferred some data,
* just not all of it */ * just not all of it */
US_DEBUGP("-- transferred only %d bytes\n", partial);
return USB_STOR_XFER_SHORT; return USB_STOR_XFER_SHORT;
} }
...@@ -654,15 +655,15 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, ...@@ -654,15 +655,15 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
* Transfer an entire SCSI command's worth of data payload over the bulk * Transfer an entire SCSI command's worth of data payload over the bulk
* pipe. * pipe.
* *
* Note that this uses usb_stor_transfer_buf to achieve its goals -- this * Note that this uses usb_stor_bulk_transfer_buf to achieve its goals --
* function simply determines if we're going to use scatter-gather or not, * this function simply determines if we're going to use scatter-gather or not,
* and acts appropriately. For now, it also re-interprets the error codes. * and acts appropriately.
*/ */
int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe, int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
char *buf, unsigned int length_left, int use_sg, int *residual) char *buf, unsigned int length_left, int use_sg, int *residual)
{ {
int i; int i;
int result = -1; int result = USB_STOR_XFER_ERROR;
struct scatterlist *sg; struct scatterlist *sg;
unsigned int amount; unsigned int amount;
unsigned int partial; unsigned int partial;
...@@ -1046,9 +1047,11 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -1046,9 +1047,11 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
/* DATA STAGE */ /* DATA STAGE */
/* transfer the data payload for this command, if one exists*/ /* transfer the data payload for this command, if one exists*/
if (transfer_length > 0) { if (transfer_length) {
result = usb_stor_bulk_transfer_srb(us, us->send_bulk_pipe, unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ?
srb, transfer_length); us->recv_bulk_pipe : us->send_bulk_pipe;
result = usb_stor_bulk_transfer_srb(us, pipe, srb,
transfer_length);
US_DEBUGP("CBI data stage result is 0x%x\n", result); US_DEBUGP("CBI data stage result is 0x%x\n", result);
/* report any errors */ /* report any errors */
...@@ -1140,6 +1143,7 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -1140,6 +1143,7 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { if (atomic_read(&us->sm_state) == US_STATE_ABORTING) {
US_DEBUGP("usb_stor_CB_transport(): transfer aborted\n"); US_DEBUGP("usb_stor_CB_transport(): transfer aborted\n");
return USB_STOR_TRANSPORT_ABORTED; return USB_STOR_TRANSPORT_ABORTED;
}
if (result != USB_STOR_XFER_GOOD) { if (result != USB_STOR_XFER_GOOD) {
/* Uh oh... serious problem here */ /* Uh oh... serious problem here */
...@@ -1148,9 +1152,11 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -1148,9 +1152,11 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
/* DATA STAGE */ /* DATA STAGE */
/* transfer the data payload for this command, if one exists*/ /* transfer the data payload for this command, if one exists*/
if (transfer_length) if (transfer_length) {
result = usb_stor_bulk_transfer_srb(us, us->send_bulk_pipe, unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ?
srb, transfer_length); us->recv_bulk_pipe : us->send_bulk_pipe;
result = usb_stor_bulk_transfer_srb(us, pipe, srb,
transfer_length);
US_DEBUGP("CB data stage result is 0x%x\n", result); US_DEBUGP("CB data stage result is 0x%x\n", result);
/* report any errors */ /* report any errors */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment