diff options
| author | Greg Kroah-Hartman <greg@kroah.com> | 2003-05-01 18:34:59 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <greg@kroah.com> | 2003-05-01 18:34:59 -0700 |
| commit | 7324c128b3f0f5013dd1f552a7a714d5a1bda50b (patch) | |
| tree | 57936d73ef93950a24e442440eaac0658a2627ed | |
| parent | ec381992dfd6bd827579cb0278541b2ae605b5d2 (diff) | |
| parent | 6971329b2f73dffddf26538e0099457fe3a87b32 (diff) | |
Merge gregkh@kernel.bkbits.net:/home/gregkh/linux/linus-2.5
into kroah.com:/home/greg/linux/BK/gregkh-2.5
| -rw-r--r-- | drivers/usb/host/ehci-hcd.c | 24 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-q.c | 35 | ||||
| -rw-r--r-- | drivers/usb/host/ehci.h | 51 | ||||
| -rw-r--r-- | drivers/usb/media/vicam.c | 30 | ||||
| -rw-r--r-- | drivers/usb/storage/unusual_devs.h | 28 |
5 files changed, 99 insertions, 69 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index f2fc3aa6e663..9ce8a6876ee6 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -116,8 +116,10 @@ static const char hcd_name [] = "ehci-hcd"; #define EHCI_TUNE_MULT_TT 1 #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ -#define EHCI_WATCHDOG_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ +#define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ +#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ +#define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ /* Initial IRQ latency: lower than default */ static int log2_irq_thresh = 0; // 0 to 6 @@ -266,16 +268,13 @@ static void ehci_watchdog (unsigned long param) } } + /* stop async processing after it's idled a bit */ + if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) + start_unlink_async (ehci, ehci->async); + + /* ehci could run by timer, without IRQs ... */ ehci_work (ehci, NULL); - if (ehci->reclaim && !timer_pending (&ehci->watchdog)) - mod_timer (&ehci->watchdog, - jiffies + EHCI_WATCHDOG_JIFFIES); - /* stop async processing after it's idled a while */ - else if (ehci->async_idle) { - start_unlink_async (ehci, ehci->async); - ehci->async_idle = 0; - } spin_unlock_irqrestore (&ehci->lock, flags); } @@ -658,11 +657,18 @@ static int ehci_resume (struct usb_hcd *hcd) */ static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs) { + timer_action_done (ehci, TIMER_IO_WATCHDOG); if (ehci->reclaim_ready) end_unlink_async (ehci, regs); scan_async (ehci, regs); if (ehci->next_uframe != -1) scan_periodic (ehci, regs); + + /* the IO watchdog guards against hardware or driver bugs that + * misplace IRQs, and should let us run completely without IRQs. + */ + if ((ehci->async->qh_next.ptr != 0) || (ehci->periodic_sched != 0)) + timer_action (ehci, TIMER_IO_WATCHDOG); } /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index d9e4c58fd0db..b2243ca6bef8 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -706,8 +706,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) /* (re)start the async schedule? */ head = ehci->async; - if (ehci->async_idle) - del_timer (&ehci->watchdog); + timer_action_done (ehci, TIMER_ASYNC_OFF); if (!head->qh_next.qh) { u32 cmd = readl (&ehci->regs->command); @@ -733,8 +732,6 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) qh->qh_state = QH_STATE_LINKED; /* qtd completions reported later by interrupt */ - - ehci->async_idle = 0; } /*-------------------------------------------------------------------------*/ @@ -915,7 +912,7 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs) struct ehci_qh *qh = ehci->reclaim; struct ehci_qh *next; - del_timer (&ehci->watchdog); + timer_action_done (ehci, TIMER_IAA_WATCHDOG); // qh->hw_next = cpu_to_le32 (qh->qh_dma); qh->qh_state = QH_STATE_IDLE; @@ -940,12 +937,8 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs) * active but idle for a while once it empties. */ if (HCD_IS_RUNNING (ehci->hcd.state) - && ehci->async->qh_next.qh == 0 - && !timer_pending (&ehci->watchdog)) { - ehci->async_idle = 1; - mod_timer (&ehci->watchdog, - jiffies + EHCI_ASYNC_JIFFIES); - } + && ehci->async->qh_next.qh == 0) + timer_action (ehci, TIMER_ASYNC_OFF); } if (next) @@ -980,6 +973,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) wmb (); // handshake later, if we need to } + timer_action_done (ehci, TIMER_ASYNC_OFF); return; } @@ -1005,9 +999,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) ehci->reclaim_ready = 0; cmd |= CMD_IAAD; writel (cmd, &ehci->regs->command); - /* posted write need not be known to HC yet ... */ - - mod_timer (&ehci->watchdog, jiffies + EHCI_WATCHDOG_JIFFIES); + (void) readl (&ehci->regs->command); + timer_action (ehci, TIMER_IAA_WATCHDOG); } /*-------------------------------------------------------------------------*/ @@ -1016,10 +1009,11 @@ static void scan_async (struct ehci_hcd *ehci, struct pt_regs *regs) { struct ehci_qh *qh; - int unlink_delay = 0; + enum ehci_timer_action action = TIMER_IO_WATCHDOG; if (!++(ehci->stamp)) ehci->stamp++; + timer_action_done (ehci, TIMER_ASYNC_SHRINK); rescan: qh = ehci->async->qh_next.qh; if (likely (qh != 0)) { @@ -1051,17 +1045,14 @@ rescan: */ if (list_empty (&qh->qtd_list)) { if (qh->stamp == ehci->stamp) - unlink_delay = 1; - else if (!ehci->reclaim) { + action = TIMER_ASYNC_SHRINK; + else if (!ehci->reclaim) start_unlink_async (ehci, qh); - unlink_delay = 0; - } } qh = qh->qh_next.qh; } while (qh); } - - if (unlink_delay && !timer_pending (&ehci->watchdog)) - mod_timer (&ehci->watchdog, jiffies + EHCI_WATCHDOG_JIFFIES/2); + if (action == TIMER_ASYNC_SHRINK) + timer_action (ehci, TIMER_ASYNC_SHRINK); } diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 72d51be569de..c730b7ea5a2c 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -52,8 +52,7 @@ struct ehci_hcd { /* one per controller */ /* async schedule support */ struct ehci_qh *async; struct ehci_qh *reclaim; - int reclaim_ready : 1, - async_idle : 1; + int reclaim_ready : 1; /* periodic schedule support */ #define DEFAULT_I_TDPS 1024 /* some HCs can do less */ @@ -83,6 +82,7 @@ struct ehci_hcd { /* one per controller */ struct timer_list watchdog; struct notifier_block reboot_notifier; + unsigned long actions; unsigned stamp; /* irq statistics */ @@ -100,6 +100,53 @@ struct ehci_hcd { /* one per controller */ /* NOTE: urb->transfer_flags expected to not use this bit !!! */ #define EHCI_STATE_UNLINK 0x8000 /* urb being unlinked */ +enum ehci_timer_action { + TIMER_IO_WATCHDOG, + TIMER_IAA_WATCHDOG, + TIMER_ASYNC_SHRINK, + TIMER_ASYNC_OFF, +}; + +static inline void +timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action) +{ + clear_bit (action, &ehci->actions); +} + +static inline void +timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) +{ + if (!test_and_set_bit (action, &ehci->actions)) { + unsigned long t; + + switch (action) { + case TIMER_IAA_WATCHDOG: + t = EHCI_IAA_JIFFIES; + break; + case TIMER_IO_WATCHDOG: + t = EHCI_IO_JIFFIES; + break; + case TIMER_ASYNC_OFF: + t = EHCI_ASYNC_JIFFIES; + break; + // case TIMER_ASYNC_SHRINK: + default: + t = EHCI_SHRINK_JIFFIES; + break; + } + t += jiffies; + // all timings except IAA watchdog can be overridden. + // async queue SHRINK often precedes IAA. while it's ready + // to go OFF neither can matter, and afterwards the IO + // watchdog stops unless there's still periodic traffic. + if (action != TIMER_IAA_WATCHDOG + && t > ehci->watchdog.expires + && timer_pending (&ehci->watchdog)) + return; + mod_timer (&ehci->watchdog, t); + } +} + /*-------------------------------------------------------------------------*/ /* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c index 562c205eff87..d75dacf24723 100644 --- a/drivers/usb/media/vicam.c +++ b/drivers/usb/media/vicam.c @@ -1101,28 +1101,6 @@ static int vicam_read_proc_gain(char *page, char **start, off_t off, ((struct vicam_camera *)data)->gain); } -static int vicam_write_proc_shutter(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - struct vicam_camera *cam = (struct vicam_camera *)data; - - cam->shutter_speed = simple_strtoul(buffer, NULL, 10); - - return count; -} - -static int vicam_write_proc_gain(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - struct vicam_camera *cam = (struct vicam_camera *)data; - - cam->gain = simple_strtoul(buffer, NULL, 10); - - return count; -} - - - static void vicam_create_proc_root(void) { @@ -1164,21 +1142,17 @@ vicam_create_proc_entry(struct vicam_camera *cam) if ( !cam->proc_dir ) return; // We should probably return an error here ent = - create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR, - cam->proc_dir); + create_proc_entry("shutter", S_IFREG | S_IRUGO, cam->proc_dir); if (ent) { ent->data = cam; ent->read_proc = vicam_read_proc_shutter; - ent->write_proc = vicam_write_proc_shutter; ent->size = 64; } - ent = create_proc_entry("gain", S_IFREG | S_IRUGO | S_IWUSR, - cam->proc_dir); + ent = create_proc_entry("gain", S_IFREG | S_IRUGO , cam->proc_dir); if ( ent ) { ent->data = cam; ent->read_proc = vicam_read_proc_gain; - ent->write_proc = vicam_write_proc_gain; ent->size = 64; } } diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index d2930c563911..81b7d968661f 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -237,14 +237,6 @@ UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100, US_SC_8070, US_PR_BULK, NULL, US_FL_FIX_INQUIRY | US_FL_START_STOP ), -/* Submitted by Lars Gemeinhardt <linux-usb@gemeinhardt.info> - * Needed for START_STOP flag */ -UNUSUAL_DEV( 0x0547, 0x2810, 0x0001, 0x0001, - "Mello", - "MP3 Player", - US_SC_SCSI, US_PR_BULK, NULL, - US_FL_START_STOP), - /* This entry is needed because the device reports Sub=ff */ UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450, "Sony", @@ -626,6 +618,26 @@ UNUSUAL_DEV( 0x1065, 0x2136, 0x0000, 0x0001, US_SC_SCSI, US_PR_BULK, NULL, US_FL_MODE_XLATE | US_FL_START_STOP | US_FL_FIX_INQUIRY ), +/* This Pentax still camera is not conformant + * to the USB storage specification: - + * - It does not like the INQUIRY command. So we must handle this command + * of the SCSI layer ourselves. + * Tested on Rev. 10.00 (0x1000) + * Submitted by James Courtier-Dutton <James@superbug.demon.co.uk> + */ +UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000, + "Pentax", + "Optio 2/3/400", + US_SC_8070, US_PR_CBI, NULL, + US_FL_FIX_INQUIRY ), + +/* Submitted by Per Winkvist <per.winkvist@uk.com> */ +UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009, + "Pentax", + "Optio S", + US_SC_8070, US_PR_CBI, NULL, + US_FL_FIX_INQUIRY ), + /* Submitted by Brian Hall <brihall@pcisys.net> * Needed for START_STOP flag */ UNUSUAL_DEV( 0x0c76, 0x0003, 0x0100, 0x0100, |
