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.
ksymoops < the_oops.txt
// 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
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?
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
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.<country>.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
-/* $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
#ifndef CONFIG_PCI
-int pcibios_present(void)
-{
- return 0;
-}
-
asmlinkage int sys_pciconfig_read(unsigned long bus,
unsigned long dfn,
unsigned long off,
if(!suser())
return -EPERM;
- lock_kernel();
switch(len) {
case 1:
err = get_user(ubyte, (unsigned char *)buf);
break;
};
- unlock_kernel();
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
for Sparc64 tftpbooting without need to set up nfs.
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);
#include <asm/sbus.h>
#include <asm/ebus.h>
#include <asm/fhc.h>
+#include <asm/starfire.h>
/* Probe and map in the Auxiliary I/O register */
unsigned long auxio_register = 0;
return;
}
#endif
- if(central_bus) {
+ if(central_bus || this_is_starfire) {
auxio_register = 0UL;
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.
*
* Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com)
#include <asm/page.h>
#include <asm/fhc.h>
+#include <asm/starfire.h>
struct linux_central *central_bus = NULL;
struct linux_fhc *fhc_list = NULL;
cnode = prom_finddevice("/central");
if(cnode == 0 || cnode == -1) {
- extern void starfire_check(void);
-
- starfire_check();
+ if (this_is_starfire)
+ starfire_cpu_setup();
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.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
#include <asm/smp.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
+#include <asm/starfire.h>
/* Internal flag, should not be visible elsewhere at all. */
#define SA_IMAP_MASKED 0x100
/* 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;
: "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);
}
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);
#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;
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);
#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)
goto out;
}
- lock_kernel();
switch(len) {
case 1:
err = get_user(byte, (u8 *)buf);
break;
};
- unlock_kernel();
out:
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.
*
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
#include <asm/pbm.h>
#include <asm/iommu.h>
#include <asm/irq.h>
+#include <asm/starfire.h>
#include "pci_impl.h"
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;
-/* $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)
#include <asm/cache.h>
#include <asm/dma.h>
#include <asm/irq.h>
+#include <asm/starfire.h>
#include "iommu_common.h"
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);
}
-/* $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)
#include <asm/pgtable.h>
#include <asm/idprom.h>
#include <asm/head.h>
+#include <asm/starfire.h>
#ifdef CONFIG_IP_PNP
#include <net/ipconfig.h>
conswitchp = &prom_con;
#endif
+ /* Work out if we are starfire early on */
+ check_if_starfire();
+
boot_flags_init(*cmdline_p);
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.
*
* Copyright (C) 1998 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com)
*/
#include <linux/kernel.h>
#include <asm/oplib.h>
#include <asm/smp.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
* 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++) {
linux_cpus[i].mid = mid;
}
+#endif
}
}
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.
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;
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;
-/* $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)
#include <asm/fhc.h>
#include <asm/pbm.h>
#include <asm/ebus.h>
+#include <asm/starfire.h>
extern rwlock_t xtime_lock;
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) {
void do_settimeofday(struct timeval *tv)
{
+ if (this_is_starfire)
+ return;
+
write_lock_irq(&xtime_lock);
tv->tv_usec -= do_gettimeoffset();
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;
-/* $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)
#include <asm/mmu_context.h>
#include <asm/vaddrs.h>
#include <asm/dma.h>
+#include <asm/starfire.h>
extern void device_scan(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;
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 +
*/
{
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);
*/
#include <linux/config.h>
#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 */
/*
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
static int sg_proc_init(void);
-#ifdef MODULE
static void sg_proc_cleanup(void);
#endif
-#endif
#ifndef LINUX_VERSION_CODE
#include <linux/version.h>
* 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));
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,
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);
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)))
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) ||
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? */
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)
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;
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);
}
return 0;
}
-#ifdef MODULE
static void sg_proc_cleanup()
{
int k;
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)
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;
*
* 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
/* 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;
*-------------------------------------------------------------------------*/
/* 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);
}
/*-------------------------------------------------------------------------*/
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
} else { /* unlink URB, call complete */
urb_rm_priv (urb);
- usb_dec_dev_use (urb->dev);
urb->complete (urb);
}
break;
case PIPE_BULK:
case PIPE_CONTROL: /* unlink URB, call complete */
urb_rm_priv (urb);
- usb_dec_dev_use (urb->dev);
urb->complete (urb);
break;
}
int bustime = 0;
if (!urb->dev || !urb->dev->bus)
- return -EINVAL;
+ return -ENODEV;
if (urb->hcpriv) /* urb already in use */
return -EINVAL;
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);
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;
}
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;
/* 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;
#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.
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;
}
} 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",
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);
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);
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;
#endif
break;
- case ISO:
+ case PIPE_ISOCHRONOUS:
ed->hwNextED = 0;
ed->int_interval = 1;
if (ohci->ed_isotail != NULL) {
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;
}
break;
- case INT:
+ case PIPE_INTERRUPT:
int_branch = ed->int_branch;
interval = ed->int_interval;
#endif
break;
- case ISO:
+ case PIPE_ISOCHRONOUS:
if (ohci->ed_isotail == ed)
ohci->ed_isotail = ed->ed_prev;
if (ed->hwNextED != 0)
| 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;
}
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;
}
}
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);
}
}
+/* 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
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);
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;
}
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);
}
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);
#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:
__u16 wLength;
if (usb_pipeint(pipe)) {
-
ohci->rh.urb = urb;
ohci->rh.send = 1;
ohci->rh.interval = urb->interval;
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;
}
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;
}
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);
return ret;
}
-
/*-------------------------------------------------------------------------*/
static void __exit ohci_hcd_cleanup (void)
module_exit (ohci_hcd_cleanup);
-
MODULE_AUTHOR ("Roman Weissgaerber <weissg@vienna.at>, David Brownell");
MODULE_DESCRIPTION ("USB OHCI Host Controller Driver");
__u32 hwBE; /* Memory Buffer End Pointer */
__u16 hwPSW[MAXPSW];
- __u8 type;
+ __u8 unused;
__u8 index;
struct ed * ed;
struct td * next_dl_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)
/*
__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;
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)
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);
#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())
if (urb->complete) {
spin_unlock(&s->urb_list_lock);
+ urb->dev = NULL;
urb->complete ((struct urb *) urb);
spin_lock(&s->urb_list_lock);
}
urb->actual_length = len;
urb->status = stat;
+ urb->dev=NULL;
if (urb->complete)
urb->complete (urb);
return 0;
int ret = 0;
urb_t *urb;
-
urb=list_entry (p, urb_t, urb_list);
//dbg("process_urb: found queued urb: %p", urb);
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) {
// 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) {
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);
}
#endif
#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 =
#ifdef CONFIG_USB_BANDWIDTH
1;
* 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;
#define _ALPHA_BITOPS_H
#include <linux/config.h>
+#include <linux/kernel.h>
/*
* Copyright 1994, Linus Torvalds.
*
*/
-#include <linux/config.h>
-
typedef struct { volatile int counter; } atomic_t;
#define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
#include <linux/config.h>
-#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)
* 31 8 7 0
*/
+#define ATOMIC_INIT(i) { (i << 8) }
+
static __inline__ int atomic_read(atomic_t *v)
{
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.
*
* Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
#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)
{
-/* $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>
#ifndef __SPARC_SYSTEM_H
#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");
#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)
-/* $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)
#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;
#include <linux/config.h>
#include <linux/threads.h>
#include <asm/asi.h>
+#include <asm/starfire.h>
#ifndef __ASSEMBLY__
/* PROM provided per-processor information we need
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;
--- /dev/null
+/* $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
#define __SPARC64_SYSTEM_H
#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) \
#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")
#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
{
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);
{
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;
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.<country>.kernel.org/pub/linux/utils/kernel/ksymoops together
+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