summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 20:20:19 -0800
committerLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 20:20:19 -0800
commit0a97b16afbcaadbe4410d78adfe8967398454945 (patch)
treea840d4dfa366d426d9063041a6d663386e4c71ac
parent5bf3be033f504f5fd79690fbb13d720407314e40 (diff)
v2.4.10.2 -> v2.4.10.3
- Al Viro: superblock cleanups, partition handling fixes and cleanups - Ben Collins: firewire update - Jeff Garzik: network driver updates - Urban Widmark: smbfs updates - Kai Mäkisara: SCSI tape driver update - various: embarrassing lack of error checking in ELF loader - Neil Brown: md formatting cleanup.
-rw-r--r--Makefile2
-rw-r--r--arch/ppc/mm/fault.c40
-rw-r--r--arch/ppc/mm/init.c5
-rw-r--r--arch/ppc/mm/mmu_context.c4
-rw-r--r--arch/ppc/mm/pgtable.c6
-rw-r--r--drivers/char/sysrq.c4
-rw-r--r--drivers/ide/ide-pmac.c316
-rw-r--r--drivers/ieee1394/highlevel.c27
-rw-r--r--drivers/ieee1394/hosts.c128
-rw-r--r--drivers/ieee1394/hosts.h7
-rw-r--r--drivers/ieee1394/ieee1394_core.c53
-rw-r--r--drivers/ieee1394/ieee1394_core.h6
-rw-r--r--drivers/ieee1394/ieee1394_hotplug.h81
-rw-r--r--drivers/ieee1394/ieee1394_syms.c5
-rw-r--r--drivers/ieee1394/ieee1394_transactions.c8
-rw-r--r--drivers/ieee1394/ieee1394_types.h7
-rw-r--r--drivers/ieee1394/nodemgr.c588
-rw-r--r--drivers/ieee1394/nodemgr.h39
-rw-r--r--drivers/ieee1394/ohci1394.c325
-rw-r--r--drivers/ieee1394/ohci1394.h23
-rw-r--r--drivers/ieee1394/pcilynx.c26
-rw-r--r--drivers/ieee1394/raw1394.c17
-rw-r--r--drivers/ieee1394/sbp2.c1611
-rw-r--r--drivers/ieee1394/sbp2.h77
-rw-r--r--drivers/ieee1394/video1394.c36
-rw-r--r--drivers/md/md.c561
-rw-r--r--drivers/net/8139too.c93
-rw-r--r--drivers/net/natsemi.c362
-rw-r--r--drivers/net/tulip/eeprom.c4
-rw-r--r--drivers/net/tulip/interrupt.c8
-rw-r--r--drivers/net/tulip/tulip_core.c4
-rw-r--r--drivers/net/wireless/airo.c51
-rw-r--r--drivers/net/wireless/hermes.c63
-rw-r--r--drivers/net/wireless/hermes.h32
-rw-r--r--drivers/net/wireless/orinoco.c148
-rw-r--r--drivers/net/wireless/orinoco.h7
-rw-r--r--drivers/net/wireless/orinoco_cs.c6
-rw-r--r--drivers/pci/pci.ids332
-rw-r--r--drivers/scsi/st.c9
-rw-r--r--drivers/video/clgenfb.c3
-rw-r--r--drivers/video/controlfb.c7
-rw-r--r--drivers/video/offb.c10
-rw-r--r--fs/binfmt_elf.c8
-rw-r--r--fs/block_dev.c71
-rw-r--r--fs/lockd/svc.c26
-rw-r--r--fs/nfsd/export.c6
-rw-r--r--fs/nfsd/nfs3xdr.c2
-rw-r--r--fs/nfsd/nfsfh.c4
-rw-r--r--fs/nfsd/nfsxdr.c2
-rw-r--r--fs/nfsd/vfs.c2
-rw-r--r--fs/partitions/acorn.c217
-rw-r--r--fs/partitions/acorn.h2
-rw-r--r--fs/partitions/amiga.c138
-rw-r--r--fs/partitions/amiga.h2
-rw-r--r--fs/partitions/atari.c232
-rw-r--r--fs/partitions/atari.h2
-rw-r--r--fs/partitions/check.c84
-rw-r--r--fs/partitions/check.h12
-rw-r--r--fs/partitions/ibm.c97
-rw-r--r--fs/partitions/ibm.h2
-rw-r--r--fs/partitions/ldm.c206
-rw-r--r--fs/partitions/ldm.h4
-rw-r--r--fs/partitions/mac.c71
-rw-r--r--fs/partitions/mac.h2
-rw-r--r--fs/partitions/msdos.c466
-rw-r--r--fs/partitions/msdos.h2
-rw-r--r--fs/partitions/osf.c21
-rw-r--r--fs/partitions/osf.h4
-rw-r--r--fs/partitions/sgi.c21
-rw-r--r--fs/partitions/sgi.h2
-rw-r--r--fs/partitions/sun.c26
-rw-r--r--fs/partitions/sun.h2
-rw-r--r--fs/partitions/ultrix.c22
-rw-r--r--fs/partitions/ultrix.h2
-rw-r--r--fs/smbfs/ChangeLog25
-rw-r--r--fs/smbfs/Makefile16
-rw-r--r--fs/smbfs/cache.c1
-rw-r--r--fs/smbfs/dir.c16
-rw-r--r--fs/smbfs/file.c1
-rw-r--r--fs/smbfs/inode.c96
-rw-r--r--fs/smbfs/ioctl.c8
-rw-r--r--fs/smbfs/proc.c267
-rw-r--r--fs/smbfs/proto.h63
-rw-r--r--fs/smbfs/sock.c5
-rw-r--r--fs/super.c390
-rw-r--r--include/asm-ppc/mmu_context.h6
-rw-r--r--include/linux/fs.h1
-rw-r--r--include/linux/gameport.h4
-rw-r--r--include/linux/genhd.h44
-rw-r--r--include/linux/module.h6
-rw-r--r--include/linux/smb_fs.h78
-rw-r--r--include/linux/smbno.h7
-rw-r--r--include/linux/spinlock.h3
-rw-r--r--init/main.c1
-rw-r--r--lib/dec_and_lock.c2
95 files changed, 4121 insertions, 3820 deletions
diff --git a/Makefile b/Makefile
index fa119e79e6fa..9cbd912ff927 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 11
-EXTRAVERSION =-pre2
+EXTRAVERSION =-pre3
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index 657bd0344971..9fee4ad0c33d 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.fault.c 1.13 06/28/01 15:50:17 paulus
+ * BK Id: SCCS/s.fault.c 1.15 09/24/01 16:35:10 paulus
*/
/*
* arch/ppc/mm/fault.c
@@ -150,6 +150,7 @@ good_area:
* make sure we exit gracefully rather than endlessly redo
* the fault.
*/
+ survive:
switch (handle_mm_fault(mm, vma, address, is_write)) {
case 1:
current->min_flt++;
@@ -195,6 +196,12 @@ bad_area:
*/
out_of_memory:
up_read(&mm->mmap_sem);
+ if (current->pid == 1) {
+ current->policy |= SCHED_YIELD;
+ schedule();
+ down_read(&mm->mmap_sem);
+ goto survive;
+ }
printk("VM: killing process %s\n", current->comm);
if (user_mode(regs))
do_exit(SIGKILL);
@@ -346,34 +353,3 @@ get_8xx_pte(struct mm_struct *mm, unsigned long addr)
return(retval);
}
#endif /* CONFIG_8xx */
-
-#if 0
-/*
- * Misc debugging functions. Please leave them here. -- Cort
- */
-void print_pte(struct _PTE p)
-{
- printk(
-"%08x %08x vsid: %06x h: %01x api: %02x rpn: %05x rcwimg: %d%d%d%d%d%d pp: %02x\n",
- *((unsigned long *)(&p)), *((long *)&p+1),
- p.vsid, p.h, p.api, p.rpn,
- p.r,p.c,p.w,p.i,p.m,p.g,p.pp);
-}
-
-/*
- * Search the hw hash table for a mapping to the given physical
- * address. -- Cort
- */
-unsigned long htab_phys_to_va(unsigned long address)
-{
- extern PTE *Hash, *Hash_end;
- PTE *ptr;
-
- for ( ptr = Hash ; ptr < Hash_end ; ptr++ )
- {
- if ( ptr->rpn == (address>>12) )
- printk("phys %08lX -> va ???\n",
- address);
- }
-}
-#endif
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index b31b61a897a4..2c8fb53a871c 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.init.c 1.34 08/20/01 22:12:43 paulus
+ * BK Id: SCCS/s.init.c 1.36 09/22/01 14:03:09 paulus
*/
/*
* PowerPC version
@@ -44,12 +44,15 @@
#include <asm/smp.h>
#include <asm/machdep.h>
#include <asm/btext.h>
+#include <asm/tlb.h>
#include "mem_pieces.h"
#include "mmu_decl.h"
#define MAX_LOW_MEM (0xF0000000UL - KERNELBASE)
+mmu_gather_t mmu_gathers[NR_CPUS];
+
void *end_of_DRAM;
unsigned long total_memory;
unsigned long total_lowmem;
diff --git a/arch/ppc/mm/mmu_context.c b/arch/ppc/mm/mmu_context.c
index cae4b53c7d1a..ba6784ec812e 100644
--- a/arch/ppc/mm/mmu_context.c
+++ b/arch/ppc/mm/mmu_context.c
@@ -36,7 +36,7 @@
#include <asm/mmu_context.h>
mm_context_t next_mmu_context;
-unsigned long context_map[(LAST_CONTEXT+1) / (8*sizeof(unsigned long))];
+unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
#ifdef FEW_CONTEXTS
atomic_t nr_free_contexts;
struct mm_struct *context_mm[LAST_CONTEXT+1];
@@ -57,7 +57,7 @@ void __init mmu_context_init(void)
context_map[0] = (1 << FIRST_CONTEXT) - 1;
next_mmu_context = FIRST_CONTEXT;
#ifdef FEW_CONTEXTS
- atomic_set(&nr_free_contexts, LAST_CONTEXT);
+ atomic_set(&nr_free_contexts, LAST_CONTEXT - FIRST_CONTEXT + 1);
#endif /* FEW_CONTEXTS */
}
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index d3f35ebbe860..d3630a8c1491 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -211,12 +211,12 @@ void __init mapin_ram(void)
#else
if ((char *) v < _stext || (char *) v >= etext)
f |= _PAGE_RW | _PAGE_DIRTY;
-#ifndef CONFIG_8xx
+#ifdef CONFIG_PPC_STD_MMU
else
- /* On the powerpc (not 8xx), no user access
+ /* On the powerpc (not all), no user access
forces R/W kernel access */
f |= _PAGE_USER;
-#endif /* CONFIG_8xx */
+#endif /* CONFIG_PPC_STD_MMU */
#endif /* CONFIG_KGDB */
map_page(v, p, f);
v += PAGE_SIZE;
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index ebca79af8ce3..07e235f166b4 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -231,12 +231,12 @@ static struct sysrq_key_op sysrq_sync_op = {
static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty) {
emergency_sync_scheduled = EMERG_REMOUNT;
- wakeup_bdflush(0);
+ wakeup_bdflush();
}
static struct sysrq_key_op sysrq_mountro_op = {
handler: sysrq_handle_mountro,
help_msg: "Unmount",
- action_msg: "Emergency Remount R/0",
+ action_msg: "Emergency Remount R/O",
};
/* END SYNC SYSRQ HANDLERS BLOCK */
diff --git a/drivers/ide/ide-pmac.c b/drivers/ide/ide-pmac.c
index 590645be879d..af7603af9e84 100644
--- a/drivers/ide/ide-pmac.c
+++ b/drivers/ide/ide-pmac.c
@@ -5,9 +5,7 @@
* These IDE interfaces are memory-mapped and have a DBDMA channel
* for doing DMA.
*
- * Copyright (C) 1998 Paul Mackerras.
- *
- * Bits from Benjamin Herrenschmidt
+ * Copyright (C) 1998-2001 Paul Mackerras & Ben. Herrenschmidt
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -99,13 +97,13 @@ static pmac_ide_timing udma_timings[] =
/* allow up to 256 DBDMA commands per xfer */
#define MAX_DCMDS 256
-/* Wait 1.5s for disk to answer on IDE bus after
+/* Wait 2s for disk to answer on IDE bus after
* enable operation.
* NOTE: There is at least one case I know of a disk that needs about 10sec
* before anwering on the bus. I beleive we could add a kernel command
* line arg to override this delay for such cases.
*/
-#define IDE_WAKEUP_DELAY_MS 1500
+#define IDE_WAKEUP_DELAY_MS 2000
static void pmac_ide_setup_dma(struct device_node *np, int ix);
static int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive);
@@ -236,13 +234,21 @@ wait_for_ready(ide_drive_t *drive)
}
if((stat & ERR_STAT) || timeout <= 0) {
if (stat & ERR_STAT) {
- printk("ide_pmace: wait_for_ready, error status: %x\n", stat);
+ printk(KERN_ERR "ide_pmac: wait_for_ready, error status: %x\n", stat);
}
return 1;
}
return 0;
}
+/* Note: We don't use the generic routine here because some of Apple's
+ * controller seem to be very sensitive about how things are done.
+ * We should probably set the NIEN bit, but that's an example of thing
+ * that can cause the controller to hang under some circumstances when
+ * done on the media-bay CD-ROM during boot. We do get occasional
+ * spurrious interrupts because of that.
+ * --BenH
+ */
static int
pmac_ide_do_setfeature(ide_drive_t *drive, byte command)
{
@@ -256,7 +262,7 @@ pmac_ide_do_setfeature(ide_drive_t *drive, byte command)
SELECT_MASK(HWIF(drive), drive, 0);
udelay(1);
if(wait_for_ready(drive)) {
- printk("pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n");
+ printk(KERN_ERR "pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n");
goto out;
}
OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
@@ -265,7 +271,7 @@ pmac_ide_do_setfeature(ide_drive_t *drive, byte command)
udelay(1);
result = wait_for_ready(drive);
if (result)
- printk("pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n");
+ printk(KERN_ERR "pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n");
out:
restore_flags(flags);
@@ -311,7 +317,7 @@ pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
}
#ifdef IDE_PMAC_DEBUG
- printk("ide_pmac: Set PIO timing for mode %d, reg: 0x%08x\n",
+ printk(KERN_ERR "ide_pmac: Set PIO timing for mode %d, reg: 0x%08x\n",
pio, *timings);
#endif
@@ -562,7 +568,7 @@ pmac_ide_probe(void)
fixes in irq.c
*/
if (np->n_intrs == 0) {
- printk("ide: no intrs for device %s, using 13\n",
+ printk(KERN_WARNING "ide: no intrs for device %s, using 13\n",
np->full_name);
irq = 13;
} else {
@@ -598,7 +604,7 @@ pmac_ide_probe(void)
feature_set(np, FEATURE_IDE0_enable);
} else {
/* This is necessary to enable IDE when net-booting */
- printk("pmac_ide: enabling IDE bus ID %d\n",
+ printk(KERN_INFO "pmac_ide: enabling IDE bus ID %d\n",
pmac_ide[i].aapl_bus_id);
switch(pmac_ide[i].aapl_bus_id) {
case 0:
@@ -732,7 +738,7 @@ pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr)
unsigned int tc = (size < 0xfe00)? size: 0xfe00;
if (++count >= MAX_DCMDS) {
- printk("%s: DMA table too small\n",
+ printk(KERN_WARNING "%s: DMA table too small\n",
drive->name);
return 0; /* revert to PIO for this request */
}
@@ -804,10 +810,10 @@ pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
int ret;
/* Set feature on drive */
- printk("%s: Enabling MultiWord DMA %d\n", drive->name, feature & 0xf);
+ printk(KERN_INFO "%s: Enabling MultiWord DMA %d\n", drive->name, feature & 0xf);
ret = pmac_ide_do_setfeature(drive, feature);
if (ret) {
- printk("%s: Failed !\n", drive->name);
+ printk(KERN_WARNING "%s: Failed !\n", drive->name);
return 0;
}
@@ -860,7 +866,7 @@ pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
(accessTicks | (recTicks << 5) | (halfTick << 10)) << 11;
}
#ifdef IDE_PMAC_DEBUG
- printk("ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
+ printk(KERN_INFO "ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
feature & 0xf, *timings);
#endif
drive->current_speed = feature;
@@ -879,10 +885,10 @@ pmac_ide_udma_enable(ide_drive_t *drive, int idx)
int ret;
/* Set feature on drive */
- printk("%s: Enabling Ultra DMA %d\n", drive->name, feature & 0xf);
+ printk(KERN_INFO "%s: Enabling Ultra DMA %d\n", drive->name, feature & 0xf);
ret = pmac_ide_do_setfeature(drive, feature);
if (ret) {
- printk("%s: Failed !\n", drive->name);
+ printk(KERN_WARNING "%s: Failed !\n", drive->name);
return 0;
}
@@ -953,7 +959,7 @@ pmac_ide_check_dma(ide_drive_t *drive)
int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
{
- int ix, dstat;
+ int ix, dstat, i;
volatile struct dbdma_regs *dma;
/* Can we stuff a pointer to our intf structure in config_data
@@ -966,7 +972,7 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
switch (func) {
case ide_dma_off:
- printk("%s: DMA disabled\n", drive->name);
+ printk(KERN_INFO "%s: DMA disabled\n", drive->name);
case ide_dma_off_quietly:
drive->using_dma = 0;
break;
@@ -994,7 +1000,27 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
/* verify good dma status */
return (dstat & (RUN|DEAD|ACTIVE)) != RUN;
case ide_dma_test_irq:
- return (in_le32(&dma->status) & (RUN|ACTIVE)) == RUN;
+ if ((in_le32(&dma->status) & (RUN|ACTIVE)) == RUN)
+ return 1;
+ /* That's a bit ugly and dangerous, but works in our case
+ * to workaround a problem with the channel status staying
+ * active if the drive returns an error
+ */
+ if (IDE_CONTROL_REG) {
+ byte stat;
+ stat = GET_ALTSTAT();
+ if (stat & ERR_STAT)
+ return 1;
+ }
+ /* In some edge cases, some datas may still be in the dbdma
+ * engine fifo, we wait a bit for dbdma to complete
+ */
+ while ((in_le32(&dma->status) & (RUN|ACTIVE)) != RUN) {
+ if (++i > 100)
+ return 0;
+ udelay(1);
+ }
+ return 1;
/* Let's implement tose just in case someone wants them */
case ide_dma_bad_drive:
@@ -1005,10 +1031,10 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
case ide_dma_retune:
case ide_dma_lostirq:
case ide_dma_timeout:
- printk("ide_pmac_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func), func);
+ printk(KERN_WARNING "ide_pmac_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func), func);
return 1;
default:
- printk("ide_pmac_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func);
+ printk(KERN_WARNING "ide_pmac_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func);
return 1;
}
return 0;
@@ -1016,13 +1042,15 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
#ifdef CONFIG_PMAC_PBOOK
-static void idepmac_sleep_disk(int i, unsigned long base)
+static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
{
- struct device_node* np = pmac_ide[i].node;
int j;
-
- /* FIXME: We only handle the master IDE */
- if (ide_hwifs[i].drives[0].media == ide_disk) {
+
+ /* FIXME: We only handle the master IDE disk, we shoud
+ * try to fix CD-ROMs here
+ */
+ switch (drive->media) {
+ case ide_disk:
/* Spin down the drive */
outb(0xa0, base+0x60);
outb(0x0, base+0x30);
@@ -1038,86 +1066,112 @@ static void idepmac_sleep_disk(int i, unsigned long base)
if (!(status & BUSY_STAT) && (status & DRQ_STAT))
break;
}
- }
- feature_set(np, FEATURE_IDE0_reset);
- feature_clear(np, FEATURE_IDE0_enable);
- switch(pmac_ide[i].aapl_bus_id) {
- case 0:
- feature_set(np, FEATURE_IDE0_reset);
- feature_clear(np, FEATURE_IDE0_enable);
break;
- case 1:
- feature_set(np, FEATURE_IDE1_reset);
- feature_clear(np, FEATURE_IDE1_enable);
+ case ide_cdrom:
+ // todo
break;
- case 2:
- feature_set(np, FEATURE_IDE2_reset);
+ case ide_floppy:
+ // todo
break;
}
- pmac_ide[i].timings[0] = 0;
- pmac_ide[i].timings[1] = 0;
}
-static void idepmac_wake_disk(int i, unsigned long base)
+static void idepmac_wake_device(ide_drive_t *drive, int used_dma)
+ {
+ /* We force the IDE subdriver to check for a media change
+ * This must be done first or we may lost the condition
+ *
+ * Problem: This can schedule. I moved the block device
+ * wakeup almost late by priority because of that.
+ */
+ if (DRIVER(drive) && DRIVER(drive)->media_change)
+ DRIVER(drive)->media_change(drive);
+
+ /* We kick the VFS too (see fix in ide.c revalidate) */
+ check_disk_change(MKDEV(HWIF(drive)->major, (drive->select.b.unit) << PARTN_BITS));
+
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+ /* We re-enable DMA on the drive if it was active. */
+ /* This doesn't work with the CD-ROM in the media-bay, probably
+ * because of a pending unit attention. The problem if that if I
+ * clear the error, the filesystem dies.
+ */
+ if (used_dma && !ide_spin_wait_hwgroup(drive)) {
+ /* Lock HW group */
+ HWGROUP(drive)->busy = 1;
+ pmac_ide_check_dma(drive);
+ HWGROUP(drive)->busy = 0;
+ spin_unlock_irq(&io_request_lock);
+ }
+#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+}
+
+static void idepmac_sleep_interface(int i, unsigned base, int mediabay)
{
struct device_node* np = pmac_ide[i].node;
- int j;
- /* Revive IDE disk and controller */
+ /* We clear the timings */
+ pmac_ide[i].timings[0] = 0;
+ pmac_ide[i].timings[1] = 0;
+
+ /* The media bay will handle itself just fine */
+ if (mediabay)
+ return;
+
+ /* Disable and reset the bus */
+ feature_set(np, FEATURE_IDE0_reset);
+ feature_clear(np, FEATURE_IDE0_enable);
switch(pmac_ide[i].aapl_bus_id) {
case 0:
feature_set(np, FEATURE_IDE0_reset);
- mdelay(10);
- feature_set(np, FEATURE_IDE0_enable);
- mdelay(10);
- feature_clear(np, FEATURE_IDE0_reset);
+ feature_clear(np, FEATURE_IDE0_enable);
break;
case 1:
feature_set(np, FEATURE_IDE1_reset);
- mdelay(10);
- feature_set(np, FEATURE_IDE1_enable);
- mdelay(10);
- feature_clear(np, FEATURE_IDE1_reset);
+ feature_clear(np, FEATURE_IDE1_enable);
break;
case 2:
- /* This one exists only for KL, I don't know
- about any enable bit */
feature_set(np, FEATURE_IDE2_reset);
- mdelay(10);
- feature_clear(np, FEATURE_IDE2_reset);
break;
}
- mdelay(IDE_WAKEUP_DELAY_MS);
-
- /* Reset timings */
- pmac_ide_selectproc(&ide_hwifs[i].drives[0]);
- mdelay(10);
-
- /* Wait up to 10 seconds (enough for recent drives) */
- for (j = 0; j < 100; j++) {
- int status;
- mdelay(100);
- status = inb(base + 0x70);
- if (!(status & BUSY_STAT))
- break;
- }
}
-/* Here we handle media bay devices */
-static void
-idepmac_wake_bay(int i, unsigned long base)
+static void idepmac_wake_interface(int i, unsigned long base, int mediabay)
{
- int timeout;
+ struct device_node* np = pmac_ide[i].node;
+ if (!mediabay) {
+ /* Revive IDE disk and controller */
+ switch(pmac_ide[i].aapl_bus_id) {
+ case 0:
+ feature_set(np, FEATURE_IDE0_reset);
+ feature_set(np, FEATURE_IOBUS_enable);
+ mdelay(10);
+ feature_set(np, FEATURE_IDE0_enable);
+ mdelay(10);
+ feature_clear(np, FEATURE_IDE0_reset);
+ break;
+ case 1:
+ feature_set(np, FEATURE_IDE1_reset);
+ feature_set(np, FEATURE_IOBUS_enable);
+ mdelay(10);
+ feature_set(np, FEATURE_IDE1_enable);
+ mdelay(10);
+ feature_clear(np, FEATURE_IDE1_reset);
+ break;
+ case 2:
+ /* This one exists only for KL, I don't know
+ about any enable bit */
+ feature_set(np, FEATURE_IDE2_reset);
+ mdelay(10);
+ feature_clear(np, FEATURE_IDE2_reset);
+ break;
+ }
+ }
+
/* Reset timings */
pmac_ide_selectproc(&ide_hwifs[i].drives[0]);
mdelay(10);
-
- timeout = 10000;
- while ((inb(base + 0x70) & BUSY_STAT) && timeout) {
- mdelay(1);
- --timeout;
- }
}
/* Note: We support only master drives for now. This will have to be
@@ -1128,6 +1182,8 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
{
int i, ret;
unsigned long base;
+ unsigned long flags;
+ int big_delay;
switch (when) {
case PBOOK_SLEEP_REQUEST:
@@ -1136,34 +1192,104 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
break;
case PBOOK_SLEEP_NOW:
for (i = 0; i < pmac_ide_count; ++i) {
+ ide_hwif_t *hwif;
+ ide_drive_t *drive;
+ int unlock = 0;
+
if ((base = pmac_ide[i].regbase) == 0)
- continue;
+ continue;
+
+ hwif = &ide_hwifs[i];
+ drive = &hwif->drives[0];
+
+ if (drive->present) {
+ /* Wait for HW group to complete operations */
+ if (ide_spin_wait_hwgroup(drive)) {
+ // What can we do here ? Wake drive we had already
+ // put to sleep and return an error ?
+ } else {
+ unlock = 1;
+ /* Lock HW group */
+ HWGROUP(drive)->busy = 1;
+
+ /* Stop the device */
+ idepmac_sleep_device(drive, i, base);
+
+ }
+ }
/* Disable irq during sleep */
disable_irq(pmac_ide[i].irq);
+ if (unlock)
+ spin_unlock_irq(&io_request_lock);
+
+ /* Check if this is a media bay with an IDE device or not
+ * a media bay.
+ */
ret = check_media_bay_by_base(base, MB_CD);
- if ((ret == -ENODEV) && ide_hwifs[i].drives[0].present)
- /* not media bay - put the disk to sleep */
- idepmac_sleep_disk(i, base);
+ if ((ret == 0) || (ret == -ENODEV))
+ idepmac_sleep_interface(i, base, (ret == 0));
}
break;
case PBOOK_WAKE:
+ big_delay = 0;
+ for (i = 0; i < pmac_ide_count; ++i) {
+
+ if ((base = pmac_ide[i].regbase) == 0)
+ continue;
+
+ /* Check if this is a media bay with an IDE device or not
+ * a media bay
+ */
+ ret = check_media_bay_by_base(base, MB_CD);
+ if ((ret == 0) || (ret == -ENODEV)) {
+ idepmac_wake_interface(i, base, (ret == 0));
+ big_delay = 1;
+ }
+
+ }
+ /* Let hardware get up to speed */
+ if (big_delay)
+ mdelay(IDE_WAKEUP_DELAY_MS);
+
for (i = 0; i < pmac_ide_count; ++i) {
ide_hwif_t *hwif;
+ ide_drive_t *drive;
+ int j, used_dma;
+
if ((base = pmac_ide[i].regbase) == 0)
continue;
+
hwif = &ide_hwifs[i];
- /* We don't handle media bay devices this way */
- ret = check_media_bay_by_base(base, MB_CD);
- if ((ret == -ENODEV) && ide_hwifs[i].drives[0].present)
- idepmac_wake_disk(i, base);
- else if (ret == 0)
- idepmac_wake_bay(i, base);
- enable_irq(pmac_ide[i].irq);
+ drive = &hwif->drives[0];
+
+ /* Wait for the drive to come up and set it's DMA */
+ if (drive->present) {
+ /* Wait up to 20 seconds */
+ for (j = 0; j < 200; j++) {
+ int status;
+ mdelay(100);
+ status = inb(base + 0x70);
+ if (!(status & BUSY_STAT))
+ break;
+ }
+ }
+
+ /* We don't have re-configured DMA yet */
+ used_dma = drive->using_dma;
+ drive->using_dma = 0;
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
- if (hwif->drives[0].present && hwif->drives[0].using_dma)
- pmac_ide_check_dma(&hwif->drives[0]);
-#endif
+ /* We resume processing on the HW group */
+ spin_lock_irqsave(&io_request_lock, flags);
+ enable_irq(pmac_ide[i].irq);
+ if (drive->present)
+ HWGROUP(drive)->busy = 0;
+ spin_unlock_irqrestore(&io_request_lock, flags);
+
+ /* Wake the device
+ * We could handle the slave here
+ */
+ if (drive->present)
+ idepmac_wake_device(drive, used_dma);
}
break;
}
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index e33b5ed75db1..3f337eb5d599 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -154,21 +154,18 @@ void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
}
-#define DEFINE_MULTIPLEXER(Function) \
-void highlevel_##Function(struct hpsb_host *host) \
-{ \
- struct list_head *entry,*next; \
- void (*funcptr)(struct hpsb_host*); \
- read_lock(&hl_drivers_lock); \
- entry = hl_drivers.next; \
- while (entry != &hl_drivers) { \
- next = entry->next; \
- funcptr = list_entry(entry, struct hpsb_highlevel, hl_list) \
- ->op->Function; \
- if (funcptr) funcptr(host); \
- entry = next; \
- } \
- read_unlock(&hl_drivers_lock); \
+#define DEFINE_MULTIPLEXER(Function) \
+void highlevel_##Function(struct hpsb_host *host) \
+{ \
+ struct list_head *lh; \
+ void (*funcptr)(struct hpsb_host*); \
+ read_lock(&hl_drivers_lock); \
+ list_for_each(lh, &hl_drivers) { \
+ funcptr = list_entry(lh, struct hpsb_highlevel, hl_list) \
+ ->op->Function; \
+ if (funcptr) funcptr(host); \
+ } \
+ read_unlock(&hl_drivers_lock); \
}
DEFINE_MULTIPLEXER(add_host)
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index 0c1ed7426270..01019eddafc6 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -23,8 +23,8 @@
#include "highlevel.h"
-static struct hpsb_host_template *templates = NULL;
-spinlock_t templates_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(templates);
+static spinlock_t templates_lock = SPIN_LOCK_UNLOCKED;
/*
* This function calls the add_host/remove_host hooks for every host currently
@@ -32,13 +32,16 @@ spinlock_t templates_lock = SPIN_LOCK_UNLOCKED;
*/
void hl_all_hosts(struct hpsb_highlevel *hl, int init)
{
+ struct list_head *tlh, *hlh;
struct hpsb_host_template *tmpl;
struct hpsb_host *host;
spin_lock(&templates_lock);
- for (tmpl = templates; tmpl != NULL; tmpl = tmpl->next) {
- for (host = tmpl->hosts; host != NULL; host = host->next) {
+ list_for_each(tlh, &templates) {
+ tmpl = list_entry(tlh, struct hpsb_host_template, list);
+ list_for_each(hlh, &tmpl->hosts) {
+ host = list_entry(hlh, struct hpsb_host, list);
if (host->initialized) {
if (init) {
if (hl->op->add_host) {
@@ -58,21 +61,24 @@ void hl_all_hosts(struct hpsb_highlevel *hl, int init)
int hpsb_inc_host_usage(struct hpsb_host *host)
{
+ struct list_head *tlh, *hlh;
struct hpsb_host_template *tmpl;
- struct hpsb_host *h;
int retval = 0;
unsigned long flags;
spin_lock_irqsave(&templates_lock, flags);
- for (tmpl = templates; (tmpl != NULL) && !retval; tmpl = tmpl->next) {
- for (h = tmpl->hosts; h != NULL; h = h->next) {
- if (h == host) {
- tmpl->devctl(h, MODIFY_USAGE, 1);
+ list_for_each(tlh, &templates) {
+ tmpl = list_entry(tlh, struct hpsb_host_template, list);
+ list_for_each(hlh, &tmpl->hosts) {
+ if (host == list_entry(hlh, struct hpsb_host, list)) {
+ tmpl->devctl(host, MODIFY_USAGE, 1);
retval = 1;
break;
}
}
+ if (retval)
+ break;
}
spin_unlock_irqrestore(&templates_lock, flags);
@@ -113,32 +119,22 @@ struct hpsb_host *hpsb_get_host(struct hpsb_host_template *tmpl,
h->speed_map = (u8 *)(h->csr.speed_map + 2);
h->template = tmpl;
- if (hd_size) {
+ if (hd_size)
h->hostdata = &h->embedded_hostdata[0];
- }
-
- if (tmpl->hosts == NULL) {
- tmpl->hosts = h;
- } else {
- struct hpsb_host *last = tmpl->hosts;
- while (last->next != NULL) {
- last = last->next;
- }
- last->next = h;
- }
+ list_add_tail(&h->list, &tmpl->hosts);
return h;
}
static void free_all_hosts(struct hpsb_host_template *tmpl)
{
- struct hpsb_host *next, *host = tmpl->hosts;
+ struct list_head *hlh, *next;
+ struct hpsb_host *host;
- while (host) {
- next = host->next;
+ list_for_each_safe(hlh, next, &tmpl->hosts) {
+ host = list_entry(hlh, struct hpsb_host, list);
vfree(host);
- host = next;
}
}
@@ -146,11 +142,13 @@ static void free_all_hosts(struct hpsb_host_template *tmpl)
static void init_hosts(struct hpsb_host_template *tmpl)
{
int count;
+ struct list_head *hlh;
struct hpsb_host *host;
count = tmpl->detect_hosts(tmpl);
- for (host = tmpl->hosts; host != NULL; host = host->next) {
+ list_for_each(hlh, &tmpl->hosts) {
+ host = list_entry(hlh, struct hpsb_host, list);
if (tmpl->initialize_host(host)) {
host->initialized = 1;
@@ -166,9 +164,11 @@ static void init_hosts(struct hpsb_host_template *tmpl)
static void shutdown_hosts(struct hpsb_host_template *tmpl)
{
+ struct list_head *hlh;
struct hpsb_host *host;
- for (host = tmpl->hosts; host != NULL; host = host->next) {
+ list_for_each(hlh, &tmpl->hosts) {
+ host = list_entry(hlh, struct hpsb_host, list);
if (host->initialized) {
host->initialized = 0;
abort_requests(host);
@@ -188,68 +188,17 @@ static void shutdown_hosts(struct hpsb_host_template *tmpl)
}
-static int add_template(struct hpsb_host_template *new)
-{
- new->next = NULL;
- new->hosts = NULL;
- new->number_of_hosts = 0;
-
- spin_lock(&templates_lock);
- if (templates == NULL) {
- templates = new;
- } else {
- struct hpsb_host_template *last = templates;
- while (last->next != NULL) {
- last = last->next;
- }
- last->next = new;
- }
- spin_unlock(&templates_lock);
-
- return 0;
-}
-
-static int remove_template(struct hpsb_host_template *tmpl)
-{
- int retval = 0;
-
- if (tmpl->number_of_hosts) {
- HPSB_ERR("attempted to remove busy host template "
- "of %s at address 0x%p", tmpl->name, tmpl);
- return 1;
- }
-
- spin_lock(&templates_lock);
- if (templates == tmpl) {
- templates = tmpl->next;
- } else {
- struct hpsb_host_template *t;
-
- t = templates;
- while (t->next != tmpl && t->next != NULL) {
- t = t->next;
- }
-
- if (t->next == NULL) {
- HPSB_ERR("attempted to remove unregistered host template "
- "of %s at address 0x%p", tmpl->name, tmpl);
- retval = -1;
- } else {
- t->next = tmpl->next;
- }
- }
- spin_unlock(&templates_lock);
-
- return retval;
-}
-
-
/*
* The following two functions are exported symbols for module usage.
*/
int hpsb_register_lowlevel(struct hpsb_host_template *tmpl)
{
- add_template(tmpl);
+ INIT_LIST_HEAD(&tmpl->hosts);
+ tmpl->number_of_hosts = 0;
+
+ spin_lock(&templates_lock);
+ list_add_tail(&tmpl->list, &templates);
+ spin_unlock(&templates_lock);
/* PCI cards should be smart and use the PCI detection layer, and
* not this one shot deal. detect_hosts() will be obsoleted soon. */
@@ -265,7 +214,12 @@ void hpsb_unregister_lowlevel(struct hpsb_host_template *tmpl)
{
shutdown_hosts(tmpl);
- if (remove_template(tmpl)) {
- HPSB_PANIC("remove_template failed on %s", tmpl->name);
- }
+ if (tmpl->number_of_hosts)
+ HPSB_PANIC("attempted to remove busy host template "
+ "of %s at address 0x%p", tmpl->name, tmpl);
+ else {
+ spin_lock(&templates_lock);
+ list_del(&tmpl->list);
+ spin_unlock(&templates_lock);
+ }
}
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index 2f3c34771913..a58d415ab0b3 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -3,6 +3,7 @@
#include <linux/wait.h>
#include <linux/tqueue.h>
+#include <linux/list.h>
#include <asm/semaphore.h>
#include "ieee1394_types.h"
@@ -13,7 +14,7 @@ struct hpsb_packet;
struct hpsb_host {
/* private fields (hosts, do not use them) */
- struct hpsb_host *next;
+ struct list_head list;
atomic_t generation;
@@ -109,9 +110,9 @@ enum reset_types {
};
struct hpsb_host_template {
- struct hpsb_host_template *next;
+ struct list_head list;
- struct hpsb_host *hosts;
+ struct list_head hosts;
int number_of_hosts;
/* fields above will be ignored and overwritten after registering */
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index fe58e3a33bc0..b19bd5d43909 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <asm/bitops.h>
#include <asm/byteorder.h>
#include <asm/semaphore.h>
@@ -30,6 +31,13 @@
#include "csr.h"
#include "nodemgr.h"
+/*
+ * Disable the nodemgr detection and config rom reading functionality.
+ */
+MODULE_PARM(disable_nodemgr, "i");
+MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality.");
+static int disable_nodemgr = 0;
+
static kmem_cache_t *hpsb_packet_cache;
@@ -95,7 +103,7 @@ struct hpsb_packet *alloc_hpsb_packet(size_t data_size)
INIT_TQ_HEAD(packet->complete_tq);
INIT_LIST_HEAD(&packet->list);
sema_init(&packet->state_change, 0);
- packet->state = unused;
+ packet->state = hpsb_unused;
packet->generation = -1;
packet->data_be = 1;
@@ -352,14 +360,14 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
}
if (ackcode != ACK_PENDING || !packet->expect_response) {
- packet->state = completed;
+ packet->state = hpsb_complete;
up(&packet->state_change);
up(&packet->state_change);
run_task_queue(&packet->complete_tq);
return;
}
- packet->state = pending;
+ packet->state = hpsb_pending;
packet->sendtime = jiffies;
spin_lock_irqsave(&host->pending_pkt_lock, flags);
@@ -393,9 +401,9 @@ int hpsb_send_packet(struct hpsb_packet *packet)
return 0;
}
- packet->state = queued;
+ packet->state = hpsb_queued;
- if (packet->type == async && packet->node_id != ALL_NODES) {
+ if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
packet->speed_code =
host->speed_map[(host->node_id & NODE_MASK) * 64
+ (packet->node_id & NODE_MASK)];
@@ -503,14 +511,14 @@ void handle_packet_response(struct hpsb_host *host, int tcode, quadlet_t *data,
break;
}
- packet->state = completed;
+ packet->state = hpsb_complete;
up(&packet->state_change);
run_task_queue(&packet->complete_tq);
}
-struct hpsb_packet *create_reply_packet(struct hpsb_host *host, quadlet_t *data,
- size_t dsize)
+static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,
+ quadlet_t *data, size_t dsize)
{
struct hpsb_packet *p;
@@ -522,13 +530,15 @@ struct hpsb_packet *create_reply_packet(struct hpsb_host *host, quadlet_t *data,
return NULL;
}
- p->type = async;
- p->state = unused;
+ p->type = hpsb_async;
+ p->state = hpsb_unused;
p->host = host;
p->node_id = data[1] >> 16;
p->tlabel = (data[0] >> 10) & 0x3f;
p->no_waiter = 1;
+ p->generation = get_hpsb_generation(host);
+
if (dsize % 4) {
p->data[dsize / 4] = 0;
}
@@ -540,8 +550,8 @@ struct hpsb_packet *create_reply_packet(struct hpsb_host *host, quadlet_t *data,
packet = create_reply_packet(host, data, length); \
if (packet == NULL) break
-void handle_incoming_packet(struct hpsb_host *host, int tcode, quadlet_t *data,
- size_t size, int write_acked)
+static void handle_incoming_packet(struct hpsb_host *host, int tcode,
+ quadlet_t *data, size_t size, int write_acked)
{
struct hpsb_packet *packet;
int length, rcode, extcode;
@@ -720,7 +730,7 @@ void abort_requests(struct hpsb_host *host)
list_for_each(lh, &llist) {
packet = list_entry(lh, struct hpsb_packet, list);
- packet->state = completed;
+ packet->state = hpsb_complete;
packet->ack_code = ACKX_ABORTED;
up(&packet->state_change);
run_task_queue(&packet->complete_tq);
@@ -732,7 +742,7 @@ void abort_timedouts(struct hpsb_host *host)
unsigned long flags;
struct hpsb_packet *packet;
unsigned long expire;
- struct list_head *lh;
+ struct list_head *lh, *next;
LIST_HEAD(expiredlist);
spin_lock_irqsave(&host->csr.lock, flags);
@@ -746,8 +756,9 @@ void abort_timedouts(struct hpsb_host *host)
spin_lock_irqsave(&host->pending_pkt_lock, flags);
- list_for_each(lh, &host->pending_packets) {
+ for (lh = host->pending_packets.next; lh != &host->pending_packets; lh = next) {
packet = list_entry(lh, struct hpsb_packet, list);
+ next = lh->next;
if (time_before(packet->sendtime + expire, jiffies)) {
list_del(&packet->list);
list_add(&packet->list, &expiredlist);
@@ -761,7 +772,7 @@ void abort_timedouts(struct hpsb_host *host)
list_for_each(lh, &expiredlist) {
packet = list_entry(lh, struct hpsb_packet, list);
- packet->state = completed;
+ packet->state = hpsb_complete;
packet->ack_code = ACKX_TIMEOUT;
up(&packet->state_change);
run_task_queue(&packet->complete_tq);
@@ -775,13 +786,19 @@ static int __init ieee1394_init(void)
0, 0, NULL, NULL);
init_hpsb_highlevel();
init_csr();
- init_ieee1394_nodemgr();
+ if (!disable_nodemgr)
+ init_ieee1394_nodemgr();
+ else
+ HPSB_INFO("nodemgr functionality disabled");
+
return 0;
}
static void __exit ieee1394_cleanup(void)
{
- cleanup_ieee1394_nodemgr();
+ if (!disable_nodemgr)
+ cleanup_ieee1394_nodemgr();
+
cleanup_csr();
kmem_cache_destroy(hpsb_packet_cache);
}
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index c1ebc47ad626..fa5d65fb785b 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -20,16 +20,16 @@ struct hpsb_packet {
/* Async and Iso types should be clear, raw means send-as-is, do not
* CRC! Byte swapping shall still be done in this case. */
- enum { async, iso, raw } __attribute__((packed)) type;
+ enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
/* Okay, this is core internal and a no care for hosts.
* queued = queued for sending
* pending = sent, waiting for response
- * completed = processing completed, successful or not
+ * complete = processing completed, successful or not
* incoming = incoming packet
*/
enum {
- unused, queued, pending, completed, incoming
+ hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete, hpsb_incoming
} __attribute__((packed)) state;
/* These are core internal. */
diff --git a/drivers/ieee1394/ieee1394_hotplug.h b/drivers/ieee1394/ieee1394_hotplug.h
index 6de64a4cc504..f5933274accd 100644
--- a/drivers/ieee1394/ieee1394_hotplug.h
+++ b/drivers/ieee1394/ieee1394_hotplug.h
@@ -2,32 +2,75 @@
#define _IEEE1394_HOTPLUG_H
#include "ieee1394_core.h"
+#include "nodemgr.h"
-#define IEEE1394_DEVICE_ID_MATCH_VENDOR_ID 0x0001
-#define IEEE1394_DEVICE_ID_MATCH_MODEL_ID 0x0002
-#define IEEE1394_DEVICE_ID_MATCH_SW_SPECIFIER_ID 0x0004
-#define IEEE1394_DEVICE_ID_MATCH_SW_SPECIFIER_VERSION 0x0008
+#define IEEE1394_MATCH_VENDOR_ID 0x0001
+#define IEEE1394_MATCH_MODEL_ID 0x0002
+#define IEEE1394_MATCH_SPECIFIER_ID 0x0004
+#define IEEE1394_MATCH_VERSION 0x0008
struct ieee1394_device_id {
u32 match_flags;
u32 vendor_id;
u32 model_id;
- u32 sw_specifier_id;
- u32 sw_specifier_version;
+ u32 specifier_id;
+ u32 version;
+ void *driver_data;
};
-#define IEEE1394_PROTOCOL(id, version) { \
- match_flags: IEEE1394_DEVICE_ID_MATCH_SW_SPECIFIER_ID | \
- IEEE1394_DEVICE_ID_MATCH_SW_SPECIFIER_VERSION, \
- sw_specifier_id: id, \
- sw_specifier_version: version \
-}
-
-#define IEEE1394_DEVICE(vendor_id, model_id) { \
- match_flags: IEEE1394_DEVICE_ID_MATCH_VENDOR_ID | \
- IEEE1394_DEVICE_ID_MATCH_MODEL_ID, \
- vendor_id: vendor_id, \
- model_id: vendor_id, \
-}
+struct hpsb_protocol_driver {
+ /* The name of the driver, e.g. SBP2 or IP1394 */
+ const char *name;
+
+ /*
+ * The device id table describing the protocols and/or devices
+ * supported by this driver. This is used by the nodemgr to
+ * decide if a driver could support a given node, but the
+ * probe function below can implement further protocol
+ * dependent or vendor dependent checking.
+ */
+ struct ieee1394_device_id *id_table;
+
+ /*
+ * The probe function is called when a device is added to the
+ * bus and the nodemgr finds a matching entry in the drivers
+ * device id table or when registering this driver and a
+ * previously unhandled device can be handled. The driver may
+ * decline to handle the device based on further investigation
+ * of the device (or whatever reason) in which case a negative
+ * error code should be returned, otherwise 0 should be
+ * returned. The driver may use the driver_data field in the
+ * unit directory to store per device driver specific data.
+ */
+ int (*probe)(struct unit_directory *ud);
+
+ /*
+ * The disconnect function is called when a device is removed
+ * from the bus or if it wasn't possible to read the guid
+ * after the last bus reset.
+ */
+ void (*disconnect)(struct unit_directory *ud);
+
+ /*
+ * The update function is called when the node has just
+ * survived a bus reset, i.e. it is still present on the bus.
+ * However, it may be necessary to reestablish the connection
+ * or login into the node again, depending on the protocol.
+ */
+ void (*update)(struct unit_directory *ud);
+
+ /* Driver in list of all registered drivers */
+ struct list_head list;
+
+ /* The list of unit directories managed by this driver */
+ struct list_head unit_directories;
+};
+
+int hpsb_register_protocol(struct hpsb_protocol_driver *driver);
+void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver);
+
+int hpsb_claim_unit_directory(struct unit_directory *ud,
+ struct hpsb_protocol_driver *driver);
+void hpsb_release_unit_directory(struct unit_directory *ud);
#endif /* _IEEE1394_HOTPLUG_H */
diff --git a/drivers/ieee1394/ieee1394_syms.c b/drivers/ieee1394/ieee1394_syms.c
index e5a07889a543..4b9324dd9cec 100644
--- a/drivers/ieee1394/ieee1394_syms.c
+++ b/drivers/ieee1394/ieee1394_syms.c
@@ -18,6 +18,7 @@
#include "hosts.h"
#include "ieee1394_core.h"
#include "ieee1394_transactions.h"
+#include "ieee1394_hotplug.h"
#include "highlevel.h"
#include "nodemgr.h"
@@ -75,8 +76,12 @@ EXPORT_SYMBOL(highlevel_add_host);
EXPORT_SYMBOL(highlevel_remove_host);
EXPORT_SYMBOL(highlevel_host_reset);
EXPORT_SYMBOL(highlevel_add_one_host);
+
EXPORT_SYMBOL(hpsb_guid_get_entry);
EXPORT_SYMBOL(hpsb_nodeid_get_entry);
EXPORT_SYMBOL(hpsb_get_host_by_ne);
EXPORT_SYMBOL(hpsb_guid_fill_packet);
+EXPORT_SYMBOL(hpsb_register_protocol);
+EXPORT_SYMBOL(hpsb_unregister_protocol);
+EXPORT_SYMBOL(hpsb_release_unit_directory);
MODULE_LICENSE("GPL");
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index 95b85139f0b8..7086bc7e2caa 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -131,7 +131,7 @@ void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
packet->header_size = 4;
packet->data_size = length;
- packet->type = iso;
+ packet->type = hpsb_iso;
packet->tcode = TCODE_ISO_DATA;
}
@@ -142,7 +142,7 @@ void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
packet->header_size = 8;
packet->data_size = 0;
packet->expect_response = 0;
- packet->type = raw; /* No CRC added */
+ packet->type = hpsb_raw; /* No CRC added */
packet->speed_code = SPEED_100; /* Force speed to be 100Mbps */
}
@@ -488,7 +488,9 @@ struct hpsb_packet *hpsb_make_packet (struct hpsb_host *host, nodeid_t node,
if (!packet)
return NULL;
- if (length != 4)
+ /* Sometimes this may be called without data, just to allocate the
+ * packet. */
+ if (length != 4 && buffer)
memcpy(packet->data, buffer, length);
return packet;
diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h
index 1385070dd984..185cecacb444 100644
--- a/drivers/ieee1394/ieee1394_types.h
+++ b/drivers/ieee1394/ieee1394_types.h
@@ -26,6 +26,13 @@
#include <linux/spinlock.h>
#endif
+#ifndef list_for_each_safe
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+#endif
+
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 37ac83b29244..7b1ee818652a 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -15,11 +15,13 @@
#include <asm/atomic.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
+#include <linux/kmod.h>
#include "ieee1394_types.h"
#include "ieee1394.h"
#include "hosts.h"
#include "ieee1394_transactions.h"
+#include "ieee1394_hotplug.h"
#include "highlevel.h"
#include "csr.h"
#include "nodemgr.h"
@@ -47,6 +49,16 @@
static LIST_HEAD(node_list);
static rwlock_t node_lock = RW_LOCK_UNLOCKED;
+static LIST_HEAD(driver_list);
+static rwlock_t driver_lock = RW_LOCK_UNLOCKED;
+
+/* The rwlock unit_directory_lock is always held when manipulating the
+ * global unit_directory_list, but this also protects access to the
+ * lists of unit directories stored in the protocol drivers.
+ */
+static LIST_HEAD(unit_directory_list);
+static rwlock_t unit_directory_lock = RW_LOCK_UNLOCKED;
+
static LIST_HEAD(host_info_list);
static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED;
@@ -56,7 +68,12 @@ struct host_info {
struct list_head list;
};
-static struct node_entry *create_node_entry(void)
+static void nodemgr_process_config_rom(struct node_entry *ne,
+ quadlet_t busoptions);
+
+
+static struct node_entry *nodemgr_create_node(octlet_t guid, quadlet_t busoptions,
+ struct hpsb_host *host, nodeid_t nodeid)
{
struct node_entry *ne;
unsigned long flags;
@@ -66,15 +83,21 @@ static struct node_entry *create_node_entry(void)
INIT_LIST_HEAD(&ne->list);
INIT_LIST_HEAD(&ne->unit_directories);
- ne->guid = (u64) -1;
- ne->host = NULL;
- ne->nodeid = 0;
- atomic_set(&ne->generation, -1);
+ ne->host = host;
+ ne->nodeid = nodeid;
+ ne->guid = guid;
+ atomic_set(&ne->generation, get_hpsb_generation(ne->host));
write_lock_irqsave(&node_lock, flags);
list_add_tail(&ne->list, &node_list);
write_unlock_irqrestore(&node_lock, flags);
+ nodemgr_process_config_rom (ne, busoptions);
+
+ HPSB_DEBUG("%s added: node " NODE_BUS_FMT ", GUID %016Lx",
+ (host->node_id == nodeid) ? "Local host" : "Device",
+ NODE_BUS_ARGS(nodeid), (unsigned long long)guid);
+
return ne;
}
@@ -104,16 +127,20 @@ static struct node_entry *find_entry_by_nodeid(nodeid_t nodeid)
return NULL;
}
-int nodemgr_read_quadlet(struct node_entry *ne,
+int nodemgr_read_quadlet(struct node_entry *ne,
octlet_t address, quadlet_t *quad)
{
- if (hpsb_read(ne->host, ne->nodeid, address, quad, 4)) {
- HPSB_DEBUG("read of address %Lx failed", address);
- return -EAGAIN;
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < 3; i++) {
+ ret = hpsb_read(ne->host, ne->nodeid, address, quad, 4);
+ if (ret != -EAGAIN)
+ break;
}
*quad = be32_to_cpu(*quad);
- return 0;
+ return ret;
}
#define CONFIG_ROM_VENDOR_ID 0x03
@@ -137,13 +164,14 @@ static void nodemgr_process_unit_directory(struct node_entry *ne,
octlet_t a;
quadlet_t quad;
int length, i;
-
if (!(ud = kmalloc (sizeof *ud, GFP_KERNEL)))
goto unit_directory_error;
memset (ud, 0, sizeof *ud);
+ ud->ne = ne;
ud->address = address;
+ ud->arb_count = 0;
if (nodemgr_read_quadlet(ne, address, &quad))
goto unit_directory_error;
@@ -151,7 +179,8 @@ static void nodemgr_process_unit_directory(struct node_entry *ne,
a = address + 4;
for (i = 0; i < length; i++, a += 4) {
- int code, value;
+ int code;
+ quadlet_t value;
if (nodemgr_read_quadlet(ne, a, &quad))
goto unit_directory_error;
@@ -183,10 +212,20 @@ static void nodemgr_process_unit_directory(struct node_entry *ne,
case CONFIG_ROM_DESCRIPTOR_DIRECTORY:
/* TODO: read strings... icons? */
break;
+
+ default:
+ if (ud->arb_count < 16) {
+ /* Place them in the arbitrary pairs */
+ ud->arb_keys[ud->arb_count] = code;
+ ud->arb_values[ud->arb_count] = value;
+ ud->arb_count++;
+ }
}
}
- list_add_tail (&ud->list, &ne->unit_directories);
+ list_add_tail(&ud->node_list, &ne->unit_directories);
+ list_add_tail(&ud->driver_list, &unit_directory_list);
+
return;
unit_directory_error:
@@ -194,27 +233,29 @@ unit_directory_error:
kfree(ud);
}
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
static void dump_directories (struct node_entry *ne)
{
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
struct list_head *l;
HPSB_DEBUG("vendor_id=0x%06x, capabilities=0x%06x",
ne->vendor_id, ne->capabilities);
list_for_each (l, &ne->unit_directories) {
- struct unit_directory *ud = list_entry (l, struct unit_directory, list);
+ struct unit_directory *ud = list_entry (l, struct unit_directory, node_list);
HPSB_DEBUG("unit directory:");
if (ud->flags & UNIT_DIRECTORY_VENDOR_ID)
HPSB_DEBUG(" vendor_id=0x%06x ", ud->vendor_id);
if (ud->flags & UNIT_DIRECTORY_MODEL_ID)
HPSB_DEBUG(" model_id=0x%06x ", ud->model_id);
if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID)
- HPSB_DEBUG(" specifier_id=0x%06x ", ud->specifier_id);
+ HPSB_DEBUG(" sw_specifier_id=0x%06x ", ud->specifier_id);
if (ud->flags & UNIT_DIRECTORY_VERSION)
- HPSB_DEBUG(" version=0x%06x ", ud->version);
+ HPSB_DEBUG(" sw_version=0x%06x ", ud->version);
}
-}
+#else
+ return;
#endif
+}
static void nodemgr_process_root_directory(struct node_entry *ne)
{
@@ -260,86 +301,383 @@ static void nodemgr_process_root_directory(struct node_entry *ne)
break;
}
}
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+
dump_directories(ne);
+}
+
+#ifdef CONFIG_HOTPLUG
+
+static void nodemgr_call_policy(char *verb, struct unit_directory *ud)
+{
+ char *argv [3], **envp, *buf, *scratch;
+ int i = 0, value;
+
+ if (!hotplug_path [0])
+ return;
+ if (!current->fs->root)
+ return;
+ if (!(envp = (char **) kmalloc(20 * sizeof (char *), GFP_KERNEL))) {
+ HPSB_DEBUG ("ENOMEM");
+ return;
+ }
+ if (!(buf = kmalloc(256, GFP_KERNEL))) {
+ kfree(envp);
+ HPSB_DEBUG("ENOMEM2");
+ return;
+ }
+
+ /* only one standardized param to hotplug command: type */
+ argv[0] = hotplug_path;
+ argv[1] = "ieee1394";
+ argv[2] = 0;
+
+ /* minimal command environment */
+ envp[i++] = "HOME=/";
+ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+ /* hint that policy agent should enter no-stdout debug mode */
+ envp[i++] = "DEBUG=kernel";
+#endif
+ /* extensible set of named bus-specific parameters,
+ * supporting multiple driver selection algorithms.
+ */
+ scratch = buf;
+
+ envp[i++] = scratch;
+ scratch += sprintf(scratch, "ACTION=%s", verb) + 1;
+ envp[i++] = scratch;
+ scratch += sprintf(scratch, "VENDOR_ID=%06x", ud->ne->vendor_id) + 1;
+ envp[i++] = scratch;
+ scratch += sprintf(scratch, "GUID=%016Lx", (long long unsigned)ud->ne->guid) + 1;
+ envp[i++] = scratch;
+ scratch += sprintf(scratch, "SPECIFIER_ID=%06x", ud->specifier_id) + 1;
+ envp[i++] = scratch;
+ scratch += sprintf(scratch, "VERSION=%06x", ud->version) + 1;
+ envp[i++] = 0;
+
+ /* NOTE: user mode daemons can call the agents too */
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+ HPSB_DEBUG("NodeMgr: %s %s %016Lx", argv[0], verb, (long long unsigned)ud->ne->guid);
#endif
+ value = call_usermodehelper(argv[0], argv, envp);
+ kfree(buf);
+ kfree(envp);
+ if (value != 0)
+ HPSB_DEBUG("NodeMgr: hotplug policy returned 0x%x", value);
}
-static void register_node(struct hpsb_host *host, nodeid_t nodeid, u64 guid,
- quadlet_t busoptions)
+#else
+
+static inline void
+nodemgr_call_policy(char *verb, struct unit_directory *ud)
{
- struct node_entry *ne;
- unsigned long flags, new = 0;
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+ HPSB_DEBUG("NodeMgr: nodemgr_call_policy(): hotplug not enabled");
+#else
+ return;
+#endif
+}
- read_lock_irqsave(&node_lock, flags);
- ne = find_entry_by_guid(guid);
- read_unlock_irqrestore(&node_lock, flags);
+#endif /* CONFIG_HOTPLUG */
- /* New entry */
- if (!ne) {
- if ((ne = create_node_entry()) == NULL)
- return;
+static void nodemgr_claim_unit_directory(struct unit_directory *ud,
+ struct hpsb_protocol_driver *driver)
+{
+ ud->driver = driver;
+ list_del(&ud->driver_list);
+ list_add_tail(&ud->driver_list, &driver->unit_directories);
+}
+
+static void nodemgr_release_unit_directory(struct unit_directory *ud)
+{
+ ud->driver = NULL;
+ list_del(&ud->driver_list);
+ list_add_tail(&ud->driver_list, &unit_directory_list);
+}
+
+void hpsb_release_unit_directory(struct unit_directory *ud)
+{
+ unsigned long flags;
+
+ write_lock_irqsave(&unit_directory_lock, flags);
+ nodemgr_release_unit_directory(ud);
+ write_unlock_irqrestore(&unit_directory_lock, flags);
+}
+
+static void nodemgr_free_unit_directories(struct node_entry *ne)
+{
+ struct list_head *lh;
+ struct unit_directory *ud;
+
+ lh = ne->unit_directories.next;
+ while (lh != &ne->unit_directories) {
+ ud = list_entry(lh, struct unit_directory, node_list);
+ lh = lh->next;
+ if (ud->driver && ud->driver->disconnect)
+ ud->driver->disconnect(ud);
+ nodemgr_release_unit_directory(ud);
+ nodemgr_call_policy("remove", ud);
+ list_del(&ud->driver_list);
+ kfree(ud);
+ }
+}
+
+static struct ieee1394_device_id *
+nodemgr_match_driver(struct hpsb_protocol_driver *driver,
+ struct unit_directory *ud)
+{
+ struct ieee1394_device_id *id;
+
+ for (id = driver->id_table; id->match_flags != 0; id++) {
+ if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
+ id->vendor_id != ud->vendor_id)
+ continue;
+
+ if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) &&
+ id->model_id != ud->model_id)
+ continue;
+
+ if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) &&
+ id->specifier_id != ud->specifier_id)
+ continue;
+
+ if ((id->match_flags & IEEE1394_MATCH_VERSION) &&
+ id->version != ud->version)
+ continue;
+
+ return id;
+ }
+
+ return NULL;
+}
+
+static struct hpsb_protocol_driver *
+nodemgr_find_driver(struct unit_directory *ud)
+{
+ struct list_head *l;
+ struct hpsb_protocol_driver *match, *driver;
+ struct ieee1394_device_id *device_id;
+
+ match = NULL;
+ list_for_each(l, &driver_list) {
+ driver = list_entry(l, struct hpsb_protocol_driver, list);
+ device_id = nodemgr_match_driver(driver, ud);
+
+ if (device_id != NULL) {
+ match = driver;
+ break;
+ }
+ }
+
+ return match;
+}
+
+static void nodemgr_bind_drivers (struct node_entry *ne)
+{
+ struct list_head *lh;
+ struct hpsb_protocol_driver *driver;
+ struct unit_directory *ud;
+
+ list_for_each(lh, &ne->unit_directories) {
+ ud = list_entry(lh, struct unit_directory, node_list);
+ driver = nodemgr_find_driver(ud);
+ if (driver != NULL && driver->probe(ud) == 0)
+ nodemgr_claim_unit_directory(ud, driver);
+ nodemgr_call_policy("add", ud);
+ }
+}
- HPSB_DEBUG("%s added: node " NODE_BUS_FMT
- ", GUID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
- (host->node_id == nodeid) ? "Local host" : "Device",
- NODE_BUS_ARGS(nodeid), ((u8 *)&guid)[0],
- ((u8 *)&guid)[1], ((u8 *)&guid)[2], ((u8 *)&guid)[3],
- ((u8 *)&guid)[4], ((u8 *)&guid)[5], ((u8 *)&guid)[6],
- ((u8 *)&guid)[7]);
+int hpsb_register_protocol(struct hpsb_protocol_driver *driver)
+{
+ struct unit_directory *ud;
+ struct list_head *lh;
+ unsigned long flags;
- ne->guid = guid;
- new = 1;
+ write_lock_irqsave(&driver_lock, flags);
+ list_add_tail(&driver->list, &driver_list);
+ write_unlock_irqrestore(&driver_lock, flags);
+
+ write_lock_irqsave(&unit_directory_lock, flags);
+ INIT_LIST_HEAD(&driver->unit_directories);
+ lh = unit_directory_list.next;
+ while (lh != &unit_directory_list) {
+ ud = list_entry(lh, struct unit_directory, driver_list);
+ lh = lh->next;
+ if (nodemgr_match_driver(driver, ud) && driver->probe(ud) == 0)
+ nodemgr_claim_unit_directory(ud, driver);
}
+ write_unlock_irqrestore(&unit_directory_lock, flags);
+
+ /*
+ * Right now registration always succeeds, but maybe we should
+ * detect clashes in protocols handled by other drivers.
+ */
+
+ return 0;
+}
+
+void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver)
+{
+ struct list_head *lh;
+ struct unit_directory *ud;
+ unsigned long flags;
+
+ write_lock_irqsave(&driver_lock, flags);
+ list_del(&driver->list);
+ write_unlock_irqrestore(&driver_lock, flags);
+
+ write_lock_irqsave(&unit_directory_lock, flags);
+ lh = driver->unit_directories.next;
+ while (lh != &driver->unit_directories) {
+ ud = list_entry(lh, struct unit_directory, driver_list);
+ lh = lh->next;
+ if (ud->driver && ud->driver->disconnect)
+ ud->driver->disconnect(ud);
+ nodemgr_release_unit_directory(ud);
+ }
+ write_unlock_irqrestore(&unit_directory_lock, flags);
+}
+
+static void nodemgr_process_config_rom(struct node_entry *ne,
+ quadlet_t busoptions)
+{
+ unsigned long flags;
+
+ ne->busopt.irmc = (busoptions >> 31) & 1;
+ ne->busopt.cmc = (busoptions >> 30) & 1;
+ ne->busopt.isc = (busoptions >> 29) & 1;
+ ne->busopt.bmc = (busoptions >> 28) & 1;
+ ne->busopt.pmc = (busoptions >> 27) & 1;
+ ne->busopt.cyc_clk_acc = (busoptions >> 16) & 0xff;
+ ne->busopt.max_rec = 1 << (((busoptions >> 12) & 0xf) + 1);
+ ne->busopt.generation = (busoptions >> 4) & 0xf;
+ ne->busopt.lnkspd = busoptions & 0x7;
+
+#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
+ HPSB_DEBUG("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d "
+ "cyc_clk_acc=%d max_rec=%d gen=%d lspd=%d",
+ busoptions, ne->busopt.irmc, ne->busopt.cmc,
+ ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc,
+ ne->busopt.cyc_clk_acc, ne->busopt.max_rec,
+ ne->busopt.generation, ne->busopt.lnkspd);
+#endif
- if (!new && ne->nodeid != nodeid)
+ /*
+ * When the config rom changes we disconnect all drivers and
+ * free the cached unit directories and reread the whole
+ * thing. If this was a new device, the call to
+ * nodemgr_disconnect_drivers is a no-op and all is well.
+ */
+ write_lock_irqsave(&unit_directory_lock, flags);
+ nodemgr_free_unit_directories(ne);
+ nodemgr_process_root_directory(ne);
+ nodemgr_bind_drivers(ne);
+ write_unlock_irqrestore(&unit_directory_lock, flags);
+}
+
+/*
+ * This function updates nodes that were present on the bus before the
+ * reset and still are after the reset. The nodeid and the config rom
+ * may have changed, and the drivers managing this device must be
+ * informed that this device just went through a bus reset, to allow
+ * the to take whatever actions required.
+ */
+static void nodemgr_update_node(struct node_entry *ne, quadlet_t busoptions,
+ struct hpsb_host *host, nodeid_t nodeid)
+{
+ struct list_head *lh;
+
+ if (ne->nodeid != nodeid)
HPSB_DEBUG("Node " NODE_BUS_FMT " changed to " NODE_BUS_FMT,
NODE_BUS_ARGS(ne->nodeid), NODE_BUS_ARGS(nodeid));
ne->host = host;
- ne->nodeid = nodeid;
+ ne->nodeid = nodeid;
- /* Now set the bus options. Only do all this crap if this is a new
- * node, or if the generation number has changed. */
- if (new || ne->busopt.generation != ((busoptions >> 6) & 0x3)) {
- ne->busopt.irmc = (busoptions >> 31) & 1;
- ne->busopt.cmc = (busoptions >> 30) & 1;
- ne->busopt.isc = (busoptions >> 29) & 1;
- ne->busopt.bmc = (busoptions >> 28) & 1;
- ne->busopt.pmc = (busoptions >> 27) & 1;
- ne->busopt.cyc_clk_acc = (busoptions >> 16) & 0xff;
- ne->busopt.max_rec = 1 << (((busoptions >> 12) & 0xf) + 1);
- ne->busopt.generation = (busoptions >> 6) & 0x3;
- ne->busopt.lnkspd = busoptions & 0x7;
-
- /* Now, process the rest of the tree */
- nodemgr_process_root_directory(ne);
- }
+ if (ne->busopt.generation != ((busoptions >> 4) & 0xf))
+ nodemgr_process_config_rom (ne, busoptions);
/* Since that's done, we can declare this record current */
- atomic_set(&ne->generation, get_hpsb_generation(host));
+ atomic_set(&ne->generation, get_hpsb_generation(ne->host));
+
+ list_for_each (lh, &ne->unit_directories) {
+ struct unit_directory *ud;
+
+ ud = list_entry (lh, struct unit_directory, node_list);
+ if (ud->driver != NULL && ud->driver->update != NULL)
+ ud->driver->update(ud);
+ }
+}
+
+static int read_businfo_block(struct hpsb_host *host, nodeid_t nodeid,
+ quadlet_t *buffer, int buffer_length)
+{
+ octlet_t base = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
+ int retries = 3;
+ int header_count;
+ unsigned header_size;
+ quadlet_t quad;
+
+retry_configrom:
+
+ if (!retries--) {
+ HPSB_ERR("Giving up on node " NODE_BUS_FMT
+ " for ConfigROM probe, too many errors",
+ NODE_BUS_ARGS(nodeid));
+ return -1;
+ }
+
+ header_count = 0;
+ header_size = 0;
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
- HPSB_DEBUG("raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d cyc_clk_acc=%d "
- "max_rec=%d gen=%d lspd=%d", busoptions,
- ne->busopt.irmc, ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc,
- ne->busopt.pmc, ne->busopt.cyc_clk_acc, ne->busopt.max_rec,
- ne->busopt.generation, ne->busopt.lnkspd);
+ HPSB_INFO("Initiating ConfigROM request for node " NODE_BUS_FMT,
+ NODE_BUS_ARGS(nodeid));
#endif
- return;
+ /* Now, P1212 says that devices should support 64byte block
+ * reads, aligned on 64byte boundaries. That doesn't seem
+ * to work though, and we are forced to doing quadlet
+ * sized reads. */
+
+ if (hpsb_read(host, nodeid, base, &quad, 4)) {
+ HPSB_ERR("ConfigROM quadlet transaction error for node " NODE_BUS_FMT,
+ NODE_BUS_ARGS(nodeid));
+ goto retry_configrom;
+ }
+ buffer[header_count++] = be32_to_cpu(quad);
+
+ header_size = buffer[0] >> 24;
+
+ if (header_size < 4) {
+ HPSB_INFO("Node " NODE_BUS_FMT " has non-standard ROM format (%d quads), "
+ "cannot parse", NODE_BUS_ARGS(nodeid), header_size);
+ return -1;
+ }
+
+ while (header_count <= header_size && header_count < buffer_length) {
+ if (hpsb_read(host, nodeid, base + (header_count<<2), &quad, 4)) {
+ HPSB_ERR("ConfigROM quadlet transaction error for " NODE_BUS_FMT,
+ NODE_BUS_ARGS(nodeid));
+ goto retry_configrom;
+ }
+ buffer[header_count++] = be32_to_cpu(quad);
+ }
+
+ return 0;
}
static void nodemgr_remove_node(struct node_entry *ne)
{
- HPSB_DEBUG("Device removed: node " NODE_BUS_FMT ", GUID "
- "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
- NODE_BUS_ARGS(ne->nodeid),
- ((u8 *)&ne->guid)[0], ((u8 *)&ne->guid)[1],
- ((u8 *)&ne->guid)[2], ((u8 *)&ne->guid)[3],
- ((u8 *)&ne->guid)[4], ((u8 *)&ne->guid)[5],
- ((u8 *)&ne->guid)[6], ((u8 *)&ne->guid)[7]);
+ unsigned long flags;
+
+ HPSB_DEBUG("Device removed: node " NODE_BUS_FMT ", GUID %016Lx",
+ NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid);
+ write_lock_irqsave(&unit_directory_lock, flags);
+ nodemgr_free_unit_directories(ne);
+ write_unlock_irqrestore(&unit_directory_lock, flags);
list_del(&ne->list);
kfree(ne);
@@ -352,82 +690,26 @@ static void nodemgr_node_probe(void *data)
{
struct hpsb_host *host = (struct hpsb_host *)data;
struct selfid *sid = (struct selfid *)host->topology_map;
- struct list_head *lh,*spare;
+ struct list_head *lh, *next;
struct node_entry *ne;
int nodecount = host->node_count;
nodeid_t nodeid = LOCAL_BUS;
- quadlet_t buffer[5], quad;
- octlet_t base = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
+ quadlet_t buffer[5];
+ octlet_t guid;
unsigned long flags;
/* We need to detect when the ConfigROM's generation has changed,
* so we only update the node's info when it needs to be. */
for (; nodecount; nodecount--, nodeid++, sid++) {
- int retries = 3;
- int header_count;
- unsigned header_size;
- octlet_t guid;
-
/* Skip extended, and non-active node's */
while (sid->extended)
sid++;
if (!sid->link_active)
continue;
- /* Just use our local ROM */
- if (nodeid == host->node_id) {
- int i;
- for (i = 0; i < 5; i++)
- buffer[i] = be32_to_cpu(host->csr.rom[i]);
- goto set_options;
- }
-
-retry_configrom:
-
- if (!retries--) {
- HPSB_ERR("Giving up on node " NODE_BUS_FMT
- " for ConfigROM probe, too many errors",
- NODE_BUS_ARGS(nodeid));
+ if (read_businfo_block (host, nodeid, buffer, sizeof(buffer) >> 2))
continue;
- }
- header_count = 0;
- header_size = 0;
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
- HPSB_INFO("Initiating ConfigROM request for node " NODE_BUS_FMT,
- NODE_BUS_ARGS(nodeid));
-#endif
-
- /* Now, P1212 says that devices should support 64byte block
- * reads, aligned on 64byte boundaries. That doesn't seem
- * to work though, and we are forced to doing quadlet
- * sized reads. */
-
- if (hpsb_read(host, nodeid, base, &quad, 4)) {
- HPSB_ERR("ConfigROM quadlet transaction error for node " NODE_BUS_FMT,
- NODE_BUS_ARGS(nodeid));
- goto retry_configrom;
- }
- buffer[header_count++] = be32_to_cpu(quad);
-
- header_size = buffer[0] >> 24;
-
- if (header_size < 4) {
- HPSB_INFO("Node " NODE_BUS_FMT " has non-standard ROM format (%d quads), "
- "cannot parse", NODE_BUS_ARGS(nodeid), header_size);
- continue;
- }
-
- while (header_count <= header_size && (header_count<<2) < sizeof(buffer)) {
- if (hpsb_read(host, nodeid, base + (header_count<<2), &quad, 4)) {
- HPSB_ERR("ConfigROM quadlet transaction error for " NODE_BUS_FMT,
- NODE_BUS_ARGS(nodeid));
- goto retry_configrom;
- }
- buffer[header_count++] = be32_to_cpu(quad);
- }
-set_options:
if (buffer[1] != IEEE1394_BUSID_MAGIC) {
/* This isn't a 1394 device */
HPSB_ERR("Node " NODE_BUS_FMT " isn't an IEEE 1394 device",
@@ -435,15 +717,21 @@ set_options:
continue;
}
- guid = be64_to_cpu(((u64)buffer[3] << 32) | buffer[4]);
- register_node(host, nodeid, guid, buffer[2]);
+ guid = ((u64)buffer[3] << 32) | buffer[4];
+ ne = hpsb_guid_get_entry(guid);
+
+ if (!ne)
+ nodemgr_create_node(guid, buffer[2], host, nodeid);
+ else
+ nodemgr_update_node(ne, buffer[2], host, nodeid);
}
/* Now check to see if we have any nodes that aren't referenced
* any longer. */
write_lock_irqsave(&node_lock, flags);
- list_for_each_safe(lh, spare, &node_list) {
+ for (lh = node_list.next; lh != &node_list; lh = next) {
ne = list_entry(lh, struct node_entry, list);
+ next = lh->next;
/* Only checking this host */
if (ne->host != host)
@@ -453,7 +741,7 @@ set_options:
* node was removed, or it failed the above probe. Either
* way, we remove references to it, since they are
* invalid. */
- if (atomic_read(&ne->generation) != get_hpsb_generation(host))
+ if (!hpsb_node_entry_valid(ne))
nodemgr_remove_node(ne);
}
write_unlock_irqrestore(&node_lock, flags);
@@ -511,7 +799,7 @@ static void nodemgr_add_host(struct hpsb_host *host)
unsigned long flags;
if (!hi) {
- HPSB_ERR ("Out of memory in Node Manager");
+ HPSB_ERR ("NodeMgr: out of memory in add host");
return;
}
@@ -544,7 +832,7 @@ static void nodemgr_host_reset(struct hpsb_host *host)
}
if (hi == NULL) {
- HPSB_ERR ("Could not process reset of non-existent host in Node Manager");
+ HPSB_ERR ("NodeMgr: could not process reset of non-existent host");
goto done_reset_host;
}
@@ -558,8 +846,7 @@ done_reset_host:
static void nodemgr_remove_host(struct hpsb_host *host)
{
- struct list_head *lh;
- struct host_info *hi = NULL;
+ struct list_head *lh, *next;
struct node_entry *ne;
unsigned long flags;
@@ -568,8 +855,10 @@ static void nodemgr_remove_host(struct hpsb_host *host)
/* First remove all node entries for this host */
write_lock_irqsave(&node_lock, flags);
- list_for_each(lh, &node_list) {
+
+ for (lh = node_list.next; lh != &node_list; lh = next) {
ne = list_entry(lh, struct node_entry, list);
+ next = lh->next;
/* Only checking this host */
if (ne->host != host)
@@ -581,22 +870,17 @@ static void nodemgr_remove_host(struct hpsb_host *host)
spin_lock_irqsave (&host_info_lock, flags);
list_for_each(lh, &host_info_list) {
- struct host_info *myhi = list_entry(lh, struct host_info, list);
- if (myhi->host == host) {
- hi = myhi;
+ struct host_info *hi = list_entry(lh, struct host_info, list);
+ if (hi->host == host) {
+ list_del(&hi->list);
+ kfree (hi);
break;
}
}
- if (hi == NULL) {
- HPSB_ERR ("Could not remove non-existent host in Node Manager");
- goto done_remove_host;
- }
-
- list_del(&hi->list);
- kfree (hi);
+ if (lh == host_info_list.next)
+ HPSB_ERR ("NodeMgr: could not remove non-existent host");
-done_remove_host:
spin_unlock_irqrestore (&host_info_lock, flags);
return;
@@ -614,7 +898,7 @@ void init_ieee1394_nodemgr(void)
{
hl = hpsb_register_highlevel("Node manager", &nodemgr_ops);
if (!hl) {
- HPSB_ERR("Out of memory during ieee1394 initialization");
+ HPSB_ERR("NodeMgr: out of memory during ieee1394 initialization");
}
}
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index 7d91a1a7ccbe..46f574e64155 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -38,13 +38,23 @@ struct bus_options {
u16 max_rec; /* Maximum packet size node can receive */
};
-#define UNIT_DIRECTORY_VENDOR_ID 0x01
-#define UNIT_DIRECTORY_MODEL_ID 0x02
-#define UNIT_DIRECTORY_SPECIFIER_ID 0x04
-#define UNIT_DIRECTORY_VERSION 0x08
+#define UNIT_DIRECTORY_VENDOR_ID 0x01
+#define UNIT_DIRECTORY_MODEL_ID 0x02
+#define UNIT_DIRECTORY_SPECIFIER_ID 0x04
+#define UNIT_DIRECTORY_VERSION 0x08
+/*
+ * A unit directory corresponds to a protocol supported by the
+ * node. If a node supports eg. IP/1394 and AV/C, its config rom has a
+ * unit directory for each of these protocols.
+ *
+ * Unit directories appear on two types of lists: for each node we
+ * maintain a list of the unit directories found in its config rom and
+ * for each driver we maintain a list of the unit directories
+ * (ie. devices) the driver manages.
+ */
struct unit_directory {
- struct list_head list;
+ struct node_entry *ne; /* The node which this directory belongs to */
octlet_t address; /* Address of the unit directory on the node */
u8 flags; /* Indicates which entries were read */
quadlet_t vendor_id;
@@ -53,6 +63,20 @@ struct unit_directory {
char *model_name;
quadlet_t specifier_id;
quadlet_t version;
+
+ /* Groupings for arbitrary key/value pairs */
+ int arb_count; /* Number of arbitrary key/values */
+ char arb_keys[16]; /* Up to 16 keys */
+ quadlet_t arb_values[16]; /* Same for values */
+
+ struct hpsb_protocol_driver *driver;
+ void *driver_data;
+
+ /* For linking the nodes managed by the driver, or unmanaged nodes */
+ struct list_head driver_list;
+
+ /* For linking directories belonging to a node */
+ struct list_head node_list;
};
struct node_entry {
@@ -69,6 +93,11 @@ struct node_entry {
struct list_head unit_directories;
};
+static inline int hpsb_node_entry_valid(struct node_entry *ne)
+{
+ return atomic_read(&ne->generation) == get_hpsb_generation(ne->host);
+}
+
/*
* Returns a node entry (which has its reference count incremented) or NULL if
* the GUID in question is not known. Getting a valid entry does not mean that
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 8c68f145bdcb..88c9e4bd91ce 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -105,6 +105,17 @@
#include <linux/vmalloc.h>
#include <linux/init.h>
+#ifdef CONFIG_ALL_PPC
+#include <asm/feature.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#endif
+
+/* Revert to old bus reset algorithm that works on my Pismo until
+ * the new one is fixed
+ */
+#undef BUSRESET_WORKAROUND
+
#include "ieee1394.h"
#include "ieee1394_types.h"
#include "hosts.h"
@@ -112,7 +123,6 @@
#include "highlevel.h"
#include "ohci1394.h"
-
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
#define OHCI1394_DEBUG
#endif
@@ -123,17 +133,17 @@
#ifdef OHCI1394_DEBUG
#define DBGMSG(card, fmt, args...) \
-printk(KERN_INFO "ohci1394_%d: " fmt "\n" , card , ## args)
+printk(KERN_INFO "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
#else
#define DBGMSG(card, fmt, args...)
#endif
#ifdef CONFIG_IEEE1394_OHCI_DMA_DEBUG
#define OHCI_DMA_ALLOC(fmt, args...) \
- HPSB_ERR("ohci1394("__FUNCTION__")alloc(%d): "fmt, \
+ HPSB_ERR("%s("__FUNCTION__")alloc(%d): "fmt, OHCI1394_DRIVER_NAME, \
++global_outstanding_dmas, ## args)
#define OHCI_DMA_FREE(fmt, args...) \
- HPSB_ERR("ohci1394("__FUNCTION__")free(%d): "fmt, \
+ HPSB_ERR("%s("__FUNCTION__")free(%d): "fmt, OHCI1394_DRIVER_NAME, \
--global_outstanding_dmas, ## args)
u32 global_outstanding_dmas = 0;
#else
@@ -143,18 +153,11 @@ u32 global_outstanding_dmas = 0;
/* print general (card independent) information */
#define PRINT_G(level, fmt, args...) \
-printk(level "ohci1394: " fmt "\n" , ## args)
+printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
/* print card specific information */
#define PRINT(level, card, fmt, args...) \
-printk(level "ohci1394_%d: " fmt "\n" , card , ## args)
-
-#define FAIL(fmt, args...) \
-do { \
- PRINT_G(KERN_ERR, fmt , ## args); \
- remove_card(ohci); \
- return 1; \
-} while(0)
+printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
#define PCI_CLASS_FIREWIRE_OHCI ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10)
@@ -179,21 +182,48 @@ MODULE_PARM(attempt_root,"i");
MODULE_PARM_DESC(attempt_root, "Attempt to make the host root.");
static int attempt_root = 0;
-#ifdef __LITTLE_ENDIAN
-/* Don't waste cycles on same sex byte swaps */
-#define packet_swab(w,x,y,z)
-#define block_swab32(x,y)
-#else
-static void packet_swab(quadlet_t *data, char tcode, int len, int payload_swap);
-static __inline__ void block_swab32(quadlet_t *data, size_t size);
-#endif
-
static unsigned int card_id_counter = 0;
static void dma_trm_tasklet(unsigned long data);
static void remove_card(struct ti_ohci *ohci);
static void dma_trm_reset(struct dma_trm_ctx *d);
+#ifndef __LITTLE_ENDIAN
+/* Swap a series of quads inplace. */
+static __inline__ void block_swab32(quadlet_t *data, size_t size) {
+ while (size--)
+ data[size] = swab32(data[size]);
+}
+
+static unsigned hdr_sizes[] =
+{
+ 3, /* TCODE_WRITEQ */
+ 4, /* TCODE_WRITEB */
+ 3, /* TCODE_WRITE_RESPONSE */
+ 0, /* ??? */
+ 3, /* TCODE_READQ */
+ 4, /* TCODE_READB */
+ 3, /* TCODE_READQ_RESPONSE */
+ 4, /* TCODE_READB_RESPONSE */
+ 1, /* TCODE_CYCLE_START (???) */
+ 4, /* TCODE_LOCK_REQUEST */
+ 2, /* TCODE_ISO_DATA */
+ 4, /* TCODE_LOCK_RESPONSE */
+};
+
+/* Swap headers */
+static inline void packet_swab(quadlet_t *data, int tcode, int len)
+{
+ if (tcode > TCODE_LOCK_RESPONSE || hdr_sizes[tcode] == 0)
+ return;
+ block_swab32(data, hdr_sizes[tcode]);
+}
+#else
+/* Don't waste cycles on same sex byte swaps */
+#define packet_swab(w,x,y)
+#define block_swab32(x,y)
+#endif /* !LITTLE_ENDIAN */
+
/***********************************
* IEEE-1394 functionality section *
***********************************/
@@ -230,7 +260,7 @@ static void set_phy_reg(struct ti_ohci *ohci, u8 addr, u8 data)
{
int i;
unsigned long flags;
- u32 r;
+ u32 r = 0;
spin_lock_irqsave (&ohci->phy_reg_lock, flags);
@@ -376,7 +406,7 @@ static int run_context(struct ti_ohci *ohci, int reg, char *msg)
}
/* Generate the dma receive prgs and start the context */
-static void initialize_dma_rcv_ctx(struct dma_rcv_ctx *d)
+static void initialize_dma_rcv_ctx(struct dma_rcv_ctx *d, int generate_irq)
{
struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
int i;
@@ -384,12 +414,17 @@ static void initialize_dma_rcv_ctx(struct dma_rcv_ctx *d)
ohci1394_stop_context(ohci, d->ctrlClear, NULL);
for (i=0; i<d->num_desc; i++) {
+ u32 c;
- d->prg_cpu[i]->control =
- cpu_to_le32((0x280C << 16) | d->buf_size);
+ c = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
+ DMA_CTL_BRANCH;
+ if (generate_irq)
+ c |= DMA_CTL_IRQ;
+
+ d->prg_cpu[i]->control = cpu_to_le32(c | d->buf_size);
/* End of descriptor list? */
- if ((i+1) < d->num_desc) {
+ if (i + 1 < d->num_desc) {
d->prg_cpu[i]->branchAddress =
cpu_to_le32((d->prg_bus[i+1] & 0xfffffff0) | 0x1);
} else {
@@ -565,15 +600,15 @@ static int ohci_initialize(struct hpsb_host *host)
reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff);
/* Initialize AR dma */
- initialize_dma_rcv_ctx(ohci->ar_req_context);
- initialize_dma_rcv_ctx(ohci->ar_resp_context);
+ initialize_dma_rcv_ctx(ohci->ar_req_context, 0);
+ initialize_dma_rcv_ctx(ohci->ar_resp_context, 0);
/* Initialize AT dma */
initialize_dma_trm_ctx(ohci->at_req_context);
initialize_dma_trm_ctx(ohci->at_resp_context);
/* Initialize IR dma */
- initialize_dma_rcv_ctx(ohci->ir_context);
+ initialize_dma_rcv_ctx(ohci->ir_context, 1);
/* Initialize IT dma */
initialize_dma_trm_ctx(ohci->it_context);
@@ -604,7 +639,6 @@ static int ohci_initialize(struct hpsb_host *host)
/* Enable interrupts */
reg_write(ohci, OHCI1394_IntMaskSet,
OHCI1394_masterIntEnable |
- OHCI1394_phyRegRcvd |
OHCI1394_busReset |
OHCI1394_selfIDComplete |
OHCI1394_RSPkt |
@@ -674,9 +708,9 @@ static void insert_packet(struct ti_ohci *ohci,
} else
d->prg_cpu[idx]->begin.status = 0;
- if ( (packet->type == async) || (packet->type == raw) ) {
+ if ( (packet->type == hpsb_async) || (packet->type == hpsb_raw) ) {
- if (packet->type == raw) {
+ if (packet->type == hpsb_raw) {
d->prg_cpu[idx]->data[0] = cpu_to_le32(OHCI1394_TCODE_PHY<<4);
d->prg_cpu[idx]->data[1] = packet->header[0];
d->prg_cpu[idx]->data[2] = packet->header[1];
@@ -689,14 +723,18 @@ static void insert_packet(struct ti_ohci *ohci,
d->prg_cpu[idx]->data[2] = packet->header[2];
d->prg_cpu[idx]->data[3] = packet->header[3];
packet_swab(d->prg_cpu[idx]->data, packet->tcode,
- packet->header_size>>2, ohci->payload_swap);
+ packet->header_size>>2);
}
if (packet->data_size) { /* block transmit */
d->prg_cpu[idx]->begin.control =
- cpu_to_le32(OUTPUT_MORE_IMMEDIATE | 0x10);
+ cpu_to_le32(DMA_CTL_OUTPUT_MORE |
+ DMA_CTL_IMMEDIATE | 0x10);
d->prg_cpu[idx]->end.control =
- cpu_to_le32(OUTPUT_LAST | packet->data_size);
+ cpu_to_le32(DMA_CTL_OUTPUT_LAST |
+ DMA_CTL_IRQ |
+ DMA_CTL_BRANCH |
+ packet->data_size);
/*
* Check that the packet data buffer
* does not cross a page boundary.
@@ -716,9 +754,6 @@ static void insert_packet(struct ti_ohci *ohci,
PCI_DMA_TODEVICE));
OHCI_DMA_ALLOC("single, block transmit packet");
- if (ohci->payload_swap)
- block_swab32(packet->data, packet->data_size >> 2);
-
d->prg_cpu[idx]->end.branchAddress = 0;
d->prg_cpu[idx]->end.status = 0;
if (d->branchAddrPtr)
@@ -727,14 +762,20 @@ static void insert_packet(struct ti_ohci *ohci,
d->branchAddrPtr =
&(d->prg_cpu[idx]->end.branchAddress);
} else { /* quadlet transmit */
- if (packet->type == raw)
- d->prg_cpu[idx]->begin.control = cpu_to_le32(
- OUTPUT_LAST_IMMEDIATE |
- (packet->header_size+4));
+ if (packet->type == hpsb_raw)
+ d->prg_cpu[idx]->begin.control =
+ cpu_to_le32(DMA_CTL_OUTPUT_LAST |
+ DMA_CTL_IMMEDIATE |
+ DMA_CTL_IRQ |
+ DMA_CTL_BRANCH |
+ (packet->header_size + 4));
else
- d->prg_cpu[idx]->begin.control = cpu_to_le32(
- OUTPUT_LAST_IMMEDIATE |
- packet->header_size);
+ d->prg_cpu[idx]->begin.control =
+ cpu_to_le32(DMA_CTL_OUTPUT_LAST |
+ DMA_CTL_IMMEDIATE |
+ DMA_CTL_IRQ |
+ DMA_CTL_BRANCH |
+ packet->header_size);
if (d->branchAddrPtr)
*(d->branchAddrPtr) =
@@ -747,20 +788,22 @@ static void insert_packet(struct ti_ohci *ohci,
d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |
(packet->header[0] & 0xFFFF);
d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000;
- packet_swab(d->prg_cpu[idx]->data, packet->tcode, packet->header_size>>2,
- ohci->payload_swap);
+ packet_swab(d->prg_cpu[idx]->data, packet->tcode, packet->header_size>>2);
- d->prg_cpu[idx]->begin.control = cpu_to_le32(OUTPUT_MORE_IMMEDIATE | 0x8);
- d->prg_cpu[idx]->end.control = cpu_to_le32(
- OUTPUT_LAST | 0x08000000 | packet->data_size);
+ d->prg_cpu[idx]->begin.control =
+ cpu_to_le32(DMA_CTL_OUTPUT_MORE |
+ DMA_CTL_IMMEDIATE | 0x8);
+ d->prg_cpu[idx]->end.control =
+ cpu_to_le32(DMA_CTL_OUTPUT_LAST |
+ DMA_CTL_UPDATE |
+ DMA_CTL_IRQ |
+ DMA_CTL_BRANCH |
+ packet->data_size);
d->prg_cpu[idx]->end.address = cpu_to_le32(
pci_map_single(ohci->dev, packet->data,
packet->data_size, PCI_DMA_TODEVICE));
OHCI_DMA_ALLOC("single, iso transmit packet");
- if (ohci->payload_swap)
- block_swab32(packet->data, packet->data_size>>2);
-
d->prg_cpu[idx]->end.branchAddress = 0;
d->prg_cpu[idx]->end.status = 0;
DBGMSG(ohci->id, "Iso xmit context info: header[%08x %08x]\n"
@@ -947,7 +990,7 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
if (arg<0 || arg>63) {
PRINT(KERN_ERR, ohci->id, __FUNCTION__
- "IS0 listne channel %d is out of range",
+ "IS0 listen channel %d is out of range",
arg);
return -EFAULT;
}
@@ -1083,13 +1126,16 @@ static void ohci_irq_handler(int irq, void *dev_id,
int phyid = -1, isroot = 0;
unsigned long flags;
- /* Read the interrupt event register. We don't clear the bus reset
- * here. We wait till we get a selfid complete interrupt and clear
- * it then, and _only_ then. */
+ /* Read and clear the interrupt event register. Don't clear
+ * the busReset event, though, this is done when we get the
+ * selfIDComplete interrupt. */
spin_lock_irqsave(&ohci->event_lock, flags);
event = reg_read(ohci, OHCI1394_IntEventClear);
- reg_write(ohci, OHCI1394_IntEventClear,
- event & ~(OHCI1394_selfIDComplete | OHCI1394_busReset));
+#ifdef BUSRESET_WORKAROUND
+ reg_write(ohci, OHCI1394_IntEventClear, event);
+#else
+ reg_write(ohci, OHCI1394_IntEventClear, event & ~OHCI1394_busReset);
+#endif
spin_unlock_irqrestore(&ohci->event_lock, flags);
if (!event) return;
@@ -1103,24 +1149,26 @@ static void ohci_irq_handler(int irq, void *dev_id,
return;
}
- /* Someone wants a bus reset. Better watch what you wish for... */
if (event & OHCI1394_busReset) {
+ /* The busReset event bit can't be cleared during the
+ * selfID phase, so we disable busReset interrupts, to
+ * avoid burying the cpu in interrupt requests. */
+ spin_lock_irqsave(&ohci->event_lock, flags);
+#ifdef BUSRESET_WORKAROUND
+ reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
+#else
+ reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset);
+#endif
+ spin_unlock_irqrestore(&ohci->event_lock, flags);
if (!host->in_bus_reset) {
DBGMSG(ohci->id, "irq_handler: Bus reset requested%s",
((host->attempt_root || attempt_root) ?
" and attempting to become root" : ""));
-
- /* Wait for the AT fifo to be flushed */
- dma_trm_reset(ohci->at_req_context);
- dma_trm_reset(ohci->at_resp_context);
/* Subsystem call */
hpsb_bus_reset(ohci->host);
-
- ohci->NumBusResets++;
}
- /* Mask out everything except selfid */
- event &= OHCI1394_selfIDComplete;
+ event &= ~OHCI1394_busReset;
}
/* XXX: We need a way to also queue the OHCI1394_reqTxComplete,
@@ -1234,11 +1282,12 @@ static void ohci_irq_handler(int irq, void *dev_id,
handle_selfid(ohci, host,
phyid, isroot);
- } else
+ } else {
PRINT(KERN_ERR, ohci->id,
"SelfID interrupt received, but "
"NodeID is not valid: %08X",
node_id);
+ }
/* Accept Physical requests from all nodes. */
reg_write(ohci,OHCI1394_AsReqFilterHiSet,
@@ -1258,21 +1307,15 @@ static void ohci_irq_handler(int irq, void *dev_id,
PRINT(KERN_ERR, ohci->id,
"SelfID received outside of bus reset sequence");
- /* Clear everything, it's a new day */
+ /* Finally, we clear the busReset event and reenable
+ * the busReset interrupt. */
+#ifndef BUSRESET_WORKAROUND
spin_lock_irqsave(&ohci->event_lock, flags);
- reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
+ reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
+ reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
spin_unlock_irqrestore(&ohci->event_lock, flags);
-
- event &= ~OHCI1394_selfIDComplete;
- }
- if (event & OHCI1394_phyRegRcvd) {
- if (host->in_bus_reset) {
- DBGMSG (ohci->id, "PhyControl: %08X",
- reg_read(ohci, OHCI1394_PhyControl));
- } else
- PRINT(KERN_ERR, ohci->id,
- "Physical register received outside of bus reset sequence");
- event &= ~OHCI1394_phyRegRcvd;
+#endif
+ event &= ~OHCI1394_selfIDComplete;
}
/* Make sure we handle everything, just in case we accidentally
@@ -1365,14 +1408,14 @@ static void dma_rcv_tasklet (unsigned long data)
dma_cache_wback_inv(buf_ptr, bytes_left);
while (bytes_left > 0) {
- tcode = (cond_le32_to_cpu(buf_ptr[0], ohci->payload_swap) >> 4) & 0xf;
+ tcode = (cond_le32_to_cpu(buf_ptr[0], ohci->no_swap_incoming) >> 4) & 0xf;
/* packet_length() will return < 4 for an error */
- length = packet_length(d, idx, buf_ptr, offset, tcode, ohci->payload_swap);
+ length = packet_length(d, idx, buf_ptr, offset, tcode, ohci->no_swap_incoming);
if (length < 4) { /* something is wrong */
sprintf(msg,"Unexpected tcode 0x%x(0x%08x) in AR ctx=%d, length=%d",
- tcode, cond_le32_to_cpu(buf_ptr[0], ohci->payload_swap),
+ tcode, cond_le32_to_cpu(buf_ptr[0], ohci->no_swap_incoming),
d->ctx, length);
ohci1394_stop_context(ohci, d->ctrlClear, msg);
spin_unlock_irqrestore(&d->lock, flags);
@@ -1448,19 +1491,18 @@ static void dma_rcv_tasklet (unsigned long data)
/* We get one phy packet to the async descriptor for each
* bus reset. We always ignore it. */
if (tcode != OHCI1394_TCODE_PHY) {
- if (!ohci->payload_swap)
- packet_swab(d->spb, tcode, (length - 4) >> 2, 0);
-
+ if (!ohci->no_swap_incoming)
+ packet_swab(d->spb, tcode, (length - 4) >> 2);
DBGMSG(ohci->id, "Packet received from node"
" %d ack=0x%02X spd=%d tcode=0x%X"
" length=%d ctx=%d tlabel=%d",
(d->spb[1]>>16)&0x3f,
- (cond_le32_to_cpu(d->spb[length/4-1], ohci->payload_swap)>>16)&0x1f,
- (cond_le32_to_cpu(d->spb[length/4-1], ohci->payload_swap)>>21)&0x3,
+ (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f,
+ (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>21)&0x3,
tcode, length, d->ctx,
- (cond_le32_to_cpu(d->spb[length/4-1], ohci->payload_swap)>>10)&0x3f);
+ (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>10)&0x3f);
- ack = (((cond_le32_to_cpu(d->spb[length/4-1], ohci->payload_swap)>>16)&0x1f)
+ ack = (((cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f)
== 0x11) ? 1 : 0;
hpsb_packet_received(ohci->host, d->spb,
@@ -1510,7 +1552,7 @@ static void dma_trm_tasklet (unsigned long data)
while (d->fifo_first) {
packet = d->fifo_first;
datasize = d->fifo_first->data_size;
- if (datasize && packet->type != raw)
+ if (datasize && packet->type != hpsb_raw)
ack = le32_to_cpu(
d->prg_cpu[d->sent_ind]->end.status) >> 16;
else
@@ -2032,6 +2074,14 @@ static struct hpsb_host_template ohci_template = {
hw_csr_reg: ohci_hw_csr_reg,
};
+
+#define FAIL(fmt, args...) \
+do { \
+ PRINT_G(KERN_ERR, fmt , ## args); \
+ remove_card(ohci); \
+ return 1; \
+} while(0)
+
static int __devinit ohci1394_add_one(struct pci_dev *dev, const struct pci_device_id *ent)
{
struct ti_ohci *ohci; /* shortcut to currently handled device */
@@ -2075,10 +2125,10 @@ static int __devinit ohci1394_add_one(struct pci_dev *dev, const struct pci_devi
* noByteSwapData registers to see if they were not cleared to
* zero. Should this work? Obviously it's not defined what these
* registers will read when they aren't supported. Bleh! */
- if (dev->vendor == PCI_VENDOR_ID_APPLE) {
- ohci->payload_swap = 1;
- if (dev->device != PCI_DEVICE_ID_APPLE_UNI_N_FW)
- ohci->selfid_swap = 1;
+ if (dev->vendor == PCI_VENDOR_ID_APPLE &&
+ dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW) {
+ ohci->no_swap_incoming = 1;
+ ohci->selfid_swap = 0;
} else
ohci->selfid_swap = 1;
#endif
@@ -2248,6 +2298,23 @@ static void remove_card(struct ti_ohci *ohci)
release_mem_region (pci_resource_start(ohci->dev, 0),
pci_resource_len(ohci->dev, 0));
+#ifdef CONFIG_ALL_PPC
+ /* On UniNorth, power down the cable and turn off the
+ * chip clock when the module is removed to save power
+ * on laptops. Turning it back ON is done by the arch
+ * code when pci_enable_device() is called
+ */
+ {
+ struct device_node* of_node;
+
+ of_node = pci_device_to_OF_node(ohci->dev);
+ if (of_node) {
+ feature_set_firewire_power(of_node, 0);
+ feature_set_firewire_cable_power(of_node, 0);
+ }
+ }
+#endif /* CONFIG_ALL_PPC */
+
pci_set_drvdata(ohci->dev, NULL);
}
@@ -2292,68 +2359,6 @@ void ohci1394_unregister_video(struct ti_ohci *ohci,
}
}
-#ifndef __LITTLE_ENDIAN
-
-/* Swap a series of quads inplace. */
-static __inline__ void block_swab32(quadlet_t *data, size_t size) {
- while (size--)
- data[size] = swab32(data[size]);
-}
-
-/* Swap headers and sometimes data too */
-static void packet_swab(quadlet_t *data, char tcode, int len, int payload_swap)
-{
- if (payload_swap) {
- block_swab32(data, len);
- return;
- }
-
- switch(tcode)
- {
- /* 4 quad header */
- case TCODE_READB_RESPONSE:
- case TCODE_LOCK_RESPONSE:
- case TCODE_LOCK_REQUEST:
- case TCODE_WRITEB:
- case TCODE_READB:
- block_swab32(data, 4);
- break;
-
- /* 3 quad header, 1 quad payload */
- case TCODE_WRITEQ:
- case TCODE_READQ_RESPONSE:
- block_swab32(data, 3);
- break;
-
- /* 3 quad header */
- case TCODE_WRITE_RESPONSE:
- case TCODE_READQ:
- block_swab32(data, 3);
- break;
-
- /* 2 quad header */
- case TCODE_ISO_DATA:
- block_swab32(data, 2);
- break;
-
- case OHCI1394_TCODE_PHY:
- break; /* should never happen anyway */
-
- case TCODE_CYCLE_START:
- PRINT_G(KERN_ERR, "Unhandled tcode in packet_swab (0x%x)", tcode);
- /* Atleast swap one quad */
- block_swab32(data, 1);
- break;
- default:
- PRINT_G(KERN_ERR, "Invalid tcode in packet_swab (0x%x)", tcode);
- break;
- }
- return;
-}
-
-#endif /* !LITTLE_ENDIAN */
-
-
#if 0
int ohci1394_request_channel(struct ti_ohci *ohci, int channel)
{
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index 985ce439ec2e..3ab491270135 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -191,15 +191,14 @@ struct ti_ohci {
spinlock_t event_lock;
int self_id_errors;
- int NumBusResets;
/* video device */
struct video_template *video_tmpl;
/* Swap the selfid buffer? */
unsigned int selfid_swap:1;
- /* Swap the payload? */
- unsigned int payload_swap:1;
+ /* Some Apple chipset seem to swap incoming headers for us */
+ unsigned int no_swap_incoming:1;
};
static inline int cross_bound(unsigned long addr, unsigned int size)
@@ -332,14 +331,16 @@ static inline u32 reg_read(const struct ti_ohci *ohci, int offset)
#define OHCI1394_phyRegRcvd 0x04000000
#define OHCI1394_masterIntEnable 0x80000000
-#define OUTPUT_MORE 0x00000000
-#define OUTPUT_MORE_IMMEDIATE 0x02000000
-#define OUTPUT_LAST 0x103c0000
-#define OUTPUT_LAST_IMMEDIATE 0x123c0000
-
-#define DMA_SPEED_100 0x0
-#define DMA_SPEED_200 0x1
-#define DMA_SPEED_400 0x2
+/* DMA Control flags */
+#define DMA_CTL_OUTPUT_MORE 0x00000000
+#define DMA_CTL_OUTPUT_LAST 0x10000000
+#define DMA_CTL_INPUT_MORE 0x20000000
+#define DMA_CTL_INPUT_LAST 0x30000000
+#define DMA_CTL_UPDATE 0x08000000
+#define DMA_CTL_IMMEDIATE 0x02000000
+#define DMA_CTL_IRQ 0x00300000
+#define DMA_CTL_BRANCH 0x000c0000
+#define DMA_CTL_WAIT 0x00030000
#define OHCI1394_TCODE_PHY 0xE
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index ee7d5b99150c..815176c8fc1f 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -38,6 +38,7 @@
#include "ieee1394_types.h"
#include "hosts.h"
#include "ieee1394_core.h"
+#include "highlevel.h"
#include "pcilynx.h"
@@ -393,7 +394,7 @@ static void send_next(struct ti_lynx *lynx, int what)
struct lynx_send_data *d;
struct hpsb_packet *packet;
- d = (what == iso ? &lynx->iso_send : &lynx->async);
+ d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async);
packet = d->queue;
d->header_dma = pci_map_single(lynx->dev, packet->header,
@@ -419,13 +420,13 @@ static void send_next(struct ti_lynx *lynx, int what)
pcl.buffer[1].pointer = d->data_dma;
switch (packet->type) {
- case async:
+ case hpsb_async:
pcl.buffer[0].control |= PCL_CMD_XMT;
break;
- case iso:
+ case hpsb_iso:
pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE;
break;
- case raw:
+ case hpsb_raw:
pcl.buffer[0].control |= PCL_CMD_UNFXMT;
break;
}
@@ -606,11 +607,11 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
}
switch (packet->type) {
- case async:
- case raw:
+ case hpsb_async:
+ case hpsb_raw:
d = &lynx->async;
break;
- case iso:
+ case hpsb_iso:
d = &lynx->iso_send;
break;
default:
@@ -1227,7 +1228,7 @@ static void lynx_irq_handler(int irq, void *dev_id,
}
if (lynx->async.queue != NULL) {
- send_next(lynx, async);
+ send_next(lynx, hpsb_async);
}
spin_unlock(&lynx->async.queue_lock);
@@ -1259,7 +1260,7 @@ static void lynx_irq_handler(int irq, void *dev_id,
}
if (lynx->iso_send.queue != NULL) {
- send_next(lynx, iso);
+ send_next(lynx, hpsb_iso);
}
spin_unlock(&lynx->iso_send.queue_lock);
@@ -1368,7 +1369,7 @@ static int __devinit add_card(struct pci_dev *dev,
FAIL("failed to allocate host structure");
lynx->state = have_host_struct;
-
+ lynx->host->hostdata = lynx;
lynx->id = num_of_cards-1;
lynx->dev = dev;
lynx->host->pdev = dev;
@@ -1501,6 +1502,9 @@ static int __devinit add_card(struct pci_dev *dev,
PRINT(KERN_INFO, lynx->id, "found old 1394 PHY");
}
+ /* Tell the highlevel this host is ready */
+ highlevel_add_one_host (lynx->host);
+
return 0;
#undef FAIL
}
@@ -1633,8 +1637,8 @@ MODULE_DEVICE_TABLE(pci, pci_table);
static void __exit pcilynx_cleanup(void)
{
- pci_unregister_driver(&lynx_pcidriver);
hpsb_unregister_lowlevel(&lynx_template);
+ pci_unregister_driver(&lynx_pcidriver);
PRINT_G(KERN_INFO, "removed " PCILYNX_DRIVER_NAME " module");
}
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 03a72ab10eb3..903ddbcb7755 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -290,8 +290,11 @@ static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data,
}
spin_unlock_irqrestore(&host_info_lock, flags);
- list_for_each(lh, &reqs) {
+ lh = reqs.next;
+ while (lh != &reqs) {
req = list_entry(lh, struct pending_request, list);
+ lh = lh->next;
+
queue_complete_req(req);
}
}
@@ -356,8 +359,11 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
}
spin_unlock_irqrestore(&host_info_lock, flags);
- list_for_each(lh, &reqs) {
+ lh = reqs.next;
+ while (lh != &reqs) {
req = list_entry(lh, struct pending_request, list);
+ lh = lh->next;
+
queue_complete_req(req);
}
}
@@ -746,6 +752,8 @@ static int handle_remote_request(struct file_info *fi,
list_add_tail(&req->list, &fi->req_pending);
spin_unlock_irq(&fi->reqlists_lock);
+ packet->generation = req->req.generation;
+
if (!hpsb_send_packet(packet)) {
req->req.error = RAW1394_ERROR_SEND_ERROR;
req->req.length = 0;
@@ -766,7 +774,7 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req,
fill_iso_packet(packet, req->req.length, channel & 0x3f,
(req->req.misc >> 16) & 0x3, req->req.misc & 0xf);
- packet->type = iso;
+ packet->type = hpsb_iso;
packet->speed_code = req->req.address & 0x3;
packet->host = fi->host;
@@ -787,6 +795,9 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req,
list_add_tail(&req->list, &fi->req_pending);
spin_unlock_irq(&fi->reqlists_lock);
+ /* Update the generation of the packet just before sending. */
+ packet->generation = get_hpsb_generation(fi->host);
+
if (!hpsb_send_packet(packet)) {
req->req.error = RAW1394_ERROR_SEND_ERROR;
queue_complete_req(req);
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index a69131f98d82..594680253913 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -122,26 +122,14 @@
* are some stress issues under investigation with deserialized I/O. To enable
* deserialized I/O for testing, do "insmod sbp2 serialize_io=0"
*
- * - Hot-Plugging: Need to add procfs support and integration with linux
- * hot-plug support (http://linux-hotplug.sourceforge.net) for auto-mounting
- * of drives.
- *
* - Error Handling: SCSI aborts and bus reset requests are handled somewhat
* but the code needs additional debugging.
*
- * - IEEE-1394 Bus Management: There is currently little bus management
- * in the core IEEE-1394 stack. Because of this, the SBP-2 driver handles
- * detection of SBP-2 devices itself. This should be moved to the core
- * stack.
- *
* - The SBP-2 driver is currently only supported as a module. It would not take
* much work to allow it to be compiled into the kernel, but you'd have to
* add some init code to the kernel to support this... and modules are much
* more flexible anyway. ;-)
*
- * - Workaround for PPC pismo firewire chipset (enable SBP2_PPC_PISMO_WORKAROUND
- * define below).
- *
*
* History:
*
@@ -222,8 +210,18 @@
* <bcollins@debian.org
* 07/22/01 - Use NodeMngr to get info about the local host and
* attached devices. Ben Collins
+ *
+ * 09/15/01 - Remove detection code, instead subscribe to the nodemgr
+ * driver management interface. This also removes the
+ * initial bus scan stuff since the nodemgr calls
+ * sbp2_probe for each sbp2 device already on the bus,
+ * when we register our driver. This change
+ * automtically adds hotplug support to the driver.
+ * Kristian Hogsberg <hogsberg@users.sf.net>
*/
+
+
/*
* Includes
*/
@@ -264,50 +262,26 @@
#include "sbp2.h"
/*
- * PPC firewire Pismo chipset workaround!!!
- *
- * This is a workaround for a bug in the firewire pismo chipset. For some odd reason the status
- * fifo address hi/lo must be byteswapped and the response address byteswapped, but no other
- * parts of the structure. Apple's drivers seem to specifically check for the pismo and do
- * the same workaround for sbp2. (Daniel Berlin)
- *
- * Please enable the following define if you're running on the PPC Pismo chipset.
- */
-
-#ifdef CONFIG_IEEE1394_SBP2_PISMO
-#define SBP2_NEED_LOGIN_DESCRIPTOR_WORKAROUND
-#endif
-
-/*
* Module load parameter definitions
*/
/*
- * Normally the sbp2 driver tries to catch the initial scsi bus scan to pick up any
- * attached sbp2 devices. Setting no_bus_scan to 1 tells the sbp2 driver not to catch
- * this initial scsi bus scan on module load. You can always either add or remove devices
- * later through the rescan-scsi-bus.sh script or scsi procfs.
- */
-MODULE_PARM(no_bus_scan,"i");
-MODULE_PARM_DESC(no_bus_scan, "Skip the initial scsi bus scan during module load");
-static int no_bus_scan = 0;
-
-/*
- * Set mode_sense_hack to 1 if you have some sort of unusual sbp2 device, like a 1394 memory
- * stick reader, compact flash reader, or MO drive that does not support mode sense. Allows
- * you to mount the media rw instead of ro.
+ * Set mode_sense_hack to 1 if you have some sort of unusual sbp2 device,
+ * like a 1394 memory stick reader, compact flash reader, or MO drive that
+ * does not support mode sense. Allows you to mount the media rw instead
+ * of ro.
*/
MODULE_PARM(mode_sense_hack,"i");
MODULE_PARM_DESC(mode_sense_hack, "Emulate mode sense for devices like 1394 memory stick readers");
static int mode_sense_hack = 0;
/*
- * Change max_speed on module load if you have a bad IEEE-1394 controller that has trouble running
- * 2KB packets at 400mb.
+ * Change max_speed on module load if you have a bad IEEE-1394 controller
+ * that has trouble running 2KB packets at 400mb.
*
- * NOTE: On certain OHCI parts I have seen short packets on async transmit (probably
- * due to PCI latency/throughput issues with the part). You can bump down the speed if
- * you are running into problems.
+ * NOTE: On certain OHCI parts I have seen short packets on async transmit
+ * (probably due to PCI latency/throughput issues with the part). You can
+ * bump down the speed if you are running into problems.
*
* Valid values:
* max_speed = 2 (default: max speed 400mb)
@@ -319,30 +293,37 @@ MODULE_PARM_DESC(max_speed, "Force down max speed (2 = 400mb default, 1 = 200mb,
static int max_speed = SPEED_400;
/*
- * Set serialize_io to 1 if you'd like only one scsi command sent down to us at a time (debugging).
+ * Set serialize_io to 1 if you'd like only one scsi command sent down to
+ * us at a time (debugging).
*/
MODULE_PARM(serialize_io,"i");
MODULE_PARM_DESC(serialize_io, "Serialize all I/O coming down from the scsi drivers (debugging)");
static int serialize_io = 1; /* serialize I/O until stress issues are resolved */
/*
- * Set no_large_packets to 1 if you'd like to limit the size of requests sent down to us (normally
- * the sbp2 driver will break up any requests to any individual devices with 128KB transfer size limits).
- * Sets max s/g list elements to 0x1f in size and disables s/g clustering.
+ * Set no_large_packets to 1 if you'd like to limit the size of requests
+ * sent down to us (normally the sbp2 driver will break up any requests to
+ * any individual devices with 128KB transfer size limits). Sets max s/g
+ * list elements to 0x1f in size and disables s/g clustering.
*/
MODULE_PARM(no_large_packets,"i");
MODULE_PARM_DESC(no_large_packets, "Do not allow large transfers from scsi drivers (debugging)");
static int no_large_packets = 0;
/*
- * Export information about protocols/devices supported by this driver
+ * Export information about protocols/devices supported by this driver.
*/
static struct ieee1394_device_id sbp2_id_table[] = {
- IEEE1394_PROTOCOL(SBP2_UNIT_SPEC_ID_ENTRY, SBP2_SW_VERSION_ENTRY),
+ {
+ match_flags: IEEE1394_MATCH_SPECIFIER_ID |
+ IEEE1394_MATCH_VERSION,
+ specifier_id: SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff,
+ version: SBP2_SW_VERSION_ENTRY & 0xffffff
+ },
{ }
};
-MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);
+MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);
/*
* Debug levels, configured via kernel config.
@@ -372,6 +353,7 @@ static u32 global_outstanding_dmas = 0;
#define SBP2_DMA_FREE(fmt, args...)
#endif
+
#if CONFIG_IEEE1394_SBP2_DEBUG >= 2
#define SBP2_DEBUG(fmt, args...) HPSB_ERR(fmt, ## args)
#define SBP2_INFO(fmt, args...) HPSB_ERR(fmt, ## args)
@@ -392,12 +374,14 @@ static u32 global_outstanding_dmas = 0;
#define SBP2_ERR(fmt, args...) HPSB_ERR(fmt, ## args)
/*
- * Spinlock debugging stuff. I'm playing it safe until the driver has been debugged on SMP. (JSG)
+ * Spinlock debugging stuff. I'm playing it safe until the driver has been
+ * debugged on SMP. (JSG)
*/
/* #define SBP2_USE_REAL_SPINLOCKS */
#ifdef SBP2_USE_REAL_SPINLOCKS
#define sbp2_spin_lock(lock, flags) spin_lock_irqsave(lock, flags)
#define sbp2_spin_unlock(lock, flags) spin_unlock_irqrestore(lock, flags);
+static spinlock_t sbp2_host_info_lock = SPIN_LOCK_UNLOCKED;
#else
#define sbp2_spin_lock(lock, flags) do {save_flags(flags); cli();} while (0)
#define sbp2_spin_unlock(lock, flags) do {restore_flags(flags);} while (0)
@@ -411,28 +395,27 @@ Scsi_Host_Template *global_scsi_tpnt = NULL;
static LIST_HEAD(sbp2_host_info_list);
static int sbp2_host_count = 0;
-static spinlock_t sbp2_host_info_lock = SPIN_LOCK_UNLOCKED;
static struct hpsb_highlevel *sbp2_hl_handle = NULL;
static struct hpsb_highlevel_ops sbp2_hl_ops = {
- sbp2_add_host,
- sbp2_remove_host,
- sbp2_host_reset,
- NULL,
- NULL
+ add_host: sbp2_add_host,
+ remove_host: sbp2_remove_host,
};
static struct hpsb_address_ops sbp2_ops = {
- write: sbp2_handle_status_write,
+ write: sbp2_handle_status_write
};
-#if 0
-static struct hpsb_address_ops sbp2_physdma_ops = {
- read: sbp2_handle_physdma_read,
- write: sbp2_handle_physdma_write,
+static struct hpsb_protocol_driver sbp2_driver = {
+ name: "SBP2 Driver",
+ id_table: sbp2_id_table,
+ probe: sbp2_probe,
+ disconnect: sbp2_disconnect,
+ update: sbp2_update
};
-#endif
+
+
/**************************************
* General utility functions
@@ -472,108 +455,29 @@ static __inline__ void sbp2util_cpu_to_be32_buffer(void *buffer, int length)
#endif
/*
- * This function does quadlet sized reads (used by detection code)
- */
-static int sbp2util_read_quadlet(struct sbp2scsi_host_info *hi, nodeid_t node, u64 addr,
- quadlet_t *buffer)
-{
- int retval = 0;
- int retry_count = 3;
-
- /*
- * Retry a couple times if needed (for slow devices)
- */
- do {
-
- retval = hpsb_read(hi->host, node, addr, buffer, 4);
-
- if (retval) {
- SBP2_DEBUG("sbp2: sbp2util_read_quadlet data packet error");
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ/50); /* 20ms delay */
- }
-
- retry_count--;
-
- } while (retval && retry_count);
-
- return(retval);
-}
-
-/*
- * This function returns the address of the unit directory.
- */
-static int sbp2util_unit_directory(struct sbp2scsi_host_info *hi, nodeid_t node_id, u64 *unit_directory_addr)
-{
- quadlet_t root_directory_length, current_quadlet;
- u64 current_addr;
- int length, i;
-
- /*
- * First, read the first quadlet of the root directory to determine its size
- */
- if (sbp2util_read_quadlet(hi, LOCAL_BUS | node_id, CONFIG_ROM_ROOT_DIR_BASE,
- &root_directory_length)) {
- SBP2_DEBUG("sbp2: Error reading root directory length - bad status");
- return(-EIO);
- }
-
- current_addr = CONFIG_ROM_ROOT_DIR_BASE;
- length = be32_to_cpu(root_directory_length) >> 16;
-
- /*
- * Step through the root directory and look for the "Unit_Directory entry", which
- * contains the offset to the unit directory.
- */
- for (i=0; i < length; i++) {
-
- current_addr += 4;
-
- if (sbp2util_read_quadlet(hi, LOCAL_BUS | node_id, current_addr, &current_quadlet)) {
- SBP2_DEBUG("sbp2: Error reading at address 0x%08x%08x - bad status",
- (unsigned int) ((current_addr) >> 32), (unsigned int) ((current_addr) & 0xffffffff));
- return(-EIO);
- }
-
- /*
- * Check for unit directory offset tag
- */
- if ((be32_to_cpu(current_quadlet) >> 24) == SBP2_UNIT_DIRECTORY_OFFSET_KEY) {
- *unit_directory_addr = current_addr + 4 * ((be32_to_cpu(current_quadlet) & 0xffffff));
- SBP2_DEBUG("sbp2: unit_directory_addr = %lu", *unit_directory_addr);
- }
- }
-
- return(0);
-}
-
-/*
- * This function is called to initially create a packet pool for use in sbp2 I/O requests.
- * This packet pool is used when sending out sbp2 command and agent reset requests, and
- * allows us to remove all kmallocs/kfrees from the critical I/O paths.
+ * This function is called to initially create a packet pool for use in
+ * sbp2 I/O requests. This packet pool is used when sending out sbp2
+ * command and agent reset requests, and allows us to remove all
+ * kmallocs/kfrees from the critical I/O paths.
*/
static int sbp2util_create_request_packet_pool(struct sbp2scsi_host_info *hi)
{
struct hpsb_packet *packet;
int i;
- unsigned long flags;
- /*
- * Create SBP2_MAX_REQUEST_PACKETS number of request packets.
- */
- sbp2_spin_lock(&hi->sbp2_request_packet_lock, flags);
+ /* Create SBP2_MAX_REQUEST_PACKETS number of request packets. */
for (i=0; i<SBP2_MAX_REQUEST_PACKETS; i++) {
/*
- * Max payload of 8 bytes since the sbp2 command request uses a payload of
- * 8 bytes, and agent reset is a quadlet write request. Bump this up if we
- * plan on using this pool for other stuff.
+ * Max payload of 8 bytes since the sbp2 command request
+ * uses a payload of 8 bytes, and agent reset is a quadlet
+ * write request. Bump this up if we plan on using this
+ * pool for other stuff.
*/
packet = alloc_hpsb_packet(8);
if (!packet) {
SBP2_ERR("sbp2: sbp2util_create_request_packet_pool - packet allocation failed!");
- sbp2_spin_unlock(&hi->sbp2_request_packet_lock, flags);
return(-ENOMEM);
}
@@ -585,13 +489,13 @@ static int sbp2util_create_request_packet_pool(struct sbp2scsi_host_info *hi)
list_add_tail(&hi->request_packet[i].list, &hi->sbp2_req_free);
}
- sbp2_spin_unlock(&hi->sbp2_request_packet_lock, flags);
return(0);
}
/*
- * This function is called to remove the packet pool. It is called when the sbp2 driver is unloaded.
+ * This function is called to remove the packet pool. It is called when
+ * the sbp2 driver is unloaded.
*/
static void sbp2util_remove_request_packet_pool(struct sbp2scsi_host_info *hi)
{
@@ -624,15 +528,17 @@ static void sbp2util_remove_request_packet_pool(struct sbp2scsi_host_info *hi)
}
/*
- * This function is called to retrieve a block write packet from our packet pool. This function is
- * used in place of calling alloc_hpsb_packet (which costs us three kmallocs). Instead we
- * just pull out a free request packet and re-initialize values in it. I'm sure this can still
- * stand some more optimization.
- */
-static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct sbp2scsi_host_info *hi,
- nodeid_t node, u64 addr,
- size_t data_size,
- quadlet_t data) {
+ * This function is called to retrieve a block write packet from our
+ * packet pool. This function is used in place of calling
+ * alloc_hpsb_packet (which costs us three kmallocs). Instead we just pull
+ * out a free request packet and re-initialize values in it. I'm sure this
+ * can still stand some more optimization.
+ */
+static struct sbp2_request_packet *
+sbp2util_allocate_write_request_packet(struct sbp2scsi_host_info *hi,
+ nodeid_t node, u64 addr,
+ size_t data_size,
+ quadlet_t data) {
struct list_head *lh;
struct sbp2_request_packet *request_packet = NULL;
struct hpsb_packet *packet;
@@ -651,13 +557,14 @@ static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct
packet = request_packet->packet;
/*
- * Initialize the packet (this is really initialization the core 1394 stack should do,
- * but I'm doing it myself to avoid the overhead).
+ * Initialize the packet (this is really initialization
+ * the core 1394 stack should do, but I'm doing it myself
+ * to avoid the overhead).
*/
packet->data_size = data_size;
INIT_LIST_HEAD(&packet->list);
sema_init(&packet->state_change, 0);
- packet->state = unused;
+ packet->state = hpsb_unused;
packet->generation = get_hpsb_generation(hi->host);
packet->data_be = 1;
@@ -672,8 +579,8 @@ static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct
}
/*
- * Set up a task queue completion routine, which returns the packet to the free list
- * and releases the tlabel
+ * Set up a task queue completion routine, which returns
+ * the packet to the free list and releases the tlabel.
*/
request_packet->tq.routine = (void (*)(void*))sbp2util_free_request_packet;
request_packet->tq.data = request_packet;
@@ -681,7 +588,7 @@ static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct
queue_task(&request_packet->tq, &packet->complete_tq);
/*
- * Now, put the packet on the in-use list
+ * Now, put the packet on the in-use list.
*/
list_add_tail(&request_packet->list, &hi->sbp2_req_inuse);
@@ -694,8 +601,8 @@ static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct
}
/*
- * This function is called to return a packet to our packet pool. It is also called as a
- * completion routine when a request packet is completed.
+ * This function is called to return a packet to our packet pool. It is
+ * also called as a completion routine when a request packet is completed.
*/
static void sbp2util_free_request_packet(struct sbp2_request_packet *request_packet)
{
@@ -703,7 +610,7 @@ static void sbp2util_free_request_packet(struct sbp2_request_packet *request_pac
struct sbp2scsi_host_info *hi = request_packet->hi_context;
/*
- * Free the tlabel, and return the packet to the free pool
+ * Free the tlabel, and return the packet to the free pool.
*/
sbp2_spin_lock(&hi->sbp2_request_packet_lock, flags);
free_tlabel(hi->host, LOCAL_BUS | request_packet->packet->node_id,
@@ -716,8 +623,8 @@ static void sbp2util_free_request_packet(struct sbp2_request_packet *request_pac
}
/*
- * This function is called to create a pool of command orbs used for command processing. It is called
- * when a new sbp2 device is detected.
+ * This function is called to create a pool of command orbs used for
+ * command processing. It is called when a new sbp2 device is detected.
*/
static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id,
struct sbp2scsi_host_info *hi)
@@ -785,10 +692,11 @@ static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_
}
/*
- * This functions finds the sbp2_command for a given outstanding
- * command orb. Only looks at the inuse list.
+ * This functions finds the sbp2_command for a given outstanding command
+ * orb. Only looks at the inuse list.
*/
-static struct sbp2_command_info *sbp2util_find_command_for_orb(struct scsi_id_instance_data *scsi_id, dma_addr_t orb)
+static struct sbp2_command_info *sbp2util_find_command_for_orb(
+ struct scsi_id_instance_data *scsi_id, dma_addr_t orb)
{
struct list_head *lh;
struct sbp2_command_info *command;
@@ -812,7 +720,8 @@ static struct sbp2_command_info *sbp2util_find_command_for_orb(struct scsi_id_in
}
/*
- * This functions finds the sbp2_command for a given outstanding SCpnt. Only looks at the inuse list
+ * This functions finds the sbp2_command for a given outstanding SCpnt.
+ * Only looks at the inuse list.
*/
static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt)
{
@@ -837,10 +746,11 @@ static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_
/*
* This function allocates a command orb used to send a scsi command.
*/
-static struct sbp2_command_info *sbp2util_allocate_command_orb(struct scsi_id_instance_data *scsi_id,
- Scsi_Cmnd *Current_SCpnt,
- void (*Current_done)(Scsi_Cmnd *),
- struct sbp2scsi_host_info *hi)
+static struct sbp2_command_info *sbp2util_allocate_command_orb(
+ struct scsi_id_instance_data *scsi_id,
+ Scsi_Cmnd *Current_SCpnt,
+ void (*Current_done)(Scsi_Cmnd *),
+ struct sbp2scsi_host_info *hi)
{
struct list_head *lh;
struct sbp2_command_info *command = NULL;
@@ -903,13 +813,15 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
sbp2_spin_unlock(&scsi_id->sbp2_command_orb_lock, flags);
}
+
+
/*********************************************
* IEEE-1394 core driver stack related section
*********************************************/
/*
- * This function is called at SCSI init in order to register our driver with the
- * IEEE-1394 stack
+ * This function is called at SCSI init in order to register our driver
+ * with the IEEE-1394 stack.
*/
int sbp2_init(void)
{
@@ -931,26 +843,21 @@ int sbp2_init(void)
hpsb_register_addrspace(sbp2_hl_handle, &sbp2_ops, SBP2_STATUS_FIFO_ADDRESS,
SBP2_STATUS_FIFO_ADDRESS + sizeof(struct sbp2_status_block));
- /*
- * Register physical dma address space... used for
- * adapters not supporting hardware phys dma.
- *
- * XXX: Disabled for now.
- */
- /* hpsb_register_addrspace(sbp2_hl_handle, &sbp2_physdma_ops,
- 0x0ULL, 0xfffffffcULL); */
+ hpsb_register_protocol(&sbp2_driver);
- return(0);
+ return 0;
}
/*
- * This function is called from cleanup module, or during shut-down, in order to
- * unregister our driver
+ * This function is called from cleanup module, or during shut-down, in
+ * order to unregister our driver.
*/
void sbp2_cleanup(void)
{
SBP2_DEBUG("sbp2: sbp2_cleanup");
+ hpsb_unregister_protocol(&sbp2_driver);
+
if (sbp2_hl_handle) {
hpsb_unregister_highlevel(sbp2_hl_handle);
sbp2_hl_handle = NULL;
@@ -958,73 +865,121 @@ void sbp2_cleanup(void)
return;
}
-/*
- * This function is called after registering our operations in sbp2_init. We go ahead and
- * allocate some memory for our host info structure, and init some structures.
- */
-static void sbp2_add_host(struct hpsb_host *host)
+static int sbp2_probe(struct unit_directory *ud)
{
struct sbp2scsi_host_info *hi;
- unsigned long flags;
- SBP2_DEBUG("sbp2: sbp2_add_host");
+ SBP2_DEBUG("sbp2: sbp2_probe");
+ hi = sbp2_find_host_info(ud->ne->host);
- /*
- * Allocate some memory for our host info structure
- */
- hi = (struct sbp2scsi_host_info *)kmalloc(sizeof(struct sbp2scsi_host_info), GFP_KERNEL);
+ return sbp2_start_device(hi, ud);
+}
- if (hi != NULL) {
+static void sbp2_disconnect(struct unit_directory *ud)
+{
+ struct sbp2scsi_host_info *hi;
+ struct scsi_id_instance_data *scsi_id = ud->driver_data;
- /*
- * Initialize some host stuff
- */
- memset(hi, 0, sizeof(struct sbp2scsi_host_info));
- INIT_LIST_HEAD(&hi->list);
- INIT_LIST_HEAD(&hi->sbp2_req_inuse);
- INIT_LIST_HEAD(&hi->sbp2_req_free);
- hi->host = host;
- hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED;
- hi->sbp2_request_packet_lock = SPIN_LOCK_UNLOCKED;
+ SBP2_DEBUG("sbp2: sbp2_disconnect");
+ hi = sbp2_find_host_info(ud->ne->host);
- /*
- * Create our request packet pool (pool of packets for use in I/O)
+ if (hi != NULL)
+ sbp2_remove_device(hi, scsi_id);
+}
+
+static void sbp2_update(struct unit_directory *ud)
+{
+ struct sbp2scsi_host_info *hi;
+ struct scsi_id_instance_data *scsi_id = ud->driver_data;
+ unsigned long flags;
+
+ SBP2_DEBUG("sbp2: sbp2_update");
+ hi = sbp2_find_host_info(ud->ne->host);
+
+ if (sbp2_reconnect_device(hi, scsi_id)) {
+
+ /* Ok, reconnect has failed. Perhaps we didn't
+ * reconnect fast enough. Try doing a regular login.
*/
- if (sbp2util_create_request_packet_pool(hi)) {
- SBP2_ERR("sbp2: sbp2util_create_request_packet_pool failed!");
+ if (sbp2_login_device(hi, scsi_id)) {
+
+ /* Login failed too... so, just mark him as
+ * unvalidated, so that he gets cleaned up
+ * later.
+ */
+ SBP2_ERR("sbp2: sbp2_reconnect_device failed!");
+ sbp2_remove_device(hi, scsi_id);
return;
}
+ }
- sbp2_spin_lock(&sbp2_host_info_lock, flags);
- list_add_tail(&hi->list, &sbp2_host_info_list);
- sbp2_host_count++;
- sbp2_spin_unlock(&sbp2_host_info_lock, flags);
+ /* Set max retries to something large on the device. */
+ sbp2_set_busy_timeout(hi, scsi_id);
- /*
- * Initialize us to bus reset in progress
- */
- hi->bus_reset_in_progress = 1;
+ /* Do a SBP-2 fetch agent reset. */
+ sbp2_agent_reset(hi, scsi_id, 0);
+
+ /* Get the max speed and packet size that we can use. */
+ sbp2_max_speed_and_size(hi, scsi_id);
- /*
- * Register our host with the SCSI stack.
- */
- sbp2scsi_register_scsi_host(hi);
+ /* Complete any pending commands with busy (so they get
+ * retried) and remove them from our queue
+ */
+ sbp2_spin_lock(&hi->sbp2_command_lock, flags);
+ sbp2scsi_complete_all_commands(hi, scsi_id, DID_BUS_BUSY);
+ sbp2_spin_unlock(&hi->sbp2_command_lock, flags);
+}
- /*
- * Start our kernel thread to deal with sbp2 device detection
- */
- init_waitqueue_head(&hi->sbp2_detection_wait);
- hi->sbp2_detection_pid = 0;
- hi->sbp2_detection_pid = kernel_thread(sbp2_detection_thread, hi, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+/*
+ * This function is called after registering our operations in sbp2_init.
+ * We go ahead and allocate some memory for our host info structure, and
+ * init some structures.
+ */
+static void sbp2_add_host(struct hpsb_host *host)
+{
+ struct sbp2scsi_host_info *hi;
+ unsigned long flags;
+ SBP2_DEBUG("sbp2: sbp2_add_host");
+
+ /* Allocate some memory for our host info structure */
+ hi = (struct sbp2scsi_host_info *)kmalloc(sizeof(struct sbp2scsi_host_info),
+ GFP_KERNEL);
+
+ if (hi == NULL) {
+ SBP2_ERR("sbp2: out of memory in sbp2_add_host");
+ return;
}
+ /* Initialize some host stuff */
+ memset(hi, 0, sizeof(struct sbp2scsi_host_info));
+ INIT_LIST_HEAD(&hi->list);
+ INIT_LIST_HEAD(&hi->sbp2_req_inuse);
+ INIT_LIST_HEAD(&hi->sbp2_req_free);
+ hi->host = host;
+ hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED;
+ hi->sbp2_request_packet_lock = SPIN_LOCK_UNLOCKED;
+
+ /* Create our request packet pool (pool of packets for use in I/O) */
+ if (sbp2util_create_request_packet_pool(hi)) {
+ SBP2_ERR("sbp2: sbp2util_create_request_packet_pool failed!");
+ return;
+ }
+
+ sbp2_spin_lock(&sbp2_host_info_lock, flags);
+ list_add_tail(&hi->list, &sbp2_host_info_list);
+ sbp2_host_count++;
+ sbp2_spin_unlock(&sbp2_host_info_lock, flags);
+
+ /* Register our host with the SCSI stack. */
+ sbp2scsi_register_scsi_host(hi);
+
return;
}
/*
- * This fuction returns a host info structure from the host structure,
- * in case we have multiple hosts
+ * This fuction returns a host info structure from the host structure, in
+ * case we have multiple hosts.
*/
static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host)
{
@@ -1047,206 +1002,55 @@ static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host)
static void sbp2_remove_host(struct hpsb_host *host)
{
struct sbp2scsi_host_info *hi;
- int i;
unsigned long flags;
+ int i;
SBP2_DEBUG("sbp2: sbp2_remove_host");
sbp2_spin_lock(&sbp2_host_info_lock, flags);
- hi = sbp2_find_host_info(host);
+ hi = sbp2_find_host_info(host);
if (hi != NULL) {
-
- /*
- * Need to remove any attached SBP-2 devices. Also make sure to logout of all devices.
+ /* Here's an annoying hack: we get a disconnect
+ * callback for each device, so this loop shouldn't be
+ * necessary. However, the sbp2 driver receives the
+ * remove_host callback before the nodemgr, so when we
+ * get the disconnect callback, we've already freed
+ * the host. Thus, we free the devices here...
*/
- for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
- if (hi->scsi_id[i]) {
+ for (i = 0; i < SBP2SCSI_MAX_SCSI_IDS; i++) {
+ if (hi->scsi_id[i] != NULL) {
sbp2_logout_device(hi, hi->scsi_id[i]);
- hi->scsi_id[i]->validated = 0;
+ sbp2_remove_device(hi, hi->scsi_id[i]);
}
}
-
- sbp2_remove_unvalidated_devices(hi);
-
- list_del(&hi->list);
+ sbp2util_remove_request_packet_pool(hi);
sbp2_host_count--;
+ list_del(&hi->list);
+ kfree(hi);
}
- sbp2_spin_unlock(&sbp2_host_info_lock, flags);
-
- if (hi == NULL) {
+ else
SBP2_ERR("sbp2: attempt to remove unknown host %p", host);
- return;
- }
-
- /*
- * Remove the packet pool (release the packets)
- */
- sbp2util_remove_request_packet_pool(hi);
-
- /*
- * Kill our detection thread
- */
- if (hi->sbp2_detection_pid >= 0) {
- kill_proc(hi->sbp2_detection_pid, SIGINT, 1);
- }
-
- /*
- * Give the detection thread a little time to exit
- */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ); /* 1 second delay */
-
- kfree(hi);
- hi = NULL;
-
- return;
-}
-
-/*
- * This is our sbp2 detection thread. It is signalled when bus resets occur
- * so that we can find and initialize any sbp2 devices.
- */
-static int sbp2_detection_thread(void *__hi)
-{
- struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *)__hi;
- SBP2_DEBUG("sbp2: sbp2_detection_thread");
-
- lock_kernel();
-
- /*
- * This thread doesn't need any user-level access,
- * so get rid of all our resources
- */
-#if LINUX_VERSION_CODE > 0x20300
- daemonize();
-#endif
-
- /*
- * Set-up a nice name
- */
- strcpy(current->comm, SBP2_DEVICE_NAME);
-
- unlock_kernel();
-
- while ((!signal_pending(current)) && hi) {
-
- /*
- * Process our bus reset now
- */
- if (hi) {
- MOD_INC_USE_COUNT;
- sbp2_bus_reset_handler(hi);
- MOD_DEC_USE_COUNT;
- }
-
- /*
- * Sleep until next bus reset
- */
- if (hi) {
- interruptible_sleep_on(&hi->sbp2_detection_wait);
- }
- }
-
- return(0);
+ sbp2_spin_unlock(&sbp2_host_info_lock, flags);
}
/*
- * This function is where we first pull the node unique ids, and then allocate memory and register
- * a SBP-2 device
+ * This function is where we first pull the node unique ids, and then
+ * allocate memory and register a SBP-2 device.
*/
-static int sbp2_start_device(struct sbp2scsi_host_info *hi, int node_id)
+static int sbp2_start_device(struct sbp2scsi_host_info *hi, struct unit_directory *ud)
{
- u64 node_unique_id;
struct scsi_id_instance_data *scsi_id = NULL;
struct node_entry *ne;
int i;
SBP2_DEBUG("sbp2: sbp2_start_device");
-
- /* XXX: This will go away once we start using the nodemgr's
- * feature subscription API. */
- ne = hpsb_nodeid_get_entry(node_id|(hi->host->node_id & BUS_MASK));
- if (!ne) {
- HPSB_ERR("sbp2: Could not find device node");
- return -ENXIO;
- }
-
- node_unique_id = ne->guid;
-
- /*
- * First, we need to find out whether this is a "new" SBP-2 device plugged in, or one that already
- * exists and is initialized. We do this by looping through our scsi id instance data structures
- * looking for matching node unique ids.
- */
- for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
-
- if (hi->scsi_id[i]) {
-
- if (hi->scsi_id[i]->node_unique_id == node_unique_id) {
-
- /*
- * Update our node id
- */
- hi->scsi_id[i]->node_id = node_id;
-
- /*
- * Mark the device as validated, since it still exists on the bus
- */
- hi->scsi_id[i]->validated = 1;
- SBP2_DEBUG("sbp2: SBP-2 device re-validated, SCSI ID = %x", (unsigned int) i);
-
- /*
- * Reconnect to the sbp-2 device
- */
- if (sbp2_reconnect_device(hi, hi->scsi_id[i])) {
-
- /*
- * Ok, reconnect has failed. Perhaps we didn't reconnect fast enough. Try
- * doing a regular login.
- */
- if (sbp2_login_device(hi, hi->scsi_id[i])) {
-
- /*
- * Login failed too... so, just mark him as unvalidated, so that he gets cleaned up
- * later
- */
- SBP2_ERR("sbp2: sbp2_reconnect_device failed!");
- hi->scsi_id[i]->validated = 0;
- }
- }
-
- if (hi->scsi_id[i]->validated) {
-
- /*
- * Set max retries to something large on the device
- */
- sbp2_set_busy_timeout(hi, hi->scsi_id[i]);
-
- /*
- * Do a SBP-2 fetch agent reset
- */
- sbp2_agent_reset(hi, hi->scsi_id[i], 0);
-
- /*
- * Get the max speed and packet size that we can use
- */
- sbp2_max_speed_and_size(hi, hi->scsi_id[i]);
-
- }
-
- /*
- * Nothing more to do, since we found the device
- */
- return(0);
-
- }
- }
- }
+ ne = ud->ne;
/*
- * This really is a "new" device plugged in. Let's allocate memory for our scsi id instance data
+ * This really is a "new" device plugged in. Let's allocate memory
+ * for our scsi id instance data.
*/
scsi_id = (struct scsi_id_instance_data *)kmalloc(sizeof(struct scsi_id_instance_data),
GFP_KERNEL);
@@ -1318,11 +1122,11 @@ alloc_fail_first:
/*
* Initialize some of the fields in this structure
*/
- scsi_id->node_id = node_id;
- scsi_id->node_unique_id = node_unique_id;
- scsi_id->validated = 1;
+ scsi_id->ne = ne;
+ scsi_id->ud = ud;
scsi_id->speed_code = SPEED_100;
scsi_id->max_payload_size = MAX_PAYLOAD_S100;
+ ud->driver_data = scsi_id;
init_waitqueue_head(&scsi_id->sbp2_login_wait);
@@ -1335,14 +1139,11 @@ alloc_fail_first:
scsi_id->sbp2_total_command_orbs = 0;
/*
- * Make sure that we've gotten ahold of the sbp2 management agent address. Also figure out the
- * command set being used (SCSI or RBC).
+ * Make sure that we've gotten ahold of the sbp2 management agent
+ * address. Also figure out the command set being used (SCSI or
+ * RBC).
*/
- if (sbp2_parse_unit_directory(hi, scsi_id)) {
- SBP2_ERR("sbp2: Error while parsing sbp2 unit directory");
- hi->scsi_id[i]->validated = 0;
- return(-EIO);
- }
+ sbp2_parse_unit_directory(scsi_id);
scsi_id->sbp2_total_command_orbs = SBP2_MAX_COMMAND_ORBS;
@@ -1354,447 +1155,136 @@ alloc_fail_first:
}
/*
- * Allocate some extra command orb structures for devices with 128KB limit
+ * Allocate some extra command orb structures for devices with
+ * 128KB limit.
*/
if (scsi_id->sbp2_firmware_revision == SBP2_128KB_BROKEN_FIRMWARE) {
scsi_id->sbp2_total_command_orbs *= 4;
}
/*
- * Create our command orb pool
- */
- if (sbp2util_create_command_orb_pool(scsi_id, hi)) {
- SBP2_ERR("sbp2: sbp2util_create_command_orb_pool failed!");
- hi->scsi_id[i]->validated = 0;
- return (-ENOMEM);
- }
-
- /*
* Find an empty spot to stick our scsi id instance data.
*/
- for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
+ for (i = 0; i < SBP2SCSI_MAX_SCSI_IDS; i++) {
if (!hi->scsi_id[i]) {
hi->scsi_id[i] = scsi_id;
+ scsi_id->id = i;
SBP2_DEBUG("sbp2: New SBP-2 device inserted, SCSI ID = %x", (unsigned int) i);
break;
}
}
/*
+ * Create our command orb pool
+ */
+ if (sbp2util_create_command_orb_pool(scsi_id, hi)) {
+ SBP2_ERR("sbp2: sbp2util_create_command_orb_pool failed!");
+ sbp2_remove_device(hi, scsi_id);
+ return -ENOMEM;
+ }
+
+ /*
* Make sure we are not out of space
*/
- if (i >= SBP2SCSI_MAX_SCSI_IDS) {
+ if (i == SBP2SCSI_MAX_SCSI_IDS) {
SBP2_ERR("sbp2: No slots left for SBP-2 device");
- hi->scsi_id[i]->validated = 0;
- return(-EBUSY);
+ sbp2_remove_device(hi, scsi_id);
+ return -EBUSY;
}
/*
* Login to the sbp-2 device
*/
- if (sbp2_login_device(hi, hi->scsi_id[i])) {
+ if (sbp2_login_device(hi, scsi_id)) {
/*
- * Login failed... so, just mark him as unvalidated, so that he gets cleaned up later
+ * Login failed... so, just mark him as unvalidated, so
+ * that he gets cleaned up later.
*/
SBP2_ERR("sbp2: sbp2_login_device failed");
- hi->scsi_id[i]->validated = 0;
+ sbp2_remove_device(hi, scsi_id);
+ return -EBUSY;
}
- if (hi->scsi_id[i]->validated) {
-
- /*
- * Set max retries to something large on the device
- */
- sbp2_set_busy_timeout(hi, hi->scsi_id[i]);
-
- /*
- * Do a SBP-2 fetch agent reset
- */
- sbp2_agent_reset(hi, hi->scsi_id[i], 0);
-
- /*
- * Get the max speed and packet size that we can use
- */
- sbp2_max_speed_and_size(hi, hi->scsi_id[i]);
-
- }
-
- return(0);
-}
-
-/*
- * This function tries to determine if a device is a valid SBP-2 device
- */
-static int sbp2_check_device(struct sbp2scsi_host_info *hi, int node_id)
-{
- quadlet_t unit_spec_id_data = 0, unit_sw_ver_data = 0;
- quadlet_t unit_directory_length, current_quadlet;
- u64 unit_directory_addr, current_addr;
- unsigned int i, length;
-
- SBP2_DEBUG("sbp2: sbp2_check_device");
-
/*
- * Let's try and read the unit spec id and unit sw ver to determine if this is an SBP2 device...
+ * Set max retries to something large on the device
*/
-
- if (sbp2util_unit_directory(hi, LOCAL_BUS | node_id, &unit_directory_addr)) {
- SBP2_DEBUG("sbp2: Error reading unit directory address - bad status");
- return(-EIO);
- }
-
- /*
- * Read the size of the unit directory
- */
- if (sbp2util_read_quadlet(hi, LOCAL_BUS | node_id, unit_directory_addr,
- &unit_directory_length)) {
- SBP2_DEBUG("sbp2: Error reading root directory length - bad status");
- return(-EIO);
- }
-
- current_addr = unit_directory_addr;
- length = be32_to_cpu(unit_directory_length) >> 16;
-
+ sbp2_set_busy_timeout(hi, scsi_id);
+
/*
- * Now, step through the unit directory and look for the unit_spec_ID and the unit_sw_version
+ * Do a SBP-2 fetch agent reset
*/
- for (i=0; i < length; i++) {
-
- current_addr += 4;
-
- if (sbp2util_read_quadlet(hi, LOCAL_BUS | node_id, current_addr, &current_quadlet)) {
- SBP2_DEBUG("sbp2: Error reading at address 0x%08x%08x - bad status",
- (unsigned int) ((current_addr) >> 32), (unsigned int) ((current_addr) & 0xffffffff));
- return(-EIO);
- }
-
- /*
- * Check for unit_spec_ID tag
- */
- if ((be32_to_cpu(current_quadlet) >> 24) == SBP2_UNIT_SPEC_ID_KEY) {
- unit_spec_id_data = current_quadlet;
- SBP2_DEBUG("sbp2: Node %x, unit spec id = %x", (LOCAL_BUS | node_id),
- (unsigned int) be32_to_cpu(unit_spec_id_data));
- }
-
- /*
- * Check for unit_sw_version tag
- */
- if ((be32_to_cpu(current_quadlet) >> 24) == SBP2_UNIT_SW_VERSION_KEY) {
- unit_sw_ver_data = current_quadlet;
- SBP2_DEBUG("sbp2: Node %x, unit sw version = %x", (LOCAL_BUS | node_id),
- (unsigned int) be32_to_cpu(unit_sw_ver_data));
- }
- }
-
+ sbp2_agent_reset(hi, scsi_id, 0);
+
/*
- * Validate unit spec id and unit sw ver to see if this is an SBP-2 device
+ * Get the max speed and packet size that we can use
*/
- if ((be32_to_cpu(unit_spec_id_data) != SBP2_UNIT_SPEC_ID_ENTRY) ||
- (be32_to_cpu(unit_sw_ver_data) != SBP2_SW_VERSION_ENTRY)) {
+ sbp2_max_speed_and_size(hi, scsi_id);
- /*
- * Not an sbp2 device
- */
- return(-ENXIO);
- }
-
- /*
- * This device is a valid SBP-2 device
- */
- SBP2_INFO("sbp2: Node 0x%04x, Found SBP-2 device", (LOCAL_BUS | node_id));
- return(0);
+ return 0;
}
/*
* This function removes (cleans-up after) any unvalidated sbp2 devices
*/
-static void sbp2_remove_unvalidated_devices(struct sbp2scsi_host_info *hi)
+static void sbp2_remove_device(struct sbp2scsi_host_info *hi,
+ struct scsi_id_instance_data *scsi_id)
{
- int i;
-
- /*
- * Loop through and free any unvalidated scsi id instance data structures
- */
- for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
- if (hi->scsi_id[i]) {
- if (!hi->scsi_id[i]->validated) {
-
- /*
- * Complete any pending commands with selection timeout
- */
- sbp2scsi_complete_all_commands(hi, hi->scsi_id[i], DID_NO_CONNECT);
+ /* Complete any pending commands with selection timeout */
+ sbp2scsi_complete_all_commands(hi, scsi_id, DID_NO_CONNECT);
- /*
- * Clean up any other structures
- */
- if (hi->scsi_id[i]->sbp2_total_command_orbs) {
- sbp2util_remove_command_orb_pool(hi->scsi_id[i], hi);
- }
- if (hi->scsi_id[i]->login_response) {
- pci_free_consistent(hi->host->pdev,
- sizeof(struct sbp2_login_response),
- hi->scsi_id[i]->login_response,
- hi->scsi_id[i]->login_response_dma);
- SBP2_DMA_FREE("single login FIFO");
- }
-
- if (hi->scsi_id[i]->login_orb) {
- pci_free_consistent(hi->host->pdev,
- sizeof(struct sbp2_login_orb),
- hi->scsi_id[i]->login_orb,
- hi->scsi_id[i]->login_orb_dma);
- SBP2_DMA_FREE("single login ORB");
- }
-
- if (hi->scsi_id[i]->reconnect_orb) {
- pci_free_consistent(hi->host->pdev,
- sizeof(struct sbp2_reconnect_orb),
- hi->scsi_id[i]->reconnect_orb,
- hi->scsi_id[i]->reconnect_orb_dma);
- SBP2_DMA_FREE("single reconnect orb");
- }
-
- if (hi->scsi_id[i]->logout_orb) {
- pci_free_consistent(hi->host->pdev,
- sizeof(struct sbp2_logout_orb),
- hi->scsi_id[i]->logout_orb,
- hi->scsi_id[i]->reconnect_orb_dma);
- SBP2_DMA_FREE("single logout orb");
- }
-
- kfree(hi->scsi_id[i]);
- hi->scsi_id[i] = NULL;
- SBP2_DEBUG("sbp2: Unvalidated SBP-2 device removed, SCSI ID = %x", (unsigned int) i);
- }
- }
+ /* Clean up any other structures */
+ if (scsi_id->sbp2_total_command_orbs) {
+ sbp2util_remove_command_orb_pool(scsi_id, hi);
}
- return;
-}
-
-/*
- * This function is our reset handler. It is run out of a thread, since we get
- * notified of a bus reset from a bh (or interrupt).
- */
-static void sbp2_bus_reset_handler(void *context)
-{
- struct sbp2scsi_host_info *hi = context;
- quadlet_t signature_data;
- int i;
- unsigned long flags;
- struct scsi_id_instance_data *scsi_id;
-
- SBP2_DEBUG("sbp2: sbp2_bus_reset_handler");
-
- /*
- * TODO. Check and keep track of generation number of all requests, in case a
- * bus reset occurs while trying to find and login to SBP-2 devices.
- */
-
- /*
- * First thing to do. Invalidate all SBP-2 devices. This is needed so that
- * we stop sending down I/O requests to the device, and also so that we can
- * figure out which devices have disappeared after a bus reset.
- */
- for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
- if (hi->scsi_id[i]) {
- hi->scsi_id[i]->validated = 0;
- }
- }
-
- /*
- * Give the sbp2 devices a little time to recover after the bus reset
- */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ/2); /* 1/2 second delay */
-
- /*
- * Spit out what we know from the host
- */
- SBP2_DEBUG("host: node_count = %x", (unsigned int) hi->host->node_count);
- SBP2_DEBUG("host: selfid_count = %x", (unsigned int) hi->host->selfid_count);
- SBP2_DEBUG("host: node_id = %x", (unsigned int) hi->host->node_id);
- SBP2_DEBUG("host: irm_id = %x", (unsigned int) hi->host->irm_id);
- SBP2_DEBUG("host: busmgr_id = %x", (unsigned int) hi->host->busmgr_id);
- SBP2_DEBUG("host: is_root = %x", (unsigned int) hi->host->is_root);
- SBP2_DEBUG("host: is_cycmst = %x", (unsigned int) hi->host->is_cycmst);
- SBP2_DEBUG("host: is_irm = %x", (unsigned int) hi->host->is_irm);
- SBP2_DEBUG("host: is_busmgr = %x", (unsigned int) hi->host->is_busmgr);
-
- /*
- * Let's try and figure out which devices out there are SBP-2 devices! Loop through all
- * nodes out there.
- */
- for (i=0; i<hi->host->node_count; i++) {
-
- /*
- * Don't read from ourselves!
- */
- if (i != ((hi->host->node_id) & NODE_MASK)) {
-
- /*
- * Try and send a request for a config rom signature. This is expected to fail for
- * some nodes, as they might be repeater phys or not be initialized.
- */
- if (!sbp2util_read_quadlet(hi, LOCAL_BUS | i, CONFIG_ROM_SIGNATURE_ADDRESS, &signature_data)) {
-
- if (be32_to_cpu(signature_data) == IEEE1394_CONFIG_ROM_SIGNATURE) {
-
- /*
- * Hey, we've got a valid responding IEEE1394 node. Need to now see if it's an SBP-2 device
- */
- if (!sbp2_check_device(hi, i)) {
-
- /*
- * Found an SBP-2 device. Now, actually start the device.
- */
- sbp2_start_device(hi, i);
- }
- }
- }
- }
+ if (scsi_id->login_response) {
+ pci_free_consistent(hi->host->pdev,
+ sizeof(struct sbp2_login_response),
+ scsi_id->login_response,
+ scsi_id->login_response_dma);
+ SBP2_DMA_FREE("single login FIFO");
}
- /*
- * This code needs protection
- */
- sbp2_spin_lock(&hi->sbp2_command_lock, flags);
-
- /*
- * Ok, we've discovered and re-validated all SBP-2 devices out there. Let's remove structures of all
- * devices not re-validated (meaning they've been removed).
- */
- sbp2_remove_unvalidated_devices(hi);
-
- /*
- * Complete any pending commands with busy (so they get retried) and remove them from our queue
- */
- for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
- if (hi->scsi_id[i]) {
- sbp2scsi_complete_all_commands(hi, hi->scsi_id[i], DID_BUS_BUSY);
- }
+ if (scsi_id->login_orb) {
+ pci_free_consistent(hi->host->pdev,
+ sizeof(struct sbp2_login_orb),
+ scsi_id->login_orb,
+ scsi_id->login_orb_dma);
+ SBP2_DMA_FREE("single login ORB");
}
- /*
- * Now, note that the bus reset is complete (finally!)
- */
- hi->bus_reset_in_progress = 0;
-
- /*
- * Deal with the initial scsi bus scan if needed (since we only now know if there are
- * any sbp2 devices attached)
- */
- if (!no_bus_scan && !hi->initial_scsi_bus_scan_complete && hi->bus_scan_SCpnt) {
-
- hi->initial_scsi_bus_scan_complete = 1;
- scsi_id = hi->scsi_id[hi->bus_scan_SCpnt->target];
-
- /*
- * If the sbp2 device exists, then let's now execute the command.
- * If not, then just complete it as a selection time-out.
- */
- if (scsi_id) {
- if (sbp2_send_command(hi, scsi_id, hi->bus_scan_SCpnt, hi->bus_scan_done)) {
- SBP2_ERR("sbp2: Error sending SCSI command");
- sbp2scsi_complete_command(hi, scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT,
- hi->bus_scan_SCpnt, hi->bus_scan_done);
- }
- } else {
- void (*done)(Scsi_Cmnd *) = hi->bus_scan_done;
- hi->bus_scan_SCpnt->result = DID_NO_CONNECT << 16;
- done (hi->bus_scan_SCpnt);
- }
+ if (scsi_id->reconnect_orb) {
+ pci_free_consistent(hi->host->pdev,
+ sizeof(struct sbp2_reconnect_orb),
+ scsi_id->reconnect_orb,
+ scsi_id->reconnect_orb_dma);
+ SBP2_DMA_FREE("single reconnect orb");
}
- sbp2_spin_unlock(&hi->sbp2_command_lock, flags);
-
- return;
-}
-
-
-/*
- * This is called from the host's bh when a bus reset is complete. We wake up our detection thread
- * to deal with the reset
- */
-static void sbp2_host_reset(struct hpsb_host *host)
-{
- unsigned long flags;
- struct sbp2scsi_host_info *hi;
- int i;
-
- SBP2_INFO("sbp2: IEEE-1394 bus reset");
- sbp2_spin_lock(&sbp2_host_info_lock, flags);
- hi = sbp2_find_host_info(host);
-
- if (hi != NULL) {
-
- /*
- * Wake up our detection thread, only if it's not already handling a reset
- */
- if (!hi->bus_reset_in_progress) {
-
- /*
- * First thing to do. Invalidate all SBP-2 devices. This is needed so that
- * we stop sending down I/O requests to the device, and also so that we can
- * figure out which devices have disappeared after a bus reset.
- */
- for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
- if (hi->scsi_id[i]) {
- hi->scsi_id[i]->validated = 0;
- }
- }
-
- hi->bus_reset_in_progress = 1;
-
- wake_up(&hi->sbp2_detection_wait);
- }
+ if (scsi_id->logout_orb) {
+ pci_free_consistent(hi->host->pdev,
+ sizeof(struct sbp2_logout_orb),
+ scsi_id->logout_orb,
+ scsi_id->reconnect_orb_dma);
+ SBP2_DMA_FREE("single logout orb");
}
- sbp2_spin_unlock(&sbp2_host_info_lock, flags);
- return;
-}
-
-/* XXX: How best to handle these with DMA interface? */
-
-#if 0
-/*
- * This function deals with physical dma write requests (for adapters that do not support
- * physical dma in hardware).
- */
-static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, quadlet_t *data,
- u64 addr, unsigned int length)
-{
- /*
- * Manually put the data in the right place.
- */
- memcpy(bus_to_virt((u32)addr), data, length);
- return(RCODE_COMPLETE);
+ SBP2_DEBUG("sbp2: Unvalidated SBP-2 device removed, SCSI ID = %d",
+ scsi_id->id);
+ hi->scsi_id[scsi_id->id] = NULL;
+ kfree(scsi_id);
}
-/*
- * This function deals with physical dma read requests (for adapters that do not support
- * physical dma in hardware).
- */
-static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data,
- u64 addr, unsigned int length)
-{
-
- /*
- * Grab data from memory and send a read response.
- */
- memcpy(data, bus_to_virt((u32)addr), length);
- return(RCODE_COMPLETE);
-}
-#endif
+
/**************************************
* SBP-2 protocol related section
**************************************/
/*
- * This function is called in order to login to a particular SBP-2 device, after a bus reset
+ * This function is called in order to login to a particular SBP-2 device,
+ * after a bus reset.
*/
static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id)
{
@@ -1808,34 +1298,28 @@ static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_insta
return(-EIO);
}
- /*
- * Set-up login ORB
- */
- scsi_id->login_orb->password_hi = 0; /* Assume no password */
+ /* Set-up login ORB, assume no password */
+ scsi_id->login_orb->password_hi = 0;
scsi_id->login_orb->password_lo = 0;
SBP2_DEBUG("sbp2: sbp2_login_device: password_hi/lo initialized");
-#ifdef SBP2_NEED_LOGIN_DESCRIPTOR_WORKAROUND
- scsi_id->login_orb->login_response_lo = cpu_to_le32(scsi_id->login_response_dma);
- scsi_id->login_orb->login_response_hi = cpu_to_le32(ORB_SET_NODE_ID(hi->host->node_id));
-#else
+
scsi_id->login_orb->login_response_lo = scsi_id->login_response_dma;
scsi_id->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
-#endif
SBP2_DEBUG("sbp2: sbp2_login_device: login_response_hi/lo initialized");
+
scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(LOGIN_REQUEST);
scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0); /* One second reconnect time */
scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(1); /* Exclusive access to device */
scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1); /* Notify us of login complete */
SBP2_DEBUG("sbp2: sbp2_login_device: lun_misc initialized");
- scsi_id->login_orb->passwd_resp_lengths = ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));
+
+ scsi_id->login_orb->passwd_resp_lengths =
+ ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));
SBP2_DEBUG("sbp2: sbp2_login_device: passwd_resp_lengths initialized");
-#ifdef SBP2_NEED_LOGIN_DESCRIPTOR_WORKAROUND
- scsi_id->login_orb->status_FIFO_lo = cpu_to_le32((u32)SBP2_STATUS_FIFO_ADDRESS_LO);
- scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | cpu_to_le16(SBP2_STATUS_FIFO_ADDRESS_HI));
-#else
+
scsi_id->login_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO;
- scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI);
-#endif
+ scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
+ SBP2_STATUS_FIFO_ADDRESS_HI);
SBP2_DEBUG("sbp2: sbp2_login_device: status FIFO initialized");
/*
@@ -1861,25 +1345,26 @@ static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_insta
sbp2util_cpu_to_be32_buffer(data, 8);
SBP2_DEBUG("sbp2: sbp2_login_device: prepared to write");
-
- hpsb_write(hi->host, LOCAL_BUS | scsi_id->node_id, scsi_id->sbp2_management_agent_addr, data, 8);
+ hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, scsi_id->sbp2_management_agent_addr, data, 8);
+ SBP2_DEBUG("sbp2: sbp2_login_device: written");
/*
- * Wait for login status... but, only if the device has not already logged-in (some devices are fast)
+ * Wait for login status... but, only if the device has not
+ * already logged-in (some devices are fast)
*/
- SBP2_DEBUG("sbp2: sbp2_login_device: written");
save_flags(flags);
cli();
- if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) {
- interruptible_sleep_on_timeout(&scsi_id->sbp2_login_wait, 10*HZ); /* 10 second timeout */
- }
+ /* 10 second timeout */
+ if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma)
+ sleep_on_timeout(&scsi_id->sbp2_login_wait, 10*HZ);
restore_flags(flags);
SBP2_DEBUG("sbp2: sbp2_login_device: initial check");
/*
- * Match status to the login orb. If they do not match, it's probably because the login timed-out
+ * Match status to the login orb. If they do not match, it's
+ * probably because the login timed-out.
*/
if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) {
SBP2_ERR("sbp2: Error logging into SBP-2 device - login timed-out");
@@ -1900,17 +1385,21 @@ static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_insta
}
/*
- * Byte swap the login response, for use when reconnecting or logging out.
+ * Byte swap the login response, for use when reconnecting or
+ * logging out.
*/
sbp2util_cpu_to_be32_buffer(scsi_id->login_response, sizeof(struct sbp2_login_response));
/*
- * Grab our command block agent address from the login response
+ * Grab our command block agent address from the login response.
*/
- SBP2_DEBUG("sbp2: command_block_agent_hi = %x", (unsigned int)scsi_id->login_response->command_block_agent_hi);
- SBP2_DEBUG("sbp2: command_block_agent_lo = %x", (unsigned int)scsi_id->login_response->command_block_agent_lo);
+ SBP2_DEBUG("sbp2: command_block_agent_hi = %x",
+ (unsigned int)scsi_id->login_response->command_block_agent_hi);
+ SBP2_DEBUG("sbp2: command_block_agent_lo = %x",
+ (unsigned int)scsi_id->login_response->command_block_agent_lo);
- scsi_id->sbp2_command_block_agent_addr = ((u64)scsi_id->login_response->command_block_agent_hi) << 32;
+ scsi_id->sbp2_command_block_agent_addr =
+ ((u64)scsi_id->login_response->command_block_agent_hi) << 32;
scsi_id->sbp2_command_block_agent_addr |= ((u64)scsi_id->login_response->command_block_agent_lo);
scsi_id->sbp2_command_block_agent_addr &= 0x0000ffffffffffffULL;
@@ -1921,8 +1410,8 @@ static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_insta
}
/*
- * This function is called in order to logout from a particular SBP-2 device, usually called during driver
- * unload
+ * This function is called in order to logout from a particular SBP-2
+ * device, usually called during driver unload.
*/
static int sbp2_logout_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id)
{
@@ -1937,17 +1426,17 @@ static int sbp2_logout_device(struct sbp2scsi_host_info *hi, struct scsi_id_inst
scsi_id->logout_orb->reserved2 = 0x0;
scsi_id->logout_orb->reserved3 = 0x0;
scsi_id->logout_orb->reserved4 = 0x0;
+
scsi_id->logout_orb->login_ID_misc = ORB_SET_FUNCTION(LOGOUT_REQUEST);
scsi_id->logout_orb->login_ID_misc |= ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID);
- scsi_id->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1); /* Notify us when complete */
+
+ /* Notify us when complete */
+ scsi_id->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
+
scsi_id->logout_orb->reserved5 = 0x0;
-#ifdef SBP2_NEED_LOGIN_DESCRIPTOR_WORKAROUND
- scsi_id->logout_orb->status_FIFO_lo = cpu_to_le32((u32)SBP2_STATUS_FIFO_ADDRESS_LO);
- scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | cpu_to_le16(SBP2_STATUS_FIFO_ADDRESS_HI));
-#else
scsi_id->logout_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO;
- scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI);
-#endif
+ scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
+ SBP2_STATUS_FIFO_ADDRESS_HI);
/*
* Byte swap ORB if necessary
@@ -1961,12 +1450,10 @@ static int sbp2_logout_device(struct sbp2scsi_host_info *hi, struct scsi_id_inst
data[1] = scsi_id->logout_orb_dma;
sbp2util_cpu_to_be32_buffer(data, 8);
- hpsb_write(hi->host, LOCAL_BUS | scsi_id->node_id, scsi_id->sbp2_management_agent_addr, data, 8);
+ hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, scsi_id->sbp2_management_agent_addr, data, 8);
- /*
- * Wait for device to logout...
- */
- interruptible_sleep_on_timeout(&scsi_id->sbp2_login_wait, HZ); /* 1 second timeout */
+ /* Wait for device to logout...1 second. */
+ sleep_on_timeout(&scsi_id->sbp2_login_wait, HZ);
SBP2_INFO("sbp2: Logged out of SBP-2 device");
@@ -1975,7 +1462,8 @@ static int sbp2_logout_device(struct sbp2scsi_host_info *hi, struct scsi_id_inst
}
/*
- * This function is called in order to reconnect to a particular SBP-2 device, after a bus reset
+ * This function is called in order to reconnect to a particular SBP-2
+ * device, after a bus reset.
*/
static int sbp2_reconnect_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id)
{
@@ -1991,18 +1479,19 @@ static int sbp2_reconnect_device(struct sbp2scsi_host_info *hi, struct scsi_id_i
scsi_id->reconnect_orb->reserved2 = 0x0;
scsi_id->reconnect_orb->reserved3 = 0x0;
scsi_id->reconnect_orb->reserved4 = 0x0;
+
scsi_id->reconnect_orb->login_ID_misc = ORB_SET_FUNCTION(RECONNECT_REQUEST);
- scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID);
- scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1); /* Notify us when complete */
+ scsi_id->reconnect_orb->login_ID_misc |=
+ ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID);
+
+ /* Notify us when complete */
+ scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
+
scsi_id->reconnect_orb->reserved5 = 0x0;
-#ifdef SBP2_NEED_LOGIN_DESCRIPTOR_WORKAROUND
- scsi_id->reconnect_orb->status_FIFO_lo = cpu_to_le32((u32)SBP2_STATUS_FIFO_ADDRESS_LO);
- scsi_id->reconnect_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | cpu_to_le16(SBP2_STATUS_FIFO_ADDRESS_HI));
-#else
scsi_id->reconnect_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO;
- scsi_id->reconnect_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI);
-#endif
-
+ scsi_id->reconnect_orb->status_FIFO_hi =
+ (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI);
+
/*
* Byte swap ORB if necessary
*/
@@ -2020,20 +1509,22 @@ static int sbp2_reconnect_device(struct sbp2scsi_host_info *hi, struct scsi_id_i
data[1] = scsi_id->reconnect_orb_dma;
sbp2util_cpu_to_be32_buffer(data, 8);
- hpsb_write(hi->host, LOCAL_BUS | scsi_id->node_id, scsi_id->sbp2_management_agent_addr, data, 8);
+ hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, scsi_id->sbp2_management_agent_addr, data, 8);
/*
- * Wait for reconnect status... but, only if the device has not already reconnected (some devices are fast)
+ * Wait for reconnect status... but, only if the device has not
+ * already reconnected (some devices are fast).
*/
save_flags(flags);
cli();
- if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) {
- interruptible_sleep_on_timeout(&scsi_id->sbp2_login_wait, HZ); /* one second timeout */
- }
+ /* One second timout */
+ if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma)
+ sleep_on_timeout(&scsi_id->sbp2_login_wait, HZ);
restore_flags(flags);
/*
- * Match status to the reconnect orb. If they do not match, it's probably because the reconnect timed-out
+ * Match status to the reconnect orb. If they do not match, it's
+ * probably because the reconnect timed-out.
*/
if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) {
SBP2_ERR("sbp2: Error reconnecting to SBP-2 device - reconnect timed-out");
@@ -2058,7 +1549,8 @@ static int sbp2_reconnect_device(struct sbp2scsi_host_info *hi, struct scsi_id_i
}
/*
- * This function is called in order to set the busy timeout (number of retries to attempt) on the sbp2 device.
+ * This function is called in order to set the busy timeout (number of
+ * retries to attempt) on the sbp2 device.
*/
static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id)
{
@@ -2071,7 +1563,7 @@ static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_i
*/
data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE);
- if (hpsb_write(hi->host, LOCAL_BUS | scsi_id->node_id, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) {
+ if (hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) {
SBP2_ERR("sbp2: sbp2_set_busy_timeout error");
}
@@ -2079,158 +1571,100 @@ static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_i
}
/*
- * This function is called to parse sbp2 device's config rom unit directory. Used to determine
- * things like sbp2 management agent offset, and command set used (SCSI or RBC).
+ * This function is called to parse sbp2 device's config rom unit
+ * directory. Used to determine things like sbp2 management agent offset,
+ * and command set used (SCSI or RBC).
*/
-static int sbp2_parse_unit_directory(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id)
+static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id)
{
- quadlet_t unit_directory_length, unit_directory_data;
- u64 unit_directory_addr;
- u32 i;
+ struct unit_directory *ud;
+ int i;
SBP2_DEBUG("sbp2: sbp2_parse_unit_directory");
- if (sbp2util_unit_directory(hi, LOCAL_BUS | scsi_id->node_id, &unit_directory_addr)) {
- SBP2_DEBUG("sbp2: Error reading unit directory address - bad status");
- return(-EIO);
- }
-
- /*
- * Read the size of the unit directory
- */
- if (sbp2util_read_quadlet(hi, LOCAL_BUS | scsi_id->node_id, unit_directory_addr,
- &unit_directory_length)) {
- SBP2_DEBUG("sbp2: Error reading unit directory length - bad status");
- return(-EIO);
- }
-
- unit_directory_length = ((be32_to_cpu(unit_directory_length)) >> 16);
-
- /*
- * Now, sweep through the unit directory looking for the management agent offset
- * Give up if we hit any error or somehow miss it...
- */
- for (i=0; i<unit_directory_length; i++) {
-
- if (sbp2util_read_quadlet(hi, LOCAL_BUS | scsi_id->node_id, unit_directory_addr + (i<<2) + 4,
- &unit_directory_data)) {
- SBP2_DEBUG("sbp2: Error reading unit directory - bad status");
- return(-EIO);
- }
-
- /*
- * Handle different fields in the unit directory, based on keys
- */
- unit_directory_data = be32_to_cpu(unit_directory_data);
- switch (unit_directory_data >> 24) {
-
- case SBP2_CSR_OFFSET_KEY:
-
- /*
- * Save off the management agent address
- */
- scsi_id->sbp2_management_agent_addr = CONFIG_ROM_INITIAL_MEMORY_SPACE +
- ((unit_directory_data & 0x00ffffff) << 2);
-
- SBP2_DEBUG("sbp2: sbp2_management_agent_addr = %x", (unsigned int) scsi_id->sbp2_management_agent_addr);
- break;
-
- case SBP2_COMMAND_SET_SPEC_ID_KEY:
-
- /*
- * Command spec organization
- */
- scsi_id->sbp2_command_set_spec_id = unit_directory_data & 0xffffff;
- SBP2_DEBUG("sbp2: sbp2_command_set_spec_id = %x", (unsigned int) scsi_id->sbp2_command_set_spec_id);
- break;
-
- case SBP2_COMMAND_SET_KEY:
+ ud = scsi_id->ud;
- /*
- * Command set used by sbp2 device
- */
- scsi_id->sbp2_command_set = unit_directory_data & 0xffffff;
- SBP2_DEBUG("sbp2: sbp2_command_set = %x", (unsigned int) scsi_id->sbp2_command_set);
- break;
+ /* Handle different fields in the unit directory, based on keys */
+ for (i = 0; i < ud->arb_count; i++) {
+ switch (ud->arb_keys[i]) {
+ case SBP2_CSR_OFFSET_KEY:
+ /* Save off the management agent address */
+ scsi_id->sbp2_management_agent_addr =
+ CONFIG_ROM_INITIAL_MEMORY_SPACE +
+ (ud->arb_values[i] << 2);
- case SBP2_UNIT_CHARACTERISTICS_KEY:
-
- /*
- * Unit characterisitcs (orb related stuff that I'm not yet paying attention to)
- */
- scsi_id->sbp2_unit_characteristics = unit_directory_data & 0xffffff;
- SBP2_DEBUG("sbp2: sbp2_unit_characteristics = %x", (unsigned int) scsi_id->sbp2_unit_characteristics);
- break;
-
- case SBP2_DEVICE_TYPE_AND_LUN_KEY:
-
- /*
- * Device type and lun (used for detemining type of sbp2 device)
- */
- scsi_id->sbp2_device_type_and_lun = unit_directory_data & 0xffffff;
- SBP2_DEBUG("sbp2: sbp2_device_type_and_lun = %x", (unsigned int) scsi_id->sbp2_device_type_and_lun);
- break;
-
- case SBP2_UNIT_SPEC_ID_KEY:
+ SBP2_DEBUG("sbp2: sbp2_management_agent_addr = %x",
+ (unsigned int) scsi_id->sbp2_management_agent_addr);
+ break;
- /*
- * Unit spec id (used for protocol detection)
- */
- scsi_id->sbp2_unit_spec_id = unit_directory_data & 0xffffff;
- SBP2_DEBUG("sbp2: sbp2_unit_spec_id = %x", (unsigned int) scsi_id->sbp2_unit_spec_id);
- break;
+ case SBP2_COMMAND_SET_SPEC_ID_KEY:
+ /* Command spec organization */
+ scsi_id->sbp2_command_set_spec_id = ud->arb_values[i];
+ SBP2_DEBUG("sbp2: sbp2_command_set_spec_id = %x",
+ (unsigned int) scsi_id->sbp2_command_set_spec_id);
+ break;
- case SBP2_UNIT_SW_VERSION_KEY:
+ case SBP2_COMMAND_SET_KEY:
+ /* Command set used by sbp2 device */
+ scsi_id->sbp2_command_set = ud->arb_values[i];
+ SBP2_DEBUG("sbp2: sbp2_command_set = %x",
+ (unsigned int) scsi_id->sbp2_command_set);
+ break;
- /*
- * Unit sw version (used for protocol detection)
- */
- scsi_id->sbp2_unit_sw_version = unit_directory_data & 0xffffff;
- SBP2_DEBUG("sbp2: sbp2_unit_sw_version = %x", (unsigned int) scsi_id->sbp2_unit_sw_version);
- break;
+ case SBP2_UNIT_CHARACTERISTICS_KEY:
+ /*
+ * Unit characterisitcs (orb related stuff
+ * that I'm not yet paying attention to)
+ */
+ scsi_id->sbp2_unit_characteristics = ud->arb_values[i];
+ SBP2_DEBUG("sbp2: sbp2_unit_characteristics = %x",
+ (unsigned int) scsi_id->sbp2_unit_characteristics);
+ break;
- case SBP2_FIRMWARE_REVISION_KEY:
+ case SBP2_DEVICE_TYPE_AND_LUN_KEY:
+ /*
+ * Device type and lun (used for
+ * detemining type of sbp2 device)
+ */
+ scsi_id->sbp2_device_type_and_lun = ud->arb_values[i];
+ SBP2_DEBUG("sbp2: sbp2_device_type_and_lun = %x",
+ (unsigned int) scsi_id->sbp2_device_type_and_lun);
+ break;
- /*
- * Firmware revision (used to find broken devices). If the vendor id is 0xa0b8
- * (Symbios vendor id), then we have a bridge with 128KB max transfer size limitation.
- */
- scsi_id->sbp2_firmware_revision = unit_directory_data & 0xffff00;
- if (scsi_id->sbp2_firmware_revision == SBP2_128KB_BROKEN_FIRMWARE) {
- SBP2_WARN("sbp2: warning: Bridge chipset supports 128KB max transfer size");
- }
- break;
+ case SBP2_FIRMWARE_REVISION_KEY:
+ /*
+ * Firmware revision (used to find broken
+ * devices). If the vendor id is 0xa0b8
+ * (Symbios vendor id), then we have a
+ * bridge with 128KB max transfer size
+ * limitation.
+ */
+ scsi_id->sbp2_firmware_revision = ud->arb_values[i];
+ if (scsi_id->sbp2_firmware_revision ==
+ SBP2_128KB_BROKEN_FIRMWARE) {
+ SBP2_WARN("sbp2: warning: Bridge chipset supports 128KB max transfer size");
+ }
+ break;
- default:
- break;
+ default:
+ break;
}
-
}
-
- return(0);
}
/*
- * This function is called in order to determine the max speed and packet size we can use in our ORBs.
+ * This function is called in order to determine the max speed and packet
+ * size we can use in our ORBs.
*/
static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id)
{
u8 speed_code;
- struct node_entry *ne;
+ unsigned int max_rec;
SBP2_DEBUG("sbp2: sbp2_max_speed_and_size");
- /* Get this nodes information */
- ne = hpsb_nodeid_get_entry(hi->host->node_id);
-
- if (!ne) {
- HPSB_ERR("sbp2: Unknown device, using S100, payload 512 bytes");
- scsi_id->speed_code = SPEED_100;
- scsi_id->max_payload_size = MAX_PAYLOAD_S100;
- return(0);
- }
-
- speed_code = ne->busopt.lnkspd;
+ speed_code = scsi_id->ne->busopt.lnkspd;
+ max_rec = scsi_id->ne->busopt.max_rec;
/* Bump down our speed if there is a module parameter forcing us slower */
if (speed_code > max_speed) {
@@ -2240,11 +1674,11 @@ static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id
/* Support the devices max_rec and max speed. We choose a setting
* that fits both values, since they may differ. */
- if (speed_code >= SPEED_400 && ne->busopt.max_rec >= MAX_REC_S400) {
+ if (speed_code >= SPEED_400 && max_rec >= MAX_REC_S400) {
HPSB_INFO("sbp2: SBP-2 device max speed S400 and payload 2KB");
scsi_id->speed_code = SPEED_400;
scsi_id->max_payload_size = MAX_PAYLOAD_S400;
- } else if (speed_code >= SPEED_200 && ne->busopt.max_rec >= MAX_REC_S200) {
+ } else if (speed_code >= SPEED_200 && max_rec >= MAX_REC_S200) {
HPSB_INFO("sbp2: SBP-2 device max speed S200 and payload 1KB");
scsi_id->speed_code = SPEED_200;
scsi_id->max_payload_size = MAX_PAYLOAD_S200;
@@ -2269,9 +1703,11 @@ static int sbp2_agent_reset(struct sbp2scsi_host_info *hi, struct scsi_id_instan
/*
* Ok, let's write to the target's management agent register
*/
- agent_reset_request_packet = sbp2util_allocate_write_request_packet(hi, LOCAL_BUS | scsi_id->node_id,
- scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET,
- 0, ntohl(SBP2_AGENT_RESET_DATA));
+ agent_reset_request_packet =
+ sbp2util_allocate_write_request_packet(hi, LOCAL_BUS | scsi_id->ne->nodeid,
+ scsi_id->sbp2_command_block_agent_addr +
+ SBP2_AGENT_RESET_OFFSET,
+ 0, ntohl(SBP2_AGENT_RESET_DATA));
if (!agent_reset_request_packet) {
SBP2_ERR("sbp2: sbp2util_allocate_write_request_packet failed");
@@ -2299,8 +1735,8 @@ static int sbp2_agent_reset(struct sbp2scsi_host_info *hi, struct scsi_id_instan
}
/*
- * This function is called to create the actual command orb and s/g list out of the
- * scsi command itself.
+ * This function is called to create the actual command orb and s/g list
+ * out of the scsi command itself.
*/
static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
struct scsi_id_instance_data *scsi_id,
@@ -2321,9 +1757,10 @@ static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
/*
* Set-up our command ORB..
*
- * NOTE: We're doing unrestricted page tables (s/g), as this is best performance
- * (at least with the devices I have). This means that data_size becomes the number
- * of s/g elements, and page_size should be zero (for unrestricted).
+ * NOTE: We're doing unrestricted page tables (s/g), as this is
+ * best performance (at least with the devices I have). This means
+ * that data_size becomes the number of s/g elements, and
+ * page_size should be zero (for unrestricted).
*/
command_orb->next_ORB_hi = 0xffffffff;
command_orb->next_ORB_lo = 0xffffffff;
@@ -2332,8 +1769,8 @@ static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
command_orb->misc |= ORB_SET_NOTIFY(1); /* Notify us when complete */
/*
- * Set-up our pagetable stuff... unfortunately, this has become messier than I'd like. Need to
- * clean this up a bit. ;-)
+ * Set-up our pagetable stuff... unfortunately, this has become
+ * messier than I'd like. Need to clean this up a bit. ;-)
*/
if (sbp2scsi_direction_table[*scsi_cmd] == ORB_DIRECTION_NO_DATA_TRANSFER) {
@@ -2405,13 +1842,15 @@ static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
}
}
- command_orb->misc |= ORB_SET_DATA_SIZE(sg_count); /* number of page table (s/g) elements */
+ /* Number of page table (s/g) elements */
+ command_orb->misc |= ORB_SET_DATA_SIZE(sg_count);
/*
* Byte swap page tables if necessary
*/
sbp2util_cpu_to_be32_buffer(scatter_gather_element,
- (sizeof(struct sbp2_unrestricted_page_table)) * sg_count);
+ (sizeof(struct sbp2_unrestricted_page_table)) *
+ sg_count);
}
@@ -2427,8 +1866,8 @@ static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
SBP2_DMA_ALLOC("single bulk");
/*
- * Handle case where we get a command w/o s/g enabled (but check
- * for transfers larger than 64K)
+ * Handle case where we get a command w/o s/g enabled (but
+ * check for transfers larger than 64K)
*/
if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
@@ -2438,7 +1877,8 @@ static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
command_orb->misc |= ORB_SET_DIRECTION(sbp2scsi_direction_table[*scsi_cmd]);
/*
- * Sanity, in case our direction table is not up-to-date
+ * Sanity, in case our direction table is not
+ * up-to-date
*/
if (!scsi_request_bufflen) {
command_orb->data_descriptor_hi = 0xffffffff;
@@ -2448,15 +1888,19 @@ static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
} else {
/*
- * Need to turn this into page tables, since the buffer is too large.
+ * Need to turn this into page tables, since the
+ * buffer is too large.
*/
command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
command_orb->data_descriptor_lo = command->sge_dma;
- command_orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1); /* use page tables (s/g) */
+
+ /* Use page tables (s/g) */
+ command_orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
command_orb->misc |= ORB_SET_DIRECTION(sbp2scsi_direction_table[*scsi_cmd]);
/*
- * fill out our sbp-2 page tables (and split up the large buffer)
+ * fill out our sbp-2 page tables (and split up
+ * the large buffer)
*/
sg_count = 0;
sg_len = scsi_request_bufflen;
@@ -2476,7 +1920,8 @@ static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
sg_count++;
}
- command_orb->misc |= ORB_SET_DATA_SIZE(sg_count); /* number of page table (s/g) elements */
+ /* Number of page table (s/g) elements */
+ command_orb->misc |= ORB_SET_DATA_SIZE(sg_count);
/*
* Byte swap page tables if necessary
@@ -2524,11 +1969,12 @@ static int sbp2_link_orb_command(struct sbp2scsi_host_info *hi, struct scsi_id_i
/*
* Ok, let's write to the target's management agent register
*/
- if (!hi->bus_reset_in_progress) {
+ if (hpsb_node_entry_valid(scsi_id->ne)) {
- command_request_packet = sbp2util_allocate_write_request_packet(hi, LOCAL_BUS | scsi_id->node_id,
- scsi_id->sbp2_command_block_agent_addr + SBP2_ORB_POINTER_OFFSET,
- 8, 0);
+ command_request_packet =
+ sbp2util_allocate_write_request_packet(hi, LOCAL_BUS | scsi_id->ne->nodeid,
+ scsi_id->sbp2_command_block_agent_addr +
+ SBP2_ORB_POINTER_OFFSET, 8, 0);
if (!command_request_packet) {
SBP2_ERR("sbp2: sbp2util_allocate_write_request_packet failed");
@@ -2561,16 +2007,19 @@ static int sbp2_link_orb_command(struct sbp2scsi_host_info *hi, struct scsi_id_i
* modifying these next orb pointers, as they are accessed
* both by the sbp2 device and us.
*/
- scsi_id->last_orb->next_ORB_lo = cpu_to_be32(command->command_orb_dma);
- scsi_id->last_orb->next_ORB_hi = 0x0; /* Tells hardware that this pointer is valid */
-
+ scsi_id->last_orb->next_ORB_lo =
+ cpu_to_be32(command->command_orb_dma);
+ /* Tells hardware that this pointer is valid */
+ scsi_id->last_orb->next_ORB_hi = 0x0;
+
/*
- * Only ring the doorbell if we need to (first parts of linked orbs don't need this)
+ * Only ring the doorbell if we need to (first parts of
+ * linked orbs don't need this).
*/
- if (!command->linked && !hi->bus_reset_in_progress) {
+ if (!command->linked && hpsb_node_entry_valid(scsi_id->ne)) {
command_request_packet = sbp2util_allocate_write_request_packet(hi,
- LOCAL_BUS | scsi_id->node_id,
+ LOCAL_BUS | scsi_id->ne->nodeid,
scsi_id->sbp2_command_block_agent_addr + SBP2_DOORBELL_OFFSET,
0, cpu_to_be32(command->command_orb_dma));
@@ -2610,8 +2059,8 @@ static int sbp2_send_command(struct sbp2scsi_host_info *hi, struct scsi_id_insta
SBP2_DEBUG("sbp2: SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg);
/*
- * Check for broken devices that can't handle greater than 128K transfers, and deal with them in a
- * hacked ugly way.
+ * Check for broken devices that can't handle greater than 128K
+ * transfers, and deal with them in a hacked ugly way.
*/
if ((scsi_id->sbp2_firmware_revision == SBP2_128KB_BROKEN_FIRMWARE) &&
(SCpnt->request_bufflen > SBP2_BROKEN_FIRMWARE_MAX_TRANSFER) &&
@@ -2620,7 +2069,8 @@ static int sbp2_send_command(struct sbp2scsi_host_info *hi, struct scsi_id_insta
(*cmd == 0x28 || *cmd == 0x2a || *cmd == 0x0a || *cmd == 0x08)) {
/*
- * Darn, a broken device. We'll need to split up the transfer ourselves
+ * Darn, a broken device. We'll need to split up the
+ * transfer ourselves.
*/
sbp2_send_split_command(hi, scsi_id, SCpnt, done);
return(0);
@@ -2637,13 +2087,12 @@ static int sbp2_send_command(struct sbp2scsi_host_info *hi, struct scsi_id_insta
/*
* Now actually fill in the comamnd orb and sbp2 s/g list
*/
- sbp2_create_command_orb(hi, scsi_id, command, cmd, SCpnt->use_sg,
- SCpnt->request_bufflen, SCpnt->request_buffer,
- scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
-
+ sbp2_create_command_orb(hi, scsi_id, command, cmd, SCpnt->use_sg,
+ SCpnt->request_bufflen, SCpnt->request_buffer,
+ scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
/*
- * Update our cdb if necessary (to handle sbp2 RBC command set differences).
- * This is where the command set hacks go! =)
+ * Update our cdb if necessary (to handle sbp2 RBC command set
+ * differences). This is where the command set hacks go! =)
*/
if ((device_type == TYPE_DISK) ||
(device_type == TYPE_SDAD) ||
@@ -2665,7 +2114,8 @@ static int sbp2_send_command(struct sbp2scsi_host_info *hi, struct scsi_id_insta
}
/*
- * This function is called for broken sbp2 device, where we have to break up large transfers.
+ * This function is called for broken sbp2 device, where we have to break
+ * up large transfers.
*/
static int sbp2_send_split_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id,
Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
@@ -2779,8 +2229,8 @@ static int sbp2_send_split_command(struct sbp2scsi_host_info *hi, struct scsi_id
}
/*
- * This function deals with command set differences between Linux scsi command set and sbp2 RBC
- * command set.
+ * This function deals with command set differences between Linux scsi
+ * command set and sbp2 RBC command set.
*/
static void sbp2_check_sbp2_command(unchar *cmd)
{
@@ -3001,9 +2451,9 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
*/
for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
if (hi->scsi_id[i]) {
- if (hi->scsi_id[i]->node_id == (nodeid & NODE_MASK)) {
+ if ((hi->scsi_id[i]->ne->nodeid & NODE_MASK) == (nodeid & NODE_MASK)) {
scsi_id = hi->scsi_id[i];
- SBP2_DEBUG("sbp2: SBP-2 status write from node %x", scsi_id->node_id);
+ SBP2_DEBUG("sbp2: SBP-2 status write from node %x", scsi_id->ne->nodeid);
break;
}
}
@@ -3089,6 +2539,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
return(RCODE_COMPLETE);
}
+
/**************************************
* SCSI interface related section
@@ -3121,18 +2572,8 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
scsi_id = hi->scsi_id[SCpnt->target];
/*
- * Save off the command if this is the initial bus scan... so that we can
- * complete it after we find all our sbp2 devices on the 1394 bus
- */
- if (!no_bus_scan && !hi->initial_scsi_bus_scan_complete) {
- hi->bus_scan_SCpnt = SCpnt;
- hi->bus_scan_done = done;
- return(0);
- }
-
- /*
- * If scsi_id is null, it means there is no device in this slot, so we should return
- * selection timeout.
+ * If scsi_id is null, it means there is no device in this slot,
+ * so we should return selection timeout.
*/
if (!scsi_id) {
SCpnt->result = DID_NO_CONNECT << 16;
@@ -3141,7 +2582,8 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
}
/*
- * Until we handle multiple luns, just return selection time-out to any IO directed at non-zero LUNs
+ * Until we handle multiple luns, just return selection time-out
+ * to any IO directed at non-zero LUNs
*/
if (SCpnt->lun) {
SCpnt->result = DID_NO_CONNECT << 16;
@@ -3150,7 +2592,8 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
}
/*
- * Check for request sense command, and handle it here (autorequest sense)
+ * Check for request sense command, and handle it here
+ * (autorequest sense)
*/
if (SCpnt->cmnd[0] == REQUEST_SENSE) {
SBP2_DEBUG("sbp2: REQUEST_SENSE");
@@ -3161,9 +2604,10 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
}
/*
- * Check to see if there is a command in progress and just return busy (to be queued later)
+ * Check to see if there is a command in progress and just return
+ * busy (to be queued later)
*/
- if (hi->bus_reset_in_progress) {
+ if (!hpsb_node_entry_valid(scsi_id->ne)) {
SBP2_ERR("sbp2: Bus reset in progress - rejecting command");
SCpnt->result = DID_BUS_BUSY << 16;
done (SCpnt);
@@ -3184,9 +2628,11 @@ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
}
/*
- * This function is called in order to complete all outstanding SBP-2 commands (in case of resets, etc.).
+ * This function is called in order to complete all outstanding SBP-2
+ * commands (in case of resets, etc.).
*/
-static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id,
+static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi,
+ struct scsi_id_instance_data *scsi_id,
u32 status)
{
struct list_head *lh;
@@ -3210,7 +2656,7 @@ static void sbp2scsi_complete_all_commands(struct sbp2scsi_host_info *hi, struct
}
/*
- * This function is called in order to complete a regular SBP-2 command.
+ * This function is called in order to complete a regular SBP-2 command.
*/
static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, u32 scsi_status,
Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
@@ -3226,10 +2672,11 @@ static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi
}
/*
- * If a bus reset is in progress and there was an error, don't complete the command,
- * just let it get retried at the end of the bus reset.
+ * If a bus reset is in progress and there was an error, don't
+ * complete the command, just let it get retried at the end of the
+ * bus reset.
*/
- if ((hi->bus_reset_in_progress) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
+ if (!hpsb_node_entry_valid(scsi_id->ne) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
SBP2_ERR("sbp2: Bus reset in progress - retry command later");
return;
}
@@ -3283,9 +2730,10 @@ static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi
}
/*
- * One more quick hack (not enabled by default). Some sbp2 devices do not support
- * mode sense. Turn-on this hack to allow the device to pass the sd driver's
- * write-protect test (so that you can mount the device rw).
+ * One more quick hack (not enabled by default). Some sbp2 devices
+ * do not support mode sense. Turn-on this hack to allow the
+ * device to pass the sd driver's write-protect test (so that you
+ * can mount the device rw).
*/
if (mode_sense_hack && SCpnt->result != DID_OK && SCpnt->cmnd[0] == MODE_SENSE) {
SBP2_INFO("sbp2: Returning success to mode sense command");
@@ -3295,17 +2743,18 @@ static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi
}
/*
- * If a bus reset is in progress and there was an error, complete the command
- * as busy so that it will get retried.
+ * If a bus reset is in progress and there was an error, complete
+ * the command as busy so that it will get retried.
*/
- if ((hi->bus_reset_in_progress) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
+ if (!hpsb_node_entry_valid(scsi_id->ne) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
SBP2_ERR("sbp2: Completing command with busy (bus reset)");
SCpnt->result = DID_BUS_BUSY << 16;
}
/*
- * If a unit attention occurs, return busy status so it gets retried... it could have happened because
- * of a 1394 bus reset or hot-plug...
+ * If a unit attention occurs, return busy status so it gets
+ * retried... it could have happened because of a 1394 bus reset
+ * or hot-plug...
*/
if ((scsi_status == SBP2_SCSI_STATUS_CHECK_CONDITION) && (SCpnt->sense_buffer[2] == UNIT_ATTENTION)) {
SBP2_INFO("sbp2: UNIT ATTENTION - return busy");
@@ -3321,8 +2770,8 @@ static void sbp2scsi_complete_command(struct sbp2scsi_host_info *hi, struct scsi
}
/*
- * Called by scsi stack when something has really gone wrong.
- * Usually called when a command has timed-out for some reason.
+ * Called by scsi stack when something has really gone wrong. Usually
+ * called when a command has timed-out for some reason.
*/
static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
{
@@ -3336,8 +2785,9 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
if (scsi_id) {
/*
- * Right now, just return any matching command structures to the free pool (there may
- * be more than one because of broken up/linked commands).
+ * Right now, just return any matching command structures
+ * to the free pool (there may be more than one because of
+ * broken up/linked commands).
*/
sbp2_spin_lock(&hi->sbp2_command_lock, flags);
do {
@@ -3445,10 +2895,6 @@ static int sbp2scsi_detect (Scsi_Host_Template *tpnt)
global_scsi_tpnt->use_clustering = DISABLE_CLUSTERING;
}
- if (no_bus_scan) {
- SBP2_ERR("sbp2: Initial scsi bus scan deferred (no_bus_scan = 1)");
- }
-
if (mode_sense_hack) {
SBP2_ERR("sbp2: Mode sense emulation enabled (mode_sense_hack = 1)");
}
@@ -3457,21 +2903,19 @@ static int sbp2scsi_detect (Scsi_Host_Template *tpnt)
if (!sbp2_host_count) {
SBP2_ERR("sbp2: Please load the lower level IEEE-1394 driver (e.g. ohci1394) before sbp2...");
- if (sbp2_hl_handle) {
- hpsb_unregister_highlevel(sbp2_hl_handle);
- sbp2_hl_handle = NULL;
- }
+ sbp2_cleanup();
}
/*
- * Since we are returning this count, it means that sbp2 must be loaded "after" the
- * host adapter module...
+ * Since we are returning this count, it means that sbp2 must be
+ * loaded "after" the host adapter module...
*/
return(sbp2_host_count);
}
/*
- * This function is called from sbp2_add_host, and is where we register our scsi host
+ * This function is called from sbp2_add_host, and is where we register
+ * our scsi host
*/
static void sbp2scsi_register_scsi_host(struct sbp2scsi_host_info *hi)
{
@@ -3488,7 +2932,8 @@ static void sbp2scsi_register_scsi_host(struct sbp2scsi_host_info *hi)
shpnt = scsi_register (global_scsi_tpnt, sizeof(void *));
/*
- * If successful, save off a context (to be used when SCSI commands are received)
+ * If successful, save off a context (to be used when SCSI
+ * commands are received)
*/
if (shpnt) {
shpnt->hostdata[0] = (unsigned long)hi;
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index 9df0ecc354b3..c1fc8dd29fe3 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -36,13 +36,6 @@
#define ORB_DIRECTION_READ_FROM_MEDIA 0x1
#define ORB_DIRECTION_NO_DATA_TRANSFER 0x2
-#define SPEED_S100 0x0
-#define SPEED_S200 0x1
-#define SPEED_S400 0x2
-#define SPEED_S800 0x3
-#define SPEED_S1600 0x4
-#define SPEED_S3200 0x5
-
/* 2^(MAX_PAYLOAD+1) = Maximum data transfer length */
#define MAX_PAYLOAD_S100 0x7
#define MAX_PAYLOAD_S200 0x8
@@ -232,8 +225,8 @@ struct sbp2_status_block {
* Unit spec id and sw version entry for SBP-2 devices
*/
-#define SBP2_UNIT_SPEC_ID_ENTRY 0x1200609e
-#define SBP2_SW_VERSION_ENTRY 0x13010483
+#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e
+#define SBP2_SW_VERSION_ENTRY 0x00010483
/*
* Miscellaneous general config rom related defines
@@ -243,11 +236,8 @@ struct sbp2_status_block {
#define CONFIG_ROM_BASE_ADDRESS 0xfffff0000400ULL
#define CONFIG_ROM_ROOT_DIR_BASE 0xfffff0000414ULL
-#define CONFIG_ROM_SIGNATURE_ADDRESS 0xfffff0000404ULL
#define CONFIG_ROM_UNIT_DIRECTORY_OFFSET 0xfffff0000424ULL
-#define IEEE1394_CONFIG_ROM_SIGNATURE 0x31333934
-
#define SBP2_128KB_BROKEN_FIRMWARE 0xa0b800
#define SBP2_BROKEN_FIRMWARE_MAX_TRANSFER 0x20000
@@ -350,6 +340,8 @@ struct sbp2_command_info {
* Information needed on a per scsi id basis (one for each sbp2 device)
*/
struct scsi_id_instance_data {
+ /* SCSI ID */
+ int id;
/*
* Various sbp2 specific structures
@@ -368,18 +360,15 @@ struct scsi_id_instance_data {
/*
* Stuff we need to know about the sbp2 device itself
*/
- u64 node_unique_id;
u64 sbp2_management_agent_addr;
u64 sbp2_command_block_agent_addr;
- u32 node_id;
u32 speed_code;
u32 max_payload_size;
/*
* Values pulled from the device's unit directory
*/
- u32 sbp2_unit_spec_id;
- u32 sbp2_unit_sw_version;
+ struct unit_directory *ud;
u32 sbp2_command_set_spec_id;
u32 sbp2_command_set;
u32 sbp2_unit_characteristics;
@@ -391,12 +380,6 @@ struct scsi_id_instance_data {
*/
wait_queue_head_t sbp2_login_wait;
- /*
- * Flag noting whether the sbp2 device is currently validated (for use during
- * bus resets).
- */
- u32 validated;
-
/*
* Pool of command orbs, so we can have more than overlapped command per id
*/
@@ -405,6 +388,8 @@ struct scsi_id_instance_data {
struct list_head sbp2_command_orb_completed;
u32 sbp2_total_command_orbs;
+ /* Node entry, as retrieved from NodeMgr entries */
+ struct node_entry *ne;
};
/*
@@ -425,22 +410,6 @@ struct sbp2scsi_host_info {
spinlock_t sbp2_request_packet_lock;
/*
- * Flag indicating if a bus reset (or device detection) is in progress
- */
- u32 bus_reset_in_progress;
-
- /*
- * We currently use a kernel thread for dealing with bus resets and sbp2
- * device detection. We use this to wake up the thread when needed.
- */
- wait_queue_head_t sbp2_detection_wait;
-
- /*
- * PID of sbp2 detection kernel thread
- */
- int sbp2_detection_pid;
-
- /*
* Lists keeping track of inuse/free sbp2_request_packets. These structures are
* used for sending out sbp2 command and agent reset packets. We initially create
* a pool of request packets so that we don't have to do any kmallocs while in critical
@@ -450,13 +419,6 @@ struct sbp2scsi_host_info {
struct list_head sbp2_req_free;
/*
- * Stuff to keep track of the initial scsi bus scan (so that we don't miss it)
- */
- u32 initial_scsi_bus_scan_complete;
- Scsi_Cmnd *bus_scan_SCpnt;
- void (*bus_scan_done)(Scsi_Cmnd *);
-
- /*
* Here is the pool of request packets. All the hpsb packets (for 1394 bus transactions)
* are allocated at init and simply re-initialized when needed.
*/
@@ -476,9 +438,6 @@ struct sbp2scsi_host_info {
/*
* Various utility prototypes
*/
-static int sbp2util_read_quadlet(struct sbp2scsi_host_info *hi, nodeid_t node, u64 addr,
- quadlet_t *buffer);
-static int sbp2util_unit_directory(struct sbp2scsi_host_info *hi, nodeid_t node, u64 *addr);
static int sbp2util_create_request_packet_pool(struct sbp2scsi_host_info *hi);
static void sbp2util_remove_request_packet_pool(struct sbp2scsi_host_info *hi);
static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct sbp2scsi_host_info *hi,
@@ -500,23 +459,19 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
/*
* IEEE-1394 core driver related prototypes
*/
-static void sbp2_remove_unvalidated_devices(struct sbp2scsi_host_info *hi);
-static int sbp2_start_device(struct sbp2scsi_host_info *hi, int node_id);
-static int sbp2_check_device(struct sbp2scsi_host_info *hi, int node_id);
-static void sbp2_bus_reset_handler(void *context);
static void sbp2_add_host(struct hpsb_host *host);
static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host);
static void sbp2_remove_host(struct hpsb_host *host);
-static void sbp2_host_reset(struct hpsb_host *host);
-static int sbp2_detection_thread(void *__sbp2);
int sbp2_init(void);
void sbp2_cleanup(void);
-#if 0
-static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, quadlet_t *data,
- u64 addr, unsigned int length);
-static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data,
- u64 addr, unsigned int length);
-#endif
+static int sbp2_probe(struct unit_directory *ud);
+static void sbp2_disconnect(struct unit_directory *ud);
+static void sbp2_update(struct unit_directory *ud);
+static int sbp2_start_device(struct sbp2scsi_host_info *hi,
+ struct unit_directory *ud);
+static void sbp2_remove_device(struct sbp2scsi_host_info *hi,
+ struct scsi_id_instance_data *scsi_id);
+
/*
* SBP-2 protocol related prototypes
*/
@@ -543,7 +498,7 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense
static void sbp2_check_sbp2_command(unchar *cmd);
static void sbp2_check_sbp2_response(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id,
Scsi_Cmnd *SCpnt);
-static int sbp2_parse_unit_directory(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
+static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id);
static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 810d6ffb7659..d3df29b05d4c 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -103,7 +103,7 @@ struct dma_iso_ctx {
int ctxMatch;
wait_queue_head_t waitq;
spinlock_t lock;
- unsigned int syt_offset;
+ unsigned int syt_offset;
int flags;
};
@@ -488,24 +488,27 @@ static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags)
int i;
/* the first descriptor will read only 4 bytes */
- ir_prg[0].control = (0x280C << 16) | 4;
+ ir_prg[0].control = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
+ DMA_CTL_BRANCH | 4;
/* set the sync flag */
if (flags & VIDEO1394_SYNC_FRAMES)
- ir_prg[0].control |= 0x00030000;
+ ir_prg[0].control |= DMA_CTL_WAIT;
ir_prg[0].address = kvirt_to_bus(buf);
ir_prg[0].branchAddress = (virt_to_bus(&(ir_prg[1].control))
& 0xfffffff0) | 0x1;
/* the second descriptor will read PAGE_SIZE-4 bytes */
- ir_prg[1].control = (0x280C << 16) | (PAGE_SIZE-4);
+ ir_prg[1].control = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
+ DMA_CTL_BRANCH | (PAGE_SIZE-4);
ir_prg[1].address = kvirt_to_bus(buf+4);
ir_prg[1].branchAddress = (virt_to_bus(&(ir_prg[2].control))
& 0xfffffff0) | 0x1;
for (i=2;i<d->nb_cmd-1;i++) {
- ir_prg[i].control = (0x280C << 16) | PAGE_SIZE;
+ ir_prg[i].control = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
+ DMA_CTL_BRANCH | PAGE_SIZE;
ir_prg[i].address = kvirt_to_bus(buf+(i-1)*PAGE_SIZE);
ir_prg[i].branchAddress =
@@ -514,7 +517,8 @@ static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags)
}
/* the last descriptor will generate an interrupt */
- ir_prg[i].control = (0x283C << 16) | d->left_size;
+ ir_prg[i].control = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
+ DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size;
ir_prg[i].address = kvirt_to_bus(buf+(i-1)*PAGE_SIZE);
}
@@ -691,13 +695,14 @@ static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
d->last_used_cmd[n] = d->nb_cmd - 1;
for (i=0;i<d->nb_cmd;i++) {
- it_prg[i].begin.control = OUTPUT_MORE_IMMEDIATE | 8 ;
+ it_prg[i].begin.control = DMA_CTL_OUTPUT_MORE |
+ DMA_CTL_IMMEDIATE | 8 ;
it_prg[i].begin.address = 0;
it_prg[i].begin.status = 0;
it_prg[i].data[0] =
- (DMA_SPEED_100 << 16)
+ (SPEED_100 << 16)
| (/* tag */ 1 << 14)
| (d->channel << 8)
| (TCODE_ISO_DATA << 4);
@@ -706,7 +711,7 @@ static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
it_prg[i].data[2] = 0;
it_prg[i].data[3] = 0;
- it_prg[i].end.control = 0x100c0000;
+ it_prg[i].end.control = DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH;
it_prg[i].end.address =
kvirt_to_bus(buf+i*d->packet_size);
@@ -721,7 +726,8 @@ static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
}
else {
/* the last prg generates an interrupt */
- it_prg[i].end.control |= 0x08300000 | d->left_size;
+ it_prg[i].end.control |= DMA_CTL_UPDATE |
+ DMA_CTL_IRQ | d->left_size;
/* the last prg doesn't branch */
it_prg[i].begin.branchAddress = 0;
it_prg[i].end.branchAddress = 0;
@@ -761,7 +767,7 @@ static void initialize_dma_it_prg_var_packet_queue(
size = packet_sizes[i];
}
it_prg[i].data[1] = size << 16;
- it_prg[i].end.control = 0x100c0000;
+ it_prg[i].end.control = DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH;
if (i < d->nb_cmd-1 && packet_sizes[i+1] != 0) {
it_prg[i].end.control |= size;
@@ -773,7 +779,8 @@ static void initialize_dma_it_prg_var_packet_queue(
& 0xfffffff0) | 0x3;
} else {
/* the last prg generates an interrupt */
- it_prg[i].end.control |= 0x08300000 | size;
+ it_prg[i].end.control |= DMA_CTL_UPDATE |
+ DMA_CTL_IRQ | size;
/* the last prg doesn't branch */
it_prg[i].begin.branchAddress = 0;
it_prg[i].end.branchAddress = 0;
@@ -1560,7 +1567,6 @@ static int video1394_init(struct ti_ohci *ohci)
static void remove_card(struct video_card *video)
{
int i;
- unsigned long flags;
ohci1394_unregister_video(video->ohci, &video_tmpl);
@@ -1581,9 +1587,7 @@ static void remove_card(struct video_card *video)
}
kfree(video->it_context);
}
- spin_lock_irqsave(&video1394_cards_lock, flags);
list_del(&video->list);
- spin_unlock_irqrestore(&video1394_cards_lock, flags);
kfree(video);
}
@@ -1607,7 +1611,7 @@ static void video1394_remove_host (struct hpsb_host *host)
p = list_entry(lh, struct video_card, list);
if (p ->ohci == ohci) {
remove_card(p);
- return;
+ break;
}
}
}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 19c30390d089..01bc86ed9aae 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -140,7 +140,7 @@ static MD_LIST_HEAD(all_mddevs);
*/
dev_mapping_t mddev_map[MAX_MD_DEVS];
-void add_mddev_mapping (mddev_t * mddev, kdev_t dev, void *data)
+void add_mddev_mapping(mddev_t * mddev, kdev_t dev, void *data)
{
unsigned int minor = MINOR(dev);
@@ -148,7 +148,7 @@ void add_mddev_mapping (mddev_t * mddev, kdev_t dev, void *data)
MD_BUG();
return;
}
- if (mddev_map[minor].mddev != NULL) {
+ if (mddev_map[minor].mddev) {
MD_BUG();
return;
}
@@ -156,7 +156,7 @@ void add_mddev_mapping (mddev_t * mddev, kdev_t dev, void *data)
mddev_map[minor].data = data;
}
-void del_mddev_mapping (mddev_t * mddev, kdev_t dev)
+void del_mddev_mapping(mddev_t * mddev, kdev_t dev)
{
unsigned int minor = MINOR(dev);
@@ -172,7 +172,7 @@ void del_mddev_mapping (mddev_t * mddev, kdev_t dev)
mddev_map[minor].data = NULL;
}
-static int md_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
+static int md_make_request(request_queue_t *q, int rw, struct buffer_head * bh)
{
mddev_t *mddev = kdev_to_mddev(bh->b_rdev);
@@ -184,7 +184,7 @@ static int md_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
}
}
-static mddev_t * alloc_mddev (kdev_t dev)
+static mddev_t * alloc_mddev(kdev_t dev)
{
mddev_t *mddev;
@@ -195,7 +195,7 @@ static mddev_t * alloc_mddev (kdev_t dev)
mddev = (mddev_t *) kmalloc(sizeof(*mddev), GFP_KERNEL);
if (!mddev)
return NULL;
-
+
memset(mddev, 0, sizeof(*mddev));
mddev->__minor = MINOR(dev);
@@ -245,7 +245,7 @@ mdk_rdev_t * find_rdev(mddev_t * mddev, kdev_t dev)
static MD_LIST_HEAD(device_names);
-char * partition_name (kdev_t dev)
+char * partition_name(kdev_t dev)
{
struct gendisk *hd;
static char nomem [] = "<nomem>";
@@ -282,7 +282,7 @@ char * partition_name (kdev_t dev)
return dname->name;
}
-static unsigned int calc_dev_sboffset (kdev_t dev, mddev_t *mddev,
+static unsigned int calc_dev_sboffset(kdev_t dev, mddev_t *mddev,
int persistent)
{
unsigned int size = 0;
@@ -294,7 +294,7 @@ static unsigned int calc_dev_sboffset (kdev_t dev, mddev_t *mddev,
return size;
}
-static unsigned int calc_dev_size (kdev_t dev, mddev_t *mddev, int persistent)
+static unsigned int calc_dev_size(kdev_t dev, mddev_t *mddev, int persistent)
{
unsigned int size;
@@ -308,7 +308,7 @@ static unsigned int calc_dev_size (kdev_t dev, mddev_t *mddev, int persistent)
return size;
}
-static unsigned int zoned_raid_size (mddev_t *mddev)
+static unsigned int zoned_raid_size(mddev_t *mddev)
{
unsigned int mask;
mdk_rdev_t * rdev;
@@ -338,7 +338,7 @@ static unsigned int zoned_raid_size (mddev_t *mddev)
* provide data have to be able to deal with loss of individual
* disks, so they do their checking themselves.
*/
-int md_check_ordering (mddev_t *mddev)
+int md_check_ordering(mddev_t *mddev)
{
int i, c;
mdk_rdev_t *rdev;
@@ -349,8 +349,8 @@ int md_check_ordering (mddev_t *mddev)
*/
ITERATE_RDEV(mddev,rdev,tmp) {
if (rdev->faulty) {
- printk("md: md%d's device %s faulty, aborting.\n",
- mdidx(mddev), partition_name(rdev->dev));
+ printk(KERN_ERR "md: md%d's device %s faulty, aborting.\n",
+ mdidx(mddev), partition_name(rdev->dev));
goto abort;
}
}
@@ -364,7 +364,7 @@ int md_check_ordering (mddev_t *mddev)
goto abort;
}
if (mddev->nb_dev != mddev->sb->raid_disks) {
- printk("md: md%d, array needs %d disks, has %d, aborting.\n",
+ printk(KERN_ERR "md: md%d, array needs %d disks, has %d, aborting.\n",
mdidx(mddev), mddev->sb->raid_disks, mddev->nb_dev);
goto abort;
}
@@ -378,13 +378,13 @@ int md_check_ordering (mddev_t *mddev)
c++;
}
if (!c) {
- printk("md: md%d, missing disk #%d, aborting.\n",
- mdidx(mddev), i);
+ printk(KERN_ERR "md: md%d, missing disk #%d, aborting.\n",
+ mdidx(mddev), i);
goto abort;
}
if (c > 1) {
- printk("md: md%d, too many disks #%d, aborting.\n",
- mdidx(mddev), i);
+ printk(KERN_ERR "md: md%d, too many disks #%d, aborting.\n",
+ mdidx(mddev), i);
goto abort;
}
}
@@ -393,7 +393,7 @@ abort:
return 1;
}
-static void remove_descriptor (mdp_disk_t *disk, mdp_super_t *sb)
+static void remove_descriptor(mdp_disk_t *disk, mdp_super_t *sb)
{
if (disk_active(disk)) {
sb->working_disks--;
@@ -426,7 +426,7 @@ static void remove_descriptor (mdp_disk_t *disk, mdp_super_t *sb)
#define BAD_CSUM KERN_WARNING \
"md: invalid superblock checksum on %s\n"
-static int alloc_array_sb (mddev_t * mddev)
+static int alloc_array_sb(mddev_t * mddev)
{
if (mddev->sb) {
MD_BUG();
@@ -440,14 +440,14 @@ static int alloc_array_sb (mddev_t * mddev)
return 0;
}
-static int alloc_disk_sb (mdk_rdev_t * rdev)
+static int alloc_disk_sb(mdk_rdev_t * rdev)
{
if (rdev->sb)
MD_BUG();
rdev->sb = (mdp_super_t *) __get_free_page(GFP_KERNEL);
if (!rdev->sb) {
- printk (OUT_OF_MEM);
+ printk(OUT_OF_MEM);
return -EINVAL;
}
md_clear_page(rdev->sb);
@@ -455,7 +455,7 @@ static int alloc_disk_sb (mdk_rdev_t * rdev)
return 0;
}
-static void free_disk_sb (mdk_rdev_t * rdev)
+static void free_disk_sb(mdk_rdev_t * rdev)
{
if (rdev->sb) {
free_page((unsigned long) rdev->sb);
@@ -468,7 +468,7 @@ static void free_disk_sb (mdk_rdev_t * rdev)
}
}
-static int read_disk_sb (mdk_rdev_t * rdev)
+static int read_disk_sb(mdk_rdev_t * rdev)
{
int ret = -EINVAL;
struct buffer_head *bh = NULL;
@@ -479,15 +479,14 @@ static int read_disk_sb (mdk_rdev_t * rdev)
if (!rdev->sb) {
MD_BUG();
goto abort;
- }
-
+ }
+
/*
* Calculate the position of the superblock,
* it's at the end of the disk
*/
sb_offset = calc_dev_sboffset(rdev->dev, rdev->mddev, 1);
rdev->sb_offset = sb_offset;
- printk("(read) %s's sb offset: %ld", partition_name(dev), sb_offset);
fsync_dev(dev);
set_blocksize (dev, MD_SB_BYTES);
bh = bread (dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES);
@@ -496,10 +495,10 @@ static int read_disk_sb (mdk_rdev_t * rdev)
sb = (mdp_super_t *) bh->b_data;
memcpy (rdev->sb, sb, MD_SB_BYTES);
} else {
- printk (NO_SB,partition_name(rdev->dev));
+ printk(NO_SB,partition_name(rdev->dev));
goto abort;
}
- printk(" [events: %08lx]\n", (unsigned long)rdev->sb->events_lo);
+ printk(KERN_INFO " [events: %08lx]\n", (unsigned long)rdev->sb->events_lo);
ret = 0;
abort:
if (bh)
@@ -507,7 +506,7 @@ abort:
return ret;
}
-static unsigned int calc_sb_csum (mdp_super_t * sb)
+static unsigned int calc_sb_csum(mdp_super_t * sb)
{
unsigned int disk_csum, csum;
@@ -522,7 +521,7 @@ static unsigned int calc_sb_csum (mdp_super_t * sb)
* Check one RAID superblock for generic plausibility
*/
-static int check_disk_sb (mdk_rdev_t * rdev)
+static int check_disk_sb(mdk_rdev_t * rdev)
{
mdp_super_t *sb;
int ret = -EINVAL;
@@ -534,13 +533,12 @@ static int check_disk_sb (mdk_rdev_t * rdev)
}
if (sb->md_magic != MD_SB_MAGIC) {
- printk (BAD_MAGIC, partition_name(rdev->dev));
+ printk(BAD_MAGIC, partition_name(rdev->dev));
goto abort;
}
if (sb->md_minor >= MAX_MD_DEVS) {
- printk (BAD_MINOR, partition_name(rdev->dev),
- sb->md_minor);
+ printk(BAD_MINOR, partition_name(rdev->dev), sb->md_minor);
goto abort;
}
@@ -590,7 +588,7 @@ static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)
static MD_LIST_HEAD(all_raid_disks);
static MD_LIST_HEAD(pending_raid_disks);
-static void bind_rdev_to_array (mdk_rdev_t * rdev, mddev_t * mddev)
+static void bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
{
mdk_rdev_t *same_pdev;
@@ -603,16 +601,16 @@ static void bind_rdev_to_array (mdk_rdev_t * rdev, mddev_t * mddev)
printk( KERN_WARNING
"md%d: WARNING: %s appears to be on the same physical disk as %s. True\n"
" protection against single-disk failure might be compromised.\n",
- mdidx(mddev), partition_name(rdev->dev),
+ mdidx(mddev), partition_name(rdev->dev),
partition_name(same_pdev->dev));
-
+
md_list_add(&rdev->same_set, &mddev->disks);
rdev->mddev = mddev;
mddev->nb_dev++;
- printk("md: bind<%s,%d>\n", partition_name(rdev->dev), mddev->nb_dev);
+ printk(KERN_INFO "md: bind<%s,%d>\n", partition_name(rdev->dev), mddev->nb_dev);
}
-static void unbind_rdev_from_array (mdk_rdev_t * rdev)
+static void unbind_rdev_from_array(mdk_rdev_t * rdev)
{
if (!rdev->mddev) {
MD_BUG();
@@ -621,7 +619,7 @@ static void unbind_rdev_from_array (mdk_rdev_t * rdev)
md_list_del(&rdev->same_set);
MD_INIT_LIST_HEAD(&rdev->same_set);
rdev->mddev->nb_dev--;
- printk("md: unbind<%s,%d>\n", partition_name(rdev->dev),
+ printk(KERN_INFO "md: unbind<%s,%d>\n", partition_name(rdev->dev),
rdev->mddev->nb_dev);
rdev->mddev = NULL;
}
@@ -633,13 +631,13 @@ static void unbind_rdev_from_array (mdk_rdev_t * rdev)
* inode is not enough, the SCSI module usage code needs
* an explicit open() on the device]
*/
-static int lock_rdev (mdk_rdev_t *rdev)
+static int lock_rdev(mdk_rdev_t *rdev)
{
int err = 0;
struct block_device *bdev;
bdev = bdget(rdev->dev);
- if (bdev == NULL)
+ if (!bdev)
return -ENOMEM;
err = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_RAW);
if (!err)
@@ -647,7 +645,7 @@ static int lock_rdev (mdk_rdev_t *rdev)
return err;
}
-static void unlock_rdev (mdk_rdev_t *rdev)
+static void unlock_rdev(mdk_rdev_t *rdev)
{
struct block_device *bdev = rdev->bdev;
rdev->bdev = NULL;
@@ -656,11 +654,11 @@ static void unlock_rdev (mdk_rdev_t *rdev)
blkdev_put(bdev, BDEV_RAW);
}
-void md_autodetect_dev (kdev_t dev);
+void md_autodetect_dev(kdev_t dev);
-static void export_rdev (mdk_rdev_t * rdev)
+static void export_rdev(mdk_rdev_t * rdev)
{
- printk("md: export_rdev(%s)\n",partition_name(rdev->dev));
+ printk(KERN_INFO "md: export_rdev(%s)\n",partition_name(rdev->dev));
if (rdev->mddev)
MD_BUG();
unlock_rdev(rdev);
@@ -668,7 +666,8 @@ static void export_rdev (mdk_rdev_t * rdev)
md_list_del(&rdev->all);
MD_INIT_LIST_HEAD(&rdev->all);
if (rdev->pending.next != &rdev->pending) {
- printk("md: (%s was pending)\n",partition_name(rdev->dev));
+ printk(KERN_INFO "md: (%s was pending)\n",
+ partition_name(rdev->dev));
md_list_del(&rdev->pending);
MD_INIT_LIST_HEAD(&rdev->pending);
}
@@ -680,13 +679,13 @@ static void export_rdev (mdk_rdev_t * rdev)
kfree(rdev);
}
-static void kick_rdev_from_array (mdk_rdev_t * rdev)
+static void kick_rdev_from_array(mdk_rdev_t * rdev)
{
unbind_rdev_from_array(rdev);
export_rdev(rdev);
}
-static void export_array (mddev_t *mddev)
+static void export_array(mddev_t *mddev)
{
struct md_list_head *tmp;
mdk_rdev_t *rdev;
@@ -708,7 +707,7 @@ static void export_array (mddev_t *mddev)
MD_BUG();
}
-static void free_mddev (mddev_t *mddev)
+static void free_mddev(mddev_t *mddev)
{
if (!mddev) {
MD_BUG();
@@ -751,45 +750,47 @@ static void print_sb(mdp_super_t *sb)
{
int i;
- printk("md: SB: (V:%d.%d.%d) ID:<%08x.%08x.%08x.%08x> CT:%08x\n",
+ printk(KERN_INFO "md: SB: (V:%d.%d.%d) ID:<%08x.%08x.%08x.%08x> CT:%08x\n",
sb->major_version, sb->minor_version, sb->patch_version,
sb->set_uuid0, sb->set_uuid1, sb->set_uuid2, sb->set_uuid3,
sb->ctime);
- printk("md: L%d S%08d ND:%d RD:%d md%d LO:%d CS:%d\n", sb->level,
+ printk(KERN_INFO "md: L%d S%08d ND:%d RD:%d md%d LO:%d CS:%d\n", sb->level,
sb->size, sb->nr_disks, sb->raid_disks, sb->md_minor,
sb->layout, sb->chunk_size);
- printk("md: UT:%08x ST:%d AD:%d WD:%d FD:%d SD:%d CSUM:%08x E:%08lx\n",
+ printk(KERN_INFO "md: UT:%08x ST:%d AD:%d WD:%d FD:%d SD:%d CSUM:%08x E:%08lx\n",
sb->utime, sb->state, sb->active_disks, sb->working_disks,
sb->failed_disks, sb->spare_disks,
sb->sb_csum, (unsigned long)sb->events_lo);
+ printk(KERN_INFO);
for (i = 0; i < MD_SB_DISKS; i++) {
mdp_disk_t *desc;
desc = sb->disks + i;
- if (desc->number || desc->major || desc->minor || desc->raid_disk || (desc->state && (desc->state != 4))) {
+ if (desc->number || desc->major || desc->minor ||
+ desc->raid_disk || (desc->state && (desc->state != 4))) {
printk(" D %2d: ", i);
print_desc(desc);
}
}
- printk("md: THIS: ");
+ printk(KERN_INFO "md: THIS: ");
print_desc(&sb->this_disk);
}
static void print_rdev(mdk_rdev_t *rdev)
{
- printk("md: rdev %s: O:%s, SZ:%08ld F:%d DN:%d ",
+ printk(KERN_INFO "md: rdev %s: O:%s, SZ:%08ld F:%d DN:%d ",
partition_name(rdev->dev), partition_name(rdev->old_dev),
rdev->size, rdev->faulty, rdev->desc_nr);
if (rdev->sb) {
- printk("md: rdev superblock:\n");
+ printk(KERN_INFO "md: rdev superblock:\n");
print_sb(rdev->sb);
} else
- printk("md: no rdev superblock!\n");
+ printk(KERN_INFO "md: no rdev superblock!\n");
}
-void md_print_devices (void)
+void md_print_devices(void)
{
struct md_list_head *tmp, *tmp2;
mdk_rdev_t *rdev;
@@ -818,7 +819,7 @@ void md_print_devices (void)
printk("\n");
}
-static int sb_equal ( mdp_super_t *sb1, mdp_super_t *sb2)
+static int sb_equal(mdp_super_t *sb1, mdp_super_t *sb2)
{
int ret;
mdp_super_t *tmp1, *tmp2;
@@ -867,7 +868,7 @@ static int uuid_equal(mdk_rdev_t *rdev1, mdk_rdev_t *rdev2)
return 0;
}
-static mdk_rdev_t * find_rdev_all (kdev_t dev)
+static mdk_rdev_t * find_rdev_all(kdev_t dev)
{
struct md_list_head *tmp;
mdk_rdev_t *rdev;
@@ -908,8 +909,8 @@ static int write_disk_sb(mdk_rdev_t * rdev)
dev = rdev->dev;
sb_offset = calc_dev_sboffset(dev, rdev->mddev, 1);
if (rdev->sb_offset != sb_offset) {
- printk("%s's sb offset has changed from %ld to %ld, skipping\n",
- partition_name(dev), rdev->sb_offset, sb_offset);
+ printk(KERN_INFO "%s's sb offset has changed from %ld to %ld, skipping\n",
+ partition_name(dev), rdev->sb_offset, sb_offset);
goto skip;
}
/*
@@ -919,12 +920,12 @@ static int write_disk_sb(mdk_rdev_t * rdev)
*/
size = calc_dev_size(dev, rdev->mddev, 1);
if (size != rdev->size) {
- printk("%s's size has changed from %ld to %ld since import, skipping\n",
- partition_name(dev), rdev->size, size);
+ printk(KERN_INFO "%s's size has changed from %ld to %ld since import, skipping\n",
+ partition_name(dev), rdev->size, size);
goto skip;
}
- printk("(write) %s's sb offset: %ld\n", partition_name(dev), sb_offset);
+ printk(KERN_INFO "(write) %s's sb offset: %ld\n", partition_name(dev), sb_offset);
fsync_dev(dev);
set_blocksize(dev, MD_SB_BYTES);
bh = getblk(dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES);
@@ -945,7 +946,7 @@ static int write_disk_sb(mdk_rdev_t * rdev)
skip:
return 0;
}
-#undef GETBLK_FAILED
+#undef GETBLK_FAILED
static void set_this_disk(mddev_t *mddev, mdk_rdev_t *rdev)
{
@@ -1025,7 +1026,7 @@ repeat:
err = 0;
ITERATE_RDEV(mddev,rdev,tmp) {
- printk("md: ");
+ printk(KERN_INFO "md: ");
if (rdev->faulty)
printk("(skipping faulty ");
if (rdev->alias_device)
@@ -1041,10 +1042,10 @@ repeat:
}
if (err) {
if (--count) {
- printk("md: errors occurred during superblock update, repeating\n");
+ printk(KERN_ERR "md: errors occurred during superblock update, repeating\n");
goto repeat;
}
- printk("md: excessive errors occurred during superblock update, exiting\n");
+ printk(KERN_ERR "md: excessive errors occurred during superblock update, exiting\n");
}
return 0;
}
@@ -1059,7 +1060,7 @@ repeat:
*
* a faulty rdev _never_ has rdev->sb set.
*/
-static int md_import_device (kdev_t newdev, int on_disk)
+static int md_import_device(kdev_t newdev, int on_disk)
{
int err;
mdk_rdev_t *rdev;
@@ -1070,13 +1071,13 @@ static int md_import_device (kdev_t newdev, int on_disk)
rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL);
if (!rdev) {
- printk("md: could not alloc mem for %s!\n", partition_name(newdev));
+ printk(KERN_ERR "md: could not alloc mem for %s!\n", partition_name(newdev));
return -ENOMEM;
}
memset(rdev, 0, sizeof(*rdev));
if (is_mounted(newdev)) {
- printk("md: can not import %s, has active inodes!\n",
+ printk(KERN_WARNING "md: can not import %s, has active inodes!\n",
partition_name(newdev));
err = -EBUSY;
goto abort_free;
@@ -1087,7 +1088,7 @@ static int md_import_device (kdev_t newdev, int on_disk)
rdev->dev = newdev;
if (lock_rdev(rdev)) {
- printk("md: could not lock %s, zero-size? Marking faulty.\n",
+ printk(KERN_ERR "md: could not lock %s, zero-size? Marking faulty.\n",
partition_name(newdev));
err = -EINVAL;
goto abort_free;
@@ -1099,7 +1100,7 @@ static int md_import_device (kdev_t newdev, int on_disk)
if (blk_size[MAJOR(newdev)])
size = blk_size[MAJOR(newdev)][MINOR(newdev)];
if (!size) {
- printk("md: %s has zero size, marking faulty!\n",
+ printk(KERN_WARNING "md: %s has zero size, marking faulty!\n",
partition_name(newdev));
err = -EINVAL;
goto abort_free;
@@ -1107,13 +1108,13 @@ static int md_import_device (kdev_t newdev, int on_disk)
if (on_disk) {
if ((err = read_disk_sb(rdev))) {
- printk("md: could not read %s's sb, not importing!\n",
- partition_name(newdev));
+ printk(KERN_WARNING "md: could not read %s's sb, not importing!\n",
+ partition_name(newdev));
goto abort_free;
}
if ((err = check_disk_sb(rdev))) {
- printk("md: %s has invalid sb, not importing!\n",
- partition_name(newdev));
+ printk(KERN_WARNING "md: %s has invalid sb, not importing!\n",
+ partition_name(newdev));
goto abort_free;
}
@@ -1162,7 +1163,7 @@ abort_free:
#define UNKNOWN_LEVEL KERN_ERR \
"md: md%d: unsupported raid level %d\n"
-static int analyze_sbs (mddev_t * mddev)
+static int analyze_sbs(mddev_t * mddev)
{
int out_of_date = 0, i, first;
struct md_list_head *tmp, *tmp2;
@@ -1197,7 +1198,7 @@ static int analyze_sbs (mddev_t * mddev)
continue;
}
if (!sb_equal(sb, rdev->sb)) {
- printk (INCONSISTENT, partition_name(rdev->dev));
+ printk(INCONSISTENT, partition_name(rdev->dev));
kick_rdev_from_array(rdev);
continue;
}
@@ -1227,7 +1228,8 @@ static int analyze_sbs (mddev_t * mddev)
rdev->sb->events_hi--;
}
- printk("md: %s's event counter: %08lx\n", partition_name(rdev->dev),
+ printk(KERN_INFO "md: %s's event counter: %08lx\n",
+ partition_name(rdev->dev),
(unsigned long)rdev->sb->events_lo);
if (!freshest) {
freshest = rdev;
@@ -1246,7 +1248,7 @@ static int analyze_sbs (mddev_t * mddev)
}
if (out_of_date) {
printk(OUT_OF_DATE);
- printk("md: freshest: %s\n", partition_name(freshest->dev));
+ printk(KERN_INFO "md: freshest: %s\n", partition_name(freshest->dev));
}
memcpy (sb, freshest->sb, sizeof(*sb));
@@ -1265,7 +1267,7 @@ static int analyze_sbs (mddev_t * mddev)
ev2 = md_event(sb);
++ev1;
if (ev1 < ev2) {
- printk("md: kicking non-fresh %s from array!\n",
+ printk(KERN_WARNING "md: kicking non-fresh %s from array!\n",
partition_name(rdev->dev));
kick_rdev_from_array(rdev);
continue;
@@ -1291,7 +1293,8 @@ static int analyze_sbs (mddev_t * mddev)
((ev1 == ev2) || (ev1 == ev3))) {
mdp_disk_t *desc;
- printk("md: device name has changed from %s to %s since last import!\n", partition_name(rdev->old_dev), partition_name(rdev->dev));
+ printk(KERN_WARNING "md: device name has changed from %s to %s since last import!\n",
+ partition_name(rdev->old_dev), partition_name(rdev->dev));
if (rdev->desc_nr == -1) {
MD_BUG();
goto abort;
@@ -1338,7 +1341,7 @@ static int analyze_sbs (mddev_t * mddev)
ITERATE_RDEV(mddev,rdev,tmp) {
if (rdev->desc_nr != desc->number)
continue;
- printk("md%d: kicking faulty %s!\n",
+ printk(KERN_WARNING "md%d: kicking faulty %s!\n",
mdidx(mddev),partition_name(rdev->dev));
kick_rdev_from_array(rdev);
found = 1;
@@ -1347,7 +1350,7 @@ static int analyze_sbs (mddev_t * mddev)
if (!found) {
if (dev == MKDEV(0,0))
continue;
- printk("md%d: removing former faulty %s!\n",
+ printk(KERN_WARNING "md%d: removing former faulty %s!\n",
mdidx(mddev), partition_name(dev));
}
remove_descriptor(desc, sb);
@@ -1389,7 +1392,8 @@ static int analyze_sbs (mddev_t * mddev)
if (found)
continue;
- printk("md%d: former device %s is unavailable, removing from array!\n", mdidx(mddev), partition_name(dev));
+ printk(KERN_WARNING "md%d: former device %s is unavailable, removing from array!\n",
+ mdidx(mddev), partition_name(dev));
remove_descriptor(desc, sb);
}
@@ -1436,7 +1440,7 @@ static int analyze_sbs (mddev_t * mddev)
first = 0;
}
}
-
+
/*
* Kick all rdevs that are not in the
* descriptor array:
@@ -1445,7 +1449,7 @@ static int analyze_sbs (mddev_t * mddev)
if (rdev->desc_nr == -1)
kick_rdev_from_array(rdev);
}
-
+
/*
* Do a final reality check.
*/
@@ -1484,14 +1488,14 @@ static int analyze_sbs (mddev_t * mddev)
if (sb->major_version != MD_MAJOR_VERSION ||
sb->minor_version > MD_MINOR_VERSION) {
- printk (OLD_VERSION, mdidx(mddev), sb->major_version,
+ printk(OLD_VERSION, mdidx(mddev), sb->major_version,
sb->minor_version, sb->patch_version);
goto abort;
}
if ((sb->state != (1 << MD_SB_CLEAN)) && ((sb->level == 1) ||
(sb->level == 4) || (sb->level == 5)))
- printk (NOT_CLEAN_IGNORE, mdidx(mddev));
+ printk(NOT_CLEAN_IGNORE, mdidx(mddev));
return 0;
abort:
@@ -1503,7 +1507,7 @@ abort:
#undef OLD_VERSION
#undef OLD_LEVEL
-static int device_size_calculation (mddev_t * mddev)
+static int device_size_calculation(mddev_t * mddev)
{
int data_disks = 0, persistent;
unsigned int readahead;
@@ -1526,7 +1530,7 @@ static int device_size_calculation (mddev_t * mddev)
}
rdev->size = calc_dev_size(rdev->dev, mddev, persistent);
if (rdev->size < sb->chunk_size / 1024) {
- printk (KERN_WARNING
+ printk(KERN_WARNING
"md: Dev %s smaller than chunk_size: %ldk < %dk\n",
partition_name(rdev->dev),
rdev->size, sb->chunk_size / 1024);
@@ -1560,7 +1564,7 @@ static int device_size_calculation (mddev_t * mddev)
data_disks = sb->raid_disks-1;
break;
default:
- printk (UNKNOWN_LEVEL, mdidx(mddev), sb->level);
+ printk(UNKNOWN_LEVEL, mdidx(mddev), sb->level);
goto abort;
}
if (!md_size[mdidx(mddev)])
@@ -1599,7 +1603,7 @@ abort:
#define BAD_CHUNKSIZE KERN_ERR \
"no chunksize specified, see 'man raidtab'\n"
-static int do_md_run (mddev_t * mddev)
+static int do_md_run(mddev_t * mddev)
{
int pnum, err;
int chunk_size;
@@ -1663,7 +1667,8 @@ static int do_md_run (mddev_t * mddev)
}
} else
if (chunk_size)
- printk(KERN_INFO "md: RAID level %d does not need chunksize! Continuing anyway.\n", mddev->sb->level);
+ printk(KERN_INFO "md: RAID level %d does not need chunksize! Continuing anyway.\n",
+ mddev->sb->level);
if (pnum >= MAX_PERSONALITY) {
MD_BUG();
@@ -1700,7 +1705,7 @@ static int do_md_run (mddev_t * mddev)
continue;
invalidate_device(rdev->dev, 1);
if (get_hardsect_size(rdev->dev)
- > md_hardsect_sizes[mdidx(mddev)])
+ > md_hardsect_sizes[mdidx(mddev)])
md_hardsect_sizes[mdidx(mddev)] =
get_hardsect_size(rdev->dev);
}
@@ -1711,7 +1716,7 @@ static int do_md_run (mddev_t * mddev)
err = mddev->pers->run(mddev);
if (err) {
- printk("md: pers->run() failed ...\n");
+ printk(KERN_ERR "md: pers->run() failed ...\n");
mddev->pers = NULL;
return -EINVAL;
}
@@ -1736,7 +1741,7 @@ static int do_md_run (mddev_t * mddev)
#define OUT(x) do { err = (x); goto out; } while (0)
-static int restart_array (mddev_t *mddev)
+static int restart_array(mddev_t *mddev)
{
int err = 0;
@@ -1753,7 +1758,7 @@ static int restart_array (mddev_t *mddev)
mddev->ro = 0;
set_device_ro(mddev_to_kdev(mddev), 0);
- printk (KERN_INFO
+ printk(KERN_INFO
"md: md%d switched to read-write mode.\n", mdidx(mddev));
/*
* Kick recovery or resync if necessary
@@ -1762,7 +1767,7 @@ static int restart_array (mddev_t *mddev)
if (mddev->pers->restart_resync)
mddev->pers->restart_resync(mddev);
} else {
- printk (KERN_ERR "md: md%d has no personality assigned.\n",
+ printk(KERN_ERR "md: md%d has no personality assigned.\n",
mdidx(mddev));
err = -EINVAL;
}
@@ -1776,15 +1781,15 @@ out:
#define STILL_IN_USE \
"md: md%d still in use.\n"
-static int do_md_stop (mddev_t * mddev, int ro)
+static int do_md_stop(mddev_t * mddev, int ro)
{
int err = 0, resync_interrupted = 0;
kdev_t dev = mddev_to_kdev(mddev);
- if (atomic_read(&mddev->active)>1) {
- printk(STILL_IN_USE, mdidx(mddev));
- OUT(-EBUSY);
- }
+ if (atomic_read(&mddev->active)>1) {
+ printk(STILL_IN_USE, mdidx(mddev));
+ OUT(-EBUSY);
+ }
if (mddev->pers) {
/*
@@ -1831,7 +1836,7 @@ static int do_md_stop (mddev_t * mddev, int ro)
* interrupted.
*/
if (!mddev->recovery_running && !resync_interrupted) {
- printk("md: marking sb clean...\n");
+ printk(KERN_INFO "md: marking sb clean...\n");
mddev->sb->state |= 1 << MD_SB_CLEAN;
}
md_update_sb(mddev);
@@ -1844,12 +1849,11 @@ static int do_md_stop (mddev_t * mddev, int ro)
* Free resources if final stop
*/
if (!ro) {
- printk (KERN_INFO "md: md%d stopped.\n", mdidx(mddev));
+ printk(KERN_INFO "md: md%d stopped.\n", mdidx(mddev));
free_mddev(mddev);
} else
- printk (KERN_INFO
- "md: md%d switched to read-only mode.\n", mdidx(mddev));
+ printk(KERN_INFO "md: md%d switched to read-only mode.\n", mdidx(mddev));
out:
return err;
}
@@ -1859,7 +1863,7 @@ out:
/*
* We have to safely support old arrays too.
*/
-int detect_old_array (mdp_super_t *sb)
+int detect_old_array(mdp_super_t *sb)
{
if (sb->major_version > 0)
return 0;
@@ -1870,7 +1874,7 @@ int detect_old_array (mdp_super_t *sb)
}
-static void autorun_array (mddev_t *mddev)
+static void autorun_array(mddev_t *mddev)
{
mdk_rdev_t *rdev;
struct md_list_head *tmp;
@@ -1881,7 +1885,7 @@ static void autorun_array (mddev_t *mddev)
return;
}
- printk("md: running: ");
+ printk(KERN_INFO "md: running: ");
ITERATE_RDEV(mddev,rdev,tmp) {
printk("<%s>", partition_name(rdev->dev));
@@ -1890,7 +1894,7 @@ static void autorun_array (mddev_t *mddev)
err = do_md_run (mddev);
if (err) {
- printk("md :do_md_run() returned %d\n", err);
+ printk(KERN_WARNING "md :do_md_run() returned %d\n", err);
/*
* prevent the writeback of an unrunnable array
*/
@@ -1911,7 +1915,7 @@ static void autorun_array (mddev_t *mddev)
*
* If "unit" is allocated, then bump its reference count
*/
-static void autorun_devices (kdev_t countdev)
+static void autorun_devices(kdev_t countdev)
{
struct md_list_head candidates;
struct md_list_head *tmp;
@@ -1920,20 +1924,22 @@ static void autorun_devices (kdev_t countdev)
kdev_t md_kdev;
- printk("md: autorun ...\n");
+ printk(KERN_INFO "md: autorun ...\n");
while (pending_raid_disks.next != &pending_raid_disks) {
rdev0 = md_list_entry(pending_raid_disks.next,
mdk_rdev_t, pending);
- printk("md: considering %s ...\n", partition_name(rdev0->dev));
+ printk(KERN_INFO "md: considering %s ...\n", partition_name(rdev0->dev));
MD_INIT_LIST_HEAD(&candidates);
ITERATE_RDEV_PENDING(rdev,tmp) {
if (uuid_equal(rdev0, rdev)) {
if (!sb_equal(rdev0->sb, rdev->sb)) {
- printk("md: %s has same UUID as %s, but superblocks differ ...\n", partition_name(rdev->dev), partition_name(rdev0->dev));
+ printk(KERN_WARNING
+ "md: %s has same UUID as %s, but superblocks differ ...\n",
+ partition_name(rdev->dev), partition_name(rdev0->dev));
continue;
}
- printk("md: adding %s ...\n", partition_name(rdev->dev));
+ printk(KERN_INFO "md: adding %s ...\n", partition_name(rdev->dev));
md_list_del(&rdev->pending);
md_list_add(&rdev->pending, &candidates);
}
@@ -1946,20 +1952,20 @@ static void autorun_devices (kdev_t countdev)
md_kdev = MKDEV(MD_MAJOR, rdev0->sb->md_minor);
mddev = kdev_to_mddev(md_kdev);
if (mddev) {
- printk("md: md%d already running, cannot run %s\n",
- mdidx(mddev), partition_name(rdev0->dev));
+ printk(KERN_WARNING "md: md%d already running, cannot run %s\n",
+ mdidx(mddev), partition_name(rdev0->dev));
ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp)
export_rdev(rdev);
continue;
}
mddev = alloc_mddev(md_kdev);
- if (mddev == NULL) {
- printk("md: cannot allocate memory for md drive.\n");
- break;
- }
- if (md_kdev == countdev)
- atomic_inc(&mddev->active);
- printk("md: created md%d\n", mdidx(mddev));
+ if (!mddev) {
+ printk(KERN_ERR "md: cannot allocate memory for md drive.\n");
+ break;
+ }
+ if (md_kdev == countdev)
+ atomic_inc(&mddev->active);
+ printk(KERN_INFO "md: created md%d\n", mdidx(mddev));
ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp) {
bind_rdev_to_array(rdev, mddev);
md_list_del(&rdev->pending);
@@ -1967,7 +1973,7 @@ static void autorun_devices (kdev_t countdev)
}
autorun_array(mddev);
}
- printk("md: ... autorun DONE.\n");
+ printk(KERN_INFO "md: ... autorun DONE.\n");
}
/*
@@ -2002,14 +2008,14 @@ static void autorun_devices (kdev_t countdev)
#define AUTORUNNING KERN_INFO \
"md: auto-running md%d.\n"
-static int autostart_array (kdev_t startdev, kdev_t countdev)
+static int autostart_array(kdev_t startdev, kdev_t countdev)
{
int err = -EINVAL, i;
mdp_super_t *sb = NULL;
mdk_rdev_t *start_rdev = NULL, *rdev;
if (md_import_device(startdev, 1)) {
- printk("md: could not import %s!\n", partition_name(startdev));
+ printk(KERN_WARNING "md: could not import %s!\n", partition_name(startdev));
goto abort;
}
@@ -2019,7 +2025,7 @@ static int autostart_array (kdev_t startdev, kdev_t countdev)
goto abort;
}
if (start_rdev->faulty) {
- printk("md: can not autostart based on faulty %s!\n",
+ printk(KERN_WARNING "md: can not autostart based on faulty %s!\n",
partition_name(startdev));
goto abort;
}
@@ -2029,7 +2035,9 @@ static int autostart_array (kdev_t startdev, kdev_t countdev)
err = detect_old_array(sb);
if (err) {
- printk("md: array version is too old to be autostarted, use raidtools 0.90 mkraid --upgrade\nto upgrade the array without data loss!\n");
+ printk(KERN_WARNING "md: array version is too old to be autostarted ,"
+ "use raidtools 0.90 mkraid --upgrade to upgrade the array "
+ "without data loss!\n");
goto abort;
}
@@ -2045,7 +2053,8 @@ static int autostart_array (kdev_t startdev, kdev_t countdev)
if (dev == startdev)
continue;
if (md_import_device(dev, 1)) {
- printk("md: could not import %s, trying to run array nevertheless.\n", partition_name(dev));
+ printk(KERN_WARNING "md: could not import %s, trying to run array nevertheless.\n",
+ partition_name(dev));
continue;
}
rdev = find_rdev_all(dev);
@@ -2078,7 +2087,7 @@ abort:
#undef AUTORUNNING
-static int get_version (void * arg)
+static int get_version(void * arg)
{
mdu_version_t ver;
@@ -2093,7 +2102,7 @@ static int get_version (void * arg)
}
#define SET_FROM_SB(x) info.x = mddev->sb->x
-static int get_array_info (mddev_t * mddev, void * arg)
+static int get_array_info(mddev_t * mddev, void * arg)
{
mdu_array_info_t info;
@@ -2131,7 +2140,7 @@ static int get_array_info (mddev_t * mddev, void * arg)
#undef SET_FROM_SB
#define SET_FROM_SB(x) info.x = mddev->sb->disks[nr].x
-static int get_disk_info (mddev_t * mddev, void * arg)
+static int get_disk_info(mddev_t * mddev, void * arg)
{
mdu_disk_info_t info;
unsigned int nr;
@@ -2160,7 +2169,7 @@ static int get_disk_info (mddev_t * mddev, void * arg)
#define SET_SB(x) mddev->sb->disks[nr].x = info->x
-static int add_new_disk (mddev_t * mddev, mdu_disk_info_t *info)
+static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
{
int err, size, persistent;
mdk_rdev_t *rdev;
@@ -2169,15 +2178,15 @@ static int add_new_disk (mddev_t * mddev, mdu_disk_info_t *info)
dev = MKDEV(info->major,info->minor);
if (find_rdev_all(dev)) {
- printk("md: device %s already used in a RAID array!\n",
- partition_name(dev));
+ printk(KERN_WARNING "md: device %s already used in a RAID array!\n",
+ partition_name(dev));
return -EBUSY;
}
if (!mddev->sb) {
/* expecting a device which has a superblock */
err = md_import_device(dev, 1);
if (err) {
- printk("md: md_import_device returned %d\n", err);
+ printk(KERN_WARNING "md: md_import_device returned %d\n", err);
return -EINVAL;
}
rdev = find_rdev_all(dev);
@@ -2189,12 +2198,14 @@ static int add_new_disk (mddev_t * mddev, mdu_disk_info_t *info)
mdk_rdev_t *rdev0 = md_list_entry(mddev->disks.next,
mdk_rdev_t, same_set);
if (!uuid_equal(rdev0, rdev)) {
- printk("md: %s has different UUID to %s\n", partition_name(rdev->dev), partition_name(rdev0->dev));
+ printk(KERN_WARNING "md: %s has different UUID to %s\n",
+ partition_name(rdev->dev), partition_name(rdev0->dev));
export_rdev(rdev);
return -EINVAL;
}
if (!sb_equal(rdev0->sb, rdev->sb)) {
- printk("md: %s has same UUID but different superblock to %s\n", partition_name(rdev->dev), partition_name(rdev0->dev));
+ printk(KERN_WARNING "md: %s has same UUID but different superblock to %s\n",
+ partition_name(rdev->dev), partition_name(rdev0->dev));
export_rdev(rdev);
return -EINVAL;
}
@@ -2219,7 +2230,7 @@ static int add_new_disk (mddev_t * mddev, mdu_disk_info_t *info)
if ((info->state & (1<<MD_DISK_FAULTY))==0) {
err = md_import_device (dev, 0);
if (err) {
- printk("md: error, md_import_device() returned %d\n", err);
+ printk(KERN_WARNING "md: error, md_import_device() returned %d\n", err);
return -EINVAL;
}
rdev = find_rdev_all(dev);
@@ -2235,7 +2246,7 @@ static int add_new_disk (mddev_t * mddev, mdu_disk_info_t *info)
persistent = !mddev->sb->not_persistent;
if (!persistent)
- printk("md: nonpersistent superblock ...\n");
+ printk(KERN_INFO "md: nonpersistent superblock ...\n");
size = calc_dev_size(dev, mddev, persistent);
rdev->sb_offset = calc_dev_sboffset(dev, mddev, persistent);
@@ -2253,24 +2264,24 @@ static int add_new_disk (mddev_t * mddev, mdu_disk_info_t *info)
}
#undef SET_SB
-static int hot_generate_error (mddev_t * mddev, kdev_t dev)
+static int hot_generate_error(mddev_t * mddev, kdev_t dev)
{
struct request_queue *q;
mdk_rdev_t *rdev;
mdp_disk_t *disk;
-
+
if (!mddev->pers)
return -ENODEV;
-
- printk("md: trying to generate %s error in md%d ... \n",
+
+ printk(KERN_INFO "md: trying to generate %s error in md%d ... \n",
partition_name(dev), mdidx(mddev));
-
+
rdev = find_rdev(mddev, dev);
if (!rdev) {
MD_BUG();
return -ENXIO;
}
-
+
if (rdev->desc_nr == -1) {
MD_BUG();
return -EINVAL;
@@ -2278,19 +2289,19 @@ static int hot_generate_error (mddev_t * mddev, kdev_t dev)
disk = &mddev->sb->disks[rdev->desc_nr];
if (!disk_active(disk))
return -ENODEV;
-
+
q = blk_get_queue(rdev->dev);
if (!q) {
MD_BUG();
return -ENODEV;
}
- printk("md: okay, generating error!\n");
+ printk(KERN_INFO "md: okay, generating error!\n");
// q->oneshot_error = 1; // disabled for now
-
+
return 0;
}
-static int hot_remove_disk (mddev_t * mddev, kdev_t dev)
+static int hot_remove_disk(mddev_t * mddev, kdev_t dev)
{
int err;
mdk_rdev_t *rdev;
@@ -2299,12 +2310,12 @@ static int hot_remove_disk (mddev_t * mddev, kdev_t dev)
if (!mddev->pers)
return -ENODEV;
- printk("md: trying to remove %s from md%d ... \n",
+ printk(KERN_INFO "md: trying to remove %s from md%d ... \n",
partition_name(dev), mdidx(mddev));
if (!mddev->pers->diskop) {
- printk("md%d: personality does not support diskops!\n",
- mdidx(mddev));
+ printk(KERN_WARNING "md%d: personality does not support diskops!\n",
+ mdidx(mddev));
return -EINVAL;
}
@@ -2325,7 +2336,7 @@ static int hot_remove_disk (mddev_t * mddev, kdev_t dev)
MD_BUG();
return -EINVAL;
}
-
+
err = mddev->pers->diskop(mddev, &disk, DISKOP_HOT_REMOVE_DISK);
if (err == -EBUSY) {
MD_BUG();
@@ -2343,12 +2354,12 @@ static int hot_remove_disk (mddev_t * mddev, kdev_t dev)
return 0;
busy:
- printk("md: cannot remove active disk %s from md%d ... \n",
+ printk(KERN_WARNING "md: cannot remove active disk %s from md%d ... \n",
partition_name(dev), mdidx(mddev));
return -EBUSY;
}
-static int hot_add_disk (mddev_t * mddev, kdev_t dev)
+static int hot_add_disk(mddev_t * mddev, kdev_t dev)
{
int i, err, persistent;
unsigned int size;
@@ -2358,12 +2369,12 @@ static int hot_add_disk (mddev_t * mddev, kdev_t dev)
if (!mddev->pers)
return -ENODEV;
- printk("md: trying to hot-add %s to md%d ... \n",
+ printk(KERN_INFO "md: trying to hot-add %s to md%d ... \n",
partition_name(dev), mdidx(mddev));
if (!mddev->pers->diskop) {
- printk("md%d: personality does not support diskops!\n",
- mdidx(mddev));
+ printk(KERN_WARNING "md%d: personality does not support diskops!\n",
+ mdidx(mddev));
return -EINVAL;
}
@@ -2371,7 +2382,7 @@ static int hot_add_disk (mddev_t * mddev, kdev_t dev)
size = calc_dev_size(dev, mddev, persistent);
if (size < mddev->sb->size) {
- printk("md%d: disk size %d blocks < array size %d\n",
+ printk(KERN_WARNING "md%d: disk size %d blocks < array size %d\n",
mdidx(mddev), size, mddev->sb->size);
return -ENOSPC;
}
@@ -2382,7 +2393,7 @@ static int hot_add_disk (mddev_t * mddev, kdev_t dev)
err = md_import_device (dev, 0);
if (err) {
- printk("md: error, md_import_device() returned %d\n", err);
+ printk(KERN_WARNING "md: error, md_import_device() returned %d\n", err);
return -EINVAL;
}
rdev = find_rdev_all(dev);
@@ -2391,7 +2402,7 @@ static int hot_add_disk (mddev_t * mddev, kdev_t dev)
return -EINVAL;
}
if (rdev->faulty) {
- printk("md: can not hot-add faulty %s disk to md%d!\n",
+ printk(KERN_WARNING "md: can not hot-add faulty %s disk to md%d!\n",
partition_name(dev), mdidx(mddev));
err = -EINVAL;
goto abort_export;
@@ -2416,7 +2427,8 @@ static int hot_add_disk (mddev_t * mddev, kdev_t dev)
break;
}
if (i == MD_SB_DISKS) {
- printk("md%d: can not hot-add to full array!\n", mdidx(mddev));
+ printk(KERN_WARNING "md%d: can not hot-add to full array!\n",
+ mdidx(mddev));
err = -EBUSY;
goto abort_unbind_export;
}
@@ -2470,7 +2482,7 @@ abort_export:
}
#define SET_SB(x) mddev->sb->x = info->x
-static int set_array_info (mddev_t * mddev, mdu_array_info_t *info)
+static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
{
if (alloc_array_sb(mddev))
@@ -2511,37 +2523,37 @@ static int set_array_info (mddev_t * mddev, mdu_array_info_t *info)
}
#undef SET_SB
-static int set_disk_info (mddev_t * mddev, void * arg)
+static int set_disk_info(mddev_t * mddev, void * arg)
{
- printk("md: not yet");
+ printk(KERN_INFO "md: not yet");
return -EINVAL;
}
-static int clear_array (mddev_t * mddev)
+static int clear_array(mddev_t * mddev)
{
- printk("md: not yet");
+ printk(KERN_INFO "md: not yet");
return -EINVAL;
}
-static int write_raid_info (mddev_t * mddev)
+static int write_raid_info(mddev_t * mddev)
{
- printk("md: not yet");
+ printk(KERN_INFO "md: not yet");
return -EINVAL;
}
-static int protect_array (mddev_t * mddev)
+static int protect_array(mddev_t * mddev)
{
- printk("md: not yet");
+ printk(KERN_INFO "md: not yet");
return -EINVAL;
}
-static int unprotect_array (mddev_t * mddev)
+static int unprotect_array(mddev_t * mddev)
{
- printk("md: not yet");
+ printk(KERN_INFO "md: not yet");
return -EINVAL;
}
-static int set_disk_faulty (mddev_t *mddev, kdev_t dev)
+static int set_disk_faulty(mddev_t *mddev, kdev_t dev)
{
int ret;
@@ -2549,7 +2561,7 @@ static int set_disk_faulty (mddev_t *mddev, kdev_t dev)
return ret;
}
-static int md_ioctl (struct inode *inode, struct file *file,
+static int md_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
unsigned int minor;
@@ -2627,7 +2639,7 @@ static int md_ioctl (struct inode *inode, struct file *file,
case SET_ARRAY_INFO:
case START_ARRAY:
if (mddev) {
- printk("md: array md%d already exists!\n",
+ printk(KERN_WARNING "md: array md%d already exists!\n",
mdidx(mddev));
err = -EEXIST;
goto abort;
@@ -2649,12 +2661,13 @@ static int md_ioctl (struct inode *inode, struct file *file,
*/
err = lock_mddev(mddev);
if (err) {
- printk("md: ioctl, reason %d, cmd %d\n", err, cmd);
+ printk(KERN_WARNING "md: ioctl, reason %d, cmd %d\n",
+ err, cmd);
goto abort;
}
if (mddev->sb) {
- printk("md: array md%d already has a superblock!\n",
+ printk(KERN_WARNING "md: array md%d already has a superblock!\n",
mdidx(mddev));
err = -EBUSY;
goto abort_unlock;
@@ -2667,7 +2680,7 @@ static int md_ioctl (struct inode *inode, struct file *file,
}
err = set_array_info(mddev, &info);
if (err) {
- printk("md: couldnt set array info. %d\n", err);
+ printk(KERN_WARNING "md: couldnt set array info. %d\n", err);
goto abort_unlock;
}
}
@@ -2679,7 +2692,7 @@ static int md_ioctl (struct inode *inode, struct file *file,
*/
err = autostart_array((kdev_t)arg, dev);
if (err) {
- printk("md: autostart %s failed!\n",
+ printk(KERN_WARNING "md: autostart %s failed!\n",
partition_name((kdev_t)arg));
goto abort;
}
@@ -2698,7 +2711,7 @@ static int md_ioctl (struct inode *inode, struct file *file,
}
err = lock_mddev(mddev);
if (err) {
- printk("md: ioctl lock interrupted, reason %d, cmd %d\n",err, cmd);
+ printk(KERN_INFO "md: ioctl lock interrupted, reason %d, cmd %d\n",err, cmd);
goto abort;
}
/* if we don't have a superblock yet, only ADD_NEW_DISK or STOP_ARRAY is allowed */
@@ -2839,7 +2852,9 @@ static int md_ioctl (struct inode *inode, struct file *file,
}
default:
- printk(KERN_WARNING "md: %s(pid %d) used obsolete MD ioctl, upgrade your software to use new ictls.\n", current->comm, current->pid);
+ printk(KERN_WARNING "md: %s(pid %d) used obsolete MD ioctl, "
+ "upgrade your software to use new ictls.\n",
+ current->comm, current->pid);
err = -EINVAL;
goto abort_unlock;
}
@@ -2852,12 +2867,12 @@ abort_unlock:
return err;
done:
if (err)
- printk("md: huh12?\n");
+ MD_BUG();
abort:
return err;
}
-static int md_open (struct inode *inode, struct file *file)
+static int md_open(struct inode *inode, struct file *file)
{
/*
* Always succeed, but increment the usage count
@@ -2868,7 +2883,7 @@ static int md_open (struct inode *inode, struct file *file)
return (0);
}
-static int md_release (struct inode *inode, struct file * file)
+static int md_release(struct inode *inode, struct file * file)
{
mddev_t *mddev = kdev_to_mddev(inode->i_rdev);
if (mddev)
@@ -2937,11 +2952,8 @@ int md_thread(void * arg)
run(thread->data);
run_task_queue(&tq_disk);
}
- if (md_signal_pending(current)) {
- printk("md: %8s(%d) flushing signals.\n", current->comm,
- current->pid);
+ if (md_signal_pending(current))
md_flush_signals();
- }
}
complete(thread->event);
return 0;
@@ -2954,22 +2966,22 @@ void md_wakeup_thread(mdk_thread_t *thread)
wake_up(&thread->wqueue);
}
-mdk_thread_t *md_register_thread (void (*run) (void *),
+mdk_thread_t *md_register_thread(void (*run) (void *),
void *data, const char *name)
{
mdk_thread_t *thread;
int ret;
struct completion event;
-
+
thread = (mdk_thread_t *) kmalloc
(sizeof(mdk_thread_t), GFP_KERNEL);
if (!thread)
return NULL;
-
+
memset(thread, 0, sizeof(mdk_thread_t));
md_init_waitqueue_head(&thread->wqueue);
- init_completion(&event);
+ init_completion(&event);
thread->event = &event;
thread->run = run;
thread->data = data;
@@ -2983,22 +2995,22 @@ mdk_thread_t *md_register_thread (void (*run) (void *),
return thread;
}
-void md_interrupt_thread (mdk_thread_t *thread)
+void md_interrupt_thread(mdk_thread_t *thread)
{
if (!thread->tsk) {
MD_BUG();
return;
}
- printk("md: interrupting MD-thread pid %d\n", thread->tsk->pid);
+ dprintk("interrupting MD-thread pid %d\n", thread->tsk->pid);
send_sig(SIGKILL, thread->tsk, 1);
}
-void md_unregister_thread (mdk_thread_t *thread)
+void md_unregister_thread(mdk_thread_t *thread)
{
struct completion event;
init_completion(&event);
-
+
thread->event = &event;
thread->run = NULL;
thread->name = NULL;
@@ -3007,7 +3019,7 @@ void md_unregister_thread (mdk_thread_t *thread)
kfree(thread);
}
-void md_recover_arrays (void)
+void md_recover_arrays(void)
{
if (!md_recovery_thread) {
MD_BUG();
@@ -3017,12 +3029,15 @@ void md_recover_arrays (void)
}
-int md_error (mddev_t *mddev, kdev_t rdev)
+int md_error(mddev_t *mddev, kdev_t rdev)
{
mdk_rdev_t * rrdev;
-/* printk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",MAJOR(dev),MINOR(dev),MAJOR(rdev),MINOR(rdev), __builtin_return_address(0),__builtin_return_address(1),__builtin_return_address(2),__builtin_return_address(3));
- */
+ dprintk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",
+ MAJOR(dev),MINOR(dev),MAJOR(rdev),MINOR(rdev),
+ __builtin_return_address(0),__builtin_return_address(1),
+ __builtin_return_address(2),__builtin_return_address(3));
+
if (!mddev) {
MD_BUG();
return 0;
@@ -3030,7 +3045,7 @@ int md_error (mddev_t *mddev, kdev_t rdev)
rrdev = find_rdev(mddev, rdev);
if (!rrdev || rrdev->faulty)
return 0;
- if (mddev->pers->error_handler == NULL
+ if (!mddev->pers->error_handler
|| mddev->pers->error_handler(mddev,rdev) <= 0) {
free_disk_sb(rrdev);
rrdev->faulty = 1;
@@ -3048,7 +3063,7 @@ int md_error (mddev_t *mddev, kdev_t rdev)
return 0;
}
-static int status_unused (char * page)
+static int status_unused(char * page)
{
int sz = 0, i = 0;
mdk_rdev_t *rdev;
@@ -3074,7 +3089,7 @@ static int status_unused (char * page)
}
-static int status_resync (char * page, mddev_t * mddev)
+static int status_resync(char * page, mddev_t * mddev)
{
int sz = 0;
unsigned long max_blocks, resync, res, dt, db, rt;
@@ -3084,7 +3099,7 @@ static int status_resync (char * page, mddev_t * mddev)
/*
* Should not happen.
- */
+ */
if (!max_blocks) {
MD_BUG();
return 0;
@@ -3126,7 +3141,7 @@ static int status_resync (char * page, mddev_t * mddev)
if (!dt) dt++;
db = resync - (mddev->resync_mark_cnt/2);
rt = (dt * ((max_blocks-resync) / (db/100+1)))/100;
-
+
sz += sprintf(page + sz, " finish=%lu.%lumin", rt / 60, (rt % 60)/6);
sz += sprintf(page + sz, " speed=%ldK/sec", db/dt);
@@ -3160,7 +3175,7 @@ static int md_status_read_proc(char *page, char **start, off_t off,
sz += sprintf(page + sz, "md%d : %sactive", mdidx(mddev),
mddev->pers ? "" : "in");
if (mddev->pers) {
- if (mddev->ro)
+ if (mddev->ro)
sz += sprintf(page + sz, " (read-only)");
sz += sprintf(page + sz, " %s", mddev->pers->name);
}
@@ -3200,12 +3215,12 @@ static int md_status_read_proc(char *page, char **start, off_t off,
}
sz += sprintf(page + sz, "\n");
}
- sz += status_unused (page + sz);
+ sz += status_unused(page + sz);
return sz;
}
-int register_md_personality (int pnum, mdk_personality_t *p)
+int register_md_personality(int pnum, mdk_personality_t *p)
{
if (pnum >= MAX_PERSONALITY) {
MD_BUG();
@@ -3222,7 +3237,7 @@ int register_md_personality (int pnum, mdk_personality_t *p)
return 0;
}
-int unregister_md_personality (int pnum)
+int unregister_md_personality(int pnum)
{
if (pnum >= MAX_PERSONALITY) {
MD_BUG();
@@ -3273,7 +3288,7 @@ void md_sync_acct(kdev_t dev, unsigned long nr_sectors)
sync_io[major][index] += nr_sectors;
}
-static int is_mddev_idle (mddev_t *mddev)
+static int is_mddev_idle(mddev_t *mddev)
{
mdk_rdev_t * rdev;
struct md_list_head *tmp;
@@ -3291,9 +3306,7 @@ static int is_mddev_idle (mddev_t *mddev)
curr_events = kstat.dk_drive_rblk[major][idx] +
kstat.dk_drive_wblk[major][idx] ;
curr_events -= sync_io[major][idx];
-// printk("md: events(major: %d, idx: %d): %ld\n", major, idx, curr_events);
if ((curr_events - rdev->last_events) > 32) {
-// printk("!I(%ld)%x", curr_events - rdev->last_events, rdev->dev);
rdev->last_events = curr_events;
idle = 0;
}
@@ -3321,7 +3334,7 @@ int md_do_sync(mddev_t *mddev, mdp_disk_t *spare)
unsigned int max_sectors, currspeed,
j, window, err, serialize;
unsigned long mark[SYNC_MARKS];
- unsigned long mark_cnt[SYNC_MARKS];
+ unsigned long mark_cnt[SYNC_MARKS];
int last_mark,m;
struct md_list_head *tmp;
unsigned long last_check;
@@ -3337,7 +3350,9 @@ recheck:
if (mddev2 == mddev)
continue;
if (mddev2->curr_resync && match_mddev_units(mddev,mddev2)) {
- printk(KERN_INFO "md: delaying resync of md%d until md%d has finished resync (they share one or more physical units)\n", mdidx(mddev), mdidx(mddev2));
+ printk(KERN_INFO "md: delaying resync of md%d until md%d "
+ "has finished resync (they share one or more physical units)\n",
+ mdidx(mddev), mdidx(mddev2));
serialize = 1;
break;
}
@@ -3359,7 +3374,9 @@ recheck:
printk(KERN_INFO "md: syncing RAID array md%d\n", mdidx(mddev));
printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed: %d KB/sec/disc.\n",
sysctl_speed_limit_min);
- printk(KERN_INFO "md: using maximum available idle IO bandwith (but not more than %d KB/sec) for reconstruction.\n", sysctl_speed_limit_max);
+ printk(KERN_INFO "md: using maximum available idle IO bandwith "
+ "(but not more than %d KB/sec) for reconstruction.\n",
+ sysctl_speed_limit_max);
/*
* Resync has low priority.
@@ -3379,7 +3396,8 @@ recheck:
* Tune reconstruction:
*/
window = MAX_READAHEAD*(PAGE_SIZE/512);
- printk(KERN_INFO "md: using %dk window, over a total of %d blocks.\n",window/2,max_sectors/2);
+ printk(KERN_INFO "md: using %dk window, over a total of %d blocks.\n",
+ window/2,max_sectors/2);
atomic_set(&mddev->recovery_active, 0);
init_waitqueue_head(&mddev->recovery_wait);
@@ -3401,14 +3419,14 @@ recheck:
continue;
last_check = j;
-
+
run_task_queue(&tq_disk);
repeat:
if (jiffies >= mark[last_mark] + SYNC_MARK_STEP ) {
/* step marks */
int next = (last_mark+1) % SYNC_MARKS;
-
+
mddev->resync_mark = mark[next];
mddev->resync_mark_cnt = mark_cnt[next];
mark[next] = jiffies;
@@ -3422,7 +3440,7 @@ recheck:
* got a signal, exit.
*/
mddev->curr_resync = 0;
- printk("md: md_do_sync() got signal ... exiting\n");
+ printk(KERN_INFO "md: md_do_sync() got signal ... exiting\n");
md_flush_signals();
err = -EINTR;
goto out;
@@ -3476,7 +3494,7 @@ out_nolock:
* of my root partition with the first 0.5 gigs of my /home partition ... so
* i'm a bit nervous ;)
*/
-void md_do_recovery (void *data)
+void md_do_recovery(void *data)
{
int err;
mddev_t *mddev;
@@ -3495,15 +3513,18 @@ restart:
if (sb->active_disks == sb->raid_disks)
continue;
if (!sb->spare_disks) {
- printk(KERN_ERR "md%d: no spare disk to reconstruct array! -- continuing in degraded mode\n", mdidx(mddev));
+ printk(KERN_ERR "md%d: no spare disk to reconstruct array! "
+ "-- continuing in degraded mode\n", mdidx(mddev));
continue;
}
/*
* now here we get the spare and resync it.
*/
- if ((spare = get_spare(mddev)) == NULL)
+ spare = get_spare(mddev);
+ if (!spare)
continue;
- printk(KERN_INFO "md%d: resyncing spare disk %s to replace failed disk\n", mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor)));
+ printk(KERN_INFO "md%d: resyncing spare disk %s to replace failed disk\n",
+ mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor)));
if (!mddev->pers->diskop)
continue;
if (mddev->pers->diskop(mddev, &spare, DISKOP_SPARE_WRITE))
@@ -3512,7 +3533,8 @@ restart:
mddev->recovery_running = 1;
err = md_do_sync(mddev, spare);
if (err == -EIO) {
- printk(KERN_INFO "md%d: spare disk %s failed, skipping to next spare.\n", mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor)));
+ printk(KERN_INFO "md%d: spare disk %s failed, skipping to next spare.\n",
+ mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor)));
if (!disk_faulty(spare)) {
mddev->pers->diskop(mddev,&spare,DISKOP_SPARE_INACTIVE);
mark_disk_faulty(spare);
@@ -3556,7 +3578,7 @@ restart:
goto restart;
}
printk(KERN_INFO "md: recovery thread finished ...\n");
-
+
}
int md_notify_reboot(struct notifier_block *this,
@@ -3589,7 +3611,7 @@ struct notifier_block md_notifier = {
priority: INT_MAX, /* before any real devices */
};
-static void md_geninit (void)
+static void md_geninit(void)
{
int i;
@@ -3611,18 +3633,18 @@ static void md_geninit (void)
#endif
}
-int md__init md_init (void)
+int md__init md_init(void)
{
static char * name = "mdrecoveryd";
int minor;
-
- printk (KERN_INFO "md: md driver %d.%d.%d MAX_MD_DEVS=%d, MD_SB_DISKS=%d\n",
+
+ printk(KERN_INFO "md: md driver %d.%d.%d MAX_MD_DEVS=%d, MD_SB_DISKS=%d\n",
MD_MAJOR_VERSION, MD_MINOR_VERSION,
MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS);
if (devfs_register_blkdev (MAJOR_NR, "md", &md_fops))
{
- printk (KERN_ALERT "md: Unable to get major %d for md\n", MAJOR_NR);
+ printk(KERN_ALERT "md: Unable to get major %d for md\n", MAJOR_NR);
return (-1);
}
devfs_handle = devfs_mk_dir (NULL, "md", NULL);
@@ -3637,7 +3659,7 @@ int md__init md_init (void)
/* forward all md request to md_make_request */
blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), md_make_request);
-
+
read_ahead[MAJOR_NR] = INT_MAX;
@@ -3678,14 +3700,14 @@ struct {
static int detected_devices[128];
static int dev_cnt;
-void md_autodetect_dev (kdev_t dev)
+void md_autodetect_dev(kdev_t dev)
{
if (dev_cnt >= 0 && dev_cnt < 127)
detected_devices[dev_cnt++] = dev;
}
-static void autostart_arrays (void)
+static void autostart_arrays(void)
{
mdk_rdev_t *rdev;
int i;
@@ -3753,21 +3775,22 @@ static int md__init md_setup(char *str)
char *str1 = str;
if (get_option(&str, &minor) != 2) { /* MD Number */
- printk("md: Too few arguments supplied to md=.\n");
+ printk(KERN_WARNING "md: Too few arguments supplied to md=.\n");
return 0;
}
if (minor >= MAX_MD_DEVS) {
- printk ("md: md=%d, Minor device number too high.\n", minor);
+ printk(KERN_WARNING "md: md=%d, Minor device number too high.\n", minor);
return 0;
} else if (md_setup_args.device_names[minor]) {
- printk ("md: md=%d, Specified more then once. Replacing previous definition.\n", minor);
+ printk(KERN_WARNING "md: md=%d, Specified more then once. "
+ "Replacing previous definition.\n", minor);
}
switch (get_option(&str, &level)) { /* RAID Personality */
case 2: /* could be 0 or -1.. */
if (level == 0 || level == -1) {
if (get_option(&str, &factor) != 2 || /* Chunk Size */
get_option(&str, &fault) != 2) {
- printk("md: Too few arguments supplied to md=.\n");
+ printk(KERN_WARNING "md: Too few arguments supplied to md=.\n");
return 0;
}
md_setup_args.pers[minor] = level;
@@ -3782,8 +3805,9 @@ static int md__init md_setup(char *str)
pername = "raid0";
break;
default:
- printk ("md: The kernel has not been configured for raid%d"
- " support!\n", level);
+ printk(KERN_WARNING
+ "md: The kernel has not been configured for raid%d support!\n",
+ level);
return 0;
}
md_setup_args.pers[minor] = level;
@@ -3797,11 +3821,11 @@ static int md__init md_setup(char *str)
md_setup_args.pers[minor] = 0;
pername="super-block";
}
-
- printk ("md: Will configure md%d (%s) from %s, below.\n",
+
+ printk(KERN_INFO "md: Will configure md%d (%s) from %s, below.\n",
minor, pername, str);
md_setup_args.device_names[minor] = str;
-
+
return 1;
}
@@ -3819,13 +3843,14 @@ void md__init md_setup_drive(void)
mdu_disk_info_t dinfo;
if ((devname = md_setup_args.device_names[minor]) == 0) continue;
-
+
for (i = 0; i < MD_SB_DISKS && devname != 0; i++) {
char *p;
void *handle;
-
- if ((p = strchr(devname, ',')) != NULL)
+
+ p = strchr(devname, ',');
+ if (p)
*p++ = 0;
dev = name_to_kdev_t(devname);
@@ -3837,29 +3862,31 @@ void md__init md_setup_drive(void)
dev = MKDEV(major, minor);
}
if (dev == 0) {
- printk ("md: Unknown device name: %s\n", devname);
+ printk(KERN_WARNING "md: Unknown device name: %s\n", devname);
break;
}
-
+
devices[i] = dev;
md_setup_args.device_set[minor] = 1;
-
+
devname = p;
}
devices[i] = 0;
-
+
if (md_setup_args.device_set[minor] == 0)
continue;
-
+
if (mddev_map[minor].mddev) {
- printk("md: Ignoring md=%d, already autodetected. (Use raid=noautodetect)\n", minor);
+ printk(KERN_WARNING
+ "md: Ignoring md=%d, already autodetected. (Use raid=noautodetect)\n",
+ minor);
continue;
}
- printk("md: Loading md%d: %s\n", minor, md_setup_args.device_names[minor]);
-
+ printk(KERN_INFO "md: Loading md%d: %s\n", minor, md_setup_args.device_names[minor]);
+
mddev = alloc_mddev(MKDEV(MD_MAJOR,minor));
- if (mddev == NULL) {
- printk("md: kmalloc failed - cannot start array %d\n", minor);
+ if (!mddev) {
+ printk(KERN_ERR "md: kmalloc failed - cannot start array %d\n", minor);
continue;
}
if (md_setup_args.pers[minor]) {
@@ -3905,7 +3932,7 @@ void md__init md_setup_drive(void)
if (err) {
mddev->sb_dirty = 0;
do_md_stop(mddev, 0);
- printk("md: starting md%d failed\n", minor);
+ printk(KERN_WARNING "md: starting md%d failed\n", minor);
}
}
}
@@ -3950,7 +3977,7 @@ __initcall(md_run_setup);
#else /* It is a MODULE */
-int init_module (void)
+int init_module(void)
{
return md_init();
}
@@ -3965,7 +3992,7 @@ static void free_device_names(void)
}
-void cleanup_module (void)
+void cleanup_module(void)
{
md_unregister_thread(md_recovery_thread);
devfs_unregister(devfs_handle);
@@ -3984,7 +4011,7 @@ void cleanup_module (void)
blk_size[MAJOR_NR] = NULL;
max_readahead[MAJOR_NR] = NULL;
hardsect_size[MAJOR_NR] = NULL;
-
+
free_device_names();
}
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 68b3035ff289..952c0225e216 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -137,7 +137,7 @@ an MMIO register read.
*/
#define DRV_NAME "8139too"
-#define DRV_VERSION "0.9.18a"
+#define DRV_VERSION "0.9.19"
#include <linux/config.h>
@@ -620,6 +620,7 @@ static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
static struct net_device_stats *rtl8139_get_stats (struct net_device *dev);
static inline u32 ether_crc (int length, unsigned char *data);
static void rtl8139_set_rx_mode (struct net_device *dev);
+static void __set_rx_mode (struct net_device *dev);
static void rtl8139_hw_start (struct net_device *dev);
#ifdef USE_IO_OPS
@@ -962,6 +963,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
dev->do_ioctl = netdev_ioctl;
dev->tx_timeout = rtl8139_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
+ dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
dev->irq = pdev->irq;
@@ -1725,18 +1727,21 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
assert (tp->tx_info[entry].mapping == 0);
tp->tx_info[entry].skb = skb;
- if ((long) skb->data & 3) { /* Must use alignment buffer. */
- /* tp->tx_info[entry].mapping = 0; */
- memcpy (tp->tx_buf[entry], skb->data, skb->len);
- dma_addr = tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs);
- } else {
+ if ( !((unsigned long)skb->data & 3) && skb_shinfo(skb)->nr_frags == 0 &&
+ skb->ip_summed != CHECKSUM_HW) {
tp->xstats.tx_buf_mapped++;
tp->tx_info[entry].mapping =
pci_map_single (tp->pci_dev, skb->data, skb->len,
PCI_DMA_TODEVICE);
dma_addr = tp->tx_info[entry].mapping;
- }
-
+ } else if (skb->len < TX_BUF_SIZE) {
+ skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
+ dma_addr = tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs);
+ } else {
+ dev_kfree_skb(skb);
+ tp->tx_info[entry].skb = NULL;
+ return 0;
+ }
/* Note: the chip doesn't have auto-pad! */
spin_lock_irq(&tp->lock);
RTL_W32_F (TxAddr0 + (entry * 4), dma_addr);
@@ -1847,8 +1852,8 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
struct rtl8139_private *tp, void *ioaddr)
{
u8 tmp8;
- int tmp_work = 1000;
-
+ int tmp_work;
+
DPRINTK ("%s: Ethernet frame had errors, status %8.8x.\n",
dev->name, rx_status);
if (rx_status & RxTooLong) {
@@ -1863,33 +1868,52 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
tp->stats.rx_length_errors++;
if (rx_status & RxCRCErr)
tp->stats.rx_crc_errors++;
+
/* Reset the receiver, based on RealTek recommendation. (Bug?) */
- tp->cur_rx = 0;
/* disable receive */
- RTL_W8 (ChipCmd, CmdTxEnb);
-
- /* A.C.: Reset the multicast list. */
- rtl8139_set_rx_mode (dev);
-
- /* XXX potentially temporary hack to
- * restart hung receiver */
+ RTL_W8_F (ChipCmd, CmdTxEnb);
+ tmp_work = 200;
while (--tmp_work > 0) {
- barrier();
+ udelay(1);
+ tmp8 = RTL_R8 (ChipCmd);
+ if (!(tmp8 & CmdRxEnb))
+ break;
+ }
+ if (tmp_work <= 0)
+ printk (KERN_WARNING PFX "rx stop wait too long\n");
+ /* restart receive */
+ tmp_work = 200;
+ while (--tmp_work > 0) {
+ RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb);
+ udelay(1);
tmp8 = RTL_R8 (ChipCmd);
if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb))
break;
- RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
}
-
- /* G.S.: Re-enable receiver */
- /* XXX temporary hack to work around receiver hang */
- rtl8139_set_rx_mode (dev);
-
if (tmp_work <= 0)
printk (KERN_WARNING PFX "tx/rx enable wait too long\n");
-}
+ /* and reinitialize all rx related registers */
+ RTL_W8_F (Cfg9346, Cfg9346_Unlock);
+ /* Must enable Tx/Rx before setting transfer thresholds! */
+ RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
+
+ tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys;
+ RTL_W32 (RxConfig, tp->rx_config);
+ tp->cur_rx = 0;
+
+ DPRINTK("init buffer addresses\n");
+
+ /* Lock Config[01234] and BMCR register writes */
+ RTL_W8 (Cfg9346, Cfg9346_Lock);
+
+ /* init Rx ring buffer DMA address */
+ RTL_W32_F (RxBuf, tp->rx_ring_dma);
+
+ /* A.C.: Reset the multicast list. */
+ __set_rx_mode (dev);
+}
static void rtl8139_rx_interrupt (struct net_device *dev,
struct rtl8139_private *tp, void *ioaddr)
@@ -2312,11 +2336,10 @@ static inline u32 ether_crc (int length, unsigned char *data)
}
-static void rtl8139_set_rx_mode (struct net_device *dev)
+static void __set_rx_mode (struct net_device *dev)
{
struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
- unsigned long flags;
u32 mc_filter[2]; /* Multicast hash filter */
int i, rx_mode;
u32 tmp;
@@ -2353,22 +2376,28 @@ static void rtl8139_set_rx_mode (struct net_device *dev)
}
}
- spin_lock_irqsave (&tp->lock, flags);
-
/* We can safely update without stopping the chip. */
tmp = rtl8139_rx_config | rx_mode;
if (tp->rx_config != tmp) {
- RTL_W32 (RxConfig, tmp);
+ RTL_W32_F (RxConfig, tmp);
tp->rx_config = tmp;
}
RTL_W32_F (MAR0 + 0, mc_filter[0]);
RTL_W32_F (MAR0 + 4, mc_filter[1]);
- spin_unlock_irqrestore (&tp->lock, flags);
DPRINTK ("EXIT\n");
}
+static void rtl8139_set_rx_mode (struct net_device *dev)
+{
+ unsigned long flags;
+ struct rtl8139_private *tp = dev->priv;
+
+ spin_lock_irqsave (&tp->lock, flags);
+ __set_rx_mode(dev);
+ spin_unlock_irqrestore (&tp->lock, flags);
+}
#ifdef CONFIG_PM
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 422894612d64..c73bd6401356 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -65,6 +65,23 @@
* Wake on lan support (Erik Gilling)
* MXDMA fixes for serverworks
* EEPROM reload
+
+ version 1.0.9 (Manfred Spraul)
+ * Main change: fix lack of synchronize
+ netif_close/netif_suspend against a last interrupt
+ or packet.
+ * do not enable superflous interrupts (e.g. the
+ drivers relies on TxDone - TxIntr not needed)
+ * wait that the hardware has really stopped in close
+ and suspend.
+ * workaround for the (at least) gcc-2.95.1 compiler
+ problem. Also simplifies the code a bit.
+ * disable_irq() in tx_timeout - needed to protect
+ against rx interrupts.
+ * stop the nic before switching into silent rx mode
+ for wol (required according to docu).
+
+
TODO:
* big endian support with CFG:BEM instead of cpu_to_le32
* support for an external PHY
@@ -72,8 +89,8 @@
*/
#define DRV_NAME "natsemi"
-#define DRV_VERSION "1.07+LK1.0.8"
-#define DRV_RELDATE "Aug 07, 2001"
+#define DRV_VERSION "1.07+LK1.0.9"
+#define DRV_RELDATE "Oct 02, 2001"
/* Updated to recommendations in pci-skeleton v2.03. */
@@ -345,6 +362,8 @@ enum intr_status_bits {
IntrNormalSummary=0x025f, IntrAbnormalSummary=0xCD20,
};
+#define DEFAULT_INTR 0x00f1cd65
+
/* Bits in the RxMode register. */
enum rx_mode_bits {
AcceptErr=0x20, AcceptRunt=0x10,
@@ -435,6 +454,7 @@ struct netdev_private {
static int eeprom_read(long ioaddr, int location);
static int mdio_read(struct net_device *dev, int phy_id, int location);
static void natsemi_reset(struct net_device *dev);
+static void natsemi_stop_rxtx(struct net_device *dev);
static int netdev_open(struct net_device *dev);
static void check_link(struct net_device *dev);
static void netdev_timer(unsigned long data);
@@ -460,6 +480,7 @@ static int netdev_set_sopass(struct net_device *dev, u8 *newval);
static int netdev_get_sopass(struct net_device *dev, u8 *data);
static int netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd);
static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd);
+static void enable_wol_mode(struct net_device *dev, int enable_intr);
static int netdev_close(struct net_device *dev);
@@ -709,7 +730,26 @@ static void natsemi_reset(struct net_device *dev)
}
}
-
+static void natsemi_stop_rxtx(struct net_device *dev)
+{
+ long ioaddr = dev->base_addr;
+ int i;
+
+ writel(RxOff | TxOff, ioaddr + ChipCmd);
+ for(i=0;i< NATSEMI_HW_TIMEOUT;i++) {
+ if ((readl(ioaddr + ChipCmd) & (TxOn|RxOn)) == 0)
+ break;
+ udelay(5);
+ }
+ if (i==NATSEMI_HW_TIMEOUT && debug) {
+ printk(KERN_INFO "%s: Tx/Rx process did not stop in %d usec.\n",
+ dev->name, i*5);
+ } else if (debug > 2) {
+ printk(KERN_DEBUG "%s: Tx/Rx process stopped in %d usec.\n",
+ dev->name, i*5);
+ }
+}
+
static int netdev_open(struct net_device *dev)
{
struct netdev_private *np = dev->priv;
@@ -731,7 +771,9 @@ static int netdev_open(struct net_device *dev)
return i;
}
init_ring(dev);
+ spin_lock_irq(&np->lock);
init_registers(dev);
+ spin_unlock_irq(&np->lock);
netif_start_queue(dev);
@@ -865,7 +907,7 @@ static void init_registers(struct net_device *dev)
__set_rx_mode(dev);
/* Enable interrupts by setting the interrupt mask. */
- writel(IntrNormalSummary | IntrAbnormalSummary, ioaddr + IntrMask);
+ writel(DEFAULT_INTR, ioaddr + IntrMask);
writel(1, ioaddr + IntrEnable);
writel(RxOn | TxOn, ioaddr + ChipCmd);
@@ -892,30 +934,51 @@ static void netdev_timer(unsigned long data)
add_timer(&np->timer);
}
-static void tx_timeout(struct net_device *dev)
+static void dump_ring(struct net_device *dev)
{
struct netdev_private *np = dev->priv;
- long ioaddr = dev->base_addr;
- printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
- " resetting...\n", dev->name, (int)readl(ioaddr + TxRingPtr));
-
- {
+ if (debug > 2) {
int i;
- printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring);
- for (i = 0; i < RX_RING_SIZE; i++)
- printk(" %8.8x", (unsigned int)np->rx_ring[i].cmd_status);
- printk("\n"KERN_DEBUG" Tx ring %p: ", np->tx_ring);
+ printk(KERN_DEBUG " Tx ring at %8.8x:\n",
+ (int)np->tx_ring);
for (i = 0; i < TX_RING_SIZE; i++)
- printk(" %4.4x", np->tx_ring[i].cmd_status);
- printk("\n");
+ printk(KERN_DEBUG " #%d desc. %8.8x %8.8x %8.8x.\n",
+ i, np->tx_ring[i].next_desc,
+ np->tx_ring[i].cmd_status, np->tx_ring[i].addr);
+ printk(KERN_DEBUG " Rx ring %8.8x:\n",
+ (int)np->rx_ring);
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ printk(KERN_DEBUG " #%d desc. %8.8x %8.8x %8.8x.\n",
+ i, np->rx_ring[i].next_desc,
+ np->rx_ring[i].cmd_status, np->rx_ring[i].addr);
+ }
}
+}
+
+static void tx_timeout(struct net_device *dev)
+{
+ struct netdev_private *np = dev->priv;
+ long ioaddr = dev->base_addr;
+
+
+ disable_irq(dev->irq);
spin_lock_irq(&np->lock);
- natsemi_reset(dev);
- drain_ring(dev);
- init_ring(dev);
- init_registers(dev);
+ if (netif_device_present(dev)) {
+ printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
+ " resetting...\n", dev->name, readl(ioaddr + IntrStatus));
+ dump_ring(dev);
+
+ natsemi_reset(dev);
+ drain_ring(dev);
+ init_ring(dev);
+ init_registers(dev);
+ } else {
+ printk(KERN_WARNING "%s: tx_timeout while in suspended state?\n",
+ dev->name);
+ }
spin_unlock_irq(&np->lock);
+ enable_irq(dev->irq);
dev->trans_start = jiffies;
np->stats.tx_errors++;
@@ -946,14 +1009,17 @@ static void init_ring(struct net_device *dev)
np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
np->rx_head_desc = &np->rx_ring[0];
+ /* Please be carefull before changing this loop - at least gcc-2.95.1
+ * miscompiles it otherwise.
+ */
/* Initialize all Rx descriptors. */
for (i = 0; i < RX_RING_SIZE; i++) {
- np->rx_ring[i].next_desc = cpu_to_le32(np->ring_dma+sizeof(struct netdev_desc)*(i+1));
+ np->rx_ring[i].next_desc = cpu_to_le32(np->ring_dma
+ +sizeof(struct netdev_desc)
+ *((i+1)%RX_RING_SIZE));
np->rx_ring[i].cmd_status = cpu_to_le32(DescOwn);
np->rx_skbuff[i] = NULL;
}
- /* Mark the last entry as wrapping the ring. */
- np->rx_ring[i-1].next_desc = cpu_to_le32(np->ring_dma);
/* Fill in the Rx buffers. Handle allocation failure gracefully. */
for (i = 0; i < RX_RING_SIZE; i++) {
@@ -965,18 +1031,18 @@ static void init_ring(struct net_device *dev)
np->rx_dma[i] = pci_map_single(np->pci_dev,
skb->data, skb->len, PCI_DMA_FROMDEVICE);
np->rx_ring[i].addr = cpu_to_le32(np->rx_dma[i]);
- np->rx_ring[i].cmd_status = cpu_to_le32(DescIntr | np->rx_buf_sz);
+ np->rx_ring[i].cmd_status = cpu_to_le32(np->rx_buf_sz);
}
np->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
for (i = 0; i < TX_RING_SIZE; i++) {
np->tx_skbuff[i] = NULL;
np->tx_ring[i].next_desc = cpu_to_le32(np->ring_dma
- +sizeof(struct netdev_desc)*(i+1+RX_RING_SIZE));
+ +sizeof(struct netdev_desc)
+ *((i+1)%TX_RING_SIZE+RX_RING_SIZE));
np->tx_ring[i].cmd_status = 0;
}
- np->tx_ring[i-1].next_desc = cpu_to_le32(np->ring_dma
- +sizeof(struct netdev_desc)*(RX_RING_SIZE));
+ dump_ring(dev);
}
static void drain_ring(struct net_device *dev)
@@ -1035,25 +1101,25 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
np->tx_ring[entry].addr = cpu_to_le32(np->tx_dma[entry]);
spin_lock_irq(&np->lock);
-
-#if 0
- np->tx_ring[entry].cmd_status = cpu_to_le32(DescOwn | DescIntr | skb->len);
-#else
- np->tx_ring[entry].cmd_status = cpu_to_le32(DescOwn | skb->len);
-#endif
- /* StrongARM: Explicitly cache flush np->tx_ring and skb->data,skb->len. */
- wmb();
- np->cur_tx++;
- if (np->cur_tx - np->dirty_tx >= TX_QUEUE_LEN - 1) {
- netdev_tx_done(dev);
- if (np->cur_tx - np->dirty_tx >= TX_QUEUE_LEN - 1)
- netif_stop_queue(dev);
+
+ if (netif_device_present(dev)) {
+ np->tx_ring[entry].cmd_status = cpu_to_le32(DescOwn | skb->len);
+ /* StrongARM: Explicitly cache flush np->tx_ring and skb->data,skb->len. */
+ wmb();
+ np->cur_tx++;
+ if (np->cur_tx - np->dirty_tx >= TX_QUEUE_LEN - 1) {
+ netdev_tx_done(dev);
+ if (np->cur_tx - np->dirty_tx >= TX_QUEUE_LEN - 1)
+ netif_stop_queue(dev);
+ }
+ /* Wake the potentially-idle transmit channel. */
+ writel(TxOn, dev->base_addr + ChipCmd);
+ } else {
+ dev_kfree_skb_irq(skb);
+ np->stats.tx_dropped++;
}
spin_unlock_irq(&np->lock);
- /* Wake the potentially-idle transmit channel. */
- writel(TxOn, dev->base_addr + ChipCmd);
-
dev->trans_start = jiffies;
if (debug > 4) {
@@ -1115,7 +1181,9 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
ioaddr = dev->base_addr;
np = dev->priv;
-
+
+ if (!netif_device_present(dev))
+ return;
do {
/* Reading automatically acknowledges all int sources. */
u32 intr_status = readl(ioaddr + IntrStatus);
@@ -1239,7 +1307,7 @@ static void netdev_rx(struct net_device *dev)
np->rx_ring[entry].addr = cpu_to_le32(np->rx_dma[entry]);
}
np->rx_ring[entry].cmd_status =
- cpu_to_le32(DescIntr | np->rx_buf_sz);
+ cpu_to_le32(np->rx_buf_sz);
}
/* Restart Rx engine if stopped. */
@@ -1305,11 +1373,13 @@ static struct net_device_stats *get_stats(struct net_device *dev)
/* The chip only need report frame silently dropped. */
spin_lock_irq(&np->lock);
- __get_stats(dev);
+ if (netif_running(dev) && netif_device_present(dev))
+ __get_stats(dev);
spin_unlock_irq(&np->lock);
return &np->stats;
}
+
/* The little-endian AUTODIN II ethernet CRC calculations.
A big-endian version is also available.
This is slow but compact code. Do not use this routine for bulk data,
@@ -1408,7 +1478,8 @@ static void set_rx_mode(struct net_device *dev)
{
struct netdev_private *np = dev->priv;
spin_lock_irq(&np->lock);
- __set_rx_mode(dev);
+ if (netif_device_present(dev))
+ __set_rx_mode(dev);
spin_unlock_irq(&np->lock);
}
@@ -1718,76 +1789,94 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
}
+static void enable_wol_mode(struct net_device *dev, int enable_intr)
+{
+ long ioaddr = dev->base_addr;
+
+ if (debug > 1)
+ printk(KERN_INFO "%s: remaining active for wake-on-lan\n",
+ dev->name);
+ /* For WOL we must restart the rx process in silent mode.
+ * Write NULL to the RxRingPtr. Only possible if
+ * rx process is stopped
+ */
+ writel(0, ioaddr + RxRingPtr);
+
+ /* and restart the rx process */
+ writel(RxOn, ioaddr + ChipCmd);
+
+ if (enable_intr) {
+ /* enable the WOL interrupt.
+ * Could be used to send a netlink message.
+ */
+ writel(readl(ioaddr + IntrMask) | WOLPkt, ioaddr + IntrMask);
+ }
+}
+
static int netdev_close(struct net_device *dev)
{
long ioaddr = dev->base_addr;
struct netdev_private *np = dev->priv;
- u32 wol = readl(ioaddr + WOLCmd) & WakeOptsSummary;
- u32 clkrun;
netif_stop_queue(dev);
- netif_carrier_off(dev);
if (debug > 1) {
- printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.",
+ printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n",
dev->name, (int)readl(ioaddr + ChipCmd));
printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d, Rx %d / %d.\n",
dev->name, np->cur_tx, np->dirty_tx, np->cur_rx, np->dirty_rx);
}
- /* Only shut down chip if wake on lan is not set */
- if (!wol) {
- /* Disable interrupts using the mask. */
- writel(0, ioaddr + IntrMask);
- writel(0, ioaddr + IntrEnable);
- writel(2, ioaddr + StatsCtrl); /* Freeze Stats */
-
- /* Stop the chip's Tx and Rx processes. */
- writel(RxOff | TxOff, ioaddr + ChipCmd);
- } else if (debug > 1) {
- printk(KERN_INFO "%s: remaining active for wake-on-lan\n",
- dev->name);
- /* spec says write 0 here */
- writel(0, ioaddr + RxRingPtr);
- /* allow wake-event interrupts now */
- writel(readl(ioaddr + IntrMask) | WOLPkt, ioaddr + IntrMask);
- }
del_timer_sync(&np->timer);
-#ifdef __i386__
- if (debug > 2) {
- int i;
- printk("\n"KERN_DEBUG" Tx ring at %8.8x:\n",
- (int)np->tx_ring);
- for (i = 0; i < TX_RING_SIZE; i++)
- printk(" #%d desc. %8.8x %8.8x.\n",
- i, np->tx_ring[i].cmd_status, np->tx_ring[i].addr);
- printk("\n"KERN_DEBUG " Rx ring %8.8x:\n",
- (int)np->rx_ring);
- for (i = 0; i < RX_RING_SIZE; i++) {
- printk(KERN_DEBUG " #%d desc. %8.8x %8.8x\n",
- i, np->rx_ring[i].cmd_status, np->rx_ring[i].addr);
- }
- }
-#endif /* __i386__ debugging only */
+ disable_irq(dev->irq);
+ spin_lock_irq(&np->lock);
+
+ writel(0, ioaddr + IntrEnable);
+ writel(0, ioaddr + IntrMask);
+ writel(2, ioaddr + StatsCtrl); /* Freeze Stats */
+
+ /* Stop the chip's Tx and Rx processes. */
+ natsemi_stop_rxtx(dev);
+ __get_stats(dev);
+ spin_unlock_irq(&np->lock);
+
+ /* race: shared irq and as most nics the DP83815
+ * reports _all_ interrupt conditions in IntrStatus, even
+ * disabled ones.
+ * packet received after disable_irq, but before stop_rxtx
+ * --> race. intr_handler would restart the rx process.
+ * netif_device_{de,a}tach around {enable,free}_irq.
+ */
+ netif_device_detach(dev);
+ enable_irq(dev->irq);
free_irq(dev->irq, dev);
+ netif_device_attach(dev);
+ /* clear the carrier last - an interrupt could reenable it otherwise */
+ netif_carrier_off(dev);
+
+ dump_ring(dev);
drain_ring(dev);
free_ring(dev);
- clkrun = np->SavedClkRun;
- if (wol) {
- /* make sure to enable PME */
- clkrun |= 0x100;
- }
-
- /* Restore PME enable bit */
- writel(np->SavedClkRun, ioaddr + ClkRun);
-
+ {
+ u32 wol = readl(ioaddr + WOLCmd) & WakeOptsSummary;
+ u32 clkrun = np->SavedClkRun;
+ /* Restore PME enable bit */
+ if (wol) {
+ /* restart the NIC in WOL mode.
+ * The nic must be stopped for this.
+ */
+ enable_wol_mode(dev, 0);
+ /* make sure to enable PME */
+ clkrun |= 0x100;
+ }
+ writel(clkrun, ioaddr + ClkRun);
#if 0
- writel(0x0200, ioaddr + ChipConfig); /* Power down Xcvr. */
+ writel(0x0200, ioaddr + ChipConfig); /* Power down Xcvr. */
#endif
-
+ }
return 0;
}
@@ -1805,49 +1894,71 @@ static void __devexit natsemi_remove1 (struct pci_dev *pdev)
#ifdef CONFIG_PM
+/*
+ * suspend/resume synchronization:
+ * entry points:
+ * netdev_open, netdev_close, netdev_ioctl, set_rx_mode, intr_handler,
+ * start_tx, tx_timeout
+ * Reading from some registers can restart the nic!
+ * No function accesses the hardware without checking netif_device_present().
+ * the check occurs under spin_lock_irq(&np->lock);
+ * exceptions:
+ * * netdev_ioctl, netdev_open.
+ * net/core checks netif_device_present() before calling them.
+ * * netdev_close: doesn't hurt.
+ * * netdev_timer: timer stopped by natsemi_suspend.
+ * * intr_handler: doesn't acquire the spinlock. suspend calls
+ * disable_irq() to enforce synchronization.
+ *
+ * netif_device_detach must occur under spin_unlock_irq(), interrupts from a detached
+ * device would cause an irq storm.
+ */
+
static int natsemi_suspend (struct pci_dev *pdev, u32 state)
{
struct net_device *dev = pci_get_drvdata (pdev);
struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
- netif_device_detach(dev);
- /* no more calls to tx_timeout, hard_start_xmit, set_rx_mode */
rtnl_lock();
- rtnl_unlock();
- /* noone within ->open */
if (netif_running (dev)) {
- int i;
del_timer_sync(&np->timer);
- /* no more link beat timer calls */
+
+ disable_irq(dev->irq);
spin_lock_irq(&np->lock);
- writel(RxOff | TxOff, ioaddr + ChipCmd);
- for(i=0;i< NATSEMI_HW_TIMEOUT;i++) {
- if ((readl(ioaddr + ChipCmd) & (TxOn|RxOn)) == 0)
- break;
- udelay(5);
- }
- if (i==NATSEMI_HW_TIMEOUT && debug) {
- printk(KERN_INFO "%s: Tx/Rx process did not stop in %d usec.\n",
- dev->name, i*5);
- } else if (debug > 2) {
- printk(KERN_DEBUG "%s: Tx/Rx process stopped in %d usec.\n",
- dev->name, i*5);
- }
- /* Tx and Rx processes stopped */
writel(0, ioaddr + IntrEnable);
- /* all irq events disabled. */
- spin_unlock_irq(&np->lock);
-
- synchronize_irq();
+ natsemi_stop_rxtx(dev);
+ netif_stop_queue(dev);
+ netif_device_detach(dev);
+ spin_unlock_irq(&np->lock);
+ enable_irq(dev->irq);
+
/* Update the error counts. */
__get_stats(dev);
/* pci_power_off(pdev, -1); */
drain_ring(dev);
+ {
+ u32 wol = readl(ioaddr + WOLCmd) & WakeOptsSummary;
+ u32 clkrun = np->SavedClkRun;
+ /* Restore PME enable bit */
+ if (wol) {
+ /* restart the NIC in WOL mode.
+ * The nic must be stopped for this.
+ * FIXME: use the WOL interupt
+ */
+ enable_wol_mode(dev, 0);
+ /* make sure to enable PME */
+ clkrun |= 0x100;
+ }
+ writel(clkrun, ioaddr + ClkRun);
+ }
+ } else {
+ netif_device_detach(dev);
}
+ rtnl_unlock();
return 0;
}
@@ -1857,18 +1968,27 @@ static int natsemi_resume (struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata (pdev);
struct netdev_private *np = dev->priv;
- if (netif_running (dev)) {
+ rtnl_lock();
+ if (netif_device_present(dev))
+ goto out;
+ if (netif_running(dev)) {
pci_enable_device(pdev);
/* pci_power_on(pdev); */
natsemi_reset(dev);
init_ring(dev);
+ spin_lock_irq(&np->lock);
init_registers(dev);
+ netif_device_attach(dev);
+ spin_unlock_irq(&np->lock);
np->timer.expires = jiffies + 1*HZ;
add_timer(&np->timer);
+ } else {
+ netif_device_attach(dev);
}
- netif_device_attach(dev);
+out:
+ rtnl_unlock();
return 0;
}
diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c
index 3bee3b574fc2..beb1430cc431 100644
--- a/drivers/net/tulip/eeprom.c
+++ b/drivers/net/tulip/eeprom.c
@@ -148,10 +148,10 @@ subsequent_board:
for (i = 0; i < count; i++) {
unsigned char media_block = *p++;
int media_code = media_block & MEDIA_MASK;
- if (media_code & 0x40)
+ if (media_block & 0x40)
p += 6;
printk(KERN_INFO "%s: 21041 media #%d, %s.\n",
- dev->name, media_code & 15, medianame[media_code & 15]);
+ dev->name, media_code, medianame[media_code]);
}
} else {
unsigned char *p = (void *)ee_data + ee_data[27];
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
index 797e1d83281c..053fdc3bdd06 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/tulip/interrupt.c
@@ -301,7 +301,7 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
long ioaddr = dev->base_addr;
int csr5;
int entry;
- int missed;
+ int csr8;
int rx = 0;
int tx = 0;
int oi = 0;
@@ -434,7 +434,6 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
}
}
if (csr5 & RxDied) { /* Missed a Rx frame. */
- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
#ifdef CONFIG_NET_HW_FLOWCONTROL
if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) {
tp->stats.rx_errors++;
@@ -548,9 +547,8 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
}
}
- if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) {
- tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
- }
+ csr8 = inl(ioaddr + CSR8);
+ tp->stats.rx_dropped += (csr8 & 0x1ffff) + ((csr8 >> 17) & 0xfff);
if (tulip_debug > 4)
printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index f130784958ff..810ceaad146a 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -15,8 +15,8 @@
*/
#define DRV_NAME "tulip"
-#define DRV_VERSION "0.9.15-pre6"
-#define DRV_RELDATE "July 2, 2001"
+#define DRV_VERSION "0.9.15-pre7"
+#define DRV_RELDATE "Oct 2, 2001"
#include <linux/config.h>
#include <linux/module.h>
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 6a90f5b5f1b5..3066566e8199 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -341,6 +341,7 @@ static int do8bitIO = 0;
/* The RIDs */
#define RID_CAPABILITIES 0xFF00
+#define RID_RSSI 0xFF04
#define RID_CONFIG 0xFF10
#define RID_SSID 0xFF11
#define RID_APLIST 0xFF12
@@ -627,6 +628,16 @@ typedef struct {
u16 atimWindow;
} BSSListRid;
+typedef struct {
+ u8 rssipct;
+ u8 rssidBm;
+} tdsRssiEntry;
+
+typedef struct {
+ u16 len;
+ tdsRssiEntry x[256];
+} tdsRssiRid;
+
#pragma pack()
#define TXCTL_TXOK (1<<1) /* report if tx is ok */
@@ -774,6 +785,7 @@ struct airo_info {
int whichbap);
int (*header_parse)(struct sk_buff*, unsigned char *);
unsigned short *flash;
+ tdsRssiEntry *rssi;
#ifdef WIRELESS_EXT
int need_commit; // Need to set config
struct iw_statistics wstats; // wireless stats
@@ -1076,6 +1088,8 @@ void stop_airo_card( struct net_device *dev, int freeres )
struct airo_info *ai = (struct airo_info*)dev->priv;
if (ai->flash)
kfree(ai->flash);
+ if (ai->rssi)
+ kfree(ai->rssi);
takedown_proc_entry( dev, ai );
if (ai->registered) {
unregister_netdev( dev );
@@ -1382,7 +1396,10 @@ static void airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) {
if (!memcmp(sa,apriv->spy_address[i],6))
{
apriv->spy_stat[i].qual = hdr.rssi[0];
- apriv->spy_stat[i].level = hdr.rssi[1];
+ if (apriv->rssi)
+ apriv->spy_stat[i].level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm;
+ else
+ apriv->spy_stat[i].level = (hdr.rssi[1] + 321) / 2;
apriv->spy_stat[i].noise = 0;
apriv->spy_stat[i].updated = 3;
break;
@@ -1568,9 +1585,29 @@ static u16 setup_card(struct airo_info *ai, u8 *mac,
if ( config->len ) {
cfg = *config;
} else {
+ tdsRssiRid rssi_rid;
+
// general configuration (read/modify/write)
status = readConfigRid(ai, &cfg);
if ( status != SUCCESS ) return ERROR;
+
+ status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid));
+ if ( status == SUCCESS ) {
+ if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)
+ memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512);
+ }
+ else {
+ CapabilityRid cap_rid;
+ if (ai->rssi) {
+ kfree(ai->rssi);
+ ai->rssi = NULL;
+ }
+ status = readCapabilityRid(ai, &cap_rid);
+ if ((status == SUCCESS) && (cap_rid.softCap & 8))
+ cfg.rmode |= RXMODE_NORMALIZED_RSSI;
+ else
+ printk(KERN_WARNING "airo: unknown received signal level\n");
+ }
cfg.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;
/* Save off the MAC */
@@ -3814,7 +3851,7 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
/* Hum... Should put the right values there */
range.max_qual.qual = 10;
- range.max_qual.level = 100;
+ range.max_qual.level = 0;
range.max_qual.noise = 0;
range.sensitivity = 65535;
@@ -3976,7 +4013,10 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
loseSync = 0;
memcpy(s[i].sa_data, BSSList.bssid, 6);
s[i].sa_family = ARPHRD_ETHER;
- qual[i].level = BSSList.rssi;
+ if (local->rssi)
+ qual[i].level = 0x100 - local->rssi[BSSList.rssi].rssidBm;
+ else
+ qual[i].level = (BSSList.rssi + 321) / 2;
qual[i].qual = qual[i].noise = 0;
qual[i].updated = 2;
if (BSSList.index == 0xffff) break;
@@ -4190,7 +4230,10 @@ struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
/* Signal quality and co. But where is the noise level ??? */
local->wstats.qual.qual = status_rid.signalQuality;
- local->wstats.qual.level = status_rid.normalizedSignalStrength;
+ if (local->rssi)
+ local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm;
+ else
+ local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2;
local->wstats.qual.noise = 0;
local->wstats.qual.updated = 3;
diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c
index 3c567682930c..17a347777392 100644
--- a/drivers/net/wireless/hermes.c
+++ b/drivers/net/wireless/hermes.c
@@ -14,8 +14,31 @@
* particular order).
*
* Copyright (C) 2000, David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
+ * Copyright (C) 2001, David Gibson, IBM <hermes@gibson.dropbear.id.au>
*
- * This file distributed under the GPL, version 2. */
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above. If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use your
+ * version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -30,10 +53,10 @@
#include "hermes.h"
-static char version[] __initdata = "hermes.c: 1 Aug 2001 David Gibson <hermes@gibson.dropbear.id.au>";
+static char version[] __initdata = "hermes.c: 3 Oct 2001 David Gibson <hermes@gibson.dropbear.id.au>";
MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller");
MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual MPL/GPL");
/* These are maximum timeouts. Most often, card wil react much faster */
#define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */
@@ -42,9 +65,6 @@ MODULE_LICENSE("GPL");
#define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
#define BAP_BUSY_TIMEOUT (500) /* In iterations of ~1us */
-#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
-#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
-
/*
* Debugging helpers
*/
@@ -292,7 +312,7 @@ int hermes_allocate(hermes_t *hw, uint16_t size, uint16_t *fid)
* from firmware
*
* Callable from any context */
-static int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset)
+int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset)
{
int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
@@ -305,9 +325,14 @@ static int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset)
k = BAP_BUSY_TIMEOUT;
reg = hermes_read_reg(hw, oreg);
+ while ((reg & HERMES_OFFSET_BUSY) & k) {
+ k--;
+ udelay(1);
+ reg = hermes_read_reg(hw, oreg);
+ }
if (reg & HERMES_OFFSET_BUSY)
- return -EBUSY;
+ return -ETIMEDOUT;
/* Now we actually set up the transfer */
hermes_write_reg(hw, sreg, id);
@@ -342,7 +367,7 @@ static int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset)
*
* Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
*/
-int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
+int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
uint16_t id, uint16_t offset)
{
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -356,7 +381,7 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
goto out;
/* Actually do the transfer */
- hermes_read_data(hw, dreg, buf, len/2);
+ hermes_read_words(hw, dreg, buf, len/2);
out:
return err;
@@ -368,7 +393,7 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
*
* Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
*/
-int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, uint16_t len,
+int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
uint16_t id, uint16_t offset)
{
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -382,7 +407,7 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, uint16_t len,
goto out;
/* Actually do the transfer */
- hermes_write_data(hw, dreg, buf, len/2);
+ hermes_write_words(hw, dreg, buf, len/2);
out:
return err;
@@ -434,17 +459,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, uint16_t rid, int buflen,
lengths in the records seem to be wrong, frequently */
count = buflen / 2;
-#if 0
- if (length)
- count = (MIN(buflen, rlength) + 1) / 2;
- else {
- count = buflen / 2;
- if (rlength != buflen)
- printk(KERN_WARNING "hermes_read_ltv(): Incorrect \
-record length %d instead of %d on RID 0x%04x\n", rlength, buflen, rid);
- }
-#endif
- hermes_read_data(hw, dreg, buf, count);
+ hermes_read_words(hw, dreg, buf, count);
out:
return err;
@@ -470,7 +485,7 @@ int hermes_write_ltv(hermes_t *hw, int bap, uint16_t rid,
count = length - 1;
- hermes_write_data(hw, dreg, value, count);
+ hermes_write_words(hw, dreg, value, count);
err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE,
rid, &resp);
diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h
index 58c663331b5b..a8cfaf4f7d56 100644
--- a/drivers/net/wireless/hermes.h
+++ b/drivers/net/wireless/hermes.h
@@ -50,6 +50,7 @@
#define HERMES_FRAME_LEN_MAX (2304)
#define HERMES_MAX_MULTICAST (16)
#define HERMES_MAGIC (0x7d1f)
+#define HERMES_SYMBOL_MAX_VER (14)
/*
* Hermes register offsets
@@ -202,24 +203,21 @@
#define HERMES_RID_WEP_AVAIL (0xfd4f)
#define HERMES_RID_CURRENT_CHANNEL (0xfdc1)
#define HERMES_RID_DATARATES (0xfdc6)
-#define HERMES_RID_SYMBOL_PRIMARY_VER (0xfd03)
-#define HERMES_RID_SYMBOL_SECONDARY_VER (0xfd21)
+#define HERMES_RID_SYMBOL_SECONDARY_VER (0xfd24)
#define HERMES_RID_SYMBOL_KEY_LENGTH (0xfc2B)
/*
* Frame structures and constants
*/
-#define __PACKED__ __attribute__ ((packed))
-
typedef struct hermes_frame_desc {
/* Hermes - i.e. little-endian byte-order */
- uint16_t status __PACKED__;
- uint16_t res1, res2 __PACKED__;
- uint16_t q_info __PACKED__;
- uint16_t res3, res4 __PACKED__;
- uint16_t tx_ctl __PACKED__;
-} hermes_frame_desc_t;
+ uint16_t status;
+ uint16_t res1, res2;
+ uint16_t q_info;
+ uint16_t res3, res4;
+ uint16_t tx_ctl;
+} __attribute__ ((packed)) hermes_frame_desc_t;
#define HERMES_RXSTAT_ERR (0x0003)
#define HERMES_RXSTAT_MACPORT (0x0700)
@@ -265,20 +263,16 @@ typedef struct hermes_multicast {
#define hermes_read_regn(hw, name) (hermes_read_reg((hw), HERMES_##name))
#define hermes_write_regn(hw, name, val) (hermes_write_reg((hw), HERMES_##name, (val)))
-/* Note that for the next two, the count is in 16-bit words, not bytes */
-#define hermes_read_data(hw, off, buf, count) (insw((hw)->iobase + (off), (buf), (count)))
-#define hermes_write_data(hw, off, buf, count) (outsw((hw)->iobase + (off), (buf), (count)))
-
/* Function prototypes */
void hermes_struct_init(hermes_t *hw, uint io);
int hermes_reset(hermes_t *hw);
int hermes_docmd_wait(hermes_t *hw, uint16_t cmd, uint16_t parm0, hermes_response_t *resp);
int hermes_allocate(hermes_t *hw, uint16_t size, uint16_t *fid);
-
-int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
+int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset);
+int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
uint16_t id, uint16_t offset);
-int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, uint16_t len,
+int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
uint16_t id, uint16_t offset);
int hermes_read_ltv(hermes_t *hw, int bap, uint16_t rid, int buflen,
uint16_t *length, void *buf);
@@ -323,6 +317,10 @@ static inline int hermes_disable_port(hermes_t *hw, int port)
#define HERMES_BYTES_TO_RECLEN(n) ( ((n) % 2) ? (((n)+1)/2)+1 : ((n)/2)+1 )
#define HERMES_RECLEN_TO_BYTES(n) ( ((n)-1) * 2 )
+/* Note that for the next two, the count is in 16-bit words, not bytes */
+#define hermes_read_words(hw, off, buf, count) (insw((hw)->iobase + (off), (buf), (count)))
+#define hermes_write_words(hw, off, buf, count) (outsw((hw)->iobase + (off), (buf), (count)))
+
#define HERMES_READ_RECORD(hw, bap, rid, buf) \
(hermes_read_ltv((hw),(bap),(rid), sizeof(*buf), NULL, (buf)))
#define HERMES_WRITE_RECORD(hw, bap, rid, buf) \
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 777faa3e56b8..3d5505048ef2 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -1,4 +1,4 @@
-/* orinoco.c 0.07 - (formerly known as dldwd_cs.c and orinoco_cs.c)
+/* orinoco.c 0.08 - (formerly known as dldwd_cs.c and orinoco_cs.c)
*
* A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
* as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
@@ -190,13 +190,35 @@
* Rx path, but don't make as much noise about it.
* o Firmware detection cleanups.
*
+ * v0.07 -> v0.08 - 3/10/2001 - David Gibson
+ * o Fixed a possible buffer overrun found by the Stanford checker (in
+ * dldwd_ioctl_setiwencode()). Can only be called by root anyway, so not
+ * a big problem.
+ * o Turned has_big_wep on for Intersil cards. That's not true for all of them
+ * but we should at least let the capable ones try.
+ * o Wait for BUSY to clear at the beginning of hermes_bap_seek(). I
+ * realised that my assumption that the driver's serialization
+ * would prevent the BAP being busy on entry was possibly false, because
+ * things other than seeks may make the BAP busy.
+ * o Use "alternate" (oui 00:00:00) encapsulation by default.
+ * Setting use_old_encaps will mimic the old behaviour, but I
+ * think we will be able to eliminate this.
+ * o Don't try to make __initdata const (the version string).
+ * This can't work because of the way the __initdata sectioning
+ * works.
+ * o Added MODULE_LICENSE tags.
+ * o Support for PLX (transparent PCMCIA->PCI brdge) cards.
+ * o Improved support for Symbol firmware - we can actually tell
+ * the version now.
*
* TODO - Jean II
- * o inline functions (lot's of candidate, need to reorder code)
+ * o inline functions (lots of candidate, need to reorder code)
* o Test PrismII/Symbol cards & firmware versions
* o Mini-PCI support (some people have reported success - JII)
*/
+#include <linux/config.h>
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -227,7 +249,7 @@
#include "hermes.h"
#include "orinoco.h"
-static char version[] __initdata = "orinoco.c 0.07 (David Gibson <hermes@gibson.dropbear.id.au> and others)";
+static char version[] __initdata = "orinoco.c 0.08 (David Gibson <hermes@gibson.dropbear.id.au> and others)";
MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based and similar wireless cards");
MODULE_LICENSE("Dual MPL/GPL");
@@ -238,10 +260,8 @@ int dldwd_debug = ORINOCO_DEBUG;
MODULE_PARM(dldwd_debug, "i");
#endif
-/* FIXME: We need a better way of handling this */
-/* Set this flag to use 00:00:00 for the encapsulation oui instead of 00:00:F8 */
-static int use_alternate_encaps; /* =0 */
-MODULE_PARM(use_alternate_encaps, "i");
+int use_old_encaps = 0;
+MODULE_PARM(use_old_encaps, "i");
const long channel_frequency[] = {
2412, 2417, 2422, 2427, 2432, 2437, 2442,
@@ -307,12 +327,13 @@ struct dldwd_frame_hdr {
/* 802.2 LLL header SNAP used for SNAP encapsulation over 802.11 */
struct p8022_hdr encaps_hdr = {
- 0xaa, 0xaa, 0x03, {0x00, 0x00, 0xf8}
-};
-struct p8022_hdr alternate_encaps_hdr = {
0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}
};
+struct p8022_hdr old_encaps_hdr = {
+ 0xaa, 0xaa, 0x03, {0x00, 0x00, 0xf8}
+};
+
/* How many times to retry if we get an EIO reading the BAP in the Rx path */
#define RX_EIO_RETRY 10
@@ -881,7 +902,7 @@ static int dldwd_hw_get_bitratelist(dldwd_priv_t *priv, int *numrates,
num = le16_to_cpu(list.len);
*numrates = num;
- num = MIN(num, max);
+ num = min(num, max);
for (i = 0; i < num; i++) {
rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
@@ -1286,7 +1307,7 @@ static void determine_firmware(struct net_device *dev)
if (sta_id.vendor == 1) {
/* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
- ELSE, Meloc, HP, IBM, Dell 1150 */
+ ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
printk(KERN_DEBUG "%s: Looks like a Lucent/Agere firmware "
"version %d.%02d\n", dev->name,
sta_id.major, sta_id.minor);
@@ -1303,7 +1324,7 @@ static void determine_firmware(struct net_device *dev)
priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
Gold cards from the others? */
priv->has_mwo = (firmver >= 0x60000);
- priv->has_pm = (firmver >= 0x40020);
+ priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
priv->has_preamble = 0;
priv->ibss_port = 1;
/* Tested with Lucent firmware :
@@ -1314,27 +1335,59 @@ static void determine_firmware(struct net_device *dev)
/* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
/* Intel MAC : 00:02:B3:* */
/* 3Com MAC : 00:50:DA:* */
+ union symbol_sta_id {
+ char raw[HERMES_SYMBOL_MAX_VER];
+ char string[HERMES_SYMBOL_MAX_VER + 1];
+ } symbol_sta_id;
+
+ /* Get the Symbol firmware version */
+ err = HERMES_READ_RECORD(hw, USER_BAP,
+ HERMES_RID_SYMBOL_SECONDARY_VER,
+ &(symbol_sta_id.raw));
+ if (err) {
+ printk(KERN_WARNING "%s: Error %d reading Symbol firmware info. Wildly guessing capabilities...\n",
+ dev->name, err);
+ firmver = 0;
+ symbol_sta_id.string[0] = '\0';
+ } else {
+ /* The firmware revision is a string, the format is
+ * something like : "V2.20-01".
+ * Quick and dirty parsing... - Jean II
+ */
+ firmver = ((symbol_sta_id.raw[1] - '0') << 16)
+ | ((symbol_sta_id.raw[3] - '0') << 12)
+ | ((symbol_sta_id.raw[4] - '0') << 8)
+ | ((symbol_sta_id.raw[6] - '0') << 4)
+ | (symbol_sta_id.raw[7] - '0');
+
+ symbol_sta_id.string[HERMES_SYMBOL_MAX_VER] = '\0';
+ }
+
printk(KERN_DEBUG "%s: Looks like a Symbol firmware "
- "(unknown version)\n", dev->name);
+ "version [%s] (parsing to %X)\n", dev->name,
+ symbol_sta_id.string, firmver);
- /* FIXME : we need to get Symbol firmware revision.
- * I tried to use SYMBOL_***ARY_VER, but it didn't
- * returned anything proper... */
priv->firmware_type = FIRMWARE_TYPE_SYMBOL;
priv->tx_rate_ctrl = 0xF; /* 11 Mb/s auto */
priv->need_card_reset = 1;
priv->broken_reset = 0;
priv->broken_allocate = 1;
priv->has_port3 = 1;
- priv->has_ibss = 1; /* FIXME */
- priv->has_wep = 1; /* FIXME */
- priv->has_big_wep = 1; /* RID_SYMBOL_KEY_LENGTH */
+ priv->has_ibss = (firmver >= 0x20000);
+ priv->has_wep = (firmver >= 0x15012);
+ priv->has_big_wep = (firmver >= 0x20000);
priv->has_mwo = 0;
- priv->has_pm = 1; /* FIXME */
- priv->has_preamble = 0; /* FIXME */
+ priv->has_pm = (firmver >= 0x20000) && (firmver < 0x22000);
+ priv->has_preamble = (firmver >= 0x20000);
priv->ibss_port = 4;
- /* Tested with Intel firmware : v15 => Jean II */
+ /* Tested with Intel firmware : 0x20015 => Jean II */
+ /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
} else {
+ /* D-Link, Linksys, Adtron, ZoomAir, and many others...
+ * Samsung, Compaq 100/200 and Proxim are slightly
+ * different and less well tested */
+ /* D-Link MAC : 00:40:05:* */
+ /* Addtron MAC : 00:90:D1:* */
printk(KERN_DEBUG "%s: Looks like an Intersil firmware "
"version %d.%02d\n", dev->name,
sta_id.major, sta_id.minor);
@@ -1347,7 +1400,7 @@ static void determine_firmware(struct net_device *dev)
priv->has_port3 = 1;
priv->has_ibss = (firmver >= 0x00007); /* FIXME */
priv->has_wep = (firmver >= 0x00008);
- priv->has_big_wep = 0;
+ priv->has_big_wep = priv->has_wep;
priv->has_mwo = 0;
priv->has_pm = (firmver >= 0x00007);
priv->has_preamble = 0;
@@ -1427,9 +1480,9 @@ dldwd_init(struct net_device *dev)
goto out;
}
if ( nickbuf.len )
- len = MIN(IW_ESSID_MAX_SIZE, le16_to_cpu(nickbuf.len));
+ len = min(IW_ESSID_MAX_SIZE, le16_to_cpu(nickbuf.len));
else
- len = MIN(IW_ESSID_MAX_SIZE, 2 * reclen);
+ len = min(IW_ESSID_MAX_SIZE, 2 * reclen);
memcpy(priv->nick, &nickbuf.val, len);
priv->nick[len] = '\0';
@@ -1556,20 +1609,12 @@ dldwd_get_wireless_stats(struct net_device *dev)
err = HERMES_READ_RECORD(hw, USER_BAP,
HERMES_RID_COMMSQUALITY, &cq);
- le16_to_cpus(&cq.qual);
- le16_to_cpus(&cq.signal);
- le16_to_cpus(&cq.noise);
-
DEBUG(3, "%s: Global stats = %X-%X-%X\n", dev->name,
cq.qual, cq.signal, cq.noise);
- /* Why are we using MIN/MAX ? We don't really care
- * if the value goes above max, because we export the
- * raw dBm values anyway. The normalisation should be done
- * in user space - Jean II */
- wstats->qual.qual = MAX(MIN(cq.qual, 0x8b-0x2f), 0);
- wstats->qual.level = MAX(MIN(cq.signal, 0x8a), 0x2f) - 0x95;
- wstats->qual.noise = MAX(MIN(cq.noise, 0x8a), 0x2f) - 0x95;
+ wstats->qual.qual = le16_to_cpu(cq.qual);
+ wstats->qual.level = le16_to_cpu(cq.signal);
+ wstats->qual.noise = le16_to_cpu(cq.noise);
wstats->qual.updated = 7;
}
@@ -1593,9 +1638,9 @@ static inline void dldwd_spy_gather(struct net_device *dev,
* source address with out list, and if match, get the stats... */
for (i = 0; i < priv->spy_number; i++)
if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
- priv->spy_stat[i].qual = MAX(MIN(cq->qual, 0x8b-0x2f), 0);
- priv->spy_stat[i].level = MAX(MIN(cq->signal, 0x8a), 0x2f) - 0x95;
- priv->spy_stat[i].noise = MAX(MIN(cq->noise, 0x8a), 0x2f) - 0x95;
+ priv->spy_stat[i].qual = cq->qual;
+ priv->spy_stat[i].level = cq->signal;
+ priv->spy_stat[i].noise = cq->noise;
priv->spy_stat[i].updated = 7;
}
}
@@ -1674,7 +1719,7 @@ dldwd_xmit(struct sk_buff *skb, struct net_device *dev)
dldwd_lock(priv);
/* Length of the packet body */
- len = MAX(skb->len - ETH_HLEN, ETH_ZLEN);
+ len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN);
eh = (struct ethhdr *)skb->data;
@@ -1699,12 +1744,13 @@ dldwd_xmit(struct sk_buff *skb, struct net_device *dev)
hdr.p8023.h_proto = htons(data_len + ENCAPS_OVERHEAD);
/* 802.2 header */
- /* FIXME: ugh, what a hack for the 00:00:00 APs. Need to find a better way */
- if (use_alternate_encaps)
- memcpy(&hdr.p8022, &alternate_encaps_hdr, sizeof(alternate_encaps_hdr));
+ if (! use_old_encaps)
+ memcpy(&hdr.p8022, &encaps_hdr,
+ sizeof(encaps_hdr));
else
- memcpy(&hdr.p8022, &encaps_hdr, sizeof(encaps_hdr));
-
+ memcpy(&hdr.p8022, &encaps_hdr,
+ sizeof(old_encaps_hdr));
+
hdr.ethertype = eh->h_proto;
err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
txfid, 0);
@@ -1933,12 +1979,12 @@ static int dldwd_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq)
uint16_t xlen = 0;
int err = 0;
char keybuf[MAX_KEY_SIZE];
-
+
if (erq->pointer) {
/* We actually have a key to set */
- if(erq->length > MAX_KEY_SIZE)
+ if ( (erq->length < SMALL_KEY_SIZE) || (erq->length > MAX_KEY_SIZE) )
return -EINVAL;
-
+
if (copy_from_user(keybuf, erq->pointer, erq->length))
return -EFAULT;
}
@@ -3512,7 +3558,7 @@ dldwd_proc_get_hermes_recs(char *page, char **start, off_t requested_offset,
buf += sprintf(buf, "%-15s (0x%04x): length=%d (%d bytes)\tvalue=", record_table[i].name,
rid, length, (length-1)*2);
- len = MIN( MAX(minlen, (length-1)*2), maxlen);
+ len = min( (int)max(minlen, ((int)length-1)*2), maxlen);
switch (record_table[i].displaytype) {
case DISPLAY_WORDS:
@@ -3531,7 +3577,7 @@ dldwd_proc_get_hermes_recs(char *page, char **start, off_t requested_offset,
break;
case DISPLAY_STRING:
- len = MIN(len, le16_to_cpu(val16[0])+2);
+ len = min(len, le16_to_cpu(val16[0])+2);
val8[len] = '\0';
buf += sprintf(buf, "\"%s\"", (char *)&val16[1]);
break;
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index 07d94110e486..c5f30c36cd9d 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -25,7 +25,7 @@
#define DLDWD_MACPORT 0
#define IRQ_LOOP_MAX 10
#define TX_NICBUF_SIZE 2048
-#define TX_NICBUF_SIZE_BUG 1585 /* Bug in Intel firmware */
+#define TX_NICBUF_SIZE_BUG 1585 /* Bug in Symbol firmware */
#define MAX_KEYS 4
#define MAX_KEY_SIZE 14
#define LARGE_KEY_SIZE 13
@@ -110,7 +110,7 @@ extern struct list_head dldwd_instances;
#ifdef ORINOCO_DEBUG
extern int dldwd_debug;
-#define DEBUG(n, args...) if (dldwd_debug>(n)) printk(KERN_DEBUG args)
+#define DEBUG(n, args...) do { if (dldwd_debug>(n)) printk(KERN_DEBUG args); } while(0)
#define DEBUGMORE(n, args...) do { if (dldwd_debug>(n)) printk(args); } while (0)
#else
#define DEBUG(n, args...) do { } while (0)
@@ -120,9 +120,6 @@ extern int dldwd_debug;
#define TRACE_ENTER(devname) DEBUG(2, "%s: -> " __FUNCTION__ "()\n", devname);
#define TRACE_EXIT(devname) DEBUG(2, "%s: <- " __FUNCTION__ "()\n", devname);
-#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
-#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
-
#define RUP_EVEN(a) ( (a) % 2 ? (a) + 1 : (a) )
/* struct net_device methods */
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index 651ee6c81925..996eb4c6f680 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -1,4 +1,4 @@
-/* orinoco_cs.c 0.07 - (formerly known as dldwd_cs.c)
+/* orinoco_cs.c 0.08 - (formerly known as dldwd_cs.c)
*
* A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
* as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
@@ -10,6 +10,8 @@
* Copyright notice & release notes in file orinoco.c
*/
+#include <linux/config.h>
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -42,7 +44,7 @@
/*====================================================================*/
-static char version[] __initdata = "orinoco_cs.c 0.07 (David Gibson <hermes@gibson.dropbear.id.au> and others)";
+static char version[] __initdata = "orinoco_cs.c 0.08 (David Gibson <hermes@gibson.dropbear.id.au> and others)";
MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco, Prism II based and similar wireless cards");
diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids
index b1f338e0aea5..45966f06cb69 100644
--- a/drivers/pci/pci.ids
+++ b/drivers/pci/pci.ids
@@ -27,6 +27,8 @@
0e11 Compaq Computer Corporation
0001 PCI to EISA Bridge
0002 PCI to ISA Bridge
+ 0049 NC7132 Gigabit Upgrade Module
+ 004a NC6136 Gigabit Server Adapter
0508 Netelligent 4/16 Token Ring
1000 Triflex/Pentium Bridge, Model 1000
2000 Triflex/Pentium Bridge, Model 2000
@@ -40,6 +42,8 @@
a0f0 Advanced System Management Controller
a0f3 Triflex PCI to ISA Bridge
a0f7 PCI Hotplug Controller
+ 8086 002a PCI Hotplug Controller A
+ 8086 002b PCI Hotplug Controller B
a0f8 USB Open Host Controller
ae10 Smart-2/P RAID Controller
0e11 4030 Smart-2/P Array Controller
@@ -61,13 +65,29 @@
ae6d NorthStar CPU to PCI Bridge
b011 Integrated Netelligent 10/100
b012 Netelligent 10 T/2
+ b01e NC3120 Fast Ethernet NIC
+ b01f NC3122 Fast Ethernet NIC
+ b02f NC1120 Ethernet NIC
b030 Netelligent WS 5100
- b04a 10/100TX WOL UTP Controller
- b0c6 10/100TX Embedded WOL UTP Controller
- b0d7 NC3121 (Rev A & B)
+ b04a 10/100 TX PCI Intel WOL UTP Controller
+ b0c6 NC3161 Fast Ethernet NIC
+ b0c7 NC3160 Fast Ethernet NIC
+ b0d7 NC3121 Fast Ethernet NIC
+ b0dd NC3131 Fast Ethernet NIC
+ b0de NC3132 Fast Ethernet Module
+ b0df NC6132 Gigabit Module
+ b0e0 NC6133 Gigabit Module
+ b0e1 NC3133 Fast Ethernet Module
+ b123 NC6134 Gigabit NIC
+ b134 NC3163 Fast Ethernet NIC
+ b13c NC3162 Fast Ethernet NIC
+ b144 NC3123 Fast Ethernet NIC
+ b163 NC3134 Fast Ethernet NIC
+ b164 NC3135 Fast Ethernet Upgrade Module
+ b1a4 NC7131 Gigabit Server Adapter
f130 NetFlex-3/P ThunderLAN 1.0
f150 NetFlex-3/P ThunderLAN 2.3
-1000 Symbios Logic Inc. (formerly NCR)
+1000 LSI Logic / Symbios Logic (formerly NCR)
0001 53c810
1000 1000 8100S
0002 53c820
@@ -141,16 +161,19 @@
0e11 b10e 3D Rage LT Pro (Compaq Armada 1750)
1028 0085 Rage 3D LT Pro
4c44 3D Rage LT Pro AGP-66
- 4c46 Mobility M3 AGP 2x
+ 4c45 Rage Mobility M3 AGP
+ 4c46 Rage Mobility M3 AGP 2x
4c47 3D Rage LT-G 215LG
4c49 3D Rage LT Pro
- 4c4d 3D Rage P/M Mobility AGP 2x
- 4c4e 3D Rage L Mobility AGP 2x
+ 4c4d Rage Mobility P/M AGP 2x
+ 4c4e Rage Mobility L AGP 2x
4c50 3D Rage LT Pro
4c51 3D Rage LT Pro
- 4c52 3D Rage P/M Mobility
- 4c53 3D Rage L Mobility
+ 4c52 Rage Mobility P/M
+ 4c53 Rage Mobility L
4c54 264LT [Mach64 LT]
+ 4d46 Rage Mobility M4 AGP
+ 4d4c Rage Mobility M4 AGP
5041 Rage 128 PA
5042 Rage 128 PB
5043 Rage 128 PC
@@ -244,7 +267,7 @@
000f OHCI Compliant FireWire Controller
0011 National PCI System I/O
0012 USB Controller
- 0020 DP83815 (MacPhyter) Ethernet Controller
+ 0020 DP83815
d001 87410 IDE
100c Tseng Labs Inc
3202 ET4000/W32p rev A
@@ -276,6 +299,8 @@
1113 1207 EN-1207-TX Fast Ethernet
1186 1100 DFE-500TX Fast Ethernet
1186 1112 DFE-570TX Fast Ethernet
+ 1186 1140 DFE-660 Cardbus Ethernet 10/100
+ 1186 1142 DFE-660 Cardbus Ethernet 10/100
1282 9100 AEF-380TXD Fast Ethernet
1385 1100 FA310TX Fast Ethernet
2646 0001 KNE100TX Fast Ethernet
@@ -374,7 +399,7 @@
0020 MCA
0022 IBM27-82351
002d Python
- 002e ServeRAID controller
+ 002e ServeRAID-3x
0036 Miami
003a CPU to PCI Bridge
003e 16/4 Token ring UTP/STP controller
@@ -415,6 +440,10 @@
0144 Yotta Video Compositor Output
1014 0145 Yotta Output Controller (ytout)
0156 405GP PLB to PCI Bridge
+ 01bd Netfinity ServeRAID controller
+ 01be ServeRAID-4M
+ 01bf ServeRAID-4L
+ 022e ServeRAID-4H
ffff MPIC-2 interrupt controller
1015 LSI Logic Corp of Canada
1016 ICL Personal Systems
@@ -438,6 +467,9 @@
9712 Pipeline 9712
c24a 90C
101e American Megatrends Inc.
+ 1960 MegaRAID
+ 1028 0471 PowerEdge RAID Controller 3/QC
+ 1028 0493 PowerEdge RAID Controller 3/DC
9010 MegaRAID
9030 EIDE Controller
9031 EIDE Controller
@@ -589,6 +621,7 @@
0005 PowerEdge Expandable RAID Controller 3/Di
0006 PowerEdge Expandable RAID Controller 3/Di
0008 PowerEdge Expandable RAID Controller 3/Di
+ 000a PowerEdge Expandable RAID Controller 3/Di
1029 Siemens Nixdorf IS
102a LSI Logic
0000 HYDRA
@@ -642,6 +675,8 @@
0e11 b16f Matrox MGA-G400 AGP
102b 0328 Millennium G400 16Mb SDRAM
102b 0338 Millennium G400 16Mb SDRAM
+ 102b 0378 Millennium G400 32Mb SDRAM
+ 102b 0641 Millennium G450 32Mb SDRAM
102b 19d8 Millennium G400 16Mb SGRAM
102b 19f8 Millennium G400 32Mb SGRAM
102b 2159 Millennium G400 Dual Head 16Mb
@@ -664,6 +699,8 @@
102b ff05 MGA-G100 Productiva AGP Multi-Monitor
110a 001e MGA-G100 AGP
2007 MGA Mistral
+ 2527 MGA G550 AGP
+ 102b 0f84 Millennium G550 Dual Head DDR 32Mb
4536 VIA Framegrabber
6573 Shark 10/100 Multiport SwitchNIC
102c Chips and Technologies
@@ -984,6 +1021,7 @@
4802 Falcon
4803 Hawk
4806 CPX8216
+ 4d68 20268
5600 SM56 PCI Modem
1057 0300 SM56 PCI Speakerphone Modem
1057 0301 SM56 PCI Voice Modem
@@ -1129,19 +1167,26 @@
0012 YMF-754 [DS-1E Audio Controller]
1073 0012 DS-XG PCI Audio Codec
0020 DS-1 Audio
+ 2000 DS2416 Digital Mixing Card
+ 1073 2000 DS2416 Digital Mixing Card
1074 NexGen Microsystems
4e78 82c500/1
1075 Advanced Integrations Research
1076 Chaintech Computer Co. Ltd
-1077 Q Logic
+1077 QLogic Corp.
+ 1016 QLA10160
1020 ISP1020
1022 ISP1022
- 1080 ISP1080
- 1240 ISP1240
- 1280 ISP1280
+ 1080 QLA1080
+ 1216 QLA12160
+ 101e 8471 QLA12160 on AMI MegaRAID
+ 101e 8493 QLA12160 on AMI MegaRAID
+ 1240 QLA1240
+ 1280 QLA1280
2020 ISP2020A
- 2100 ISP2100
- 2200 ISP2200
+ 2100 QLA2100
+ 2200 QLA2200
+ 2300 QLA2300
1078 Cyrix Corporation
0000 5510 [Grappa]
0001 PCI Master
@@ -1291,7 +1336,7 @@
109e Brooktree Corporation
0350 Bt848 TV with DMA push
0351 Bt849A Video capture
- 036c Bt879(?) Video Capture
+ 036c Bt879(??) Video Capture
13e9 0070 Win/TV (Video Section)
036e Bt878
0070 13eb WinTV/GO
@@ -1476,6 +1521,8 @@
906e 9060ES
9080 9080
10b5 9080 9080 [real subsystem ID not set]
+ a001 GTEK Jetport II 2 port serial adaptor
+ c001 GTEK Cyclone 16/32 port serial adaptor
10b6 Madge Networks
0001 Smart 16/4 PCI Ringnode
0002 Smart 16/4 PCI Ringnode Mk2
@@ -1505,13 +1552,13 @@
10b7 3590 TokenLink Velocity XL Adapter
4500 3c450 Cyclone/unknown
5055 3c555 Laptop Hurricane
- 6055 3c556 Laptop Tornado
+ 6055 3c556 Laptop Hurricane
6056 3c556B Laptop Hurricane
5057 3c575 [Megahertz] 10/100 LAN CardBus
10b7 5a57 3C575 Megahertz 10/100 LAN Cardbus PC Card
- 5157 3CCFE575BT Cyclone CardBus
+ 5157 3c575 [Megahertz] 10/100 LAN CardBus
10b7 5b57 3C575 Megahertz 10/100 LAN Cardbus PC Card
- 5257 3CCFE575CT Tornado CardBus
+ 5257 3CCFE575CT Cyclone CardBus
5900 3c590 10BaseT [Vortex]
5920 3c592 EISA 10mbps Demon/Vortex
5950 3c595 100BaseTX [Vortex]
@@ -1521,8 +1568,8 @@
5b57 3c595 [Megahertz] 10/100 LAN CardBus
10b7 5b57 3C575 Megahertz 10/100 LAN Cardbus PC Card
6560 3CCFE656 Cyclone CardBus
- 6562 3CCFEM656B Cyclone CardBus
- 6564 3CXFEM656C Tornado CardBus
+ 6562 3CCFEM656 [id 6562] Cyclone CardBus
+ 6564 3CCFEM656 [id 6564] Cyclone CardBus
7646 3cSOHO100-TX Hurricane
8811 Token ring
9000 3c900 10BaseT [Boomerang]
@@ -1564,8 +1611,8 @@
10b7 1000 3C905C-TX Fast Etherlink for PC Management NIC
9800 3c980-TX [Fast Etherlink XL Server Adapter]
10b7 9800 3c980-TX Fast Etherlink XL Server Adapter
- 9805 3c982 Dual Port Server Cyclone
- 10b7 9805 3c982 Dual Port Server Cyclone
+ 9805 3c980-TX 10/100baseTX NIC [Python-T]
+ 10b7 9805 3c980 10/100baseTX NIC [Python-T]
10b8 Standard Microsystems Corp [SMC]
0005 83C170QF
1055 e000 LANEPIC
@@ -1674,6 +1721,8 @@
10f7 8312 MagicGraph 128XD
0005 [MagicMedia 256AV]
0006 NM2360 [MagicMedia 256ZX]
+ 0016 NM2380 [MagicMedia 256XL+]
+ 10c8 0016 MagicMedia 256XL+
0083 [MagicGraph 128ZV Plus]
8005 [MagicMedia 256AV Audio]
0e11 b0d1 MagicMedia 256AV Audio Device on Discovery
@@ -1730,7 +1779,7 @@
0008 EDGE 3D [NV1]
0009 EDGE 3D [NV1]
0010 Mutara V08 [NV2]
- 0020 Riva TnT 128 [NV04]
+ 0020 Riva TnT [NV04]
1043 0200 V3400 TNT
1048 0c18 Erazor II SGRAM
1092 0550 Viper V550
@@ -1803,14 +1852,16 @@
1102 102e CT6971 GeForce 256 DDR
14af 5021 3D Prophet DDR-DVI
0103 Quadro (GeForce 256 GL)
- 0110 NV11
- 0111 NV11 DDR
- 0113 NV11 GL
- 0150 NV15 (Geforce2 GTS)
+ 0110 NV11 (GeForce2 MX)
+ 0111 NV11 (GeForce2 MX DDR)
+ 0112 GeForce2 Go
+ 0113 NV11 (GeForce2 MXR)
+ 0150 NV15 (Geforce2 Pro)
107d 2840 WinFast GeForce2 GTS with TV output
0151 NV15 DDR (Geforce2 GTS)
- 0152 NV15 Bladerunner (Geforce2 GTS)
- 0153 NV15 GL (Quadro2)
+ 0152 NV15 Bladerunner (Geforce2 Ultra)
+ 0153 NV15 GL (Quadro2 Pro)
+ 0203 Quadro DCC
10df Emulex Corporation
10df Light Pulse Fibre Channel Adapter
1ae5 LP6000 Fibre Channel Host Adapter
@@ -1824,6 +1875,7 @@
9128 IMS9129 [Twin turbo 128]
10e1 Tekram Technology Co.,Ltd.
0391 TRM-S1040
+ 10e1 0391 DC-315U SCSI-3 Host Adapter
690c DC-690c
dc29 DC-290
10e2 Aptix Corporation
@@ -1877,6 +1929,7 @@
1025 8921 ALN-325
10bd 0320 EP-320X-R
10ec 8139 RT8139
+ 1186 1300 DFE-538TX
1186 1320 SN5200
1259 2500 AT-2500TX
1429 d010 ND010
@@ -1926,7 +1979,7 @@
9401 INI-950
9500 360P
1102 Creative Labs
- 0002 SB Live! EMU10000
+ 0002 SB Live! EMU10k1
1102 0020 CT4850 SBLive! Value
1102 0021 CT4620 SBLive!
1102 002f SBLive! mainboard implementation
@@ -1942,9 +1995,10 @@
1102 8051 CT4850 SBLive! Value
7002 SB Live!
1102 0020 Gameport Joystick
-1103 HighPoint Technologies, Inc.
- 0003 HPT343 UltraDMA 33 IDE Controller
- 0004 HPT366/370 UltraDMA 66/100 IDE Controller
+1103 Triones Technologies, Inc.
+ 0003 HPT343
+ 0004 HPT366 / HPT370
+ 1103 0005 HPT370 UDMA100
1104 RasterOps Corp.
1105 Sigma Designs, Inc.
8300 REALmagic Hollywood Plus DVD Decoder
@@ -1955,7 +2009,7 @@
0505 VT82C505
0561 VT82C561
0571 Bus Master IDE
- 0576 VT82C576 [Apollo Master]
+ 0576 VT82C576 3V [Apollo Master]
0585 VT82C585VP [Apollo VP1/VPX]
0586 VT82C586/A/B PCI-to-ISA [Apollo VP]
1106 0000 MVP3 ISA Bridge
@@ -1973,12 +2027,12 @@
1106 0686 VT82C686/A PCI to ISA Bridge
0691 VT82C693A/694x [Apollo PRO133x]
1458 0691 VT82C691 Apollo Pro System Controller
- 0698 VT82C693A [Apollo Pro133 AGP]
0693 VT82C693 [Apollo Pro Plus]
+ 0698 VT82C693A [Apollo Pro133 AGP]
0926 VT82C926 [Amazon]
1000 VT82C570MV
1106 VT82C570MV
- 1571 VT82C576 IDE [Apollo Master]
+ 1571 VT82C416MV
1595 VT82C595/97 [Apollo VP2/97]
3038 UHCI USB
1234 0925 MVP3 USB Controller
@@ -2012,8 +2066,8 @@
8598 VT82C598/694x [Apollo MVP3/Pro133x AGP]
8601 VT8601 [Apollo ProMedia AGP]
8605 VT8605 [PM133 AGP]
- B091 VT8633 [Apollo Pro266 AGP]
- B099 VT8367 [KT266 AGP]
+ b091 VT8633 [Apollo Pro266 AGP]
+ b099 VT8367 [KT266 AGP]
8691 VT82C691 [Apollo Pro]
1107 Stratus Computers
0576 VIA VT82C570MV [Apollo] (Wrong vendor ID!)
@@ -2073,7 +2127,7 @@
1118 Berg Electronics
1119 ICP Vortex Computersysteme GmbH
0000 GDT 6000/6020/6050
- 0001 GDT 6000b/6010
+ 0001 GDT 6000B/6010
0002 GDT 6110/6510
0003 GDT 6120/6520
0004 GDT 6530
@@ -2081,9 +2135,9 @@
0006 GDT 6x17
0007 GDT 6x27
0008 GDT 6537
- 0009 GDT 5557
- 000a GDT 6x15
- 000b GDT 6x25
+ 0009 GDT 6557
+ 000a GDT 6115/6515
+ 000b GDT 6125/6525
000c GDT 6535
000d GDT 6555
0100 GDT 6117RP/6517RP
@@ -2092,30 +2146,34 @@
0103 GDT 6557RP
0104 GDT 6111RP/6511RP
0105 GDT 6121RP/6521RP
- 0110 GDT 6117RP1/6517RP1
- 0111 GDT 6127RP1/6527RP1
- 0112 GDT 6537RP1
- 0113 GDT 6557RP1
- 0114 GDT 6111RP1/6511RP1
- 0115 GDT 6121RP1/6521RP1
- 0118 GDT 6x18RD
- 0119 GDT 6x28RD
- 011a GDT 6x38RD
- 011b GDT 6x58RD
- 0120 GDT 6117RP2/6517RP2
- 0121 GDT 6127RP2/6527RP2
- 0122 GDT 6537RP2
- 0123 GDT 6557RP2
- 0124 GDT 6111RP2/6511RP2
- 0125 GDT 6121RP2/6521RP2
- 0168 GDT 7x18RN
- 0169 GDT 7x28RN
- 016a GDT 7x38RN
- 016b GDT 7x58RN
- 0210 GDT 6x19RD
- 0211 GDT 6x29RD
- 0260 GDT 7x19RN
- 0261 GDT 7x29RN
+ 0110 GDT 6117RD/6517RD
+ 0111 GDT 6127RD/6527RD
+ 0112 GDT 6537RD
+ 0113 GDT 6557RD
+ 0114 GDT 6111RD/6511RD
+ 0115 GDT 6121RD/6521RD
+ 0118 GDT 6118RD/6518RD/6618RD
+ 0119 GDT 6128RD/6528RD/6628RD
+ 011a GDT 6538RD/6638RD
+ 011b GDT 6558RD/6658RD
+ 0138 GDT 6118RS/6518RS/6618RS
+ 0139 GDT 6128RS/6528RS/6628RS
+ 013a GDT 6538RS/6638RS
+ 013b GDT 6558RS/6658RS
+ 0166 GDT 7113RN/7513RN/7613RN
+ 0167 GDT 7123RN/7523RN/7623RN
+ 0168 GDT 7118RN/7518RN/7518RN
+ 0169 GDT 7128RN/7528RN/7628RN
+ 016a GDT 7538RN/7638RN
+ 016b GDT 7558RN/7658RN
+ 016c GDT 7533RN/7633RN
+ 016d GDT 7543RN/7643RN
+ 016e GDT 7553RN/7653RN
+ 016f GDT 7563RN/7663RN
+ 0210 GDT 6519RD/6619RD
+ 0211 GDT 6529RD/6629RD
+ 0260 GDT 7519RN/7619RN
+ 0261 GDT 7529RN/7629RN
111a Efficient Networks, Inc
0000 155P-MF1 (FPGA)
0002 155P-MF1 (ASIC)
@@ -2235,7 +2293,7 @@
1145 Workbit Corporation
1146 Force Computers
1147 Interface Corp
-1148 SysKonnect GmbH
+1148 Syskonnect (Schneider & Koch)
4000 FDDI Adapter
0e11 b03b Netelligent 100 FDDI DAS Fibre SC
0e11 b03c Netelligent 100 FDDI SAS Fibre SC
@@ -2252,7 +2310,7 @@
1148 5841 FDDI SK-5841 (SK-NET FDDI-FP64)
1148 5843 FDDI SK-5843 (SK-NET FDDI-LP64)
1148 5844 FDDI SK-5844 (SK-NET FDDI-LP64 DAS)
- 4200 Token Ring adapter
+ 4200 Token ring adaptor
4300 Gigabit Ethernet
1148 9821 SK-9821 (1000Base-T single link)
1148 9822 SK-9822 (1000Base-T dual link)
@@ -2429,6 +2487,7 @@
118b Hypertec Pty Limited
118c Corollary, Inc
0014 PCIB [C-bus II to PCI bus host bridge chip]
+ 1117 Intel 8-way XEON Profusion Chipset [Cache Coherency Filter]
118d BitFlow Inc
0001 Raptor-PCI framegrabber
0012 Model 12 Road Runner Frame Grabber
@@ -2478,7 +2537,7 @@
1221 82C092G
119c Information Technology Inst.
119d Bug, Inc. Sapporo Japan
-119e Fujitsu Microelectronics Europe GMBH
+119e Fujitsu Microelectronics Ltd.
0001 FireStream 155
0003 FireStream 50
119f Bull HN Information Systems
@@ -2692,6 +2751,7 @@
11f5 Computing Devices International
11f6 Compex
0112 ENet100VG4
+ 0113 FreedomLine 100
1401 ReadyLink 2000
2011 RL100-ATX 10/100
2201 ReadyLink 100TX (Winbond W89C840)
@@ -2803,7 +2863,8 @@
121a 0060 Voodoo3 3500 TV (NTSC)
121a 0061 Voodoo3 3500 TV (PAL)
121a 0062 Voodoo3 3500 TV (SECAM)
- 0009 Voodoo 4
+ 0009 Voodoo 4 / Voodoo 5
+ 121a 0009 Voodoo5 AGP 5500/6000
121b Advanced Telecommunications Modules
121c Nippon Texaco., Ltd
121d Lippert Automationstechnik GmbH
@@ -3029,13 +3090,13 @@
8086 5753 ES1371, ES1373 AudioPCI On Motherboard WS440BX
5000 ES1370 [AudioPCI]
4942 4c4c Creative Sound Blaster AudioPCI128
- 5880 CT5880 [AudioPCI]
+ 5880 5880 AudioPCI
1274 2000 Creative Sound Blaster AudioPCI128
1274 5880 Creative Sound Blaster AudioPCI128
- 1462 6880 CT5880 AudioPCI On Motherboard MS-6188 1.00
- 270f 2001 CT5880 AudioPCI On Motherboard 6CTR
- 270f 2200 CT5880 AudioPCI On Motherboard 6WTX
- 270f 7040 CT5880 AudioPCI On Motherboard 6ATA4
+ 1462 6880 5880 AudioPCI On Motherboard MS-6188 1.00
+ 270f 2001 5880 AudioPCI On Motherboard 6CTR
+ 270f 2200 5880 AudioPCI On Motherboard 6WTX
+ 270f 7040 5880 AudioPCI On Motherboard 6ATA4
1275 Network Appliance Corporation
1276 Switched Network Technologies, Inc.
1277 Comstream
@@ -3146,8 +3207,9 @@
12ac Measurex Corporation
12ad Multidata GmbH
12ae Alteon Networks Inc.
- 0001 AceNIC Gigabit Ethernet
+ 0001 AceNIC Gigabit Ethernet (Fibre)
1410 0104 Gigabit Ethernet-SX PCI Adapter (14100401)
+ 0002 AceNIC Gigabit Ethernet (Copper)
12af TDK USA Corp
12b0 Jorge Scientific Corp
12b1 GammaLink
@@ -3368,7 +3430,8 @@
1312 Acuity Imaging, Inc
1313 Yaskawa Electric Co.
1316 Teradyne Inc
-1317 Bridgecom, Inc
+1317 Linksys
+ 0985 Network Everywhere Fast Ethernet 10/100 model NC100
1318 Packet Engines Inc.
0911 PCI Ethernet Adapter
1319 Fortemedia, Inc
@@ -3528,6 +3591,7 @@
1384 Reality Simulation Systems Inc
1385 Netgear
620a GA620
+ f311 FA311
1386 Video Domain Technologies
1387 Systran Corp
1388 Hitachi Information Technology Co Ltd
@@ -3920,7 +3984,31 @@
14e2 INFOLIBRIA
14e3 AMTELCO
14e4 BROADCOM Corporation
- 1644 Tigon3
+ 1644 NetXtreme BCM5700 Gigabit Ethernet
+ 10b7 1000 3C996-T 1000BaseTX
+ 10b7 1001 3C996B-T 1000BaseTX
+ 10b7 1002 3C996C-T 1000BaseTX
+ 10b7 1003 3C997-T 1000BaseTX
+ 10b7 1004 3C996-SX 1000BaseSX
+ 10b7 1005 3C997-SX 1000BaseSX
+ 14e4 0002 NetXtreme 1000BaseSX
+ 14e4 0003 NetXtreme 1000BaseSX
+ 14e4 0004 NetXtreme 1000BaseTX
+ 14e4 1644 NetXtreme BCM5700 1000BaseTX
+ 1645 NetXtreme BCM5701 Gigabit Ethernet
+ 0e11 007d NC6770 1000BaseSX
+ 0e11 007c NC7770 1000BaseTX
+ 0e11 0085 NC7780 1000BaseTX
+ 10b7 1004 3C996-SX 1000BaseSX
+ 10b7 1006 3C996B-T 1000BaseTX
+ 10b7 1007 3C1000-T 1000BaseTX
+ 10b7 1008 3C940-BR01 1000BaseTX
+ 14e4 0001 NetXtreme BCM5701 1000BaseTX
+ 14e4 0005 NetXtreme BCM5701 1000BaseTX
+ 14e4 0006 NetXtreme BCM5701 1000BaseTX
+ 14e4 0007 NetXtreme BCM5701 1000BaseSX
+ 14e4 0008 NetXtreme BCM5701 1000BaseTX
+ 14e4 8008 NetXtreme BCM5701 1000BaseTX
14e5 Pixelfusion Ltd
14e6 SHINING Technology Inc
14e7 3CX
@@ -3955,6 +4043,8 @@
14f1 2015 SoftK56 Speakerphone Winmodem
2016 SoftK56 Speakerphone Winmodem
14f1 2016 SoftK56 Speakerphone Winmodem
+ 2443 SoftK56 Speakerphone Winmodem
+ 14f1 2443 SoftK56 Speakerphone Winmodem
14f2 MOBILITY Electronics
14f3 BROADLOGIC
14f4 TOKYO Electronic Industry CO Ltd
@@ -3979,7 +4069,7 @@
# 1507 HTEC Ltd
# Commented out because there are no known HTEC chips and 1507 is already
# used by mistake by Motorola (see vendor ID 1057)
-1507 Motorola ? / HTEC
+1507 Motorola ?? / HTEC
0001 MPC105 [Eagle]
0002 MPC106 [Grackle]
0003 MPC8240 [Kahlua]
@@ -4300,7 +4390,7 @@
270b Xantel Corporation
270f Chaintech Computer Co. Ltd
2711 AVID Technology Inc.
-2a15 3D Vision(?)
+2a15 3D Vision(???)
3000 Hansol Electronics Inc.
3142 Post Impression Systems.
3388 Hint Corp
@@ -4332,6 +4422,7 @@
3d3d 0125 Oxygen VX1
3d3d 0127 Permedia3 Create!
000a GLINT R3
+ 3d3d 0121 Oxygen VX1
0100 Permedia II 2D+3D
1004 Permedia
3d04 Permedia
@@ -4476,12 +4567,16 @@
5333 9125 86C394-397 Savage4 SGRAM 125
5333 9143 86C394-397 Savage4 SGRAM 143
8a23 Savage 4
+ 8a25 ProSavage PM133
+ 8a26 ProSavage KM133
8c00 ViRGE/M3
8c01 ViRGE/MX
8c02 ViRGE/MX+
8c03 ViRGE/MX+MV
- 8c10 86C270-294 Savage/MX-/IX
- 8c12 86C270-294 Savage/MX-/IX
+ 8c10 86C270-294 Savage/MX-MV
+ 8c11 82C270-294 Savage/MX
+ 8c12 86C270-294 Savage/IX-MV
+ 8c13 86C270-294 Savage/IX
9102 86C410 Savage 2000
1092 5932 Viper II Z200
1092 5934 Viper II Z200
@@ -4496,6 +4591,8 @@
5455 Technische University Berlin
4458 S5933
5519 Cnet Technologies, Inc.
+5544 Dunord Technologies
+ 0001 I-30xx Scanner Interface
5555 Genroco, Inc
0003 TURBOstor HFP-832 [HiPPI NIC]
5700 Netpower
@@ -4523,22 +4620,37 @@
04a3 82434LX [Mercury/Neptune]
04d0 82437FX [Triton FX]
0960 80960RP [i960 RP Microprocessor/Bridge]
- 1000 82542 Gigabit Ethernet Adapter
+ 0964 80960RP [i960 RP Microprocessor/Bridge]
+ 1000 82542 Gigabit Ethernet Controller
0e11 b0df NC1632 Gigabit Ethernet Adapter
0e11 b0e0 NC1633 Gigabit Ethernet Adapter
0e11 b123 NC1634 Gigabit Ethernet Adapter
1014 0119 Netfinity Gigabit Ethernet SX Adapter
- 8086 1000 EtherExpress PRO/1000 Gigabit Server Adapter
+ 1001 82543GC Gigabit Ethernet Controller
+ 1004 82543GC Gigabit Ethernet Controller
+ 1008 82544EI Gigabit Ethernet Controller
+ 100c 82544GC Gigabit Ethernet Controller
+ 100d 82544GC Gigabit Ethernet Controller
1030 82559 InBusiness 10/100
+ 1031 82801CAM (ICH3) Chipset Ethernet Controller
+ 1032 82801CAM (ICH3) Chipset Ethernet Controller
+ 1033 82801CAM (ICH3) Chipset Ethernet Controller
+ 1034 82801CAM (ICH3) Chipset Ethernet Controller
+ 1035 82801CAM (ICH3) Chipset Ethernet Controller
+ 1036 82801CAM (ICH3) Chipset Ethernet Controller
+ 1037 82801CAM (ICH3) Chipset Ethernet Controller
+ 1038 82801CAM (ICH3) Chipset Ethernet Controller
+ 1130 82815 815 Chipset Host Bridge and Memory Controller Hub
+ 1132 82815 CGC [Chipset Graphics Controller]
1161 82806AA PCI64 Hub Advanced Programmable Interrupt Controller
1209 82559ER
1221 82092AA_0
1222 82092AA_1
1223 SAA7116
1225 82452KX/GX [Orion]
- 1226 82596
- 1227 82865 [Ether Express Pro 100]
- 1228 82556 [Ether Express Pro 100 Smart]
+ 1226 82596 PRO/10 PCI
+ 1227 82865 EtherExpress PRO/100A
+ 1228 82556 EtherExpress PRO/100 Smart
1229 82557 [Ethernet Pro 100]
0e11 b01e NC3120
0e11 b01f NC3122
@@ -4550,6 +4662,7 @@
0e11 b0dd NC3131
0e11 b0de NC3132
0e11 b0e1 NC3133
+ 0e11 b144 NC3123 (82559)
1014 005c 82558B Ethernet Pro 10/100
1014 105c Netfinity 10/100
1033 8000 PC-9821X-B06
@@ -4604,6 +4717,9 @@
1960 80960RP [i960RP Microprocessor]
101e 0438 MegaRaid 438
101e 0466 MegaRaid 466
+ 101e 0467 MegaRaid 467
+ 1028 0467 PowerEdge Expandable RAID Controller 2/DC
+ 1028 1111 PowerEdge Expandable RAID Controller 2/SC
103c 10c6 MegaRaid 438
103c 10c7 MegaRaid T5
1111 1111 MegaRaid 466
@@ -4630,18 +4746,18 @@
11d4 0048 SoundMAX Integrated Digital Audio
2426 82801AB AC'97 Modem
2428 82801AB PCI Bridge
- 2440 82801BA ISA Bridge (ICH2)
- 2442 82801BA(M) USB (Hub A)
- 2443 82801BA(M) SMBus
- 2444 82801BA(M) USB (Hub B)
- 2445 82801BA(M) AC'97 Audio
- 2446 82801BA(M) AC'97 Modem
- 2448 82801BA PCI
- 2449 82801BA(M) Ethernet
- 244a 82801BAM IDE U100
- 244b 82801BA IDE U100
- 244c 82801BAM ISA Bridge (ICH2)
- 244e 82801BAM PCI
+ 2440 82820 820 (Camino 2) Chipset ISA Bridge (ICH2)
+ 2442 82820 820 (Camino 2) Chipset USB (Hub A)
+ 2443 82820 820 (Camino 2) Chipset SMBus
+ 2444 82820 820 (Camino 2) Chipset USB (Hub B)
+ 2445 82820 820 (Camino 2) Chipset AC'97 Audio Controller
+ 2446 82820 820 (Camino 2) Chipset AC'97 Modem Controller
+ 2448 82820 820 (Camino 2) Chipset PCI (-M)
+ 2449 82820 (ICH2) Chipset Ethernet Controller
+ 244a 82820 820 (Camino 2) Chipset IDE U100 (-M)
+ 244b 82820 820 (Camino 2) Chipset IDE U100
+ 244c 82820 820 (Camino 2) Chipset ISA Bridge (ICH2-M)
+ 244e 82820 820 (Camino 2) Chipset PCI
2500 82820 820 (Camino) Chipset Host Bridge (MCH)
1043 801c P3C-2000 system chipset
2501 82820 820 (Camino) Chipset Host Bridge (MCH)
@@ -4651,10 +4767,13 @@
2520 82805AA MTH Memory Translator Hub
2521 82804AA MRH-S Memory Repeater Hub for SDRAM
2530 82850 850 (Tehama) Chipset Host Bridge (MCH)
+ 2531 82850 860 (Wombat) Chipset Host Bridge (MCH)
2532 82850 850 (Tehama) Chipset AGP Bridge
- 5200 EtherExpress PRO/100
- 5201 EtherExpress PRO/100
+ 2533 82860 860 (Wombat) Chipset AGP Bridge
+ 5200 EtherExpress PRO/100 Intelligent Server
+ 5201 EtherExpress PRO/100 Intelligent Server
8086 0001 EtherExpress PRO/100 Server Ethernet Adapter
+ 530d 80310 IOP [IO Processor]
7000 82371SB PIIX3 ISA [Natoma/Triton II]
7010 82371SB PIIX3 IDE [Natoma/Triton II]
7020 82371SB PIIX3 USB [Natoma/Triton II]
@@ -4717,7 +4836,7 @@
9004 Adaptec
# FIXME: [dj] In one document I have, lot of these AIC's are actually AHA's
1078 AIC-7810
- 1160 AIC-1160 [Family Fiber Channel Adapter]
+ 1160 AIC-1160 [Family Fibre Channel Adapter]
2178 AIC-7821
3860 AHA-2930CU
3b78 AHA-4844W/4844UW
@@ -4834,6 +4953,7 @@
00c0 7899A
00c1 7899B
00c3 7899D
+ 00c5 RAID subsystem HBA
00cf 7899P
907f Atronics
2015 IDE-2015PL
@@ -5017,7 +5137,7 @@ C 0c Serial bus controller
10 OHCI
80 Unspecified
Fe USB Device
- 04 Fiber Channel
+ 04 Fibre Channel
05 SMBus
06 InfiniBand
C 0d Wireless controller
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 83368d4cc5f2..488e7d496f92 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -12,7 +12,7 @@
Copyright 1992 - 2001 Kai Makisara
email Kai.Makisara@metla.fi
- Last modified: Sun Aug 12 12:34:28 2001 by makisara@kai.makisara.local
+ Last modified: Wed Oct 3 22:17:59 2001 by makisara@kai.makisara.local
Some small formal changes - aeb, 950809
Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
@@ -21,7 +21,7 @@
error handling will be discarded.
*/
-static char *verstr = "20010812";
+static char *verstr = "20011003";
#include <linux/module.h>
@@ -89,6 +89,8 @@ MODULE_PARM_DESC(max_buffers, "Maximum number of buffer allocated at initialisat
MODULE_PARM(max_sg_segs, "i");
MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (32)");
+EXPORT_NO_SYMBOLS;
+
#ifndef MODULE
static struct st_dev_parm {
char *name;
@@ -669,6 +671,7 @@ static int st_open(struct inode *inode, struct file *filp)
if (STp->device->host->hostt->module)
__MOD_INC_USE_COUNT(STp->device->host->hostt->module);
+ STp->device->access_count++;
if (!scsi_block_when_processing_errors(STp->device)) {
retval = (-ENXIO);
@@ -909,6 +912,7 @@ static int st_open(struct inode *inode, struct file *filp)
STp->buffer = NULL;
}
STp->in_use = 0;
+ STp->device->access_count--;
if (STp->device->host->hostt->module)
__MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
return retval;
@@ -1066,6 +1070,7 @@ static int st_release(struct inode *inode, struct file *filp)
STp->in_use = 0;
write_unlock_irqrestore(&st_dev_arr_lock, flags);
+ STp->device->access_count--;
if (STp->device->host->hostt->module)
__MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
diff --git a/drivers/video/clgenfb.c b/drivers/video/clgenfb.c
index 6b220143dc90..b0235faa4e1e 100644
--- a/drivers/video/clgenfb.c
+++ b/drivers/video/clgenfb.c
@@ -31,7 +31,7 @@
*
*/
-#define CLGEN_VERSION "1.9.8"
+#define CLGEN_VERSION "1.9.9"
#include <linux/config.h>
#include <linux/module.h>
@@ -273,6 +273,7 @@ static const struct {
{ BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5434_8 },
{ BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5434_4 },
{ BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5430 }, /* GD-5440 has identical id */
+ { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_7543 },
{ BT_GD5480, NULL, PCI_DEVICE_ID_CIRRUS_5480 }, /* MacPicasso probably */
{ BT_PICASSO4, NULL, PCI_DEVICE_ID_CIRRUS_5446 }, /* Picasso 4 is a GD5446 */
{ BT_LAGUNA, "CL Laguna", PCI_DEVICE_ID_CIRRUS_5462 },
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index a3ca017d6c23..52ca30f5a42a 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -51,6 +51,7 @@
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/pgtable.h>
+#include <asm/btext.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
@@ -757,6 +758,12 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro
console_fb_info = &p->info;
}
#endif /* CONFIG_FB_COMPAT_XPMAC */
+#ifdef CONFIG_BOOTX_TEXT
+ btext_update_display(p->frame_buffer_phys + CTRLFB_OFF,
+ p->par.xres, p->par.yres,
+ (cmode == CMODE_32? 32: cmode == CMODE_16? 16: 8),
+ p->par.pitch);
+#endif /* CONFIG_BOOTX_TEXT */
}
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 4aa1d3f6b36c..80621868bd1c 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -32,7 +32,9 @@
#endif
#include <asm/io.h>
#include <asm/prom.h>
+#ifdef CONFIG_BOOTX_TEXT
#include <asm/bootx.h>
+#endif
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
@@ -95,8 +97,9 @@ static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info);
static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info);
-
+#ifdef CONFIG_BOOTX_TEXT
extern boot_infos_t *boot_infos;
+#endif
static void offb_init_nodriver(struct device_node *);
static void offb_init_fb(const char *name, const char *full_name, int width,
@@ -253,6 +256,7 @@ int __init offb_init(void)
{
struct device_node *dp;
unsigned int dpy;
+#ifdef CONFIG_BOOTX_TEXT
struct device_node *displays = find_type_devices("display");
struct device_node *macos_display = NULL;
@@ -315,6 +319,7 @@ int __init offb_init(void)
boot_infos->dispDeviceDepth,
boot_infos->dispDeviceRowBytes, addr, NULL);
}
+#endif
for (dpy = 0; dpy < prom_num_displays; dpy++) {
if ((dp = find_path_device(prom_display_paths[dpy])))
@@ -426,7 +431,8 @@ static void __init offb_init_fb(const char *name, const char *full_name,
unsigned long regbase = dp->addrs[2].address;
info->cmap_adr = ioremap(regbase, 0x1FFF);
info->cmap_type = cmap_r128;
- } else if (dp && !strncmp(name, "ATY,RageM3pA", 12)) {
+ } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
+ || !strncmp(name, "ATY,RageM3p12A", 14))) {
unsigned long regbase = dp->parent->addrs[2].address;
info->cmap_adr = ioremap(regbase, 0x1FFF);
info->cmap_type = cmap_M3A;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 76b6c22490d7..ee93f1f75d83 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -76,6 +76,8 @@ static struct linux_binfmt elf_format = {
NULL, THIS_MODULE, load_elf_binary, load_elf_library, elf_core_dump, ELF_EXEC_PAGESIZE
};
+#define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE)
+
static void set_brk(unsigned long start, unsigned long end)
{
start = ELF_PAGEALIGN(start);
@@ -298,6 +300,8 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
elf_type |= MAP_FIXED;
map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type);
+ if (BAD_ADDR(map_addr))
+ goto out_close;
if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
load_addr = map_addr - ELF_PAGESTART(vaddr);
@@ -649,6 +653,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
}
error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
+ if (BAD_ADDR(error))
+ continue;
if (!load_addr_set) {
load_addr_set = 1;
@@ -697,7 +703,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
fput(interpreter);
kfree(elf_interpreter);
- if (elf_entry == ~0UL) {
+ if (BAD_ADDR(elf_entry)) {
printk(KERN_ERR "Unable to load interpreter\n");
kfree(elf_phdata);
send_sig(SIGSEGV, current, 0);
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 8ce2918bf78d..2df9d2a00686 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -549,36 +549,23 @@ int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
return res;
}
-int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
+static int do_open(struct block_device *bdev, struct inode *inode, struct file *file)
{
- int ret = -ENODEV;
- kdev_t rdev = to_kdev_t(bdev->bd_dev); /* this should become bdev */
- down(&bdev->bd_sem);
+ int ret = -ENXIO;
+ kdev_t dev = to_kdev_t(bdev->bd_dev);
+ down(&bdev->bd_sem);
lock_kernel();
if (!bdev->bd_op)
- bdev->bd_op = get_blkfops(MAJOR(rdev));
+ bdev->bd_op = get_blkfops(MAJOR(dev));
if (bdev->bd_op) {
- /*
- * This crockload is due to bad choice of ->open() type.
- * It will go away.
- * For now, block device ->open() routine must _not_
- * examine anything in 'inode' argument except ->i_rdev.
- */
- struct file fake_file = {};
- struct dentry fake_dentry = {};
- ret = -ENOMEM;
- fake_file.f_mode = mode;
- fake_file.f_flags = flags;
- fake_file.f_dentry = &fake_dentry;
- fake_dentry.d_inode = bdev->bd_inode;
ret = 0;
if (bdev->bd_op->open)
- ret = bdev->bd_op->open(bdev->bd_inode, &fake_file);
+ ret = bdev->bd_op->open(inode, file);
if (!ret) {
bdev->bd_openers++;
- bdev->bd_inode->i_size = blkdev_size(rdev);
- bdev->bd_inode->i_blkbits = blksize_bits(block_size(rdev));
+ bdev->bd_inode->i_size = blkdev_size(dev);
+ bdev->bd_inode->i_blkbits = blksize_bits(block_size(dev));
} else if (!bdev->bd_openers)
bdev->bd_op = NULL;
}
@@ -589,9 +576,26 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
return ret;
}
+int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
+{
+ /*
+ * This crockload is due to bad choice of ->open() type.
+ * It will go away.
+ * For now, block device ->open() routine must _not_
+ * examine anything in 'inode' argument except ->i_rdev.
+ */
+ struct file fake_file = {};
+ struct dentry fake_dentry = {};
+ fake_file.f_mode = mode;
+ fake_file.f_flags = flags;
+ fake_file.f_dentry = &fake_dentry;
+ fake_dentry.d_inode = bdev->bd_inode;
+
+ return do_open(bdev, bdev->bd_inode, &fake_file);
+}
+
int blkdev_open(struct inode * inode, struct file * filp)
{
- int ret;
struct block_device *bdev;
/*
@@ -604,29 +608,8 @@ int blkdev_open(struct inode * inode, struct file * filp)
bd_acquire(inode);
bdev = inode->i_bdev;
- down(&bdev->bd_sem);
- ret = -ENXIO;
- lock_kernel();
- if (!bdev->bd_op)
- bdev->bd_op = get_blkfops(MAJOR(inode->i_rdev));
-
- if (bdev->bd_op) {
- ret = 0;
- if (bdev->bd_op->open)
- ret = bdev->bd_op->open(inode,filp);
- if (!ret) {
- bdev->bd_openers++;
- bdev->bd_inode->i_size = blkdev_size(inode->i_rdev);
- } else if (!bdev->bd_openers)
- bdev->bd_op = NULL;
- }
-
- unlock_kernel();
- up(&bdev->bd_sem);
- if (ret)
- bdput(bdev);
- return ret;
+ return do_open(bdev, inode, filp);
}
int blkdev_put(struct block_device *bdev, int kind)
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index d3339912a25d..7b2eaba253e6 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -15,6 +15,7 @@
#define __KERNEL_SYSCALLS__
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/init.h>
#include <linux/sched.h>
#include <linux/errno.h>
@@ -55,6 +56,7 @@ static DECLARE_WAIT_QUEUE_HEAD(lockd_exit);
*/
unsigned long nlm_grace_period;
unsigned long nlm_timeout = LOCKD_DFLT_TIMEO;
+unsigned long nlm_udpport, nlm_tcpport;
static unsigned long set_grace_period(void)
{
@@ -241,9 +243,9 @@ lockd_up(void)
goto out;
}
- if ((error = svc_makesock(serv, IPPROTO_UDP, 0)) < 0
+ if ((error = svc_makesock(serv, IPPROTO_UDP, nlm_udpport)) < 0
#ifdef CONFIG_NFSD_TCP
- || (error = svc_makesock(serv, IPPROTO_TCP, 0)) < 0
+ || (error = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport)) < 0
#endif
) {
if (warned++ == 0)
@@ -323,6 +325,8 @@ MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
MODULE_PARM(nlm_grace_period, "10-240l");
MODULE_PARM(nlm_timeout, "3-20l");
+MODULE_PARM(nlm_udpport, "0-65535l");
+MODULE_PARM(nlm_tcpport, "0-65535l");
int
init_module(void)
@@ -340,6 +344,24 @@ cleanup_module(void)
/* FIXME: delete all NLM clients */
nlm_shutdown_hosts();
}
+#else
+/* not a module, so process bootargs
+ * lockd.udpport and lockd.tcpport
+ */
+
+static int __init udpport_set(char *str)
+{
+ nlm_udpport = simple_strtoul(str, NULL, 0);
+ return 1;
+}
+static int __init tcpport_set(char *str)
+{
+ nlm_tcpport = simple_strtoul(str, NULL, 0);
+ return 1;
+}
+__setup("lockd.udpport=", udpport_set);
+__setup("lockd.tcpport=", tcpport_set);
+
#endif
/*
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 46340e88f1c8..537b685ce576 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -550,15 +550,15 @@ struct flags {
{ NFSEXP_INSECURE_PORT, {"insecure", ""}},
{ NFSEXP_ROOTSQUASH, {"root_squash", "no_root_squash"}},
{ NFSEXP_ALLSQUASH, {"all_squash", ""}},
- { NFSEXP_ASYNC, {"async", ""}},
- { NFSEXP_GATHERED_WRITES, {"wdelay", ""}},
+ { NFSEXP_ASYNC, {"async", "sync"}},
+ { NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}},
{ NFSEXP_UIDMAP, {"uidmap", ""}},
{ NFSEXP_KERBEROS, { "kerberos", ""}},
{ NFSEXP_SUNSECURE, { "sunsecure", ""}},
{ NFSEXP_CROSSMNT, {"nohide", ""}},
{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
-#ifdef NSMFS
+#ifdef MSNFS
{ NFSEXP_MSNFS, {"msnfs", ""}},
#endif
{ 0, {"", ""}}
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index aa35c9aae007..e3b037803b0e 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -99,7 +99,7 @@ decode_pathname(u32 *p, char **namp, int *lenp)
char *name;
int i;
- if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS3_MAXPATHLEN)) != NULL) {
+ if ((p = xdr_decode_string(p, namp, lenp, NFS3_MAXPATHLEN)) != NULL) {
for (i = 0, name = *namp; i < *lenp; i++, name++) {
if (*name == '\0')
return NULL;
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index bc7315c87c05..417b4173c477 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -731,8 +731,10 @@ inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
{
struct super_block *sb = dentry->d_inode->i_sb;
- if (dentry == exp->ex_dentry)
+ if (dentry == exp->ex_dentry) {
+ *maxsize = 0;
return 0;
+ }
if (sb->s_op->dentry_to_fh) {
int need_parent = !S_ISDIR(dentry->d_inode->i_mode) &&
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 25d8ddf63af6..debae923e8f2 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -65,7 +65,7 @@ decode_filename(u32 *p, char **namp, int *lenp)
char *name;
int i;
- if ((p = xdr_decode_string(p, namp, lenp, NFS_MAXNAMLEN)) != NULL) {
+ if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXNAMLEN)) != NULL) {
for (i = 0, name = *namp; i < *lenp; i++, name++) {
if (*name == '\0' || *name == '/')
return NULL;
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 2aaa9149758a..015ef90095e0 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -227,7 +227,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
#define MAX_TOUCH_TIME_ERROR (30*60)
if (err
&& (iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET
- && iap->ia_mtime == iap->ia_ctime
+ && iap->ia_mtime == iap->ia_atime
) {
/* looks good. now just make sure time is in the right ballpark.
* solaris, at least, doesn't seem to care what the time request is
diff --git a/fs/partitions/acorn.c b/fs/partitions/acorn.c
index d0afb47eec09..e87f0a717314 100644
--- a/fs/partitions/acorn.c
+++ b/fs/partitions/acorn.c
@@ -22,15 +22,16 @@
#include "acorn.h"
static void
-adfspart_setgeometry(kdev_t dev, unsigned int secspertrack, unsigned int heads,
- unsigned long totalblocks)
+adfspart_setgeometry(kdev_t dev, unsigned int secspertrack, unsigned int heads)
{
+#ifdef CONFIG_BLK_DEV_MFM
extern void xd_set_geometry(kdev_t dev, unsigned char, unsigned char,
unsigned long, unsigned int);
-#ifdef CONFIG_BLK_DEV_MFM
- if (MAJOR(dev) == MFM_ACORN_MAJOR)
+ if (MAJOR(dev) == MFM_ACORN_MAJOR) {
+ unsigned long totalblocks = hd->part[MINOR(dev)].nr_sects;
xd_set_geometry(dev, secspertrack, heads, totalblocks, 1);
+ }
#endif
}
@@ -60,32 +61,26 @@ adfs_partition(struct gendisk *hd, char *name, char *data,
#ifdef CONFIG_ACORN_PARTITION_RISCIX
static int
-riscix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sect,
- int minor, unsigned long nr_sects)
+riscix_partition(struct gendisk *hd, struct block_device *bdev,
+ unsigned long first_sect, int minor, unsigned long nr_sects)
{
- struct buffer_head *bh;
+ Sector sect;
struct riscix_record *rr;
- unsigned int riscix_minor;
- if(get_ptable_blocksize(dev)!=1024)
- return 0;
+ rr = (struct riscix_record *)read_dev_sector(bdev, first_sect, &sect);
+ if (!rr)
+ return -1;
printk(" [RISCiX]");
- add_gd_partition(hd, riscix_minor = minor++, first_sect, nr_sects);
- hd->sizes[riscix_minor] = hd->part[riscix_minor].nr_sects >>
- (BLOCK_SIZE_BITS - 9);
- dev = MKDEV(hd->major, riscix_minor);
-
- if (!(bh = bread(dev, 0, 1024)))
- return -1;
- rr = (struct riscix_record *)bh->b_data;
if (rr->magic == RISCIX_MAGIC) {
+ unsigned long size = nr_sects > 2 ? 2 : nr_sects;
int part;
printk(" <");
+ add_gd_partition(hd, minor++, first_sect, size);
for (part = 0; part < 8; part++) {
if (rr->part[part].one &&
memcmp(rr->part[part].name, "All\0", 4)) {
@@ -97,38 +92,32 @@ riscix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sect,
}
printk(" >\n");
-
- if (hd->part[riscix_minor].nr_sects > 2)
- hd->part[riscix_minor].nr_sects = 2;
+ } else {
+ add_gd_partition(hd, minor++, first_sect, nr_sects);
}
- brelse(bh);
+ put_dev_sector(sect);
return minor;
}
#endif
static int
-linux_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sect,
- int minor, unsigned long nr_sects)
+linux_partition(struct gendisk *hd, struct block_device *bdev,
+ unsigned long first_sect, int minor, unsigned long nr_sects)
{
- struct buffer_head *bh;
+ Sector sect;
struct linux_part *linuxp;
- unsigned int linux_minor, mask = (1 << hd->minor_shift) - 1;
+ unsigned int mask = (1 << hd->minor_shift) - 1;
+ unsigned long size = nr_sects > 2 ? 2 : nr_sects;
- if(get_ptable_blocksize(dev)!=1024)
- return 0;
-
printk(" [Linux]");
- add_gd_partition(hd, linux_minor = minor++, first_sect, nr_sects);
- hd->sizes[linux_minor] = hd->part[linux_minor].nr_sects >>
- (BLOCK_SIZE_BITS - 9);
- dev = MKDEV(hd->major, linux_minor);
+ add_gd_partition(hd, minor++, first_sect, size);
- if (!(bh = bread(dev, 0, 1024)))
+ linuxp = (struct linux_part *)read_dev_sector(bdev, first_sect, &sect);
+ if (!linuxp)
return -1;
- linuxp = (struct linux_part *)bh->b_data;
printk(" <");
while (linuxp->magic == cpu_to_le32(LINUX_NATIVE_MAGIC) ||
linuxp->magic == cpu_to_le32(LINUX_SWAP_MAGIC)) {
@@ -140,29 +129,22 @@ linux_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sect,
linuxp ++;
}
printk(" >");
- /*
- * Prevent someone doing a mkswap or mkfs on this partition
- */
- if(hd->part[linux_minor].nr_sects > 2)
- hd->part[linux_minor].nr_sects = 2;
- brelse(bh);
+ put_dev_sector(sect);
return minor;
}
#ifdef CONFIG_ACORN_PARTITION_CUMANA
static int
-adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev,
+adfspart_check_CUMANA(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int minor)
{
unsigned int start_blk = 0, mask = (1 << hd->minor_shift) - 1;
- struct buffer_head *bh = NULL;
+ Sector sect;
+ unsigned char *data;
char *name = "CUMANA/ADFS";
int first = 1;
- if(get_ptable_blocksize(dev)!=1024)
- return 0;
-
/*
* Try Cumana style partitions - sector 3 contains ADFS boot block
* with pointer to next 'drive'.
@@ -183,16 +165,17 @@ adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev,
if (!(minor & mask))
break;
- if (!(bh = bread(dev, start_blk + 3, 1024)))
+ data = read_dev_sector(bdev, start_blk * 2 + 6, &sect);
+ if (!data)
return -1;
- dr = adfs_partition(hd, name, bh->b_data,
- first_sector, minor++);
+ dr = adfs_partition(hd, name, data, first_sector, minor++);
if (!dr)
break;
+
name = NULL;
- nr_sects = (bh->b_data[0x1fd] + (bh->b_data[0x1fe] << 8)) *
+ nr_sects = (data[0x1fd] + (data[0x1fe] << 8)) *
(dr->heads + (dr->lowsector & 0x40 ? 1 : 0)) *
dr->secspertrack;
@@ -204,30 +187,28 @@ adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev,
start_blk += nr_sects >> (BLOCK_SIZE_BITS - 9);
nr_sects = 0; /* hmm - should be partition size */
- switch (bh->b_data[0x1fc] & 15) {
+ switch (data[0x1fc] & 15) {
case 0: /* No partition / ADFS? */
break;
#ifdef CONFIG_ACORN_PARTITION_RISCIX
case PARTITION_RISCIX_SCSI:
/* RISCiX - we don't know how to find the next one. */
- minor = riscix_partition(hd, dev, first_sector,
+ minor = riscix_partition(hd, bdev, first_sector,
minor, nr_sects);
break;
#endif
case PARTITION_LINUX:
- minor = linux_partition(hd, dev, first_sector,
+ minor = linux_partition(hd, bdev, first_sector,
minor, nr_sects);
break;
}
- brelse(bh);
- bh = NULL;
+ put_dev_sector(sect);
if (minor == -1)
return minor;
} while (1);
- if (bh)
- bforget(bh);
+ put_dev_sector(sect);
return first ? 0 : 1;
}
#endif
@@ -248,73 +229,73 @@ adfspart_check_CUMANA(struct gendisk *hd, kdev_t dev,
* hda2 = non-ADFS partition.
*/
static int
-adfspart_check_ADFS(struct gendisk *hd, kdev_t dev,
+adfspart_check_ADFS(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int minor)
{
unsigned long start_sect, nr_sects, sectscyl, heads;
- struct buffer_head *bh;
+ Sector sect;
+ unsigned char *data;
struct adfs_discrecord *dr;
+ unsigned char id;
- if(get_ptable_blocksize(dev)!=1024)
- return 0;
-
- if (!(bh = bread(dev, 3, 1024)))
+ data = read_dev_sector(bdev, 6, &sect);
+ if (!data)
return -1;
- dr = adfs_partition(hd, "ADFS", bh->b_data, first_sector, minor++);
+ dr = adfs_partition(hd, "ADFS", data, first_sector, minor++);
if (!dr) {
- bforget(bh);
+ put_dev_sector(sect);
return 0;
}
heads = dr->heads + ((dr->lowsector >> 6) & 1);
- adfspart_setgeometry(dev, dr->secspertrack, heads,
- hd->part[MINOR(dev)].nr_sects);
sectscyl = dr->secspertrack * heads;
+ start_sect = ((data[0x1fe] << 8) + data[0x1fd]) * sectscyl;
+ id = data[0x1fc] & 15;
+ put_dev_sector(sect);
+
+ adfspart_setgeometry(to_kdev_t(bdev->bd_dev), dr->secspertrack, heads);
+ invalidate_bdev(bdev, 1);
+ truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
/*
* Work out start of non-adfs partition.
*/
- start_sect = ((bh->b_data[0x1fe] << 8) + bh->b_data[0x1fd]) * sectscyl;
- nr_sects = hd->part[MINOR(dev)].nr_sects - start_sect;
+ nr_sects = hd->part[MINOR(to_kdev_t(bdev->bd_dev))].nr_sects - start_sect;
if (start_sect) {
first_sector += start_sect;
- switch (bh->b_data[0x1fc] & 15) {
+ switch (id) {
#ifdef CONFIG_ACORN_PARTITION_RISCIX
case PARTITION_RISCIX_SCSI:
case PARTITION_RISCIX_MFM:
- minor = riscix_partition(hd, dev, first_sector,
+ minor = riscix_partition(hd, bdev, first_sector,
minor, nr_sects);
break;
#endif
case PARTITION_LINUX:
- minor = linux_partition(hd, dev, first_sector,
+ minor = linux_partition(hd, bdev, first_sector,
minor, nr_sects);
break;
}
}
- brelse(bh);
return 1;
}
#endif
#ifdef CONFIG_ACORN_PARTITION_ICS
-static int adfspart_check_ICSLinux(kdev_t dev, unsigned long block)
+static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long block)
{
- struct buffer_head *bh;
- unsigned int offset = block & 1 ? 512 : 0;
+ Sector sect;
+ unsigned char *data = read_dev_sector(bdev, block, &sect);
int result = 0;
- bh = bread(dev, block >> 1, 1024);
-
- if (bh != NULL) {
- if (memcmp(bh->b_data + offset, "LinuxPart", 9) == 0)
+ if (data) {
+ if (memcmp(data, "LinuxPart", 9) == 0)
result = 1;
-
- brelse(bh);
+ put_dev_sector(sect);
}
return result;
@@ -333,38 +314,37 @@ static int adfspart_check_ICSLinux(kdev_t dev, unsigned long block)
* ..etc..
*/
static int
-adfspart_check_ICS(struct gendisk *hd, kdev_t dev,
+adfspart_check_ICS(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int minor)
{
- struct buffer_head *bh;
+ Sector sect;
+ unsigned char *data;
unsigned long sum;
unsigned int i, mask = (1 << hd->minor_shift) - 1;
struct ics_part *p;
- if(get_ptable_blocksize(dev)!=1024)
- return 0;
-
/*
* Try ICS style partitions - sector 0 contains partition info.
*/
- if (!(bh = bread(dev, 0, 1024)))
+ data = read_dev_sector(bdev, 0, &sect);
+ if (!data)
return -1;
/*
* check for a valid checksum
*/
for (i = 0, sum = 0x50617274; i < 508; i++)
- sum += bh->b_data[i];
+ sum += data[i];
- sum -= le32_to_cpu(*(__u32 *)(&bh->b_data[508]));
+ sum -= le32_to_cpu(*(__u32 *)(&data[508]));
if (sum) {
- bforget(bh);
+ put_dev_sector(sect);
return 0; /* not ICS partition table */
}
printk(" [ICS]");
- for (p = (struct ics_part *)bh->b_data; p->size; p++) {
+ for (p = (struct ics_part *)data; p->size; p++) {
unsigned long start;
long size;
@@ -381,7 +361,7 @@ adfspart_check_ICS(struct gendisk *hd, kdev_t dev,
* We use the first sector to identify what type
* this partition is...
*/
- if (size > 1 && adfspart_check_ICSLinux(dev, start)) {
+ if (size > 1 && adfspart_check_ICSLinux(bdev, start)) {
start += 1;
size -= 1;
}
@@ -393,12 +373,11 @@ adfspart_check_ICS(struct gendisk *hd, kdev_t dev,
}
}
- brelse(bh);
+ put_dev_sector(sect);
return 1;
}
#endif
-#ifdef CONFIG_ACORN_PARTITION_POWERTEC
/*
* Purpose: allocate ICS partitions.
* Params : hd - pointer to gendisk structure to store partition info.
@@ -411,29 +390,32 @@ adfspart_check_ICS(struct gendisk *hd, kdev_t dev,
* hda2 = ADFS partition 1 on first drive.
* ..etc..
*/
+#ifdef CONFIG_ACORN_PARTITION_POWERTEC
static int
-adfspart_check_POWERTEC(struct gendisk *hd, kdev_t dev,
+adfspart_check_POWERTEC(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int minor)
{
- struct buffer_head *bh;
+ Sector sect;
+ unsigned char *data;
struct ptec_partition *p;
unsigned char checksum;
int i;
- if (!(bh = bread(dev, 0, 1024)))
+ data = read_dev_sector(bdev, 0, &sect);
+ if (!data)
return -1;
for (checksum = 0x2a, i = 0; i < 511; i++)
- checksum += bh->b_data[i];
+ checksum += data[i];
- if (checksum != bh->b_data[511]) {
- bforget(bh);
+ if (checksum != data[511]) {
+ put_dev_sector(sect);
return 0;
}
printk(" [POWERTEC]");
- for (i = 0, p = (struct ptec_partition *)bh->b_data; i < 12; i++, p++) {
+ for (i = 0, p = (struct ptec_partition *)data; i < 12; i++, p++) {
unsigned long start;
unsigned long size;
@@ -446,24 +428,24 @@ adfspart_check_POWERTEC(struct gendisk *hd, kdev_t dev,
minor++;
}
- brelse(bh);
+ put_dev_sector(sect);
return 1;
}
#endif
-static int (*partfn[])(struct gendisk *, kdev_t, unsigned long, int) = {
+static int (*partfn[])(struct gendisk *, struct block_device *, unsigned long, int) = {
#ifdef CONFIG_ACORN_PARTITION_ICS
adfspart_check_ICS,
#endif
+#ifdef CONFIG_ACORN_PARTITION_POWERTEC
+ adfspart_check_POWERTEC,
+#endif
#ifdef CONFIG_ACORN_PARTITION_CUMANA
adfspart_check_CUMANA,
#endif
#ifdef CONFIG_ACORN_PARTITION_ADFS
adfspart_check_ADFS,
#endif
-#ifdef CONFIG_ACORN_PARTITION_POWERTEC
- adfspart_check_POWERTEC,
-#endif
NULL
};
/*
@@ -478,17 +460,18 @@ static int (*partfn[])(struct gendisk *, kdev_t, unsigned long, int) = {
*
* Returns: -1 on error, 0 if not ADFS format, 1 if ok.
*/
-int acorn_partition(struct gendisk *hd, kdev_t dev,
+int acorn_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sect, int first_minor)
{
- int r = 0, i;
-
- for (i = 0; partfn[i] && r == 0; i++)
- r = partfn[i](hd, dev, first_sect, first_minor);
+ int i;
- if (r < 0 && warn_no_part)
- printk(" unable to read boot sectors / partition sectors\n");
- if (r > 0)
- printk("\n");
- return r;
+ for (i = 0; partfn[i]; i++) {
+ int r = partfn[i](hd, bdev, first_sect, first_minor);
+ if (r) {
+ if (r > 0)
+ printk("\n");
+ return r;
+ }
+ }
+ return 0;
}
diff --git a/fs/partitions/acorn.h b/fs/partitions/acorn.h
index e1d0a3830e8b..f4b3b80d383c 100644
--- a/fs/partitions/acorn.h
+++ b/fs/partitions/acorn.h
@@ -50,6 +50,6 @@ struct ptec_partition {
};
-int acorn_partition(struct gendisk *hd, kdev_t dev,
+int acorn_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sect, int first_minor);
diff --git a/fs/partitions/amiga.c b/fs/partitions/amiga.c
index 4717a1b5f0a0..3ecf9c4f88b4 100644
--- a/fs/partitions/amiga.c
+++ b/fs/partitions/amiga.c
@@ -31,90 +31,82 @@ checksum_block(u32 *m, int size)
}
int
-amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
+amiga_partition(struct gendisk *hd, struct block_device *bdev,
+ unsigned long first_sector, int first_part_minor)
{
- struct buffer_head *bh;
- struct RigidDiskBlock *rdb;
- struct PartitionBlock *pb;
- int start_sect;
- int nr_sects;
- int blk;
- int part, res;
- int old_blocksize;
- int blocksize;
+ Sector sect;
+ unsigned char *data;
+ struct RigidDiskBlock *rdb;
+ struct PartitionBlock *pb;
+ int start_sect, nr_sects, blk, part, res = 0;
+ kdev_t dev = to_kdev_t(bdev->bd_dev);
- old_blocksize = get_ptable_blocksize(dev);
- blocksize = get_hardsect_size(dev);
+ for (blk = 0; ; blk++, put_dev_sector(sect)) {
+ if (blk == RDB_ALLOCATION_LIMIT)
+ goto rdb_done;
+ data = read_dev_sector(bdev, blk, &sect);
+ if (!data) {
+ if (warn_no_part)
+ printk("Dev %s: unable to read RDB block %d\n",
+ bdevname(dev), blk);
+ goto rdb_done;
+ }
+ if (*(u32 *)data != cpu_to_be32(IDNAME_RIGIDDISK))
+ continue;
- if (blocksize < 512)
- blocksize = 512;
+ rdb = (struct RigidDiskBlock *)data;
+ if (checksum_block((u32 *)data, be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F) == 0)
+ break;
+ /* Try again with 0xdc..0xdf zeroed, Windows might have
+ * trashed it.
+ */
+ *(u32 *)(data+0xdc) = 0;
+ if (checksum_block((u32 *)data,
+ be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)==0) {
+ printk("Warning: Trashed word at 0xd0 in block %d "
+ "ignored in checksum calculation\n",blk);
+ break;
+ }
- set_blocksize(dev,blocksize);
- res = 0;
+ printk("Dev %s: RDB in block %d has bad checksum\n",
+ bdevname(dev),blk);
+ }
- for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
- if(!(bh = bread(dev,blk,blocksize))) {
- if (warn_no_part) printk("Dev %s: unable to read RDB block %d\n",
- kdevname(dev),blk);
+ printk(" RDSK");
+ blk = be32_to_cpu(rdb->rdb_PartitionList);
+ put_dev_sector(sect);
+ for (part = 1; blk>0 && part<=16; part++, put_dev_sector(sect)) {
+ data = read_dev_sector(bdev, blk, &sect);
+ if (!data) {
+ if (warn_no_part)
+ printk("Dev %s: unable to read partition block %d\n",
+ bdevname(dev),blk);
goto rdb_done;
}
- if (*(u32 *)bh->b_data == cpu_to_be32(IDNAME_RIGIDDISK)) {
- rdb = (struct RigidDiskBlock *)bh->b_data;
- if (checksum_block((u32 *)bh->b_data,be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)) {
- /* Try again with 0xdc..0xdf zeroed, Windows might have
- * trashed it.
- */
- *(u32 *)(&bh->b_data[0xdc]) = 0;
- if (checksum_block((u32 *)bh->b_data,
- be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)) {
- brelse(bh);
- printk("Dev %s: RDB in block %d has bad checksum\n",
- kdevname(dev),blk);
- continue;
- }
- printk("Warning: Trashed word at 0xd0 in block %d "
- "ignored in checksum calculation\n",blk);
- }
- printk(" RDSK");
- blk = be32_to_cpu(rdb->rdb_PartitionList);
- brelse(bh);
- for (part = 1; blk > 0 && part <= 16; part++) {
- if (!(bh = bread(dev,blk,blocksize))) {
- if (warn_no_part) printk("Dev %s: unable to read partition block %d\n",
- kdevname(dev),blk);
- goto rdb_done;
- }
- pb = (struct PartitionBlock *)bh->b_data;
- blk = be32_to_cpu(pb->pb_Next);
- if (pb->pb_ID == cpu_to_be32(IDNAME_PARTITION) && checksum_block(
- (u32 *)pb,be32_to_cpu(pb->pb_SummedLongs) & 0x7F) == 0 ) {
+ pb = (struct PartitionBlock *)data;
+ blk = be32_to_cpu(pb->pb_Next);
+ if (pb->pb_ID != cpu_to_be32(IDNAME_PARTITION))
+ continue;
+ if (checksum_block((u32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 )
+ continue;
- /* Tell Kernel about it */
+ /* Tell Kernel about it */
- if (!(nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
- be32_to_cpu(pb->pb_Environment[9])) *
- be32_to_cpu(pb->pb_Environment[3]) *
- be32_to_cpu(pb->pb_Environment[5]))) {
- brelse(bh);
- continue;
- }
- start_sect = be32_to_cpu(pb->pb_Environment[9]) *
- be32_to_cpu(pb->pb_Environment[3]) *
- be32_to_cpu(pb->pb_Environment[5]);
- add_gd_partition(hd,first_part_minor,start_sect,nr_sects);
- first_part_minor++;
- res = 1;
- }
- brelse(bh);
- }
- printk("\n");
- break;
- }
- else
- brelse(bh);
+ nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
+ be32_to_cpu(pb->pb_Environment[9])) *
+ be32_to_cpu(pb->pb_Environment[3]) *
+ be32_to_cpu(pb->pb_Environment[5]);
+ if (!nr_sects)
+ continue;
+ start_sect = be32_to_cpu(pb->pb_Environment[9]) *
+ be32_to_cpu(pb->pb_Environment[3]) *
+ be32_to_cpu(pb->pb_Environment[5]);
+ add_gd_partition(hd,first_part_minor,start_sect,nr_sects);
+ first_part_minor++;
+ res = 1;
}
+ printk("\n");
rdb_done:
- set_blocksize(dev,old_blocksize);
return res;
}
diff --git a/fs/partitions/amiga.h b/fs/partitions/amiga.h
index 37c6ec144627..4f4f8a2772d9 100644
--- a/fs/partitions/amiga.h
+++ b/fs/partitions/amiga.h
@@ -3,6 +3,6 @@
*/
int
-amiga_partition(struct gendisk *hd, kdev_t dev,
+amiga_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor);
diff --git a/fs/partitions/atari.c b/fs/partitions/atari.c
index 0180daca8ef4..11a7b4a79625 100644
--- a/fs/partitions/atari.c
+++ b/fs/partitions/atari.c
@@ -33,146 +33,130 @@
be32_to_cpu((pi)->st) <= (hdsiz) && \
be32_to_cpu((pi)->st) + be32_to_cpu((pi)->siz) <= (hdsiz))
-int atari_partition (struct gendisk *hd, kdev_t dev,
+static inline int OK_id(char *s)
+{
+ return memcmp (s, "GEM", 3) == 0 || memcmp (s, "BGM", 3) == 0 ||
+ memcmp (s, "LNX", 3) == 0 || memcmp (s, "SWP", 3) == 0 ||
+ memcmp (s, "RAW", 3) == 0 ;
+}
+
+int atari_partition (struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int minor)
{
- int m_lim = minor + hd->max_p;
- struct buffer_head *bh;
- struct rootsector *rs;
- struct partition_info *pi;
- u32 extensect;
- u32 hd_size;
+ int m_lim = minor + hd->max_p;
+ Sector sect;
+ struct rootsector *rs;
+ struct partition_info *pi;
+ u32 extensect;
+ u32 hd_size;
#ifdef ICD_PARTS
- int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
+ int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
#endif
- bh = bread (dev, 0, get_ptable_blocksize(dev));
- if (!bh) {
- if (warn_no_part) printk (" unable to read block 0 (partition table)\n");
- return -1;
- }
-
- /* Verify this is an Atari rootsector: */
- rs = (struct rootsector *) bh->b_data;
- hd_size = hd->part[minor - 1].nr_sects;
- if (!VALID_PARTITION(&rs->part[0], hd_size) &&
- !VALID_PARTITION(&rs->part[1], hd_size) &&
- !VALID_PARTITION(&rs->part[2], hd_size) &&
- !VALID_PARTITION(&rs->part[3], hd_size)) {
- /* if there's no valid primary partition, assume that no Atari
- format partition table (there's no reliable magic or the like
- :-() */
- brelse(bh);
- return 0;
- }
-
- pi = &rs->part[0];
- printk (" AHDI");
- for (; pi < &rs->part[4] && minor < m_lim; minor++, pi++)
- {
- if (pi->flg & 1)
- /* active partition */
- {
- if (memcmp (pi->id, "XGM", 3) == 0)
- /* extension partition */
- {
- struct rootsector *xrs;
- struct buffer_head *xbh;
- ulong partsect;
+ rs = (struct rootsector *) read_dev_sector(bdev, 0, &sect);
+ if (!rs)
+ return -1;
+
+ /* Verify this is an Atari rootsector: */
+ hd_size = hd->part[minor - 1].nr_sects;
+ if (!VALID_PARTITION(&rs->part[0], hd_size) &&
+ !VALID_PARTITION(&rs->part[1], hd_size) &&
+ !VALID_PARTITION(&rs->part[2], hd_size) &&
+ !VALID_PARTITION(&rs->part[3], hd_size)) {
+ /*
+ * if there's no valid primary partition, assume that no Atari
+ * format partition table (there's no reliable magic or the like
+ * :-()
+ */
+ put_dev_sector(sect);
+ return 0;
+ }
+ pi = &rs->part[0];
+ printk (" AHDI");
+ for (; pi < &rs->part[4] && minor < m_lim; minor++, pi++) {
+ struct rootsector *xrs;
+ Sector sect2;
+ ulong partsect;
+
+ if ( !(pi->flg & 1) )
+ continue;
+ /* active partition */
+ if (memcmp (pi->id, "XGM", 3) != 0) {
+ /* we don't care about other id's */
+ add_gd_partition (hd, minor, be32_to_cpu(pi->st),
+ be32_to_cpu(pi->siz));
+ continue;
+ }
+ /* extension partition */
#ifdef ICD_PARTS
- part_fmt = 1;
+ part_fmt = 1;
#endif
- printk(" XGM<");
- partsect = extensect = be32_to_cpu(pi->st);
- while (1)
- {
- xbh = bread (dev, partsect / 2, get_ptable_blocksize(dev));
- if (!xbh)
- {
- printk (" block %ld read failed\n", partsect);
- brelse(bh);
- return 0;
- }
- if (partsect & 1)
- xrs = (struct rootsector *) &xbh->b_data[512];
- else
- xrs = (struct rootsector *) &xbh->b_data[0];
-
- /* ++roman: sanity check: bit 0 of flg field must be set */
- if (!(xrs->part[0].flg & 1)) {
- printk( "\nFirst sub-partition in extended partition is not valid!\n" );
- break;
- }
-
- add_gd_partition(hd, minor,
+ printk(" XGM<");
+ partsect = extensect = be32_to_cpu(pi->st);
+ while (1) {
+ xrs = (struct rootsector *)read_dev_sector(bdev, partsect, &sect2);
+ if (!xrs) {
+ printk (" block %ld read failed\n", partsect);
+ put_dev_sector(sect);
+ return 0;
+ }
+
+ /* ++roman: sanity check: bit 0 of flg field must be set */
+ if (!(xrs->part[0].flg & 1)) {
+ printk( "\nFirst sub-partition in extended partition is not valid!\n" );
+ put_dev_sector(sect2);
+ break;
+ }
+
+ add_gd_partition(hd, minor,
partsect + be32_to_cpu(xrs->part[0].st),
be32_to_cpu(xrs->part[0].siz));
- if (!(xrs->part[1].flg & 1)) {
- /* end of linked partition list */
- brelse( xbh );
- break;
- }
- if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) {
- printk( "\nID of extended partition is not XGM!\n" );
- brelse( xbh );
- break;
- }
-
- partsect = be32_to_cpu(xrs->part[1].st) + extensect;
- brelse (xbh);
- minor++;
- if (minor >= m_lim) {
- printk( "\nMaximum number of partitions reached!\n" );
- break;
- }
+ if (!(xrs->part[1].flg & 1)) {
+ /* end of linked partition list */
+ put_dev_sector(sect2);
+ break;
+ }
+ if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) {
+ printk("\nID of extended partition is not XGM!\n");
+ put_dev_sector(sect2);
+ break;
+ }
+
+ partsect = be32_to_cpu(xrs->part[1].st) + extensect;
+ put_dev_sector(sect2);
+ minor++;
+ if (minor >= m_lim) {
+ printk( "\nMaximum number of partitions reached!\n" );
+ break;
+ }
}
- printk(" >");
- }
- else
- {
- /* we don't care about other id's */
- add_gd_partition (hd, minor, be32_to_cpu(pi->st),
- be32_to_cpu(pi->siz));
- }
+ printk(" >");
}
- }
#ifdef ICD_PARTS
- if ( part_fmt!=1 ) /* no extended partitions -> test ICD-format */
- {
- pi = &rs->icdpart[0];
- /* sanity check: no ICD format if first partition invalid */
- if (memcmp (pi->id, "GEM", 3) == 0 ||
- memcmp (pi->id, "BGM", 3) == 0 ||
- memcmp (pi->id, "LNX", 3) == 0 ||
- memcmp (pi->id, "SWP", 3) == 0 ||
- memcmp (pi->id, "RAW", 3) == 0 )
- {
- printk(" ICD<");
- for (; pi < &rs->icdpart[8] && minor < m_lim; minor++, pi++)
- {
- /* accept only GEM,BGM,RAW,LNX,SWP partitions */
- if (pi->flg & 1 &&
- (memcmp (pi->id, "GEM", 3) == 0 ||
- memcmp (pi->id, "BGM", 3) == 0 ||
- memcmp (pi->id, "LNX", 3) == 0 ||
- memcmp (pi->id, "SWP", 3) == 0 ||
- memcmp (pi->id, "RAW", 3) == 0) )
- {
- part_fmt = 2;
- add_gd_partition (hd, minor, be32_to_cpu(pi->st),
- be32_to_cpu(pi->siz));
- }
- }
- printk(" >");
- }
- }
+ if ( part_fmt!=1 ) { /* no extended partitions -> test ICD-format */
+ pi = &rs->icdpart[0];
+ /* sanity check: no ICD format if first partition invalid */
+ if (OK_id(pi->id)) {
+ printk(" ICD<");
+ for (; pi < &rs->icdpart[8] && minor < m_lim; minor++, pi++) {
+ /* accept only GEM,BGM,RAW,LNX,SWP partitions */
+ if (!((pi->flg & 1) && OK_id(pi->id)))
+ continue;
+ part_fmt = 2;
+ add_gd_partition (hd, minor,
+ be32_to_cpu(pi->st),
+ be32_to_cpu(pi->siz));
+ }
+ printk(" >");
+ }
+ }
#endif
- brelse (bh);
+ put_dev_sector(sect);
- printk ("\n");
+ printk ("\n");
- return 1;
+ return 1;
}
diff --git a/fs/partitions/atari.h b/fs/partitions/atari.h
index 6d19c93e561a..6a14eb75947d 100644
--- a/fs/partitions/atari.h
+++ b/fs/partitions/atari.h
@@ -31,6 +31,6 @@ struct rootsector
u16 checksum; /* checksum for bootable disks */
} __attribute__((__packed__));
-int atari_partition (struct gendisk *hd, kdev_t dev,
+int atari_partition (struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor);
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 6d00b601a179..ee0ce88fed84 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -38,7 +38,7 @@ extern int *blk_size[];
int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
-static int (*check_part[])(struct gendisk *hd, kdev_t dev, unsigned long first_sect, int first_minor) = {
+static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = {
#ifdef CONFIG_ACORN_PARTITION
acorn_partition,
#endif
@@ -215,54 +215,12 @@ void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
#endif
}
-unsigned int get_ptable_blocksize(kdev_t dev)
-{
- int ret = 1024;
-
- /*
- * See whether the low-level driver has given us a minumum blocksize.
- * If so, check to see whether it is larger than the default of 1024.
- */
- if (!blksize_size[MAJOR(dev)])
- return ret;
-
- /*
- * Check for certain special power of two sizes that we allow.
- * With anything larger than 1024, we must force the blocksize up to
- * the natural blocksize for the device so that we don't have to try
- * and read partial sectors. Anything smaller should be just fine.
- */
-
- switch (blksize_size[MAJOR(dev)][MINOR(dev)]) {
- case 2048:
- ret = 2048;
- break;
- case 4096:
- ret = 4096;
- break;
- case 8192:
- ret = 8192;
- break;
- case 1024:
- case 512:
- case 256:
- case 0:
- /*
- * These are all OK.
- */
- break;
- default:
- panic("Strange blocksize for partition table\n");
- }
-
- return ret;
-}
-
static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
{
devfs_handle_t de = NULL;
static int first_time = 1;
unsigned long first_sector;
+ struct block_device *bdev;
char buf[64];
int i;
@@ -287,12 +245,23 @@ static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor
printk(KERN_INFO " /dev/%s:", buf + i);
else
printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
- for (i = 0; check_part[i]; i++)
- if (check_part[i](hd, dev, first_sector, first_part_minor))
+ bdev = bdget(kdev_t_to_nr(dev));
+ bdev->bd_inode->i_size = (loff_t)hd->part[MINOR(dev)].nr_sects << 9;
+ for (i = 0; check_part[i]; i++) {
+ int res;
+ res = check_part[i](hd, bdev, first_sector, first_part_minor);
+ if (res) {
+ if (res < 0 && warn_no_part)
+ printk(" unable to read partition table\n");
goto setup_devfs;
+ }
+ }
printk(" unknown partition table\n");
setup_devfs:
+ invalidate_bdev(bdev, 1);
+ truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
+ bdput(bdev);
i = first_part_minor - 1;
devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
}
@@ -428,3 +397,26 @@ void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
blk_size[dev->major] = dev->sizes;
}
}
+
+unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p)
+{
+ struct address_space *mapping = bdev->bd_inode->i_mapping;
+ int sect = PAGE_CACHE_SIZE / 512;
+ struct page *page;
+
+ page = read_cache_page(mapping, n/sect,
+ (filler_t *)mapping->a_ops->readpage, NULL);
+ if (!IS_ERR(page)) {
+ wait_on_page(page);
+ if (!Page_Uptodate(page))
+ goto fail;
+ if (PageError(page))
+ goto fail;
+ p->v = page;
+ return (unsigned char *)page_address(page) + 512 * (n % sect);
+fail:
+ page_cache_release(page);
+ }
+ p->v = NULL;
+ return NULL;
+}
diff --git a/fs/partitions/check.h b/fs/partitions/check.h
index c2dde3a97edf..32d7940469a4 100644
--- a/fs/partitions/check.h
+++ b/fs/partitions/check.h
@@ -4,9 +4,13 @@
*/
void add_gd_partition(struct gendisk *hd, int minor, int start, int size);
-/*
- * Get the default block size for this device
- */
-unsigned int get_ptable_blocksize(kdev_t dev);
+typedef struct {struct page *v;} Sector;
+
+unsigned char *read_dev_sector(struct block_device *, unsigned long, Sector *);
+
+static inline void put_dev_sector(Sector p)
+{
+ page_cache_release(p.v);
+}
extern int warn_no_part;
diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c
index 8e2b6d5da229..cc6e7470eb7f 100644
--- a/fs/partitions/ibm.c
+++ b/fs/partitions/ibm.c
@@ -42,30 +42,6 @@ static char* part_names[] = { [ibm_partition_lnx1] = "LNX1",
[ibm_partition_none] = "(nonl)"
};
-static int
-get_drive_geometry(int kdev,struct hd_geometry *geo)
-{
- struct block_device *bdev = bdget(kdev_t_to_nr(kdev));
- int rc = blkdev_get(bdev, 0, 1, BDEV_FILE);
- if ( rc == 0 ) {
- rc = ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo);
- blkdev_put(bdev, BDEV_FILE);
- }
- return rc;
-}
-
-static int
-get_drive_info(int kdev,dasd_information_t *info)
-{
- struct block_device *bdev = bdget(kdev_t_to_nr(kdev));
- int rc = blkdev_get(bdev, 0, 1, BDEV_FILE);
- if ( rc == 0 ) {
- rc = ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)(info));
- blkdev_put(bdev, BDEV_FILE);
- }
- return rc;
-}
-
static ibm_partition_t
get_partition_type ( char * type )
{
@@ -89,10 +65,8 @@ two_partitions(struct gendisk *hd,
int offset,
int size) {
- add_gd_partition( hd, minor, 0,size);
- add_gd_partition( hd, minor + 1,
- offset * (blocksize >> 9),
- size-offset*(blocksize>>9));
+ add_gd_partition( hd, minor, 0, size);
+ add_gd_partition( hd, minor+1, offset*blocksize, size-offset*blocksize);
}
@@ -119,10 +93,11 @@ cchhb2blk (cchhb_t *ptr, struct hd_geometry *geo) {
}
int
-ibm_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int
-first_part_minor)
+ibm_partition(struct gendisk *hd, struct block_device *bdev,
+ unsigned long first_sector, int first_part_minor)
{
- struct buffer_head *bh, *buf;
+ Sector sect, sect2;
+ unsigned char *data;
ibm_partition_t partition_type;
char type[5] = {0,};
char name[7] = {0,};
@@ -133,40 +108,41 @@ first_part_minor)
format1_label_t f1;
volume_label_t vlabel;
dasd_information_t *info;
+ kdev_t dev = to_kdev_t(bdev->bd_dev);
- if ( first_sector != 0 ) {
+ if ( first_sector != 0 )
BUG();
- }
+
info = (struct dasd_information_t *)kmalloc(sizeof(dasd_information_t),
GFP_KERNEL);
if ( info == NULL )
return 0;
- if (get_drive_info (dev,info))
+ if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)(info)))
return 0;
geo = (struct hd_geometry *)kmalloc(sizeof(struct hd_geometry),
GFP_KERNEL);
if ( geo == NULL )
return 0;
- if (get_drive_geometry (dev,geo))
+ if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo);
return 0;
blocksize = hardsect_size[MAJOR(dev)][MINOR(dev)];
if ( blocksize <= 0 ) {
return 0;
}
+ blocksize >>= 9;
- set_blocksize(dev, blocksize); /* OUCH !! */
- if ( ( bh = bread( dev, info->label_block, blocksize) ) != NULL ) {
- strncpy ( type,bh -> b_data + 0, 4);
- if ((!info->FBA_layout) && (!strcmp(info->type,"ECKD"))) {
-
- strncpy ( name,bh -> b_data + 8, 6);
- } else {
- strncpy ( name,bh -> b_data + 4, 6);
- }
- memcpy (&vlabel, bh->b_data, sizeof(volume_label_t));
- } else {
+ data = read_dev_sector(bdev, inode->label_block*blocksize, &sect);
+ if (!data)
return 0;
+
+ strncpy (type, data, 4);
+ if ((!info->FBA_layout) && (!strcmp(info->type,"ECKD"))) {
+ strncpy ( name, data + 8, 6);
+ } else {
+ strncpy ( name, data + 4, 6);
}
+ memcpy (&vlabel, data, sizeof(volume_label_t));
+
EBCASC(type,4);
EBCASC(name,6);
@@ -174,12 +150,12 @@ first_part_minor)
printk ( "%4s/%8s:",part_names[partition_type],name);
switch ( partition_type ) {
case ibm_partition_cms1:
- if (* (((long *)bh->b_data) + 13) != 0) {
+ if (* ((long *)data + 13) != 0) {
/* disk is reserved minidisk */
- long *label=(long*)bh->b_data;
- blocksize = label[3];
+ long *label=(long*)data;
+ blocksize = label[3]>>9;
offset = label[13];
- size = (label[7]-1)*(blocksize>>9);
+ size = (label[7]-1)*blocksize;
printk ("(MDSK)");
} else {
offset = (info->label_block + 1);
@@ -199,9 +175,10 @@ first_part_minor)
/* get block number and read then first format1 label */
blk = cchhb2blk(&vlabel.vtoc, geo) + 1;
- if ((buf = bread( dev, blk, blocksize)) != NULL) {
- memcpy (&f1, buf->b_data, sizeof(format1_label_t));
- bforget(buf);
+ data = read_dev_sector(bdev, blk * blocksize, &sect2);
+ if (data) {
+ memcpy (&f1, data, sizeof(format1_label_t));
+ put_dev_sector(sect2);
}
while (f1.DS1FMTID == _ascebc['1']) {
@@ -211,14 +188,14 @@ first_part_minor)
counter++;
add_gd_partition(hd, MINOR(dev) + counter,
- offset * (blocksize >> 9),
- psize * (blocksize >> 9));
+ offset * blocksize,
+ psize * blocksize);
blk++;
- if ((buf = bread( dev, blk, blocksize)) != NULL) {
- memcpy (&f1, buf->b_data,
- sizeof(format1_label_t));
- bforget(buf);
+ data = read_dev_sector(bdev, blk * blocksize, &sect2);
+ if (data) {
+ memcpy (&f1, data, sizeof(format1_label_t));
+ put_dev_sector(sect2);
}
}
break;
@@ -228,6 +205,6 @@ first_part_minor)
}
printk ( "\n" );
- bforget(bh);
+ put_dev_sector(sect);
return 1;
}
diff --git a/fs/partitions/ibm.h b/fs/partitions/ibm.h
index 49ff10bc45b6..08b05ed151fe 100644
--- a/fs/partitions/ibm.h
+++ b/fs/partitions/ibm.h
@@ -1 +1 @@
-int ibm_partition(struct gendisk *, kdev_t, unsigned long, int);
+int ibm_partition(struct gendisk *, struct block_device *, unsigned long, int);
diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c
index 9da28781cf52..9cef2a18fbd0 100644
--- a/fs/partitions/ldm.c
+++ b/fs/partitions/ldm.c
@@ -178,10 +178,12 @@ static int parse_vblk(const u8 *buffer, const int buf_size, struct vblk *vb)
*/
static int create_data_partitions(struct gendisk *hd,
const unsigned long first_sector, int first_part_minor,
- const kdev_t dev, const struct vmdb *vm,
- const struct privhead *ph, const struct ldmdisk *dk)
+ struct block_device *bdev, const struct vmdb *vm,
+ const struct privhead *ph, const struct ldmdisk *dk,
+ unsigned long base)
{
- struct buffer_head *bh;
+ Sector sect;
+ unsigned char *data;
struct vblk *vb;
int vblk;
int vsize; /* VBLK size. */
@@ -192,14 +194,14 @@ static int create_data_partitions(struct gendisk *hd,
if (!vb)
goto no_mem;
vsize = vm->vblk_size;
- if (vsize < 1 || vsize > LDM_BLOCKSIZE)
+ if (vsize < 1 || vsize > 512)
goto err_out;
- perbuf = LDM_BLOCKSIZE / vsize;
- if (perbuf < 1 || LDM_BLOCKSIZE % vsize)
+ perbuf = 512 / vsize;
+ if (perbuf < 1 || 512 % vsize)
goto err_out;
/* 512 == VMDB size */
- lastbuf = (vm->last_vblk_seq - (512 / vsize)) / perbuf;
- lastofs = (vm->last_vblk_seq - (512 / vsize)) % perbuf;
+ lastbuf = vm->last_vblk_seq / perbuf - 1;
+ lastofs = vm->last_vblk_seq % perbuf;
if (lastofs)
lastbuf++;
if (OFF_VBLK * LDM_BLOCKSIZE + vm->last_vblk_seq * vsize >
@@ -207,17 +209,18 @@ static int create_data_partitions(struct gendisk *hd,
goto err_out;
printk(" <");
for (buffer = 0; buffer < lastbuf; buffer++) {
- if (!(bh = bread(dev, buffer + OFF_VBLK, LDM_BLOCKSIZE)))
+ data = read_dev_sector(bdev, base + 2*OFF_VBLK + buffer, &sect);
+ if (!data)
goto read_err;
for (vblk = 0; vblk < perbuf; vblk++) {
u8 *block;
if (lastofs && buffer == lastbuf - 1 && vblk >= lastofs)
break;
- block = bh->b_data + vsize * vblk;
- if (block + vsize > (u8*)bh->b_data + LDM_BLOCKSIZE)
+ block = data + vsize * vblk;
+ if (block + vsize > data + 512)
goto brelse_out;
- if (parse_vblk(block, LDM_BLOCKSIZE, vb) != 1)
+ if (parse_vblk(block, vsize, vb) != 1)
continue;
if (vb->vblk_type != VBLK_PART)
continue;
@@ -229,7 +232,7 @@ static int create_data_partitions(struct gendisk *hd,
vb->num_sectors) == 1)
first_part_minor++;
}
- brelse(bh);
+ put_dev_sector(sect);
}
printk(" >\n");
err = 1;
@@ -237,7 +240,7 @@ out:
kfree(vb);
return err;
brelse_out:
- brelse(bh);
+ put_dev_sector(sect);
goto err_out;
no_mem:
printk(LDM_CRIT "Not enough memory to allocate required buffers.\n");
@@ -326,10 +329,12 @@ static int get_vstr(const u8 *block, u8 *buffer, const int buflen)
*
* Return 1 on success and -1 on error, in which case @dk is undefined.
*/
-static int get_disk_objid(const kdev_t dev, const struct vmdb *vm,
- const struct privhead *ph, struct ldmdisk *dk)
+static int get_disk_objid(struct block_device *bdev, const struct vmdb *vm,
+ const struct privhead *ph, struct ldmdisk *dk,
+ unsigned long base)
{
- struct buffer_head *bh;
+ Sector sect;
+ unsigned char *data;
u8 *disk_id;
int vblk;
int vsize; /* VBLK size. */
@@ -340,21 +345,22 @@ static int get_disk_objid(const kdev_t dev, const struct vmdb *vm,
if (!disk_id)
goto no_mem;
vsize = vm->vblk_size;
- if (vsize < 1 || vsize > LDM_BLOCKSIZE)
+ if (vsize < 1 || vsize > 512)
goto err_out;
- perbuf = LDM_BLOCKSIZE / vsize;
- if (perbuf < 1 || LDM_BLOCKSIZE % vsize)
+ perbuf = 512 / vsize;
+ if (perbuf < 1 || 512 % vsize)
goto err_out;
/* 512 == VMDB size */
- lastbuf = (vm->last_vblk_seq - (512 / vsize)) / perbuf;
- lastofs = (vm->last_vblk_seq - (512 / vsize)) % perbuf;
+ lastbuf = vm->last_vblk_seq / perbuf - 1;
+ lastofs = vm->last_vblk_seq % perbuf;
if (lastofs)
lastbuf++;
if (OFF_VBLK * LDM_BLOCKSIZE + vm->last_vblk_seq * vsize >
ph->config_size * 512)
goto err_out;
for (buffer = 0; buffer < lastbuf; buffer++) {
- if (!(bh = bread(dev, buffer + OFF_VBLK, LDM_BLOCKSIZE)))
+ data = read_dev_sector(bdev, base + 2*OFF_VBLK + buffer, &sect);
+ if (!data)
goto read_err;
for (vblk = 0; vblk < perbuf; vblk++) {
int rel_objid, rel_name, delta;
@@ -362,20 +368,19 @@ static int get_disk_objid(const kdev_t dev, const struct vmdb *vm,
if (lastofs && buffer == lastbuf - 1 && vblk >= lastofs)
break;
- block = bh->b_data + vblk * vsize;
+ block = data + vblk * vsize;
delta = vblk * vsize + 0x18;
- if (delta >= LDM_BLOCKSIZE)
+ if (delta >= 512)
goto brelse_out;
if (block[0x13] != VBLK_DISK)
continue;
/* Calculate relative offsets. */
rel_objid = 1 + block[0x18];
- if (delta + rel_objid >= LDM_BLOCKSIZE)
+ if (delta + rel_objid >= 512)
goto brelse_out;
rel_name = 1 + block[0x18 + rel_objid] + rel_objid;
- if (delta + rel_name >= LDM_BLOCKSIZE ||
- delta + rel_name + block[0x18 + rel_name] >=
- LDM_BLOCKSIZE)
+ if (delta + rel_name >= 512 ||
+ delta + rel_name + block[0x18 + rel_name] >= 512)
goto brelse_out;
err = get_vstr(block + 0x18 + rel_name, disk_id,
DISK_ID_SIZE);
@@ -383,7 +388,7 @@ static int get_disk_objid(const kdev_t dev, const struct vmdb *vm,
goto brelse_out;
if (!strncmp(disk_id, ph->disk_id, DISK_ID_SIZE)) {
dk->obj_id = get_vnum(block + 0x18, &err);
- brelse(bh);
+ put_dev_sector(sect);
if (err)
goto out;
strncpy(dk->disk_id, ph->disk_id,
@@ -393,14 +398,14 @@ static int get_disk_objid(const kdev_t dev, const struct vmdb *vm,
goto out;
}
}
- brelse(bh);
+ put_dev_sector(sect);
}
err = -1;
out:
kfree(disk_id);
return err;
brelse_out:
- brelse(bh);
+ put_dev_sector(sect);
goto err_out;
no_mem:
printk(LDM_CRIT "Not enough memory to allocate required buffers.\n");
@@ -457,17 +462,19 @@ static int parse_vmdb(const u8 *buffer, struct vmdb *vm)
*
* Return 1 on success and -1 on error, in which case @vm is undefined.
*/
-static int validate_vmdb(const kdev_t dev, struct vmdb *vm)
+static int validate_vmdb(struct block_device *bdev, struct vmdb *vm, unsigned long base)
{
- struct buffer_head *bh;
+ Sector sect;
+ unsigned char *data;
int ret;
- if (!(bh = bread(dev, OFF_VMDB, LDM_BLOCKSIZE))) {
+ data = read_dev_sector(bdev, base + OFF_VMDB * 2 + 1, &sect);
+ if (!data) {
printk(LDM_CRIT "Disk read failed in validate_vmdb.\n");
return -1;
}
- ret = parse_vmdb(bh->b_data + 0x200, vm);
- brelse(bh);
+ ret = parse_vmdb(data, vm);
+ put_dev_sector(sect);
return ret;
}
@@ -553,9 +560,12 @@ static int parse_tocblock(const u8 *buffer, struct tocblock *toc)
*
* Return 1 on success and -1 on error, in which case @toc1 is undefined.
*/
-static int validate_tocblocks(const kdev_t devdb, struct tocblock *toc1)
+static int validate_tocblocks(struct block_device *bdev,
+ struct tocblock *toc1,
+ unsigned long base)
{
- struct buffer_head *bh;
+ Sector sect;
+ unsigned char *data;
struct tocblock *toc2 = NULL, *toc3 = NULL, *toc4 = NULL;
int err;
@@ -569,39 +579,43 @@ static int validate_tocblocks(const kdev_t devdb, struct tocblock *toc1)
if (!toc4)
goto no_mem;
/* Read and parse first toc. */
- if (!(bh = bread(devdb, OFF_TOCBLOCK1, LDM_BLOCKSIZE))) {
+ data = read_dev_sector(bdev, base + OFF_TOCBLOCK1 * 2 + 1, &sect);
+ if (!data) {
printk(LDM_CRIT "Disk read 1 failed in validate_tocblocks.\n");
goto err_out;
}
- err = parse_tocblock(bh->b_data + 0x0200, toc1);
- brelse(bh);
+ err = parse_tocblock(data, toc1);
+ put_dev_sector(sect);
if (err != 1)
goto out;
/* Read and parse second toc. */
- if (!(bh = bread(devdb, OFF_TOCBLOCK2, LDM_BLOCKSIZE))) {
+ data = read_dev_sector(bdev, base + OFF_TOCBLOCK2 * 2, &sect);
+ if (!data) {
printk(LDM_CRIT "Disk read 2 failed in validate_tocblocks.\n");
goto err_out;
}
- err = parse_tocblock(bh->b_data, toc2);
- brelse(bh);
+ err = parse_tocblock(data, toc2);
+ put_dev_sector(sect);
if (err != 1)
goto out;
/* Read and parse third toc. */
- if (!(bh = bread(devdb, OFF_TOCBLOCK3, LDM_BLOCKSIZE))) {
+ data = read_dev_sector(bdev, base + OFF_TOCBLOCK3 * 2 + 1, &sect);
+ if (!data) {
printk(LDM_CRIT "Disk read 3 failed in validate_tocblocks.\n");
goto err_out;
}
- err = parse_tocblock(bh->b_data + 0x0200, toc3);
- brelse(bh);
+ err = parse_tocblock(data, toc3);
+ put_dev_sector(sect);
if (err != 1)
goto out;
/* Read and parse fourth toc. */
- if (!(bh = bread(devdb, OFF_TOCBLOCK4, LDM_BLOCKSIZE))) {
+ data = read_dev_sector(bdev, base + OFF_TOCBLOCK4 * 2, &sect);
+ if (!data) {
printk(LDM_CRIT "Disk read 4 failed in validate_tocblocks.\n");
goto err_out;
}
- err = parse_tocblock(bh->b_data, toc4);
- brelse(bh);
+ err = parse_tocblock(data, toc4);
+ put_dev_sector(sect);
if (err != 1)
goto out;
/* Compare all tocs. */
@@ -665,9 +679,12 @@ static int compare_privheads(const struct privhead *ph1,
*
* Return 1 on succes and -1 on error.
*/
-static int validate_privheads(const kdev_t dev, const struct privhead *ph1)
+static int validate_privheads(struct block_device *bdev,
+ const struct privhead *ph1,
+ unsigned long base)
{
- struct buffer_head *bh;
+ Sector sect;
+ unsigned char *data;
struct privhead *ph2 = NULL, *ph3 = NULL;
int err;
@@ -677,20 +694,22 @@ static int validate_privheads(const kdev_t dev, const struct privhead *ph1)
ph3 = (struct privhead*)kmalloc(sizeof(*ph3), GFP_KERNEL);
if (!ph3)
goto no_mem;
- if (!(bh = bread(dev, OFF_PRIVHEAD2, LDM_BLOCKSIZE))) {
+ data = read_dev_sector(bdev, base + OFF_PRIVHEAD2 * 2, &sect);
+ if (!data) {
printk(LDM_CRIT "Disk read 1 failed in validate_privheads.\n");
goto err_out;
}
- err = parse_privhead(bh->b_data, ph2);
- brelse(bh);
+ err = parse_privhead(data, ph2);
+ put_dev_sector(sect);
if (err != 1)
goto out;
- if (!(bh = bread(dev, OFF_PRIVHEAD3, LDM_BLOCKSIZE))) {
+ data = read_dev_sector(bdev, base + OFF_PRIVHEAD3 * 2 + 1, &sect);
+ if (!data) {
printk(LDM_CRIT "Disk read 2 failed in validate_privheads.\n");
goto err_out;
}
- err = parse_privhead(bh->b_data + 0x0200, ph3);
- brelse(bh);
+ err = parse_privhead(data, ph3);
+ put_dev_sector(sect);
if (err != 1)
goto out;
err = compare_privheads(ph1, ph2);
@@ -807,27 +826,29 @@ static int parse_privhead(const u8 *buffer, struct privhead *ph)
*
* Return 1 on succes, 0 if device is not a dynamic disk and -1 on error.
*/
-static int create_db_partition(struct gendisk *hd, const kdev_t dev,
+static int create_db_partition(struct gendisk *hd, struct block_device *bdev,
const unsigned long first_sector, const int first_part_minor,
struct privhead *ph)
{
- struct buffer_head *bh;
+ Sector sect;
+ unsigned char *data;
int err;
- if (!(bh = bread(dev, OFF_PRIVHEAD1, LDM_BLOCKSIZE))) {
+ data = read_dev_sector(bdev, OFF_PRIVHEAD1*2, &sect);
+ if (!data) {
printk(LDM_CRIT __FUNCTION__ "(): Device read failed.\n");
return -1;
}
- if (BE64(bh->b_data) != MAGIC_PRIVHEAD) {
+ if (BE64(data) != MAGIC_PRIVHEAD) {
ldm_debug("Cannot find PRIVHEAD structure. Not a dynamic disk "
"or corrupt LDM database.\n");
return 0;
}
- err = parse_privhead(bh->b_data, ph);
+ err = parse_privhead(data, ph);
if (err == 1)
err = create_partition(hd, first_part_minor, first_sector +
ph->config_start, ph->config_size);
- brelse(bh);
+ put_dev_sector(sect);
return err;
}
@@ -842,23 +863,23 @@ static int create_db_partition(struct gendisk *hd, const kdev_t dev,
*
* Return 1 if @dev is a dynamic disk, 0 if not and -1 on error.
*/
-static int validate_partition_table(const kdev_t dev)
+static int validate_partition_table(struct block_device *bdev)
{
- struct buffer_head *bh;
+ Sector sect;
+ unsigned char *data;
struct partition *p;
int i, nr_sfs;
- if (!(bh = bread(dev, 0, LDM_BLOCKSIZE))) {
- if (warn_no_part)
- printk(LDM_ERR "Unable to read partition table.\n");
+ data = read_dev_sector(bdev, 0, &sect);
+ if (!data)
return -1;
- }
- if (*(u16*)(bh->b_data + 0x01FE) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
+
+ if (*(u16*)(data + 0x01FE) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
ldm_debug("No MS-DOS partition found.\n");
goto no_msdos_partition;
}
nr_sfs = 0;
- p = (struct partition*)(bh->b_data + 0x01BE);
+ p = (struct partition*)(data + 0x01BE);
for (i = 0; i < 4; i++) {
if (!SYS_IND(p+i) || SYS_IND(p+i) == WIN2K_EXTENDED_PARTITION)
continue;
@@ -871,12 +892,12 @@ static int validate_partition_table(const kdev_t dev)
if (!nr_sfs)
goto not_dynamic_disk;
ldm_debug("Parsed partition table successfully.\n");
- brelse(bh);
+ put_dev_sector(sect);
return 1;
not_dynamic_disk:
ldm_debug("Found basic MS-DOS partition, not a dynamic disk.\n");
no_msdos_partition:
- brelse(bh);
+ put_dev_sector(sect);
return 0;
}
@@ -904,67 +925,54 @@ no_msdos_partition:
* 0 if @dev is not a dynamic disk,
* -1 if an error occured.
*/
-int ldm_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
- int first_part_minor)
+int ldm_partition(struct gendisk *hd, struct block_device *bdev,
+ unsigned long first_sector, int first_part_minor)
{
- kdev_t devdb;
struct privhead *ph = NULL;
struct tocblock *toc = NULL;
struct vmdb *vm = NULL;
struct ldmdisk *dk = NULL;
+ unsigned long db_first;
int err;
if (!hd)
return 0;
- err = (int)get_ptable_blocksize(dev);
- if (err != LDM_BLOCKSIZE) { /* 1024 bytes */
- ldm_debug("Expected a blocksize of %d bytes, got %d instead.\n",
- LDM_BLOCKSIZE, get_ptable_blocksize(dev));
- return 0;
- }
- err = get_hardsect_size(dev);
- if (err != 512) {
- ldm_debug("Expected a sector size of %d bytes, got %d "
- "instead.\n", 512, get_hardsect_size(dev));
- return 0;
- }
/* Check the partition table. */
- err = validate_partition_table(dev);
+ err = validate_partition_table(bdev);
if (err != 1)
return err;
if (!(ph = (struct privhead*)kmalloc(sizeof(*ph), GFP_KERNEL)))
goto no_mem;
/* Create the LDM database device. */
- err = create_db_partition(hd, dev, first_sector, first_part_minor, ph);
+ err = create_db_partition(hd, bdev, first_sector, first_part_minor, ph);
if (err != 1)
goto out;
- /* For convenience, work with the LDM database device from now on. */
- devdb = MKDEV(MAJOR(dev), first_part_minor);
+ db_first = hd->part[first_part_minor].start_sect;
/* Check the backup privheads. */
- err = validate_privheads(devdb, ph);
+ err = validate_privheads(bdev, ph, db_first);
if (err != 1)
goto out;
/* Check the table of contents and its backups. */
if (!(toc = (struct tocblock*)kmalloc(sizeof(*toc), GFP_KERNEL)))
goto no_mem;
- err = validate_tocblocks(devdb, toc);
+ err = validate_tocblocks(bdev, toc, db_first);
if (err != 1)
goto out;
/* Check the vmdb. */
if (!(vm = (struct vmdb*)kmalloc(sizeof(*vm), GFP_KERNEL)))
goto no_mem;
- err = validate_vmdb(devdb, vm);
+ err = validate_vmdb(bdev, vm, db_first);
if (err != 1)
goto out;
/* Find the object id for @dev in the LDM database. */
if (!(dk = (struct ldmdisk*)kmalloc(sizeof(*dk), GFP_KERNEL)))
goto no_mem;
- err = get_disk_objid(devdb, vm, ph, dk);
+ err = get_disk_objid(bdev, vm, ph, dk, db_first);
if (err != 1)
goto out;
/* Finally, create the data partition devices. */
err = create_data_partitions(hd, first_sector, first_part_minor +
- LDM_FIRST_PART_OFFSET, devdb, vm, ph, dk);
+ LDM_FIRST_PART_OFFSET, bdev, vm, ph, dk, db_first);
if (err == 1)
ldm_debug("Parsed LDM database successfully.\n");
out:
diff --git a/fs/partitions/ldm.h b/fs/partitions/ldm.h
index ee7c60becb84..0404543ec1b2 100644
--- a/fs/partitions/ldm.h
+++ b/fs/partitions/ldm.h
@@ -144,8 +144,8 @@ struct vblk {
u64 num_sectors;
};
-int ldm_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
- int first_part_minor);
+int ldm_partition(struct gendisk *hd, struct block_device *bdev,
+ unsigned long first_sector, int first_part_minor);
#endif /* _FS_PT_LDM_H_ */
diff --git a/fs/partitions/mac.c b/fs/partitions/mac.c
index 5c46935c7288..84baad30c812 100644
--- a/fs/partitions/mac.c
+++ b/fs/partitions/mac.c
@@ -20,7 +20,7 @@
#include "check.h"
#include "mac.h"
-#ifdef CONFIG_PPC
+#ifdef CONFIG_ALL_PPC
extern void note_bootable_part(kdev_t dev, int part, int goodness);
#endif
@@ -36,69 +36,54 @@ static inline void mac_fix_string(char *stg, int len)
stg[i] = 0;
}
-int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_part_minor)
+int mac_partition(struct gendisk *hd, struct block_device *bdev,
+ unsigned long fsec, int first_part_minor)
{
- struct buffer_head *bh;
+ Sector sect;
+ unsigned char *data;
int blk, blocks_in_map;
- int dev_bsize, dev_pos, pos;
unsigned secsize;
-#ifdef CONFIG_PPC
+#ifdef CONFIG_ALL_PPC
int found_root = 0;
int found_root_goodness = 0;
#endif
struct mac_partition *part;
struct mac_driver_desc *md;
- dev_bsize = get_ptable_blocksize(dev);
- dev_pos = 0;
/* Get 0th block and look at the first partition map entry. */
- if ((bh = bread(dev, 0, dev_bsize)) == 0) {
- printk("%s: error reading partition table\n",
- kdevname(dev));
- return -1;
- }
- md = (struct mac_driver_desc *) bh->b_data;
+ md = (struct mac_driver_desc *) read_dev_sector(bdev, 0, &sect);
+ if (!md)
+ return -1;
if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) {
- brelse(bh);
+ put_dev_sector(sect);
return 0;
}
secsize = be16_to_cpu(md->block_size);
- if (secsize >= dev_bsize) {
- brelse(bh);
- dev_pos = secsize;
- if ((bh = bread(dev, secsize/dev_bsize, dev_bsize)) == 0) {
- printk("%s: error reading Mac partition table\n",
- kdevname(dev));
- return -1;
- }
- }
- part = (struct mac_partition *) (bh->b_data + secsize - dev_pos);
+ put_dev_sector(sect);
+ data = read_dev_sector(bdev, secsize/512, &sect);
+ if (!data)
+ return -1;
+ part = (struct mac_partition *) (data + secsize%512);
if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
- brelse(bh);
+ put_dev_sector(sect);
return 0; /* not a MacOS disk */
}
printk(" [mac]");
blocks_in_map = be32_to_cpu(part->map_count);
for (blk = 1; blk <= blocks_in_map; ++blk) {
- pos = blk * secsize;
- if (pos >= dev_pos + dev_bsize) {
- brelse(bh);
- dev_pos = pos;
- if ((bh = bread(dev, pos/dev_bsize, dev_bsize)) == 0) {
- printk("%s: error reading partition table\n",
- kdevname(dev));
- return -1;
- }
- }
- part = (struct mac_partition *) (bh->b_data + pos - dev_pos);
+ int pos = blk * secsize;
+ put_dev_sector(sect);
+ data = read_dev_sector(bdev, pos/512, &sect);
+ if (!data)
+ return -1;
+ part = (struct mac_partition *) (data + pos%512);
if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
break;
- blocks_in_map = be32_to_cpu(part->map_count);
add_gd_partition(hd, first_part_minor,
fsec + be32_to_cpu(part->start_block) * (secsize/512),
be32_to_cpu(part->block_count) * (secsize/512));
-#ifdef CONFIG_PPC
+#ifdef CONFIG_ALL_PPC
/*
* If this is the first bootable partition, tell the
* setup code, in case it wants to make this the root.
@@ -139,15 +124,17 @@ int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_
found_root_goodness = goodness;
}
}
-#endif /* CONFIG_PPC */
+#endif /* CONFIG_ALL_PPC */
++first_part_minor;
}
-#ifdef CONFIG_PPC
+#ifdef CONFIG_ALL_PPC
if (found_root_goodness)
- note_bootable_part(dev, found_root, found_root_goodness);
+ note_bootable_part(to_kdev_t(bdev->bd_dev),
+ found_root, found_root_goodness);
#endif
- brelse(bh);
+
+ put_dev_sector(sect);
printk("\n");
return 1;
}
diff --git a/fs/partitions/mac.h b/fs/partitions/mac.h
index 1a3fd68de6e5..9d36ec64983e 100644
--- a/fs/partitions/mac.h
+++ b/fs/partitions/mac.h
@@ -41,4 +41,4 @@ struct mac_driver_desc {
/* ... more stuff */
};
-int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_part_minor);
+int mac_partition(struct gendisk *hd, struct block_device *bdev, unsigned long fsec, int first_part_minor);
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 52e626ab8459..8777f50178a9 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -40,8 +40,6 @@
extern void md_autodetect_dev(kdev_t dev);
#endif
-static int current_minor;
-
/*
* Many architectures don't like unaligned accesses, which is
* frequently the case with the nr_sects and start_sect partition
@@ -88,7 +86,8 @@ static char __attribute__ ((unused))
#define MSDOS_LABEL_MAGIC2 0xAA
static inline int
-msdos_magic_present(unsigned char *p) {
+msdos_magic_present(unsigned char *p)
+{
return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
}
@@ -103,35 +102,38 @@ msdos_magic_present(unsigned char *p) {
* only for the actual data partitions.
*/
-static void extended_partition(struct gendisk *hd, kdev_t dev)
+static void extended_partition(struct gendisk *hd, struct block_device *bdev,
+ int minor, int *current_minor)
{
- struct buffer_head *bh;
struct partition *p;
+ Sector sect;
+ unsigned char *data;
unsigned long first_sector, first_size, this_sector, this_size;
int mask = (1 << hd->minor_shift) - 1;
- int sector_size = get_hardsect_size(dev) / 512;
+ int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
int loopct = 0; /* number of links followed
without finding a data partition */
int i;
- first_sector = hd->part[MINOR(dev)].start_sect;
- first_size = hd->part[MINOR(dev)].nr_sects;
+ first_sector = hd->part[minor].start_sect;
+ first_size = hd->part[minor].nr_sects;
this_sector = first_sector;
while (1) {
if (++loopct > 100)
return;
- if ((current_minor & mask) == 0)
+ if ((*current_minor & mask) == 0)
return;
- if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
+ data = read_dev_sector(bdev, this_sector, &sect);
+ if (!data)
return;
- if (!msdos_magic_present(bh->b_data + 510))
- goto done;
+ if (!msdos_magic_present(data + 510))
+ goto done;
- p = (struct partition *) (bh->b_data + 0x1be);
+ p = (struct partition *) (data + 0x1be);
- this_size = hd->part[MINOR(dev)].nr_sects;
+ this_size = hd->part[minor].nr_sects;
/*
* Usually, the first entry is the real data partition,
@@ -146,30 +148,34 @@ static void extended_partition(struct gendisk *hd, kdev_t dev)
* First process the data partition(s)
*/
for (i=0; i<4; i++, p++) {
+ unsigned long offs, size, next;
if (!NR_SECTS(p) || is_extended_partition(p))
continue;
/* Check the 3rd and 4th entries -
these sometimes contain random garbage */
- if (i >= 2
- && START_SECT(p) + NR_SECTS(p) > this_size
- && (this_sector + START_SECT(p) < first_sector ||
- this_sector + START_SECT(p) + NR_SECTS(p) >
- first_sector + first_size))
- continue;
+ offs = START_SECT(p)*sector_size;
+ size = NR_SECTS(p)*sector_size;
+ next = this_sector + offs;
+ if (i >= 2) {
+ if (offs + size > this_size)
+ continue;
+ if (next < first_sector)
+ continue;
+ if (next + size > first_sector + first_size)
+ continue;
+ }
- add_gd_partition(hd, current_minor,
- this_sector+START_SECT(p)*sector_size,
- NR_SECTS(p)*sector_size);
+ add_gd_partition(hd, *current_minor, next, size);
#if CONFIG_BLK_DEV_MD
if (SYS_IND(p) == LINUX_RAID_PARTITION) {
- md_autodetect_dev(MKDEV(hd->major,current_minor));
+ md_autodetect_dev(MKDEV(hd->major,*current_minor));
}
#endif
- current_minor++;
+ (*current_minor)++;
loopct = 0;
- if ((current_minor & mask) == 0)
+ if ((*current_minor & mask) == 0)
goto done;
}
/*
@@ -184,61 +190,52 @@ static void extended_partition(struct gendisk *hd, kdev_t dev)
*/
p -= 4;
for (i=0; i<4; i++, p++)
- if(NR_SECTS(p) && is_extended_partition(p))
+ if (NR_SECTS(p) && is_extended_partition(p))
break;
if (i == 4)
goto done; /* nothing left to do */
- hd->part[current_minor].nr_sects = NR_SECTS(p) * sector_size; /* JSt */
- hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size;
this_sector = first_sector + START_SECT(p) * sector_size;
- dev = MKDEV(hd->major, current_minor);
-
- /* Use bforget(), as we have changed the disk geometry */
- bforget(bh);
+ minor = *current_minor;
+ put_dev_sector(sect);
}
done:
- bforget(bh);
+ put_dev_sector(sect);
}
-static inline struct buffer_head *
-get_partition_table_block(struct gendisk *hd, int minor, int blocknr) {
- kdev_t dev = MKDEV(hd->major, minor);
- return bread(dev, blocknr, get_ptable_blocksize(dev));
-}
-
-#ifdef CONFIG_SOLARIS_X86_PARTITION
-
/* james@bpgc.com: Solaris has a nasty indicator: 0x82 which also
indicates linux swap. Be careful before believing this is Solaris. */
static void
-solaris_x86_partition(struct gendisk *hd, int minor) {
- long offset = hd->part[minor].start_sect;
+solaris_x86_partition(struct gendisk *hd, struct block_device *bdev,
+ int minor, int *current_minor)
+{
- struct buffer_head *bh;
+#ifdef CONFIG_SOLARIS_X86_PARTITION
+ long offset = hd->part[minor].start_sect;
+ Sector sect;
struct solaris_x86_vtoc *v;
struct solaris_x86_slice *s;
int mask = (1 << hd->minor_shift) - 1;
int i;
char buf[40];
- if(!(bh = get_partition_table_block(hd, minor, 0)))
+ v = (struct solaris_x86_vtoc *)read_dev_sector(bdev, offset+1, &sect);
+ if (!v)
return;
- v = (struct solaris_x86_vtoc *)(bh->b_data + 512);
- if(le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {
- brelse(bh);
+ if (le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {
+ put_dev_sector(sect);
return;
}
printk(" %s: <solaris:", partition_name(hd, minor, buf));
- if(le32_to_cpu(v->v_version) != 1) {
+ if (le32_to_cpu(v->v_version) != 1) {
printk(" cannot handle version %d vtoc>\n",
le32_to_cpu(v->v_version));
- brelse(bh);
+ put_dev_sector(sect);
return;
}
- for(i=0; i<SOLARIS_X86_NUMSLICE; i++) {
- if ((current_minor & mask) == 0)
+ for (i=0; i<SOLARIS_X86_NUMSLICE; i++) {
+ if ((*current_minor & mask) == 0)
break;
s = &v->v_slice[i];
@@ -249,23 +246,25 @@ solaris_x86_partition(struct gendisk *hd, int minor) {
* one but add_gd_partition starts relative to sector
* zero of the disk. Therefore, must add the offset
* of the current partition */
- add_gd_partition(hd, current_minor, le32_to_cpu(s->s_start)+offset,
+ add_gd_partition(hd, *current_minor,
+ le32_to_cpu(s->s_start)+offset,
le32_to_cpu(s->s_size));
- current_minor++;
+ (*current_minor)++;
}
- brelse(bh);
+ put_dev_sector(sect);
printk(" >\n");
-}
#endif
+}
#ifdef CONFIG_BSD_DISKLABEL
static void
-check_and_add_bsd_partition(struct gendisk *hd,
- struct bsd_partition *bsd_p, int minor) {
+check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p,
+ int minor, int *current_minor)
+{
struct hd_struct *lin_p;
/* check relative position of partitions. */
for (lin_p = hd->part + 1 + minor;
- lin_p - hd->part - minor < current_minor; lin_p++) {
+ lin_p - hd->part - minor < *current_minor; lin_p++) {
/* no relationship -> try again */
if (lin_p->start_sect + lin_p->nr_sects <= le32_to_cpu(bsd_p->p_offset) ||
lin_p->start_sect >= le32_to_cpu(bsd_p->p_offset) + le32_to_cpu(bsd_p->p_size))
@@ -297,232 +296,290 @@ check_and_add_bsd_partition(struct gendisk *hd,
} /* if the bsd partition is not currently known to linux, we end
* up here
*/
- add_gd_partition(hd, current_minor, le32_to_cpu(bsd_p->p_offset),
+ add_gd_partition(hd, *current_minor, le32_to_cpu(bsd_p->p_offset),
le32_to_cpu(bsd_p->p_size));
- current_minor++;
+ (*current_minor)++;
}
/*
* Create devices for BSD partitions listed in a disklabel, under a
* dos-like partition. See extended_partition() for more information.
*/
-static void bsd_disklabel_partition(struct gendisk *hd, int minor, int type) {
- struct buffer_head *bh;
+static void do_bsd_partition(struct gendisk *hd, struct block_device *bdev,
+ int minor, int *current_minor, char *name, int max_partitions)
+{
+ long offset = hd->part[minor].start_sect;
+ Sector sect;
struct bsd_disklabel *l;
struct bsd_partition *p;
- int max_partitions;
int mask = (1 << hd->minor_shift) - 1;
char buf[40];
- if (!(bh = get_partition_table_block(hd, minor, 0)))
+ l = (struct bsd_disklabel *)read_dev_sector(bdev, offset+1, &sect);
+ if (!l)
return;
- l = (struct bsd_disklabel *) (bh->b_data+512);
if (le32_to_cpu(l->d_magic) != BSD_DISKMAGIC) {
- brelse(bh);
+ put_dev_sector(sect);
return;
}
- printk(" %s:", partition_name(hd, minor, buf));
- printk((type == OPENBSD_PARTITION) ? " <openbsd:" :
- (type == NETBSD_PARTITION) ? " <netbsd:" : " <bsd:");
+ printk(" %s: <%s", partition_name(hd, minor, buf), name);
- max_partitions = ((type == OPENBSD_PARTITION) ? OPENBSD_MAXPARTITIONS
- : BSD_MAXPARTITIONS);
if (le16_to_cpu(l->d_npartitions) < max_partitions)
max_partitions = le16_to_cpu(l->d_npartitions);
for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
- if ((current_minor & mask) == 0)
+ if ((*current_minor & mask) == 0)
break;
-
- if (p->p_fstype != BSD_FS_UNUSED)
- check_and_add_bsd_partition(hd, p, minor);
+ if (p->p_fstype == BSD_FS_UNUSED)
+ continue;
+ check_and_add_bsd_partition(hd, p, minor, current_minor);
}
+ put_dev_sector(sect);
+ printk(" >\n");
+}
+#endif
- /* Use bforget(), as we have changed the disk setup */
- bforget(bh);
+static void bsd_partition(struct gendisk *hd, struct block_device *bdev,
+ int minor, int *current_minor)
+{
+#ifdef CONFIG_BSD_DISKLABEL
+ do_bsd_partition(hd, bdev, minor, current_minor, "bsd",
+ BSD_MAXPARTITIONS);
+#endif
+}
- printk(" >\n");
+static void netbsd_partition(struct gendisk *hd, struct block_device *bdev,
+ int minor, int *current_minor)
+{
+#ifdef CONFIG_BSD_DISKLABEL
+ do_bsd_partition(hd, bdev, minor, current_minor, "netbsd",
+ BSD_MAXPARTITIONS);
+#endif
}
+
+static void openbsd_partition(struct gendisk *hd, struct block_device *bdev,
+ int minor, int *current_minor)
+{
+#ifdef CONFIG_BSD_DISKLABEL
+ do_bsd_partition(hd, bdev, minor, current_minor,
+ "openbsd", OPENBSD_MAXPARTITIONS);
#endif
+}
-#ifdef CONFIG_UNIXWARE_DISKLABEL
/*
* Create devices for Unixware partitions listed in a disklabel, under a
* dos-like partition. See extended_partition() for more information.
*/
-static void unixware_partition(struct gendisk *hd, int minor) {
- struct buffer_head *bh;
+static void unixware_partition(struct gendisk *hd, struct block_device *bdev,
+ int minor, int *current_minor)
+{
+#ifdef CONFIG_UNIXWARE_DISKLABEL
+ long offset = hd->part[minor].start_sect;
+ Sector sect;
struct unixware_disklabel *l;
struct unixware_slice *p;
int mask = (1 << hd->minor_shift) - 1;
char buf[40];
- if (!(bh = get_partition_table_block(hd, minor, 14)))
+ l = (struct unixware_disklabel *)read_dev_sector(bdev, offset+29, &sect);
+ if (!l)
return;
- l = (struct unixware_disklabel *) (bh->b_data+512);
if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
- brelse(bh);
+ put_dev_sector(sect);
return;
}
printk(" %s: <unixware:", partition_name(hd, minor, buf));
p = &l->vtoc.v_slice[1];
/* I omit the 0th slice as it is the same as whole disk. */
while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
- if ((current_minor & mask) == 0)
+ if ((*current_minor & mask) == 0)
break;
if (p->s_label != UNIXWARE_FS_UNUSED) {
- add_gd_partition(hd, current_minor, START_SECT(p),
+ add_gd_partition(hd, *current_minor, START_SECT(p),
NR_SECTS(p));
- current_minor++;
+ (*current_minor)++;
}
p++;
}
- /* Use bforget, as we have changed the disk setup */
- bforget(bh);
+ put_dev_sector(sect);
printk(" >\n");
-}
#endif
+}
-#ifdef CONFIG_MINIX_SUBPARTITION
/*
* Minix 2.0.0/2.0.2 subpartition support.
* Anand Krishnamurthy <anandk@wiproge.med.ge.com>
* Rajeev V. Pillai <rajeevvp@yahoo.com>
*/
-static void minix_partition(struct gendisk *hd, int minor)
+static void minix_partition(struct gendisk *hd, struct block_device *bdev,
+ int minor, int *current_minor)
{
- struct buffer_head *bh;
+#ifdef CONFIG_MINIX_SUBPARTITION
+ long offset = hd->part[minor].start_sect;
+ Sector sect;
+ unsigned char *data;
struct partition *p;
int mask = (1 << hd->minor_shift) - 1;
int i;
char buf[40];
- if (!(bh = get_partition_table_block(hd, minor, 0)))
+ data = read_dev_sector(bdev, offset, &sect);
+ if (!data)
return;
- bh->b_state = 0;
- p = (struct partition *)(bh->b_data + 0x1be);
+ p = (struct partition *)(data + 0x1be);
/* The first sector of a Minix partition can have either
* a secondary MBR describing its subpartitions, or
* the normal boot sector. */
- if (msdos_magic_present (bh->b_data + 510) &&
+ if (msdos_magic_present (data + 510) &&
SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */
printk(" %s: <minix:", partition_name(hd, minor, buf));
for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) {
- if ((current_minor & mask) == 0)
+ if ((*current_minor & mask) == 0)
break;
/* add each partition in use */
if (SYS_IND(p) == MINIX_PARTITION) {
- add_gd_partition(hd, current_minor,
+ add_gd_partition(hd, *current_minor,
START_SECT(p), NR_SECTS(p));
- current_minor++;
+ (*current_minor)++;
}
}
printk(" >\n");
}
- brelse(bh);
-}
+ put_dev_sector(sect);
#endif /* CONFIG_MINIX_SUBPARTITION */
-
-int msdos_partition(struct gendisk *hd, kdev_t dev,
- unsigned long first_sector, int first_part_minor) {
- int i, minor = current_minor = first_part_minor;
- struct buffer_head *bh;
- struct partition *p;
- unsigned char *data;
- int mask = (1 << hd->minor_shift) - 1;
- int sector_size = get_hardsect_size(dev) / 512;
-#ifdef CONFIG_BLK_DEV_IDE
- int tested_for_xlate = 0;
+}
-read_mbr:
-#endif /* CONFIG_BLK_DEV_IDE */
- if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
- if (warn_no_part) printk(" unable to read partition table\n");
- return -1;
- }
- data = bh->b_data;
+static struct {
+ unsigned char id;
+ void (*parse)(struct gendisk *, struct block_device *, int, int *);
+} subtypes[] = {
+ {BSD_PARTITION, bsd_partition},
+ {NETBSD_PARTITION, netbsd_partition},
+ {OPENBSD_PARTITION, openbsd_partition},
+ {MINIX_PARTITION, minix_partition},
+ {UNIXWARE_PARTITION, unixware_partition},
+ {SOLARIS_X86_PARTITION, solaris_x86_partition},
+ {0, NULL},
+};
+/*
+ * Look for various forms of IDE disk geometry translation
+ */
+static int handle_ide_mess(struct block_device *bdev)
+{
#ifdef CONFIG_BLK_DEV_IDE
-check_table:
-#endif /* CONFIG_BLK_DEV_IDE */
- /* Use bforget(), because we may have changed the disk geometry */
+ Sector sect;
+ unsigned char *data;
+ kdev_t dev = to_kdev_t(bdev->bd_dev);
+ unsigned int sig;
+ int heads = 0;
+ struct partition *p;
+ int i;
+ /*
+ * The i386 partition handling programs very often
+ * make partitions end on cylinder boundaries.
+ * There is no need to do so, and Linux fdisk doesnt always
+ * do this, and Windows NT on Alpha doesnt do this either,
+ * but still, this helps to guess #heads.
+ */
+ data = read_dev_sector(bdev, 0, &sect);
+ if (!data)
+ return -1;
if (!msdos_magic_present(data + 510)) {
- bforget(bh);
+ put_dev_sector(sect);
return 0;
}
+ sig = le16_to_cpu(*(unsigned short *)(data + 2));
p = (struct partition *) (data + 0x1be);
+ for (i = 0; i < 4; i++) {
+ struct partition *q = &p[i];
+ if (NR_SECTS(q)) {
+ if ((q->sector & 63) == 1 &&
+ (q->end_sector & 63) == 63)
+ heads = q->end_head + 1;
+ break;
+ }
+ }
+ if (SYS_IND(p) == EZD_PARTITION) {
+ /*
+ * Accesses to sector 0 must go to sector 1 instead.
+ */
+ if (ide_xlate_1024(dev, -1, heads, " [EZD]"))
+ goto reread;
+ } else if (SYS_IND(p) == DM6_PARTITION) {
-#ifdef CONFIG_BLK_DEV_IDE
- if (!tested_for_xlate++) { /* Do this only once per disk */
/*
- * Look for various forms of IDE disk geometry translation
+ * Everything on the disk is offset by 63 sectors,
+ * including a "new" MBR with its own partition table.
*/
- unsigned int sig = le16_to_cpu(*(unsigned short *)(data + 2));
- int heads = 0;
+ if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]"))
+ goto reread;
+ } else if (sig <= 0x1ae &&
+ data[sig] == 0xAA && data[sig+1] == 0x55 &&
+ (data[sig+2] & 1)) {
+ /* DM6 signature in MBR, courtesy of OnTrack */
+ (void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]");
+ } else if (SYS_IND(p) == DM6_AUX1PARTITION ||
+ SYS_IND(p) == DM6_AUX3PARTITION) {
/*
- * The i386 partition handling programs very often
- * make partitions end on cylinder boundaries.
- * There is no need to do so, and Linux fdisk doesnt always
- * do this, and Windows NT on Alpha doesnt do this either,
- * but still, this helps to guess #heads.
+ * DM6 on other than the first (boot) drive
*/
- for (i = 0; i < 4; i++) {
- struct partition *q = &p[i];
- if (NR_SECTS(q)) {
- if ((q->sector & 63) == 1 &&
- (q->end_sector & 63) == 63)
- heads = q->end_head + 1;
- break;
- }
- }
- if (SYS_IND(p) == EZD_PARTITION) {
- /*
- * Accesses to sector 0 must go to sector 1 instead.
- */
- if (ide_xlate_1024(dev, -1, heads, " [EZD]")) {
- data += 512;
- goto check_table;
- }
- } else if (SYS_IND(p) == DM6_PARTITION) {
-
- /*
- * Everything on the disk is offset by 63 sectors,
- * including a "new" MBR with its own partition table.
- */
- if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]")) {
- bforget(bh);
- goto read_mbr; /* start over with new MBR */
- }
- } else if (sig <= 0x1ae &&
- data[sig] == 0xAA && data[sig+1] == 0x55 &&
- (data[sig+2] & 1)) {
- /* DM6 signature in MBR, courtesy of OnTrack */
- (void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]");
- } else if (SYS_IND(p) == DM6_AUX1PARTITION ||
- SYS_IND(p) == DM6_AUX3PARTITION) {
- /*
- * DM6 on other than the first (boot) drive
- */
- (void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]");
- } else {
- (void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
- }
+ (void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]");
+ } else {
+ (void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
}
+ put_dev_sector(sect);
+ return 1;
+
+reread:
+ put_dev_sector(sect);
+ /* Flush the cache */
+ invalidate_bdev(bdev, 1);
+ truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
#endif /* CONFIG_BLK_DEV_IDE */
+ return 1;
+}
+
+int msdos_partition(struct gendisk *hd, struct block_device *bdev,
+ unsigned long first_sector, int first_part_minor)
+{
+ int i, minor = first_part_minor;
+ Sector sect;
+ struct partition *p;
+ unsigned char *data;
+ int mask = (1 << hd->minor_shift) - 1;
+ int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
+ int current_minor = first_part_minor;
+ int err;
+
+ err = handle_ide_mess(bdev);
+ if (err <= 0)
+ return err;
+ data = read_dev_sector(bdev, 0, &sect);
+ if (!data)
+ return -1;
+ if (!msdos_magic_present(data + 510)) {
+ put_dev_sector(sect);
+ return 0;
+ }
+ p = (struct partition *) (data + 0x1be);
- /* Look for partitions in two passes:
- First find the primary partitions, and the DOS-type extended partitions.
- On the second pass look inside *BSD and Unixware and Solaris partitions. */
+ /*
+ * Look for partitions in two passes:
+ * First find the primary and DOS-type extended partitions.
+ * On the second pass look inside *BSD, Unixware and Solaris partitions.
+ */
- current_minor += 4; /* first "extra" minor (for extended partitions) */
+ current_minor += 4;
for (i=1 ; i<=4 ; minor++,i++,p++) {
if (!NR_SECTS(p))
continue;
- add_gd_partition(hd, minor, first_sector+START_SECT(p)*sector_size,
- NR_SECTS(p)*sector_size);
+ add_gd_partition(hd, minor,
+ first_sector+START_SECT(p)*sector_size,
+ NR_SECTS(p)*sector_size);
#if CONFIG_BLK_DEV_MD
if (SYS_IND(p) == LINUX_RAID_PARTITION) {
md_autodetect_dev(MKDEV(hd->major,minor));
@@ -530,20 +587,12 @@ check_table:
#endif
if (is_extended_partition(p)) {
printk(" <");
- /*
- * If we are rereading the partition table, we need
- * to set the size of the partition so that we will
- * be able to bread the block containing the extended
- * partition info.
- */
- hd->sizes[minor] = hd->part[minor].nr_sects
- >> (BLOCK_SIZE_BITS - 9);
- extended_partition(hd, MKDEV(hd->major, minor));
- printk(" >");
/* prevent someone doing mkfs or mkswap on an
extended partition, but leave room for LILO */
if (hd->part[minor].nr_sects > 2)
hd->part[minor].nr_sects = 2;
+ extended_partition(hd, bdev, minor, &current_minor);
+ printk(" >");
}
}
@@ -567,29 +616,18 @@ check_table:
minor -= 4;
p = (struct partition *) (0x1be + data);
for (i=1 ; i<=4 ; minor++,i++,p++) {
+ unsigned char id = SYS_IND(p);
+ int n;
+
if (!NR_SECTS(p))
continue;
-#ifdef CONFIG_BSD_DISKLABEL
- if (SYS_IND(p) == BSD_PARTITION ||
- SYS_IND(p) == NETBSD_PARTITION ||
- SYS_IND(p) == OPENBSD_PARTITION)
- bsd_disklabel_partition(hd, minor, SYS_IND(p));
-#endif
-#ifdef CONFIG_MINIX_SUBPARTITION
- if (SYS_IND(p) == MINIX_PARTITION) {
- minix_partition(hd, minor);
- }
-#endif
-#ifdef CONFIG_UNIXWARE_DISKLABEL
- if (SYS_IND(p) == UNIXWARE_PARTITION)
- unixware_partition(hd, minor);
-#endif
-#ifdef CONFIG_SOLARIS_X86_PARTITION
- if(SYS_IND(p) == SOLARIS_X86_PARTITION)
- solaris_x86_partition(hd, minor);
-#endif
- }
- bforget(bh);
+ for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
+ ;
+
+ if (subtypes[n].parse)
+ subtypes[n].parse(hd, bdev, minor, &current_minor);
+ }
+ put_dev_sector(sect);
return 1;
}
diff --git a/fs/partitions/msdos.h b/fs/partitions/msdos.h
index e24740c5e031..09c8b095ad56 100644
--- a/fs/partitions/msdos.h
+++ b/fs/partitions/msdos.h
@@ -4,6 +4,6 @@
#define MSDOS_LABEL_MAGIC 0xAA55
-int msdos_partition(struct gendisk *hd, kdev_t dev,
+int msdos_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor);
diff --git a/fs/partitions/osf.c b/fs/partitions/osf.c
index 52aae3bbd6ba..e178ca2b6543 100644
--- a/fs/partitions/osf.c
+++ b/fs/partitions/osf.c
@@ -17,12 +17,13 @@
#include "check.h"
#include "osf.h"
-int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
- int current_minor)
+int osf_partition(struct gendisk *hd, struct block_device *bdev,
+ unsigned long first_sector, int current_minor)
{
int i;
+ Sector sect;
+ unsigned char *data;
int mask = (1 << hd->minor_shift) - 1;
- struct buffer_head *bh;
struct disklabel {
u32 d_magic;
u16 d_type,d_subtype;
@@ -56,18 +57,18 @@ int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
} * label;
struct d_partition * partition;
- if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
- if (warn_no_part) printk("unable to read partition table\n");
+ data = read_dev_sector(bdev, 0, &sect);
+ if (!data)
return -1;
- }
- label = (struct disklabel *) (bh->b_data+64);
+
+ label = (struct disklabel *) (data+64);
partition = label->d_partitions;
if (le32_to_cpu(label->d_magic) != DISKLABELMAGIC) {
- brelse(bh);
+ put_dev_sector(sect);
return 0;
}
if (le32_to_cpu(label->d_magic2) != DISKLABELMAGIC) {
- brelse(bh);
+ put_dev_sector(sect);
return 0;
}
for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) {
@@ -80,7 +81,7 @@ int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
current_minor++;
}
printk("\n");
- brelse(bh);
+ put_dev_sector(sect);
return 1;
}
diff --git a/fs/partitions/osf.h b/fs/partitions/osf.h
index ce14150565b9..6f02393c490b 100644
--- a/fs/partitions/osf.h
+++ b/fs/partitions/osf.h
@@ -4,6 +4,6 @@
#define DISKLABELMAGIC (0x82564557UL)
-int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector,
- int current_minor);
+int osf_partition(struct gendisk *hd, struct block_device *bdev,
+ unsigned long first_sector, int current_minor);
diff --git a/fs/partitions/sgi.c b/fs/partitions/sgi.c
index 3806b5f31afb..ea74ebb4b57b 100644
--- a/fs/partitions/sgi.c
+++ b/fs/partitions/sgi.c
@@ -17,11 +17,12 @@
#include "check.h"
#include "sgi.h"
-int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int current_minor)
+int sgi_partition(struct gendisk *hd, struct block_device *bdev, unsigned long first_sector, int current_minor)
{
int i, csum, magic;
unsigned int *ui, start, blocks, cs;
- struct buffer_head *bh;
+ Sector sect;
+ kdev_t dev = to_kdev_t(bdev->bd_dev);
struct sgi_disklabel {
int magic_mushroom; /* Big fat spliff... */
short root_part_num; /* Root partition number */
@@ -43,17 +44,15 @@ int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, in
} *label;
struct sgi_partition *p;
- if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
- if (warn_no_part) printk(KERN_WARNING "Dev %s: unable to read partition table\n", kdevname(dev));
+ label = (struct sgi_disklabel *) read_dev_sector(bdev, 0, &sect);
+ if (!label)
return -1;
- }
- label = (struct sgi_disklabel *) bh->b_data;
p = &label->partitions[0];
magic = label->magic_mushroom;
if(be32_to_cpu(magic) != SGI_LABEL_MAGIC) {
/*printk("Dev %s SGI disklabel: bad magic %08x\n",
- kdevname(dev), magic);*/
- brelse(bh);
+ bdevname(dev), magic);*/
+ put_dev_sector(sect);
return 0;
}
ui = ((unsigned int *) (label + 1)) - 1;
@@ -63,8 +62,8 @@ int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, in
}
if(csum) {
printk(KERN_WARNING "Dev %s SGI disklabel: csum bad, label corrupted\n",
- kdevname(dev));
- brelse(bh);
+ bdevname(dev));
+ put_dev_sector(sect);
return 0;
}
/* All SGI disk labels have 16 partitions, disks under Linux only
@@ -81,6 +80,6 @@ int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, in
current_minor++;
}
printk("\n");
- brelse(bh);
+ put_dev_sector(sect);
return 1;
}
diff --git a/fs/partitions/sgi.h b/fs/partitions/sgi.h
index 6e4ac1ac488f..55840d9285e5 100644
--- a/fs/partitions/sgi.h
+++ b/fs/partitions/sgi.h
@@ -2,7 +2,7 @@
* fs/partitions/sgi.h
*/
-extern int sgi_partition(struct gendisk *hd, kdev_t dev,
+extern int sgi_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor);
#define SGI_LABEL_MAGIC 0x0be5a941
diff --git a/fs/partitions/sun.c b/fs/partitions/sun.c
index f48bc5cd8c5c..bee5abb6537b 100644
--- a/fs/partitions/sun.c
+++ b/fs/partitions/sun.c
@@ -19,11 +19,12 @@
#include "check.h"
#include "sun.h"
-int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
+int sun_partition(struct gendisk *hd, struct block_device *bdev, unsigned long first_sector, int first_part_minor)
{
int i, csum;
unsigned short *ush;
- struct buffer_head *bh;
+ Sector sect;
+ kdev_t dev = to_kdev_t(bdev->bd_dev);
struct sun_disklabel {
unsigned char info[128]; /* Informative text string */
unsigned char spare[292]; /* Boot information etc. */
@@ -47,27 +48,25 @@ int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, in
struct sun_partition *p;
unsigned long spc;
- if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
- if (warn_no_part) printk(KERN_WARNING "Dev %s: unable to read partition table\n",
- kdevname(dev));
+ label = (struct sun_disklabel *)read_dev_sector(bdev, 0, &sect);
+ if (!label)
return -1;
- }
- label = (struct sun_disklabel *) bh->b_data;
+
p = label->partitions;
if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) {
/* printk(KERN_INFO "Dev %s Sun disklabel: bad magic %04x\n",
- kdevname(dev), be16_to_cpu(label->magic)); */
- brelse(bh);
+ bdevname(dev), be16_to_cpu(label->magic)); */
+ put_dev_sector(sect);
return 0;
}
/* Look at the checksum */
ush = ((unsigned short *) (label+1)) - 1;
- for(csum = 0; ush >= ((unsigned short *) label);)
+ for (csum = 0; ush >= ((unsigned short *) label);)
csum ^= *ush--;
if(csum) {
printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
- kdevname(dev));
- brelse(bh);
+ bdevname(dev));
+ put_dev_sector(sect);
return 0;
}
/* All Sun disks have 8 partition entries */
@@ -83,7 +82,6 @@ int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, in
first_part_minor++;
}
printk("\n");
- brelse(bh);
+ put_dev_sector(sect);
return 1;
}
-
diff --git a/fs/partitions/sun.h b/fs/partitions/sun.h
index 3426d4aa29fc..ae2f9579ef87 100644
--- a/fs/partitions/sun.h
+++ b/fs/partitions/sun.h
@@ -4,6 +4,6 @@
#define SUN_LABEL_MAGIC 0xDABE
-int sun_partition(struct gendisk *hd, kdev_t dev,
+int sun_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor);
diff --git a/fs/partitions/ultrix.c b/fs/partitions/ultrix.c
index aa49ba517fd8..a7e0629dd2da 100644
--- a/fs/partitions/ultrix.c
+++ b/fs/partitions/ultrix.c
@@ -14,11 +14,12 @@
#include "check.h"
-int ultrix_partition(struct gendisk *hd, kdev_t dev,
+int ultrix_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor)
{
int i;
- struct buffer_head *bh;
+ Sector sect;
+ unsigned char *data;
struct ultrix_disklabel {
s32 pt_magic; /* magic no. indicating part. info exits */
s32 pt_valid; /* set by driver if pt is current */
@@ -31,18 +32,11 @@ int ultrix_partition(struct gendisk *hd, kdev_t dev,
#define PT_MAGIC 0x032957 /* Partition magic number */
#define PT_VALID 1 /* Indicates if struct is valid */
-#define SBLOCK ((unsigned long)((16384 - sizeof(struct ultrix_disklabel)) \
- /get_ptable_blocksize(dev)))
-
- bh = bread (dev, SBLOCK, get_ptable_blocksize(dev));
- if (!bh) {
- if (warn_no_part) printk (" unable to read block 0x%lx\n", SBLOCK);
+ data = read_dev_sector(bdev, (16384 - sizeof(*label))/512, &sect);
+ if (!data)
return -1;
- }
- label = (struct ultrix_disklabel *)(bh->b_data
- + get_ptable_blocksize(dev)
- - sizeof(struct ultrix_disklabel));
+ label = (struct ultrix_disklabel *)(data + 512 - sizeof(*label));
if (label->pt_magic == PT_MAGIC && label->pt_valid == PT_VALID) {
for (i=0; i<8; i++, first_part_minor++)
@@ -50,11 +44,11 @@ int ultrix_partition(struct gendisk *hd, kdev_t dev,
add_gd_partition(hd, first_part_minor,
label->pt_part[i].pi_blkoff,
label->pt_part[i].pi_nblocks);
- brelse(bh);
+ put_dev_sector(sect);
printk ("\n");
return 1;
} else {
- brelse(bh);
+ put_dev_sector(sect);
return 0;
}
}
diff --git a/fs/partitions/ultrix.h b/fs/partitions/ultrix.h
index d2259db3e917..1572c90d90be 100644
--- a/fs/partitions/ultrix.h
+++ b/fs/partitions/ultrix.h
@@ -2,6 +2,6 @@
* fs/partitions/ultrix.h
*/
-int ultrix_partition(struct gendisk *hd, kdev_t dev,
+int ultrix_partition(struct gendisk *hd, struct block_device *bdev,
unsigned long first_sector, int first_part_minor);
diff --git a/fs/smbfs/ChangeLog b/fs/smbfs/ChangeLog
index cf9e3ffc5c67..63ecf3d06caf 100644
--- a/fs/smbfs/ChangeLog
+++ b/fs/smbfs/ChangeLog
@@ -1,5 +1,30 @@
ChangeLog for smbfs.
+2001-09-17 Urban Widmark <urban@teststation.com>
+
+ * proc.c: Use 4096 (was 512) as the blocksize for better write
+ performance (patch originally by Jan Kratochvil)
+ * proc.c: Skip disconnect smb, allows umount on unreachable servers.
+ * proc.c: Go back to the interruptible sleep as reconnects seem to
+ handle it now.
+ * *.c: use autogenerated and private proto.h
+
+2000-11-22 Igor Zhbanov <bsg@uniyar.ac.ru>
+
+ * proc.c: fixed date_unix2dos for dates earlier than 01/01/1980
+ and date_dos2unix for date==0 (from 2.2)
+
+2001-07-13 Rob Radez <rob@osinvestor.com>
+
+ * proc.c: make smb_errno return negative error values
+
+2001-07-09 Jochen Dolze <dolze@epcnet.de>
+
+ * inode.c: smb_statfs always returned success.
+ * proc.c, ioctl.c: Allow smbmount to signal failure to reconnect with
+ a NULL argument to SMB_IOC_NEWCONN (speeds up error detection).
+ * proc.c: Add some of the missing error codes to smb_errno
+
2001-06-12 Urban Widmark <urban@teststation.com>
* proc.c: replace the win95-flush fix with smb_seek, when needed.
diff --git a/fs/smbfs/Makefile b/fs/smbfs/Makefile
index 16e8ceb15d5a..93ddc0df84f2 100644
--- a/fs/smbfs/Makefile
+++ b/fs/smbfs/Makefile
@@ -23,3 +23,19 @@ EXTRA_CFLAGS += -DSMBFS_PARANOIA
#EXTRA_CFLAGS += -Werror
include $(TOPDIR)/Rules.make
+
+#
+# Maintainer rules
+#
+
+# getopt.c not included. It is intentionally separate
+SRC = proc.c dir.c cache.c sock.c inode.c file.c ioctl.c
+
+proto:
+ -rm -f proto.h
+ @echo > proto2.h "/*"
+ @echo >> proto2.h " * Autogenerated with cproto on: " `date`
+ @echo >> proto2.h " */"
+ @echo >> proto2.h ""
+ cproto -E "gcc -E" -e -v -I $(TOPDIR)/include -DMAKING_PROTO -D__KERNEL__ $(SRC) >> proto2.h
+ mv proto2.h proto.h
diff --git a/fs/smbfs/cache.c b/fs/smbfs/cache.c
index 3dc17d2292e3..3e98f83ab19f 100644
--- a/fs/smbfs/cache.c
+++ b/fs/smbfs/cache.c
@@ -20,6 +20,7 @@
#include <asm/page.h>
#include "smb_debug.h"
+#include "proto.h"
/*
* Force the next attempt to use the cache to be a timeout.
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index 48d716c9e3a8..5696c8e2fbe7 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -18,6 +18,7 @@
#include <linux/smbno.h>
#include "smb_debug.h"
+#include "proto.h"
static int smb_readdir(struct file *, void *, filldir_t);
static int smb_dir_open(struct inode *, struct file *);
@@ -452,8 +453,7 @@ smb_instantiate(struct dentry *dentry, __u16 fileid, int have_id)
if (!inode)
goto out_no_inode;
- if (have_id)
- {
+ if (have_id) {
inode->u.smbfs_i.fileid = fileid;
inode->u.smbfs_i.access = SMB_O_RDWR;
inode->u.smbfs_i.open = server->generation;
@@ -465,8 +465,7 @@ out:
out_no_inode:
error = -EACCES;
out_close:
- if (have_id)
- {
+ if (have_id) {
PARANOIA("%s/%s failed, error=%d, closing %u\n",
DENTRY_PATH(dentry), error, fileid);
smb_close_fileid(dentry, fileid);
@@ -562,12 +561,10 @@ smb_rename(struct inode *old_dir, struct dentry *old_dentry,
*/
if (old_dentry->d_inode)
smb_close(old_dentry->d_inode);
- if (new_dentry->d_inode)
- {
+ if (new_dentry->d_inode) {
smb_close(new_dentry->d_inode);
error = smb_proc_unlink(new_dentry);
- if (error)
- {
+ if (error) {
VERBOSE("unlink %s/%s, error=%d\n",
DENTRY_PATH(new_dentry), error);
goto out;
@@ -579,8 +576,7 @@ smb_rename(struct inode *old_dir, struct dentry *old_dentry,
smb_invalid_dir_cache(old_dir);
smb_invalid_dir_cache(new_dir);
error = smb_proc_mv(old_dentry, new_dentry);
- if (!error)
- {
+ if (!error) {
smb_renew_times(old_dentry);
smb_renew_times(new_dentry);
}
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index 189828846025..d74e32ad6bf5 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -24,6 +24,7 @@
#include <linux/smb_fs.h>
#include "smb_debug.h"
+#include "proto.h"
static int
smb_fsync(struct file *file, struct dentry * dentry, int datasync)
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 348e5acad771..9f5921c18fb5 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -32,6 +32,7 @@
#include "smb_debug.h"
#include "getopt.h"
+#include "proto.h"
/* Always pick a default string */
#ifdef CONFIG_SMB_NLS_REMOTE
@@ -259,7 +260,7 @@ smb_delete_inode(struct inode *ino)
}
/* FIXME: flags and has_arg could probably be merged. */
-struct option opts[] = {
+static struct option opts[] = {
{ "version", 1, 0, 'v' },
{ "win95", 0, SMB_MOUNT_WIN95, 1 },
{ "oldattr", 0, SMB_MOUNT_OLDATTR, 1 },
@@ -344,7 +345,6 @@ smb_put_super(struct super_block *sb)
struct smb_sb_info *server = &(sb->u.smbfs_sb);
if (server->sock_file) {
- smb_proc_disconnect(server);
smb_dont_catch_keepalive(server);
fput(server->sock_file);
}
@@ -353,23 +353,24 @@ smb_put_super(struct super_block *sb)
kill_proc(server->conn_pid, SIGTERM, 1);
smb_kfree(server->mnt);
- smb_kfree(sb->u.smbfs_sb.temp_buf);
+ smb_kfree(server->temp_buf);
if (server->packet)
smb_vfree(server->packet);
- if(sb->u.smbfs_sb.remote_nls) {
- unload_nls(sb->u.smbfs_sb.remote_nls);
- sb->u.smbfs_sb.remote_nls = NULL;
+ if (server->remote_nls) {
+ unload_nls(server->remote_nls);
+ server->remote_nls = NULL;
}
- if(sb->u.smbfs_sb.local_nls) {
- unload_nls(sb->u.smbfs_sb.local_nls);
- sb->u.smbfs_sb.local_nls = NULL;
+ if (server->local_nls) {
+ unload_nls(server->local_nls);
+ server->local_nls = NULL;
}
}
struct super_block *
smb_read_super(struct super_block *sb, void *raw_data, int silent)
{
+ struct smb_sb_info *server = &sb->u.smbfs_sb;
struct smb_mount_data_kernel *mnt;
struct smb_mount_data *oldmnt;
struct inode *root_inode;
@@ -389,34 +390,34 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
sb->s_magic = SMB_SUPER_MAGIC;
sb->s_op = &smb_sops;
- sb->u.smbfs_sb.mnt = NULL;
- sb->u.smbfs_sb.sock_file = NULL;
- init_MUTEX(&sb->u.smbfs_sb.sem);
- init_waitqueue_head(&sb->u.smbfs_sb.wait);
- sb->u.smbfs_sb.conn_pid = 0;
- sb->u.smbfs_sb.state = CONN_INVALID; /* no connection yet */
- sb->u.smbfs_sb.generation = 0;
- sb->u.smbfs_sb.packet_size = smb_round_length(SMB_INITIAL_PACKET_SIZE);
- sb->u.smbfs_sb.packet = smb_vmalloc(sb->u.smbfs_sb.packet_size);
- if (!sb->u.smbfs_sb.packet)
+ server->mnt = NULL;
+ server->sock_file = NULL;
+ init_MUTEX(&server->sem);
+ init_waitqueue_head(&server->wait);
+ server->conn_pid = 0;
+ server->state = CONN_INVALID; /* no connection yet */
+ server->generation = 0;
+ server->packet_size = smb_round_length(SMB_INITIAL_PACKET_SIZE);
+ server->packet = smb_vmalloc(server->packet_size);
+ if (!server->packet)
goto out_no_mem;
/* Allocate the global temp buffer */
- sb->u.smbfs_sb.temp_buf = smb_kmalloc(2*SMB_MAXPATHLEN+20, GFP_KERNEL);
- if (!sb->u.smbfs_sb.temp_buf)
+ server->temp_buf = smb_kmalloc(2*SMB_MAXPATHLEN+20, GFP_KERNEL);
+ if (!server->temp_buf)
goto out_no_temp;
/* Setup NLS stuff */
- sb->u.smbfs_sb.remote_nls = NULL;
- sb->u.smbfs_sb.local_nls = NULL;
- sb->u.smbfs_sb.name_buf = sb->u.smbfs_sb.temp_buf + SMB_MAXPATHLEN + 20;
+ server->remote_nls = NULL;
+ server->local_nls = NULL;
+ server->name_buf = server->temp_buf + SMB_MAXPATHLEN + 20;
/* Allocate the mount data structure */
/* FIXME: merge this with the other malloc and get a whole page? */
mnt = smb_kmalloc(sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
if (!mnt)
goto out_no_mount;
- sb->u.smbfs_sb.mnt = mnt;
+ server->mnt = mnt;
memset(mnt, 0, sizeof(struct smb_mount_data_kernel));
strncpy(mnt->codepage.local_name, CONFIG_NLS_DEFAULT,
@@ -447,9 +448,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
mnt->mounted_uid = current->uid;
}
- smb_setcodepage(&sb->u.smbfs_sb, &mnt->codepage);
- if (!sb->u.smbfs_sb.convert)
- PARANOIA("convert funcptr was NULL!\n");
+ smb_setcodepage(server, &mnt->codepage);
/*
* Display the enabled options
@@ -463,7 +462,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
/*
* Keep the super block locked while we get the root inode.
*/
- smb_init_root_dirent(&(sb->u.smbfs_sb), &root);
+ smb_init_root_dirent(server, &root);
root_inode = smb_iget(sb, &root);
if (!root_inode)
goto out_no_root;
@@ -478,13 +477,13 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
out_no_root:
iput(root_inode);
out_bad_option:
- smb_kfree(sb->u.smbfs_sb.mnt);
+ smb_kfree(server->mnt);
out_no_mount:
- smb_kfree(sb->u.smbfs_sb.temp_buf);
+ smb_kfree(server->temp_buf);
out_no_temp:
- smb_vfree(sb->u.smbfs_sb.packet);
+ smb_vfree(server->packet);
out_no_mem:
- if (!sb->u.smbfs_sb.mnt)
+ if (!server->mnt)
printk(KERN_ERR "smb_read_super: allocation failure\n");
goto out_fail;
out_wrong_data:
@@ -499,11 +498,11 @@ out_fail:
static int
smb_statfs(struct super_block *sb, struct statfs *buf)
{
- smb_proc_dskattr(sb, buf);
+ int result = smb_proc_dskattr(sb, buf);
buf->f_type = SMB_SUPER_MAGIC;
buf->f_namelen = SMB_MAXPATHLEN;
- return 0;
+ return result;
}
int
@@ -532,8 +531,7 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr)
if ((attr->ia_valid & ATTR_MODE) && (attr->ia_mode & ~mask))
goto out;
- if ((attr->ia_valid & ATTR_SIZE) != 0)
- {
+ if ((attr->ia_valid & ATTR_SIZE) != 0) {
VERBOSE("changing %s/%s, old size=%ld, new size=%ld\n",
DENTRY_PATH(dentry),
(long) inode->i_size, (long) attr->ia_size);
@@ -558,20 +556,17 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr)
smb_get_inode_attr(inode, &fattr);
changed = 0;
- if ((attr->ia_valid & ATTR_MTIME) != 0)
- {
+ if ((attr->ia_valid & ATTR_MTIME) != 0) {
fattr.f_mtime = attr->ia_mtime;
changed = 1;
}
- if ((attr->ia_valid & ATTR_ATIME) != 0)
- {
+ if ((attr->ia_valid & ATTR_ATIME) != 0) {
fattr.f_atime = attr->ia_atime;
/* Earlier protocols don't have an access time */
if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
changed = 1;
}
- if (changed)
- {
+ if (changed) {
error = smb_proc_settime(dentry, &fattr);
if (error)
goto out;
@@ -582,27 +577,22 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr)
* Check for mode changes ... we're extremely limited in
* what can be set for SMB servers: just the read-only bit.
*/
- if ((attr->ia_valid & ATTR_MODE) != 0)
- {
+ if ((attr->ia_valid & ATTR_MODE) != 0) {
VERBOSE("%s/%s mode change, old=%x, new=%x\n",
DENTRY_PATH(dentry), fattr.f_mode, attr->ia_mode);
changed = 0;
- if (attr->ia_mode & S_IWUSR)
- {
- if (fattr.attr & aRONLY)
- {
+ if (attr->ia_mode & S_IWUSR) {
+ if (fattr.attr & aRONLY) {
fattr.attr &= ~aRONLY;
changed = 1;
}
} else {
- if (!(fattr.attr & aRONLY))
- {
+ if (!(fattr.attr & aRONLY)) {
fattr.attr |= aRONLY;
changed = 1;
}
}
- if (changed)
- {
+ if (changed) {
error = smb_proc_setattr(dentry, &fattr);
if (error)
goto out;
diff --git a/fs/smbfs/ioctl.c b/fs/smbfs/ioctl.c
index 285c25b039aa..afc45b4f7fd9 100644
--- a/fs/smbfs/ioctl.c
+++ b/fs/smbfs/ioctl.c
@@ -19,6 +19,8 @@
#include <asm/uaccess.h>
+#include "proto.h"
+
int
smb_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
@@ -37,9 +39,11 @@ smb_ioctl(struct inode *inode, struct file *filp,
break;
case SMB_IOC_NEWCONN:
- /* require an argument == smb_conn_opt, else it is EINVAL */
- if (!arg)
+ /* arg is smb_conn_opt, or NULL if no connection was made */
+ if (!arg) {
+ result = smb_wakeup(server);
break;
+ }
result = -EFAULT;
if (!copy_from_user(&opt, (void *)arg, sizeof(opt)))
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index c075b7aa4973..27ec4c40a70b 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -23,16 +23,18 @@
#include <linux/smb_mount.h>
#include <asm/string.h>
+#include <asm/div64.h>
#include "smb_debug.h"
+#include "proto.h"
/* Features. Undefine if they cause problems, this should perhaps be a
config option. */
#define SMBFS_POSIX_UNLINK 1
-/* Allow smb_retry to be interrupted. Not sure of the benefit ... */
-/* #define SMB_RETRY_INTR */
+/* Allow smb_retry to be interrupted. */
+#define SMB_RETRY_INTR
#define SMB_VWV(packet) ((packet) + SMB_HEADER_LEN)
#define SMB_CMD(packet) (*(packet+8))
@@ -43,6 +45,9 @@
#define SMB_DIRINFO_SIZE 43
#define SMB_STATUS_SIZE 21
+#define SMB_ST_BLKSIZE (PAGE_SIZE)
+#define SMB_ST_BLKSHIFT (PAGE_SHIFT)
+
static int
smb_proc_setattr_ext(struct smb_sb_info *, struct inode *,
struct smb_fattr *);
@@ -137,8 +142,7 @@ out:
return len;
}
-static int setcodepage(struct smb_sb_info *server,
- struct nls_table **p, char *name)
+static int setcodepage(struct nls_table **p, char *name)
{
struct nls_table *nls;
@@ -160,16 +164,20 @@ static int setcodepage(struct smb_sb_info *server,
/* Handles all changes to codepage settings. */
int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp)
{
- int n;
+ int n = 0;
smb_lock_server(server);
- n = setcodepage(server, &server->local_nls, cp->local_name);
+ /* Don't load any nls_* at all, if no remote is requested */
+ if (!*cp->remote_name)
+ goto out;
+
+ n = setcodepage(&server->local_nls, cp->local_name);
if (n != 0)
goto out;
- n = setcodepage(server, &server->remote_nls, cp->remote_name);
+ n = setcodepage(&server->remote_nls, cp->remote_name);
if (n != 0)
- setcodepage(server, &server->local_nls, NULL);
+ setcodepage(&server->local_nls, NULL);
out:
if (server->local_nls != NULL && server->remote_nls != NULL)
@@ -188,7 +196,7 @@ out:
/* */
/*****************************************************************************/
-__u8 *
+static __u8 *
smb_encode_smb_length(__u8 * p, __u32 len)
{
*p = 0;
@@ -308,7 +316,9 @@ date_dos2unix(struct smb_sb_info *server, __u16 date, __u16 time)
int month, year;
time_t secs;
- month = ((date >> 5) & 15) - 1;
+ /* first subtract and mask after that... Otherwise, if
+ date == 0, bad things happen */
+ month = ((date >> 5) - 1) & 15;
year = date >> 9;
secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 86400 *
((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 - ((year & 3) == 0 &&
@@ -327,6 +337,9 @@ date_unix2dos(struct smb_sb_info *server,
int day, year, nl_day, month;
unix_date = utc2local(server, unix_date);
+ if (unix_date < 315532800)
+ unix_date = 315532800;
+
*time = (unix_date % 60) / 2 +
(((unix_date / 60) % 60) << 5) +
(((unix_date / 3600) % 24) << 11);
@@ -350,57 +363,20 @@ date_unix2dos(struct smb_sb_info *server,
/* The following are taken from fs/ntfs/util.c */
+#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
+
/*
* Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
* into Unix UTC (based 1970-01-01, in seconds).
- *
- * This is very gross because
- * 1: We must do 64-bit division on a 32-bit machine
- * 2: We can't use libgcc for long long operations in the kernel
- * 3: Floating point math in the kernel would corrupt user data
*/
static time_t
-smb_ntutc2unixutc(struct smb_sb_info *server, u64 ntutc)
+smb_ntutc2unixutc(u64 ntutc)
{
- const unsigned int D = 10000000;
- unsigned int H = (unsigned int)(ntutc >> 32);
- unsigned int L = (unsigned int)ntutc;
- unsigned int numerator2;
- unsigned int lowseconds;
- unsigned int result;
-
- /*
- * It is best to subtract 0x019db1ded53e8000 first.
- * Then the 1601-based date becomes a 1970-based date.
- */
- if (L < (unsigned)0xd53e8000) H--;
- L -= (unsigned)0xd53e8000;
- H -= (unsigned)0x019db1de;
-
- /*
- * Now divide 64-bit numbers on a 32-bit machine :-)
- * With the subtraction already done, the result fits in 32 bits.
- * The numerator fits in 56 bits and the denominator fits
- * in 24 bits, so we can shift by 8 bits to make this work.
- */
-
- numerator2 = (H<<8) | (L>>24);
- result = (numerator2 / D); /* shifted 24 right!! */
- lowseconds = result << 24;
-
- numerator2 = ((numerator2-result*D)<<8) | ((L>>16)&0xff);
- result = (numerator2 / D); /* shifted 16 right!! */
- lowseconds |= result << 16;
-
- numerator2 = ((numerator2-result*D)<<8) | ((L>>8)&0xff);
- result = (numerator2 / D); /* shifted 8 right!! */
- lowseconds |= result << 8;
-
- numerator2 = ((numerator2-result*D)<<8) | (L&0xff);
- result = (numerator2 / D); /* not shifted */
- lowseconds |= result;
-
- return lowseconds;
+ /* FIXME: what about the timezone difference? */
+ /* Subtract the NTFS time offset, then convert to 1s intervals. */
+ u64 t = ntutc - NTFS_TIME_OFFSET;
+ do_div(t, 10000000);
+ return (time_t)t;
}
#if 0
@@ -409,7 +385,7 @@ static u64
smb_unixutc2ntutc(struct smb_sb_info *server, time_t t)
{
/* Note: timezone conversion is probably wrong. */
- return ((utc2local(server, t) + (u64)(369*365+89)*24*3600) * 10000000);
+ return ((u64)utc2local(server, t)) * 10000000 + NTFS_TIME_OFFSET;
}
#endif
@@ -519,6 +495,9 @@ smb_get_wsize(struct smb_sb_info *server)
return size;
}
+/*
+ * Convert SMB error codes to -E... errno values.
+ */
int
smb_errno(struct smb_sb_info *server)
{
@@ -529,110 +508,115 @@ smb_errno(struct smb_sb_info *server)
VERBOSE("errcls %d code %d from command 0x%x\n",
errcls, error, SMB_CMD(server->packet));
- if (errcls == ERRDOS)
- switch (error)
- {
+ if (errcls == ERRDOS) {
+ switch (error) {
case ERRbadfunc:
- return EINVAL;
+ return -EINVAL;
case ERRbadfile:
case ERRbadpath:
- return ENOENT;
+ return -ENOENT;
case ERRnofids:
- return EMFILE;
+ return -EMFILE;
case ERRnoaccess:
- return EACCES;
+ return -EACCES;
case ERRbadfid:
- return EBADF;
+ return -EBADF;
case ERRbadmcb:
- return EREMOTEIO;
+ return -EREMOTEIO;
case ERRnomem:
- return ENOMEM;
+ return -ENOMEM;
case ERRbadmem:
- return EFAULT;
+ return -EFAULT;
case ERRbadenv:
case ERRbadformat:
- return EREMOTEIO;
+ return -EREMOTEIO;
case ERRbadaccess:
- return EACCES;
+ return -EACCES;
case ERRbaddata:
- return E2BIG;
+ return -E2BIG;
case ERRbaddrive:
- return ENXIO;
+ return -ENXIO;
case ERRremcd:
- return EREMOTEIO;
+ return -EREMOTEIO;
case ERRdiffdevice:
- return EXDEV;
- case ERRnofiles: /* Why is this mapped to 0?? */
- return 0;
+ return -EXDEV;
+ case ERRnofiles:
+ return -ENOENT;
case ERRbadshare:
- return ETXTBSY;
+ return -ETXTBSY;
case ERRlock:
- return EDEADLK;
+ return -EDEADLK;
case ERRfilexists:
- return EEXIST;
- case 87: /* should this map to 0?? */
- return 0; /* Unknown error!! */
- case 123: /* Invalid name?? e.g. .tmp* */
- return ENOENT;
- case 145: /* Win NT 4.0: non-empty directory? */
- return ENOTEMPTY;
- /* This next error seems to occur on an mv when
- * the destination exists */
- case 183:
- return EEXIST;
+ return -EEXIST;
+ case ERRinvalidparam:
+ return -EINVAL;
+ case ERRdiskfull:
+ return -ENOSPC;
+ case ERRinvalidname:
+ return -ENOENT;
+ case ERRdirnotempty:
+ return -ENOTEMPTY;
+ case ERRnotlocked:
+ return -ENOLCK;
+ case ERRexists:
+ return -EEXIST;
default:
class = "ERRDOS";
goto err_unknown;
- } else if (errcls == ERRSRV)
- switch (error)
- {
+ }
+ } else if (errcls == ERRSRV) {
+ switch (error) {
/* N.B. This is wrong ... EIO ? */
case ERRerror:
- return ENFILE;
+ return -ENFILE;
case ERRbadpw:
- return EINVAL;
+ return -EINVAL;
case ERRbadtype:
- return EIO;
+ return -EIO;
case ERRaccess:
- return EACCES;
+ return -EACCES;
/*
* This is a fatal error, as it means the "tree ID"
* for this connection is no longer valid. We map
* to a special error code and get a new connection.
*/
case ERRinvnid:
- return EBADSLT;
+ return -EBADSLT;
default:
class = "ERRSRV";
goto err_unknown;
- } else if (errcls == ERRHRD)
- switch (error)
- {
+ }
+ } else if (errcls == ERRHRD) {
+ switch (error) {
case ERRnowrite:
- return EROFS;
+ return -EROFS;
case ERRbadunit:
- return ENODEV;
+ return -ENODEV;
case ERRnotready:
- return EUCLEAN;
+ return -EUCLEAN;
case ERRbadcmd:
case ERRdata:
- return EIO;
+ return -EIO;
case ERRbadreq:
- return ERANGE;
+ return -ERANGE;
case ERRbadshare:
- return ETXTBSY;
+ return -ETXTBSY;
case ERRlock:
- return EDEADLK;
+ return -EDEADLK;
default:
class = "ERRHRD";
goto err_unknown;
- } else if (errcls == ERRCMD)
+ }
+ } else if (errcls == ERRCMD) {
class = "ERRCMD";
+ } else if (errcls == SUCCESS) {
+ return 0; /* This is the only valid 0 return */
+ }
err_unknown:
printk(KERN_ERR "smb_errno: class %s, code %d from command 0x%x\n",
class, error, SMB_CMD(server->packet));
- return EIO;
+ return -EIO;
}
/*
@@ -749,12 +733,10 @@ smb_request_ok(struct smb_sb_info *s, int command, int wct, int bcc)
}
/*
- * Check for server errors. The current smb_errno() routine
- * is squashing some error codes, but I don't think this is
- * correct: after a server error the packet won't be valid.
+ * Check for server errors.
*/
if (s->rcls != 0) {
- result = -smb_errno(s);
+ result = smb_errno(s);
if (!result)
printk(KERN_DEBUG "smb_request_ok: rcls=%d, err=%d mapped to 0\n",
s->rcls, s->err);
@@ -850,17 +832,23 @@ smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
out:
smb_unlock_server(server);
+ smb_wakeup(server);
+ return error;
+out_putf:
+ fput(filp);
+ goto out;
+}
+
+int
+smb_wakeup(struct smb_sb_info *server)
+{
#ifdef SMB_RETRY_INTR
wake_up_interruptible(&server->wait);
#else
wake_up(&server->wait);
#endif
- return error;
-
-out_putf:
- fput(filp);
- goto out;
+ return 0;
}
/* smb_setup_header: We completely set up the packet. You only have to
@@ -1490,7 +1478,7 @@ smb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
fattr->f_nlink = 1;
fattr->f_uid = server->mnt->uid;
fattr->f_gid = server->mnt->gid;
- fattr->f_blksize = 512;
+ fattr->f_blksize = SMB_ST_BLKSIZE;
}
static void
@@ -1500,18 +1488,16 @@ smb_finish_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
if (fattr->attr & aDIR)
{
fattr->f_mode = server->mnt->dir_mode;
- fattr->f_size = 512;
+ fattr->f_size = SMB_ST_BLKSIZE;
}
/* Check the read-only flag */
if (fattr->attr & aRONLY)
fattr->f_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+ /* How many 512 byte blocks do we need for this file? */
fattr->f_blocks = 0;
- if ((fattr->f_blksize != 0) && (fattr->f_size != 0))
- {
- fattr->f_blocks =
- (fattr->f_size - 1) / fattr->f_blksize + 1;
- }
+ if (fattr->f_size != 0)
+ fattr->f_blocks = 1 + ((fattr->f_size-1) >> 9);
return;
}
@@ -1770,9 +1756,9 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p, int level,
if (len && qname->name[len-1] == '\0')
len--;
- fattr->f_ctime = smb_ntutc2unixutc(server, LVAL(p, 8));
- fattr->f_atime = smb_ntutc2unixutc(server, LVAL(p, 16));
- fattr->f_mtime = smb_ntutc2unixutc(server, LVAL(p, 24));
+ fattr->f_ctime = smb_ntutc2unixutc(LVAL(p, 8));
+ fattr->f_atime = smb_ntutc2unixutc(LVAL(p, 16));
+ fattr->f_mtime = smb_ntutc2unixutc(LVAL(p, 24));
/* change time (32) */
fattr->f_size = DVAL(p, 40);
/* alloc size (48) */
@@ -1940,7 +1926,7 @@ smb_proc_readdir_long(struct file *filp, void *dirent, filldir_t filldir,
}
if (server->rcls != 0) {
- result = -smb_errno(server);
+ result = smb_errno(server);
PARANOIA("name=%s, result=%d, rcls=%d, err=%d\n",
mask, result, server->rcls, server->err);
break;
@@ -2104,7 +2090,7 @@ retry:
}
if (server->rcls != 0)
{
- result = -smb_errno(server);
+ result = smb_errno(server);
#ifdef SMBFS_PARANOIA
if (result != -ENOENT)
PARANOIA("error for %s, rcls=%d, err=%d\n",
@@ -2227,7 +2213,7 @@ smb_proc_getattr_trans2(struct smb_sb_info *server, struct dentry *dir,
{
VERBOSE("for %s: result=%d, rcls=%d, err=%d\n",
&param[6], result, server->rcls, server->err);
- result = -smb_errno(server);
+ result = smb_errno(server);
goto out;
}
result = -ENOENT;
@@ -2490,7 +2476,7 @@ smb_proc_setattr_trans2(struct smb_sb_info *server,
}
result = 0;
if (server->rcls != 0)
- result = -smb_errno(server);
+ result = smb_errno(server);
out:
return result;
@@ -2559,6 +2545,7 @@ smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
struct smb_sb_info *server = &(sb->u.smbfs_sb);
int result;
char *p;
+ long unit;
smb_lock_server(server);
@@ -2571,23 +2558,13 @@ smb_proc_dskattr(struct super_block *sb, struct statfs *attr)
goto out;
}
p = SMB_VWV(server->packet);
- attr->f_blocks = WVAL(p, 0);
- attr->f_bsize = WVAL(p, 2) * WVAL(p, 4);
- attr->f_bavail = attr->f_bfree = WVAL(p, 6);
+ unit = (WVAL(p, 2) * WVAL(p, 4)) >> SMB_ST_BLKSHIFT;
+ attr->f_blocks = WVAL(p, 0) * unit;
+ attr->f_bsize = SMB_ST_BLKSIZE;
+ attr->f_bavail = attr->f_bfree = WVAL(p, 6) * unit;
result = 0;
out:
smb_unlock_server(server);
return result;
}
-
-int
-smb_proc_disconnect(struct smb_sb_info *server)
-{
- int result;
- smb_lock_server(server);
- smb_setup_header(server, SMBtdis, 0, 0);
- result = smb_request_ok(server, SMBtdis, 0, 0);
- smb_unlock_server(server);
- return result;
-}
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h
new file mode 100644
index 000000000000..65b18719da77
--- /dev/null
+++ b/fs/smbfs/proto.h
@@ -0,0 +1,63 @@
+/*
+ * Autogenerated with cproto on: Tue Oct 2 20:40:54 CEST 2001
+ */
+
+/* proc.c */
+extern int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp);
+extern __u32 smb_len(__u8 *p);
+extern int smb_get_rsize(struct smb_sb_info *server);
+extern int smb_get_wsize(struct smb_sb_info *server);
+extern int smb_errno(struct smb_sb_info *server);
+extern int smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt);
+extern int smb_wakeup(struct smb_sb_info *server);
+extern __u8 *smb_setup_header(struct smb_sb_info *server, __u8 command, __u16 wct, __u16 bcc);
+extern int smb_open(struct dentry *dentry, int wish);
+extern int smb_close(struct inode *ino);
+extern int smb_close_fileid(struct dentry *dentry, __u16 fileid);
+extern int smb_proc_read(struct inode *inode, off_t offset, int count, char *data);
+extern int smb_proc_write(struct inode *inode, off_t offset, int count, const char *data);
+extern int smb_proc_create(struct dentry *dentry, __u16 attr, time_t ctime, __u16 *fileid);
+extern int smb_proc_mv(struct dentry *old_dentry, struct dentry *new_dentry);
+extern int smb_proc_mkdir(struct dentry *dentry);
+extern int smb_proc_rmdir(struct dentry *dentry);
+extern int smb_proc_unlink(struct dentry *dentry);
+extern int smb_proc_flush(struct smb_sb_info *server, __u16 fileid);
+extern int smb_proc_trunc(struct smb_sb_info *server, __u16 fid, __u32 length);
+extern void smb_init_root_dirent(struct smb_sb_info *server, struct smb_fattr *fattr);
+extern int smb_proc_readdir(struct file *filp, void *dirent, filldir_t filldir, struct smb_cache_control *ctl);
+extern int smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr);
+extern int smb_proc_setattr(struct dentry *dir, struct smb_fattr *fattr);
+extern int smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr);
+extern int smb_proc_dskattr(struct super_block *sb, struct statfs *attr);
+/* dir.c */
+extern struct file_operations smb_dir_operations;
+extern struct inode_operations smb_dir_inode_operations;
+extern void smb_new_dentry(struct dentry *dentry);
+extern void smb_renew_times(struct dentry *dentry);
+/* cache.c */
+extern void smb_invalid_dir_cache(struct inode *dir);
+extern void smb_invalidate_dircache_entries(struct dentry *parent);
+extern struct dentry *smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos);
+extern int smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct smb_cache_control *ctrl, struct qstr *qname, struct smb_fattr *entry);
+/* sock.c */
+extern int smb_valid_socket(struct inode *inode);
+extern int smb_catch_keepalive(struct smb_sb_info *server);
+extern int smb_dont_catch_keepalive(struct smb_sb_info *server);
+extern void smb_close_socket(struct smb_sb_info *server);
+extern int smb_round_length(int len);
+extern int smb_request(struct smb_sb_info *server);
+extern int smb_trans2_request(struct smb_sb_info *server, __u16 trans2_command, int ldata, unsigned char *data, int lparam, unsigned char *param, int *lrdata, unsigned char **rdata, int *lrparam, unsigned char **rparam);
+/* inode.c */
+extern struct inode *smb_iget(struct super_block *sb, struct smb_fattr *fattr);
+extern void smb_get_inode_attr(struct inode *inode, struct smb_fattr *fattr);
+extern void smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr);
+extern void smb_invalidate_inodes(struct smb_sb_info *server);
+extern int smb_revalidate_inode(struct dentry *dentry);
+extern struct super_block *smb_read_super(struct super_block *sb, void *raw_data, int silent);
+extern int smb_notify_change(struct dentry *dentry, struct iattr *attr);
+/* file.c */
+extern struct address_space_operations smb_file_aops;
+extern struct file_operations smb_file_operations;
+extern struct inode_operations smb_file_inode_operations;
+/* ioctl.c */
+extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
diff --git a/fs/smbfs/sock.c b/fs/smbfs/sock.c
index 47aad9dc1cb1..46313b623c7b 100644
--- a/fs/smbfs/sock.c
+++ b/fs/smbfs/sock.c
@@ -27,6 +27,7 @@
#include <asm/uaccess.h>
#include "smb_debug.h"
+#include "proto.h"
static int
@@ -674,7 +675,7 @@ smb_request(struct smb_sb_info *server)
*/
if (server->rcls) {
int error = smb_errno(server);
- if (error == EBADSLT) {
+ if (error == -EBADSLT) {
printk(KERN_ERR "smb_request: tree ID invalid\n");
result = error;
goto bad_conn;
@@ -866,7 +867,7 @@ smb_trans2_request(struct smb_sb_info *server, __u16 trans2_command,
*/
if (server->rcls) {
int error = smb_errno(server);
- if (error == EBADSLT) {
+ if (error == -EBADSLT) {
printk(KERN_ERR "smb_request: tree ID invalid\n");
result = error;
goto bad_conn;
diff --git a/fs/super.c b/fs/super.c
index 4736ded323c6..c4ad15b24195 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -280,6 +280,7 @@ struct file_system_type *get_fs_type(const char *name)
}
static LIST_HEAD(vfsmntlist);
+static struct vfsmount *root_vfsmnt;
static struct list_head *mount_hashtable;
static int hash_mask, hash_bits;
@@ -326,6 +327,15 @@ struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
return p;
}
+static int check_mnt(struct vfsmount *mnt)
+{
+ spin_lock(&dcache_lock);
+ while (mnt->mnt_parent != mnt)
+ mnt = mnt->mnt_parent;
+ spin_unlock(&dcache_lock);
+ return mnt == root_vfsmnt;
+}
+
static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd)
{
old_nd->dentry = mnt->mnt_mountpoint;
@@ -346,50 +356,20 @@ static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd)
nd->dentry->d_mounted++;
}
-/**
- * add_vfsmnt - add a new mount node
- * @nd: location of mountpoint or %NULL if we want a root node
- * @root: root of (sub)tree to be mounted
- * @dev_name: device name to show in /proc/mounts or %NULL (for "none").
- *
- * This is VFS idea of mount. New node is allocated, bound to a tree
- * we are mounting and optionally (OK, usually) registered as mounted
- * on a given mountpoint. Returns a pointer to new node or %NULL in
- * case of failure.
- *
- * Potential reason for failure (aside of trivial lack of memory) is a
- * deleted mountpoint. Caller must hold ->i_zombie on mountpoint
- * dentry (if any).
- */
-
-static struct vfsmount *add_vfsmnt(struct dentry *root, const char *dev_name)
+static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root)
{
- struct vfsmount *mnt;
- struct super_block *sb = root->d_inode->i_sb;
- char *name;
-
- mnt = alloc_vfsmnt();
- if (!mnt)
- goto out;
-
- /* It may be NULL, but who cares? */
- if (dev_name) {
- name = kmalloc(strlen(dev_name)+1, GFP_KERNEL);
- if (name) {
- strcpy(name, dev_name);
- mnt->mnt_devname = name;
+ struct list_head *next = p->mnt_mounts.next;
+ if (next == &p->mnt_mounts) {
+ while (1) {
+ if (p == root)
+ return NULL;
+ next = p->mnt_child.next;
+ if (next != &p->mnt_parent->mnt_mounts)
+ break;
+ p = p->mnt_parent;
}
}
- mnt->mnt_sb = sb;
- mnt->mnt_root = dget(root);
- mnt->mnt_mountpoint = mnt->mnt_root;
- mnt->mnt_parent = mnt;
-
- spin_lock(&dcache_lock);
- list_add(&mnt->mnt_list, vfsmntlist.prev);
- spin_unlock(&dcache_lock);
-out:
- return mnt;
+ return list_entry(next, struct vfsmount, mnt_child);
}
static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root)
@@ -447,37 +427,6 @@ fail1:
return -ENOENT;
}
-#ifdef CONFIG_BLK_DEV_INITRD
-static void move_vfsmnt(struct vfsmount *mnt,
- struct nameidata *nd,
- const char *dev_name)
-{
- struct nameidata parent_nd;
- char *new_devname = NULL;
-
- if (dev_name) {
- new_devname = kmalloc(strlen(dev_name)+1, GFP_KERNEL);
- if (new_devname)
- strcpy(new_devname, dev_name);
- }
-
- spin_lock(&dcache_lock);
- detach_mnt(mnt, &parent_nd);
- attach_mnt(mnt, nd);
-
- if (new_devname) {
- if (mnt->mnt_devname)
- kfree(mnt->mnt_devname);
- mnt->mnt_devname = new_devname;
- }
- spin_unlock(&dcache_lock);
-
- /* put the old stuff */
- if (parent_nd.mnt != mnt)
- path_release(&parent_nd);
-}
-#endif
-
static void kill_super(struct super_block *);
void __mntput(struct vfsmount *mnt)
@@ -1189,10 +1138,52 @@ int may_umount(struct vfsmount *mnt)
return 0;
}
+void umount_tree(struct vfsmount *mnt)
+{
+ struct vfsmount *p;
+ LIST_HEAD(kill);
+
+ if (list_empty(&mnt->mnt_list))
+ return;
+
+ for (p = mnt; p; p = next_mnt(p, mnt)) {
+ list_del(&p->mnt_list);
+ list_add(&p->mnt_list, &kill);
+ }
+
+ while (!list_empty(&kill)) {
+ mnt = list_entry(kill.next, struct vfsmount, mnt_list);
+ list_del_init(&mnt->mnt_list);
+ if (mnt->mnt_parent == mnt) {
+ spin_unlock(&dcache_lock);
+ } else {
+ struct nameidata old_nd;
+ detach_mnt(mnt, &old_nd);
+ spin_unlock(&dcache_lock);
+ path_release(&old_nd);
+ }
+ mntput(mnt);
+ spin_lock(&dcache_lock);
+ }
+}
+
static int do_umount(struct vfsmount *mnt, int flags)
{
struct super_block * sb = mnt->mnt_sb;
- struct nameidata parent_nd;
+ int retval = 0;
+
+ /*
+ * If we may have to abort operations to get out of this
+ * mount, and they will themselves hold resources we must
+ * allow the fs to do things. In the Unix tradition of
+ * 'Gee thats tricky lets do it in userspace' the umount_begin
+ * might fail to complete on the first run through as other tasks
+ * must return, and the like. Thats for the mount program to worry
+ * about for the moment.
+ */
+
+ if( (flags&MNT_FORCE) && sb->s_op->umount_begin)
+ sb->s_op->umount_begin(sb);
/*
* No sense to grab the lock for this test, but test itself looks
@@ -1204,7 +1195,7 @@ static int do_umount(struct vfsmount *mnt, int flags)
* /reboot - static binary that would close all descriptors and
* call reboot(9). Then init(8) could umount root and exec /reboot.
*/
- if (mnt == current->fs->rootmnt) {
+ if (mnt == current->fs->rootmnt && !(flags & MNT_DETACH)) {
int retval = 0;
/*
* Special case for "unmounting" root ...
@@ -1220,59 +1211,20 @@ static int do_umount(struct vfsmount *mnt, int flags)
spin_lock(&dcache_lock);
- if (atomic_read(&sb->s_active) > 1) {
- if (atomic_read(&mnt->mnt_count) > 2) {
- spin_unlock(&dcache_lock);
- return -EBUSY;
- }
- detach_mnt(mnt, &parent_nd);
- list_del(&mnt->mnt_list);
+ if (atomic_read(&sb->s_active) == 1) {
+ /* last instance - try to be smart */
spin_unlock(&dcache_lock);
- mntput(mnt);
- if (parent_nd.mnt != mnt)
- path_release(&parent_nd);
- return 0;
+ DQUOT_OFF(sb);
+ acct_auto_close(sb->s_dev);
+ spin_lock(&dcache_lock);
}
- spin_unlock(&dcache_lock);
-
- /*
- * Before checking whether the filesystem is still busy,
- * make sure the kernel doesn't hold any quota files open
- * on the device. If the umount fails, too bad -- there
- * are no quotas running any more. Just turn them on again.
- */
- DQUOT_OFF(sb);
- acct_auto_close(sb->s_dev);
-
- /*
- * If we may have to abort operations to get out of this
- * mount, and they will themselves hold resources we must
- * allow the fs to do things. In the Unix tradition of
- * 'Gee thats tricky lets do it in userspace' the umount_begin
- * might fail to complete on the first run through as other tasks
- * must return, and the like. Thats for the mount program to worry
- * about for the moment.
- */
-
- if( (flags&MNT_FORCE) && sb->s_op->umount_begin)
- sb->s_op->umount_begin(sb);
-
- /* Something might grab it again - redo checks */
-
- spin_lock(&dcache_lock);
- if (atomic_read(&mnt->mnt_count) > 2) {
- spin_unlock(&dcache_lock);
- return -EBUSY;
+ retval = -EBUSY;
+ if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) {
+ umount_tree(mnt);
+ retval = 0;
}
-
- /* OK, that's the point of no return */
- detach_mnt(mnt, &parent_nd);
- list_del(&mnt->mnt_list);
spin_unlock(&dcache_lock);
- mntput(mnt);
- if (parent_nd.mnt != mnt)
- path_release(&parent_nd);
- return 0;
+ return retval;
}
/*
@@ -1302,6 +1254,8 @@ asmlinkage long sys_umount(char * name, int flags)
retval = -EINVAL;
if (nd.dentry != nd.mnt->mnt_root)
goto dput_and_out;
+ if (!check_mnt(nd.mnt))
+ goto dput_and_out;
retval = -EPERM;
if (!capable(CAP_SYS_ADMIN) && current->uid!=nd.mnt->mnt_owner)
@@ -1353,7 +1307,7 @@ static int mount_is_safe(struct nameidata *nd)
static int do_loopback(struct nameidata *nd, char *old_name)
{
struct nameidata old_nd;
- struct vfsmount *mnt;
+ struct vfsmount *mnt = NULL;
int err;
err = mount_is_safe(nd);
@@ -1369,12 +1323,16 @@ static int do_loopback(struct nameidata *nd, char *old_name)
return err;
down(&mount_sem);
- err = -ENOMEM;
- mnt = clone_mnt(old_nd.mnt, old_nd.dentry);
+ err = -EINVAL;
+ if (check_mnt(nd->mnt)) {
+ err = -ENOMEM;
+ mnt = clone_mnt(old_nd.mnt, old_nd.dentry);
+ }
if (mnt) {
err = graft_tree(mnt, nd);
mntput(mnt);
}
+
up(&mount_sem);
path_release(&old_nd);
return err;
@@ -1394,6 +1352,9 @@ static int do_remount(struct nameidata *nd,int flags,int mnt_flags,char *data)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+ if (!check_mnt(nd->mnt))
+ return -EINVAL;
+
if (nd->dentry != nd->mnt->mnt_root)
return -EINVAL;
@@ -1472,27 +1433,31 @@ static int do_add_mount(struct nameidata *nd, char *type, int flags,
int mnt_flags, char *name, void *data)
{
struct vfsmount *mnt = do_kern_mount(type, flags, name, data);
- int retval = PTR_ERR(mnt);
+ int err = PTR_ERR(mnt);
if (IS_ERR(mnt))
goto out;
- mnt->mnt_flags = mnt_flags;
-
down(&mount_sem);
/* Something was mounted here while we slept */
while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry))
;
+ err = -EINVAL;
+ if (!check_mnt(nd->mnt))
+ goto unlock;
/* Refuse the same filesystem on the same mount point */
+ err = -EBUSY;
if (nd->mnt->mnt_sb == mnt->mnt_sb && nd->mnt->mnt_root == nd->dentry)
- retval = -EBUSY;
- else
- retval = graft_tree(mnt, nd);
+ goto unlock;
+
+ mnt->mnt_flags = mnt_flags;
+ err = graft_tree(mnt, nd);
+unlock:
up(&mount_sem);
mntput(mnt);
out:
- return retval;
+ return err;
}
static int copy_mount_options (const void *data, unsigned long *where)
@@ -1630,6 +1595,7 @@ out1:
void __init mount_root(void)
{
+ struct nameidata root_nd;
struct file_system_type * fs_type;
struct super_block * sb;
struct vfsmount *vfsmnt;
@@ -1639,6 +1605,7 @@ void __init mount_root(void)
void *handle;
char path[64];
int path_start = -1;
+ char *name = "/dev/root";
#ifdef CONFIG_ROOT_NFS
void *data;
@@ -1776,13 +1743,26 @@ mount_it:
fs_type->name,
(sb->s_flags & MS_RDONLY) ? " readonly" : "");
if (path_start >= 0) {
+ name = path + path_start;
devfs_mk_symlink (NULL, "root", DEVFS_FL_DEFAULT,
- path + 5 + path_start, NULL, NULL);
- memcpy (path + path_start, "/dev/", 5);
- vfsmnt = add_vfsmnt(sb->s_root, path + path_start);
+ name + 5, NULL, NULL);
+ memcpy (name, "/dev/", 5);
}
- else
- vfsmnt = add_vfsmnt(sb->s_root, "/dev/root");
+ vfsmnt = alloc_vfsmnt();
+ if (!vfsmnt)
+ panic("VFS: alloc_vfsmnt failed for root fs");
+
+ vfsmnt->mnt_devname = kmalloc(strlen(name)+1, GFP_KERNEL);
+ if (vfsmnt->mnt_devname)
+ strcpy(vfsmnt->mnt_devname, name);
+ vfsmnt->mnt_sb = sb;
+ vfsmnt->mnt_root = dget(sb->s_root);
+
+ root_nd.mnt = root_vfsmnt;
+ root_nd.dentry = root_vfsmnt->mnt_sb->s_root;
+ graft_tree(vfsmnt, &root_nd);
+ mntput(vfsmnt);
+
/* FIXME: if something will try to umount us right now... */
if (vfsmnt) {
set_fs_root(current->fs, vfsmnt, sb->s_root);
@@ -1791,10 +1771,8 @@ mount_it:
bdput(bdev); /* sb holds a reference */
return;
}
- panic("VFS: add_vfsmnt failed for root fs");
}
-
static void chroot_fs_refs(struct dentry *old_root,
struct vfsmount *old_rootmnt,
struct dentry *new_root,
@@ -1836,10 +1814,8 @@ static void chroot_fs_refs(struct dentry *old_root,
asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
{
- struct dentry *root;
- struct vfsmount *root_mnt;
struct vfsmount *tmp;
- struct nameidata new_nd, old_nd, parent_nd, root_parent;
+ struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
char *name;
int error;
@@ -1858,11 +1834,14 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
putname(name);
if (error)
goto out0;
+ error = -EINVAL;
+ if (!check_mnt(new_nd.mnt))
+ goto out1;
name = getname(put_old);
error = PTR_ERR(name);
if (IS_ERR(name))
- goto out0;
+ goto out1;
error = 0;
if (path_init(name, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd))
error = path_walk(name, &old_nd);
@@ -1871,11 +1850,14 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
goto out1;
read_lock(&current->fs->lock);
- root_mnt = mntget(current->fs->rootmnt);
- root = dget(current->fs->root);
+ user_nd.mnt = mntget(current->fs->rootmnt);
+ user_nd.dentry = dget(current->fs->root);
read_unlock(&current->fs->lock);
down(&mount_sem);
down(&old_nd.dentry->d_inode->i_zombie);
+ error = -EINVAL;
+ if (!check_mnt(user_nd.mnt))
+ goto out2;
error = -ENOENT;
if (IS_DEADDIR(new_nd.dentry->d_inode))
goto out2;
@@ -1884,10 +1866,10 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
if (d_unhashed(old_nd.dentry) && !IS_ROOT(old_nd.dentry))
goto out2;
error = -EBUSY;
- if (new_nd.mnt == root_mnt || old_nd.mnt == root_mnt)
+ if (new_nd.mnt == user_nd.mnt || old_nd.mnt == user_nd.mnt)
goto out2; /* loop */
error = -EINVAL;
- if (root_mnt->mnt_root != root)
+ if (user_nd.mnt->mnt_root != user_nd.dentry)
goto out2;
if (new_nd.mnt->mnt_root != new_nd.dentry)
goto out2; /* not a mountpoint */
@@ -1906,22 +1888,18 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
} else if (!is_subdir(old_nd.dentry, new_nd.dentry))
goto out3;
detach_mnt(new_nd.mnt, &parent_nd);
- detach_mnt(root_mnt, &root_parent);
- attach_mnt(root_mnt, &old_nd);
- if (root_parent.mnt != root_mnt)
- attach_mnt(new_nd.mnt, &root_parent);
+ detach_mnt(user_nd.mnt, &root_parent);
+ attach_mnt(user_nd.mnt, &old_nd);
+ attach_mnt(new_nd.mnt, &root_parent);
spin_unlock(&dcache_lock);
- chroot_fs_refs(root,root_mnt,new_nd.dentry,new_nd.mnt);
+ chroot_fs_refs(user_nd.dentry,user_nd.mnt,new_nd.dentry,new_nd.mnt);
error = 0;
- if (root_parent.mnt != root_mnt)
- path_release(&root_parent);
- if (parent_nd.mnt != new_nd.mnt)
- path_release(&parent_nd);
+ path_release(&root_parent);
+ path_release(&parent_nd);
out2:
up(&old_nd.dentry->d_inode->i_zombie);
up(&mount_sem);
- dput(root);
- mntput(root_mnt);
+ path_release(&user_nd);
path_release(&old_nd);
out1:
path_release(&new_nd);
@@ -1940,8 +1918,13 @@ int __init change_root(kdev_t new_root_dev,const char *put_old)
{
struct vfsmount *old_rootmnt;
struct nameidata devfs_nd, nd;
+ struct nameidata parent_nd;
+ char *new_devname = kmalloc(strlen("/dev/root.old")+1, GFP_KERNEL);
int error = 0;
+ if (new_devname)
+ strcpy(new_devname, "/dev/root.old");
+
read_lock(&current->fs->lock);
old_rootmnt = mntget(current->fs->rootmnt);
read_unlock(&current->fs->lock);
@@ -1958,6 +1941,9 @@ int __init change_root(kdev_t new_root_dev,const char *put_old)
} else
path_release(&devfs_nd);
}
+ spin_lock(&dcache_lock);
+ detach_mnt(old_rootmnt, &parent_nd);
+ spin_unlock(&dcache_lock);
ROOT_DEV = new_root_dev;
mount_root();
#if 1
@@ -1980,25 +1966,36 @@ int __init change_root(kdev_t new_root_dev,const char *put_old)
blivet = blkdev_get(ramdisk, FMODE_READ, 0, BDEV_FS);
printk(KERN_NOTICE "Trying to unmount old root ... ");
if (!blivet) {
- blivet = do_umount(old_rootmnt, 0);
+ spin_lock(&dcache_lock);
+ list_del(&old_rootmnt->mnt_list);
+ spin_unlock(&dcache_lock);
+ mntput(old_rootmnt);
mntput(old_rootmnt);
- if (!blivet) {
- int ioctl_err;
-
- ioctl_err = ioctl_by_bdev(ramdisk, BLKFLSBUF, 0);
- if (ioctl_err)
- printk("failed to release ramdisk %d...", ioctl_err);
- printk("okay\n");
- error = 0;
- }
+ blivet = ioctl_by_bdev(ramdisk, BLKFLSBUF, 0);
+ path_release(&parent_nd);
blkdev_put(ramdisk, BDEV_FS);
}
- if (blivet)
+ if (blivet) {
printk(KERN_ERR "error %d\n", blivet);
+ } else {
+ printk("okay\n");
+ error = 0;
+ }
+ kfree(new_devname);
return error;
}
- /* FIXME: we should hold i_zombie on nd.dentry */
- move_vfsmnt(old_rootmnt, &nd, "/dev/root.old");
+
+ spin_lock(&dcache_lock);
+ attach_mnt(old_rootmnt, &nd);
+ if (new_devname) {
+ if (old_rootmnt->mnt_devname)
+ kfree(old_rootmnt->mnt_devname);
+ old_rootmnt->mnt_devname = new_devname;
+ }
+ spin_unlock(&dcache_lock);
+
+ /* put the old stuff */
+ path_release(&parent_nd);
mntput(old_rootmnt);
path_release(&nd);
return 0;
@@ -2006,6 +2003,54 @@ int __init change_root(kdev_t new_root_dev,const char *put_old)
#endif
+/*
+ * Absolutely minimal fake fs - only empty root directory and nothing else.
+ * In 2.5 we'll use ramfs or tmpfs, but for now it's all we need - just
+ * something to go with root vfsmount.
+ */
+static struct dentry *rootfs_lookup(struct inode *dir, struct dentry *dentry)
+{
+ d_add(dentry, NULL);
+ return NULL;
+}
+static struct file_operations rootfs_dir_operations = {
+ read: generic_read_dir,
+ readdir: dcache_readdir,
+};
+static struct inode_operations rootfs_dir_inode_operations = {
+ lookup: rootfs_lookup,
+};
+static struct super_block *rootfs_read_super(struct super_block * sb, void * data, int silent)
+{
+ struct inode * inode;
+ struct dentry * root;
+ static struct super_operations s_ops = {};
+ sb->s_op = &s_ops;
+ inode = new_inode(sb);
+ if (!inode)
+ return NULL;
+ inode->i_mode = S_IFDIR|0555;
+ inode->i_uid = inode->i_gid = 0;
+ inode->i_op = &rootfs_dir_inode_operations;
+ inode->i_fop = &rootfs_dir_operations;
+ root = d_alloc_root(inode);
+ if (!root) {
+ iput(inode);
+ return NULL;
+ }
+ sb->s_root = root;
+ return sb;
+}
+static DECLARE_FSTYPE(root_fs_type, "rootfs", rootfs_read_super, FS_NOMOUNT);
+
+static void __init init_mount_tree(void)
+{
+ register_filesystem(&root_fs_type);
+ root_vfsmnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
+ if (IS_ERR(root_vfsmnt))
+ panic("can't allocate root vfsmount");
+}
+
void __init mnt_init(unsigned long mempages)
{
struct list_head *d;
@@ -2061,4 +2106,5 @@ void __init mnt_init(unsigned long mempages)
d++;
i--;
} while (i);
+ init_mount_tree();
}
diff --git a/include/asm-ppc/mmu_context.h b/include/asm-ppc/mmu_context.h
index 7624088c38d5..58b4d6179855 100644
--- a/include/asm-ppc/mmu_context.h
+++ b/include/asm-ppc/mmu_context.h
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.mmu_context.h 1.15 08/16/01 23:00:17 paulus
+ * BK Id: SCCS/s.mmu_context.h 1.18 09/26/01 16:02:49 paulus
*/
#ifdef __KERNEL__
#ifndef __PPC_MMU_CONTEXT_H
@@ -29,7 +29,7 @@
* of the 32-bit virtual address (the "effective segment ID") in order
* to spread out the entries in the MMU hash table. Note, if this
* function is changed then arch/ppc/mm/hashtable.S will have to be
- * changed correspondly.
+ * changed to correspond.
*/
#define CTX_TO_VSID(ctx, va) (((ctx) * (897 * 16) + ((va) >> 28) * 0x111) \
& 0xffffff)
@@ -89,7 +89,7 @@ extern void set_context(mm_context_t context, pgd_t *pgd);
* Bitmap of contexts in use.
* The size of this bitmap is LAST_CONTEXT + 1 bits.
*/
-extern unsigned long context_map[(LAST_CONTEXT+1) / (8*sizeof(unsigned long))];
+extern unsigned long context_map[];
/*
* This caches the next context number that we expect to be free.
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9d04f9af4908..9d314051fb0b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -650,6 +650,7 @@ struct quota_mount_options
*/
#define MNT_FORCE 0x00000001 /* Attempt to forcibily umount */
+#define MNT_DETACH 0x00000002 /* Just detach from the tree */
#include <linux/minix_fs_sb.h>
#include <linux/ext2_fs_sb.h>
diff --git a/include/linux/gameport.h b/include/linux/gameport.h
index 4e341f1fdbe9..37b72807182b 100644
--- a/include/linux/gameport.h
+++ b/include/linux/gameport.h
@@ -74,8 +74,8 @@ void gameport_rescan(struct gameport *gameport);
void gameport_register_port(struct gameport *gameport);
void gameport_unregister_port(struct gameport *gameport);
#else
-void __inline__ gameport_register_port(struct gameport *gameport) { return; }
-void __inline__ gameport_unregister_port(struct gameport *gameport) { return; }
+static void __inline__ gameport_register_port(struct gameport *gameport) { return; }
+static void __inline__ gameport_unregister_port(struct gameport *gameport) { return; }
#endif
void gameport_register_device(struct gameport_dev *dev);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 7aea8bc88b32..a356cb65a4ac 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -13,23 +13,33 @@
#include <linux/types.h>
#include <linux/major.h>
+enum {
/* These three have identical behaviour; use the second one if DOS fdisk gets
confused about extended/logical partitions starting past cylinder 1023. */
-#define DOS_EXTENDED_PARTITION 5
-#define LINUX_EXTENDED_PARTITION 0x85
-#define WIN98_EXTENDED_PARTITION 0x0f
+ DOS_EXTENDED_PARTITION = 5,
+ LINUX_EXTENDED_PARTITION = 0x85,
+ WIN98_EXTENDED_PARTITION = 0x0f,
-#define LINUX_SWAP_PARTITION 0x82
-#define LINUX_RAID_PARTITION 0xfd /* autodetect RAID partition */
+ LINUX_SWAP_PARTITION = 0x82,
+ LINUX_RAID_PARTITION = 0xfd, /* autodetect RAID partition */
-#ifdef CONFIG_SOLARIS_X86_PARTITION
-#define SOLARIS_X86_PARTITION LINUX_SWAP_PARTITION
-#endif
+ SOLARIS_X86_PARTITION = LINUX_SWAP_PARTITION,
-#define DM6_PARTITION 0x54 /* has DDO: use xlated geom & offset */
-#define EZD_PARTITION 0x55 /* EZ-DRIVE */
-#define DM6_AUX1PARTITION 0x51 /* no DDO: use xlated geom */
-#define DM6_AUX3PARTITION 0x53 /* no DDO: use xlated geom */
+ DM6_PARTITION = 0x54, /* has DDO: use xlated geom & offset */
+ EZD_PARTITION = 0x55, /* EZ-DRIVE */
+ DM6_AUX1PARTITION = 0x51, /* no DDO: use xlated geom */
+ DM6_AUX3PARTITION = 0x53, /* no DDO: use xlated geom */
+
+ FREEBSD_PARTITION = 0xa5, /* FreeBSD Partition ID */
+ OPENBSD_PARTITION = 0xa6, /* OpenBSD Partition ID */
+ NETBSD_PARTITION = 0xa9, /* NetBSD Partition ID */
+ BSDI_PARTITION = 0xb7, /* BSDI Partition ID */
+/* Ours is not to wonder why.. */
+ BSD_PARTITION = FREEBSD_PARTITION,
+ MINIX_PARTITION = 0x81, /* Minix Partition ID */
+ UNIXWARE_PARTITION = 0x63, /* Partition ID, same as */
+ /* GNU_HURD and SCO Unix */
+};
struct partition {
unsigned char boot_ind; /* 0x80 - active */
@@ -117,13 +127,6 @@ struct solaris_x86_vtoc {
* BSD disklabel support by Yossi Gottlieb <yogo@math.tau.ac.il>
* updated by Marc Espie <Marc.Espie@openbsd.org>
*/
-#define FREEBSD_PARTITION 0xa5 /* FreeBSD Partition ID */
-#define OPENBSD_PARTITION 0xa6 /* OpenBSD Partition ID */
-#define NETBSD_PARTITION 0xa9 /* NetBSD Partition ID */
-#define BSDI_PARTITION 0xb7 /* BSDI Partition ID */
-
-/* Ours is not to wonder why.. */
-#define BSD_PARTITION FREEBSD_PARTITION
/* check against BSD src/sys/sys/disklabel.h for consistency */
@@ -182,8 +185,6 @@ struct bsd_disklabel {
* and Krzysztof G. Baranowski <kgb@knm.org.pl>
*/
-#define UNIXWARE_PARTITION 0x63 /* Partition ID, same as */
- /* GNU_HURD and SCO Unix */
#define UNIXWARE_DISKMAGIC (0xCA5E600DUL) /* The disk magic number */
#define UNIXWARE_DISKMAGIC2 (0x600DDEEEUL) /* The slice table magic nr */
#define UNIXWARE_NUMSLICE 16
@@ -233,7 +234,6 @@ struct unixware_disklabel {
#endif /* CONFIG_UNIXWARE_DISKLABEL */
#ifdef CONFIG_MINIX_SUBPARTITION
-# define MINIX_PARTITION 0x81 /* Minix Partition ID */
# define MINIX_NR_SUBPARTITIONS 4
#endif /* CONFIG_MINIX_SUBPARTITION */
diff --git a/include/linux/module.h b/include/linux/module.h
index d32bf62b8fb0..becc3a0e48c8 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -366,10 +366,10 @@ __attribute__((section("__ksymtab"))) = \
#define __EXPORT_SYMBOL_GPL(sym, str) \
const char __kstrtab_##sym[] \
-__attribute__((section(".kstrtab"))) = str; \
-const struct module_symbol __ksymtab_GPLONLY_##sym \
+__attribute__((section(".kstrtab"))) = "GPLONLY_" str; \
+const struct module_symbol __ksymtab_##sym \
__attribute__((section("__ksymtab"))) = \
-{ (unsigned long)&sym, __kstrtab_GPLONLY_##sym }
+{ (unsigned long)&sym, __kstrtab_##sym }
#if defined(MODVERSIONS) || !defined(CONFIG_MODVERSIONS)
#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var))
diff --git a/include/linux/smb_fs.h b/include/linux/smb_fs.h
index 716e50ec65f9..2200209882ec 100644
--- a/include/linux/smb_fs.h
+++ b/include/linux/smb_fs.h
@@ -161,84 +161,6 @@ smb_is_open(struct inode *i)
}
-/* FIXME! the prototype list is probably not correct. Automate? */
-
-/* linux/fs/smbfs/file.c */
-extern struct inode_operations smb_file_inode_operations;
-extern struct file_operations smb_file_operations;
-extern struct address_space_operations smb_file_aops;
-
-/* linux/fs/smbfs/dir.c */
-extern struct inode_operations smb_dir_inode_operations;
-extern struct file_operations smb_dir_operations;
-void smb_new_dentry(struct dentry *dentry);
-void smb_renew_times(struct dentry *);
-
-/* linux/fs/smbfs/ioctl.c */
-int smb_ioctl (struct inode *, struct file *, unsigned int, unsigned long);
-
-/* linux/fs/smbfs/inode.c */
-struct super_block *smb_read_super(struct super_block *, void *, int);
-void smb_get_inode_attr(struct inode *, struct smb_fattr *);
-void smb_set_inode_attr(struct inode *, struct smb_fattr *);
-void smb_invalidate_inodes(struct smb_sb_info *);
-int smb_revalidate_inode(struct dentry *);
-int smb_notify_change(struct dentry *, struct iattr *);
-struct inode *smb_iget(struct super_block *, struct smb_fattr *);
-
-/* linux/fs/smbfs/proc.c */
-int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp);
-__u32 smb_len(unsigned char *);
-__u8 *smb_setup_header(struct smb_sb_info *, __u8, __u16, __u16);
-int smb_get_rsize(struct smb_sb_info *);
-int smb_get_wsize(struct smb_sb_info *);
-int smb_newconn(struct smb_sb_info *, struct smb_conn_opt *);
-int smb_errno(struct smb_sb_info *);
-int smb_close(struct inode *);
-int smb_close_fileid(struct dentry *, __u16);
-int smb_open(struct dentry *, int);
-int smb_proc_read(struct inode *, off_t, int, char *);
-int smb_proc_write(struct inode *, off_t, int, const char *);
-int smb_proc_create(struct dentry *, __u16, time_t, __u16 *);
-int smb_proc_mv(struct dentry *, struct dentry *);
-int smb_proc_mkdir(struct dentry *);
-int smb_proc_rmdir(struct dentry *);
-int smb_proc_unlink(struct dentry *);
-int smb_proc_readdir(struct file *filp, void *dirent, filldir_t filldir,
- struct smb_cache_control *ctl);
-int smb_proc_getattr(struct dentry *, struct smb_fattr *);
-int smb_proc_setattr(struct dentry *, struct smb_fattr *);
-int smb_proc_settime(struct dentry *, struct smb_fattr *);
-int smb_proc_dskattr(struct super_block *, struct statfs *);
-int smb_proc_disconnect(struct smb_sb_info *);
-int smb_proc_trunc(struct smb_sb_info *, __u16, __u32);
-int smb_proc_flush(struct smb_sb_info *, __u16);
-void smb_init_root_dirent(struct smb_sb_info *, struct smb_fattr *);
-
-/* linux/fs/smbfs/sock.c */
-int smb_round_length(int);
-int smb_valid_socket(struct inode *);
-void smb_close_socket(struct smb_sb_info *);
-int smb_request(struct smb_sb_info *server);
-int smb_catch_keepalive(struct smb_sb_info *server);
-int smb_dont_catch_keepalive(struct smb_sb_info *server);
-int smb_trans2_request(struct smb_sb_info *server, __u16 trans2_command,
- int ldata, unsigned char *data,
- int lparam, unsigned char *param,
- int *lrdata, unsigned char **rdata,
- int *lrparam, unsigned char **rparam);
-
-/* fs/smbfs/cache.c */
-
-void smb_invalid_dir_cache(struct inode * dir);
-void smb_invalidate_dircache_entries(struct dentry *parent);
-struct dentry * smb_dget_fpos(struct dentry *dentry, struct dentry *parent,
- unsigned long fpos);
-int smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
- struct smb_cache_control *ctrl, struct qstr *qname,
- struct smb_fattr *entry);
-
-
#endif /* __KERNEL__ */
#endif /* _LINUX_SMB_FS_H */
diff --git a/include/linux/smbno.h b/include/linux/smbno.h
index 0f25e0265393..aa5ac336c8cf 100644
--- a/include/linux/smbno.h
+++ b/include/linux/smbno.h
@@ -39,7 +39,12 @@
#define ERRbadshare 32 /* Share mode on file conflict with open mode */
#define ERRlock 33 /* Lock request conflicts with existing lock */
#define ERRfilexists 80 /* File in operation already exists */
-#define ERRundocumented1 123 /* Invalid name?? e.g. .tmp* */
+#define ERRinvalidparam 87 /* ERROR_INVALID_PARAMETER */
+#define ERRdiskfull 112 /* ERROR_DISK_FULL */
+#define ERRinvalidname 123 /* ERROR_INVALID_NAME */
+#define ERRdirnotempty 145 /* ERROR_DIR_NOT_EMPTY */
+#define ERRnotlocked 158 /* ERROR_NOT_LOCKED */
+#define ERRexists 183 /* ERROR_ALREADY_EXISTS, see also 80 */
#define ERRbadpipe 230 /* Named pipe invalid */
#define ERRpipebusy 231 /* All instances of pipe are busy */
#define ERRpipeclosing 232 /* named pipe close in progress */
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 1d49bb8e265a..059329c7759e 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -42,6 +42,7 @@
#if (DEBUG_SPINLOCKS < 1)
#define atomic_dec_and_lock(atomic,lock) atomic_dec_and_test(atomic)
+#define ATOMIC_DEC_AND_LOCK
/*
* Your basic spinlocks, allowing only a single CPU anywhere
@@ -128,7 +129,7 @@ typedef struct {
#endif /* !SMP */
/* "lock on reference count zero" */
-#ifndef atomic_dec_and_lock
+#ifndef ATOMIC_DEC_AND_LOCK
#include <asm/atomic.h>
extern int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
#endif
diff --git a/init/main.c b/init/main.c
index d4c15678e4f8..5ef5c9d5e13e 100644
--- a/init/main.c
+++ b/init/main.c
@@ -94,7 +94,6 @@ extern void ppc_init(void);
extern void sysctl_init(void);
extern void signals_init(void);
extern int init_pcmcia_ds(void);
-extern void net_notifier_init(void);
extern void free_initmem(void);
diff --git a/lib/dec_and_lock.c b/lib/dec_and_lock.c
index b9d574ce4eb4..f84d1608bef5 100644
--- a/lib/dec_and_lock.c
+++ b/lib/dec_and_lock.c
@@ -26,7 +26,7 @@
* store-conditional approach, for example.
*/
-#ifndef atomic_dec_and_lock
+#ifndef ATOMIC_DEC_AND_LOCK
int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
{
spin_lock(lock);