From: Linus Torvalds Date: Fri, 23 Nov 2007 20:39:18 +0000 (-0500) Subject: Linux 2.4.0-test9 X-Git-Tag: 2.4.0-test9 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=78ff69d03e876f9d7f57d87be6dcfa3f0c831dfc;p=history.git Linux 2.4.0-test9 - USB: ohci controller update, round-robin device numbering - ksymoops moved: document - sparc updates - sg.c: get rid of more #ifdef MODULE code --- diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt index 5510e53496ad..21ffe7b06bd4 100644 --- a/Documentation/oops-tracing.txt +++ b/Documentation/oops-tracing.txt @@ -1,7 +1,8 @@ Quick Summary ------------- -Install ksymoops from ftp://ftp.ocs.com.au/pub/ksymoops +Install ksymoops from +ftp://ftp..kernel.org/pub/linux/utils/kernel/ksymoops Read the ksymoops man page. ksymoops < the_oops.txt diff --git a/Documentation/usb/URB.txt b/Documentation/usb/URB.txt index 3fc29d1f29aa..7d99567adcdd 100644 --- a/Documentation/usb/URB.txt +++ b/Documentation/usb/URB.txt @@ -44,7 +44,7 @@ typedef struct urb // status after each completion int status; // returned status - unsigned int transfer_flags; // ASAP, SP_OK, EARLY_COMPLETE + unsigned int transfer_flags; // ASAP, SP_OK, etc. // for data stage (CTRL), BULK, INT and ISO void *transfer_buffer; // associated data buffer @@ -105,10 +105,9 @@ For ASAP set USB_ISO_ASAP in transfer_flags. If short packets should NOT be tolerated, set USB_DISABLE_SPD in transfer_flags. -Usually, (to reduce restart time) the completion handler is called -AFTER the URB re-submission. You can get the other way by setting -USB_URB_EARLY_COMPLETE in transfer_flags. This is implicit for -INT transfers. +Usually, to reduce restart time, the completion handler is called +AFTER the URB re-submission. However, it is called BEFORE URB +re-submission for INT transfers that are being continued. 1.5. How to submit an URB? @@ -172,10 +171,12 @@ In the completion handler, you should have a look at urb->status to detect any USB errors. Since the context parameter is included in the URB, you can pass information to the completion handler. -Avoid using the urb->dev field in your completion handler; it's cleared +NOTE: ***** WARNING ***** +AVOID using the urb->dev field in your completion handler; it's cleared as part of URB unlinking. Instead, use urb->context to hold all the data your driver needs. +NOTE: ***** WARNING ***** Also, NEVER SLEEP IN A COMPLETION HANDLER. These are normally called during hardware interrupt processing. If you can, defer substantial work to a tasklet (bottom half) to keep system latencies low. You'll diff --git a/README b/README index d77afd45ef76..fa9492f80d01 100644 --- a/README +++ b/README @@ -270,7 +270,8 @@ IF SOMETHING GOES WRONG: on making sense of the dump is in Documentation/oops-tracing.txt - You can use the "ksymoops" program to make sense of the dump. This - utility can be downloaded from ftp://ftp.ocs.com.au/pub/ksymoops . + utility can be downloaded from + ftp://ftp..kernel.org/pub/linux/utils/kernel/ksymoops. Alternately you can do the dump lookup by hand: - In debugging dumps like the above, it helps enormously if you can diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 293cf43f9598..028612687585 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -1,4 +1,4 @@ -/* $Id: pcic.c,v 1.17 2000/09/05 06:49:44 anton Exp $ +/* $Id: pcic.c,v 1.18 2000/09/25 06:09:12 anton Exp $ * pcic.c: Sparc/PCI controller support * * Copyright (C) 1998 V. Roganov and G. Raiko @@ -35,11 +35,6 @@ #ifndef CONFIG_PCI -int pcibios_present(void) -{ - return 0; -} - asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn, unsigned long off, @@ -976,7 +971,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, if(!suser()) return -EPERM; - lock_kernel(); switch(len) { case 1: err = get_user(ubyte, (unsigned char *)buf); @@ -1004,7 +998,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, break; }; - unlock_kernel(); return err; } diff --git a/arch/sparc64/boot/piggyback.c b/arch/sparc64/boot/piggyback.c index 503b366db695..36f907408c60 100644 --- a/arch/sparc64/boot/piggyback.c +++ b/arch/sparc64/boot/piggyback.c @@ -1,4 +1,4 @@ -/* $Id: piggyback.c,v 1.1 1997/07/11 11:05:26 jj Exp $ +/* $Id: piggyback.c,v 1.2 2000/09/19 14:34:39 anton Exp $ Simple utility to make a single-image install kernel with initial ramdisk for Sparc64 tftpbooting without need to set up nfs. @@ -50,9 +50,9 @@ int main(int argc,char **argv) map = fopen (argv[2], "r"); if (!map) die(argv[2]); while (fgets (buffer, 1024, map)) { - if (!strcmp (buffer + 19, "start\n")) + if (!strcmp (buffer + 19, "_start\n")) start = strtoul (buffer + 8, NULL, 16); - else if (!strcmp (buffer + 19, "end\n")) + else if (!strcmp (buffer + 19, "_end\n")) end = strtoul (buffer + 8, NULL, 16); } fclose (map); diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c index 9be09c3b01e9..cc26817b40f6 100644 --- a/arch/sparc64/kernel/auxio.c +++ b/arch/sparc64/kernel/auxio.c @@ -18,6 +18,7 @@ #include #include #include +#include /* Probe and map in the Auxiliary I/O register */ unsigned long auxio_register = 0; @@ -55,7 +56,7 @@ found_sdev: return; } #endif - if(central_bus) { + if(central_bus || this_is_starfire) { auxio_register = 0UL; return; } diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c index 2c4fb1355fda..dba732a6d9e5 100644 --- a/arch/sparc64/kernel/central.c +++ b/arch/sparc64/kernel/central.c @@ -1,4 +1,4 @@ -/* $Id: central.c,v 1.13 1999/12/01 10:44:43 davem Exp $ +/* $Id: central.c,v 1.14 2000/09/21 06:25:14 anton Exp $ * central.c: Central FHC driver for Sunfire/Starfire/Wildfire. * * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com) @@ -15,6 +15,7 @@ #include #include +#include struct linux_central *central_bus = NULL; struct linux_fhc *fhc_list = NULL; @@ -254,9 +255,8 @@ void central_probe(void) cnode = prom_finddevice("/central"); if(cnode == 0 || cnode == -1) { - extern void starfire_check(void); - - starfire_check(); + if (this_is_starfire) + starfire_cpu_setup(); return; } diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index daefe6d4386f..92bd3ed88a98 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.93 2000/08/31 10:00:39 anton Exp $ +/* $Id: irq.c,v 1.94 2000/09/21 06:27:10 anton Exp $ * irq.c: UltraSparc IRQ handling/init/registry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -31,6 +31,7 @@ #include #include #include +#include /* Internal flag, should not be visible elsewhere at all. */ #define SA_IMAP_MASKED 0x100 @@ -123,7 +124,6 @@ int get_irq_list(char *buf) /* Now these are always passed a true fully specified sun4u INO. */ void enable_irq(unsigned int irq) { - extern int this_is_starfire; struct ino_bucket *bucket = __bucket(irq); unsigned long imap; unsigned long tid; @@ -139,9 +139,6 @@ void enable_irq(unsigned int irq) : "i" (ASI_UPA_CONFIG)); tid = ((tid & UPA_CONFIG_MID) << 9); } else { - extern unsigned int starfire_translate(unsigned long imap, - unsigned int upaid); - tid = (starfire_translate(imap, current->processor) << 26); } @@ -715,7 +712,6 @@ void handler_irq(int irq, struct pt_regs *regs) struct ino_bucket *bp, *nbp; int cpu = smp_processor_id(); #ifdef CONFIG_SMP - extern int this_is_starfire; int should_forward = (this_is_starfire == 0 && irq < 10 && current->pid != 0); @@ -1029,7 +1025,6 @@ void init_timers(void (*cfunc)(int, void *, struct pt_regs *), #ifdef CONFIG_SMP static int retarget_one_irq(struct irqaction *p, int goal_cpu) { - extern int this_is_starfire; struct ino_bucket *bucket = __bucket(p->mask); unsigned long imap = bucket->imap; unsigned int tid; @@ -1041,9 +1036,6 @@ static int retarget_one_irq(struct irqaction *p, int goal_cpu) if(this_is_starfire == 0) { tid = __cpu_logical_map[goal_cpu] << 26; } else { - extern unsigned int starfire_translate(unsigned long imap, - unsigned int upaid); - tid = (starfire_translate(imap, __cpu_logical_map[goal_cpu]) << 26); } upa_writel(IMAP_VALID | (tid & IMAP_TID), imap); diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 8af0c0f1caf9..24b1a7217f18 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -24,7 +24,6 @@ unsigned long pci_memspace_mask = 0xffffffffUL; #ifndef CONFIG_PCI /* A "nop" PCI implementation. */ -int pcibios_present(void) { return 0; } asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn, unsigned long off, unsigned long len, unsigned char *buf) @@ -316,7 +315,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, goto out; } - lock_kernel(); switch(len) { case 1: err = get_user(byte, (u8 *)buf); @@ -344,7 +342,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, break; }; - unlock_kernel(); out: return err; diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 8d7db0c9bc7a..aff2de594699 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1,4 +1,4 @@ -/* $Id: pci_psycho.c,v 1.16 2000/04/15 10:06:16 davem Exp $ +/* $Id: pci_psycho.c,v 1.17 2000/09/21 06:25:14 anton Exp $ * pci_psycho.c: PSYCHO/U2P specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -15,6 +15,7 @@ #include #include #include +#include #include "pci_impl.h" @@ -1254,8 +1255,6 @@ static void __init psycho_scan_bus(struct pci_controller_info *p) static void __init psycho_iommu_init(struct pci_controller_info *p) { - extern int this_is_starfire; - extern void *starfire_hookup(int); unsigned long tsbbase, i; u64 control; diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 602ee9ca2b3c..7baebc89e86d 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -1,4 +1,4 @@ -/* $Id: sbus.c,v 1.11 2000/04/14 09:13:04 davem Exp $ +/* $Id: sbus.c,v 1.12 2000/09/21 06:25:14 anton Exp $ * sbus.c: UltraSparc SBUS controller support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -18,6 +18,7 @@ #include #include #include +#include #include "iommu_common.h" @@ -1151,15 +1152,10 @@ void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus) upa_writeq(control, iommu->sbus_control_reg); /* Now some Xfire specific grot... */ - { - extern void *starfire_hookup(int); - extern int this_is_starfire; - - if (this_is_starfire) - sbus->starfire_cookie = starfire_hookup(sbus->portid); - else - sbus->starfire_cookie = NULL; - } + if (this_is_starfire) + sbus->starfire_cookie = starfire_hookup(sbus->portid); + else + sbus->starfire_cookie = NULL; sysio_register_error_handlers(sbus); } diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 486254fb9543..84cc201fd49e 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.55 2000/07/24 14:13:13 anton Exp $ +/* $Id: setup.c,v 1.56 2000/09/21 06:29:01 anton Exp $ * linux/arch/sparc64/kernel/setup.c * * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef CONFIG_IP_PNP #include @@ -479,6 +480,9 @@ void __init setup_arch(char **cmdline_p) conswitchp = &prom_con; #endif + /* Work out if we are starfire early on */ + check_if_starfire(); + boot_flags_init(*cmdline_p); idprom_init(); diff --git a/arch/sparc64/kernel/starfire.c b/arch/sparc64/kernel/starfire.c index 8ff7ea4d2435..dc8f96b7a6b0 100644 --- a/arch/sparc64/kernel/starfire.c +++ b/arch/sparc64/kernel/starfire.c @@ -1,7 +1,8 @@ -/* $Id: starfire.c,v 1.5 2000/01/31 04:59:12 davem Exp $ +/* $Id: starfire.c,v 1.7 2000/09/22 23:02:13 davem Exp $ * starfire.c: Starfire/E10000 support. * * Copyright (C) 1998 David S. Miller (davem@redhat.com) + * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com) */ #include @@ -11,23 +12,31 @@ #include #include #include +#include -/* A few places around the kernel check this to see if +/* + * A few places around the kernel check this to see if * they need to call us to do things in a Starfire specific * way. */ int this_is_starfire = 0; -void starfire_check(void) +void check_if_starfire(void) { int ssnode = prom_finddevice("/ssp-serial"); + if(ssnode != 0 && ssnode != -1) + this_is_starfire = 1; +} - if(ssnode != 0 && ssnode != -1) { +void starfire_cpu_setup(void) +{ + if (this_is_starfire) { +/* We do this in starfire_translate - Anton */ +#if 0 int i; - this_is_starfire = 1; - - /* Now must fixup cpu MIDs. OBP gave us a logical + /* + * Now must fixup cpu MIDs. OBP gave us a logical * linear cpuid number, not the real upaid. */ for(i = 0; i < linux_num_cpus; i++) { @@ -39,6 +48,7 @@ void starfire_check(void) linux_cpus[i].mid = mid; } +#endif } } @@ -47,7 +57,8 @@ int starfire_hard_smp_processor_id(void) return upa_readl(0x1fff40000d0UL); } -/* Each Starfire board has 32 registers which perform translation +/* + * Each Starfire board has 32 registers which perform translation * and delivery of traditional interrupt packets into the extended * Starfire hardware format. Essentially UPAID's now have 2 more * bits than in all previous Sun5 systems. @@ -82,6 +93,9 @@ void *starfire_hookup(int upaid) for(i = 0; i < 32; i++) { p->imap_slots[i] = 0UL; p->tregs[i] = treg_base + (i * 0x10UL); + /* Lets play it safe and not overwrite existing mappings */ + if (upa_readl(p->tregs[i]) != 0) + p->imap_slots[i] = 0xdeadbeaf; } p->upaid = upaid; p->next = sflist; @@ -116,6 +130,12 @@ unsigned int starfire_translate(unsigned long imap, panic("Lucy in the sky...."); } p->imap_slots[i] = imap; + + /* map to real upaid */ + upaid = (((upaid & 0x3c) << 1) | + ((upaid & 0x40) >> 4) | + (upaid & 0x3)); + upa_writel(upaid, p->tregs[i]); return i; diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 3c989847743a..0264f94189a7 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.29 2000/09/16 07:33:45 davem Exp $ +/* $Id: time.c,v 1.32 2000/09/22 23:02:13 davem Exp $ * time.c: UltraSparc timer and TOD clock support. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -30,6 +30,7 @@ #include #include #include +#include extern rwlock_t xtime_lock; @@ -305,6 +306,20 @@ void __init clock_probe(void) struct linux_ebus *ebus = NULL; #endif + + if (this_is_starfire) { + /* davem suggests we keep this within the 4M locked kernel image */ + static char obp_gettod[256]; + static u32 unix_tod; + + sprintf(obp_gettod, "h# %08x unix-gettod", + (unsigned int) (long) &unix_tod); + prom_feval(obp_gettod); + xtime.tv_sec = unix_tod; + xtime.tv_usec = 0; + return; + } + __save_and_cli(flags); if(central_bus != NULL) { @@ -473,6 +488,9 @@ static __inline__ unsigned long do_gettimeoffset(void) void do_settimeofday(struct timeval *tv) { + if (this_is_starfire) + return; + write_lock_irq(&xtime_lock); tv->tv_usec -= do_gettimeoffset(); @@ -496,7 +514,10 @@ static int set_rtc_mmss(unsigned long nowtime) unsigned long regs = mstk48t02_regs; u8 tmp; - /* Not having a register set can lead to trouble. */ + /* + * Not having a register set can lead to trouble. + * Also starfire doesnt have a tod clock. + */ if (!regs) return -1; diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index d00faa92231e..d694e40f9c3f 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.155 2000/09/09 00:02:19 davem Exp $ +/* $Id: init.c,v 1.156 2000/09/21 06:34:48 anton Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) @@ -29,6 +29,7 @@ #include #include #include +#include extern void device_scan(void); @@ -200,7 +201,7 @@ static void inherit_prom_mappings(void) for (i = 0; i < n; i++) { unsigned long vaddr; - + if (trans[i].virt >= 0xf0000000 && trans[i].virt < 0x100000000) { for (vaddr = trans[i].virt; vaddr < trans[i].virt + trans[i].size; @@ -808,7 +809,6 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) unsigned long bootmap_pfn, bytes_avail, size; int i; - bytes_avail = 0UL; for (i = 0; sp_banks[i].num_bytes != 0; i++) { end_of_phys_memory = sp_banks[i].base_addr + @@ -999,12 +999,7 @@ void __init paging_init(void) */ { extern void setup_tba(int); - int is_starfire = prom_finddevice("/ssp-serial"); - if (is_starfire != 0 && is_starfire != -1) - is_starfire = 1; - else - is_starfire = 0; - setup_tba(is_starfire); + setup_tba(this_is_starfire); } inherit_locked_prom_mappings(1); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 2e512345b503..6d5b92f1fbef 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -19,7 +19,7 @@ */ #include #ifdef CONFIG_PROC_FS - static char * sg_version_str = "Version: 3.1.17 (20000921)"; + static char * sg_version_str = "Version: 3.1.17 (20001002)"; #endif static int sg_version_num = 30117; /* 2 digits for each component */ /* @@ -69,10 +69,8 @@ #ifdef CONFIG_PROC_FS #include static int sg_proc_init(void); -#ifdef MODULE static void sg_proc_cleanup(void); #endif -#endif #ifndef LINUX_VERSION_CODE #include @@ -271,7 +269,8 @@ static int sg_open(struct inode * inode, struct file * filp) * else try and use this device. Also, if error recovery fails, it * may try and take the device offline, in which case all further * access to the device is prohibited. */ - if(! scsi_block_when_processing_errors(sdp->device)) + if (! ((flags & O_NONBLOCK) || + scsi_block_when_processing_errors(sdp->device))) return -ENXIO; SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags)); @@ -279,7 +278,7 @@ static int sg_open(struct inode * inode, struct file * filp) if (flags & O_EXCL) { if (O_RDONLY == (flags & O_ACCMODE)) return -EACCES; /* Can't lock it with read only access */ - if (sdp->headfp && (filp->f_flags & O_NONBLOCK)) + if (sdp->headfp && (flags & O_NONBLOCK)) return -EBUSY; res = 0; /* following is a macro that beats race condition */ __wait_event_interruptible(sdp->o_excl_wait, @@ -289,7 +288,7 @@ static int sg_open(struct inode * inode, struct file * filp) return res; /* -ERESTARTSYS because signal hit process */ } else if (sdp->exclude) { /* some other fd has an exclusive lock on dev */ - if (filp->f_flags & O_NONBLOCK) + if (flags & O_NONBLOCK) return -EBUSY; res = 0; /* following is a macro that beats race condition */ __wait_event_interruptible(sdp->o_excl_wait, (! sdp->exclude), res); @@ -353,9 +352,6 @@ static ssize_t sg_read(struct file * filp, char * buf, return -ENXIO; SCSI_LOG_TIMEOUT(3, printk("sg_read: dev=%d, count=%d\n", MINOR(sdp->i_rdev), (int)count)); - - if(! scsi_block_when_processing_errors(sdp->device)) - return -ENXIO; if (ppos != &filp->f_pos) ; /* FIXME: Hmm. Seek to the right place, or fail? */ if ((k = verify_area(VERIFY_WRITE, buf, count))) @@ -451,15 +447,11 @@ static ssize_t sg_read(struct file * filp, char * buf, static ssize_t sg_new_read(Sg_fd * sfp, char * buf, size_t count, Sg_request * srp) { - Sg_device * sdp = sfp->parentdp; sg_io_hdr_t * hp = &srp->header; int k, len; - if(! scsi_block_when_processing_errors(sdp->device) ) - return -ENXIO; if (count < size_sg_io_hdr) return -EINVAL; - hp->sb_len_wr = 0; if ((hp->mx_sb_len > 0) && hp->sbp) { if ((CHECK_CONDITION & hp->masked_status) || @@ -503,7 +495,8 @@ static ssize_t sg_write(struct file * filp, const char * buf, SCSI_LOG_TIMEOUT(3, printk("sg_write: dev=%d, count=%d\n", MINOR(sdp->i_rdev), (int)count)); - if(! scsi_block_when_processing_errors(sdp->device) ) + if (! ((filp->f_flags & O_NONBLOCK) || + scsi_block_when_processing_errors(sdp->device))) return -ENXIO; if (ppos != &filp->f_pos) ; /* FIXME: Hmm. Seek to the right place, or fail? */ @@ -712,8 +705,6 @@ static int sg_ioctl(struct inode * inode, struct file * filp, return -ENXIO; SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: dev=%d, cmd=0x%x\n", MINOR(sdp->i_rdev), (int)cmd_in)); - if(! scsi_block_when_processing_errors(sdp->device) ) - return -ENXIO; read_only = (O_RDWR != (filp->f_flags & O_ACCMODE)); switch(cmd_in) @@ -885,7 +876,11 @@ static int sg_ioctl(struct inode * inode, struct file * filp, case SG_EMULATED_HOST: return put_user(sdp->device->host->hostt->emulated, (int *)arg); case SG_SCSI_RESET: - if (! scsi_block_when_processing_errors(sdp->device)) + if (filp->f_flags & O_NONBLOCK) { + if (sdp->device->host->in_recovery) + return -EBUSY; + } + else if (! scsi_block_when_processing_errors(sdp->device)) return -EBUSY; result = get_user(val, (int *)arg); if (result) return result; @@ -1301,16 +1296,14 @@ static void sg_detach(Scsi_Device * scsidp) return; } -#ifdef MODULE +MODULE_AUTHOR("Douglas Gilbert"); +MODULE_DESCRIPTION("SCSI generic (sg) driver"); MODULE_PARM(def_reserved_size, "i"); MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd"); -#endif /* MODULE */ static int __init init_sg(void) { -#ifdef MODULE if (def_reserved_size >= 0) sg_big_buff = def_reserved_size; -#endif /* MODULE */ sg_template.module = THIS_MODULE; return scsi_register_module(MODULE_SCSI_DEV, &sg_template); } @@ -2551,7 +2544,6 @@ static int sg_proc_init() return 0; } -#ifdef MODULE static void sg_proc_cleanup() { int k; @@ -2563,7 +2555,6 @@ static void sg_proc_cleanup() remove_proc_entry(sg_proc_leaf_names[k], sg_proc_sgp); remove_proc_entry(sg_proc_sg_dirname, proc_scsi); } -#endif static int sg_proc_dressz_read(char * buffer, char ** start, off_t offset, int size, int * eof, void * data) diff --git a/drivers/usb/dabusb.h b/drivers/usb/dabusb.h index 82877003c008..ddb4d8971573 100644 --- a/drivers/usb/dabusb.h +++ b/drivers/usb/dabusb.h @@ -23,7 +23,7 @@ typedef struct wait_queue_head_t wait; wait_queue_head_t remove_ok; spinlock_t lock; - volatile atomic_t pending_io; + atomic_t pending_io; driver_state_t state; int remove_pending; int got_mem; diff --git a/drivers/usb/usb-ohci.c b/drivers/usb/usb-ohci.c index 339b93965e75..4fb391a8b9bb 100644 --- a/drivers/usb/usb-ohci.c +++ b/drivers/usb/usb-ohci.c @@ -12,6 +12,10 @@ * * History: * + * 2000/09/26 fixed races in removing the private portion of the urb + * 2000/09/07 disable bulk and control lists when unlinking the last + * endpoint descriptor in order to avoid unrecoverable errors on + * the Lucent chips. * 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some * urb unlink probs, indentation fixes * 2000/08/11 various oops fixes mostly affecting iso and cleanup from @@ -78,8 +82,9 @@ /* For initializing controller (mask in an HCFS mode too) */ #define OHCI_CONTROL_INIT \ - (OHCI_CTRL_CBSR & 0x3) \ - | OHCI_CTRL_BLE | OHCI_CTRL_CLE | OHCI_CTRL_IE | OHCI_CTRL_PLE + (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE + +#define OHCI_UNLINK_TIMEOUT (HZ / 10) static LIST_HEAD (ohci_hcd_list); static spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED; @@ -89,36 +94,54 @@ static spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED; *-------------------------------------------------------------------------*/ /* free HCD-private data associated with this URB */ - -static void urb_rm_priv (urb_t * urb) + +static void urb_free_priv (urb_priv_t * urb_priv) { - urb_priv_t * urb_priv = urb->hcpriv; int i; - - /* Release int/iso bandwidth for Interrupt or Isoc. transfers */ - if (urb->bandwidth) { - switch (usb_pipetype(urb->pipe)) { - case PIPE_INTERRUPT: - usb_release_bandwidth (urb->dev, urb, 0); - break; - case PIPE_ISOCHRONOUS: - usb_release_bandwidth (urb->dev, urb, 1); - break; - default: - break; - } - } - if (!urb_priv) - return; for (i = 0; i < urb_priv->length; i++) { if (urb_priv->td [i]) { OHCI_FREE (urb_priv->td [i]); } } - kfree (urb->hcpriv); - urb->hcpriv = NULL; + kfree (urb_priv); +} + +static void urb_rm_priv_locked (urb_t * urb) +{ + urb_priv_t * urb_priv = urb->hcpriv; + + if (urb_priv) { + urb->hcpriv = NULL; + + /* Release int/iso bandwidth */ + if (urb->bandwidth) { + switch (usb_pipetype(urb->pipe)) { + case PIPE_INTERRUPT: + usb_release_bandwidth (urb->dev, urb, 0); + break; + case PIPE_ISOCHRONOUS: + usb_release_bandwidth (urb->dev, urb, 1); + break; + default: + break; + } + } + + urb_free_priv (urb_priv); + usb_dec_dev_use (urb->dev); + urb->dev = NULL; + } +} + +static void urb_rm_priv (urb_t * urb) +{ + unsigned long flags; + + spin_lock_irqsave (&usb_ed_lock, flags); + urb_rm_priv_locked (urb); + spin_unlock_irqrestore (&usb_ed_lock, flags); } /*-------------------------------------------------------------------------*/ @@ -366,15 +389,15 @@ static int sohci_return_urb (urb_t * urb) unsigned long flags; int i; + if (!urb_priv) + return -1; /* urb already unlinked */ + /* just to be sure */ if (!urb->complete) { urb_rm_priv (urb); - usb_dec_dev_use (urb->dev); return -1; } - if (!urb_priv) return -1; /* urb already unlinked */ - #ifdef DEBUG urb_print (urb, "RET", usb_pipeout (urb->pipe)); #endif @@ -408,7 +431,6 @@ static int sohci_return_urb (urb_t * urb) } else { /* unlink URB, call complete */ urb_rm_priv (urb); - usb_dec_dev_use (urb->dev); urb->complete (urb); } break; @@ -416,7 +438,6 @@ static int sohci_return_urb (urb_t * urb) case PIPE_BULK: case PIPE_CONTROL: /* unlink URB, call complete */ urb_rm_priv (urb); - usb_dec_dev_use (urb->dev); urb->complete (urb); break; } @@ -438,7 +459,7 @@ static int sohci_submit_urb (urb_t * urb) int bustime = 0; if (!urb->dev || !urb->dev->bus) - return -EINVAL; + return -ENODEV; if (urb->hcpriv) /* urb already in use */ return -EINVAL; @@ -453,7 +474,7 @@ static int sohci_submit_urb (urb_t * urb) urb_print (urb, "SUB", usb_pipein (pipe)); #endif - /* a request to the virtual root hub */ + /* handle a request to the virtual root hub */ if (usb_pipedevice (pipe) == ohci->rh.devnum) return rh_submit_urb (urb); @@ -505,26 +526,22 @@ static int sohci_submit_urb (urb_t * urb) memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (td_t *)); /* fill the private part of the URB */ - urb->hcpriv = urb_priv; urb_priv->length = size; - urb_priv->td_cnt = 0; - urb_priv->state = 0; urb_priv->ed = ed; /* allocate the TDs */ for (i = 0; i < size; i++) { OHCI_ALLOC (urb_priv->td[i], sizeof (td_t)); if (!urb_priv->td[i]) { - urb_rm_priv (urb); + urb_free_priv (urb_priv); usb_dec_dev_use (urb->dev); return -ENOMEM; } } - spin_lock_irqsave (&usb_ed_lock, flags); + if (ed->state == ED_NEW || (ed->state & ED_DEL)) { - urb_rm_priv(urb); + urb_free_priv (urb_priv); usb_dec_dev_use (urb->dev); - spin_unlock_irqrestore(&usb_ed_lock, flags); return -EINVAL; } @@ -544,23 +561,24 @@ static int sohci_submit_urb (urb_t * urb) bustime = usb_check_bandwidth (urb->dev, urb); } if (bustime < 0) { - urb_rm_priv (urb); + urb_free_priv (urb_priv); usb_dec_dev_use (urb->dev); - spin_unlock_irqrestore (&usb_ed_lock, flags); return bustime; } usb_claim_bandwidth (urb->dev, urb, bustime, usb_pipeisoc (urb->pipe)); } - - urb->status = USB_ST_URB_PENDING; + + spin_lock_irqsave (&usb_ed_lock, flags); urb->actual_length = 0; - - if (ed->state != ED_OPER) /* link the ed into a chain if is not already */ + urb->hcpriv = urb_priv; + urb->status = USB_ST_URB_PENDING; + + /* link the ed into a chain if is not already */ + if (ed->state != ED_OPER) ep_link (ohci, ed); - - urb->status = USB_ST_URB_PENDING; - td_submit_urb (urb); /* fill the TDs and link it to the ed */ + /* fill the TDs and link it to the ed */ + td_submit_urb (urb); spin_unlock_irqrestore (&usb_ed_lock, flags); return 0; @@ -570,7 +588,7 @@ static int sohci_submit_urb (urb_t * urb) /* deactivate all TDs and remove the private part of the URB */ /* interrupt callers must use async unlink mode */ - + static int sohci_unlink_urb (urb_t * urb) { unsigned long flags; @@ -587,16 +605,14 @@ static int sohci_unlink_urb (urb_t * urb) #ifdef DEBUG urb_print (urb, "UNLINK", 1); #endif - - if (usb_pipedevice (urb->pipe) == ohci->rh.devnum) { - usb_dec_dev_use(urb->dev); - return rh_unlink_urb (urb); /* a request to the virtual root hub */ - } - if (urb->hcpriv) { - /* URB active? */ - if (urb->status == USB_ST_URB_PENDING && !ohci->disabled) { - urb_priv_t * urb_priv = urb->hcpriv; + /* handle a request to the virtual root hub */ + if (usb_pipedevice (urb->pipe) == ohci->rh.devnum) + return rh_unlink_urb (urb); + + if (urb->hcpriv && (urb->status == USB_ST_URB_PENDING)) { + if (!ohci->disabled) { + urb_priv_t * urb_priv; /* interrupt code may not sleep; it must use * async status return to unlink pending urbs. @@ -608,44 +624,50 @@ static int sohci_unlink_urb (urb_t * urb) return -EWOULDBLOCK; } - /* flag the urb and its TDs for deletion in some * upcoming SF interrupt delete list processing */ - urb_priv->state = URB_DEL; - spin_lock_irqsave (&usb_ed_lock, flags); + urb_priv = urb->hcpriv; - if (urb_priv->ed->state == ED_OPER) - ep_unlink(ohci, urb_priv->ed); - + if (!urb_priv || (urb_priv->state == URB_DEL)) { + spin_unlock_irqrestore (&usb_ed_lock, flags); + return 0; + } + + urb_priv->state = URB_DEL; ep_rm_ed (urb->dev, urb_priv->ed); urb_priv->ed->state |= ED_URB_DEL; - spin_unlock_irqrestore (&usb_ed_lock, flags); if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) { DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); DECLARE_WAITQUEUE (wait, current); + int timeout = OHCI_UNLINK_TIMEOUT; - usb_dec_dev_use (urb->dev); - /* wait until all TDs are deleted */ add_wait_queue (&unlink_wakeup, &wait); urb_priv->wait = &unlink_wakeup; - current->state = TASK_UNINTERRUPTIBLE; - schedule (); + spin_unlock_irqrestore (&usb_ed_lock, flags); + + /* wait until all TDs are deleted */ + set_current_state(TASK_UNINTERRUPTIBLE); + while (timeout && (urb->status == USB_ST_URB_PENDING)) + timeout = schedule_timeout (timeout); remove_wait_queue (&unlink_wakeup, &wait); - urb->status = -ENOENT; - urb_priv->wait = 0; + if (urb->status == USB_ST_URB_PENDING) { + err ("unlink URB timeout"); + return -ETIMEDOUT; + } } else { /* usb_dec_dev_use done in dl_del_list() */ urb->status = -EINPROGRESS; + spin_unlock_irqrestore (&usb_ed_lock, flags); } } else { urb_rm_priv (urb); - usb_dec_dev_use (urb->dev); - if (urb->complete && (urb->transfer_flags & USB_ASYNC_UNLINK)) { - urb->complete (urb); - urb->status = 0; + if (urb->transfer_flags & USB_ASYNC_UNLINK) { + urb->status = -ECONNRESET; + if (urb->complete) + urb->complete (urb); } else urb->status = -ENOENT; } @@ -729,14 +751,19 @@ static int sohci_free_dev (struct usb_device * usb_dev) } else if (!in_interrupt ()) { DECLARE_WAIT_QUEUE_HEAD (freedev_wakeup); DECLARE_WAITQUEUE (wait, current); + int timeout = OHCI_UNLINK_TIMEOUT; /* SF interrupt handler calls dl_del_list */ add_wait_queue (&freedev_wakeup, &wait); dev->wait = &freedev_wakeup; - current->state = TASK_UNINTERRUPTIBLE; - schedule (); + set_current_state(TASK_UNINTERRUPTIBLE); + while (timeout && dev->ed_cnt) + timeout = schedule_timeout (timeout); remove_wait_queue (&freedev_wakeup, &wait); - + if (dev->ed_cnt) { + err ("free device %d timeout", usb_dev->devnum); + return -ETIMEDOUT; + } } else { /* likely some interface's driver has a refcount bug */ err ("bus %s devnum %d deletion in interrupt", @@ -836,7 +863,7 @@ static int ep_link (ohci_t * ohci, ed_t * edi) ed->state = ED_OPER; switch (ed->type) { - case CTRL: + case PIPE_CONTROL: ed->hwNextED = 0; if (ohci->ed_controltail == NULL) { writel (virt_to_bus (ed), &ohci->regs->ed_controlhead); @@ -844,10 +871,15 @@ static int ep_link (ohci_t * ohci, ed_t * edi) ohci->ed_controltail->hwNextED = cpu_to_le32 (virt_to_bus (ed)); } ed->ed_prev = ohci->ed_controltail; + if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1]) { + ohci->hc_control |= OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + } ohci->ed_controltail = edi; break; - case BULK: + case PIPE_BULK: ed->hwNextED = 0; if (ohci->ed_bulktail == NULL) { writel (virt_to_bus (ed), &ohci->regs->ed_bulkhead); @@ -855,10 +887,15 @@ static int ep_link (ohci_t * ohci, ed_t * edi) ohci->ed_bulktail->hwNextED = cpu_to_le32 (virt_to_bus (ed)); } ed->ed_prev = ohci->ed_bulktail; + if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1]) { + ohci->hc_control |= OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } ohci->ed_bulktail = edi; break; - case INT: + case PIPE_INTERRUPT: load = ed->int_load; interval = ep_2_n_interval (ed->int_period); ed->int_interval = interval; @@ -879,7 +916,7 @@ static int ep_link (ohci_t * ohci, ed_t * edi) #endif break; - case ISO: + case PIPE_ISOCHRONOUS: ed->hwNextED = 0; ed->int_interval = 1; if (ohci->ed_isotail != NULL) { @@ -923,21 +960,29 @@ static int ep_unlink (ohci_t * ohci, ed_t * ed) ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP); switch (ed->type) { - case CTRL: + case PIPE_CONTROL: if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + } writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_controlhead); } else { ed->ed_prev->hwNextED = ed->hwNextED; } - if(ohci->ed_controltail == ed) { + if (ohci->ed_controltail == ed) { ohci->ed_controltail = ed->ed_prev; } else { ((ed_t *) bus_to_virt (le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev; } break; - case BULK: + case PIPE_BULK: if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_bulkhead); } else { ed->ed_prev->hwNextED = ed->hwNextED; @@ -949,7 +994,7 @@ static int ep_unlink (ohci_t * ohci, ed_t * ed) } break; - case INT: + case PIPE_INTERRUPT: int_branch = ed->int_branch; interval = ed->int_interval; @@ -971,7 +1016,7 @@ static int ep_unlink (ohci_t * ohci, ed_t * ed) #endif break; - case ISO: + case PIPE_ISOCHRONOUS: if (ohci->ed_isotail == ed) ohci->ed_isotail = ed->ed_prev; if (ed->hwNextED != 0) @@ -1054,7 +1099,7 @@ static ed_t * ep_add_ed (struct usb_device * usb_dev, unsigned int pipe, int int | usb_pipeslow (pipe) << 13 | usb_maxpacket (usb_dev, pipe, usb_pipeout (pipe)) << 16); - if (ed->type == INT && ed->state == ED_UNLINK) { + if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) { ed->int_period = interval; ed->int_load = load; } @@ -1081,13 +1126,13 @@ static void ep_rm_ed (struct usb_device * usb_dev, ed_t * ed) if (!ohci->disabled) { switch (ed->type) { - case CTRL: /* stop CTRL list */ - writel (ohci->hc_control &= ~OHCI_CTRL_CLE, - &ohci->regs->control); + case PIPE_CONTROL: /* stop control list */ + ohci->hc_control &= ~OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); break; - case BULK: /* stop BULK list */ - writel (ohci->hc_control &= ~OHCI_CTRL_BLE, - &ohci->regs->control); + case PIPE_BULK: /* stop bulk list */ + ohci->hc_control &= ~OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); break; } } @@ -1128,7 +1173,7 @@ static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int i td->index = index; td->urb = urb; td->hwINFO = cpu_to_le32 (info); - if ((td->ed->type & 3) == PIPE_ISOCHRONOUS) { + if ((td->ed->type) == PIPE_ISOCHRONOUS) { td->hwCBP = cpu_to_le32 (((!data || !len) ? 0 : virt_to_bus (data)) & 0xFFFFF000); @@ -1269,6 +1314,27 @@ static void dl_transfer_length(td_t * td) } } +/* handle an urb that is being unlinked */ + +static void dl_del_urb (urb_t * urb) +{ + wait_queue_head_t * wait_head = ((urb_priv_t *)(urb->hcpriv))->wait; + + urb_rm_priv_locked (urb); + + if (urb->transfer_flags & USB_ASYNC_UNLINK) { + urb->status = -ECONNRESET; + if (urb->complete) + urb->complete (urb); + } else { + urb->status = -ENOENT; + + /* unblock sohci_unlink_urb */ + if (wait_head) + wake_up (wait_head); + } +} + /*-------------------------------------------------------------------------*/ /* replies to the request have to be on a FIFO basis so @@ -1330,6 +1396,7 @@ static void dl_del_list (ohci_t * ohci, unsigned int frame) int ctrl = 0, bulk = 0; spin_lock_irqsave (&usb_ed_lock, flags); + for (ed = ohci->ed_rm_list[frame]; ed != NULL; ed = ed->ed_rm_list) { tdTailP = bus_to_virt (le32_to_cpup (&ed->hwTailP) & 0xfffffff0); @@ -1344,22 +1411,13 @@ static void dl_del_list (ohci_t * ohci, unsigned int frame) td_next = bus_to_virt (le32_to_cpup (&td->hwNextTD) & 0xfffffff0); if ((urb_priv->state == URB_DEL) || (ed->state & ED_DEL)) { tdINFO = le32_to_cpup (&td->hwINFO); - if (TD_CC_GET (tdINFO) < 0xE) dl_transfer_length (td); + if (TD_CC_GET (tdINFO) < 0xE) + dl_transfer_length (td); *td_p = td->hwNextTD | (*td_p & cpu_to_le32 (0x3)); + /* URB is done; clean up */ - if (++(urb_priv->td_cnt) == urb_priv->length) { - void *condition = urb_priv->wait; - - urb_rm_priv (urb); - if (urb->transfer_flags & USB_ASYNC_UNLINK) { - usb_dec_dev_use (urb->dev); - urb->status = -ECONNRESET; - urb->complete (urb); - } else if (condition) { - /* unblock sohci_unlink_urb */ - wake_up (condition); - } - } + if (++(urb_priv->td_cnt) == urb_priv->length) + dl_del_urb (urb); } else { td_p = &td->hwNextTD; } @@ -1371,31 +1429,54 @@ static void dl_del_list (ohci_t * ohci, unsigned int frame) ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); ed->state = ED_NEW; /* if all eds are removed wake up sohci_free_dev */ - if (!--dev->ed_cnt && dev->wait) - wake_up (dev->wait); - } - else { + if (!--dev->ed_cnt) { + wait_queue_head_t *wait_head = dev->wait; + + dev->wait = 0; + if (wait_head) + wake_up (wait_head); + } + } else { ed->state &= ~ED_URB_DEL; - ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP); + tdHeadP = bus_to_virt (le32_to_cpup (&ed->hwHeadP) & 0xfffffff0); + + if (tdHeadP == tdTailP) { + if (ed->state == ED_OPER) + ep_unlink(ohci, ed); + OHCI_FREE (tdTailP); + ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); + ed->state = ED_NEW; + --(usb_to_ohci (ohci->dev[edINFO & 0x7F]))->ed_cnt; + } else + ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP); } - - if ((ed->type & 3) == CTRL) ctrl |= 1; - if ((ed->type & 3) == BULK) bulk |= 1; + + switch (ed->type) { + case PIPE_CONTROL: + ctrl = 1; + break; + case PIPE_BULK: + bulk = 1; + break; + } } - /* maybe reenable CTRL and BULK lists */ + /* maybe reenable control and bulk lists */ if (!ohci->disabled) { - if (ctrl) /* reset CTRL list */ + if (ctrl) /* reset control list */ writel (0, &ohci->regs->ed_controlcurrent); - if (bulk) /* reset BULK list */ + if (bulk) /* reset bulk list */ writel (0, &ohci->regs->ed_bulkcurrent); if (!ohci->ed_rm_list[!frame]) { - ohci->hc_control |= OHCI_CTRL_CLE | OHCI_CTRL_BLE; + if (ohci->ed_controltail) + ohci->hc_control |= OHCI_CTRL_CLE; + if (ohci->ed_bulktail) + ohci->hc_control |= OHCI_CTRL_BLE; writel (ohci->hc_control, &ohci->regs->control); } } - ohci->ed_rm_list[frame] = NULL; + ohci->ed_rm_list[frame] = NULL; spin_unlock_irqrestore (&usb_ed_lock, flags); } @@ -1439,14 +1520,15 @@ static void dl_done_list (ohci_t * ohci, td_t * td_list) cc = TD_CC_NOERROR; if (++(urb_priv->td_cnt) == urb_priv->length) { - if (urb_priv->state != URB_DEL - && !(ed->state & ED_DEL) - && ed->state != ED_NEW) { + if ((ed->state & (ED_OPER | ED_UNLINK)) + && (urb_priv->state != URB_DEL)) { urb->status = cc_to_error[cc]; sohci_return_urb (urb); } else { - urb_rm_priv (urb); - } + spin_lock_irqsave (&usb_ed_lock, flags); + dl_del_urb (urb); + spin_unlock_irqrestore (&usb_ed_lock, flags); + } } spin_lock_irqsave (&usb_ed_lock, flags); @@ -1600,7 +1682,8 @@ static void rh_int_timer_do (unsigned long ptr) #ifdef DEBUG urb_print (urb, "RET-t(rh)", usb_pipeout (urb->pipe)); #endif - if (urb->complete) urb->complete (urb); + if (urb->complete) + urb->complete (urb); } } out: @@ -1656,7 +1739,6 @@ static int rh_submit_urb (urb_t * urb) __u16 wLength; if (usb_pipeint(pipe)) { - ohci->rh.urb = urb; ohci->rh.send = 1; ohci->rh.interval = urb->interval; @@ -1827,9 +1909,11 @@ static int rh_submit_urb (urb_t * urb) urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe)); #endif + urb->hcpriv = NULL; + usb_dec_dev_use (usb_dev); + urb->dev = NULL; if (urb->complete) urb->complete (urb); - usb_dec_dev_use (urb->dev); return 0; } @@ -1842,6 +1926,17 @@ static int rh_unlink_urb (urb_t * urb) if (ohci->rh.urb == urb) { ohci->rh.send = 0; del_timer (&ohci->rh.rh_int_timer); + ohci->rh.urb = NULL; + + urb->hcpriv = NULL; + usb_dec_dev_use(urb->dev); + urb->dev = NULL; + if (urb->transfer_flags & USB_ASYNC_UNLINK) { + urb->status = -ECONNRESET; + if (urb->complete) + urb->complete (urb); + } else + urb->status = -ENOENT; } return 0; } @@ -2352,6 +2447,12 @@ ohci_pci_resume (struct pci_dev *dev) ohci->disabled = 0; ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; + if (!ohci->ed_rm_list[0] & !ohci->ed_rm_list[1]) { + if (ohci->ed_controltail) + ohci->hc_control |= OHCI_CTRL_CLE; + if (ohci->ed_bulktail) + ohci->hc_control |= OHCI_CTRL_BLE; + } writel (ohci->hc_control, &ohci->regs->control); #ifdef CONFIG_PMAC_PBOOK enable_irq (ohci->irq); @@ -2448,7 +2549,6 @@ static int __init ohci_hcd_init (void) return ret; } - /*-------------------------------------------------------------------------*/ static void __exit ohci_hcd_cleanup (void) @@ -2463,6 +2563,5 @@ module_init (ohci_hcd_init); module_exit (ohci_hcd_cleanup); - MODULE_AUTHOR ("Roman Weissgaerber , David Brownell"); MODULE_DESCRIPTION ("USB OHCI Host Controller Driver"); diff --git a/drivers/usb/usb-ohci.h b/drivers/usb/usb-ohci.h index c49f9e91c846..086db1a12f19 100644 --- a/drivers/usb/usb-ohci.h +++ b/drivers/usb/usb-ohci.h @@ -107,7 +107,7 @@ typedef struct td { __u32 hwBE; /* Memory Buffer End Pointer */ __u16 hwPSW[MAXPSW]; - __u8 type; + __u8 unused; __u8 index; struct ed * ed; struct td * next_dl_td; @@ -115,18 +115,6 @@ typedef struct td { } td_t; -/* TD types */ -#define BULK 0x03 -#define INT 0x01 -#define CTRL 0x02 -#define ISO 0x00 - -#define SEND 0x01 -#define ST_ADDR 0x02 -#define ADD_LEN 0x04 -#define DEL 0x08 - - #define OHCI_ED_SKIP (1 << 14) /* @@ -347,7 +335,7 @@ typedef struct __u16 length; // number of tds associated with this request __u16 td_cnt; // number of tds already serviced int state; - void * wait; + wait_queue_head_t * wait; td_t * td[0]; // list pointer to all corresponding TDs associated with this request } urb_priv_t; @@ -398,7 +386,7 @@ typedef struct ohci { struct ohci_device { ed_t ed[NUM_EDS]; int ed_cnt; - void * wait; + wait_queue_head_t * wait; }; // #define ohci_to_usb(ohci) ((ohci)->usb) diff --git a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c index 881342af6201..fbed8c1584d3 100644 --- a/drivers/usb/usb-uhci.c +++ b/drivers/usb/usb-uhci.c @@ -1057,6 +1057,7 @@ _static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb) uhci_desc_t *qh; urb_priv_t *urb_priv; unsigned long flags=0; + struct usb_device *usb_dev; spin_lock_irqsave (&s->urb_list_lock, flags); @@ -1103,11 +1104,13 @@ _static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb) #else kfree (urb->hcpriv); #endif + usb_dev = urb->dev; if (urb->complete) { dbg("unlink_urb: calling completion"); + urb->dev = NULL; urb->complete ((struct urb *) urb); } - usb_dec_dev_use (urb->dev); + usb_dec_dev_use (usb_dev); } else { if (!in_interrupt()) @@ -1171,6 +1174,7 @@ _static void uhci_cleanup_unlink(uhci_t *s, int force) if (urb->complete) { spin_unlock(&s->urb_list_lock); + urb->dev = NULL; urb->complete ((struct urb *) urb); spin_lock(&s->urb_list_lock); } @@ -2082,6 +2086,7 @@ _static int rh_submit_urb (urb_t *urb) urb->actual_length = len; urb->status = stat; + urb->dev=NULL; if (urb->complete) urb->complete (urb); return 0; @@ -2484,7 +2489,6 @@ _static int process_urb (uhci_t *s, struct list_head *p) int ret = 0; urb_t *urb; - urb=list_entry (p, urb_t, urb_list); //dbg("process_urb: found queued urb: %p", urb); @@ -2508,6 +2512,9 @@ _static int process_urb (uhci_t *s, struct list_head *p) if (urb->status != -EINPROGRESS) { int proceed = 0; + struct usb_device *usb_dev; + + usb_dev=urb->dev; /* Release bandwidth for Interrupt or Iso transfers */ if (urb->bandwidth) { @@ -2549,9 +2556,12 @@ _static int process_urb (uhci_t *s, struct list_head *p) // In case you need the current URB status for your completion handler (before resubmit) if (urb->complete && (!proceed )) { dbg("process_transfer: calling early completion"); + urb->dev = NULL; urb->complete ((struct urb *) urb); - if (!proceed && is_ring && (urb->status != -ENOENT)) + if (!proceed && is_ring && (urb->status != -ENOENT)) { + urb->dev=usb_dev; uhci_submit_urb (urb); + } } if (proceed && urb->next) { @@ -2567,11 +2577,13 @@ _static int process_urb (uhci_t *s, struct list_head *p) if (urb->complete) { dbg("process_transfer: calling completion"); + urb->dev=NULL; urb->complete ((struct urb *) urb); } } - - usb_dec_dev_use (urb->dev); + + urb->dev=NULL; // Just in case no completion was called + usb_dec_dev_use (usb_dev); spin_unlock(&urb->lock); spin_lock(&s->urb_list_lock); } diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c index ececaa03b1f4..df469e7d81ff 100644 --- a/drivers/usb/usb.c +++ b/drivers/usb/usb.c @@ -35,6 +35,11 @@ #endif #include +#define DEVNUM_ROUND_ROBIN /***** OPTION *****/ +#ifdef DEVNUM_ROUND_ROBIN +static int devnum_next = 1; +#endif + static const int usb_bandwidth_option = #ifdef CONFIG_USB_BANDWIDTH 1; @@ -1470,7 +1475,19 @@ void usb_connect(struct usb_device *dev) * which hopefully doesn't run on multiple CPU's simultaneously 8-) */ dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */ +#ifndef DEVNUM_ROUND_ROBIN devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1); +#else /* round_robin alloc of devnums */ + /* Try to allocate the next devnum beginning at devnum_next. */ + devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, devnum_next); + if (devnum >= 128) + devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1); + + devnum_next = devnum + 1; + if (devnum_next >= 128) + devnum_next = 1; +#endif /* round_robin alloc of devnums */ + if (devnum < 128) { set_bit(devnum, dev->bus->devmap.devicemap); dev->devnum = devnum; diff --git a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h index 89a566312a73..649abd02d351 100644 --- a/include/asm-alpha/bitops.h +++ b/include/asm-alpha/bitops.h @@ -2,6 +2,7 @@ #define _ALPHA_BITOPS_H #include +#include /* * Copyright 1994, Linus Torvalds. diff --git a/include/asm-sh/atomic.h b/include/asm-sh/atomic.h index f9aa875aea98..6fe7d5194eb3 100644 --- a/include/asm-sh/atomic.h +++ b/include/asm-sh/atomic.h @@ -7,8 +7,6 @@ * */ -#include - typedef struct { volatile int counter; } atomic_t; #define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) diff --git a/include/asm-sparc/atomic.h b/include/asm-sparc/atomic.h index 9e7f4a5b05a8..4a55a8929a68 100644 --- a/include/asm-sparc/atomic.h +++ b/include/asm-sparc/atomic.h @@ -8,19 +8,12 @@ #include -#ifdef CONFIG_SMP -/* This is a temporary measure. -DaveM */ typedef struct { volatile int counter; } atomic_t; -#define ATOMIC_INIT(i) { (i << 8) } -#else -typedef struct { int counter; } atomic_t; -#define ATOMIC_INIT(i) { (i) } -#endif #ifdef __KERNEL__ - #ifndef CONFIG_SMP +#define ATOMIC_INIT(i) { (i) } #define atomic_read(v) ((v)->counter) #define atomic_set(v, i) (((v)->counter) = i) @@ -39,6 +32,8 @@ typedef struct { int counter; } atomic_t; * 31 8 7 0 */ +#define ATOMIC_INIT(i) { (i << 8) } + static __inline__ int atomic_read(atomic_t *v) { int ret = v->counter; diff --git a/include/asm-sparc/bitops.h b/include/asm-sparc/bitops.h index 8ab8bdaf024c..b1085349015a 100644 --- a/include/asm-sparc/bitops.h +++ b/include/asm-sparc/bitops.h @@ -1,4 +1,4 @@ -/* $Id: bitops.h,v 1.60 2000/08/10 23:49:16 davem Exp $ +/* $Id: bitops.h,v 1.61 2000/09/23 02:11:22 davem Exp $ * bitops.h: Bit string operations on the Sparc. * * Copyright 1995 David S. Miller (davem@caip.rutgers.edu) @@ -156,6 +156,9 @@ extern __inline__ void change_bit(unsigned long nr, volatile void *addr) #endif /* __KERNEL__ */ +#define smp_mb__before_clear_bit() do { } while(0) +#define smp_mb__after_clear_bit() do { } while(0) + /* The following routine need not be atomic. */ extern __inline__ int test_bit(int nr, __const__ void *addr) { diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h index 0a101cacd790..28b07675fa8c 100644 --- a/include/asm-sparc/system.h +++ b/include/asm-sparc/system.h @@ -1,4 +1,4 @@ -/* $Id: system.h,v 1.83 2000/08/04 05:35:55 davem Exp $ */ +/* $Id: system.h,v 1.84 2000/09/23 02:11:22 davem Exp $ */ #include #ifndef __SPARC_SYSTEM_H @@ -280,6 +280,9 @@ extern void __global_restore_flags(unsigned long flags); #define wmb() mb() #define set_mb(__var, __value) do { __var = __value; mb(); } while(0) #define set_wmb(__var, __value) set_mb(__var, __value) +#define smp_mb() __asm__ __volatile__("":::"memory"); +#define smp_rmb() __asm__ __volatile__("":::"memory"); +#define smp_wmb() __asm__ __volatile__("":::"memory"); #define nop() __asm__ __volatile__ ("nop"); diff --git a/include/asm-sparc64/atomic.h b/include/asm-sparc64/atomic.h index db3cd58319d9..2461ec29d435 100644 --- a/include/asm-sparc64/atomic.h +++ b/include/asm-sparc64/atomic.h @@ -8,7 +8,7 @@ #ifndef __ARCH_SPARC64_ATOMIC__ #define __ARCH_SPARC64_ATOMIC__ -typedef struct { int counter; } atomic_t; +typedef struct { volatile int counter; } atomic_t; #define ATOMIC_INIT(i) { (i) } #define atomic_read(v) ((v)->counter) diff --git a/include/asm-sparc64/bitops.h b/include/asm-sparc64/bitops.h index e297d6f96e88..26e3716ccea3 100644 --- a/include/asm-sparc64/bitops.h +++ b/include/asm-sparc64/bitops.h @@ -1,4 +1,4 @@ -/* $Id: bitops.h,v 1.30 2000/08/10 23:49:16 davem Exp $ +/* $Id: bitops.h,v 1.31 2000/09/23 02:09:21 davem Exp $ * bitops.h: Bit string operations on the V9. * * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -20,6 +20,9 @@ extern long __test_and_change_bit(unsigned long nr, volatile void *addr); #define clear_bit(nr,addr) ((void)__test_and_clear_bit(nr,addr)) #define change_bit(nr,addr) ((void)__test_and_change_bit(nr,addr)) +#define smp_mb__before_clear_bit() do { } while(0) +#define smp_mb__after_clear_bit() do { } while(0) + extern __inline__ int test_bit(int nr, __const__ void *addr) { return (1UL & (((__const__ long *) addr)[nr >> 6] >> (nr & 63))) != 0UL; diff --git a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h index 0927fe5cc432..3898efdd2e9f 100644 --- a/include/asm-sparc64/smp.h +++ b/include/asm-sparc64/smp.h @@ -9,6 +9,7 @@ #include #include #include +#include #ifndef __ASSEMBLY__ /* PROM provided per-processor information we need @@ -82,11 +83,7 @@ extern __inline__ int cpu_number_map(int cpu) extern __inline__ int hard_smp_processor_id(void) { - extern int this_is_starfire; - if(this_is_starfire != 0) { - extern int starfire_hard_smp_processor_id(void); - return starfire_hard_smp_processor_id(); } else { unsigned long upaconfig; diff --git a/include/asm-sparc64/starfire.h b/include/asm-sparc64/starfire.h new file mode 100644 index 000000000000..d59bda0c3a9d --- /dev/null +++ b/include/asm-sparc64/starfire.h @@ -0,0 +1,21 @@ +/* $Id: starfire.h,v 1.1 2000/09/21 06:18:53 anton Exp $ + * starfire.h: Group all starfire specific code together. + * + * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com) + */ + +#ifndef _SPARC64_STARFIRE_H +#define _SPARC64_STARFIRE_H + +#ifndef __ASSEMBLY__ + +extern int this_is_starfire; + +extern void check_if_starfire(void); +extern void starfire_cpu_setup(void); +extern int starfire_hard_smp_processor_id(void); +extern void *starfire_hookup(int); +extern unsigned int starfire_translate(unsigned long imap, unsigned int upaid); + +#endif +#endif diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h index 6235edd7c743..3c396eb0073f 100644 --- a/include/asm-sparc64/system.h +++ b/include/asm-sparc64/system.h @@ -1,4 +1,4 @@ -/* $Id: system.h,v 1.61 2000/08/04 05:35:55 davem Exp $ */ +/* $Id: system.h,v 1.62 2000/09/23 02:09:21 davem Exp $ */ #ifndef __SPARC64_SYSTEM_H #define __SPARC64_SYSTEM_H @@ -95,11 +95,11 @@ extern void __global_restore_flags(unsigned long flags); #endif -#define mb() __asm__ __volatile__ ("stbar" : : : "memory") - #define nop() __asm__ __volatile__ ("nop") #define membar(type) __asm__ __volatile__ ("membar " type : : : "memory"); +#define mb() \ + membar("#LoadLoad | #LoadStore | #StoreStore | #StoreLoad"); #define rmb() membar("#LoadLoad") #define wmb() membar("#StoreStore") #define set_mb(__var, __value) \ @@ -107,6 +107,16 @@ extern void __global_restore_flags(unsigned long flags); #define set_wmb(__var, __value) \ do { __var = __value; membar("#StoreStore"); } while(0) +#ifdef CONFIG_SMP +#define smp_mb() mb() +#define smp_rmb() rmb() +#define smp_wmb() wmb() +#else +#define smp_mb() __asm__ __volatile__("":::"memory"); +#define smp_rmb() __asm__ __volatile__("":::"memory"); +#define smp_wmb() __asm__ __volatile__("":::"memory"); +#endif + #define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory") #define flushw_all() __asm__ __volatile__("flushw") diff --git a/include/linux/major.h b/include/linux/major.h index 1a3f0ddb5d52..372e1841a3ac 100644 --- a/include/linux/major.h +++ b/include/linux/major.h @@ -147,6 +147,10 @@ #define UNIX98_PTY_MAJOR_COUNT 8 #define UNIX98_PTY_SLAVE_MAJOR (UNIX98_PTY_MASTER_MAJOR+UNIX98_PTY_MAJOR_COUNT) +#define VXVM_MAJOR 199 /* VERITAS volume i/o driver */ +#define VXSPEC_MAJOR 200 /* VERITAS volume config driver */ +#define VXDMP_MAJOR 201 /* VERITAS volume multipath driver */ + #define MSR_MAJOR 202 #define CPUID_MAJOR 203 diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index bbbefdbf45ba..c173b9eb30f5 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1066,16 +1066,13 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length) { char tbuf[16]; sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->primary_key)); - - size = sprintf(buffer+len, "%-16s 0x%-10x0x%-10x%s", + size = sprintf(buffer+len, "%-16s 0x%-10x0x%-10x%s" + " * %s\n", tbuf, hatype, arp_state_to_flags(n), - hbuffer); - - size += sprintf(buffer+len+size, - " %-8s %s\n", - "*", dev->name); + hbuffer, + dev->name); } read_unlock(&n->lock); @@ -1102,15 +1099,14 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length) { char tbuf[16]; sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->key)); - size = sprintf(buffer+len, "%-16s 0x%-10x0x%-10x%s", + size = sprintf(buffer+len, "%-16s 0x%-10x0x%-10x%s" + " * %s\n", tbuf, hatype, ATF_PUBL|ATF_PERM, - "00:00:00:00:00:00"); + "00:00:00:00:00:00", + dev ? dev->name : "*"); } - size += sprintf(buffer+len+size, - " * %-16s\n", - dev ? dev->name : "*"); len += size; pos += size; diff --git a/scripts/ksymoops/README b/scripts/ksymoops/README index c463b4c7182e..f6cb06e3f30e 100644 --- a/scripts/ksymoops/README +++ b/scripts/ksymoops/README @@ -1,7 +1,8 @@ ksymoops has been removed from the kernel. It was always meant to be a free standing utility, not linked to any particular kernel version. -The latest version can be found in ftp://ftp.ocs.com.au/pub/ksymoops, -together with patches to other utilities in order to give more accurate -Oops debugging. +The latest version can be found in +ftp://ftp..kernel.org/pub/linux/utils/kernel/ksymoops together +with patches to other utilities in order to give more accurate Oops +debugging. Keith Owens Sat Jun 19 10:30:34 EST 1999