Commit 78ff69d0 authored by Linus Torvalds's avatar Linus Torvalds

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
parent 33aa1817
Quick Summary Quick Summary
------------- -------------
Install ksymoops from ftp://ftp.ocs.com.au/pub/ksymoops Install ksymoops from
ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops
Read the ksymoops man page. Read the ksymoops man page.
ksymoops < the_oops.txt ksymoops < the_oops.txt
......
...@@ -44,7 +44,7 @@ typedef struct urb ...@@ -44,7 +44,7 @@ typedef struct urb
// status after each completion // status after each completion
int status; // returned status 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 // for data stage (CTRL), BULK, INT and ISO
void *transfer_buffer; // associated data buffer void *transfer_buffer; // associated data buffer
...@@ -105,10 +105,9 @@ For ASAP set USB_ISO_ASAP in transfer_flags. ...@@ -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 If short packets should NOT be tolerated, set USB_DISABLE_SPD in
transfer_flags. transfer_flags.
Usually, (to reduce restart time) the completion handler is called Usually, to reduce restart time, the completion handler is called
AFTER the URB re-submission. You can get the other way by setting AFTER the URB re-submission. However, it is called BEFORE URB
USB_URB_EARLY_COMPLETE in transfer_flags. This is implicit for re-submission for INT transfers that are being continued.
INT transfers.
1.5. How to submit an URB? 1.5. How to submit an URB?
...@@ -172,10 +171,12 @@ In the completion handler, you should have a look at urb->status to ...@@ -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, detect any USB errors. Since the context parameter is included in the URB,
you can pass information to the completion handler. 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 as part of URB unlinking. Instead, use urb->context to hold all the
data your driver needs. data your driver needs.
NOTE: ***** WARNING *****
Also, NEVER SLEEP IN A COMPLETION HANDLER. These are normally called Also, NEVER SLEEP IN A COMPLETION HANDLER. These are normally called
during hardware interrupt processing. If you can, defer substantial during hardware interrupt processing. If you can, defer substantial
work to a tasklet (bottom half) to keep system latencies low. You'll work to a tasklet (bottom half) to keep system latencies low. You'll
......
...@@ -270,7 +270,8 @@ IF SOMETHING GOES WRONG: ...@@ -270,7 +270,8 @@ IF SOMETHING GOES WRONG:
on making sense of the dump is in Documentation/oops-tracing.txt 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 - 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.<country>.kernel.org/pub/linux/utils/kernel/ksymoops.
Alternately you can do the dump lookup by hand: Alternately you can do the dump lookup by hand:
- In debugging dumps like the above, it helps enormously if you can - In debugging dumps like the above, it helps enormously if you can
......
/* $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 * pcic.c: Sparc/PCI controller support
* *
* Copyright (C) 1998 V. Roganov and G. Raiko * Copyright (C) 1998 V. Roganov and G. Raiko
...@@ -35,11 +35,6 @@ ...@@ -35,11 +35,6 @@
#ifndef CONFIG_PCI #ifndef CONFIG_PCI
int pcibios_present(void)
{
return 0;
}
asmlinkage int sys_pciconfig_read(unsigned long bus, asmlinkage int sys_pciconfig_read(unsigned long bus,
unsigned long dfn, unsigned long dfn,
unsigned long off, unsigned long off,
...@@ -976,7 +971,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, ...@@ -976,7 +971,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus,
if(!suser()) if(!suser())
return -EPERM; return -EPERM;
lock_kernel();
switch(len) { switch(len) {
case 1: case 1:
err = get_user(ubyte, (unsigned char *)buf); err = get_user(ubyte, (unsigned char *)buf);
...@@ -1004,7 +998,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, ...@@ -1004,7 +998,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus,
break; break;
}; };
unlock_kernel();
return err; return err;
} }
......
/* $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 Simple utility to make a single-image install kernel with initial ramdisk
for Sparc64 tftpbooting without need to set up nfs. for Sparc64 tftpbooting without need to set up nfs.
...@@ -50,9 +50,9 @@ int main(int argc,char **argv) ...@@ -50,9 +50,9 @@ int main(int argc,char **argv)
map = fopen (argv[2], "r"); map = fopen (argv[2], "r");
if (!map) die(argv[2]); if (!map) die(argv[2]);
while (fgets (buffer, 1024, map)) { while (fgets (buffer, 1024, map)) {
if (!strcmp (buffer + 19, "start\n")) if (!strcmp (buffer + 19, "_start\n"))
start = strtoul (buffer + 8, NULL, 16); 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); end = strtoul (buffer + 8, NULL, 16);
} }
fclose (map); fclose (map);
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <asm/sbus.h> #include <asm/sbus.h>
#include <asm/ebus.h> #include <asm/ebus.h>
#include <asm/fhc.h> #include <asm/fhc.h>
#include <asm/starfire.h>
/* Probe and map in the Auxiliary I/O register */ /* Probe and map in the Auxiliary I/O register */
unsigned long auxio_register = 0; unsigned long auxio_register = 0;
...@@ -55,7 +56,7 @@ void __init auxio_probe(void) ...@@ -55,7 +56,7 @@ void __init auxio_probe(void)
return; return;
} }
#endif #endif
if(central_bus) { if(central_bus || this_is_starfire) {
auxio_register = 0UL; auxio_register = 0UL;
return; return;
} }
......
/* $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. * central.c: Central FHC driver for Sunfire/Starfire/Wildfire.
* *
* Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com) * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com)
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/fhc.h> #include <asm/fhc.h>
#include <asm/starfire.h>
struct linux_central *central_bus = NULL; struct linux_central *central_bus = NULL;
struct linux_fhc *fhc_list = NULL; struct linux_fhc *fhc_list = NULL;
...@@ -254,9 +255,8 @@ void central_probe(void) ...@@ -254,9 +255,8 @@ void central_probe(void)
cnode = prom_finddevice("/central"); cnode = prom_finddevice("/central");
if(cnode == 0 || cnode == -1) { if(cnode == 0 || cnode == -1) {
extern void starfire_check(void); if (this_is_starfire)
starfire_cpu_setup();
starfire_check();
return; return;
} }
......
/* $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. * irq.c: UltraSparc IRQ handling/init/registry.
* *
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/hardirq.h> #include <asm/hardirq.h>
#include <asm/softirq.h> #include <asm/softirq.h>
#include <asm/starfire.h>
/* Internal flag, should not be visible elsewhere at all. */ /* Internal flag, should not be visible elsewhere at all. */
#define SA_IMAP_MASKED 0x100 #define SA_IMAP_MASKED 0x100
...@@ -123,7 +124,6 @@ int get_irq_list(char *buf) ...@@ -123,7 +124,6 @@ int get_irq_list(char *buf)
/* Now these are always passed a true fully specified sun4u INO. */ /* Now these are always passed a true fully specified sun4u INO. */
void enable_irq(unsigned int irq) void enable_irq(unsigned int irq)
{ {
extern int this_is_starfire;
struct ino_bucket *bucket = __bucket(irq); struct ino_bucket *bucket = __bucket(irq);
unsigned long imap; unsigned long imap;
unsigned long tid; unsigned long tid;
...@@ -139,9 +139,6 @@ void enable_irq(unsigned int irq) ...@@ -139,9 +139,6 @@ void enable_irq(unsigned int irq)
: "i" (ASI_UPA_CONFIG)); : "i" (ASI_UPA_CONFIG));
tid = ((tid & UPA_CONFIG_MID) << 9); tid = ((tid & UPA_CONFIG_MID) << 9);
} else { } else {
extern unsigned int starfire_translate(unsigned long imap,
unsigned int upaid);
tid = (starfire_translate(imap, current->processor) << 26); tid = (starfire_translate(imap, current->processor) << 26);
} }
...@@ -715,7 +712,6 @@ void handler_irq(int irq, struct pt_regs *regs) ...@@ -715,7 +712,6 @@ void handler_irq(int irq, struct pt_regs *regs)
struct ino_bucket *bp, *nbp; struct ino_bucket *bp, *nbp;
int cpu = smp_processor_id(); int cpu = smp_processor_id();
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
extern int this_is_starfire;
int should_forward = (this_is_starfire == 0 && int should_forward = (this_is_starfire == 0 &&
irq < 10 && irq < 10 &&
current->pid != 0); current->pid != 0);
...@@ -1029,7 +1025,6 @@ void init_timers(void (*cfunc)(int, void *, struct pt_regs *), ...@@ -1029,7 +1025,6 @@ void init_timers(void (*cfunc)(int, void *, struct pt_regs *),
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static int retarget_one_irq(struct irqaction *p, int goal_cpu) static int retarget_one_irq(struct irqaction *p, int goal_cpu)
{ {
extern int this_is_starfire;
struct ino_bucket *bucket = __bucket(p->mask); struct ino_bucket *bucket = __bucket(p->mask);
unsigned long imap = bucket->imap; unsigned long imap = bucket->imap;
unsigned int tid; unsigned int tid;
...@@ -1041,9 +1036,6 @@ static int retarget_one_irq(struct irqaction *p, int goal_cpu) ...@@ -1041,9 +1036,6 @@ static int retarget_one_irq(struct irqaction *p, int goal_cpu)
if(this_is_starfire == 0) { if(this_is_starfire == 0) {
tid = __cpu_logical_map[goal_cpu] << 26; tid = __cpu_logical_map[goal_cpu] << 26;
} else { } else {
extern unsigned int starfire_translate(unsigned long imap,
unsigned int upaid);
tid = (starfire_translate(imap, __cpu_logical_map[goal_cpu]) << 26); tid = (starfire_translate(imap, __cpu_logical_map[goal_cpu]) << 26);
} }
upa_writel(IMAP_VALID | (tid & IMAP_TID), imap); upa_writel(IMAP_VALID | (tid & IMAP_TID), imap);
......
...@@ -24,7 +24,6 @@ unsigned long pci_memspace_mask = 0xffffffffUL; ...@@ -24,7 +24,6 @@ unsigned long pci_memspace_mask = 0xffffffffUL;
#ifndef CONFIG_PCI #ifndef CONFIG_PCI
/* A "nop" PCI implementation. */ /* A "nop" PCI implementation. */
int pcibios_present(void) { return 0; }
asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn, asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn,
unsigned long off, unsigned long len, unsigned long off, unsigned long len,
unsigned char *buf) unsigned char *buf)
...@@ -316,7 +315,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, ...@@ -316,7 +315,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus,
goto out; goto out;
} }
lock_kernel();
switch(len) { switch(len) {
case 1: case 1:
err = get_user(byte, (u8 *)buf); err = get_user(byte, (u8 *)buf);
...@@ -344,7 +342,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, ...@@ -344,7 +342,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus,
break; break;
}; };
unlock_kernel();
out: out:
return err; return err;
......
/* $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. * pci_psycho.c: PSYCHO/U2P specific PCI controller support.
* *
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <asm/pbm.h> #include <asm/pbm.h>
#include <asm/iommu.h> #include <asm/iommu.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/starfire.h>
#include "pci_impl.h" #include "pci_impl.h"
...@@ -1254,8 +1255,6 @@ static void __init psycho_scan_bus(struct pci_controller_info *p) ...@@ -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) 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; unsigned long tsbbase, i;
u64 control; u64 control;
......
/* $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. * sbus.c: UltraSparc SBUS controller support.
* *
* Copyright (C) 1999 David S. Miller (davem@redhat.com) * Copyright (C) 1999 David S. Miller (davem@redhat.com)
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/starfire.h>
#include "iommu_common.h" #include "iommu_common.h"
...@@ -1151,15 +1152,10 @@ void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus) ...@@ -1151,15 +1152,10 @@ void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus)
upa_writeq(control, iommu->sbus_control_reg); upa_writeq(control, iommu->sbus_control_reg);
/* Now some Xfire specific grot... */ /* Now some Xfire specific grot... */
{ if (this_is_starfire)
extern void *starfire_hookup(int); sbus->starfire_cookie = starfire_hookup(sbus->portid);
extern int this_is_starfire; 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); sysio_register_error_handlers(sbus);
} }
/* $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 * linux/arch/sparc64/kernel/setup.c
* *
* Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/idprom.h> #include <asm/idprom.h>
#include <asm/head.h> #include <asm/head.h>
#include <asm/starfire.h>
#ifdef CONFIG_IP_PNP #ifdef CONFIG_IP_PNP
#include <net/ipconfig.h> #include <net/ipconfig.h>
...@@ -479,6 +480,9 @@ void __init setup_arch(char **cmdline_p) ...@@ -479,6 +480,9 @@ void __init setup_arch(char **cmdline_p)
conswitchp = &prom_con; conswitchp = &prom_con;
#endif #endif
/* Work out if we are starfire early on */
check_if_starfire();
boot_flags_init(*cmdline_p); boot_flags_init(*cmdline_p);
idprom_init(); idprom_init();
......
/* $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. * starfire.c: Starfire/E10000 support.
* *
* Copyright (C) 1998 David S. Miller (davem@redhat.com) * Copyright (C) 1998 David S. Miller (davem@redhat.com)
* Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com)
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -11,23 +12,31 @@ ...@@ -11,23 +12,31 @@
#include <asm/oplib.h> #include <asm/oplib.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/upa.h> #include <asm/upa.h>
#include <asm/starfire.h>
/* 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 * they need to call us to do things in a Starfire specific
* way. * way.
*/ */
int this_is_starfire = 0; int this_is_starfire = 0;
void starfire_check(void) void check_if_starfire(void)
{ {
int ssnode = prom_finddevice("/ssp-serial"); 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; 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. * linear cpuid number, not the real upaid.
*/ */
for(i = 0; i < linux_num_cpus; i++) { for(i = 0; i < linux_num_cpus; i++) {
...@@ -39,6 +48,7 @@ void starfire_check(void) ...@@ -39,6 +48,7 @@ void starfire_check(void)
linux_cpus[i].mid = mid; linux_cpus[i].mid = mid;
} }
#endif
} }
} }
...@@ -47,7 +57,8 @@ int starfire_hard_smp_processor_id(void) ...@@ -47,7 +57,8 @@ int starfire_hard_smp_processor_id(void)
return upa_readl(0x1fff40000d0UL); 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 * and delivery of traditional interrupt packets into the extended
* Starfire hardware format. Essentially UPAID's now have 2 more * Starfire hardware format. Essentially UPAID's now have 2 more
* bits than in all previous Sun5 systems. * bits than in all previous Sun5 systems.
...@@ -82,6 +93,9 @@ void *starfire_hookup(int upaid) ...@@ -82,6 +93,9 @@ void *starfire_hookup(int upaid)
for(i = 0; i < 32; i++) { for(i = 0; i < 32; i++) {
p->imap_slots[i] = 0UL; p->imap_slots[i] = 0UL;
p->tregs[i] = treg_base + (i * 0x10UL); 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->upaid = upaid;
p->next = sflist; p->next = sflist;
...@@ -116,6 +130,12 @@ unsigned int starfire_translate(unsigned long imap, ...@@ -116,6 +130,12 @@ unsigned int starfire_translate(unsigned long imap,
panic("Lucy in the sky...."); panic("Lucy in the sky....");
} }
p->imap_slots[i] = imap; p->imap_slots[i] = imap;
/* map to real upaid */
upaid = (((upaid & 0x3c) << 1) |
((upaid & 0x40) >> 4) |
(upaid & 0x3));
upa_writel(upaid, p->tregs[i]); upa_writel(upaid, p->tregs[i]);
return i; return i;
......
/* $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. * time.c: UltraSparc timer and TOD clock support.
* *
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <asm/fhc.h> #include <asm/fhc.h>
#include <asm/pbm.h> #include <asm/pbm.h>
#include <asm/ebus.h> #include <asm/ebus.h>
#include <asm/starfire.h>
extern rwlock_t xtime_lock; extern rwlock_t xtime_lock;
...@@ -305,6 +306,20 @@ void __init clock_probe(void) ...@@ -305,6 +306,20 @@ void __init clock_probe(void)
struct linux_ebus *ebus = NULL; struct linux_ebus *ebus = NULL;
#endif #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); __save_and_cli(flags);
if(central_bus != NULL) { if(central_bus != NULL) {
...@@ -473,6 +488,9 @@ static __inline__ unsigned long do_gettimeoffset(void) ...@@ -473,6 +488,9 @@ static __inline__ unsigned long do_gettimeoffset(void)
void do_settimeofday(struct timeval *tv) void do_settimeofday(struct timeval *tv)
{ {
if (this_is_starfire)
return;
write_lock_irq(&xtime_lock); write_lock_irq(&xtime_lock);
tv->tv_usec -= do_gettimeoffset(); tv->tv_usec -= do_gettimeoffset();
...@@ -496,7 +514,10 @@ static int set_rtc_mmss(unsigned long nowtime) ...@@ -496,7 +514,10 @@ static int set_rtc_mmss(unsigned long nowtime)
unsigned long regs = mstk48t02_regs; unsigned long regs = mstk48t02_regs;
u8 tmp; 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) if (!regs)
return -1; return -1;
......
/* $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 * arch/sparc64/mm/init.c
* *
* Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/vaddrs.h> #include <asm/vaddrs.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/starfire.h>
extern void device_scan(void); extern void device_scan(void);
...@@ -200,7 +201,7 @@ static void inherit_prom_mappings(void) ...@@ -200,7 +201,7 @@ static void inherit_prom_mappings(void)
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
unsigned long vaddr; unsigned long vaddr;
if (trans[i].virt >= 0xf0000000 && trans[i].virt < 0x100000000) { if (trans[i].virt >= 0xf0000000 && trans[i].virt < 0x100000000) {
for (vaddr = trans[i].virt; for (vaddr = trans[i].virt;
vaddr < trans[i].virt + trans[i].size; vaddr < trans[i].virt + trans[i].size;
...@@ -808,7 +809,6 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) ...@@ -808,7 +809,6 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
unsigned long bootmap_pfn, bytes_avail, size; unsigned long bootmap_pfn, bytes_avail, size;
int i; int i;
bytes_avail = 0UL; bytes_avail = 0UL;
for (i = 0; sp_banks[i].num_bytes != 0; i++) { for (i = 0; sp_banks[i].num_bytes != 0; i++) {
end_of_phys_memory = sp_banks[i].base_addr + end_of_phys_memory = sp_banks[i].base_addr +
...@@ -999,12 +999,7 @@ void __init paging_init(void) ...@@ -999,12 +999,7 @@ void __init paging_init(void)
*/ */
{ {
extern void setup_tba(int); extern void setup_tba(int);
int is_starfire = prom_finddevice("/ssp-serial"); setup_tba(this_is_starfire);
if (is_starfire != 0 && is_starfire != -1)
is_starfire = 1;
else
is_starfire = 0;
setup_tba(is_starfire);
} }
inherit_locked_prom_mappings(1); inherit_locked_prom_mappings(1);
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#ifdef CONFIG_PROC_FS #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 #endif
static int sg_version_num = 30117; /* 2 digits for each component */ static int sg_version_num = 30117; /* 2 digits for each component */
/* /*
...@@ -69,10 +69,8 @@ ...@@ -69,10 +69,8 @@
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
static int sg_proc_init(void); static int sg_proc_init(void);
#ifdef MODULE
static void sg_proc_cleanup(void); static void sg_proc_cleanup(void);
#endif #endif
#endif
#ifndef LINUX_VERSION_CODE #ifndef LINUX_VERSION_CODE
#include <linux/version.h> #include <linux/version.h>
...@@ -271,7 +269,8 @@ static int sg_open(struct inode * inode, struct file * filp) ...@@ -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 * else try and use this device. Also, if error recovery fails, it
* may try and take the device offline, in which case all further * may try and take the device offline, in which case all further
* access to the device is prohibited. */ * 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; return -ENXIO;
SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags)); 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) ...@@ -279,7 +278,7 @@ static int sg_open(struct inode * inode, struct file * filp)
if (flags & O_EXCL) { if (flags & O_EXCL) {
if (O_RDONLY == (flags & O_ACCMODE)) if (O_RDONLY == (flags & O_ACCMODE))
return -EACCES; /* Can't lock it with read only access */ 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; return -EBUSY;
res = 0; /* following is a macro that beats race condition */ res = 0; /* following is a macro that beats race condition */
__wait_event_interruptible(sdp->o_excl_wait, __wait_event_interruptible(sdp->o_excl_wait,
...@@ -289,7 +288,7 @@ static int sg_open(struct inode * inode, struct file * filp) ...@@ -289,7 +288,7 @@ static int sg_open(struct inode * inode, struct file * filp)
return res; /* -ERESTARTSYS because signal hit process */ return res; /* -ERESTARTSYS because signal hit process */
} }
else if (sdp->exclude) { /* some other fd has an exclusive lock on dev */ 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; return -EBUSY;
res = 0; /* following is a macro that beats race condition */ res = 0; /* following is a macro that beats race condition */
__wait_event_interruptible(sdp->o_excl_wait, (! sdp->exclude), res); __wait_event_interruptible(sdp->o_excl_wait, (! sdp->exclude), res);
...@@ -353,9 +352,6 @@ static ssize_t sg_read(struct file * filp, char * buf, ...@@ -353,9 +352,6 @@ static ssize_t sg_read(struct file * filp, char * buf,
return -ENXIO; return -ENXIO;
SCSI_LOG_TIMEOUT(3, printk("sg_read: dev=%d, count=%d\n", SCSI_LOG_TIMEOUT(3, printk("sg_read: dev=%d, count=%d\n",
MINOR(sdp->i_rdev), (int)count)); MINOR(sdp->i_rdev), (int)count));
if(! scsi_block_when_processing_errors(sdp->device))
return -ENXIO;
if (ppos != &filp->f_pos) if (ppos != &filp->f_pos)
; /* FIXME: Hmm. Seek to the right place, or fail? */ ; /* FIXME: Hmm. Seek to the right place, or fail? */
if ((k = verify_area(VERIFY_WRITE, buf, count))) if ((k = verify_area(VERIFY_WRITE, buf, count)))
...@@ -451,15 +447,11 @@ static ssize_t sg_read(struct file * filp, char * buf, ...@@ -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, static ssize_t sg_new_read(Sg_fd * sfp, char * buf, size_t count,
Sg_request * srp) Sg_request * srp)
{ {
Sg_device * sdp = sfp->parentdp;
sg_io_hdr_t * hp = &srp->header; sg_io_hdr_t * hp = &srp->header;
int k, len; int k, len;
if(! scsi_block_when_processing_errors(sdp->device) )
return -ENXIO;
if (count < size_sg_io_hdr) if (count < size_sg_io_hdr)
return -EINVAL; return -EINVAL;
hp->sb_len_wr = 0; hp->sb_len_wr = 0;
if ((hp->mx_sb_len > 0) && hp->sbp) { if ((hp->mx_sb_len > 0) && hp->sbp) {
if ((CHECK_CONDITION & hp->masked_status) || if ((CHECK_CONDITION & hp->masked_status) ||
...@@ -503,7 +495,8 @@ static ssize_t sg_write(struct file * filp, const char * buf, ...@@ -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", SCSI_LOG_TIMEOUT(3, printk("sg_write: dev=%d, count=%d\n",
MINOR(sdp->i_rdev), (int)count)); 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; return -ENXIO;
if (ppos != &filp->f_pos) if (ppos != &filp->f_pos)
; /* FIXME: Hmm. Seek to the right place, or fail? */ ; /* FIXME: Hmm. Seek to the right place, or fail? */
...@@ -712,8 +705,6 @@ static int sg_ioctl(struct inode * inode, struct file * filp, ...@@ -712,8 +705,6 @@ static int sg_ioctl(struct inode * inode, struct file * filp,
return -ENXIO; return -ENXIO;
SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: dev=%d, cmd=0x%x\n", SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: dev=%d, cmd=0x%x\n",
MINOR(sdp->i_rdev), (int)cmd_in)); 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)); read_only = (O_RDWR != (filp->f_flags & O_ACCMODE));
switch(cmd_in) switch(cmd_in)
...@@ -885,7 +876,11 @@ static int sg_ioctl(struct inode * inode, struct file * filp, ...@@ -885,7 +876,11 @@ static int sg_ioctl(struct inode * inode, struct file * filp,
case SG_EMULATED_HOST: case SG_EMULATED_HOST:
return put_user(sdp->device->host->hostt->emulated, (int *)arg); return put_user(sdp->device->host->hostt->emulated, (int *)arg);
case SG_SCSI_RESET: 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; return -EBUSY;
result = get_user(val, (int *)arg); result = get_user(val, (int *)arg);
if (result) return result; if (result) return result;
...@@ -1301,16 +1296,14 @@ static void sg_detach(Scsi_Device * scsidp) ...@@ -1301,16 +1296,14 @@ static void sg_detach(Scsi_Device * scsidp)
return; return;
} }
#ifdef MODULE MODULE_AUTHOR("Douglas Gilbert");
MODULE_DESCRIPTION("SCSI generic (sg) driver");
MODULE_PARM(def_reserved_size, "i"); MODULE_PARM(def_reserved_size, "i");
MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd"); MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd");
#endif /* MODULE */
static int __init init_sg(void) { static int __init init_sg(void) {
#ifdef MODULE
if (def_reserved_size >= 0) if (def_reserved_size >= 0)
sg_big_buff = def_reserved_size; sg_big_buff = def_reserved_size;
#endif /* MODULE */
sg_template.module = THIS_MODULE; sg_template.module = THIS_MODULE;
return scsi_register_module(MODULE_SCSI_DEV, &sg_template); return scsi_register_module(MODULE_SCSI_DEV, &sg_template);
} }
...@@ -2551,7 +2544,6 @@ static int sg_proc_init() ...@@ -2551,7 +2544,6 @@ static int sg_proc_init()
return 0; return 0;
} }
#ifdef MODULE
static void sg_proc_cleanup() static void sg_proc_cleanup()
{ {
int k; int k;
...@@ -2563,7 +2555,6 @@ static void sg_proc_cleanup() ...@@ -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_leaf_names[k], sg_proc_sgp);
remove_proc_entry(sg_proc_sg_dirname, proc_scsi); remove_proc_entry(sg_proc_sg_dirname, proc_scsi);
} }
#endif
static int sg_proc_dressz_read(char * buffer, char ** start, off_t offset, static int sg_proc_dressz_read(char * buffer, char ** start, off_t offset,
int size, int * eof, void * data) int size, int * eof, void * data)
......
...@@ -23,7 +23,7 @@ typedef struct ...@@ -23,7 +23,7 @@ typedef struct
wait_queue_head_t wait; wait_queue_head_t wait;
wait_queue_head_t remove_ok; wait_queue_head_t remove_ok;
spinlock_t lock; spinlock_t lock;
volatile atomic_t pending_io; atomic_t pending_io;
driver_state_t state; driver_state_t state;
int remove_pending; int remove_pending;
int got_mem; int got_mem;
......
...@@ -12,6 +12,10 @@ ...@@ -12,6 +12,10 @@
* *
* History: * 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 * 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some
* urb unlink probs, indentation fixes * urb unlink probs, indentation fixes
* 2000/08/11 various oops fixes mostly affecting iso and cleanup from * 2000/08/11 various oops fixes mostly affecting iso and cleanup from
...@@ -78,8 +82,9 @@ ...@@ -78,8 +82,9 @@
/* For initializing controller (mask in an HCFS mode too) */ /* For initializing controller (mask in an HCFS mode too) */
#define OHCI_CONTROL_INIT \ #define OHCI_CONTROL_INIT \
(OHCI_CTRL_CBSR & 0x3) \ (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
| OHCI_CTRL_BLE | OHCI_CTRL_CLE | OHCI_CTRL_IE | OHCI_CTRL_PLE
#define OHCI_UNLINK_TIMEOUT (HZ / 10)
static LIST_HEAD (ohci_hcd_list); static LIST_HEAD (ohci_hcd_list);
static spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED; static spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
...@@ -89,36 +94,54 @@ 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 */ /* 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; 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++) { for (i = 0; i < urb_priv->length; i++) {
if (urb_priv->td [i]) { if (urb_priv->td [i]) {
OHCI_FREE (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) ...@@ -366,15 +389,15 @@ static int sohci_return_urb (urb_t * urb)
unsigned long flags; unsigned long flags;
int i; int i;
if (!urb_priv)
return -1; /* urb already unlinked */
/* just to be sure */ /* just to be sure */
if (!urb->complete) { if (!urb->complete) {
urb_rm_priv (urb); urb_rm_priv (urb);
usb_dec_dev_use (urb->dev);
return -1; return -1;
} }
if (!urb_priv) return -1; /* urb already unlinked */
#ifdef DEBUG #ifdef DEBUG
urb_print (urb, "RET", usb_pipeout (urb->pipe)); urb_print (urb, "RET", usb_pipeout (urb->pipe));
#endif #endif
...@@ -408,7 +431,6 @@ static int sohci_return_urb (urb_t * urb) ...@@ -408,7 +431,6 @@ static int sohci_return_urb (urb_t * urb)
} else { /* unlink URB, call complete */ } else { /* unlink URB, call complete */
urb_rm_priv (urb); urb_rm_priv (urb);
usb_dec_dev_use (urb->dev);
urb->complete (urb); urb->complete (urb);
} }
break; break;
...@@ -416,7 +438,6 @@ static int sohci_return_urb (urb_t * urb) ...@@ -416,7 +438,6 @@ static int sohci_return_urb (urb_t * urb)
case PIPE_BULK: case PIPE_BULK:
case PIPE_CONTROL: /* unlink URB, call complete */ case PIPE_CONTROL: /* unlink URB, call complete */
urb_rm_priv (urb); urb_rm_priv (urb);
usb_dec_dev_use (urb->dev);
urb->complete (urb); urb->complete (urb);
break; break;
} }
...@@ -438,7 +459,7 @@ static int sohci_submit_urb (urb_t * urb) ...@@ -438,7 +459,7 @@ static int sohci_submit_urb (urb_t * urb)
int bustime = 0; int bustime = 0;
if (!urb->dev || !urb->dev->bus) if (!urb->dev || !urb->dev->bus)
return -EINVAL; return -ENODEV;
if (urb->hcpriv) /* urb already in use */ if (urb->hcpriv) /* urb already in use */
return -EINVAL; return -EINVAL;
...@@ -453,7 +474,7 @@ static int sohci_submit_urb (urb_t * urb) ...@@ -453,7 +474,7 @@ static int sohci_submit_urb (urb_t * urb)
urb_print (urb, "SUB", usb_pipein (pipe)); urb_print (urb, "SUB", usb_pipein (pipe));
#endif #endif
/* a request to the virtual root hub */ /* handle a request to the virtual root hub */
if (usb_pipedevice (pipe) == ohci->rh.devnum) if (usb_pipedevice (pipe) == ohci->rh.devnum)
return rh_submit_urb (urb); return rh_submit_urb (urb);
...@@ -505,26 +526,22 @@ static int sohci_submit_urb (urb_t * 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 *)); memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (td_t *));
/* fill the private part of the URB */ /* fill the private part of the URB */
urb->hcpriv = urb_priv;
urb_priv->length = size; urb_priv->length = size;
urb_priv->td_cnt = 0;
urb_priv->state = 0;
urb_priv->ed = ed; urb_priv->ed = ed;
/* allocate the TDs */ /* allocate the TDs */
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
OHCI_ALLOC (urb_priv->td[i], sizeof (td_t)); OHCI_ALLOC (urb_priv->td[i], sizeof (td_t));
if (!urb_priv->td[i]) { if (!urb_priv->td[i]) {
urb_rm_priv (urb); urb_free_priv (urb_priv);
usb_dec_dev_use (urb->dev); usb_dec_dev_use (urb->dev);
return -ENOMEM; return -ENOMEM;
} }
} }
spin_lock_irqsave (&usb_ed_lock, flags);
if (ed->state == ED_NEW || (ed->state & ED_DEL)) { if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
urb_rm_priv(urb); urb_free_priv (urb_priv);
usb_dec_dev_use (urb->dev); usb_dec_dev_use (urb->dev);
spin_unlock_irqrestore(&usb_ed_lock, flags);
return -EINVAL; return -EINVAL;
} }
...@@ -544,23 +561,24 @@ static int sohci_submit_urb (urb_t * urb) ...@@ -544,23 +561,24 @@ static int sohci_submit_urb (urb_t * urb)
bustime = usb_check_bandwidth (urb->dev, urb); bustime = usb_check_bandwidth (urb->dev, urb);
} }
if (bustime < 0) { if (bustime < 0) {
urb_rm_priv (urb); urb_free_priv (urb_priv);
usb_dec_dev_use (urb->dev); usb_dec_dev_use (urb->dev);
spin_unlock_irqrestore (&usb_ed_lock, flags);
return bustime; return bustime;
} }
usb_claim_bandwidth (urb->dev, urb, bustime, usb_pipeisoc (urb->pipe)); 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; urb->actual_length = 0;
urb->hcpriv = urb_priv;
if (ed->state != ED_OPER) /* link the ed into a chain if is not already */ 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); 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); spin_unlock_irqrestore (&usb_ed_lock, flags);
return 0; return 0;
...@@ -570,7 +588,7 @@ static int sohci_submit_urb (urb_t * urb) ...@@ -570,7 +588,7 @@ static int sohci_submit_urb (urb_t * urb)
/* deactivate all TDs and remove the private part of the URB */ /* deactivate all TDs and remove the private part of the URB */
/* interrupt callers must use async unlink mode */ /* interrupt callers must use async unlink mode */
static int sohci_unlink_urb (urb_t * urb) static int sohci_unlink_urb (urb_t * urb)
{ {
unsigned long flags; unsigned long flags;
...@@ -587,16 +605,14 @@ static int sohci_unlink_urb (urb_t * urb) ...@@ -587,16 +605,14 @@ static int sohci_unlink_urb (urb_t * urb)
#ifdef DEBUG #ifdef DEBUG
urb_print (urb, "UNLINK", 1); urb_print (urb, "UNLINK", 1);
#endif #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) { /* handle a request to the virtual root hub */
/* URB active? */ if (usb_pipedevice (urb->pipe) == ohci->rh.devnum)
if (urb->status == USB_ST_URB_PENDING && !ohci->disabled) { return rh_unlink_urb (urb);
urb_priv_t * urb_priv = urb->hcpriv;
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 /* interrupt code may not sleep; it must use
* async status return to unlink pending urbs. * async status return to unlink pending urbs.
...@@ -608,44 +624,50 @@ static int sohci_unlink_urb (urb_t * urb) ...@@ -608,44 +624,50 @@ static int sohci_unlink_urb (urb_t * urb)
return -EWOULDBLOCK; return -EWOULDBLOCK;
} }
/* flag the urb and its TDs for deletion in some /* flag the urb and its TDs for deletion in some
* upcoming SF interrupt delete list processing * upcoming SF interrupt delete list processing
*/ */
urb_priv->state = URB_DEL;
spin_lock_irqsave (&usb_ed_lock, flags); spin_lock_irqsave (&usb_ed_lock, flags);
urb_priv = urb->hcpriv;
if (urb_priv->ed->state == ED_OPER) if (!urb_priv || (urb_priv->state == URB_DEL)) {
ep_unlink(ohci, urb_priv->ed); spin_unlock_irqrestore (&usb_ed_lock, flags);
return 0;
}
urb_priv->state = URB_DEL;
ep_rm_ed (urb->dev, urb_priv->ed); ep_rm_ed (urb->dev, urb_priv->ed);
urb_priv->ed->state |= ED_URB_DEL; urb_priv->ed->state |= ED_URB_DEL;
spin_unlock_irqrestore (&usb_ed_lock, flags);
if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) { if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) {
DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup);
DECLARE_WAITQUEUE (wait, current); 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); add_wait_queue (&unlink_wakeup, &wait);
urb_priv->wait = &unlink_wakeup; urb_priv->wait = &unlink_wakeup;
current->state = TASK_UNINTERRUPTIBLE; spin_unlock_irqrestore (&usb_ed_lock, flags);
schedule ();
/* 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); remove_wait_queue (&unlink_wakeup, &wait);
urb->status = -ENOENT; if (urb->status == USB_ST_URB_PENDING) {
urb_priv->wait = 0; err ("unlink URB timeout");
return -ETIMEDOUT;
}
} else { } else {
/* usb_dec_dev_use done in dl_del_list() */ /* usb_dec_dev_use done in dl_del_list() */
urb->status = -EINPROGRESS; urb->status = -EINPROGRESS;
spin_unlock_irqrestore (&usb_ed_lock, flags);
} }
} else { } else {
urb_rm_priv (urb); urb_rm_priv (urb);
usb_dec_dev_use (urb->dev); if (urb->transfer_flags & USB_ASYNC_UNLINK) {
if (urb->complete && (urb->transfer_flags & USB_ASYNC_UNLINK)) { urb->status = -ECONNRESET;
urb->complete (urb); if (urb->complete)
urb->status = 0; urb->complete (urb);
} else } else
urb->status = -ENOENT; urb->status = -ENOENT;
} }
...@@ -729,14 +751,19 @@ static int sohci_free_dev (struct usb_device * usb_dev) ...@@ -729,14 +751,19 @@ static int sohci_free_dev (struct usb_device * usb_dev)
} else if (!in_interrupt ()) { } else if (!in_interrupt ()) {
DECLARE_WAIT_QUEUE_HEAD (freedev_wakeup); DECLARE_WAIT_QUEUE_HEAD (freedev_wakeup);
DECLARE_WAITQUEUE (wait, current); DECLARE_WAITQUEUE (wait, current);
int timeout = OHCI_UNLINK_TIMEOUT;
/* SF interrupt handler calls dl_del_list */ /* SF interrupt handler calls dl_del_list */
add_wait_queue (&freedev_wakeup, &wait); add_wait_queue (&freedev_wakeup, &wait);
dev->wait = &freedev_wakeup; dev->wait = &freedev_wakeup;
current->state = TASK_UNINTERRUPTIBLE; set_current_state(TASK_UNINTERRUPTIBLE);
schedule (); while (timeout && dev->ed_cnt)
timeout = schedule_timeout (timeout);
remove_wait_queue (&freedev_wakeup, &wait); remove_wait_queue (&freedev_wakeup, &wait);
if (dev->ed_cnt) {
err ("free device %d timeout", usb_dev->devnum);
return -ETIMEDOUT;
}
} else { } else {
/* likely some interface's driver has a refcount bug */ /* likely some interface's driver has a refcount bug */
err ("bus %s devnum %d deletion in interrupt", err ("bus %s devnum %d deletion in interrupt",
...@@ -836,7 +863,7 @@ static int ep_link (ohci_t * ohci, ed_t * edi) ...@@ -836,7 +863,7 @@ static int ep_link (ohci_t * ohci, ed_t * edi)
ed->state = ED_OPER; ed->state = ED_OPER;
switch (ed->type) { switch (ed->type) {
case CTRL: case PIPE_CONTROL:
ed->hwNextED = 0; ed->hwNextED = 0;
if (ohci->ed_controltail == NULL) { if (ohci->ed_controltail == NULL) {
writel (virt_to_bus (ed), &ohci->regs->ed_controlhead); writel (virt_to_bus (ed), &ohci->regs->ed_controlhead);
...@@ -844,10 +871,15 @@ static int ep_link (ohci_t * ohci, ed_t * edi) ...@@ -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)); ohci->ed_controltail->hwNextED = cpu_to_le32 (virt_to_bus (ed));
} }
ed->ed_prev = ohci->ed_controltail; 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; ohci->ed_controltail = edi;
break; break;
case BULK: case PIPE_BULK:
ed->hwNextED = 0; ed->hwNextED = 0;
if (ohci->ed_bulktail == NULL) { if (ohci->ed_bulktail == NULL) {
writel (virt_to_bus (ed), &ohci->regs->ed_bulkhead); writel (virt_to_bus (ed), &ohci->regs->ed_bulkhead);
...@@ -855,10 +887,15 @@ static int ep_link (ohci_t * ohci, ed_t * edi) ...@@ -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)); ohci->ed_bulktail->hwNextED = cpu_to_le32 (virt_to_bus (ed));
} }
ed->ed_prev = ohci->ed_bulktail; 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; ohci->ed_bulktail = edi;
break; break;
case INT: case PIPE_INTERRUPT:
load = ed->int_load; load = ed->int_load;
interval = ep_2_n_interval (ed->int_period); interval = ep_2_n_interval (ed->int_period);
ed->int_interval = interval; ed->int_interval = interval;
...@@ -879,7 +916,7 @@ static int ep_link (ohci_t * ohci, ed_t * edi) ...@@ -879,7 +916,7 @@ static int ep_link (ohci_t * ohci, ed_t * edi)
#endif #endif
break; break;
case ISO: case PIPE_ISOCHRONOUS:
ed->hwNextED = 0; ed->hwNextED = 0;
ed->int_interval = 1; ed->int_interval = 1;
if (ohci->ed_isotail != NULL) { if (ohci->ed_isotail != NULL) {
...@@ -923,21 +960,29 @@ static int ep_unlink (ohci_t * ohci, ed_t * ed) ...@@ -923,21 +960,29 @@ static int ep_unlink (ohci_t * ohci, ed_t * ed)
ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP); ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP);
switch (ed->type) { switch (ed->type) {
case CTRL: case PIPE_CONTROL:
if (ed->ed_prev == NULL) { 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); writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_controlhead);
} else { } else {
ed->ed_prev->hwNextED = ed->hwNextED; ed->ed_prev->hwNextED = ed->hwNextED;
} }
if(ohci->ed_controltail == ed) { if (ohci->ed_controltail == ed) {
ohci->ed_controltail = ed->ed_prev; ohci->ed_controltail = ed->ed_prev;
} else { } else {
((ed_t *) bus_to_virt (le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev; ((ed_t *) bus_to_virt (le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev;
} }
break; break;
case BULK: case PIPE_BULK:
if (ed->ed_prev == NULL) { 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); writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_bulkhead);
} else { } else {
ed->ed_prev->hwNextED = ed->hwNextED; ed->ed_prev->hwNextED = ed->hwNextED;
...@@ -949,7 +994,7 @@ static int ep_unlink (ohci_t * ohci, ed_t * ed) ...@@ -949,7 +994,7 @@ static int ep_unlink (ohci_t * ohci, ed_t * ed)
} }
break; break;
case INT: case PIPE_INTERRUPT:
int_branch = ed->int_branch; int_branch = ed->int_branch;
interval = ed->int_interval; interval = ed->int_interval;
...@@ -971,7 +1016,7 @@ static int ep_unlink (ohci_t * ohci, ed_t * ed) ...@@ -971,7 +1016,7 @@ static int ep_unlink (ohci_t * ohci, ed_t * ed)
#endif #endif
break; break;
case ISO: case PIPE_ISOCHRONOUS:
if (ohci->ed_isotail == ed) if (ohci->ed_isotail == ed)
ohci->ed_isotail = ed->ed_prev; ohci->ed_isotail = ed->ed_prev;
if (ed->hwNextED != 0) if (ed->hwNextED != 0)
...@@ -1054,7 +1099,7 @@ static ed_t * ep_add_ed (struct usb_device * usb_dev, unsigned int pipe, int int ...@@ -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_pipeslow (pipe) << 13
| usb_maxpacket (usb_dev, pipe, usb_pipeout (pipe)) << 16); | 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_period = interval;
ed->int_load = load; ed->int_load = load;
} }
...@@ -1081,13 +1126,13 @@ static void ep_rm_ed (struct usb_device * usb_dev, ed_t * ed) ...@@ -1081,13 +1126,13 @@ static void ep_rm_ed (struct usb_device * usb_dev, ed_t * ed)
if (!ohci->disabled) { if (!ohci->disabled) {
switch (ed->type) { switch (ed->type) {
case CTRL: /* stop CTRL list */ case PIPE_CONTROL: /* stop control list */
writel (ohci->hc_control &= ~OHCI_CTRL_CLE, ohci->hc_control &= ~OHCI_CTRL_CLE;
&ohci->regs->control); writel (ohci->hc_control, &ohci->regs->control);
break; break;
case BULK: /* stop BULK list */ case PIPE_BULK: /* stop bulk list */
writel (ohci->hc_control &= ~OHCI_CTRL_BLE, ohci->hc_control &= ~OHCI_CTRL_BLE;
&ohci->regs->control); writel (ohci->hc_control, &ohci->regs->control);
break; break;
} }
} }
...@@ -1128,7 +1173,7 @@ static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int i ...@@ -1128,7 +1173,7 @@ static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int i
td->index = index; td->index = index;
td->urb = urb; td->urb = urb;
td->hwINFO = cpu_to_le32 (info); 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) td->hwCBP = cpu_to_le32 (((!data || !len)
? 0 ? 0
: virt_to_bus (data)) & 0xFFFFF000); : virt_to_bus (data)) & 0xFFFFF000);
...@@ -1269,6 +1314,27 @@ static void dl_transfer_length(td_t * td) ...@@ -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 /* 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) ...@@ -1330,6 +1396,7 @@ static void dl_del_list (ohci_t * ohci, unsigned int frame)
int ctrl = 0, bulk = 0; int ctrl = 0, bulk = 0;
spin_lock_irqsave (&usb_ed_lock, flags); spin_lock_irqsave (&usb_ed_lock, flags);
for (ed = ohci->ed_rm_list[frame]; ed != NULL; ed = ed->ed_rm_list) { for (ed = ohci->ed_rm_list[frame]; ed != NULL; ed = ed->ed_rm_list) {
tdTailP = bus_to_virt (le32_to_cpup (&ed->hwTailP) & 0xfffffff0); 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) ...@@ -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); td_next = bus_to_virt (le32_to_cpup (&td->hwNextTD) & 0xfffffff0);
if ((urb_priv->state == URB_DEL) || (ed->state & ED_DEL)) { if ((urb_priv->state == URB_DEL) || (ed->state & ED_DEL)) {
tdINFO = le32_to_cpup (&td->hwINFO); 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)); *td_p = td->hwNextTD | (*td_p & cpu_to_le32 (0x3));
/* URB is done; clean up */ /* URB is done; clean up */
if (++(urb_priv->td_cnt) == urb_priv->length) { if (++(urb_priv->td_cnt) == urb_priv->length)
void *condition = urb_priv->wait; dl_del_urb (urb);
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);
}
}
} else { } else {
td_p = &td->hwNextTD; td_p = &td->hwNextTD;
} }
...@@ -1371,31 +1429,54 @@ static void dl_del_list (ohci_t * ohci, unsigned int frame) ...@@ -1371,31 +1429,54 @@ static void dl_del_list (ohci_t * ohci, unsigned int frame)
ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP);
ed->state = ED_NEW; ed->state = ED_NEW;
/* if all eds are removed wake up sohci_free_dev */ /* if all eds are removed wake up sohci_free_dev */
if (!--dev->ed_cnt && dev->wait) if (!--dev->ed_cnt) {
wake_up (dev->wait); wait_queue_head_t *wait_head = dev->wait;
}
else { dev->wait = 0;
if (wait_head)
wake_up (wait_head);
}
} else {
ed->state &= ~ED_URB_DEL; 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; switch (ed->type) {
if ((ed->type & 3) == BULK) bulk |= 1; 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 (!ohci->disabled) {
if (ctrl) /* reset CTRL list */ if (ctrl) /* reset control list */
writel (0, &ohci->regs->ed_controlcurrent); writel (0, &ohci->regs->ed_controlcurrent);
if (bulk) /* reset BULK list */ if (bulk) /* reset bulk list */
writel (0, &ohci->regs->ed_bulkcurrent); writel (0, &ohci->regs->ed_bulkcurrent);
if (!ohci->ed_rm_list[!frame]) { 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); 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); spin_unlock_irqrestore (&usb_ed_lock, flags);
} }
...@@ -1439,14 +1520,15 @@ static void dl_done_list (ohci_t * ohci, td_t * td_list) ...@@ -1439,14 +1520,15 @@ static void dl_done_list (ohci_t * ohci, td_t * td_list)
cc = TD_CC_NOERROR; cc = TD_CC_NOERROR;
if (++(urb_priv->td_cnt) == urb_priv->length) { if (++(urb_priv->td_cnt) == urb_priv->length) {
if (urb_priv->state != URB_DEL if ((ed->state & (ED_OPER | ED_UNLINK))
&& !(ed->state & ED_DEL) && (urb_priv->state != URB_DEL)) {
&& ed->state != ED_NEW) {
urb->status = cc_to_error[cc]; urb->status = cc_to_error[cc];
sohci_return_urb (urb); sohci_return_urb (urb);
} else { } 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); spin_lock_irqsave (&usb_ed_lock, flags);
...@@ -1600,7 +1682,8 @@ static void rh_int_timer_do (unsigned long ptr) ...@@ -1600,7 +1682,8 @@ static void rh_int_timer_do (unsigned long ptr)
#ifdef DEBUG #ifdef DEBUG
urb_print (urb, "RET-t(rh)", usb_pipeout (urb->pipe)); urb_print (urb, "RET-t(rh)", usb_pipeout (urb->pipe));
#endif #endif
if (urb->complete) urb->complete (urb); if (urb->complete)
urb->complete (urb);
} }
} }
out: out:
...@@ -1656,7 +1739,6 @@ static int rh_submit_urb (urb_t * urb) ...@@ -1656,7 +1739,6 @@ static int rh_submit_urb (urb_t * urb)
__u16 wLength; __u16 wLength;
if (usb_pipeint(pipe)) { if (usb_pipeint(pipe)) {
ohci->rh.urb = urb; ohci->rh.urb = urb;
ohci->rh.send = 1; ohci->rh.send = 1;
ohci->rh.interval = urb->interval; ohci->rh.interval = urb->interval;
...@@ -1827,9 +1909,11 @@ static int rh_submit_urb (urb_t * urb) ...@@ -1827,9 +1909,11 @@ static int rh_submit_urb (urb_t * urb)
urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe)); urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe));
#endif #endif
urb->hcpriv = NULL;
usb_dec_dev_use (usb_dev);
urb->dev = NULL;
if (urb->complete) if (urb->complete)
urb->complete (urb); urb->complete (urb);
usb_dec_dev_use (urb->dev);
return 0; return 0;
} }
...@@ -1842,6 +1926,17 @@ static int rh_unlink_urb (urb_t * urb) ...@@ -1842,6 +1926,17 @@ static int rh_unlink_urb (urb_t * urb)
if (ohci->rh.urb == urb) { if (ohci->rh.urb == urb) {
ohci->rh.send = 0; ohci->rh.send = 0;
del_timer (&ohci->rh.rh_int_timer); 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; return 0;
} }
...@@ -2352,6 +2447,12 @@ ohci_pci_resume (struct pci_dev *dev) ...@@ -2352,6 +2447,12 @@ ohci_pci_resume (struct pci_dev *dev)
ohci->disabled = 0; ohci->disabled = 0;
ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; 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); writel (ohci->hc_control, &ohci->regs->control);
#ifdef CONFIG_PMAC_PBOOK #ifdef CONFIG_PMAC_PBOOK
enable_irq (ohci->irq); enable_irq (ohci->irq);
...@@ -2448,7 +2549,6 @@ static int __init ohci_hcd_init (void) ...@@ -2448,7 +2549,6 @@ static int __init ohci_hcd_init (void)
return ret; return ret;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static void __exit ohci_hcd_cleanup (void) static void __exit ohci_hcd_cleanup (void)
...@@ -2463,6 +2563,5 @@ module_init (ohci_hcd_init); ...@@ -2463,6 +2563,5 @@ module_init (ohci_hcd_init);
module_exit (ohci_hcd_cleanup); module_exit (ohci_hcd_cleanup);
MODULE_AUTHOR ("Roman Weissgaerber <weissg@vienna.at>, David Brownell"); MODULE_AUTHOR ("Roman Weissgaerber <weissg@vienna.at>, David Brownell");
MODULE_DESCRIPTION ("USB OHCI Host Controller Driver"); MODULE_DESCRIPTION ("USB OHCI Host Controller Driver");
...@@ -107,7 +107,7 @@ typedef struct td { ...@@ -107,7 +107,7 @@ typedef struct td {
__u32 hwBE; /* Memory Buffer End Pointer */ __u32 hwBE; /* Memory Buffer End Pointer */
__u16 hwPSW[MAXPSW]; __u16 hwPSW[MAXPSW];
__u8 type; __u8 unused;
__u8 index; __u8 index;
struct ed * ed; struct ed * ed;
struct td * next_dl_td; struct td * next_dl_td;
...@@ -115,18 +115,6 @@ typedef struct td { ...@@ -115,18 +115,6 @@ typedef struct td {
} td_t; } 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) #define OHCI_ED_SKIP (1 << 14)
/* /*
...@@ -347,7 +335,7 @@ typedef struct ...@@ -347,7 +335,7 @@ typedef struct
__u16 length; // number of tds associated with this request __u16 length; // number of tds associated with this request
__u16 td_cnt; // number of tds already serviced __u16 td_cnt; // number of tds already serviced
int state; int state;
void * wait; wait_queue_head_t * wait;
td_t * td[0]; // list pointer to all corresponding TDs associated with this request td_t * td[0]; // list pointer to all corresponding TDs associated with this request
} urb_priv_t; } urb_priv_t;
...@@ -398,7 +386,7 @@ typedef struct ohci { ...@@ -398,7 +386,7 @@ typedef struct ohci {
struct ohci_device { struct ohci_device {
ed_t ed[NUM_EDS]; ed_t ed[NUM_EDS];
int ed_cnt; int ed_cnt;
void * wait; wait_queue_head_t * wait;
}; };
// #define ohci_to_usb(ohci) ((ohci)->usb) // #define ohci_to_usb(ohci) ((ohci)->usb)
......
...@@ -1057,6 +1057,7 @@ _static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb) ...@@ -1057,6 +1057,7 @@ _static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb)
uhci_desc_t *qh; uhci_desc_t *qh;
urb_priv_t *urb_priv; urb_priv_t *urb_priv;
unsigned long flags=0; unsigned long flags=0;
struct usb_device *usb_dev;
spin_lock_irqsave (&s->urb_list_lock, flags); spin_lock_irqsave (&s->urb_list_lock, flags);
...@@ -1103,11 +1104,13 @@ _static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb) ...@@ -1103,11 +1104,13 @@ _static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb)
#else #else
kfree (urb->hcpriv); kfree (urb->hcpriv);
#endif #endif
usb_dev = urb->dev;
if (urb->complete) { if (urb->complete) {
dbg("unlink_urb: calling completion"); dbg("unlink_urb: calling completion");
urb->dev = NULL;
urb->complete ((struct urb *) urb); urb->complete ((struct urb *) urb);
} }
usb_dec_dev_use (urb->dev); usb_dec_dev_use (usb_dev);
} }
else { else {
if (!in_interrupt()) if (!in_interrupt())
...@@ -1171,6 +1174,7 @@ _static void uhci_cleanup_unlink(uhci_t *s, int force) ...@@ -1171,6 +1174,7 @@ _static void uhci_cleanup_unlink(uhci_t *s, int force)
if (urb->complete) { if (urb->complete) {
spin_unlock(&s->urb_list_lock); spin_unlock(&s->urb_list_lock);
urb->dev = NULL;
urb->complete ((struct urb *) urb); urb->complete ((struct urb *) urb);
spin_lock(&s->urb_list_lock); spin_lock(&s->urb_list_lock);
} }
...@@ -2082,6 +2086,7 @@ _static int rh_submit_urb (urb_t *urb) ...@@ -2082,6 +2086,7 @@ _static int rh_submit_urb (urb_t *urb)
urb->actual_length = len; urb->actual_length = len;
urb->status = stat; urb->status = stat;
urb->dev=NULL;
if (urb->complete) if (urb->complete)
urb->complete (urb); urb->complete (urb);
return 0; return 0;
...@@ -2484,7 +2489,6 @@ _static int process_urb (uhci_t *s, struct list_head *p) ...@@ -2484,7 +2489,6 @@ _static int process_urb (uhci_t *s, struct list_head *p)
int ret = 0; int ret = 0;
urb_t *urb; urb_t *urb;
urb=list_entry (p, urb_t, urb_list); urb=list_entry (p, urb_t, urb_list);
//dbg("process_urb: found queued urb: %p", urb); //dbg("process_urb: found queued urb: %p", urb);
...@@ -2508,6 +2512,9 @@ _static int process_urb (uhci_t *s, struct list_head *p) ...@@ -2508,6 +2512,9 @@ _static int process_urb (uhci_t *s, struct list_head *p)
if (urb->status != -EINPROGRESS) { if (urb->status != -EINPROGRESS) {
int proceed = 0; int proceed = 0;
struct usb_device *usb_dev;
usb_dev=urb->dev;
/* Release bandwidth for Interrupt or Iso transfers */ /* Release bandwidth for Interrupt or Iso transfers */
if (urb->bandwidth) { if (urb->bandwidth) {
...@@ -2549,9 +2556,12 @@ _static int process_urb (uhci_t *s, struct list_head *p) ...@@ -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) // In case you need the current URB status for your completion handler (before resubmit)
if (urb->complete && (!proceed )) { if (urb->complete && (!proceed )) {
dbg("process_transfer: calling early completion"); dbg("process_transfer: calling early completion");
urb->dev = NULL;
urb->complete ((struct urb *) urb); 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); uhci_submit_urb (urb);
}
} }
if (proceed && urb->next) { if (proceed && urb->next) {
...@@ -2567,11 +2577,13 @@ _static int process_urb (uhci_t *s, struct list_head *p) ...@@ -2567,11 +2577,13 @@ _static int process_urb (uhci_t *s, struct list_head *p)
if (urb->complete) { if (urb->complete) {
dbg("process_transfer: calling completion"); dbg("process_transfer: calling completion");
urb->dev=NULL;
urb->complete ((struct urb *) urb); 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_unlock(&urb->lock);
spin_lock(&s->urb_list_lock); spin_lock(&s->urb_list_lock);
} }
......
...@@ -35,6 +35,11 @@ ...@@ -35,6 +35,11 @@
#endif #endif
#include <linux/usb.h> #include <linux/usb.h>
#define DEVNUM_ROUND_ROBIN /***** OPTION *****/
#ifdef DEVNUM_ROUND_ROBIN
static int devnum_next = 1;
#endif
static const int usb_bandwidth_option = static const int usb_bandwidth_option =
#ifdef CONFIG_USB_BANDWIDTH #ifdef CONFIG_USB_BANDWIDTH
1; 1;
...@@ -1470,7 +1475,19 @@ void usb_connect(struct usb_device *dev) ...@@ -1470,7 +1475,19 @@ void usb_connect(struct usb_device *dev)
* which hopefully doesn't run on multiple CPU's simultaneously 8-) * which hopefully doesn't run on multiple CPU's simultaneously 8-)
*/ */
dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */ dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */
#ifndef DEVNUM_ROUND_ROBIN
devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1); 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) { if (devnum < 128) {
set_bit(devnum, dev->bus->devmap.devicemap); set_bit(devnum, dev->bus->devmap.devicemap);
dev->devnum = devnum; dev->devnum = devnum;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define _ALPHA_BITOPS_H #define _ALPHA_BITOPS_H
#include <linux/config.h> #include <linux/config.h>
#include <linux/kernel.h>
/* /*
* Copyright 1994, Linus Torvalds. * Copyright 1994, Linus Torvalds.
......
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
* *
*/ */
#include <linux/config.h>
typedef struct { volatile int counter; } atomic_t; typedef struct { volatile int counter; } atomic_t;
#define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) #define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
......
...@@ -8,19 +8,12 @@ ...@@ -8,19 +8,12 @@
#include <linux/config.h> #include <linux/config.h>
#ifdef CONFIG_SMP
/* This is a temporary measure. -DaveM */
typedef struct { volatile int counter; } atomic_t; 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__ #ifdef __KERNEL__
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
#define ATOMIC_INIT(i) { (i) }
#define atomic_read(v) ((v)->counter) #define atomic_read(v) ((v)->counter)
#define atomic_set(v, i) (((v)->counter) = i) #define atomic_set(v, i) (((v)->counter) = i)
...@@ -39,6 +32,8 @@ typedef struct { int counter; } atomic_t; ...@@ -39,6 +32,8 @@ typedef struct { int counter; } atomic_t;
* 31 8 7 0 * 31 8 7 0
*/ */
#define ATOMIC_INIT(i) { (i << 8) }
static __inline__ int atomic_read(atomic_t *v) static __inline__ int atomic_read(atomic_t *v)
{ {
int ret = v->counter; int ret = v->counter;
......
/* $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. * bitops.h: Bit string operations on the Sparc.
* *
* Copyright 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
...@@ -156,6 +156,9 @@ extern __inline__ void change_bit(unsigned long nr, volatile void *addr) ...@@ -156,6 +156,9 @@ extern __inline__ void change_bit(unsigned long nr, volatile void *addr)
#endif /* __KERNEL__ */ #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. */ /* The following routine need not be atomic. */
extern __inline__ int test_bit(int nr, __const__ void *addr) extern __inline__ int test_bit(int nr, __const__ void *addr)
{ {
......
/* $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 <linux/config.h> #include <linux/config.h>
#ifndef __SPARC_SYSTEM_H #ifndef __SPARC_SYSTEM_H
...@@ -280,6 +280,9 @@ extern void __global_restore_flags(unsigned long flags); ...@@ -280,6 +280,9 @@ extern void __global_restore_flags(unsigned long flags);
#define wmb() mb() #define wmb() mb()
#define set_mb(__var, __value) do { __var = __value; mb(); } while(0) #define set_mb(__var, __value) do { __var = __value; mb(); } while(0)
#define set_wmb(__var, __value) set_mb(__var, __value) #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"); #define nop() __asm__ __volatile__ ("nop");
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#ifndef __ARCH_SPARC64_ATOMIC__ #ifndef __ARCH_SPARC64_ATOMIC__
#define __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_INIT(i) { (i) }
#define atomic_read(v) ((v)->counter) #define atomic_read(v) ((v)->counter)
......
/* $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. * bitops.h: Bit string operations on the V9.
* *
* Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu) * 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); ...@@ -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 clear_bit(nr,addr) ((void)__test_and_clear_bit(nr,addr))
#define change_bit(nr,addr) ((void)__test_and_change_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) extern __inline__ int test_bit(int nr, __const__ void *addr)
{ {
return (1UL & (((__const__ long *) addr)[nr >> 6] >> (nr & 63))) != 0UL; return (1UL & (((__const__ long *) addr)[nr >> 6] >> (nr & 63))) != 0UL;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/threads.h> #include <linux/threads.h>
#include <asm/asi.h> #include <asm/asi.h>
#include <asm/starfire.h>
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
/* PROM provided per-processor information we need /* PROM provided per-processor information we need
...@@ -82,11 +83,7 @@ extern __inline__ int cpu_number_map(int cpu) ...@@ -82,11 +83,7 @@ extern __inline__ int cpu_number_map(int cpu)
extern __inline__ int hard_smp_processor_id(void) extern __inline__ int hard_smp_processor_id(void)
{ {
extern int this_is_starfire;
if(this_is_starfire != 0) { if(this_is_starfire != 0) {
extern int starfire_hard_smp_processor_id(void);
return starfire_hard_smp_processor_id(); return starfire_hard_smp_processor_id();
} else { } else {
unsigned long upaconfig; unsigned long upaconfig;
......
/* $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
/* $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 #ifndef __SPARC64_SYSTEM_H
#define __SPARC64_SYSTEM_H #define __SPARC64_SYSTEM_H
...@@ -95,11 +95,11 @@ extern void __global_restore_flags(unsigned long flags); ...@@ -95,11 +95,11 @@ extern void __global_restore_flags(unsigned long flags);
#endif #endif
#define mb() __asm__ __volatile__ ("stbar" : : : "memory")
#define nop() __asm__ __volatile__ ("nop") #define nop() __asm__ __volatile__ ("nop")
#define membar(type) __asm__ __volatile__ ("membar " type : : : "memory"); #define membar(type) __asm__ __volatile__ ("membar " type : : : "memory");
#define mb() \
membar("#LoadLoad | #LoadStore | #StoreStore | #StoreLoad");
#define rmb() membar("#LoadLoad") #define rmb() membar("#LoadLoad")
#define wmb() membar("#StoreStore") #define wmb() membar("#StoreStore")
#define set_mb(__var, __value) \ #define set_mb(__var, __value) \
...@@ -107,6 +107,16 @@ extern void __global_restore_flags(unsigned long flags); ...@@ -107,6 +107,16 @@ extern void __global_restore_flags(unsigned long flags);
#define set_wmb(__var, __value) \ #define set_wmb(__var, __value) \
do { __var = __value; membar("#StoreStore"); } while(0) 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 flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory")
#define flushw_all() __asm__ __volatile__("flushw") #define flushw_all() __asm__ __volatile__("flushw")
......
...@@ -147,6 +147,10 @@ ...@@ -147,6 +147,10 @@
#define UNIX98_PTY_MAJOR_COUNT 8 #define UNIX98_PTY_MAJOR_COUNT 8
#define UNIX98_PTY_SLAVE_MAJOR (UNIX98_PTY_MASTER_MAJOR+UNIX98_PTY_MAJOR_COUNT) #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 MSR_MAJOR 202
#define CPUID_MAJOR 203 #define CPUID_MAJOR 203
......
...@@ -1066,16 +1066,13 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -1066,16 +1066,13 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length)
{ {
char tbuf[16]; char tbuf[16];
sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->primary_key)); 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, tbuf,
hatype, hatype,
arp_state_to_flags(n), arp_state_to_flags(n),
hbuffer); hbuffer,
dev->name);
size += sprintf(buffer+len+size,
" %-8s %s\n",
"*", dev->name);
} }
read_unlock(&n->lock); read_unlock(&n->lock);
...@@ -1102,15 +1099,14 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -1102,15 +1099,14 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length)
{ {
char tbuf[16]; char tbuf[16];
sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->key)); 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, tbuf,
hatype, hatype,
ATF_PUBL|ATF_PERM, 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; len += size;
pos += size; pos += size;
......
ksymoops has been removed from the kernel. It was always meant to be a ksymoops has been removed from the kernel. It was always meant to be a
free standing utility, not linked to any particular kernel version. free standing utility, not linked to any particular kernel version.
The latest version can be found in ftp://ftp.ocs.com.au/pub/ksymoops, The latest version can be found in
together with patches to other utilities in order to give more accurate ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops together
Oops debugging. with patches to other utilities in order to give more accurate Oops
debugging.
Keith Owens <kaos@ocs.com.au> Sat Jun 19 10:30:34 EST 1999 Keith Owens <kaos@ocs.com.au> Sat Jun 19 10:30:34 EST 1999
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