Commit e13641c9 authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/scratch/anton/linux-2.5

into samba.org:/scratch/anton/linux-2.5_ppc64_work
parents d3c837bd 467578b9
......@@ -2489,13 +2489,10 @@ E: ken@halcyon.com
D: CDROM driver "sonycd535" (Sony CDU-535/531)
N: Stelian Pop
E: stelian.pop@fr.alcove.com
E: stelian@popies.net
P: 1024D/EDBB6147 7B36 0E07 04BC 11DC A7A0 D3F7 7185 9E7A EDBB 6147
D: sonypi, meye drivers, mct_u232 usb serial hacks
S: Alcve
S: 153, bd. Anatole France
S: 93200 Saint Denis
S: France
S: Paris, France
N: Frederic Potter
E: fpotter@cirpack.com
......
......@@ -8,10 +8,12 @@ if you want to format from within Linux.
VFAT MOUNT OPTIONS
----------------------------------------------------------------------
umask=### -- The permission mask (see umask(1)) for the regulare file.
umask=### -- The permission mask (for files and directories, see umask(1)).
The default is the umask of current process.
dmask=### -- The permission mask for the directory.
The default is the umask of current process.
fmask=### -- The permission mask for files.
The default is the umask of current process.
codepage=### -- Sets the codepage for converting to shortname characters
on FAT and VFAT filesystems. By default, codepage 437
is used. This is the default for the U.S. and some
......
......@@ -95,6 +95,7 @@ where:
SONYPI_ZOOM_MASK 0x0100
SONYPI_THUMBPHRASE_MASK 0x0200
SONYPI_MEYE_MASK 0x0400
SONYPI_MEMORYSTICK_MASK 0x0800
Module use:
-----------
......
......@@ -1112,6 +1112,12 @@ W: http://www.acc.umu.se/~mcalinux/
L: linux-kernel@vger.kernel.org
S: Maintained
MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER
P: Stelian Pop
M: stelian@popies.net
W: http://popies.net/meye/
S: Maintained
MOUSE AND MISC DEVICES [GENERAL]
P: Alessandro Rubini
M: rubini@ipvvis.unipv.it
......@@ -1565,6 +1571,12 @@ M: tsbogend@alpha.franken.de
L: linux-net@vger.kernel.org
S: Maintained
SONY VAIO CONTROL DEVICE DRIVER
P: Stelian Pop
M: stelian@popies.net
W: http://popies.net/sonypi/
S: Maintained
SOUND
P: Jaroslav Kysela
M: perex@suse.cz
......
......@@ -367,6 +367,45 @@ void __init init_ISA_irqs (void)
}
}
static void setup_timer(void)
{
outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
udelay(10);
outb_p(LATCH & 0xff , 0x40); /* LSB */
udelay(10);
outb(LATCH >> 8 , 0x40); /* MSB */
}
static int timer_resume(struct device *dev, u32 level)
{
if (level == RESUME_POWER_ON)
setup_timer();
return 0;
}
static struct device_driver timer_driver = {
.name = "timer",
.bus = &system_bus_type,
.resume = timer_resume,
};
static struct sys_device device_timer = {
.name = "timer",
.id = 0,
.dev = {
.name = "timer",
.driver = &timer_driver,
},
};
static int __init init_timer_devicefs(void)
{
driver_register(&timer_driver);
return sys_device_register(&device_timer);
}
device_initcall(init_timer_devicefs);
void __init init_IRQ(void)
{
int i;
......@@ -386,16 +425,15 @@ void __init init_IRQ(void)
}
/* setup after call gates are initialised (usually add in
* the architecture specific gates */
* the architecture specific gates)
*/
intr_init_hook();
/*
* Set the clock to HZ Hz, we already have a valid
* vector now:
*/
outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
outb_p(LATCH & 0xff , 0x40); /* LSB */
outb(LATCH >> 8 , 0x40); /* MSB */
setup_timer();
/*
* External FPU? Set up irq13 if so, for
......
......@@ -11,7 +11,7 @@ endif
AFLAGS_entry.o := -traditional
AFLAGS_pacache.o := -traditional
export-objs := parisc_ksyms.o keyboard.o
export-objs := parisc_ksyms.o
obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \
pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
......@@ -22,7 +22,6 @@ obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PA11) += pci-dma.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_VT) += keyboard.o
obj-$(CONFIG_PARISC64) += binfmt_elf32.o sys_parisc32.o \
ioctl32.o signal32.o
# only supported for PCX-W/U in 64-bit mode at the moment
......
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
* ---------------------------------------------------------------
* This source file will be removed as soon as we have converted
* hp_psaux.c and hp_keyb.c to the input layer !
*
*/
/*
* linux/arch/parisc/kernel/keyboard.c
*
* Alex deVries <adevries@thepuffingroup.com>
* Copyright (1999) The Puffin Group
* Mostly rewritten by Philipp Rumpf <prumpf@tux.org>
* Copyright 2000 Philipp Rumpf
*/
#include <linux/errno.h>
#include <linux/keyboard.h>
#include <asm/keyboard.h>
#include <linux/module.h>
static int def_setkeycode(unsigned int x, unsigned int y)
{
return 0;
}
static int def_getkeycode(unsigned int x)
{
return 0;
}
static int def_translate(unsigned char scancode, unsigned char *keycode,
char raw)
{
*keycode = scancode;
return 1;
}
static char def_unexpected_up(unsigned char c)
{
return 128;
}
static void def_leds(unsigned char leds)
{
}
static void def_init_hw(void)
{
}
static char def_sysrq_xlate[NR_KEYS];
#define DEFAULT_KEYB_OPS \
.setkeycode = def_setkeycode, \
.getkeycode = def_getkeycode, \
.translate = def_translate, \
.unexpected_up = def_unexpected_up, \
.leds = def_leds, \
.init_hw = def_init_hw, \
.sysrq_key = 0xff, \
.sysrq_xlate = def_sysrq_xlate,
static struct kbd_ops def_kbd_ops = {
DEFAULT_KEYB_OPS
};
struct kbd_ops *kbd_ops = &def_kbd_ops;
void unregister_kbd_ops(void)
{
struct kbd_ops new_kbd_ops = { DEFAULT_KEYB_OPS };
register_kbd_ops(&new_kbd_ops);
}
EXPORT_SYMBOL(unregister_kbd_ops);
void register_kbd_ops(struct kbd_ops *ops)
{
if(ops->setkeycode)
kbd_ops->setkeycode = ops->setkeycode;
if(ops->getkeycode)
kbd_ops->getkeycode = ops->getkeycode;
if(ops->translate)
kbd_ops->translate = ops->translate;
if(ops->unexpected_up)
kbd_ops->unexpected_up = ops->unexpected_up;
if(ops->leds)
kbd_ops->leds = ops->leds;
if(ops->init_hw)
kbd_ops->init_hw = ops->init_hw;
kbd_ops->sysrq_key = ops->sysrq_key;
kbd_ops->sysrq_xlate = ops->sysrq_xlate;
}
......@@ -90,11 +90,13 @@ extern void dump_thread(struct pt_regs *, struct user *);
#define EXPORT_SYMBOL_DOT(sym) \
extern int __sparc_dot_ ## sym (int) __asm__("." #sym); \
__EXPORT_SYMBOL(__sparc_dot_ ## sym, "." #sym)
const struct kernel_symbol __ksymtab___sparc_dot_##sym \
__attribute__((section("__ksymtab"))) \
= { (unsigned long)&__sparc_dot_##sym , "." #sym }
#define EXPORT_SYMBOL_PRIVATE(sym) \
extern int __sparc_priv_ ## sym (int) __asm__("__" #sym); \
const struct module_symbol __export_priv_##sym \
const struct kernel_symbol __export_priv_##sym \
__attribute__((section("__ksymtab"))) = \
{ (unsigned long) &__sparc_priv_ ## sym, "__" #sym }
......
......@@ -34,6 +34,8 @@
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <net/sock.h>
#include <asm/uaccess.h>
#ifndef KERNEL_DS
#include <linux/segment.h>
......
......@@ -16,6 +16,7 @@
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/timex.h>
#include <linux/interrupt.h>
#include <asm/oplib.h>
#include <asm/segment.h>
......
......@@ -192,9 +192,9 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu
{
unsigned long page, oldpage = 0;
while(sz >= 0) {
while(sz != 0) {
--sz;
page = ((unsigned long) sg[sz].offset) & PAGE_MASK;
page = (unsigned long) page_address(sg[sz].page);
if (oldpage == page)
page += PAGE_SIZE; /* We flushed that page already */
while(page < (unsigned long)(page_address(sg[sz].page) + sg[sz].offset + sg[sz].length)) {
......
......@@ -19,6 +19,7 @@ CC := $(shell if gcc -m64 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then e
NEW_GCC := $(shell if $(CC) -m64 -mcmodel=medlow -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
NEW_GAS := $(shell if $(LD) -V 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
UNDECLARED_REGS := $(shell if $(CC) -c -x assembler /dev/null -Wa,--help | grep undeclared-regs > /dev/null; then echo y; else echo n; fi; )
INLINE_LIMIT := $(shell if $(CC) -m64 -finline-limit=100000 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
export NEW_GCC
......@@ -51,6 +52,10 @@ else
AFLAGS += -m64 -mcpu=ultrasparc $(CC_UNDECL)
endif
ifeq ($(INLINE_LIMIT),y)
CFLAGS := $(CFLAGS) -finline-limit=100000
endif
ifeq ($(CONFIG_MCOUNT),y)
CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS))
CFLAGS := $(CFLAGS) -pg
......
......@@ -145,28 +145,28 @@ void __init smp_callin(void)
* purposes. Also workaround BB_ERRATA_1 by doing a dummy
* read back of %tick after writing it.
*/
__asm__ __volatile__("
sethi %%hi(0x80000000), %%g1
ba,pt %%xcc, 1f
sllx %%g1, 32, %%g1
.align 64
1: rd %%tick, %%g2
add %%g2, 6, %%g2
andn %%g2, %%g1, %%g2
wrpr %%g2, 0, %%tick
rdpr %%tick, %%g0"
__asm__ __volatile__(
"sethi %%hi(0x80000000), %%g1\n\t"
"ba,pt %%xcc, 1f\n\t"
" sllx %%g1, 32, %%g1\n\t"
".align 64\n"
"1: rd %%tick, %%g2\n\t"
"add %%g2, 6, %%g2\n\t"
"andn %%g2, %%g1, %%g2\n\t"
"wrpr %%g2, 0, %%tick\n\t"
"rdpr %%tick, %%g0"
: /* no outputs */
: /* no inputs */
: "g1", "g2");
if (SPARC64_USE_STICK) {
/* Let the user get at STICK too. */
__asm__ __volatile__("
sethi %%hi(0x80000000), %%g1
sllx %%g1, 32, %%g1
rd %%asr24, %%g2
andn %%g2, %%g1, %%g2
wr %%g2, 0, %%asr24"
__asm__ __volatile__(
"sethi %%hi(0x80000000), %%g1\n\t"
"sllx %%g1, 32, %%g1\n\t"
"rd %%asr24, %%g2\n\t"
"andn %%g2, %%g1, %%g2\n\t"
"wr %%g2, 0, %%asr24"
: /* no outputs */
: /* no inputs */
: "g1", "g2");
......@@ -283,18 +283,18 @@ static void spitfire_xcall_helper(u64 data0, u64 data1, u64 data2, u64 pstate, u
* ADDR 0x20) for the dummy read. -DaveM
*/
tmp = 0x40;
__asm__ __volatile__("
wrpr %1, %2, %%pstate
stxa %4, [%0] %3
stxa %5, [%0+%8] %3
add %0, %8, %0
stxa %6, [%0+%8] %3
membar #Sync
stxa %%g0, [%7] %3
membar #Sync
mov 0x20, %%g1
ldxa [%%g1] 0x7f, %%g0
membar #Sync"
__asm__ __volatile__(
"wrpr %1, %2, %%pstate\n\t"
"stxa %4, [%0] %3\n\t"
"stxa %5, [%0+%8] %3\n\t"
"add %0, %8, %0\n\t"
"stxa %6, [%0+%8] %3\n\t"
"membar #Sync\n\t"
"stxa %%g0, [%7] %3\n\t"
"membar #Sync\n\t"
"mov 0x20, %%g1\n\t"
"ldxa [%%g1] 0x7f, %%g0\n\t"
"membar #Sync"
: "=r" (tmp)
: "r" (pstate), "i" (PSTATE_IE), "i" (ASI_INTR_W),
"r" (data0), "r" (data1), "r" (data2), "r" (target),
......@@ -1054,21 +1054,21 @@ static void __init smp_setup_percpu_timer(void)
* read back from %tick_cmpr right after writing to it. -DaveM
*/
if (!SPARC64_USE_STICK) {
__asm__ __volatile__("
rd %%tick, %%g1
ba,pt %%xcc, 1f
add %%g1, %0, %%g1
.align 64
1: wr %%g1, 0x0, %%tick_cmpr
rd %%tick_cmpr, %%g0"
__asm__ __volatile__(
"rd %%tick, %%g1\n\t"
"ba,pt %%xcc, 1f\n\t"
" add %%g1, %0, %%g1\n\t"
".align 64\n"
"1: wr %%g1, 0x0, %%tick_cmpr\n\t"
"rd %%tick_cmpr, %%g0"
: /* no outputs */
: "r" (current_tick_offset)
: "g1");
} else {
__asm__ __volatile__("
rd %%asr24, %%g1
add %%g1, %0, %%g1
wr %%g1, 0x0, %%asr25"
__asm__ __volatile__(
"rd %%asr24, %%g1\n\t"
"add %%g1, %0, %%g1\n\t"
"wr %%g1, 0x0, %%asr25"
: /* no outputs */
: "r" (current_tick_offset)
: "g1");
......
......@@ -51,6 +51,7 @@
#include <linux/sysctl.h>
#include <linux/binfmts.h>
#include <linux/dnotify.h>
#include <linux/security.h>
#include <asm/types.h>
#include <asm/ipc.h>
......@@ -1096,7 +1097,7 @@ static long do_readv_writev32(int type, struct file *file,
/* VERIFY_WRITE actually means a read, as we write to user space */
if ((retval + (type == VERIFY_WRITE)) > 0)
dnotify_parent(file->f_dentry,
(type == VERIFY_WRITE) ? DN_MODIFY : DN_ACCESS);
(type == VERIFY_WRITE) ? DN_ACCESS : DN_MODIFY);
return retval;
}
......
......@@ -369,6 +369,7 @@ static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
case 106: /* SI_GETINTRANSIT */
case 107: /* SI_TCL_LINK */
case 108: /* SI_TCL_UNLINK */
;
}
return TNOTSUPPORT;
}
......@@ -456,6 +457,7 @@ static inline int solaris_timod(unsigned int fd, unsigned int cmd, u32 arg,
case 145: /* TI_GETPEERNAME */
case 146: /* TI_SETMYNAME */
case 147: /* TI_SETPEERNAME */
;
}
return TNOTSUPPORT;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -37,7 +37,7 @@
#ifdef __KERNEL__
#define SONYPI_DRIVER_MAJORVERSION 1
#define SONYPI_DRIVER_MINORVERSION 15
#define SONYPI_DRIVER_MINORVERSION 16
#define SONYPI_DEVICE_MODEL_TYPE1 1
#define SONYPI_DEVICE_MODEL_TYPE2 2
......@@ -165,6 +165,7 @@ static struct sonypi_irq_list sonypi_type2_irq_list[] = {
#define SONYPI_ZOOM_MASK 0x00000100
#define SONYPI_THUMBPHRASE_MASK 0x00000200
#define SONYPI_MEYE_MASK 0x00000400
#define SONYPI_MEMORYSTICK_MASK 0x00000800
struct sonypi_event {
u8 data;
......@@ -262,7 +263,7 @@ static struct sonypi_event sonypi_lidev[] = {
/* The set of possible zoom events */
static struct sonypi_event sonypi_zoomev[] = {
{ 0x3a, SONYPI_EVENT_ZOOM_PRESSED },
{ 0x39, SONYPI_EVENT_ZOOM_PRESSED },
{ 0, 0 }
};
......@@ -279,6 +280,13 @@ static struct sonypi_event sonypi_meyeev[] = {
{ 0, 0 }
};
/* The set of possible memorystick events */
static struct sonypi_event sonypi_memorystickev[] = {
{ 0x53, SONYPI_EVENT_MEMORYSTICK_INSERT },
{ 0x54, SONYPI_EVENT_MEMORYSTICK_EJECT },
{ 0, 0 }
};
struct sonypi_eventtypes {
int model;
u8 data;
......@@ -303,6 +311,7 @@ struct sonypi_eventtypes {
{ SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_HELP_MASK, sonypi_helpev },
{ SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_ZOOM_MASK, sonypi_zoomev },
{ SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
{ SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
{ 0, 0, 0, 0 }
};
......
......@@ -8,13 +8,17 @@ obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o
obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o
obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI) += cpci_hotplug.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o
pci_hotplug-objs := pci_hotplug_core.o \
pci_hotplug_util.o
ifdef CONFIG_HOTPLUG_PCI_CPCI
pci_hotplug-objs += cpci_hotplug_core.o \
cpci_hotplug_pci.o
endif
cpqphp-objs := cpqphp_core.o \
cpqphp_ctrl.o \
cpqphp_proc.o \
......@@ -31,9 +35,6 @@ acpiphp-objs := acpiphp_core.o \
acpiphp_pci.o \
acpiphp_res.o
cpci_hotplug-objs := cpci_hotplug_core.o \
cpci_hotplug_pci.o
ifdef CONFIG_HOTPLUG_PCI_ACPI
EXTRA_CFLAGS += -D_LINUX -I$(TOPDIR)/drivers/acpi
ifdef CONFIG_ACPI_DEBUG
......
......@@ -891,16 +891,17 @@ cleanup_slots(void)
return;
}
static int __init
cpci_hotplug_init(void)
int __init
cpci_hotplug_init(int debug)
{
spin_lock_init(&list_lock);
cpci_debug = debug;
info(DRIVER_DESC " version: " DRIVER_VERSION);
return 0;
}
static void __exit
void __exit
cpci_hotplug_exit(void)
{
/*
......@@ -909,14 +910,6 @@ cpci_hotplug_exit(void)
cleanup_slots();
}
module_init(cpci_hotplug_init);
module_exit(cpci_hotplug_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_PARM(cpci_debug, "i");
MODULE_PARM_DESC(cpci_debug, "Debugging mode");
EXPORT_SYMBOL_GPL(cpci_hp_register_controller);
EXPORT_SYMBOL_GPL(cpci_hp_unregister_controller);
......
......@@ -572,16 +572,16 @@ static int unconfigure_visit_pci_bus_phase2(struct pci_bus_wrapped *wrapped_bus,
}
static struct pci_visit configure_functions = {
visit_pci_dev:configure_visit_pci_dev,
.visit_pci_dev = configure_visit_pci_dev,
};
static struct pci_visit unconfigure_functions_phase1 = {
post_visit_pci_dev:unconfigure_visit_pci_dev_phase1
.post_visit_pci_dev = unconfigure_visit_pci_dev_phase1
};
static struct pci_visit unconfigure_functions_phase2 = {
post_visit_pci_bus:unconfigure_visit_pci_bus_phase2,
post_visit_pci_dev:unconfigure_visit_pci_dev_phase2
.post_visit_pci_bus = unconfigure_visit_pci_bus_phase2,
.post_visit_pci_dev = unconfigure_visit_pci_dev_phase2
};
......
......@@ -1240,11 +1240,11 @@ void ibmphp_free_ebda_pci_rsrc_queue (void)
static struct pci_device_id id_table[] __devinitdata = {
{
vendor: PCI_VENDOR_ID_IBM,
device: HPC_DEVICE_ID,
subvendor: PCI_VENDOR_ID_IBM,
subdevice: HPC_SUBSYSTEM_ID,
class: ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00),
.vendor = PCI_VENDOR_ID_IBM,
.device = HPC_DEVICE_ID,
.subvendor = PCI_VENDOR_ID_IBM,
.subdevice = HPC_SUBSYSTEM_ID,
.class = ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00),
}, {}
};
......@@ -1252,9 +1252,9 @@ MODULE_DEVICE_TABLE(pci, id_table);
static int ibmphp_probe (struct pci_dev *, const struct pci_device_id *);
static struct pci_driver ibmphp_driver = {
name: "ibmphp",
id_table: id_table,
probe: ibmphp_probe,
.name = "ibmphp",
.id_table = id_table,
.probe = ibmphp_probe,
};
int ibmphp_register_pci (void)
......
......@@ -60,8 +60,8 @@
/* local variables */
static int debug;
#define DRIVER_VERSION "0.4"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
#define DRIVER_VERSION "0.5"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Scott Murray <scottm@somanetworks.com>"
#define DRIVER_DESC "PCI Hot Plug PCI Core"
......@@ -89,7 +89,7 @@ static int pcihpfs_mount_count; /* times we have mounted our fs */
static spinlock_t mount_lock; /* protects our mount_count */
static spinlock_t list_lock;
LIST_HEAD(pci_hotplug_slot_list);
static LIST_HEAD(pci_hotplug_slot_list);
/* these strings match up with the values in pci_bus_speed */
static char *pci_bus_speed_strings[] = {
......@@ -121,6 +121,14 @@ static struct proc_dir_entry *slotdir = NULL;
static const char *slotdir_name = "slots";
#endif
#ifdef CONFIG_HOTPLUG_PCI_CPCI
extern int cpci_hotplug_init(int debug);
extern void cpci_hotplug_exit(void);
#else
static inline int cpci_hotplug_init(int debug) { return 0; }
static inline void cpci_hotplug_exit(void) { }
#endif
static struct inode *pcihpfs_get_inode (struct super_block *sb, int mode, dev_t dev)
{
struct inode *inode = new_inode(sb);
......@@ -311,19 +319,19 @@ static struct file_operations presence_file_operations = {
/* file ops for the "max bus speed" files */
static ssize_t max_bus_speed_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
static struct file_operations max_bus_speed_file_operations = {
read: max_bus_speed_read_file,
write: default_write_file,
open: default_open,
llseek: default_file_lseek,
.read = max_bus_speed_read_file,
.write = default_write_file,
.open = default_open,
.llseek = default_file_lseek,
};
/* file ops for the "current bus speed" files */
static ssize_t cur_bus_speed_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
static struct file_operations cur_bus_speed_file_operations = {
read: cur_bus_speed_read_file,
write: default_write_file,
open: default_open,
llseek: default_file_lseek,
.read = cur_bus_speed_read_file,
.write = default_write_file,
.open = default_open,
.llseek = default_file_lseek,
};
/* file ops for the "test" files */
......@@ -1273,19 +1281,30 @@ static int __init pci_hotplug_init (void)
goto exit;
}
result = cpci_hotplug_init(debug);
if (result) {
err ("cpci_hotplug_init with error %d\n", result);
goto error_fs;
}
#ifdef CONFIG_PROC_FS
/* create mount point for pcihpfs */
slotdir = proc_mkdir(slotdir_name, proc_bus_pci_dir);
#endif
info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
goto exit;
error_fs:
unregister_filesystem(&pcihpfs_type);
exit:
return result;
}
static void __exit pci_hotplug_exit (void)
{
cpci_hotplug_exit();
unregister_filesystem(&pcihpfs_type);
#ifdef CONFIG_PROC_FS
......
......@@ -6,83 +6,6 @@
#include <linux/mc146818rtc.h>
#include <asm/io.h>
/*
* We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc
* controller that is BIOS compatible with ST-506, and thus showing up in our
* BIOS table, but not register compatible, and therefore not present in CMOS.
*
* Furthermore, we will assume that our ST-506 drives <if any> are the primary
* drives in the system -- the ones reflected as drive 1 or 2. The first
* drive is stored in the high nibble of CMOS byte 0x12, the second in the low
* nibble. This will be either a 4 bit drive type or 0xf indicating use byte
* 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. A non-zero value
* means we have an AT controller hard disk for that drive.
*
* Of course, there is no guarantee that either drive is actually on the
* "primary" IDE interface, but we don't bother trying to sort that out here.
* If a drive is not actually on the primary interface, then these parameters
* will be ignored. This results in the user having to supply the logical
* drive geometry as a boot parameter for each drive not on the primary i/f.
*
* The only "perfect" way to handle this would be to modify the setup.[cS] code
* to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info
* for us during initialization. I have the necessary docs -- any takers? -ml
*
* I did this, but it doesn't work - there is no reasonable way to find the
* correspondence between the BIOS numbering of the disks and the Linux
* numbering. -aeb
*
* The code below is bad. One of the problems is that drives 1 and 2
* may be SCSI disks (even when IDE disks are present), so that
* the geometry we read here from BIOS is attributed to the wrong disks.
* Consequently, also the former "drive->present = 1" below was a mistake.
*
* Eventually the entire routine below should be removed.
*
* 17-OCT-2000 rjohnson@analogic.com Added spin-locks for reading CMOS
* chip.
*/
void probe_cmos_for_drives (ide_hwif_t *hwif)
{
#ifdef __i386__
extern struct drive_info_struct drive_info;
u8 cmos_disks, *BIOS = (u8 *) &drive_info;
int unit;
unsigned long flags;
if (hwif->chipset == ide_pdc4030 && hwif->channel != 0)
return;
spin_lock_irqsave(&rtc_lock, flags);
cmos_disks = CMOS_READ(0x12);
spin_unlock_irqrestore(&rtc_lock, flags);
/* Extract drive geometry from CMOS+BIOS if not already setup */
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
if ((cmos_disks & (0xf0 >> (unit*4)))
&& !drive->present && !drive->nobios) {
u16 cyl = *(u16 *)BIOS;
unsigned char head = *(BIOS+2);
unsigned char sect = *(BIOS+14);
if (cyl > 0 && head > 0 && sect > 0 && sect < 64) {
drive->cyl = drive->bios_cyl = cyl;
drive->head = drive->bios_head = head;
drive->sect = drive->bios_sect = sect;
drive->ctl = *(BIOS+8);
} else {
printk("hd%c: C/H/S=%d/%d/%d from BIOS ignored\n",
unit+'a', cyl, head, sect);
}
}
BIOS += 16;
}
#endif
}
extern unsigned long current_capacity (ide_drive_t *);
/*
......
......@@ -639,12 +639,6 @@ void probe_hwif (ide_hwif_t *hwif)
if (hwif->noprobe)
return;
#ifdef CONFIG_BLK_DEV_IDE
if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) {
extern void probe_cmos_for_drives(ide_hwif_t *);
probe_cmos_for_drives(hwif);
}
#endif
if ((hwif->chipset != ide_4drives || !hwif->mate || !hwif->mate->present) &&
#if CONFIG_BLK_DEV_PDC4030
......
......@@ -56,3 +56,12 @@ config INPUT_UINPUT
The module will be called uinput.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
config INPUT_GSC
tristate "PA-RISC GSC PS/2 keyboard/mouse support"
depends on GSC && INPUT && INPUT_MISC
help
Say Y here if you have a PS/2 keyboard and/or mouse attached
to your PA-RISC box. HP run the keyboard in AT mode rather than
XT mode like everyone else, so we need our own driver.
Furthermore, the GSC PS/2 controller shares IRQ between mouse and
keyboard.
......@@ -8,7 +8,4 @@ obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
# The global Rules.make.
include $(TOPDIR)/Rules.make
obj-$(CONFIG_INPUT_GSC) += gsc_ps2.o
This diff is collapsed.
......@@ -982,7 +982,7 @@ static struct i2c_driver driver = {
.detach_client = tuner_detach,
.command = tuner_command,
};
static structi2c_clientclient_template =
static struct i2c_client client_template =
{
.name = "(tunerunset)",
.flags = I2C_CLIENT_ALLOW_USE,
......
......@@ -245,7 +245,7 @@ static void add_us_sample(struct mm_struct * mm, struct op_sample * s)
static inline int is_kernel(unsigned long val)
{
return val > __PAGE_OFFSET;
return val > PAGE_OFFSET;
}
......
......@@ -21,6 +21,7 @@
#include <linux/vmalloc.h>
#include <linux/smp.h>
#include <linux/errno.h>
#include <linux/cache.h>
#include "cpu_buffer.h"
#include "oprof.h"
......
......@@ -12,6 +12,7 @@
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/cache.h>
struct task_struct;
......
......@@ -1586,8 +1586,9 @@ static void __init sunzilog_init_hw(void)
} else {
/* Normal serial TTY. */
up->parity_mask = 0xff;
up->curregs[R3] = RxENAB;
up->curregs[R5] = TxENAB;
up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
up->curregs[R3] = RxENAB | Rx8;
up->curregs[R5] = TxENAB | Tx8;
up->curregs[R9] = NV | MIE;
up->curregs[R10] = NRZ;
up->curregs[R11] = TCBR | RCBR;
......
......@@ -239,18 +239,14 @@ extern __inline__ struct async *async_getpending(struct dev_state *ps, void *use
{
unsigned long flags;
struct async *as;
struct list_head *p;
spin_lock_irqsave(&ps->lock, flags);
for (p = ps->async_pending.next; p != &ps->async_pending; ) {
as = list_entry(p, struct async, asynclist);
p = p->next;
if (as->userurb != userurb)
continue;
list_del_init(&as->asynclist);
spin_unlock_irqrestore(&ps->lock, flags);
return as;
}
list_for_each_entry(as, &ps->async_pending, asynclist)
if (as->userurb == userurb) {
list_del_init(&as->asynclist);
spin_unlock_irqrestore(&ps->lock, flags);
return as;
}
spin_unlock_irqrestore(&ps->lock, flags);
return NULL;
}
......@@ -295,19 +291,14 @@ static void destroy_async (struct dev_state *ps, struct list_head *list)
static void destroy_async_on_interface (struct dev_state *ps, unsigned int intf)
{
struct async *as;
struct list_head *p, hitlist;
struct list_head *p, *q, hitlist;
unsigned long flags;
INIT_LIST_HEAD(&hitlist);
spin_lock_irqsave(&ps->lock, flags);
for (p = ps->async_pending.next; p != &ps->async_pending; ) {
as = list_entry(p, struct async, asynclist);
p = p->next;
if (as->intf == intf)
list_move_tail(&as->asynclist, &hitlist);
}
list_for_each_safe(p, q, &ps->async_pending)
if (intf == list_entry(p, struct async, asynclist)->intf)
list_move_tail(p, &hitlist);
spin_unlock_irqrestore(&ps->lock, flags);
destroy_async(ps, &hitlist);
}
......@@ -869,7 +860,7 @@ static int proc_submiturb(struct dev_state *ps, void *arg)
if (uurb.buffer_length > 16384)
return -EINVAL;
if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
return -EFAULT;
return -EFAULT;
break;
default:
......@@ -964,10 +955,10 @@ static int processcompl(struct async *as)
if (!(usb_pipeisoc(urb->pipe)))
return 0;
for (i = 0; i < urb->number_of_packets; i++) {
if (put_user(urb->iso_frame_desc[i].actual_length,
if (put_user(urb->iso_frame_desc[i].actual_length,
&((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].actual_length))
return -EFAULT;
if (put_user(urb->iso_frame_desc[i].status,
if (put_user(urb->iso_frame_desc[i].status,
&((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].status))
return -EFAULT;
}
......@@ -1099,12 +1090,10 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
else switch (ctrl.ioctl_code) {
/* disconnect kernel driver from interface, leaving it unbound. */
/* maybe unbound - you get no guarantee it stays unbound */
case USBDEVFS_DISCONNECT:
/* this function is voodoo. */
/* which function ... usb_device_remove()?
* FIXME either the module lock (BKL) should be involved
* here too, or the 'default' case below is broken
*/
/* this function is misdesigned - retained for compatibility */
lock_kernel();
driver = ifp->driver;
if (driver) {
dbg ("disconnect '%s' from dev %d interface %d",
......@@ -1112,11 +1101,14 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
usb_device_remove(&ifp->dev);
} else
retval = -ENODATA;
unlock_kernel();
break;
/* let kernel drivers try to (re)bind to the interface */
case USBDEVFS_CONNECT:
lock_kernel();
retval = usb_device_probe (&ifp->dev);
unlock_kernel();
break;
/* talk directly to the interface's driver */
......@@ -1131,20 +1123,17 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
unlock_kernel();
retval = -ENOSYS;
} else {
if (driver->owner
&& !try_inc_mod_count (driver->owner)) {
if (!try_module_get (driver->owner)) {
unlock_kernel();
retval = -ENOSYS;
break;
}
unlock_kernel ();
retval = driver->ioctl (ifp, ctrl.ioctl_code, buf);
if (driver->owner)
__MOD_DEC_USE_COUNT (driver->owner);
if (retval == -ENOIOCTLCMD)
retval = -ENOTTY;
module_put (driver->owner);
}
if (retval == -ENOIOCTLCMD)
retval = -ENOTTY;
}
/* cleanup and return */
......@@ -1197,7 +1186,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
case USBDEVFS_RESET:
ret = proc_resetdevice(ps);
break;
case USBDEVFS_CLEAR_HALT:
ret = proc_clearhalt(ps, (void *)arg);
if (ret >= 0)
......
......@@ -146,7 +146,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
goto clean_2;
}
info ("%s @ %s, %s", hcd->description, dev->slot_name, dev->dev.name);
dev_info (*hcd->controller, "%s\n", hcd->product_desc);
#ifndef __sparc__
sprintf (buf, "%d", dev->irq);
......@@ -155,7 +155,8 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
#endif
if (request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ, hcd->description, hcd)
!= 0) {
err ("request interrupt %s failed", bufp);
dev_err (*hcd->controller,
"request interrupt %s failed\n", bufp);
retval = -EBUSY;
goto clean_3;
}
......@@ -163,7 +164,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
hcd->regs = base;
hcd->region = region;
info ("irq %s, %s %p", bufp,
dev_info (*hcd->controller, "irq %s, %s %p\n", bufp,
(driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
base);
......@@ -205,19 +206,20 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
hcd = pci_get_drvdata(dev);
if (!hcd)
return;
info ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
dev_info (*hcd->controller, "remove, state %x\n", hcd->state);
if (in_interrupt ()) BUG ();
hub = hcd->self.root_hub;
hcd->state = USB_STATE_QUIESCING;
dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);
dev_dbg (*hcd->controller, "roothub graceful disconnect\n");
usb_disconnect (&hub);
hcd->driver->stop (hcd);
hcd_buffer_destroy (hcd);
hcd->state = USB_STATE_HALT;
pci_set_drvdata (dev, 0);
free_irq (hcd->irq, hcd);
if (hcd->driver->flags & HCD_MEMORY) {
......@@ -230,9 +232,12 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
}
usb_deregister_bus (&hcd->self);
if (atomic_read (&hcd->self.refcnt) != 1)
err ("usb_hcd_pci_remove %s, count != 1", hcd->self.bus_name);
if (atomic_read (&hcd->self.refcnt) != 1) {
dev_warn (*hcd->controller,
"dangling refs (%d) to bus %d!\n",
atomic_read (&hcd->self.refcnt) - 1,
hcd->self.busnum);
}
hcd->driver->hcd_free (hcd);
}
EXPORT_SYMBOL (usb_hcd_pci_remove);
......@@ -279,7 +284,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
int retval;
hcd = pci_get_drvdata(dev);
info ("suspend %s to state %d", hcd->self.bus_name, state);
dev_info (*hcd->controller, "suspend to state %d\n", state);
pci_save_state (dev, hcd->pci_state);
......@@ -308,19 +313,19 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
int retval;
hcd = pci_get_drvdata(dev);
info ("resume %s", hcd->self.bus_name);
dev_info (*hcd->controller, "resume\n");
/* guard against multiple resumes (APM bug?) */
atomic_inc (&hcd->resume_count);
if (atomic_read (&hcd->resume_count) != 1) {
err ("concurrent PCI resumes for %s", hcd->self.bus_name);
dev_err (*hcd->controller, "concurrent PCI resumes\n");
retval = 0;
goto done;
}
retval = -EBUSY;
if (hcd->state != USB_STATE_SUSPENDED) {
dbg ("can't resume, not suspended!");
dev_dbg (*hcd->controller, "can't resume, not suspended!\n");
goto done;
}
hcd->state = USB_STATE_RESUMING;
......@@ -330,7 +335,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
retval = hcd->driver->resume (hcd);
if (!HCD_IS_RUNNING (hcd->state)) {
dbg ("resume %s failure, retval %d", hcd->self.bus_name, retval);
dev_dbg (*hcd->controller, "resume fail, retval %d\n", retval);
usb_hc_died (hcd);
// FIXME: recover, reset etc.
} else {
......
......@@ -715,7 +715,8 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev
sprintf (&usb_dev->dev.bus_id[0], "usb%d", usb_dev->bus->busnum);
retval = usb_new_device (usb_dev, parent_dev);
if (retval)
err("%s - usb_new_device failed with value %d", __FUNCTION__, retval);
dev_err (*parent_dev, "can't register root hub for %s, %d\n",
usb_dev->dev.bus_id, retval);
return retval;
}
EXPORT_SYMBOL (usb_register_root_hub);
......@@ -1286,13 +1287,7 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
// NOTE: a generic device/urb monitoring hook would go here.
// hcd_monitor_hook(MONITOR_URB_FINISH, urb, dev)
// It would catch exit/unlink paths for all urbs, but non-exit
// completions for periodic urbs need hooks inside the HCD.
// hcd_monitor_hook(MONITOR_URB_UPDATE, urb, dev)
if (urb->status)
dbg ("giveback urb %p status %d len %d",
urb, urb->status, urb->actual_length);
// It would catch exit/unlink paths for all urbs.
/* lower level hcd code should use *_dma exclusively */
if (!(urb->transfer_flags & URB_NO_DMA_MAP)) {
......
......@@ -69,24 +69,23 @@ static struct device_driver usb_generic_driver = {
.probe = generic_probe,
.remove = generic_remove,
};
/* needs to be called with BKL held */
int usb_device_probe(struct device *dev)
{
struct usb_interface * intf = to_usb_interface(dev);
struct usb_driver * driver = to_usb_driver(dev->driver);
const struct usb_device_id *id;
int error = -ENODEV;
int m;
dbg("%s", __FUNCTION__);
if (!driver->probe)
return error;
if (driver->owner) {
m = try_inc_mod_count(driver->owner);
if (m == 0)
return error;
if (!try_module_get(driver->owner)) {
err ("Can't get a module reference for %s", driver->name);
return error;
}
id = usb_match_id (intf, driver->id_table);
......@@ -99,8 +98,7 @@ int usb_device_probe(struct device *dev)
if (!error)
intf->driver = driver;
if (driver->owner)
__MOD_DEC_USE_COUNT(driver->owner);
module_put(driver->owner);
return error;
}
......@@ -109,7 +107,6 @@ int usb_device_remove(struct device *dev)
{
struct usb_interface *intf;
struct usb_driver *driver;
int m;
intf = list_entry(dev,struct usb_interface,dev);
driver = to_usb_driver(dev->driver);
......@@ -120,14 +117,11 @@ int usb_device_remove(struct device *dev)
return -ENODEV;
}
if (driver->owner) {
m = try_inc_mod_count(driver->owner);
if (m == 0) {
// FIXME this happens even when we just rmmod
// drivers that aren't in active use...
err("Dieing driver still bound to device.\n");
return -EIO;
}
if (!try_module_get(driver->owner)) {
// FIXME this happens even when we just rmmod
// drivers that aren't in active use...
err("Dieing driver still bound to device.\n");
return -EIO;
}
/* if we sleep here on an umanaged driver
......@@ -143,8 +137,7 @@ int usb_device_remove(struct device *dev)
usb_driver_release_interface(driver, intf);
up(&driver->serialize);
if (driver->owner)
__MOD_DEC_USE_COUNT(driver->owner);
module_put(driver->owner);
return 0;
}
......
......@@ -18,6 +18,17 @@
/* this file is part of ehci-hcd.c */
#define ehci_dbg(ehci, fmt, args...) \
dev_dbg (*(ehci)->hcd.controller, fmt, ## args )
#ifdef EHCI_VERBOSE_DEBUG
#define ehci_vdbg(ehci, fmt, args...) \
dev_dbg (*(ehci)->hcd.controller, fmt, ## args )
#else
#define ehci_vdbg(ehci, fmt, args...) do { } while (0)
#endif
#ifdef EHCI_VERBOSE_DEBUG
# define vdbg dbg
#else
......@@ -34,7 +45,8 @@ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label)
{
u32 params = readl (&ehci->caps->hcs_params);
dbg ("%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d",
ehci_dbg (ehci,
"%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d\n",
label, params,
HCS_DEBUG_PORT (params),
HCS_INDICATOR (params) ? " ind" : "",
......@@ -56,9 +68,8 @@ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label)
((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf)));
strcat(buf, tmp);
}
dbg ("%s: %s portroute %s",
hcd_to_bus (&ehci->hcd)->bus_name, label,
buf);
ehci_dbg (ehci, "%s portroute %s\n",
label, buf);
}
}
#else
......@@ -77,19 +88,16 @@ static void dbg_hcc_params (struct ehci_hcd *ehci, char *label)
{
u32 params = readl (&ehci->caps->hcc_params);
if (HCC_EXT_CAPS (params)) {
// EHCI 0.96 ... could interpret these (legacy?)
dbg ("%s extended capabilities at pci %2x",
label, HCC_EXT_CAPS (params));
}
if (HCC_ISOC_CACHE (params)) {
dbg ("%s hcc_params %04x caching frame %s%s%s",
ehci_dbg (ehci,
"%s hcc_params %04x caching frame %s%s%s\n",
label, params,
HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024",
HCC_CANPARK (params) ? " park" : "",
HCC_64BIT_ADDR (params) ? " 64 bit addr" : "");
} else {
dbg ("%s hcc_params %04x caching %d uframes %s%s%s",
ehci_dbg (ehci,
"%s hcc_params %04x thresh %d uframes %s%s%s\n",
label,
params,
HCC_ISOC_THRES (params),
......@@ -235,19 +243,19 @@ dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status)
#define dbg_status(ehci, label, status) { \
char _buf [80]; \
dbg_status_buf (_buf, sizeof _buf, label, status); \
dbg ("%s", _buf); \
ehci_dbg (ehci, "%s\n", _buf); \
}
#define dbg_cmd(ehci, label, command) { \
char _buf [80]; \
dbg_command_buf (_buf, sizeof _buf, label, command); \
dbg ("%s", _buf); \
ehci_dbg (ehci, "%s\n", _buf); \
}
#define dbg_port(hcd, label, port, status) { \
#define dbg_port(ehci, label, port, status) { \
char _buf [80]; \
dbg_port_buf (_buf, sizeof _buf, label, port, status); \
dbg ("%s", _buf); \
ehci_dbg (ehci, "%s\n", _buf); \
}
/*-------------------------------------------------------------------------*/
......@@ -338,12 +346,8 @@ show_async (struct device *dev, char *buf, size_t count, loff_t off)
* one QH per line, and TDs we know about
*/
spin_lock_irqsave (&ehci->lock, flags);
if (ehci->async) {
qh = ehci->async;
do {
qh_lines (qh, &next, &size);
} while ((qh = qh->qh_next.qh) != ehci->async);
}
for (qh = ehci->async->qh_next.qh; qh; qh = qh->qh_next.qh)
qh_lines (qh, &next, &size);
if (ehci->reclaim) {
temp = snprintf (next, size, "\nreclaim =\n");
size -= temp;
......
......@@ -17,6 +17,13 @@
*/
#include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
......@@ -31,12 +38,6 @@
#include <linux/list.h>
#include <linux/interrupt.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/usb.h>
#include <linux/version.h>
......@@ -70,6 +71,7 @@
*
* HISTORY:
*
* 2002-11-29 Correct handling for hw async_next register.
* 2002-08-06 Handling for bulk and interrupt transfers is mostly shared;
* only scheduling is different, no arbitrary limitations.
* 2002-07-25 Sanity check PCI reads, mostly for better cardbus support,
......@@ -92,7 +94,7 @@
* 2001-June Works with usb-storage and NEC EHCI on 2.4
*/
#define DRIVER_VERSION "2002-Sep-23"
#define DRIVER_VERSION "2002-Nov-29"
#define DRIVER_AUTHOR "David Brownell"
#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
......@@ -114,7 +116,7 @@ static const char hcd_name [] = "ehci-hcd";
#define EHCI_TUNE_MULT_TT 1
#define EHCI_WATCHDOG_JIFFIES (HZ/100) /* arbitrary; ~10 msec */
#define EHCI_ASYNC_JIFFIES (HZ/3) /* async idle timeout */
#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */
/* Initial IRQ latency: lower than default */
static int log2_irq_thresh = 0; // 0 to 6
......@@ -215,7 +217,7 @@ static void ehci_ready (struct ehci_hcd *ehci)
/* wait for any schedule enables/disables to take effect */
temp = 0;
if (ehci->async)
if (ehci->async->qh_next.qh)
temp = STS_ASS;
if (ehci->next_uframe != -1)
temp |= STS_PSS;
......@@ -260,7 +262,7 @@ static void ehci_watchdog (unsigned long param)
spin_lock_irqsave (&ehci->lock, flags);
/* guard against lost IAA, which wedges everything */
ehci_irq (&ehci->hcd);
/* unlink the last qh after it's idled a while */
/* stop async processing after it's idled a while */
if (ehci->async_idle) {
start_unlink_async (ehci, ehci->async);
ehci->async_idle = 0;
......@@ -287,12 +289,13 @@ static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
pci_read_config_dword (ehci->hcd.pdev, where, &cap);
} while ((cap & (1 << 16)) && msec);
if (cap & (1 << 16)) {
info ("BIOS handoff failed (%d, %04x)", where, cap);
dev_info (*ehci->hcd.controller,
"BIOS handoff failed (%d, %04x)\n",
where, cap);
return 1;
}
dbg ("BIOS handoff succeeded");
} else
dbg ("BIOS handoff not needed");
ehci_dbg (ehci, "BIOS handoff succeeded\n");
}
return 0;
}
......@@ -323,14 +326,15 @@ static int ehci_start (struct usb_hcd *hcd)
u32 cap;
pci_read_config_dword (ehci->hcd.pdev, temp, &cap);
dbg ("capability %04x at %02x", cap, temp);
ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp);
switch (cap & 0xff) {
case 1: /* BIOS/SMM/... handoff */
if (bios_handoff (ehci, temp, cap) != 0)
return -EOPNOTSUPP;
break;
case 0: /* illegal reserved capability */
warn ("illegal capability!");
dev_warn (*ehci->hcd.controller,
"illegal capability!\n");
cap = 0;
/* FALLTHROUGH */
default: /* unknown */
......@@ -360,7 +364,6 @@ static int ehci_start (struct usb_hcd *hcd)
else // N microframes cached
ehci->i_thresh = 2 + HCC_ISOC_THRES (hcc_params);
ehci->async = 0;
ehci->reclaim = 0;
ehci->next_uframe = -1;
......@@ -374,6 +377,21 @@ static int ehci_start (struct usb_hcd *hcd)
writel (INTR_MASK, &ehci->regs->intr_enable);
writel (ehci->periodic_dma, &ehci->regs->frame_list);
/*
* dedicate a qh for the async ring head, since we couldn't unlink
* a 'real' qh without stopping the async schedule [4.8]. use it
* as the 'reclamation list head' too.
*/
ehci->async->qh_next.qh = 0;
ehci->async->hw_next = QH_NEXT (ehci->async->qh_dma);
ehci->async->hw_info1 = cpu_to_le32 (QH_HEAD);
ehci->async->hw_token = cpu_to_le32 (QTD_STS_HALT);
ehci->async->hw_qtd_next = EHCI_LIST_END;
ehci->async->qh_state = QH_STATE_LINKED;
ehci_qtd_free (ehci, ehci->async->dummy);
ehci->async->dummy = 0;
writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
/*
* hcc_params controls whether ehci->regs->segment must (!!!)
* be used; it constrains QH/ITD/SITD and QTD locations.
......@@ -388,7 +406,8 @@ static int ehci_start (struct usb_hcd *hcd)
if (HCC_64BIT_ADDR (hcc_params)) {
writel (0, &ehci->regs->segment);
if (!pci_set_dma_mask (ehci->hcd.pdev, 0xffffffffffffffffULL))
info ("enabled 64bit PCI DMA (DAC)");
dev_info (*ehci->hcd.controller,
"enabled 64bit PCI DMA (DAC)\n");
}
/* clear interrupt enables, set irq latency */
......@@ -435,10 +454,10 @@ static int ehci_start (struct usb_hcd *hcd)
/* PCI Serial Bus Release Number is at 0x60 offset */
pci_read_config_byte (hcd->pdev, 0x60, &tempbyte);
temp = readw (&ehci->caps->hci_version);
info ("USB %x.%x support enabled, EHCI rev %x.%02x, %s %s",
((tempbyte & 0xf0)>>4), (tempbyte & 0x0f),
temp >> 8, temp & 0xff,
hcd_name, DRIVER_VERSION);
dev_info (*hcd->controller,
"USB %x.%x enabled, EHCI %x.%02x, driver %s\n",
((tempbyte & 0xf0)>>4), (tempbyte & 0x0f),
temp >> 8, temp & 0xff, DRIVER_VERSION);
/*
* From here on, khubd concurrently accesses the root
......@@ -470,13 +489,13 @@ static void ehci_stop (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
dbg ("%s: stop", hcd_to_bus (hcd)->bus_name);
ehci_dbg (ehci, "stop\n");
/* no more interrupts ... */
if (hcd->state == USB_STATE_RUNNING)
ehci_ready (ehci);
if (in_interrupt ()) /* should not happen!! */
err ("stopped %s!", RUN_CONTEXT);
dev_err (*hcd->controller, "stopped %s!\n", RUN_CONTEXT);
else
del_timer_sync (&ehci->watchdog);
ehci_reset (ehci);
......@@ -492,9 +511,9 @@ static void ehci_stop (struct usb_hcd *hcd)
ehci_mem_cleanup (ehci);
#ifdef EHCI_STATS
dbg ("irq normal %ld err %ld reclaim %ld",
ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld\n",
ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim);
dbg ("complete %ld unlink %ld",
ehci_dbg (ehci, "complete %ld unlink %ld\n",
ehci->stats.complete, ehci->stats.unlink);
#endif
......@@ -738,8 +757,8 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv;
unsigned long flags;
dbg ("%s urb_dequeue %p qh %p state %d",
hcd_to_bus (hcd)->bus_name, urb, qh, qh->qh_state);
ehci_vdbg (ehci, "urb_dequeue %p qh %p state %d\n",
urb, qh, qh->qh_state);
switch (usb_pipetype (urb->pipe)) {
// case PIPE_CONTROL:
......@@ -982,7 +1001,6 @@ MODULE_LICENSE ("GPL");
static int __init init (void)
{
dbg (DRIVER_INFO);
if (usb_disabled())
return -ENODEV;
......
......@@ -40,18 +40,15 @@ static int check_reset_complete (
/* if reset finished and it's still not enabled -- handoff */
if (!(port_status & PORT_PE)) {
dbg ("%s port %d full speed, give to companion, 0x%x",
hcd_to_bus (&ehci->hcd)->bus_name,
index + 1, port_status);
ehci_dbg (ehci, "port %d full speed --> companion\n",
index + 1);
// what happens if HCS_N_CC(params) == 0 ?
port_status |= PORT_OWNER;
writel (port_status, &ehci->regs->port_status [index]);
} else
dbg ("%s port %d high speed",
hcd_to_bus (&ehci->hcd)->bus_name,
index + 1);
ehci_dbg (ehci, "port %d high speed\n", index + 1);
return port_status;
}
......@@ -277,7 +274,7 @@ static int ehci_hub_control (
#ifndef EHCI_VERBOSE_DEBUG
if (status & ~0xffff) /* only if wPortChange is interesting */
#endif
dbg_port (hcd, "GetStatus", wIndex + 1, temp);
dbg_port (ehci, "GetStatus", wIndex + 1, temp);
// we "know" this alignment is good, caller used kmalloc()...
*((u32 *) buf) = cpu_to_le32 (status);
break;
......@@ -313,14 +310,12 @@ static int ehci_hub_control (
/* line status bits may report this as low speed */
if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
&& PORT_USB11 (temp)) {
dbg ("%s port %d low speed, give to companion",
hcd_to_bus (&ehci->hcd)->bus_name,
ehci_dbg (ehci,
"port %d low speed --> companion\n",
wIndex + 1);
temp |= PORT_OWNER;
} else {
vdbg ("%s port %d reset",
hcd_to_bus (&ehci->hcd)->bus_name,
wIndex + 1);
ehci_vdbg (ehci, "port %d reset", wIndex + 1);
temp |= PORT_RESET;
temp &= ~PORT_PE;
......
......@@ -103,7 +103,7 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
/* dummy td enables safe urb queuing */
qh->dummy = ehci_qtd_alloc (ehci, flags);
if (qh->dummy == 0) {
dbg ("no dummy td");
ehci_dbg (ehci, "no dummy td\n");
pci_pool_free (ehci->qh_pool, qh, qh->qh_dma);
qh = 0;
}
......@@ -113,19 +113,17 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
/* to share a qh (cpu threads, or hc) */
static inline struct ehci_qh *qh_get (/* ehci, */ struct ehci_qh *qh)
{
// dbg ("get %p (%d++)", qh, qh->refcount.counter);
atomic_inc (&qh->refcount);
return qh;
}
static void qh_put (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
// dbg ("put %p (--%d)", qh, qh->refcount.counter);
if (!atomic_dec_and_test (&qh->refcount))
return;
/* clean qtds first, and know this is not linked */
if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) {
dbg ("unused qh not empty!");
ehci_dbg (ehci, "unused qh not empty!\n");
BUG ();
}
if (qh->dummy)
......@@ -142,6 +140,10 @@ static void qh_put (struct ehci_hcd *ehci, struct ehci_qh *qh)
static void ehci_mem_cleanup (struct ehci_hcd *ehci)
{
if (ehci->async)
qh_put (ehci, ehci->async);
ehci->async = 0;
/* PCI consistent memory and pools */
if (ehci->qtd_pool)
pci_pool_destroy (ehci->qtd_pool);
......@@ -183,20 +185,20 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
if (!ehci->qtd_pool) {
dbg ("no qtd pool");
ehci_mem_cleanup (ehci);
return -ENOMEM;
goto fail;
}
/* QH for control/bulk/intr transfers */
/* QHs for control/bulk/intr transfers */
ehci->qh_pool = pci_pool_create ("ehci_qh", ehci->hcd.pdev,
sizeof (struct ehci_qh),
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
if (!ehci->qh_pool) {
dbg ("no qh pool");
ehci_mem_cleanup (ehci);
return -ENOMEM;
goto fail;
}
ehci->async = ehci_qh_alloc (ehci, flags);
if (!ehci->async) {
goto fail;
}
/* ITD for high speed ISO transfers */
......@@ -205,9 +207,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
if (!ehci->itd_pool) {
dbg ("no itd pool");
ehci_mem_cleanup (ehci);
return -ENOMEM;
goto fail;
}
/* SITD for full/low speed split ISO transfers */
......@@ -216,9 +216,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
if (!ehci->sitd_pool) {
dbg ("no sitd pool");
ehci_mem_cleanup (ehci);
return -ENOMEM;
goto fail;
}
/* Hardware periodic table */
......@@ -227,9 +225,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
ehci->periodic_size * sizeof (u32),
&ehci->periodic_dma);
if (ehci->periodic == 0) {
dbg ("no hw periodic table");
ehci_mem_cleanup (ehci);
return -ENOMEM;
goto fail;
}
for (i = 0; i < ehci->periodic_size; i++)
ehci->periodic [i] = EHCI_LIST_END;
......@@ -237,11 +233,14 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
/* software shadow of hardware table */
ehci->pshadow = kmalloc (ehci->periodic_size * sizeof (void *), flags);
if (ehci->pshadow == 0) {
dbg ("no shadow periodic table");
ehci_mem_cleanup (ehci);
return -ENOMEM;
goto fail;
}
memset (ehci->pshadow, 0, ehci->periodic_size * sizeof (void *));
return 0;
fail:
ehci_dbg (ehci, "couldn't init memory\n");
ehci_mem_cleanup (ehci);
return -ENOMEM;
}
......@@ -130,8 +130,9 @@ static inline void qtd_copy_status (struct urb *urb, size_t length, u32 token)
else /* unknown */
urb->status = -EPROTO;
dbg ("ep %d-%s qtd token %08x --> status %d",
/* devpath */
ehci_vdbg (ehci,
"dev%d ep%d%s qtd token %08x --> status %d\n",
usb_pipedev (urb->pipe),
usb_pipeendpoint (urb->pipe),
usb_pipein (urb->pipe) ? "in" : "out",
token, urb->status);
......@@ -678,33 +679,33 @@ ehci_qh_make (
static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
u32 dma = QH_NEXT (qh->qh_dma);
struct ehci_qh *q;
struct ehci_qh *head;
if (unlikely (!(q = ehci->async))) {
/* (re)start the async schedule? */
head = ehci->async;
if (ehci->async_idle)
del_timer (&ehci->watchdog);
else if (!head->qh_next.qh) {
u32 cmd = readl (&ehci->regs->command);
/* in case a clear of CMD_ASE didn't take yet */
(void) handshake (&ehci->regs->status, STS_ASS, 0, 150);
qh->hw_info1 |= __constant_cpu_to_le32 (QH_HEAD); /* [4.8] */
qh->qh_next.qh = qh;
qh->hw_next = dma;
wmb ();
ehci->async = qh;
writel ((u32)qh->qh_dma, &ehci->regs->async_next);
cmd |= CMD_ASE | CMD_RUN;
writel (cmd, &ehci->regs->command);
ehci->hcd.state = USB_STATE_RUNNING;
/* posted write need not be known to HC yet ... */
} else {
/* splice right after "start" of ring */
qh->hw_info1 &= ~__constant_cpu_to_le32 (QH_HEAD); /* [4.8] */
qh->qh_next = q->qh_next;
qh->hw_next = q->hw_next;
wmb ();
q->qh_next.qh = qh;
q->hw_next = dma;
if (!(cmd & CMD_ASE)) {
/* in case a clear of CMD_ASE didn't take yet */
(void) handshake (&ehci->regs->status, STS_ASS, 0, 150);
cmd |= CMD_ASE | CMD_RUN;
writel (cmd, &ehci->regs->command);
ehci->hcd.state = USB_STATE_RUNNING;
/* posted write need not be known to HC yet ... */
}
}
/* splice right after start */
qh->qh_next = head->qh_next;
qh->hw_next = head->hw_next;
wmb ();
head->qh_next.qh = qh;
head->hw_next = dma;
qh->qh_state = QH_STATE_LINKED;
/* qtd completions reported later by interrupt */
......@@ -897,6 +898,14 @@ static void end_unlink_async (struct ehci_hcd *ehci)
qh_link_async (ehci, qh);
else
qh_put (ehci, qh); // refcount from async list
/* it's not free to turn the async schedule on/off, so we leave it
* active but idle for a while once it empties.
*/
if (!ehci->async->qh_next.qh && !timer_pending (&ehci->watchdog)) {
ehci->async_idle = 1;
mod_timer (&ehci->watchdog, jiffies + EHCI_ASYNC_JIFFIES);
}
}
/* makes sure the async qh will become idle */
......@@ -909,7 +918,6 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
#ifdef DEBUG
if (ehci->reclaim
|| !ehci->async
|| qh->qh_state != QH_STATE_LINKED
#ifdef CONFIG_SMP
// this macro lies except on SMP compiles
......@@ -919,31 +927,20 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
BUG ();
#endif
qh->qh_state = QH_STATE_UNLINK;
ehci->reclaim = qh = qh_get (qh);
// dbg_qh ("start unlink", ehci, qh);
/* Remove the last QH (qhead)? Stop async schedule first. */
if (unlikely (qh == ehci->async && qh->qh_next.qh == qh)) {
/* stop async schedule right now? */
if (unlikely (qh == ehci->async)) {
/* can't get here without STS_ASS set */
if (ehci->hcd.state != USB_STATE_HALT) {
writel (cmd & ~CMD_ASE, &ehci->regs->command);
(void) handshake (&ehci->regs->status, STS_ASS, 0, 150);
#if 0
// one VT8235 system wants to die with STS_FATAL
// unless this qh is leaked here. others seem ok...
qh = qh_get (qh);
dbg_qh ("async/off", ehci, qh);
#endif
wmb ();
// handshake later, if we need to
}
qh->qh_next.qh = ehci->async = 0;
ehci->reclaim_ready = 1;
tasklet_schedule (&ehci->tasklet);
return;
}
qh->qh_state = QH_STATE_UNLINK;
ehci->reclaim = qh = qh_get (qh);
if (unlikely (ehci->hcd.state == USB_STATE_HALT)) {
ehci->reclaim_ready = 1;
tasklet_schedule (&ehci->tasklet);
......@@ -951,13 +948,9 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
}
prev = ehci->async;
while (prev->qh_next.qh != qh && prev->qh_next.qh != ehci->async)
while (prev->qh_next.qh != qh)
prev = prev->qh_next.qh;
if (qh->hw_info1 & __constant_cpu_to_le32 (QH_HEAD)) {
ehci->async = prev;
prev->hw_info1 |= __constant_cpu_to_le32 (QH_HEAD);
}
prev->hw_next = qh->hw_next;
prev->qh_next = qh->qh_next;
wmb ();
......@@ -979,7 +972,7 @@ scan_async (struct ehci_hcd *ehci)
unsigned count;
rescan:
qh = ehci->async;
qh = ehci->async->qh_next.qh;
count = 0;
if (likely (qh != 0)) {
do {
......@@ -991,25 +984,17 @@ scan_async (struct ehci_hcd *ehci)
/* concurrent unlink could happen here */
count += qh_completions (ehci, qh);
qh_put (ehci, qh);
goto rescan;
}
/* unlink idle entries, reducing HC PCI usage as
* well as HCD schedule-scanning costs. removing
* the last qh is deferred, since it's costly.
* well as HCD schedule-scanning costs.
*
* FIXME don't unlink idle entries so quickly; it
* can penalize (common) half duplex protocols.
*/
if (list_empty (&qh->qtd_list) && !ehci->reclaim) {
if (qh->qh_next.qh != qh) {
// dbg ("irq/empty");
start_unlink_async (ehci, qh);
} else if (!timer_pending (&ehci->watchdog)) {
/* can't use IAA for last entry */
ehci->async_idle = 1;
mod_timer (&ehci->watchdog,
jiffies + EHCI_ASYNC_JIFFIES);
}
start_unlink_async (ehci, qh);
}
/* keep latencies down: let any irqs in */
......@@ -1021,8 +1006,6 @@ scan_async (struct ehci_hcd *ehci)
}
qh = qh->qh_next.qh;
if (!qh) /* unlinked? */
goto rescan;
} while (qh != ehci->async);
} while (qh);
}
}
......@@ -1051,10 +1051,6 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
td_error:
ret = uhci_map_status(status, uhci_packetout(td_token(td)));
if (ret == -EPIPE)
/* endpoint has stalled - mark it halted */
usb_endpoint_halt(urb->dev, uhci_endpoint(td_token(td)),
uhci_packetout(td_token(td)));
err:
if ((debug == 1 && ret != -EPIPE) || debug > 1) {
......
......@@ -467,9 +467,12 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
down (&port->sem);
port->tty = tty;
/* lock this module before we call it */
if (serial->type->owner)
__MOD_INC_USE_COUNT(serial->type->owner);
/* lock this module before we call it,
this may, which means we must bail out, safe because we are called with BKL held */
if (!try_module_get(serial->type->owner)) {
retval = -ENODEV;
goto bailout;
}
++port->open_count;
if (port->open_count == 1) {
......@@ -481,10 +484,10 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
retval = usb_serial_generic_open(port, filp);
if (retval) {
port->open_count = 0;
if (serial->type->owner)
__MOD_DEC_USE_COUNT(serial->type->owner);
module_put(serial->type->owner);
}
}
bailout:
up (&port->sem);
return retval;
......@@ -508,8 +511,7 @@ static void __serial_close(struct usb_serial_port *port, struct file *filp)
port->open_count = 0;
}
if (port->serial->type->owner)
__MOD_DEC_USE_COUNT(port->serial->type->owner);
module_put(port->serial->type->owner);
}
static void serial_close(struct tty_struct *tty, struct file * filp)
......@@ -899,11 +901,13 @@ int usb_serial_probe(struct usb_interface *interface,
/* if this device type has a probe function, call it */
if (type->probe) {
if (type->owner)
__MOD_INC_USE_COUNT(type->owner);
if (!try_module_get(type->owner)) {
err ("module get failed, exiting");
kfree (serial);
return -EIO;
}
retval = type->probe (serial);
if (type->owner)
__MOD_DEC_USE_COUNT(type->owner);
module_put(type->owner);
if (retval < 0) {
dbg ("sub driver rejected device");
......@@ -996,11 +1000,13 @@ int usb_serial_probe(struct usb_interface *interface,
if (!num_ports) {
/* if this device type has a calc_num_ports function, call it */
if (type->calc_num_ports) {
if (type->owner)
__MOD_INC_USE_COUNT(type->owner);
if (!try_module_get(type->owner)) {
err ("module get failed, exiting");
kfree (serial);
return -EIO;
}
num_ports = type->calc_num_ports (serial);
if (type->owner)
__MOD_DEC_USE_COUNT(type->owner);
module_put(type->owner);
}
if (!num_ports)
num_ports = type->num_ports;
......@@ -1110,11 +1116,12 @@ int usb_serial_probe(struct usb_interface *interface,
/* if this device type has an attach function, call it */
if (type->attach) {
if (type->owner)
__MOD_INC_USE_COUNT(type->owner);
if (!try_module_get(type->owner)) {
err ("module get failed, exiting");
goto probe_error;
}
retval = type->attach (serial);
if (type->owner)
__MOD_DEC_USE_COUNT(type->owner);
module_put(type->owner);
if (retval < 0)
goto probe_error;
if (retval > 0) {
......
......@@ -532,8 +532,6 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
if (result < 0)
return result;
printk(KERN_ERR "usb_stor_clear_halt() WORKED!\n");
/* reset the toggles and endpoint flags */
usb_endpoint_running(us->pusb_dev, usb_pipeendpoint(pipe),
usb_pipeout(pipe));
......
......@@ -1238,49 +1238,58 @@ static void zap_threads (struct mm_struct *mm)
{
struct task_struct *g, *p;
/* give other threads a chance to run: */
yield();
read_lock(&tasklist_lock);
do_each_thread(g,p)
if (mm == p->mm && !p->core_waiter)
if (mm == p->mm && p != current) {
force_sig_specific(SIGKILL, p);
mm->core_waiters++;
}
while_each_thread(g,p);
read_unlock(&tasklist_lock);
}
static void coredump_wait(struct mm_struct *mm)
{
DECLARE_WAITQUEUE(wait, current);
DECLARE_COMPLETION(startup_done);
mm->core_waiters++; /* let other threads block */
mm->core_startup_done = &startup_done;
/* give other threads a chance to run: */
yield();
atomic_inc(&mm->core_waiters);
add_wait_queue(&mm->core_wait, &wait);
zap_threads(mm);
current->state = TASK_UNINTERRUPTIBLE;
if (atomic_read(&mm->core_waiters) != atomic_read(&mm->mm_users))
schedule();
else
current->state = TASK_RUNNING;
if (--mm->core_waiters) {
up_write(&mm->mmap_sem);
wait_for_completion(&startup_done);
} else
up_write(&mm->mmap_sem);
BUG_ON(mm->core_waiters);
}
int do_coredump(long signr, struct pt_regs * regs)
{
struct linux_binfmt * binfmt;
char corename[CORENAME_MAX_SIZE + 1];
struct file * file;
struct mm_struct *mm = current->mm;
struct linux_binfmt * binfmt;
struct inode * inode;
struct file * file;
int retval = 0;
lock_kernel();
binfmt = current->binfmt;
if (!binfmt || !binfmt->core_dump)
goto fail;
if (!current->mm->dumpable)
down_write(&mm->mmap_sem);
if (!mm->dumpable) {
up_write(&mm->mmap_sem);
goto fail;
current->mm->dumpable = 0;
if (down_trylock(&current->mm->core_sem))
BUG();
coredump_wait(current->mm);
}
mm->dumpable = 0;
init_completion(&mm->core_done);
coredump_wait(mm);
if (current->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
goto fail_unlock;
......@@ -1308,7 +1317,7 @@ int do_coredump(long signr, struct pt_regs * regs)
close_fail:
filp_close(file, NULL);
fail_unlock:
up(&current->mm->core_sem);
complete_all(&mm->core_done);
fail:
unlock_kernel();
return retval;
......
......@@ -8,7 +8,6 @@
*/
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/smp_lock.h>
#include <linux/file.h>
#include <linux/xattr.h>
......@@ -19,7 +18,7 @@
/*
* Extended attribute memory allocation wrappers, originally
* based on the Intermezzo PRESTO_ALLOC/PRESTO_FREE macros.
* The vmalloc use here is very uncommon - extended attributes
* Values larger than a page are uncommon - extended attributes
* are supposed to be small chunks of metadata, and it is quite
* unusual to have very many extended attributes, so lists tend
* to be quite short as well. The 64K upper limit is derived
......@@ -36,10 +35,8 @@ xattr_alloc(size_t size, size_t limit)
if (!size) /* size request, no buffer is needed */
return NULL;
else if (size <= PAGE_SIZE)
ptr = kmalloc((unsigned long) size, GFP_KERNEL);
else
ptr = vmalloc((unsigned long) size);
ptr = kmalloc((unsigned long) size, GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
return ptr;
......@@ -48,12 +45,8 @@ xattr_alloc(size_t size, size_t limit)
static void
xattr_free(void *ptr, size_t size)
{
if (!size) /* size request, no buffer was needed */
return;
else if (size <= PAGE_SIZE)
if (size) /* for a size request, no buffer was needed */
kfree(ptr);
else
vfree(ptr);
}
/*
......
......@@ -135,17 +135,14 @@ probe_unmapped_page(
struct page *page;
int ret = 0;
page = find_get_page(mapping, index);
page = find_trylock_page(mapping, index);
if (!page)
return 0;
if (PageWriteback(page) || TestSetPageLocked(page)) {
page_cache_release(page);
return 0;
}
if (PageWriteback(page))
goto out;
if (page->mapping && PageDirty(page)) {
if (!page_has_buffers(page)) {
ret = PAGE_CACHE_SIZE;
} else {
if (page_has_buffers(page)) {
struct buffer_head *bh, *head;
bh = head = page_buffers(page);
do {
......@@ -156,11 +153,12 @@ probe_unmapped_page(
if (ret >= pg_offset)
break;
} while ((bh = bh->b_this_page) != head);
}
} else
ret = PAGE_CACHE_SIZE;
}
out:
unlock_page(page);
page_cache_release(page);
return ret;
}
......@@ -214,13 +212,12 @@ probe_page(
{
struct page *page;
page = find_get_page(inode->i_mapping, index);
page = find_trylock_page(inode->i_mapping, index);
if (!page)
return NULL;
if (PageWriteback(page) || TestSetPageLocked(page)) {
page_cache_release(page);
return NULL;
}
if (PageWriteback(page))
goto out;
if (page->mapping && page_has_buffers(page)) {
struct buffer_head *bh, *head;
......@@ -230,8 +227,9 @@ probe_page(
return page;
} while ((bh = bh->b_this_page) != head);
}
out:
unlock_page(page);
page_cache_release(page);
return NULL;
}
......@@ -319,8 +317,6 @@ convert_page(
} else {
unlock_page(page);
}
page_cache_release(page);
}
/*
......
......@@ -138,6 +138,22 @@ linvfs_aio_write(
return linvfs_writev(iocb->ki_filp, &iov, 1, &iocb->ki_pos);
}
STATIC ssize_t
linvfs_sendfile(
struct file *filp,
loff_t *ppos,
size_t count,
read_actor_t actor,
void *target)
{
vnode_t *vp = LINVFS_GET_VP(filp->f_dentry->d_inode);
int error;
VOP_SENDFILE(vp, filp, ppos, count, actor, target, NULL, error);
return error;
}
STATIC int
linvfs_open(
......@@ -186,7 +202,7 @@ linvfs_fsync(
ASSERT(vp);
VOP_FSYNC(vp, flags, NULL, (off_t)0, (off_t)-1, error);
VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error);
return -error;
}
......@@ -212,7 +228,7 @@ linvfs_readdir(
caddr_t read_buf;
int namelen, size = 0;
size_t rlen = PAGE_CACHE_SIZE << 2;
off_t start_offset;
xfs_off_t start_offset;
xfs_dirent_t *dbp = NULL;
vp = LINVFS_GET_VP(filp->f_dentry->d_inode);
......@@ -280,7 +296,7 @@ linvfs_file_mmap(
{
struct inode *ip = filp->f_dentry->d_inode;
vnode_t *vp = LINVFS_GET_VP(ip);
vattr_t va = { .va_mask = AT_UPDATIME };
vattr_t va = { .va_mask = XFS_AT_UPDATIME };
int error;
if ((vp->v_type == VREG) && (vp->v_vfsp->vfs_flag & VFS_DMI)) {
......@@ -291,7 +307,7 @@ linvfs_file_mmap(
vma->vm_ops = &linvfs_file_vm_ops;
VOP_SETATTR(vp, &va, AT_UPDATIME, NULL, error);
VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error);
UPDATE_ATIME(ip);
return 0;
}
......@@ -348,6 +364,7 @@ struct file_operations linvfs_file_operations = {
.writev = linvfs_writev,
.aio_read = linvfs_aio_read,
.aio_write = linvfs_aio_write,
.sendfile = linvfs_sendfile,
.ioctl = linvfs_ioctl,
.mmap = linvfs_file_mmap,
.open = linvfs_open,
......
......@@ -34,8 +34,9 @@
#include <xfs_fsops.h>
#include <xfs_dfrag.h>
#include <linux/dcache.h>
#include <linux/namei.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/pagemap.h>
extern int xfs_change_file_space(bhv_desc_t *, int,
......@@ -591,17 +592,16 @@ xfs_ioctl(
case XFS_IOC_DIOINFO: {
struct dioattr da;
da.d_miniosz = mp->m_sb.sb_blocksize;
da.d_mem = mp->m_sb.sb_blocksize;
/*
* this only really needs to be BBSIZE.
* it is set to the file system block size to
* avoid having to do block zeroing on short writes.
*/
#define KIO_MAX_ATOMIC_IO 512 /* FIXME: what do we really want here? */
da.d_maxiosz = XFS_FSB_TO_B(mp,
XFS_B_TO_FSBT(mp, KIO_MAX_ATOMIC_IO << 10));
da.d_miniosz = mp->m_sb.sb_blocksize;
da.d_mem = mp->m_sb.sb_blocksize;
/* The size dio will do in one go */
da.d_maxiosz = 64 * PAGE_CACHE_SIZE;
if (copy_to_user((struct dioattr *)arg, &da, sizeof(da)))
return -XFS_ERROR(EFAULT);
......@@ -945,7 +945,7 @@ int xfs_ioc_xattr(
switch (cmd) {
case XFS_IOC_FSGETXATTR: {
va.va_mask = AT_XFLAGS|AT_EXTSIZE|AT_NEXTENTS;
va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS;
VOP_GETATTR(vp, &va, 0, NULL, error);
if (error)
return -error;
......@@ -965,7 +965,7 @@ int xfs_ioc_xattr(
if (copy_from_user(&fa, (struct fsxattr *)arg, sizeof(fa)))
return -XFS_ERROR(EFAULT);
va.va_mask = AT_XFLAGS | AT_EXTSIZE;
va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE;
va.va_xflags = fa.fsx_xflags;
va.va_extsize = fa.fsx_extsize;
......@@ -978,7 +978,7 @@ int xfs_ioc_xattr(
case XFS_IOC_FSGETXATTRA: {
va.va_mask = AT_XFLAGS|AT_EXTSIZE|AT_ANEXTENTS;
va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_ANEXTENTS;
VOP_GETATTR(vp, &va, 0, NULL, error);
if (error)
return -error;
......
......@@ -45,7 +45,7 @@ validate_fields(
vattr_t va;
int error;
va.va_mask = AT_NLINK|AT_SIZE;
va.va_mask = XFS_AT_NLINK|XFS_AT_SIZE;
VOP_GETATTR(vp, &va, ATTR_LAZY, NULL, error);
ip->i_nlink = va.va_nlink;
ip->i_size = va.va_size;
......@@ -85,14 +85,14 @@ linvfs_mknod(
mode &= ~current->fs->umask;
memset(&va, 0, sizeof(va));
va.va_mask = AT_TYPE|AT_MODE;
va.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
va.va_type = IFTOVT(mode);
va.va_mode = mode;
switch (mode & S_IFMT) {
case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
va.va_rdev = XFS_MKDEV(MAJOR(rdev), MINOR(rdev));
va.va_mask |= AT_RDEV;
va.va_mask |= XFS_AT_RDEV;
/*FALLTHROUGH*/
case S_IFREG:
VOP_CREATE(dvp, dentry, &va, &vp, NULL, error);
......@@ -255,7 +255,7 @@ linvfs_symlink(
memset(&va, 0, sizeof(va));
va.va_type = VLNK;
va.va_mode = irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO;
va.va_mask = AT_TYPE|AT_MODE;
va.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
error = 0;
VOP_SYMLINK(dvp, dentry, &va, (char *)symname, &cvp, NULL, error);
......@@ -462,31 +462,31 @@ linvfs_setattr(
memset(&vattr, 0, sizeof(vattr_t));
if (ia_valid & ATTR_UID) {
vattr.va_mask |= AT_UID;
vattr.va_mask |= XFS_AT_UID;
vattr.va_uid = attr->ia_uid;
}
if (ia_valid & ATTR_GID) {
vattr.va_mask |= AT_GID;
vattr.va_mask |= XFS_AT_GID;
vattr.va_gid = attr->ia_gid;
}
if (ia_valid & ATTR_SIZE) {
vattr.va_mask |= AT_SIZE;
vattr.va_mask |= XFS_AT_SIZE;
vattr.va_size = attr->ia_size;
}
if (ia_valid & ATTR_ATIME) {
vattr.va_mask |= AT_ATIME;
vattr.va_mask |= XFS_AT_ATIME;
vattr.va_atime = attr->ia_atime;
}
if (ia_valid & ATTR_MTIME) {
vattr.va_mask |= AT_MTIME;
vattr.va_mask |= XFS_AT_MTIME;
vattr.va_mtime = attr->ia_mtime;
}
if (ia_valid & ATTR_CTIME) {
vattr.va_mask |= AT_CTIME;
vattr.va_mask |= XFS_AT_CTIME;
vattr.va_ctime = attr->ia_ctime;
}
if (ia_valid & ATTR_MODE) {
vattr.va_mask |= AT_MODE;
vattr.va_mask |= XFS_AT_MODE;
vattr.va_mode = attr->ia_mode;
if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
inode->i_mode &= ~S_ISGID;
......
......@@ -153,7 +153,6 @@ typedef struct xfs_dirent { /* data from readdir() */
#define EFSCORRUPTED 990 /* Filesystem is corrupted */
#define SYNCHRONIZE() barrier()
#define rootdev ROOT_DEV
#define __return_address __builtin_return_address(0)
/* IRIX uses a dynamic sizing algorithm (ndquot = 200 + numprocs*2) */
......
......@@ -205,6 +205,67 @@ xfs_read(
return ret;
}
ssize_t
xfs_sendfile(
bhv_desc_t *bdp,
struct file *filp,
loff_t *offp,
size_t count,
read_actor_t actor,
void *target,
cred_t *credp)
{
size_t size = 0;
ssize_t ret;
xfs_fsize_t n;
xfs_inode_t *ip;
xfs_mount_t *mp;
vnode_t *vp;
ip = XFS_BHVTOI(bdp);
vp = BHV_TO_VNODE(bdp);
mp = ip->i_mount;
vn_trace_entry(vp, "xfs_sendfile", (inst_t *)__return_address);
XFS_STATS_INC(xfsstats.xs_read_calls);
n = XFS_MAX_FILE_OFFSET - *offp;
if ((n <= 0) || (size == 0))
return 0;
if (n < size)
size = n;
if (XFS_FORCED_SHUTDOWN(mp)) {
return -EIO;
}
xfs_ilock(ip, XFS_IOLOCK_SHARED);
if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
!(filp->f_mode & FINVIS)) {
int error;
vrwlock_t locktype = VRWLOCK_READ;
error = xfs_dm_send_data_event(DM_EVENT_READ, bdp, *offp,
size, FILP_DELAY_FLAG(filp), &locktype);
if (error) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
return -error;
}
}
ret = generic_file_sendfile(filp, offp, count, actor, target);
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
XFS_STATS_ADD(xfsstats.xs_read_bytes, ret);
if (!(filp->f_mode & FINVIS))
xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
return ret;
}
/*
* This routine is called to handle zeroing any space in the last
* block of the file that is beyond the EOF. We do this since the
......
......@@ -32,15 +32,128 @@
#ifndef __XFS_STATS_H__
#define __XFS_STATS_H__
#if defined(CONFIG_PROC_FS) && !defined(XFS_STATS_OFF)
/*
* procfs interface
* XFS global statistics
*/
#ifdef CONFIG_PROC_FS
struct xfsstats {
# define XFSSTAT_END_EXTENT_ALLOC 4
__uint32_t xs_allocx;
__uint32_t xs_allocb;
__uint32_t xs_freex;
__uint32_t xs_freeb;
# define XFSSTAT_END_ALLOC_BTREE (XFSSTAT_END_EXTENT_ALLOC+4)
__uint32_t xs_abt_lookup;
__uint32_t xs_abt_compare;
__uint32_t xs_abt_insrec;
__uint32_t xs_abt_delrec;
# define XFSSTAT_END_BLOCK_MAPPING (XFSSTAT_END_ALLOC_BTREE+7)
__uint32_t xs_blk_mapr;
__uint32_t xs_blk_mapw;
__uint32_t xs_blk_unmap;
__uint32_t xs_add_exlist;
__uint32_t xs_del_exlist;
__uint32_t xs_look_exlist;
__uint32_t xs_cmp_exlist;
# define XFSSTAT_END_BLOCK_MAP_BTREE (XFSSTAT_END_BLOCK_MAPPING+4)
__uint32_t xs_bmbt_lookup;
__uint32_t xs_bmbt_compare;
__uint32_t xs_bmbt_insrec;
__uint32_t xs_bmbt_delrec;
# define XFSSTAT_END_DIRECTORY_OPS (XFSSTAT_END_BLOCK_MAP_BTREE+4)
__uint32_t xs_dir_lookup;
__uint32_t xs_dir_create;
__uint32_t xs_dir_remove;
__uint32_t xs_dir_getdents;
# define XFSSTAT_END_TRANSACTIONS (XFSSTAT_END_DIRECTORY_OPS+3)
__uint32_t xs_trans_sync;
__uint32_t xs_trans_async;
__uint32_t xs_trans_empty;
# define XFSSTAT_END_INODE_OPS (XFSSTAT_END_TRANSACTIONS+7)
__uint32_t xs_ig_attempts;
__uint32_t xs_ig_found;
__uint32_t xs_ig_frecycle;
__uint32_t xs_ig_missed;
__uint32_t xs_ig_dup;
__uint32_t xs_ig_reclaims;
__uint32_t xs_ig_attrchg;
# define XFSSTAT_END_LOG_OPS (XFSSTAT_END_INODE_OPS+5)
__uint32_t xs_log_writes;
__uint32_t xs_log_blocks;
__uint32_t xs_log_noiclogs;
__uint32_t xs_log_force;
__uint32_t xs_log_force_sleep;
# define XFSSTAT_END_TAIL_PUSHING (XFSSTAT_END_LOG_OPS+10)
__uint32_t xs_try_logspace;
__uint32_t xs_sleep_logspace;
__uint32_t xs_push_ail;
__uint32_t xs_push_ail_success;
__uint32_t xs_push_ail_pushbuf;
__uint32_t xs_push_ail_pinned;
__uint32_t xs_push_ail_locked;
__uint32_t xs_push_ail_flushing;
__uint32_t xs_push_ail_restarts;
__uint32_t xs_push_ail_flush;
# define XFSSTAT_END_WRITE_CONVERT (XFSSTAT_END_TAIL_PUSHING+2)
__uint32_t xs_xstrat_quick;
__uint32_t xs_xstrat_split;
# define XFSSTAT_END_READ_WRITE_OPS (XFSSTAT_END_WRITE_CONVERT+2)
__uint32_t xs_write_calls;
__uint32_t xs_read_calls;
# define XFSSTAT_END_ATTRIBUTE_OPS (XFSSTAT_END_READ_WRITE_OPS+4)
__uint32_t xs_attr_get;
__uint32_t xs_attr_set;
__uint32_t xs_attr_remove;
__uint32_t xs_attr_list;
# define XFSSTAT_END_QUOTA_OPS (XFSSTAT_END_ATTRIBUTE_OPS+8)
__uint32_t xs_qm_dqreclaims;
__uint32_t xs_qm_dqreclaim_misses;
__uint32_t xs_qm_dquot_dups;
__uint32_t xs_qm_dqcachemisses;
__uint32_t xs_qm_dqcachehits;
__uint32_t xs_qm_dqwants;
__uint32_t xs_qm_dqshake_reclaims;
__uint32_t xs_qm_dqinact_reclaims;
# define XFSSTAT_END_INODE_CLUSTER (XFSSTAT_END_QUOTA_OPS+3)
__uint32_t xs_iflush_count;
__uint32_t xs_icluster_flushcnt;
__uint32_t xs_icluster_flushinode;
# define XFSSTAT_END_VNODE_OPS (XFSSTAT_END_INODE_CLUSTER+8)
__uint32_t vn_active; /* # vnodes not on free lists */
__uint32_t vn_alloc; /* # times vn_alloc called */
__uint32_t vn_get; /* # times vn_get called */
__uint32_t vn_hold; /* # times vn_hold called */
__uint32_t vn_rele; /* # times vn_rele called */
__uint32_t vn_reclaim; /* # times vn_reclaim called */
__uint32_t vn_remove; /* # times vn_remove called */
__uint32_t vn_free; /* # times vn_free called */
/* Extra precision counters */
__uint64_t xs_xstrat_bytes;
__uint64_t xs_write_bytes;
__uint64_t xs_read_bytes;
};
extern struct xfsstats xfsstats;
# define XFS_STATS_INC(count) ( (count)++ )
# define XFS_STATS_DEC(count) ( (count)-- )
# define XFS_STATS_ADD(count, inc) ( (count) += (inc) )
extern void xfs_init_procfs(void);
extern void xfs_cleanup_procfs(void);
#else
#else /* !CONFIG_PROC_FS */
# define XFS_STATS_INC(count)
# define XFS_STATS_DEC(count)
# define XFS_STATS_ADD(count, inc)
static __inline void xfs_init_procfs(void) { };
static __inline void xfs_cleanup_procfs(void) { };
#endif
#endif /* !CONFIG_PROC_FS */
#endif /* __XFS_STATS_H__ */
......@@ -46,10 +46,6 @@
extern int xfs_init(void);
extern void xfs_cleanup(void);
#ifndef EVMS_MAJOR
# define EVMS_MAJOR 117
#endif
/* For kernels which have the s_maxbytes field - set it */
#ifdef MAX_NON_LFS
# define set_max_bytes(sb) ((sb)->s_maxbytes = XFS_MAX_FILE_OFFSET)
......@@ -101,7 +97,6 @@ STATIC struct export_operations linvfs_export_ops;
#define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */
#define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */
#define MNTOPT_QUOTA "quota" /* disk quotas */
#define MNTOPT_MRQUOTA "mrquota" /* don't turnoff if SB has quotas on */
#define MNTOPT_NOQUOTA "noquota" /* no quotas */
#define MNTOPT_UQUOTA "usrquota" /* user quota enabled */
#define MNTOPT_GQUOTA "grpquota" /* group quota enabled */
......@@ -513,6 +508,23 @@ xfs_free_buftarg(
kfree(btp);
}
void
xfs_size_buftarg(
xfs_buftarg_t *btp,
unsigned int blocksize,
unsigned int sectorsize)
{
btp->pbr_bsize = blocksize;
btp->pbr_sshift = ffs(sectorsize) - 1;
btp->pbr_smask = sectorsize - 1;
if (set_blocksize(btp->pbr_bdev, sectorsize)) {
printk(KERN_WARNING
"XFS: Cannot set_blocksize to %u on device 0x%x\n",
sectorsize, btp->pbr_dev);
}
}
xfs_buftarg_t *
xfs_alloc_buftarg(
struct block_device *bdev)
......@@ -524,14 +536,7 @@ xfs_alloc_buftarg(
btp->pbr_dev = bdev->bd_dev;
btp->pbr_bdev = bdev;
btp->pbr_mapping = bdev->bd_inode->i_mapping;
btp->pbr_blocksize = PAGE_CACHE_SIZE;
switch (MAJOR(btp->pbr_dev)) {
case MD_MAJOR:
case EVMS_MAJOR:
btp->pbr_flags = PBR_ALIGNED_ONLY;
break;
}
xfs_size_buftarg(btp, PAGE_CACHE_SIZE, bdev_hardsect_size(bdev));
return btp;
}
......
......@@ -87,6 +87,7 @@ extern int xfs_blkdev_get (const char *, struct block_device **);
extern void xfs_blkdev_put (struct block_device *);
extern struct pb_target *xfs_alloc_buftarg (struct block_device *);
extern void xfs_size_buftarg (struct pb_target *, unsigned int, unsigned int);
extern void xfs_free_buftarg (struct pb_target *);
#endif /* __XFS_SUPER_H__ */
......@@ -35,8 +35,7 @@
uint64_t vn_generation; /* vnode generation number */
spinlock_t vnumber_lock = SPIN_LOCK_UNLOCKED;
spinlock_t vnumber_lock = SPIN_LOCK_UNLOCKED;
/*
* Dedicated vnode inactive/reclaim sync semaphores.
......@@ -59,9 +58,6 @@ u_short vttoif_tab[] = {
0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFIFO, 0, S_IFSOCK
};
#define VN_LOCK(vp) spin_lock(&(vp)->v_lock)
#define VN_UNLOCK(vp) spin_unlock(&(vp)->v_lock)
void
vn_init(void)
......@@ -73,14 +69,13 @@ vn_init(void)
init_sv(svp, SV_DEFAULT, "vsy", i);
}
/*
* Clean a vnode of filesystem-specific data and prepare it for reuse.
*/
STATIC int
vn_reclaim(struct vnode *vp)
{
int error;
int error;
XFS_STATS_INC(xfsstats.vn_reclaim);
......@@ -98,7 +93,6 @@ vn_reclaim(struct vnode *vp)
ASSERT(vp->v_fbhv == NULL);
VN_LOCK(vp);
vp->v_flag &= (VRECLM|VWAIT);
VN_UNLOCK(vp);
......@@ -189,7 +183,7 @@ vn_get(struct vnode *vp, vmap_t *vmap)
}
/*
* "revalidate" the linux inode.
* Revalidate the Linux inode from the vnode.
*/
int
vn_revalidate(struct vnode *vp)
......@@ -199,17 +193,12 @@ vn_revalidate(struct vnode *vp)
vattr_t va;
vn_trace_entry(vp, "vn_revalidate", (inst_t *)__return_address);
ASSERT(vp->v_fbhv != NULL);
va.va_mask = AT_STAT|AT_GENCOUNT;
ASSERT(vp->v_bh.bh_first != NULL);
va.va_mask = XFS_AT_STAT|XFS_AT_GENCOUNT;
VOP_GETATTR(vp, &va, 0, NULL, error);
if (! error) {
if (!error) {
inode = LINVFS_GET_IP(vp);
ASSERT(inode);
inode->i_mode = VTTOIF(va.va_type) | va.va_mode;
inode->i_nlink = va.va_nlink;
inode->i_uid = va.va_uid;
......@@ -224,11 +213,9 @@ vn_revalidate(struct vnode *vp)
inode->i_atime.tv_nsec = va.va_atime.tv_nsec;
VUNMODIFY(vp);
}
return -error;
}
/*
* purge a vnode from the cache
* At this point the vnode is guaranteed to have no references (vn_count == 0)
......@@ -317,12 +304,10 @@ void
vn_rele(struct vnode *vp)
{
int vcnt;
/* REFERENCED */
int cache;
int cache;
XFS_STATS_INC(xfsstats.vn_rele);
VN_LOCK(vp);
vn_trace_entry(vp, "vn_rele", (inst_t *)__return_address);
......@@ -365,7 +350,6 @@ vn_rele(struct vnode *vp)
vn_trace_exit(vp, "vn_rele", (inst_t *)__return_address);
}
/*
* Finish the removal of a vnode.
*/
......
This diff is collapsed.
......@@ -63,10 +63,8 @@
#include "page_buf_internal.h"
#define SECTOR_SHIFT 9
#define SECTOR_SIZE (1<<SECTOR_SHIFT)
#define SECTOR_MASK (SECTOR_SIZE - 1)
#define BN_ALIGN_MASK ((1 << (PAGE_CACHE_SHIFT - SECTOR_SHIFT)) - 1)
#define BBSHIFT 9
#define BN_ALIGN_MASK ((1 << (PAGE_CACHE_SHIFT - BBSHIFT)) - 1)
#ifndef GFP_READAHEAD
#define GFP_READAHEAD 0
......@@ -245,19 +243,27 @@ typedef struct a_list {
STATIC a_list_t *as_free_head;
STATIC int as_list_len;
/*
* Try to batch vunmaps because they are costly.
*/
STATIC void
free_address(
void *addr)
{
a_list_t *aentry;
spin_lock(&as_lock);
aentry = kmalloc(sizeof(a_list_t), GFP_ATOMIC);
aentry->next = as_free_head;
aentry->vm_addr = addr;
as_free_head = aentry;
as_list_len++;
spin_unlock(&as_lock);
if (aentry) {
spin_lock(&as_lock);
aentry->next = as_free_head;
aentry->vm_addr = addr;
as_free_head = aentry;
as_list_len++;
spin_unlock(&as_lock);
} else {
vunmap(addr);
}
}
STATIC void
......@@ -265,7 +271,8 @@ purge_addresses(void)
{
a_list_t *aentry, *old;
if (as_free_head == NULL) return;
if (as_free_head == NULL)
return;
spin_lock(&as_lock);
aentry = as_free_head;
......@@ -462,7 +469,8 @@ _pagebuf_lookup_pages(
struct page *page;
int gfp_mask, retry_count = 5, rval = 0;
int all_mapped, good_pages, nbytes;
size_t blocksize, size, offset;
unsigned int blocksize, sectorshift;
size_t size, offset;
/* For pagebufs where we want to map an address, do not use
......@@ -508,7 +516,8 @@ _pagebuf_lookup_pages(
return rval;
rval = pi = 0;
blocksize = pb->pb_target->pbr_blocksize;
blocksize = pb->pb_target->pbr_bsize;
sectorshift = pb->pb_target->pbr_sshift;
size = pb->pb_count_desired;
offset = pb->pb_offset;
......@@ -549,15 +558,15 @@ _pagebuf_lookup_pages(
pb->pb_locked = 1;
good_pages--;
} else if (!PagePrivate(page)) {
unsigned long i, range = (offset + nbytes) >> SECTOR_SHIFT;
unsigned long i, range;
ASSERT(blocksize < PAGE_CACHE_SIZE);
ASSERT(!(pb->pb_flags & _PBF_PRIVATE_BH));
/*
* In this case page->private holds a bitmap
* of uptodate sectors (512) within the page
* of uptodate sectors within the page
*/
for (i = offset >> SECTOR_SHIFT; i < range; i++)
ASSERT(blocksize < PAGE_CACHE_SIZE);
range = (offset + nbytes) >> sectorshift;
for (i = offset >> sectorshift; i < range; i++)
if (!test_bit(i, &page->private))
break;
if (i != range)
......@@ -642,8 +651,14 @@ _pagebuf_find( /* find buffer for block */
page_buf_t *pb;
int not_locked;
range_base = (ioff << SECTOR_SHIFT);
range_length = (isize << SECTOR_SHIFT);
range_base = (ioff << BBSHIFT);
range_length = (isize << BBSHIFT);
/* Ensure we never do IOs smaller than the sector size */
BUG_ON(range_length < (1 << target->pbr_sshift));
/* Ensure we never do IOs that are not sector aligned */
BUG_ON(range_base & (loff_t)target->pbr_smask);
hval = _bhash(target->pbr_bdev->bd_dev, range_base);
h = &pbhash[hval];
......@@ -851,8 +866,20 @@ pagebuf_readahead(
size_t isize,
page_buf_flags_t flags)
{
struct backing_dev_info *bdi;
bdi = target->pbr_mapping->backing_dev_info;
if (bdi_read_congested(bdi))
return;
if (bdi_write_congested(bdi))
return;
flags |= (PBF_TRYLOCK|PBF_READ|PBF_ASYNC|PBF_MAPPABLE|PBF_READ_AHEAD);
/* don't complain on allocation failure, it's fine with us */
current->flags |= PF_NOWARN;
pagebuf_get(target, ioff, isize, flags);
current->flags &= ~PF_NOWARN;
}
page_buf_t *
......@@ -956,18 +983,12 @@ pagebuf_get_no_daddr(
} else {
kfree(rmem); /* free the mem from the previous try */
tlen <<= 1; /* double the size and try again */
/*
printk(
"pb_get_no_daddr NOT block 0x%p mask 0x%p len %d\n",
rmem, ((size_t)rmem & (size_t)~SECTOR_MASK),
len);
*/
}
if ((rmem = kmalloc(tlen, GFP_KERNEL)) == 0) {
pagebuf_free(pb);
return NULL;
}
} while ((size_t)rmem != ((size_t)rmem & (size_t)~SECTOR_MASK));
} while ((size_t)rmem != ((size_t)rmem & ~target->pbr_smask));
if ((rval = pagebuf_associate_memory(pb, rmem, len)) != 0) {
kfree(rmem);
......@@ -1248,9 +1269,7 @@ pagebuf_iostart( /* start I/O on a buffer */
pb->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_DELWRI|PBF_READ_AHEAD);
pb->pb_flags |= flags & (PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_SYNC|PBF_READ_AHEAD);
if (pb->pb_bn == PAGE_BUF_DADDR_NULL) {
BUG();
}
BUG_ON(pb->pb_bn == PAGE_BUF_DADDR_NULL);
/* For writes call internal function which checks for
* filesystem specific callout function and execute it.
......@@ -1279,7 +1298,8 @@ bio_end_io_pagebuf(
int error)
{
page_buf_t *pb = (page_buf_t *)bio->bi_private;
unsigned int i, blocksize = pb->pb_target->pbr_blocksize;
unsigned int i, blocksize = pb->pb_target->pbr_bsize;
unsigned int sectorshift = pb->pb_target->pbr_sshift;
struct bio_vec *bvec = bio->bi_io_vec;
if (bio->bi_size)
......@@ -1299,10 +1319,8 @@ bio_end_io_pagebuf(
unsigned int j, range;
ASSERT(blocksize < PAGE_CACHE_SIZE);
ASSERT(!(pb->pb_flags & _PBF_PRIVATE_BH));
range = (bvec->bv_offset + bvec->bv_len)>>SECTOR_SHIFT;
for (j = bvec->bv_offset>>SECTOR_SHIFT; j < range; j++)
range = (bvec->bv_offset + bvec->bv_len) >> sectorshift;
for (j = bvec->bv_offset >> sectorshift; j < range; j++)
set_bit(j, &page->private);
if (page->private == (unsigned long)(PAGE_CACHE_SIZE-1))
SetPageUptodate(page);
......@@ -1353,7 +1371,7 @@ pagebuf_iorequest( /* start real I/O */
int offset = pb->pb_offset;
int size = pb->pb_count_desired;
sector_t sector = pb->pb_bn;
size_t blocksize = pb->pb_target->pbr_blocksize;
unsigned int blocksize = pb->pb_target->pbr_bsize;
int locking;
locking = (pb->pb_flags & _PBF_LOCKABLE) == 0 && (pb->pb_locked == 0);
......@@ -1382,7 +1400,7 @@ pagebuf_iorequest( /* start real I/O */
bio = bio_alloc(GFP_NOIO, 1);
bio->bi_bdev = pb->pb_target->pbr_bdev;
bio->bi_sector = sector - (offset >> SECTOR_SHIFT);
bio->bi_sector = sector - (offset >> BBSHIFT);
bio->bi_end_io = bio_end_io_pagebuf;
bio->bi_private = pb;
bio->bi_vcnt++;
......@@ -1427,7 +1445,7 @@ pagebuf_iorequest( /* start real I/O */
next_chunk:
atomic_inc(&PBP(pb)->pb_io_remaining);
nr_pages = BIO_MAX_SECTORS >> (PAGE_SHIFT - SECTOR_SHIFT);
nr_pages = BIO_MAX_SECTORS >> (PAGE_SHIFT - BBSHIFT);
if (nr_pages > total_nr_pages)
nr_pages = total_nr_pages;
......@@ -1452,7 +1470,7 @@ pagebuf_iorequest( /* start real I/O */
offset = 0;
sector += nbytes >> SECTOR_SHIFT;
sector += nbytes >> BBSHIFT;
size -= nbytes;
total_nr_pages--;
}
......
......@@ -132,11 +132,12 @@ typedef enum page_buf_flags_e { /* pb_flags values */
#define PBR_ALIGNED_ONLY 2 /* only use aligned I/O */
typedef struct pb_target {
int pbr_flags;
dev_t pbr_dev;
struct block_device *pbr_bdev;
struct address_space *pbr_mapping;
unsigned int pbr_blocksize;
unsigned int pbr_bsize;
unsigned int pbr_sshift;
size_t pbr_smask;
} pb_target_t;
/*
......
......@@ -30,6 +30,7 @@
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <xfs_types.h>
......
......@@ -33,6 +33,7 @@
#define __XFS_H__
#include <linux/config.h>
#include <linux/types.h>
#include <xfs_types.h>
#include <xfs_arch.h>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment