This is a brief list of all the files in ./linux/Documentation and what
-they contain. If you add a documentation file, please list it here in
-alphabetical order as well, or risk being hunted down like a rabid dog.
+they contain. If you add a documentation file, please list it here in
+alphabetical order as well, or risk being hunted down like a rabid dog.
Please try and keep the descriptions small enough to fit on one line.
Thanks -- Paul G.
- directory with DocBook templates etc. for kernel documentation.
IO-mapping.txt
- how to access I/O mapped memory from within device drivers.
+IPMI.txt
+ - info on Linux Intelligent Platform Management Interface (IPMI) Driver.
IRQ-affinity.txt
- how to select which CPU(s) handle which interrupt events on SMP.
+MSI-HOWTO.txt
+ - the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ.
README.DAC960
- - info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux
+ - info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux.
README.moxa
- release notes for Moxa mutiport serial card.
SAK.txt
- how to change your VGA cursor from a blinking underscore.
arm/
- directory with info about Linux on the ARM architecture.
+as-iosched.txt
+ - info on anticipatory IO scheduler.
+basic_profiling.txt
+ - basic instructions for those who wants to profile Linux kernel.
binfmt_misc.txt
- info on the kernel support for extra binary formats.
block/
cdrom/
- directory with information on the CD-ROM drivers that Linux has.
computone.txt
- - info on Computone Intelliport II/Plus Multiport Serial Driver
+ - info on Computone Intelliport II/Plus Multiport Serial Driver.
cpqarray.txt
- info on using Compaq's SMART2 Intelligent Disk Array Controllers.
cpufreq/
- - info on CPU frequency and voltage scaling
+ - info on CPU frequency and voltage scaling.
cris/
- directory with info about Linux on CRIS architecture.
+debugging-modules.txt
+ - some notes on debugging modules after Linux 2.6.3.
devices.txt
- - plain ASCII listing of all the nodes in /dev/ with major minor #'s
+ - plain ASCII listing of all the nodes in /dev/ with major minor #'s.
digiboard.txt
- info on the Digiboard PC/X{i,e,eve} multiport boards.
digiepca.txt
- info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
dnotify.txt
- info about directory notification in Linux.
-driver-model.txt
- - info about Linux driver model.
+driver-model/
+ - directory with info about Linux driver model.
+dvb/
+ - info on Linux Digital Video Broadcast (DVB) subsystem.
early-userspace/
- info about initramfs, klibc, and userspace early during boot.
+eisa.txt
+ - info on EISA bus support.
exception.txt
- how Linux v2.2 handles exceptions without verify_area etc.
fb/
floppy.txt
- notes and driver options for the floppy disk driver.
ftape.txt
- - notes about the floppy tape device driver
+ - notes about the floppy tape device driver.
hayes-esp.txt
- info on using the Hayes ESP serial driver.
highuid.txt
- notes on the change from 16 bit to 32 bit user/group IDs.
+hw_random.txt
+ - info on Linux support for random number generator in i8xx chipsets.
i2c/
- - directory with info about the I2C bus/protocol (2 wire, kHz speed)
+ - directory with info about the I2C bus/protocol (2 wire, kHz speed).
i386/
- - directory with info about Linux on intel 32 bit architecture.
-i810_rng.txt
- - info on Linux support for random number generator in i8xx chipsets.
+ - directory with info about Linux on Intel 32 bit architecture.
ia64/
- - directory with info about Linux on intel 64 bit architecture.
+ - directory with info about Linux on Intel 64 bit architecture.
ide.txt
- - important info for users of ATA devices (IDE/EIDE disks and CD-ROMS)
+ - important info for users of ATA devices (IDE/EIDE disks and CD-ROMS).
initrd.txt
- how to use the RAM disk as an initial/temporary root filesystem.
input/
- info on Linux input device support.
ioctl-number.txt
- how to implement and register device/driver ioctl calls.
+iostats.txt
+ - info on I/O statistics Linux kernel provides.
isapnp.txt
- - info on Linux ISA Plug & Play support
+ - info on Linux ISA Plug & Play support.
isdn/
- directory with info on the Linux ISDN support, and supported cards.
java.txt
- - info on the in-kernel binary support for Java(tm)
+ - info on the in-kernel binary support for Java(tm).
kbuild/
- - directory with info about the kernel build process
+ - directory with info about the kernel build process.
kernel-doc-nano-HOWTO.txt
- mini HowTo on generation and location of kernel documentation files.
kernel-docs.txt
- listing of various WWW + books that document kernel internals.
kernel-parameters.txt
- summary listing of command line / boot prompt args for the kernel.
+kobject.txt
+ - info of the kobject infrastructure of the Linux kernel.
ldm.txt
- a brief description of LDM (Windows Dynamic Disks).
locks.txt
- info on file locking implementations, flock() vs. fcntl(), etc.
logo.gif
- - Full colour GIF image of Linux logo (penguin)
+ - Full colour GIF image of Linux logo (penguin).
logo.txt
- Info on creator of above logo & site to get additional images from.
m68k/
mca.txt
- info on supporting Micro Channel Architecture (e.g. PS/2) systems.
md.txt
- - info on boot arguments for the multiple devices driver
+ - info on boot arguments for the multiple devices driver.
memory.txt
- info on typical Linux memory problems.
mips/
- directory with info about Linux on MIPS architecture.
mkdev.cciss
- - script to make /dev entries for SMART controllers (see cciss.txt)
+ - script to make /dev entries for SMART controllers (see cciss.txt).
mkdev.ida
- script to make /dev entries for Intelligent Disk Array Controllers.
moxa-smartio
- info on installing/using Moxa multiport serial driver.
mtrr.txt
- - how to use PPro Memory Type Range Registers to increase performance
+ - how to use PPro Memory Type Range Registers to increase performance.
nbd.txt
- info on a TCP implementation of a network block device.
networking/
- directory with info on various aspects of networking with Linux.
nfsroot.txt
- - short guide on setting up a diskless box with NFS root filesystem
+ - short guide on setting up a diskless box with NFS root filesystem.
nmi_watchdog.txt
- - info on NMI watchdog for SMP systems
+ - info on NMI watchdog for SMP systems.
oops-tracing.txt
- how to decode those nasty internal kernel error dump messages.
paride.txt
parport-lowlevel.txt
- description and usage of the low level parallel port functions.
pci.txt
- - info on the PCI subsystem for device driver authors
-pcwd-watchdog.txt
- - info and sample code for using with the PC Watchdog reset card.
+ - info on the PCI subsystem for device driver authors.
pm.txt
- info on Linux power management support.
+pnp.txt
+ - Linux Plug and Play documentation.
power/
- directory with info on Linux PCI power management.
powerpc/
riscom8.txt
- notes on using the RISCom/8 multi-port serial driver.
rocket.txt
- - info on installing/using the Comtrol RocketPort multiport serial driver
+ - info on installing/using the Comtrol RocketPort multiport serial driver.
+rpc-cache.txt
+ - introduction to the caching mechanisms in the sunrpc layer.
rtc.txt
- notes on how to use the Real Time Clock (aka CMOS clock) driver.
s390/
- directory with info on using Linux on the IBM S390.
-sh/
- - directory with info on porting Linux to a new architecture.
+sched-design.txt
+ - goals, design and implementation of the Linux O(1) scheduler.
scsi/
- directory with info on Linux scsi support.
serial-console.txt
- how to set up Linux with a serial line console as the default.
sgi-visws.txt
- short blurb on the SGI Visual Workstations.
+sh/
+ - directory with info on porting Linux to a new architecture.
smart-config.txt
- description of the Smart Config makefile feature.
-smp.tex
- - LaTeX document describing implementation of Multiprocessor Linux
smp.txt
- - a few more notes on symmetric multi-processing
+ - a few notes on symmetric multi-processing.
sonypi.txt
- info on Linux Sony Programmable I/O Device support.
sound/
- - directory with info on sound card support
+ - directory with info on sound card support.
sparc/
- directory with info on using Linux on Sparc architecture.
specialix.txt
sx.txt
- info on the Specialix SX/SI multiport serial driver.
sysctl/
- - directory with info on the /proc/sys/* files
+ - directory with info on the /proc/sys/* files.
sysrq.txt
- - info on the magic SysRq key
+ - info on the magic SysRq key.
telephony/
- directory with info on telephony (e.g. voice over IP) support.
unicode.txt
- directory with info regarding video/TV/radio cards and linux.
vm/
- directory with info on the Linux vm code.
-watchdog.txt
+watchdog/
- how to auto-reboot Linux if it has "fallen and can't get up". ;-)
x86_64/
- directory with info on Linux support for AMD x86-64 (Hammer) machines.
- XPM image of penguin logo (see logo.txt) sitting on an xterm.
zorro.txt
- info on writing drivers for Zorro bus devices found on Amigas.
-
to the chipset support if you wish.
make config
- make dep
make clean
make zImage
make modules
ZR36067 VIDEO FOR LINUX DRIVER
P: Ronald Bultje
-M: R.S.Bultje@pharm.uu.nl
+M: rbultje@ronald.bitfreak.net
L: mjpeg-users@lists.sourceforge.net
W: http://mjpeg.sourceforge.net/driver-zoran/
S: Maintained
Please note that you can still run a.out user programs with this kernel.
- - Do a "make bzImage" to create a compressed kernel image. If you want
- to make a boot disk (without root filesystem or LILO), insert a floppy
- in your A: drive, and do a "make bzdisk". It is also possible to do
- "make install" if you have lilo installed to suit the kernel makefiles,
- but you may want to check your particular lilo setup first.
+ - Do a "make" to create a compressed kernel image. It is also
+ possible to do "make install" if you have lilo installed to suit the
+ kernel makefiles, but you may want to check your particular lilo setup first.
To do the actual install you have to be root, but none of the normal
build should require that. Don't take the name of root in vain.
- - In the unlikely event that your system cannot boot bzImage kernels you
- can still compile your kernel as zImage. However, since zImage support
- will be removed at some point in the future in favor of bzImage we
- encourage people having problems with booting bzImage kernels to report
- these, with detailed hardware configuration information, to the
- linux-kernel mailing list and to H. Peter Anvin <hpa+linux@zytor.com>.
-
- If you configured any of the parts of the kernel as `modules', you
- will have to do "make modules" followed by "make modules_install".
+ will also have to do "make modules_install".
- Keep a backup kernel handy in case something goes wrong. This is
especially true for the development releases, since each new release
do a "make modules_install".
- In order to boot your new kernel, you'll need to copy the kernel
- image (found in .../linux/arch/i386/boot/bzImage after compilation)
+ image (e.g. .../linux/arch/i386/boot/bzImage after compilation)
to the place where your regular bootable kernel is found.
- For some, this is on a floppy disk, in which case you can copy the
- kernel bzImage file to /dev/fd0 to make a bootable floppy.
+ - Booting a kernel directly from a floppy without the assistance of a
+ bootloader such as LILO, is no longer supported.
If you boot Linux from the hard drive, chances are you use LILO which
uses the kernel image as specified in the file /etc/lilo.conf. The
the above example it's due to a bad kernel pointer). More information
on making sense of the dump is in Documentation/oops-tracing.txt
- - You can use the "ksymoops" program to make sense of the dump. This
- utility can be downloaded from
+ - If you compiled the kernel with CONFIG_KALLSYMS you can send the dump
+ as is, otherwise you will have to use the "ksymoops" program to make
+ sense of the dump. This utility can be downloaded from
ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops.
Alternately you can do the dump lookup by hand:
extra-y := $(head-y) init_task.o vmlinux.lds.s
-# Spell out some dependencies that `make dep' doesn't spot
+# Spell out some dependencies that aren't automatically figured out
$(obj)/entry-armv.o: $(obj)/entry-header.S include/asm-arm/constants.h
$(obj)/entry-common.o: $(obj)/entry-header.S include/asm-arm/constants.h \
$(obj)/calls.S
#
# Makefile for the linux arm26-specific parts of the memory manager.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definition is now in the main makefile...
-
-# Object file lists.
obj-y := init.o extable.o proc-funcs.o mm-memc.o fault.o
#
# Makefile for the linux m68k-specific parts of the memory manager.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definition is now in the main makefile...
obj-y := init.o fault.o memory.o kmap.o
#VPATH := $(VPATH):$(BOARD)
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
.S.o:
$(CC) -D__ASSEMBLY__ $(AFLAGS) -I. -c $< -o $*.o
#
# Makefile for the linux kernel.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
extra-y := crt0_ram.o
obj-y := timer.o
#
# Makefile for the linux kernel.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := timer.o
extra-y = crt0_$(MODEL).o
#
# Makefile for the linux kernel.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
extra-y := crt0_ram.o
obj-y := timer.o
#VPATH := $(VPATH):$(BOARD)
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
.S.o:
$(CC) -D__ASSEMBLY__ $(AFLAGS) -I. -c $< -o $*.o
#
# Makefile for the linux kernel.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
extra-y := crt0_ram.o
obj-y := timer.o
#
# Makefile for the linux kernel.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
extra-y = crt0_$(MODEL).o
obj-y := timer.o
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
CONFIG_LOG_BUF_SHIFT=15
+CONFIG_HOTPLUG=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# Processor type and features
#
CONFIG_X86_PC=y
+# CONFIG_X86_ELAN is not set
# CONFIG_X86_VOYAGER is not set
# CONFIG_X86_NUMAQ is not set
# CONFIG_X86_SUMMIT is not set
# CONFIG_M686 is not set
# CONFIG_MPENTIUMII is not set
# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
CONFIG_MPENTIUM4=y
# CONFIG_MK6 is not set
# CONFIG_MK7 is not set
# CONFIG_MATH_EMULATION is not set
CONFIG_MTRR=y
# CONFIG_EFI is not set
+CONFIG_IRQBALANCE=y
CONFIG_HAVE_DEC_LOCK=y
+# CONFIG_REGPARM is not set
#
# Power management options (ACPI, APM)
CONFIG_ACPI_PCI=y
CONFIG_ACPI_SYSTEM=y
# CONFIG_ACPI_RELAXED_AML is not set
+# CONFIG_X86_PM_TIMER is not set
#
# APM (Advanced Power Management) BIOS Support
# CONFIG_EISA is not set
# CONFIG_MCA is not set
# CONFIG_SCx200 is not set
-CONFIG_HOTPLUG=y
#
# PCMCIA/CardBus support
#
# IDE chipset support/bugfixes
#
+CONFIG_IDE_GENERIC=y
CONFIG_BLK_DEV_CMD640=y
# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
# CONFIG_BLK_DEV_IDEPNP is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX_CONFIG=y
+CONFIG_SCSI_QLA2XXX=y
# CONFIG_SCSI_QLA21XX is not set
# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA23XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_FUSION is not set
#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# IEEE 1394 (FireWire) support
#
CONFIG_IEEE1394=y
#
# CONFIG_IEEE1394_VERBOSEDEBUG is not set
# CONFIG_IEEE1394_OUI_DB is not set
+# CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set
#
# Device Drivers
# CONFIG_IEEE1394_SBP2 is not set
# CONFIG_IEEE1394_ETH1394 is not set
# CONFIG_IEEE1394_DV1394 is not set
-# CONFIG_IEEE1394_RAWIO is not set
+CONFIG_IEEE1394_RAWIO=y
# CONFIG_IEEE1394_CMP is not set
#
# CONFIG_I2O is not set
#
+# Macintosh device drivers
+#
+
+#
# Networking support
#
CONFIG_NET=y
# CONFIG_NE2K_PCI is not set
# CONFIG_8139CP is not set
CONFIG_8139TOO=y
-# CONFIG_8139TOO_PIO is not set
+CONFIG_8139TOO_PIO=y
# CONFIG_8139TOO_TUNE_TWISTER is not set
# CONFIG_8139TOO_8129 is not set
# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_8139_RXBUF_IDX=2
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
#
# ISDN subsystem
#
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
#
# Telephony Support
#
CONFIG_SERIAL_CORE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
CONFIG_PRINTER=y
# CONFIG_LP_CONSOLE is not set
# CONFIG_PPDEV is not set
# CONFIG_AGP_SIS is not set
# CONFIG_AGP_SWORKS is not set
# CONFIG_AGP_VIA is not set
+# CONFIG_AGP_EFFICEON is not set
CONFIG_DRM=y
# CONFIG_DRM_TDFX is not set
# CONFIG_DRM_GAMMA is not set
#
# CONFIG_SND_ALI5451 is not set
# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
# CONFIG_SND_CS46XX is not set
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_EMU10K1 is not set
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_SCANNER is not set
# CONFIG_USB_MICROTEK is not set
# CONFIG_USB_HPUSBSCSI is not set
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
# Kernel hacking
#
# CONFIG_DEBUG_KERNEL is not set
+CONFIG_EARLY_PRINTK=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_FRAME_POINTER is not set
CONFIG_X86_FIND_SMP_CONFIG=y
*
* Based on the powernow-k7.c module written by Dave Jones.
* (C) 2003 Dave Jones <davej@codemonkey.ork.uk> on behalf of SuSE Labs
+ * (C) 2004 Dominik Brodowski <linux@brodo.de>
+ * (C) 2004 Pavel Machek <pavel@suse.cz>
* Licensed under the terms of the GNU GPL License version 2.
* Based upon datasheets & sample CPUs kindly provided by AMD.
*
#define VERSION "version 1.00.08a"
#include "powernow-k8.h"
-#ifdef CONFIG_PREEMPT
-#warning this driver has not been tested on a preempt system
-#endif
-
static u32 vstable; /* voltage stabalization time, from PSB, units 20 us */
static u32 plllock; /* pll lock time, from PSB, units 1 us */
static u32 numps; /* number of p-states, from PSB */
return -ENOMEM;
}
- for (j = 0; j < numps; j++) {
- printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n", j,
- pst[j].fid, find_freq_from_fid(pst[j].fid), pst[j].vid);
+ for (j = 0; j < psb->numpstates; j++) {
powernow_table[j].index = pst[j].fid; /* lower 8 bits */
powernow_table[j].index |= (pst[j].vid << 8); /* upper 8 bits */
- powernow_table[j].frequency = find_freq_from_fid(pst[j].fid);
}
+
+ /* If you want to override your frequency tables, this
+ is right place. */
+
+ for (j = 0; j < numps; j++) {
+ powernow_table[j].frequency = find_freq_from_fid(powernow_table[j].index & 0xff)*1000;
+ printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n", j,
+ powernow_table[j].index & 0xff,
+ powernow_table[j].frequency/1000,
+ powernow_table[j].index >> 8);
+ }
+
powernow_table[numps].frequency = CPUFREQ_TABLE_END;
powernow_table[numps].index = 0;
#
# Makefile for the linux kernel.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definitions are now in the main makefile...
EXTRA_CFLAGS += -I../kernel
obj-y := setup.o voyager_basic.o voyager_thread.o
}
-static void nmi_save_registers(struct op_msrs * msrs)
+static void nmi_cpu_save_registers(struct op_msrs * msrs)
{
unsigned int const nr_ctrs = model->num_counters;
unsigned int const nr_ctrls = model->num_controls;
}
+static void nmi_save_registers(void * dummy)
+{
+ int cpu = smp_processor_id();
+ struct op_msrs * msrs = &cpu_msrs[cpu];
+ model->fill_in_addresses(msrs);
+ nmi_cpu_save_registers(msrs);
+}
+
+
static void free_msrs(void)
{
int i;
{
int cpu = smp_processor_id();
struct op_msrs * msrs = &cpu_msrs[cpu];
- model->fill_in_addresses(msrs);
- nmi_save_registers(msrs);
spin_lock(&oprofilefs_lock);
model->setup_ctrs(msrs);
spin_unlock(&oprofilefs_lock);
* break the core code horrifically.
*/
disable_lapic_nmi_watchdog();
+ /* We need to serialize save and setup for HT because the subset
+ * of msrs are distinct for save and setup operations
+ */
+ on_each_cpu(nmi_save_registers, NULL, 0, 1);
on_each_cpu(nmi_cpu_setup, NULL, 0, 1);
set_nmi_callback(nmi_callback);
nmi_enabled = 1;
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <asm/amipcmcia.h>
-#include <asm/unistd.h>
extern int cia_request_irq(struct ciabase *base,int irq,
irqreturn_t (*handler)(int, void *, struct pt_regs *),
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/traps.h>
-#include <asm/unistd.h>
static irqreturn_t bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp);
#include <asm/io.h>
#include <asm/system.h>
#include <asm/traps.h>
-#include <asm/unistd.h>
#include "ints.h"
/* Clock hardware definitions */
#include <asm/macints.h>
#include <asm/mac_iop.h>
#include <asm/mac_oss.h>
-#include <asm/unistd.h>
/*#define DEBUG_IOP*/
#include <asm/hwtest.h>
#include <asm/errno.h>
#include <asm/macints.h>
-#include <asm/unistd.h>
#define DEBUG_SPURIOUS
#define SHUTUP_SONIC
#include <asm/macints.h>
#include <asm/mac_via.h>
#include <asm/mac_oss.h>
-#include <asm/unistd.h>
int oss_present;
volatile struct mac_oss *oss;
#include <asm/macintosh.h>
#include <asm/macints.h>
#include <asm/mac_psc.h>
-#include <asm/unistd.h>
#define DEBUG_PSC
#include <asm/machw.h>
#include <asm/mac_via.h>
#include <asm/mac_psc.h>
-#include <asm/unistd.h>
volatile __u8 *via1, *via2;
#if 0
#include <asm/irq.h>
#include <asm/hardirq.h>
#include <asm/traps.h>
-#include <asm/unistd.h>
#include <asm/q40_master.h>
#include <asm/q40ints.h>
#include <asm/intersil.h>
#include <asm/oplib.h>
#include <asm/sun3ints.h>
-#include <asm/unistd.h>
#include <linux/seq_file.h>
extern void sun3_leds (unsigned char);
#
# Makefile for the Cogent CSB250 Au1500 board. Copied from Pb1500.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
USE_STANDARD_AS_RULE := true
#
# Makefile for the Alchemy Semiconductor PB1000 board.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
.S.s:
$(CPP) $(CFLAGS) $< -o $*.s
#
# Makefile for 4G Systems MTX-1 board.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
lib-y := init.o board_setup.o irqmap.o
#
# Makefile for the Alchemy Semiconductor PB1000 board.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
.S.s:
$(CPP) $(CFLAGS) $< -o $*.s
#
# Makefile for MyCable XXS1500 board.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
lib-y := init.o board_setup.o irqmap.o
* Example:
* $ cd ~/linux
* $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging>
- * $ make dep; make vmlinux
+ * $ make
*
* Step 3:
* Download the kernel to the remote target and start
#
# Makefile for Momentum Computer's Jaguar-ATX board.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y += mv-irq.o int-handler.o irq.o pci-irq.o prom.o reset.o setup.o
obj-$(CONFIG_PCI) += pci.o
#
# Makefile for common code for Toshiba TX4927 based systems
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := tx4927_prom.o
obj-y += tx4927_setup.o
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
CONFIG_LOG_BUF_SHIFT=17
+CONFIG_HOTPLUG=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
CONFIG_PPC_OF=y
CONFIG_ALTIVEC=y
CONFIG_PPC_PMAC=y
+# CONFIG_PMAC_DART is not set
CONFIG_PPC_PMAC64=y
CONFIG_BOOTX_TEXT=y
CONFIG_POWER4_ONLY=y
+# CONFIG_IOMMU_VMERGE is not set
CONFIG_SMP=y
CONFIG_IRQ_ALL_CPUS=y
CONFIG_NR_CPUS=2
# CONFIG_HMT is not set
-CONFIG_DISCONTIGMEM=y
-# CONFIG_NUMA is not set
+# CONFIG_DISCONTIGMEM is not set
# CONFIG_PPC_RTAS is not set
# CONFIG_LPARCFG is not set
# CONFIG_BINFMT_MISC is not set
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
-CONFIG_HOTPLUG=y
#
# PCMCIA/CardBus support
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_INITRD=y
+# CONFIG_DCSSBLK is not set
#
# ATA/ATAPI/MFM/RLL support
# CONFIG_MD_MULTIPATH is not set
CONFIG_BLK_DEV_DM=y
CONFIG_DM_IOCTL_V4=y
+# CONFIG_DM_CRYPT is not set
#
# Fusion MPT device support
# CONFIG_FUSION is not set
#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# IEEE 1394 (FireWire) support
#
CONFIG_IEEE1394=y
#
# Macintosh device drivers
#
+CONFIG_ADB=y
CONFIG_ADB_PMU=y
# CONFIG_PMAC_PBOOK is not set
# CONFIG_PMAC_BACKLIGHT is not set
# CONFIG_MAC_SERIAL is not set
-CONFIG_ADB=y
# CONFIG_INPUT_ADBHID is not set
CONFIG_THERM_PM72=y
# CONFIG_IXGB is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
+# CONFIG_IBMVETH is not set
CONFIG_PPP=m
# CONFIG_PPP_MULTILINK is not set
# CONFIG_PPP_FILTER is not set
#
# ISDN subsystem
#
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
#
# Telephony Support
#
# CONFIG_SERIAL_PMACZILOG is not set
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
CONFIG_HVC_CONSOLE=y
#
# CONFIG_FB_RADEON_OLD is not set
CONFIG_FB_RADEON=y
CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
# CONFIG_FB_SIS is not set
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
CONFIG_DEVPTS_FS_XATTR=y
# CONFIG_DEVPTS_FS_SECURITY is not set
CONFIG_TMPFS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CIFS=m
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
# Kernel hacking
#
CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
-# CONFIG_XMON is not set
+# CONFIG_DEBUGGER is not set
# CONFIG_PPCDBG is not set
# CONFIG_DEBUG_INFO is not set
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* Change Activity:
- * 2001/10/27 : engebret : Created.
- * End Change Activity
- */
-
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/bootmem.h>
#include <linux/mm.h>
+#include <linux/rbtree.h>
+#include <linux/spinlock.h>
+#include <linux/seq_file.h>
#include <asm/paca.h>
#include <asm/processor.h>
#include <asm/naca.h>
#include <asm/io.h>
#include <asm/machdep.h>
+#include <asm/pgtable.h>
#include "pci.h"
+#undef DEBUG
+
#define BUID_HI(buid) ((buid) >> 32)
#define BUID_LO(buid) ((buid) & 0xffffffff)
-#define CONFIG_ADDR(busno, devfn) (((((busno) & 0xff) << 8) | ((devfn) & 0xf8)) << 8)
+#define CONFIG_ADDR(busno, devfn) \
+ (((((busno) & 0xff) << 8) | ((devfn) & 0xf8)) << 8)
-unsigned long eeh_total_mmio_ffs;
-unsigned long eeh_false_positives;
/* RTAS tokens */
static int ibm_set_eeh_option;
static int ibm_set_slot_reset;
static int ibm_read_slot_reset_state;
-static int eeh_implemented;
+static int eeh_subsystem_enabled;
#define EEH_MAX_OPTS 4096
static char *eeh_opts;
static int eeh_opts_last;
-unsigned char slot_err_buf[RTAS_ERROR_LOG_MAX];
+/* System monitoring statistics */
+static DEFINE_PER_CPU(unsigned long, total_mmio_ffs);
+static DEFINE_PER_CPU(unsigned long, false_positives);
+static DEFINE_PER_CPU(unsigned long, ignored_failures);
-pte_t *find_linux_pte(pgd_t *pgdir, unsigned long va); /* from htab.c */
-static int eeh_check_opts_config(struct device_node *dn,
- int class_code, int vendor_id, int device_id,
+static int eeh_check_opts_config(struct device_node *dn, int class_code,
+ int vendor_id, int device_id,
int default_state);
-unsigned long eeh_token_to_phys(unsigned long token)
+/**
+ * The pci address cache subsystem. This subsystem places
+ * PCI device address resources into a red-black tree, sorted
+ * according to the address range, so that given only an i/o
+ * address, the corresponding PCI device can be **quickly**
+ * found.
+ *
+ * Currently, the only customer of this code is the EEH subsystem;
+ * thus, this code has been somewhat tailored to suit EEH better.
+ * In particular, the cache does *not* hold the addresses of devices
+ * for which EEH is not enabled.
+ *
+ * (Implementation Note: The RB tree seems to be better/faster
+ * than any hash algo I could think of for this problem, even
+ * with the penalty of slow pointer chases for d-cache misses).
+ */
+struct pci_io_addr_range
+{
+ struct rb_node rb_node;
+ unsigned long addr_lo;
+ unsigned long addr_hi;
+ struct pci_dev *pcidev;
+ unsigned int flags;
+};
+
+static struct pci_io_addr_cache
+{
+ struct rb_root rb_root;
+ spinlock_t piar_lock;
+} pci_io_addr_cache_root;
+
+static inline struct pci_dev *__pci_get_device_by_addr(unsigned long addr)
+{
+ struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node;
+
+ while (n) {
+ struct pci_io_addr_range *piar;
+ piar = rb_entry(n, struct pci_io_addr_range, rb_node);
+
+ if (addr < piar->addr_lo) {
+ n = n->rb_left;
+ } else {
+ if (addr > piar->addr_hi) {
+ n = n->rb_right;
+ } else {
+ pci_dev_get(piar->pcidev);
+ return piar->pcidev;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * pci_get_device_by_addr - Get device, given only address
+ * @addr: mmio (PIO) phys address or i/o port number
+ *
+ * Given an mmio phys address, or a port number, find a pci device
+ * that implements this address. Be sure to pci_dev_put the device
+ * when finished. I/O port numbers are assumed to be offset
+ * from zero (that is, they do *not* have pci_io_addr added in).
+ * It is safe to call this function within an interrupt.
+ */
+static struct pci_dev *pci_get_device_by_addr(unsigned long addr)
+{
+ struct pci_dev *dev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
+ dev = __pci_get_device_by_addr(addr);
+ spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
+ return dev;
+}
+
+#ifdef DEBUG
+/*
+ * Handy-dandy debug print routine, does nothing more
+ * than print out the contents of our addr cache.
+ */
+static void pci_addr_cache_print(struct pci_io_addr_cache *cache)
{
- if (REGION_ID(token) == EEH_REGION_ID) {
- unsigned long vaddr = IO_TOKEN_TO_ADDR(token);
- pte_t *ptep = find_linux_pte(ioremap_mm.pgd, vaddr);
- unsigned long pa = pte_pfn(*ptep) << PAGE_SHIFT;
- return pa | (vaddr & (PAGE_SIZE-1));
- } else
+ struct rb_node *n;
+ int cnt = 0;
+
+ n = rb_first(&cache->rb_root);
+ while (n) {
+ struct pci_io_addr_range *piar;
+ piar = rb_entry(n, struct pci_io_addr_range, rb_node);
+ printk(KERN_DEBUG "PCI: %s addr range %d [%lx-%lx]: %s %s\n",
+ (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt,
+ piar->addr_lo, piar->addr_hi, pci_name(piar->pcidev),
+ pci_pretty_name(piar->pcidev));
+ cnt++;
+ n = rb_next(n);
+ }
+}
+#endif
+
+/* Insert address range into the rb tree. */
+static struct pci_io_addr_range *
+pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
+ unsigned long ahi, unsigned int flags)
+{
+ struct rb_node **p = &pci_io_addr_cache_root.rb_root.rb_node;
+ struct rb_node *parent = NULL;
+ struct pci_io_addr_range *piar;
+
+ /* Walk tree, find a place to insert into tree */
+ while (*p) {
+ parent = *p;
+ piar = rb_entry(parent, struct pci_io_addr_range, rb_node);
+ if (alo < piar->addr_lo) {
+ p = &parent->rb_left;
+ } else if (ahi > piar->addr_hi) {
+ p = &parent->rb_right;
+ } else {
+ if (dev != piar->pcidev ||
+ alo != piar->addr_lo || ahi != piar->addr_hi) {
+ printk(KERN_WARNING "PIAR: overlapping address range\n");
+ }
+ return piar;
+ }
+ }
+ piar = (struct pci_io_addr_range *)kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
+ if (!piar)
+ return NULL;
+
+ piar->addr_lo = alo;
+ piar->addr_hi = ahi;
+ piar->pcidev = dev;
+ piar->flags = flags;
+
+ rb_link_node(&piar->rb_node, parent, p);
+ rb_insert_color(&piar->rb_node, &pci_io_addr_cache_root.rb_root);
+
+ return piar;
+}
+
+static void __pci_addr_cache_insert_device(struct pci_dev *dev)
+{
+ struct device_node *dn;
+ int i;
+
+ dn = pci_device_to_OF_node(dev);
+ if (!dn) {
+ printk(KERN_WARNING "PCI: no pci dn found for dev=%s %s\n",
+ pci_name(dev), pci_pretty_name(dev));
+ pci_dev_put(dev);
+ return;
+ }
+
+ /* Skip any devices for which EEH is not enabled. */
+ if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) ||
+ dn->eeh_mode & EEH_MODE_NOCHECK) {
+#ifdef DEBUG
+ printk(KERN_INFO "PCI: skip building address cache for=%s %s\n",
+ pci_name(dev), pci_pretty_name(dev));
+#endif
+ pci_dev_put(dev);
+ return;
+ }
+
+ /* Walk resources on this device, poke them into the tree */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ unsigned long start = pci_resource_start(dev,i);
+ unsigned long end = pci_resource_end(dev,i);
+ unsigned int flags = pci_resource_flags(dev,i);
+
+ /* We are interested only bus addresses, not dma or other stuff */
+ if (0 == (flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+ continue;
+ if (start == 0 || ~start == 0 || end == 0 || ~end == 0)
+ continue;
+ pci_addr_cache_insert(dev, start, end, flags);
+ }
+}
+
+/**
+ * pci_addr_cache_insert_device - Add a device to the address cache
+ * @dev: PCI device whose I/O addresses we are interested in.
+ *
+ * In order to support the fast lookup of devices based on addresses,
+ * we maintain a cache of devices that can be quickly searched.
+ * This routine adds a device to that cache.
+ */
+void pci_addr_cache_insert_device(struct pci_dev *dev)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
+ __pci_addr_cache_insert_device(dev);
+ spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
+}
+
+static inline void __pci_addr_cache_remove_device(struct pci_dev *dev)
+{
+ struct rb_node *n;
+
+restart:
+ n = rb_first(&pci_io_addr_cache_root.rb_root);
+ while (n) {
+ struct pci_io_addr_range *piar;
+ piar = rb_entry(n, struct pci_io_addr_range, rb_node);
+
+ if (piar->pcidev == dev) {
+ rb_erase(n, &pci_io_addr_cache_root.rb_root);
+ kfree(piar);
+ goto restart;
+ }
+ n = rb_next(n);
+ }
+ pci_dev_put(dev);
+}
+
+/**
+ * pci_addr_cache_remove_device - remove pci device from addr cache
+ * @dev: device to remove
+ *
+ * Remove a device from the addr-cache tree.
+ * This is potentially expensive, since it will walk
+ * the tree multiple times (once per resource).
+ * But so what; device removal doesn't need to be that fast.
+ */
+void pci_addr_cache_remove_device(struct pci_dev *dev)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
+ __pci_addr_cache_remove_device(dev);
+ spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
+}
+
+/**
+ * pci_addr_cache_build - Build a cache of I/O addresses
+ *
+ * Build a cache of pci i/o addresses. This cache will be used to
+ * find the pci device that corresponds to a given address.
+ * This routine scans all pci busses to build the cache.
+ * Must be run late in boot process, after the pci controllers
+ * have been scaned for devices (after all device resources are known).
+ */
+void __init pci_addr_cache_build(void)
+{
+ struct pci_dev *dev = NULL;
+
+ spin_lock_init(&pci_io_addr_cache_root.piar_lock);
+
+ while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ /* Ignore PCI bridges ( XXX why ??) */
+ if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) {
+ pci_dev_put(dev);
+ continue;
+ }
+ pci_addr_cache_insert_device(dev);
+ }
+
+#ifdef DEBUG
+ /* Verify tree built up above, echo back the list of addrs. */
+ pci_addr_cache_print(&pci_io_addr_cache_root);
+#endif
+}
+
+/**
+ * eeh_token_to_phys - convert EEH address token to phys address
+ * @token i/o token, should be address in the form 0xA....
+ *
+ * Converts EEH address tokens into physical addresses. Note that
+ * ths routine does *not* convert I/O BAR addresses (which start
+ * with 0xE...) to phys addresses!
+ */
+static unsigned long eeh_token_to_phys(unsigned long token)
+{
+ pte_t *ptep;
+ unsigned long pa, vaddr;
+
+ if (REGION_ID(token) == EEH_REGION_ID)
+ vaddr = IO_TOKEN_TO_ADDR(token);
+ else
return token;
+
+ ptep = find_linux_pte(ioremap_mm.pgd, vaddr);
+ pa = pte_pfn(*ptep) << PAGE_SHIFT;
+
+ return pa | (vaddr & (PAGE_SIZE-1));
}
-/* Check for an eeh failure at the given token address.
+/**
+ * eeh_check_failure - check if all 1's data is due to EEH slot freeze
+ * @token i/o token, should be address in the form 0xA....
+ * @val value, should be all 1's (XXX why do we need this arg??)
+ *
+ * Check for an eeh failure at the given token address.
* The given value has been read and it should be 1's (0xff, 0xffff or
* 0xffffffff).
*
* Probe to determine if an error actually occurred. If not return val.
* Otherwise panic.
+ *
+ * Note this routine might be called in an interrupt context ...
*/
unsigned long eeh_check_failure(void *token, unsigned long val)
{
struct pci_dev *dev;
struct device_node *dn;
unsigned long ret, rets[2];
+ static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+ /* dont want this on the stack */
+ static unsigned char slot_err_buf[RTAS_ERROR_LOG_MAX];
+ unsigned long flags;
- /* IO BAR access could get us here...or if we manually force EEH
- * operation on even if the hardware won't support it.
- */
- if (!eeh_implemented || ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE)
+ __get_cpu_var(total_mmio_ffs)++;
+
+ if (!eeh_subsystem_enabled)
return val;
- /* Finding the phys addr + pci device is quite expensive.
- * However, the RTAS call is MUCH slower.... :(
- */
+ /* Finding the phys addr + pci device; this is pretty quick. */
addr = eeh_token_to_phys((unsigned long)token);
- dev = pci_find_dev_by_addr(addr);
- if (!dev) {
- printk("EEH: no pci dev found for addr=0x%lx\n", addr);
+ dev = pci_get_device_by_addr(addr);
+ if (!dev)
return val;
- }
+
dn = pci_device_to_OF_node(dev);
if (!dn) {
- printk("EEH: no pci dn found for addr=0x%lx\n", addr);
+ pci_dev_put(dev);
return val;
}
/* Access to IO BARs might get this far and still not want checking. */
- if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) || dn->eeh_mode & EEH_MODE_NOCHECK)
+ if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) ||
+ dn->eeh_mode & EEH_MODE_NOCHECK) {
+ pci_dev_put(dev);
return val;
+ }
+ if (!dn->eeh_config_addr) {
+ pci_dev_put(dev);
+ return val;
+ }
- /* Now test for an EEH failure. This is VERY expensive.
+ /*
+ * Now test for an EEH failure. This is VERY expensive.
* Note that the eeh_config_addr may be a parent device
* in the case of a device behind a bridge, or it may be
* function zero of a multi-function device.
* In any case they must share a common PHB.
*/
- if (dn->eeh_config_addr) {
- ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets,
- dn->eeh_config_addr, BUID_HI(dn->phb->buid),
- BUID_LO(dn->phb->buid));
- if (ret == 0 && rets[1] == 1 && rets[0] >= 2) {
- unsigned long slot_err_ret;
-
- memset(slot_err_buf, 0, RTAS_ERROR_LOG_MAX);
- slot_err_ret = rtas_call(rtas_token("ibm,slot-error-detail"),
- 8, 1, NULL, dn->eeh_config_addr,
- BUID_HI(dn->phb->buid),
- BUID_LO(dn->phb->buid), NULL, 0,
- __pa(slot_err_buf), RTAS_ERROR_LOG_MAX,
- 2 /* Permanent Error */);
-
- if (slot_err_ret == 0)
- log_error(slot_err_buf, ERR_TYPE_RTAS_LOG, 1 /* Fatal */);
-
- /*
- * XXX We should create a separate sysctl for this.
- *
- * Since the panic_on_oops sysctl is used to halt
- * the system in light of potential corruption, we
- * can use it here.
- */
- if (panic_on_oops)
- panic("EEH: MMIO failure (%ld) on device:\n%s\n",
- rets[0], pci_name(dev));
- else
- printk("EEH: MMIO failure (%ld) on device:\n%s\n",
- rets[0], pci_name(dev));
+ ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets,
+ dn->eeh_config_addr, BUID_HI(dn->phb->buid),
+ BUID_LO(dn->phb->buid));
+
+ if (ret == 0 && rets[1] == 1 && rets[0] >= 2) {
+ unsigned long slot_err_ret;
+
+ spin_lock_irqsave(&lock, flags);
+ memset(slot_err_buf, 0, RTAS_ERROR_LOG_MAX);
+ slot_err_ret = rtas_call(rtas_token("ibm,slot-error-detail"),
+ 8, 1, NULL, dn->eeh_config_addr,
+ BUID_HI(dn->phb->buid),
+ BUID_LO(dn->phb->buid), NULL, 0,
+ __pa(slot_err_buf),
+ RTAS_ERROR_LOG_MAX,
+ 2 /* Permanent Error */);
+
+ if (slot_err_ret == 0)
+ log_error(slot_err_buf, ERR_TYPE_RTAS_LOG,
+ 1 /* Fatal */);
+
+ spin_unlock_irqrestore(&lock, flags);
+
+ /*
+ * XXX We should create a separate sysctl for this.
+ *
+ * Since the panic_on_oops sysctl is used to halt
+ * the system in light of potential corruption, we
+ * can use it here.
+ */
+ if (panic_on_oops) {
+ panic("EEH: MMIO failure (%ld) on device:%s %s\n",
+ rets[0], pci_name(dev), pci_pretty_name(dev));
+ } else {
+ __get_cpu_var(ignored_failures)++;
+ printk(KERN_INFO "EEH: MMIO failure (%ld) on device:%s %s\n",
+ rets[0], pci_name(dev), pci_pretty_name(dev));
}
+ } else {
+ __get_cpu_var(false_positives)++;
}
- eeh_false_positives++;
- return val; /* good case */
+ pci_dev_put(dev);
+ return val;
}
+EXPORT_SYMBOL(eeh_check_failure);
struct eeh_early_enable_info {
unsigned int buid_hi;
unsigned int buid_lo;
- int adapters_enabled;
};
/* Enable eeh for the given device node. */
long ret;
char *status = get_property(dn, "status", 0);
u32 *class_code = (u32 *)get_property(dn, "class-code", 0);
- u32 *vendor_id =(u32 *) get_property(dn, "vendor-id", 0);
+ u32 *vendor_id = (u32 *)get_property(dn, "vendor-id", 0);
u32 *device_id = (u32 *)get_property(dn, "device-id", 0);
u32 *regs;
int enable;
*device_id == 0x0188 || *device_id == 0x0302))
return NULL;
- /* Now decide if we are going to "Disable" EEH checking
+ /*
+ * Now decide if we are going to "Disable" EEH checking
* for this device. We still run with the EEH hardware active,
* but we won't be checking for ff's. This means a driver
* could return bad data (very bad!), an interrupt handler could
if ((*class_code >> 16) == PCI_BASE_CLASS_DISPLAY)
enable = 0;
- if (!eeh_check_opts_config(dn, *class_code, *vendor_id, *device_id, enable)) {
+ if (!eeh_check_opts_config(dn, *class_code, *vendor_id, *device_id,
+ enable)) {
if (enable) {
- printk(KERN_INFO "EEH: %s user requested to run without EEH.\n", dn->full_name);
+ printk(KERN_WARNING "EEH: %s user requested to run "
+ "without EEH.\n", dn->full_name);
enable = 0;
}
}
- if (!enable)
+ if (!enable) {
dn->eeh_mode = EEH_MODE_NOCHECK;
+ return NULL;
+ }
/* This device may already have an EEH parent. */
if (dn->parent && (dn->parent->eeh_mode & EEH_MODE_SUPPORTED)) {
return NULL;
}
- /* Ok..see if this device supports EEH. */
+ /* Ok... see if this device supports EEH. */
regs = (u32 *)get_property(dn, "reg", 0);
if (regs) {
/* First register entry is addr (00BBSS00) */
regs[0], info->buid_hi, info->buid_lo,
EEH_ENABLE);
if (ret == 0) {
- info->adapters_enabled++;
+ eeh_subsystem_enabled = 1;
dn->eeh_mode |= EEH_MODE_SUPPORTED;
dn->eeh_config_addr = regs[0];
+#ifdef DEBUG
+ printk(KERN_DEBUG "EEH: %s: eeh enabled\n",
+ dn->full_name);
+#endif
+ } else {
+ printk(KERN_WARNING "EEH: %s: rtas_call failed.\n",
+ dn->full_name);
}
+ } else {
+ printk(KERN_WARNING "EEH: %s: unable to get reg property.\n",
+ dn->full_name);
}
+
return NULL;
}
/*
- * Initialize eeh by trying to enable it for all of the adapters in the system.
+ * Initialize EEH by trying to enable it for all of the adapters in the system.
* As a side effect we can determine here if eeh is supported at all.
* Note that we leave EEH on so failed config cycles won't cause a machine
* check. If a user turns off EEH for a particular adapter they are really
* but for now disabling EEH for adapters is mostly to work around drivers that
* directly access mmio space (without using the macros).
*
- * The eeh-force-off/on option does literally what it says, so if Linux must
+ * The eeh-force-off option does literally what it says, so if Linux must
* avoid enabling EEH this must be done.
*/
-void eeh_init(void)
+void __init eeh_init(void)
{
struct device_node *phb;
struct eeh_early_enable_info info;
char *eeh_force_off = strstr(saved_command_line, "eeh-force-off");
- char *eeh_force_on = strstr(saved_command_line, "eeh-force-on");
ibm_set_eeh_option = rtas_token("ibm,set-eeh-option");
ibm_set_slot_reset = rtas_token("ibm,set-slot-reset");
ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");
- /* Allow user to force eeh mode on or off -- even if the hardware
- * doesn't exist. This allows driver writers to at least test use
- * of I/O macros even if we can't actually test for EEH failure.
- */
- if (eeh_force_on > eeh_force_off)
- eeh_implemented = 1;
- else if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE)
+ if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE)
return;
- if (eeh_force_off > eeh_force_on) {
- /* User is forcing EEH off. Be noisy if it is implemented. */
- if (eeh_implemented)
- printk(KERN_WARNING "EEH: WARNING: PCI Enhanced I/O Error Handling is user disabled\n");
- eeh_implemented = 0;
+ if (eeh_force_off) {
+ printk(KERN_WARNING "EEH: WARNING: PCI Enhanced I/O Error "
+ "Handling is user disabled\n");
return;
}
-
/* Enable EEH for all adapters. Note that eeh requires buid's */
- info.adapters_enabled = 0;
- for (phb = of_find_node_by_name(NULL, "pci"); phb; phb = of_find_node_by_name(phb, "pci")) {
+ for (phb = of_find_node_by_name(NULL, "pci"); phb;
+ phb = of_find_node_by_name(phb, "pci")) {
int len;
- int *buid_vals = (int *) get_property(phb, "ibm,fw-phb-id", &len);
+ int *buid_vals;
+
+ buid_vals = (int *)get_property(phb, "ibm,fw-phb-id", &len);
if (!buid_vals)
continue;
if (len == sizeof(int)) {
info.buid_hi = buid_vals[0];
info.buid_lo = buid_vals[1];
} else {
- printk("EEH: odd ibm,fw-phb-id len returned: %d\n", len);
+ printk(KERN_INFO "EEH: odd ibm,fw-phb-id len returned: %d\n", len);
continue;
}
traverse_pci_devices(phb, early_enable_eeh, NULL, &info);
}
- if (info.adapters_enabled) {
+
+ if (eeh_subsystem_enabled)
printk(KERN_INFO "EEH: PCI Enhanced I/O Error Handling Enabled\n");
- eeh_implemented = 1;
- }
}
-
-int eeh_set_option(struct pci_dev *dev, int option)
+/**
+ * eeh_add_device - perform EEH initialization for the indicated pci device
+ * @dev: pci device for which to set up EEH
+ *
+ * This routine can be used to perform EEH initialization for PCI
+ * devices that were added after system boot (e.g. hotplug, dlpar).
+ * Whether this actually enables EEH or not for this device depends
+ * on the type of the device, on earlier boot command-line
+ * arguments & etc.
+ */
+void eeh_add_device(struct pci_dev *dev)
{
- struct device_node *dn = pci_device_to_OF_node(dev);
- struct pci_controller *phb = PCI_GET_PHB_PTR(dev);
+ struct device_node *dn;
+ struct pci_controller *phb;
+ struct eeh_early_enable_info info;
+
+ if (!dev || !eeh_subsystem_enabled)
+ return;
- if (dn == NULL || phb == NULL || phb->buid == 0 || !eeh_implemented)
- return -2;
+#ifdef DEBUG
+ printk(KERN_DEBUG "EEH: adding device %s %s\n", pci_name(dev),
+ pci_pretty_name(dev));
+#endif
+ dn = pci_device_to_OF_node(dev);
+ if (NULL == dn)
+ return;
+
+ phb = PCI_GET_PHB_PTR(dev);
+ if (NULL == phb || 0 == phb->buid) {
+ printk(KERN_WARNING "EEH: Expected buid but found none\n");
+ return;
+ }
+
+ info.buid_hi = BUID_HI(phb->buid);
+ info.buid_lo = BUID_LO(phb->buid);
- return rtas_call(ibm_set_eeh_option, 4, 1, NULL,
- CONFIG_ADDR(dn->busno, dn->devfn),
- BUID_HI(phb->buid), BUID_LO(phb->buid), option);
+ early_enable_eeh(dn, &info);
+ pci_addr_cache_insert_device (dev);
}
+/**
+ * eeh_remove_device - undo EEH setup for the indicated pci device
+ * @dev: pci device to be removed
+ *
+ * This routine should be when a device is removed from a running
+ * system (e.g. by hotplug or dlpar).
+ */
+void eeh_remove_device(struct pci_dev *dev)
+{
+ if (!dev || !eeh_subsystem_enabled)
+ return;
-/* If EEH is implemented, find the PCI device using given phys addr
+ /* Unregister the device with the EEH/PCI address search system */
+#ifdef DEBUG
+ printk(KERN_DEBUG "EEH: remove device %s %s\n", pci_name(dev),
+ pci_pretty_name(dev));
+#endif
+ pci_addr_cache_remove_device(dev);
+}
+
+/*
+ * If EEH is implemented, find the PCI device using given phys addr
* and check to see if eeh failure checking is disabled.
- * Remap the addr (trivially) to the EEH region if not.
+ * Remap the addr (trivially) to the EEH region if EEH checking enabled.
* For addresses not known to PCI the vaddr is simply returned unchanged.
*/
void *eeh_ioremap(unsigned long addr, void *vaddr)
struct pci_dev *dev;
struct device_node *dn;
- if (!eeh_implemented)
+ if (!eeh_subsystem_enabled)
return vaddr;
- dev = pci_find_dev_by_addr(addr);
+
+ dev = pci_get_device_by_addr(addr);
if (!dev)
return vaddr;
+
dn = pci_device_to_OF_node(dev);
- if (!dn)
+ if (!dn) {
+ pci_dev_put(dev);
return vaddr;
- if (dn->eeh_mode & EEH_MODE_NOCHECK)
+ }
+
+ if (dn->eeh_mode & EEH_MODE_NOCHECK) {
+ pci_dev_put(dev);
return vaddr;
+ }
+ pci_dev_put(dev);
return (void *)IO_ADDR_TO_TOKEN(vaddr);
}
-static int eeh_proc_falsepositive_read(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+static int proc_eeh_show(struct seq_file *m, void *v)
{
- int len;
- len = sprintf(page, "eeh_false_positives=%ld\n"
- "eeh_total_mmio_ffs=%ld\n",
- eeh_false_positives, eeh_total_mmio_ffs);
- return len;
+ unsigned int cpu;
+ unsigned long ffs = 0, positives = 0, failures = 0;
+
+ for_each_cpu(cpu) {
+ ffs += per_cpu(total_mmio_ffs, cpu);
+ positives += per_cpu(false_positives, cpu);
+ failures += per_cpu(ignored_failures, cpu);
+ }
+
+ if (0 == eeh_subsystem_enabled) {
+ seq_printf(m, "EEH Subsystem is globally disabled\n");
+ seq_printf(m, "eeh_total_mmio_ffs=%ld\n", ffs);
+ } else {
+ seq_printf(m, "EEH Subsystem is enabled\n");
+ seq_printf(m, "eeh_total_mmio_ffs=%ld\n"
+ "eeh_false_positives=%ld\n"
+ "eeh_ignored_failures=%ld\n",
+ ffs, positives, failures);
+ }
+
+ return 0;
}
-/* Implementation of /proc/ppc64/eeh
- * For now it is one file showing false positives.
- */
+static int proc_eeh_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, proc_eeh_show, NULL);
+}
+
+static struct file_operations proc_eeh_operations = {
+ .open = proc_eeh_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static int __init eeh_init_proc(void)
{
- struct proc_dir_entry *ent = create_proc_entry("ppc64/eeh", S_IRUGO, 0);
- if (ent) {
- ent->nlink = 1;
- ent->data = NULL;
- ent->read_proc = (void *)eeh_proc_falsepositive_read;
+ struct proc_dir_entry *e;
+
+ if (systemcfg->platform & PLATFORM_PSERIES) {
+ e = create_proc_entry("ppc64/eeh", 0, NULL);
+ if (e)
+ e->proc_fops = &proc_eeh_operations;
}
- return 0;
+
+ return 0;
}
+__initcall(eeh_init_proc);
/*
* Test if "dev" should be configured on or off.
strs[nstrs++] = classname;
strs[nstrs++] = ""; /* yes, this matches the empty string */
- /* Now see if any string matches the eeh_opts list.
+ /*
+ * Now see if any string matches the eeh_opts list.
* The eeh_opts list entries start with + or -.
*/
- for (s = eeh_opts; s && (s < (eeh_opts + eeh_opts_last)); s += strlen(s)+1) {
+ for (s = eeh_opts; s && (s < (eeh_opts + eeh_opts_last));
+ s += strlen(s)+1) {
for (i = 0; i < nstrs; i++) {
if (strcasecmp(strs[i], s+1) == 0) {
ret = (strs[i][0] == '+') ? 1 : 0;
return ret;
}
-/* Handle kernel eeh-on & eeh-off cmd line options for eeh.
+/*
+ * Handle kernel eeh-on & eeh-off cmd line options for eeh.
*
* We support:
* eeh-off=loc1,loc2,loc3...
* so eeh-off means eeh by default is off.
*/
-/* This is implemented as a null separated list of strings.
+/*
+ * This is implemented as a null separated list of strings.
* Each string looks like this: "+X" or "-X"
* where X is a loc code, vendor:device, class (as shown above)
* or empty which is used to indicate all.
* We interpret this option string list so that it will literally
* behave left-to-right even if some combinations don't make sense.
*/
-
static int __init eeh_parm(char *str, int state)
{
char *s, *cur, *curend;
+
if (!eeh_opts) {
eeh_opts = alloc_bootmem(EEH_MAX_OPTS);
eeh_opts[eeh_opts_last++] = '+'; /* default */
str++;
for (s = str; s && *s != '\0'; s = curend) {
cur = s;
+ /* ignore empties. Don't treat as "all-on" or "all-off" */
while (*cur == ',')
- cur++; /* ignore empties. Don't treat as "all-on" or "all-off" */
+ cur++;
curend = strchr(cur, ',');
if (!curend)
curend = cur + strlen(cur);
if (*cur) {
int curlen = curend-cur;
if (eeh_opts_last + curlen > EEH_MAX_OPTS-2) {
- printk(KERN_INFO "EEH: sorry...too many eeh cmd line options\n");
+ printk(KERN_WARNING "EEH: sorry...too many "
+ "eeh cmd line options\n");
return 1;
}
eeh_opts[eeh_opts_last++] = state ? '+' : '-';
eeh_opts[eeh_opts_last++] = '\0';
}
}
+
return 1;
}
return eeh_parm(str, 1);
}
-__initcall(eeh_init_proc);
__setup("eeh-off", eehoff_parm);
__setup("eeh-on", eehon_parm);
}
}
-/* Given an mmio phys address, find a pci device that implements
- * this address. This is of course expensive, but only used
- * for device initialization or error paths.
- * For io BARs it is assumed the pci_io_base has already been added
- * into addr.
- *
- * Bridges are ignored although they could be used to optimize the search.
- */
-struct pci_dev *pci_find_dev_by_addr(unsigned long addr)
-{
- struct pci_dev *dev = NULL;
- int i;
- unsigned long ioaddr;
-
- ioaddr = (addr > isa_io_base) ? addr - isa_io_base : 0;
-
- while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
- continue;
-
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- unsigned long start = pci_resource_start(dev,i);
- unsigned long end = pci_resource_end(dev,i);
- unsigned int flags = pci_resource_flags(dev,i);
- if (start == 0 || ~start == 0 ||
- end == 0 || ~end == 0)
- continue;
- if ((flags & IORESOURCE_IO) &&
- (ioaddr >= start && ioaddr <= end))
- return dev;
- else if ((flags & IORESOURCE_MEM) &&
- (addr >= start && addr <= end))
- return dev;
- }
- }
- return NULL;
-}
-
void
pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
struct resource *res)
printk("PCI: Probing PCI hardware done\n");
//ppc64_boot_msg(0x41, "PCI Done");
+#ifdef CONFIG_PPC_PSERIES
+ pci_addr_cache_build();
+#endif
+
return 0;
}
void *traverse_pci_devices(struct device_node *start, traverse_func pre, traverse_func post, void *data);
void *traverse_all_pci_devices(traverse_func pre);
-struct pci_dev *pci_find_dev_by_addr(unsigned long addr);
void pci_devs_phb_init(void);
void pci_fix_bus_sysdata(void);
struct device_node *fetch_dev_dn(struct pci_dev *dev);
#define PCI_GET_PHB_PTR(dev) (((struct device_node *)(dev)->sysdata)->phb)
+/* PCI address cache management routines */
+void pci_addr_cache_insert_device(struct pci_dev *dev);
+void pci_addr_cache_remove_device(struct pci_dev *dev);
+
#endif /* __PPC_KERNEL_PCI_H__ */
EXPORT_SYMBOL(iSeries_Write_Word);
EXPORT_SYMBOL(iSeries_Write_Long);
#endif /* CONFIG_PPC_ISERIES */
-#ifndef CONFIG_PPC_ISERIES
-EXPORT_SYMBOL(eeh_check_failure);
-EXPORT_SYMBOL(eeh_total_mmio_ffs);
-#endif /* CONFIG_PPC_ISERIES */
#endif /* CONFIG_PCI */
EXPORT_SYMBOL(start_thread);
cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES];
int nr_cpus_in_node[MAX_NUMNODES] = { [0 ... (MAX_NUMNODES -1)] = 0};
-EXPORT_SYMBOL(numa_cpu_lookup_table);
-EXPORT_SYMBOL(numa_memory_lookup_table);
-EXPORT_SYMBOL(numa_cpumask_lookup_table);
-EXPORT_SYMBOL(nr_cpus_in_node);
-
struct pglist_data node_data[MAX_NUMNODES];
bootmem_data_t plat_node_bdata[MAX_NUMNODES];
static unsigned long node0_io_hole_size;
EXPORT_SYMBOL(node_data);
+EXPORT_SYMBOL(numa_cpu_lookup_table);
+EXPORT_SYMBOL(numa_memory_lookup_table);
+EXPORT_SYMBOL(numa_cpumask_lookup_table);
+EXPORT_SYMBOL(nr_cpus_in_node);
static inline void map_cpu_to_node(int cpu, int node)
{
#
# Makefile for ADX boards
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := setup.o irq.o irq_maskreq.o
#
# Makefile for the BigSur specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := setup.o io.o irq.o led.o
#
# Makefile for the CAT-68701 specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := setup.o irq.o
#
# Makefile for the CqREEK specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := setup.o irq.o
# Makefile for the DataMyte Industrial Digital Assistant(tm) specific parts
# of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := mach.o
#
# Makefile for the Sega Dreamcast specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := setup.o irq.o rtc.o
#
# Makefile for the EC3104 specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := setup.o io.o irq.o
#
# Makefile for STMicroelectronics board specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := irq.o setup.o mach.o led.o
#
# Makefile for the HP620 specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := mach.o
#
# Makefile for the HP680 specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := mach.o setup.o
#
# Makefile for the HP690 specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := mach.o
#
# Makefile for the Interface (CTP/PCI/MPC-SH02) specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := setup.o rtc.o led.o
#
# Makefile for the STMicroelectronics Overdrive specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := mach.o setup.o io.o irq.o led.o time.o
#
# Makefile for the Sega Saturn specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := setup.o io.o irq.o
#
# Makefile for the 770x SolutionEngine specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := mach.o setup.o io.o irq.o led.o
#
# Makefile for the 7751 SolutionEngine specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := mach.o setup.o io.o irq.o led.o
#
# Makefile for the SH2000 specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := setup.o
#
# Makefile for the SnapGear specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := setup.o io.o rtc.o
#
# Makefile for the SystemH specific parts of the kernel
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := setup.o irq.o io.o
#
# Makefile for unknown SH boards
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := mach.o io.o setup.o
#
# Makefile for the HD64461
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := setup.o io.o
#
# Makefile for the HD64465
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
obj-y := setup.o io.o gpio.o
another UltraSPARC-IIi-cEngine boardset with a 7-segment display,
you should say N to this option.
-config WATCHDOG_CP1XXX
- tristate "CP1XXX Hardware Watchdog support"
- depends on PCI
- ---help---
- This is the driver for the hardware watchdog timers present on
- Sun Microsystems CompactPCI models CP1400 and CP1500.
-
- To compile this driver as a module, choose M here: the
- module will be called cpwatchdog.
-
- If you do not have a CompactPCI model CP1400 or CP1500, or
- another UltraSPARC-IIi-cEngine boardset with hardware watchdog,
- you should say N to this option.
-
-config WATCHDOG_RIO
- tristate "RIO Hardware Watchdog support"
- depends on PCI
- help
- Say Y here to support the hardware watchdog capability on Sun RIO
- machines. The watchdog timeout period is normally one minute but
- can be changed with a boot-time parameter.
-
config CMDLINE_BOOL
bool "Default bootloader kernel arguments"
LDFLAGS_vmlinux := -e stext
cflags-$(CONFIG_MK8) += $(call check_gcc,-march=k8,)
-cflags-$(CONFIG_MPSC) += $(call check_gcc,-march=pentium4,)
+cflags-$(CONFIG_MPSC) += $(call check_gcc,-march=prescott,)
CFLAGS += $(cflags-y)
CFLAGS += -mno-red-zone
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
CONFIG_LOG_BUF_SHIFT=18
+# CONFIG_HOTPLUG is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_EMBEDDED is not set
CONFIG_ACPI_PCI=y
CONFIG_ACPI_SYSTEM=y
# CONFIG_ACPI_RELAXED_AML is not set
+# CONFIG_X86_PM_TIMER is not set
#
# CPU Frequency scaling
CONFIG_PCI_DIRECT=y
# CONFIG_PCI_LEGACY_PROC is not set
# CONFIG_PCI_NAMES is not set
-# CONFIG_HOTPLUG is not set
#
# Executable file formats / Emulations
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
CONFIG_LBD=y
+# CONFIG_DCSSBLK is not set
#
# ATA/ATAPI/MFM/RLL support
# CONFIG_FUSION_CTL is not set
#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# IEEE 1394 (FireWire) support
#
# CONFIG_IEEE1394 is not set
#
# ISDN subsystem
#
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
#
# Telephony Support
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
#
# Mice
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
static struct sys_device device_timer = {
.id = 0,
- .cls &timer_sysclass,
+ .cls = &timer_sysclass,
};
static int __init init_timer_sysfs(void)
printk("CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n",
m->cpu, m->mcgstatus, m->bank, m->status);
if (m->rip) {
- printk("RIP %02x:<%016Lx> ", m->cs, m->rip);
+ printk("RIP%s %02x:<%016Lx> ",
+ !(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "",
+ m->cs, m->rip);
if (m->cs == __KERNEL_CS)
print_symbol("{%s}", m->rip);
printk("\n");
return;
if (!(m.mcgstatus & MCG_STATUS_RIPV))
kill_it = 1;
- if (regs && (m.mcgstatus & MCG_STATUS_EIPV)) {
+ if (regs) {
m.rip = regs->rip;
m.cs = regs->cs;
}
* At this point we only support two siblings per
* processor package.
*/
-#define NR_SIBLINGS 2
- if (smp_num_siblings != NR_SIBLINGS) {
+ if (smp_num_siblings > NR_CPUS) {
printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
smp_num_siblings = 1;
return;
#include <linux/device.h>
#include <linux/sysdev.h>
#include <linux/bcd.h>
+#include <linux/kallsyms.h>
#include <asm/pgtable.h>
#include <asm/vsyscall.h>
#include <asm/timex.h>
}
if (lost) {
- if (report_lost_ticks)
+ if (report_lost_ticks) {
printk(KERN_WARNING "time.c: Lost %ld timer "
- "tick(s)! (rip %016lx)\n",
- (offset - vxtime.last) / hpet_tick - 1,
- regs->rip);
+ "tick(s)! ", lost);
+ print_symbol("rip %s)\n", regs->rip);
+ }
jiffies += lost;
}
return IRQ_HANDLED;
}
-/* RED-PEN: calculation is done in 32bits with multiply for performance
- and could overflow, it may be better (but slower)to use an 64bit division. */
+static unsigned int cyc2ns_scale;
+#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
+
+static inline void set_cyc2ns_scale(unsigned long cpu_mhz)
+{
+ cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz;
+}
+
+static inline unsigned long long cycles_2_ns(unsigned long long cyc)
+{
+ return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
+}
+
unsigned long long sched_clock(void)
{
unsigned long a = 0;
purposes. */
rdtscll(a);
- return (a * vxtime.tsc_quot) >> 32;
+ return cycles_2_ns(a);
}
unsigned long get_cmos_time(void)
vxtime.tsc_quot = (1000L << 32) / cpu_khz;
}
+ set_cyc2ns_scale(cpu_khz_ref / 1000);
+
return 0;
}
rdtscll_sync(&vxtime.last_tsc);
setup_irq(0, &irq0);
+ set_cyc2ns_scale(cpu_khz / 1000);
+
#ifdef CONFIG_CPU_FREQ
cpufreq_register_notifier(&time_cpufreq_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER);
void __die(const char * str, struct pt_regs * regs, long err)
{
+ int nl = 0;
static int die_counter;
printk(KERN_EMERG "%s: %04lx [%u]\n", str, err & 0xffff,++die_counter);
notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
+#ifdef CONFIG_PREEMPT
+ printk("PREEMPT ");
+ nl = 1;
+#endif
+#ifdef CONFIG_SMP
+ printk("SMP ");
+ nl = 1;
+#endif
+#ifdef CONFIG_DEBUG_PAGEALLOC
+ printk("DEBUG_PAGEALLOC");
+ nl = 1;
+#endif
+ if (nl)
+ printk("\n");
show_registers(regs);
/* Executive summary in case the oops scrolled away */
printk("RIP ");
proc-crypto-$(CONFIG_PROC_FS) = proc.o
-obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o \
+obj-$(CONFIG_CRYPTO) += api.o scatterwalk.o cipher.o digest.o compress.o \
$(proc-crypto-y)
obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
* Cipher operations.
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- * Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <linux/highmem.h>
#include <asm/scatterlist.h>
#include "internal.h"
+#include "scatterwalk.h"
typedef void (cryptfn_t)(void *, u8 *, const u8 *);
typedef void (procfn_t)(struct crypto_tfm *, u8 *,
- u8*, cryptfn_t, int enc, void *);
-
-struct scatter_walk {
- struct scatterlist *sg;
- struct page *page;
- void *data;
- unsigned int len_this_page;
- unsigned int len_this_segment;
- unsigned int offset;
-};
-
-enum km_type crypto_km_types[] = {
- KM_USER0,
- KM_USER1,
- KM_SOFTIRQ0,
- KM_SOFTIRQ1,
-};
+ u8*, cryptfn_t, int enc, void *, int);
static inline void xor_64(u8 *a, const u8 *b)
{
}
-/* Define sg_next is an inline routine now in case we want to change
- scatterlist to a linked list later. */
-static inline struct scatterlist *sg_next(struct scatterlist *sg)
-{
- return sg + 1;
-}
-
-void *which_buf(struct scatter_walk *walk, unsigned int nbytes, void *scratch)
-{
- if (nbytes <= walk->len_this_page &&
- (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <=
- PAGE_CACHE_SIZE)
- return walk->data;
- else
- return scratch;
-}
-
-static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
-{
- if (out)
- memcpy(sgdata, buf, nbytes);
- else
- memcpy(buf, sgdata, nbytes);
-}
-
-static void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
-{
- unsigned int rest_of_page;
-
- walk->sg = sg;
-
- walk->page = sg->page;
- walk->len_this_segment = sg->length;
-
- rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1));
- walk->len_this_page = min(sg->length, rest_of_page);
- walk->offset = sg->offset;
-}
-
-static void scatterwalk_map(struct scatter_walk *walk, int out)
-{
- walk->data = crypto_kmap(walk->page, out) + walk->offset;
-}
-
-static void scatter_page_done(struct scatter_walk *walk, int out,
- unsigned int more)
-{
- /* walk->data may be pointing the first byte of the next page;
- however, we know we transfered at least one byte. So,
- walk->data - 1 will be a virutual address in the mapped page. */
-
- if (out)
- flush_dcache_page(walk->page);
-
- if (more) {
- walk->len_this_segment -= walk->len_this_page;
-
- if (walk->len_this_segment) {
- walk->page++;
- walk->len_this_page = min(walk->len_this_segment,
- (unsigned)PAGE_CACHE_SIZE);
- walk->offset = 0;
- }
- else
- scatterwalk_start(walk, sg_next(walk->sg));
- }
-}
-
-static void scatter_done(struct scatter_walk *walk, int out, int more)
-{
- crypto_kunmap(walk->data, out);
- if (walk->len_this_page == 0 || !more)
- scatter_page_done(walk, out, more);
-}
-
-/*
- * Do not call this unless the total length of all of the fragments
- * has been verified as multiple of the block size.
- */
-static int copy_chunks(void *buf, struct scatter_walk *walk,
- size_t nbytes, int out)
-{
- if (buf != walk->data) {
- while (nbytes > walk->len_this_page) {
- memcpy_dir(buf, walk->data, walk->len_this_page, out);
- buf += walk->len_this_page;
- nbytes -= walk->len_this_page;
-
- crypto_kunmap(walk->data, out);
- scatter_page_done(walk, out, 1);
- scatterwalk_map(walk, out);
- }
-
- memcpy_dir(buf, walk->data, nbytes, out);
- }
-
- walk->offset += nbytes;
- walk->len_this_page -= nbytes;
- walk->len_this_segment -= nbytes;
- return 0;
-}
-
/*
* Generic encrypt/decrypt wrapper for ciphers, handles operations across
* multiple page boundaries by using temporary blocks. In user context,
scatterwalk_map(&walk_in, 0);
scatterwalk_map(&walk_out, 1);
- src_p = which_buf(&walk_in, bsize, tmp_src);
- dst_p = which_buf(&walk_out, bsize, tmp_dst);
+ src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src);
+ dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst);
nbytes -= bsize;
- copy_chunks(src_p, &walk_in, bsize, 0);
+ scatterwalk_copychunks(src_p, &walk_in, bsize, 0);
- prfn(tfm, dst_p, src_p, crfn, enc, info);
+ prfn(tfm, dst_p, src_p, crfn, enc, info,
+ scatterwalk_samebuf(&walk_in, &walk_out,
+ src_p, dst_p));
- scatter_done(&walk_in, 0, nbytes);
+ scatterwalk_done(&walk_in, 0, nbytes);
- copy_chunks(dst_p, &walk_out, bsize, 1);
- scatter_done(&walk_out, 1, nbytes);
+ scatterwalk_copychunks(dst_p, &walk_out, bsize, 1);
+ scatterwalk_done(&walk_out, 1, nbytes);
if (!nbytes)
return 0;
}
}
-static void cbc_process(struct crypto_tfm *tfm,
- u8 *dst, u8 *src, cryptfn_t fn, int enc, void *info)
+static void cbc_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
+ cryptfn_t fn, int enc, void *info, int in_place)
{
u8 *iv = info;
fn(crypto_tfm_ctx(tfm), dst, iv);
memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm));
} else {
- const int need_stack = (src == dst);
- u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0];
- u8 *buf = need_stack ? stack : dst;
-
+ u8 stack[in_place ? crypto_tfm_alg_blocksize(tfm) : 0];
+ u8 *buf = in_place ? stack : dst;
+
fn(crypto_tfm_ctx(tfm), buf, src);
tfm->crt_u.cipher.cit_xor_block(buf, iv);
memcpy(iv, src, crypto_tfm_alg_blocksize(tfm));
}
static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
- cryptfn_t fn, int enc, void *info)
+ cryptfn_t fn, int enc, void *info, int in_place)
{
fn(crypto_tfm_ctx(tfm), dst, src);
}
*/
#ifndef _CRYPTO_INTERNAL_H
#define _CRYPTO_INTERNAL_H
+#include <linux/crypto.h>
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/interrupt.h>
--- /dev/null
+/*
+ * Cryptographic API.
+ *
+ * Cipher operations.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * 2002 Adam J. Richter <adam@yggdrasil.com>
+ * 2004 Jean-Luc Cooke <jlcooke@certainkey.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <asm/scatterlist.h>
+#include "internal.h"
+#include "scatterwalk.h"
+
+enum km_type crypto_km_types[] = {
+ KM_USER0,
+ KM_USER1,
+ KM_SOFTIRQ0,
+ KM_SOFTIRQ1,
+};
+
+void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch)
+{
+ if (nbytes <= walk->len_this_page &&
+ (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <=
+ PAGE_CACHE_SIZE)
+ return walk->data;
+ else
+ return scratch;
+}
+
+static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
+{
+ if (out)
+ memcpy(sgdata, buf, nbytes);
+ else
+ memcpy(buf, sgdata, nbytes);
+}
+
+void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
+{
+ unsigned int rest_of_page;
+
+ walk->sg = sg;
+
+ walk->page = sg->page;
+ walk->len_this_segment = sg->length;
+
+ rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1));
+ walk->len_this_page = min(sg->length, rest_of_page);
+ walk->offset = sg->offset;
+}
+
+void scatterwalk_map(struct scatter_walk *walk, int out)
+{
+ walk->data = crypto_kmap(walk->page, out) + walk->offset;
+}
+
+static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
+ unsigned int more)
+{
+ /* walk->data may be pointing the first byte of the next page;
+ however, we know we transfered at least one byte. So,
+ walk->data - 1 will be a virutual address in the mapped page. */
+
+ if (out)
+ flush_dcache_page(walk->page);
+
+ if (more) {
+ walk->len_this_segment -= walk->len_this_page;
+
+ if (walk->len_this_segment) {
+ walk->page++;
+ walk->len_this_page = min(walk->len_this_segment,
+ (unsigned)PAGE_CACHE_SIZE);
+ walk->offset = 0;
+ }
+ else
+ scatterwalk_start(walk, sg_next(walk->sg));
+ }
+}
+
+void scatterwalk_done(struct scatter_walk *walk, int out, int more)
+{
+ crypto_kunmap(walk->data, out);
+ if (walk->len_this_page == 0 || !more)
+ scatterwalk_pagedone(walk, out, more);
+}
+
+/*
+ * Do not call this unless the total length of all of the fragments
+ * has been verified as multiple of the block size.
+ */
+int scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
+ size_t nbytes, int out)
+{
+ if (buf != walk->data) {
+ while (nbytes > walk->len_this_page) {
+ memcpy_dir(buf, walk->data, walk->len_this_page, out);
+ buf += walk->len_this_page;
+ nbytes -= walk->len_this_page;
+
+ crypto_kunmap(walk->data, out);
+ scatterwalk_pagedone(walk, out, 1);
+ scatterwalk_map(walk, out);
+ }
+
+ memcpy_dir(buf, walk->data, nbytes, out);
+ }
+
+ walk->offset += nbytes;
+ walk->len_this_page -= nbytes;
+ walk->len_this_segment -= nbytes;
+ return 0;
+}
--- /dev/null
+/*
+ * Cryptographic API.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2002 Adam J. Richter <adam@yggdrasil.com>
+ * Copyright (c) 2004 Jean-Luc Cooke <jlcooke@certainkey.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#ifndef _CRYPTO_SCATTERWALK_H
+#define _CRYPTO_SCATTERWALK_H
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+
+struct scatter_walk {
+ struct scatterlist *sg;
+ struct page *page;
+ void *data;
+ unsigned int len_this_page;
+ unsigned int len_this_segment;
+ unsigned int offset;
+};
+
+/* Define sg_next is an inline routine now in case we want to change
+ scatterlist to a linked list later. */
+static inline struct scatterlist *sg_next(struct scatterlist *sg)
+{
+ return sg + 1;
+}
+
+static inline int scatterwalk_samebuf(struct scatter_walk *walk_in,
+ struct scatter_walk *walk_out,
+ void *src_p, void *dst_p)
+{
+ return walk_in->page == walk_out->page &&
+ walk_in->data == src_p && walk_out->data == dst_p;
+}
+
+void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch);
+void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg);
+int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, size_t nbytes, int out);
+void scatterwalk_map(struct scatter_walk *walk, int out);
+void scatterwalk_done(struct scatter_walk *walk, int out, int more);
+
+#endif /* _CRYPTO_SCATTERWALK_H */
FW_STATUS_LOADING,
FW_STATUS_DONE,
FW_STATUS_ABORT,
+ FW_STATUS_READY,
};
static int loading_timeout = 10; /* In seconds */
int i = 0;
char *scratch = buffer;
+ if (!test_bit(FW_STATUS_READY, &fw_priv->status))
+ return -ENODEV;
+
if (buffer_size < (FIRMWARE_NAME_MAX + 10))
return -ENOMEM;
if (num_envp < 1)
kfree(fw_priv);
kfree(class_dev);
+
+ module_put(THIS_MODULE);
}
static void
kfree(class_dev);
return retval;
}
+
static int
fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
const char *fw_name, struct device *device)
if (retval)
goto out;
+ /* Need to pin this module until class device is destroyed */
+ __module_get(THIS_MODULE);
+
fw_priv = class_get_devdata(class_dev);
fw_priv->fw = fw;
goto error_unreg;
}
+ set_bit(FW_STATUS_READY, &fw_priv->status);
*class_dev_p = class_dev;
goto out;
add_timer(&fw_priv->timeout);
}
+ kobject_hotplug("add", &class_dev->kobj);
wait_for_completion(&fw_priv->completion);
set_bit(FW_STATUS_DONE, &fw_priv->status);
static void bluecard_write_wakeup(bluecard_info_t *info)
{
if (!info) {
- printk(KERN_WARNING "bluecard_cs: Call of write_wakeup for unknown device.\n");
+ BT_ERR("Unknown device");
return;
}
int i, len;
if (!info) {
- printk(KERN_WARNING "bluecard_cs: Call of receive for unknown device.\n");
+ BT_ERR("Unknown device");
return;
}
info->rx_state = RECV_WAIT_PACKET_TYPE;
info->rx_count = 0;
if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
- printk(KERN_WARNING "bluecard_cs: Can't allocate mem for new packet.\n");
+ BT_ERR("Can't allocate mem for new packet");
return;
}
}
default:
/* unknown packet */
- printk(KERN_WARNING "bluecard_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type);
+ BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type);
info->hdev->stat.err_rx++;
kfree_skb(info->rx_skb);
unsigned char reg;
if (!info) {
- printk(KERN_WARNING "bluecard_cs: Call of irq %d for unknown device.\n", irq);
+ BT_ERR("Call of irq %d for unknown device", irq);
return IRQ_NONE;
}
unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 };
if (!(skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
- printk(KERN_WARNING "bluecard_cs: Can't allocate mem for new packet.\n");
+ BT_ERR("Can't allocate mem for new packet");
return -1;
}
struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
if (!hdev) {
- printk(KERN_WARNING "bluecard_cs: Frame for unknown HCI device (hdev=NULL).");
+ BT_ERR("Frame for unknown HCI device (hdev=NULL)");
return -ENODEV;
}
/* Initialize and register HCI device */
hdev = hci_alloc_dev();
if (!hdev) {
- printk(KERN_WARNING "bluecard_cs: Can't allocate HCI device.\n");
+ BT_ERR("Can't allocate HCI device");
return -ENOMEM;
}
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) {
- printk(KERN_WARNING "bluecard_cs: Can't register HCI device.\n");
+ BT_ERR("Can't register HCI device");
hci_free_dev(hdev);
return -ENODEV;
}
outb(0x80, iobase + 0x30);
if (hci_unregister_dev(hdev) < 0)
- printk(KERN_WARNING "bluecard_cs: Can't unregister HCI device %s.\n", hdev->name);
+ BT_ERR("Can't unregister HCI device %s", hdev->name);
hci_free_dev(hdev);
unsigned long flags;
if (!info) {
- printk(KERN_WARNING "bt3c_cs: Call of write_wakeup for unknown device.\n");
+ BT_ERR("Unknown device");
return;
}
len = bt3c_write(iobase, 256, skb->data, skb->len);
if (len != skb->len) {
- printk(KERN_WARNING "bt3c_cs: very strange\n");
+ BT_ERR("Very strange");
}
kfree_skb(skb);
int size = 0, avail;
if (!info) {
- printk(KERN_WARNING "bt3c_cs: Call of receive for unknown device.\n");
+ BT_ERR("Unknown device");
return;
}
info->rx_state = RECV_WAIT_PACKET_TYPE;
info->rx_count = 0;
if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
- printk(KERN_WARNING "bt3c_cs: Can't allocate mem for new packet.\n");
+ BT_ERR("Can't allocate mem for new packet");
return;
}
}
default:
/* Unknown packet */
- printk(KERN_WARNING "bt3c_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type);
+ BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type);
info->hdev->stat.err_rx++;
clear_bit(HCI_RUNNING, &(info->hdev->flags));
int iir;
if (!info) {
- printk(KERN_WARNING "bt3c_cs: Call of irq %d for unknown device.\n", irq);
+ BT_ERR("Call of irq %d for unknown device", irq);
return IRQ_NONE;
}
int stat = bt3c_read(iobase, 0x7001);
if ((stat & 0xff) == 0x7f) {
- printk(KERN_WARNING "bt3c_cs: STRANGE stat=%04x\n", stat);
+ BT_ERR("Very strange (stat=0x%04x)", stat);
} else if ((stat & 0xff) != 0xff) {
if (stat & 0x0020) {
int stat = bt3c_read(iobase, 0x7002) & 0x10;
- printk(KERN_WARNING "bt3c_cs: antena %s\n", stat ? "OUT" : "IN");
+ BT_ERR("Antenna %s", stat ? "out" : "in");
}
if (stat & 0x0001)
bt3c_receive(info);
if (stat & 0x0002) {
- //printk("bt3c_cs: ACK %04x\n", stat);
+ //BT_ERR("Ack (stat=0x%04x)", stat);
clear_bit(XMIT_SENDING, &(info->tx_state));
bt3c_write_wakeup(info, 1);
}
struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
if (!hdev) {
- printk(KERN_WARNING "bt3c_cs: Frame for unknown HCI device (hdev=NULL).");
+ BT_ERR("Frame for unknown HCI device (hdev=NULL)");
return -ENODEV;
}
err = call_usermodehelper(FW_LOADER, argv, envp, 1);
if (err)
- printk(KERN_WARNING "bt3c_cs: Failed to run \"%s pccard %s\" (errno=%d).\n", FW_LOADER, dev, err);
+ BT_ERR("Failed to run \"%s pccard %s\" (errno=%d)", FW_LOADER, dev, err);
return err;
}
/* Initialize and register HCI device */
hdev = hci_alloc_dev();
if (!hdev) {
- printk(KERN_WARNING "bt3c_cs: Can't allocate HCI device.\n");
+ BT_ERR("Can't allocate HCI device");
return -ENOMEM;
}
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) {
- printk(KERN_WARNING "bt3c_cs: Can't register HCI device.\n");
+ BT_ERR("Can't register HCI device");
hci_free_dev(hdev);
return -ENODEV;
}
bt3c_hci_close(hdev);
if (hci_unregister_dev(hdev) < 0)
- printk(KERN_WARNING "bt3c_cs: Can't unregister HCI device %s.\n", hdev->name);
+ BT_ERR("Can't unregister HCI device %s", hdev->name);
hci_free_dev(hdev);
found_port:
if (i != CS_SUCCESS) {
- printk(KERN_NOTICE "bt3c_cs: No usable port range found. Giving up.\n");
+ BT_ERR("No usable port range found");
cs_error(link->handle, RequestIO, i);
goto failed;
}
static void btuart_write_wakeup(btuart_info_t *info)
{
if (!info) {
- printk(KERN_WARNING "btuart_cs: Call of write_wakeup for unknown device.\n");
+ BT_ERR("Unknown device");
return;
}
int boguscount = 0;
if (!info) {
- printk(KERN_WARNING "btuart_cs: Call of receive for unknown device.\n");
+ BT_ERR("Unknown device");
return;
}
info->rx_state = RECV_WAIT_PACKET_TYPE;
info->rx_count = 0;
if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
- printk(KERN_WARNING "btuart_cs: Can't allocate mem for new packet.\n");
+ BT_ERR("Can't allocate mem for new packet");
return;
}
}
default:
/* Unknown packet */
- printk(KERN_WARNING "btuart_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type);
+ BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type);
info->hdev->stat.err_rx++;
clear_bit(HCI_RUNNING, &(info->hdev->flags));
int iir, lsr;
if (!info) {
- printk(KERN_WARNING "btuart_cs: Call of irq %d for unknown device.\n", irq);
+ BT_ERR("Call of irq %d for unknown device", irq);
return IRQ_NONE;
}
switch (iir) {
case UART_IIR_RLSI:
- printk(KERN_NOTICE "btuart_cs: RLSI\n");
+ BT_ERR("RLSI");
break;
case UART_IIR_RDI:
/* Receive interrupt */
}
break;
default:
- printk(KERN_NOTICE "btuart_cs: Unhandled IIR=%#x\n", iir);
+ BT_ERR("Unhandled IIR=%#x", iir);
break;
}
int divisor;
if (!info) {
- printk(KERN_WARNING "btuart_cs: Call of change speed for unknown device.\n");
+ BT_ERR("Unknown device");
return;
}
struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
if (!hdev) {
- printk(KERN_WARNING "btuart_cs: Frame for unknown HCI device (hdev=NULL).");
+ BT_ERR("Frame for unknown HCI device (hdev=NULL)");
return -ENODEV;
}
/* Initialize and register HCI device */
hdev = hci_alloc_dev();
if (!hdev) {
- printk(KERN_WARNING "btuart_cs: Can't allocate HCI device.\n");
+ BT_ERR("Can't allocate HCI device");
return -ENOMEM;
}
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) {
- printk(KERN_WARNING "btuart_cs: Can't register HCI device.\n");
+ BT_ERR("Can't register HCI device");
hci_free_dev(hdev);
return -ENODEV;
}
spin_unlock_irqrestore(&(info->lock), flags);
if (hci_unregister_dev(hdev) < 0)
- printk(KERN_WARNING "btuart_cs: Can't unregister HCI device %s.\n", hdev->name);
+ BT_ERR("Can't unregister HCI device %s", hdev->name);
hci_free_dev(hdev);
found_port:
if (i != CS_SUCCESS) {
- printk(KERN_NOTICE "btuart_cs: No usable port range found. Giving up.\n");
+ BT_ERR("No usable port range found");
cs_error(link->handle, RequestIO, i);
goto failed;
}
static void dtl1_write_wakeup(dtl1_info_t *info)
{
if (!info) {
- printk(KERN_WARNING "dtl1_cs: Call of write_wakeup for unknown device.\n");
+ BT_ERR("Unknown device");
return;
}
u8 flowmask = *(u8 *)skb->data;
int i;
- printk(KERN_INFO "dtl1_cs: Nokia control data = ");
+ printk(KERN_INFO "Bluetooth: Nokia control data =");
for (i = 0; i < skb->len; i++) {
- printk("%02x ", skb->data[i]);
+ printk(" %02x", skb->data[i]);
}
printk("\n");
int boguscount = 0;
if (!info) {
- printk(KERN_WARNING "dtl1_cs: Call of receive for unknown device.\n");
+ BT_ERR("Unknown device");
return;
}
/* Allocate packet */
if (info->rx_skb == NULL)
if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
- printk(KERN_WARNING "dtl1_cs: Can't allocate mem for new packet.\n");
+ BT_ERR("Can't allocate mem for new packet");
info->rx_state = RECV_WAIT_NSH;
info->rx_count = NSHL;
return;
break;
default:
/* unknown packet */
- printk(KERN_WARNING "dtl1_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type);
+ BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type);
kfree_skb(info->rx_skb);
break;
}
int iir, lsr;
if (!info) {
- printk(KERN_WARNING "dtl1_cs: Call of irq %d for unknown device.\n", irq);
+ BT_ERR("Call of irq %d for unknown device", irq);
return IRQ_NONE;
}
switch (iir) {
case UART_IIR_RLSI:
- printk(KERN_NOTICE "dtl1_cs: RLSI\n");
+ BT_ERR("RLSI");
break;
case UART_IIR_RDI:
/* Receive interrupt */
}
break;
default:
- printk(KERN_NOTICE "dtl1_cs: Unhandled IIR=%#x\n", iir);
+ BT_ERR("Unhandled IIR=%#x", iir);
break;
}
nsh_t nsh;
if (!hdev) {
- printk(KERN_WARNING "dtl1_cs: Frame for unknown HCI device (hdev=NULL).");
+ BT_ERR("Frame for unknown HCI device (hdev=NULL)");
return -ENODEV;
}
/* Initialize and register HCI device */
hdev = hci_alloc_dev();
if (!hdev) {
- printk(KERN_WARNING "dtl1_cs: Can't allocate HCI device.\n");
+ BT_ERR("Can't allocate HCI device");
return -ENOMEM;
}
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) {
- printk(KERN_WARNING "dtl1_cs: Can't register HCI device.\n");
+ BT_ERR("Can't register HCI device");
hci_free_dev(hdev);
return -ENODEV;
}
spin_unlock_irqrestore(&(info->lock), flags);
if (hci_unregister_dev(hdev) < 0)
- printk(KERN_WARNING "dtl1_cs: Can't unregister HCI device %s.\n", hdev->name);
+ BT_ERR("Can't unregister HCI device %s", hdev->name);
hci_free_dev(hdev);
cy_serial_driver->owner = THIS_MODULE;
cy_serial_driver->driver_name = "cyclades";
cy_serial_driver->name = "ttyC";
+ cy_serial_driver->devfs_name = "tts/C";
cy_serial_driver->major = CYCLADES_MAJOR;
cy_serial_driver->minor_start = 0;
cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
pc_driver->owner = THIS_MODULE;
pc_driver->name = "ttyD";
+ pc_driver->devfs_name = "tts/D";
pc_driver->major = DIGI_MAJOR;
pc_driver->minor_start = 0;
pc_driver->type = TTY_DRIVER_TYPE_SERIAL;
esp_driver->owner = THIS_MODULE;
esp_driver->name = "ttyP";
+ esp_driver->devfs_name = "tts/P";
esp_driver->major = ESP_IN_MAJOR;
esp_driver->minor_start = 0;
esp_driver->type = TTY_DRIVER_TYPE_SERIAL;
isicom_normal->owner = THIS_MODULE;
isicom_normal->name = "ttyM";
+ isicom_normal->devfs_name = "isicom/";
isicom_normal->major = ISICOM_NMAJOR;
isicom_normal->minor_start = 0;
isicom_normal->type = TTY_DRIVER_TYPE_SERIAL;
init_MUTEX(&moxaBuffSem);
moxaDriver->owner = THIS_MODULE;
moxaDriver->name = "ttya";
+ moxaDriver->devfs_name = "tts/a";
moxaDriver->major = ttymajor;
moxaDriver->minor_start = 0;
moxaDriver->type = TTY_DRIVER_TYPE_SERIAL;
pcxe_driver->owner = THIS_MODULE;
pcxe_driver->name = "ttyD";
+ pcxe_driver->devfs_name = "pcxe/";
pcxe_driver->major = DIGI_MAJOR;
pcxe_driver->minor_start = 0;
pcxe_driver->type = TTY_DRIVER_TYPE_SERIAL;
memset(IRQ_to_board, 0, sizeof(IRQ_to_board));
riscom_driver->owner = THIS_MODULE;
riscom_driver->name = "ttyL";
+ riscom_driver->devfs_name = "tts/L";
riscom_driver->major = RISCOM8_NORMAL_MAJOR;
riscom_driver->type = TTY_DRIVER_TYPE_SERIAL;
riscom_driver->subtype = SERIAL_TYPE_NORMAL;
* Called only if powerdown features are allowed.
*/
switch (vesa_blank_mode) {
- case VESA_NO_BLANKING:
- c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1);
+ case VESA_NO_BLANKING:
+ c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1, 0);
break;
- case VESA_VSYNC_SUSPEND:
- case VESA_HSYNC_SUSPEND:
- c->vc_sw->con_blank(c, VESA_POWERDOWN+1);
+ case VESA_VSYNC_SUSPEND:
+ case VESA_HSYNC_SUSPEND:
+ c->vc_sw->con_blank(c, VESA_POWERDOWN+1, 0);
break;
}
}
if (entering_gfx) {
hide_cursor(currcons);
save_screen(currcons);
- sw->con_blank(vc_cons[currcons].d, -1);
+ sw->con_blank(vc_cons[currcons].d, -1, 1);
console_blanked = fg_console + 1;
set_origin(currcons);
return;
save_screen(currcons);
/* In case we need to reset origin, blanking hook returns 1 */
- i = sw->con_blank(vc_cons[currcons].d, 1);
+ i = sw->con_blank(vc_cons[currcons].d, 1, 0);
console_blanked = fg_console + 1;
if (i)
set_origin(currcons);
}
if (vesa_blank_mode)
- sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1);
+ sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1, 0);
}
/*
* Called by timer as well as from vt_console_driver
*/
-void unblank_screen(void)
+void do_unblank_screen(int leaving_gfx)
{
int currcons;
}
console_blanked = 0;
- if (sw->con_blank(vc_cons[currcons].d, 0))
+ if (sw->con_blank(vc_cons[currcons].d, 0, leaving_gfx))
/* Low-level driver cannot restore -> do it ourselves */
update_screen(fg_console);
if (console_blank_hook)
}
/*
+ * This is called by the outside world to cause a forced unblank, mostly for
+ * oopses. Currently, I just call do_unblank_screen(0), but we could eventually
+ * call it with 1 as an argument and so force a mode restore... that may kill
+ * X or at least garbage the screen but would also make the Oops visible...
+ */
+void unblank_screen(void)
+{
+ do_unblank_screen(0);
+}
+
+/*
* We defer the timer blanking to work queue so it can take the console semaphore
* (console operations can still happen at irq time, but only from printk which
* has the console semaphore. Not perfect yet, but better than no locking
*/
acquire_console_sem();
if (arg == KD_TEXT)
- unblank_screen();
+ do_unblank_screen(1);
else
do_blank_screen(1);
release_console_sem();
if (old_vc_mode != vt_cons[new_console]->vc_mode)
{
if (vt_cons[new_console]->vc_mode == KD_TEXT)
- unblank_screen();
+ do_unblank_screen(1);
else
do_blank_screen(1);
}
if (old_vc_mode != vt_cons[new_console]->vc_mode)
{
if (vt_cons[new_console]->vc_mode == KD_TEXT)
- unblank_screen();
+ do_unblank_screen(1);
else
do_blank_screen(1);
}
To compile this driver as a module, choose M here: the
module will be called shwdt.
+# SPARC64 Architecture
+
+config WATCHDOG_CP1XXX
+ tristate "CP1XXX Hardware Watchdog support"
+ depends on WATCHDOG && SPARC64 && PCI
+ ---help---
+ This is the driver for the hardware watchdog timers present on
+ Sun Microsystems CompactPCI models CP1400 and CP1500.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cpwatchdog.
+
+ If you do not have a CompactPCI model CP1400 or CP1500, or
+ another UltraSPARC-IIi-cEngine boardset with hardware watchdog,
+ you should say N to this option.
+
+config WATCHDOG_RIO
+ tristate "RIO Hardware Watchdog support"
+ depends on WATCHDOG && SPARC64 && PCI
+ help
+ Say Y here to support the hardware watchdog capability on Sun RIO
+ machines. The watchdog timeout period is normally one minute but
+ can be changed with a boot-time parameter.
+
#
# ISA-based Watchdog Cards
#
Fahrenheit. This works only if you have a WDT501P watchdog board
installed.
+#
+# USB-based Watchdog Cards
+#
+
+comment "USB-based Watchdog Cards"
+ depends on WATCHDOG && USB
+
+config USBPCWATCHDOG
+ tristate "Berkshire Products USB-PC Watchdog"
+ depends on WATCHDOG && USB
+ ---help---
+ This is the driver for the Berkshire Products USB-PC Watchdog card.
+ This card simply watches your kernel to make sure it doesn't freeze,
+ and if it does, it reboots your computer after a certain amount of
+ time. The card can also monitor the internal temperature of the PC.
+ More info is available at <http://www.berkprod.com/usb_pc_watchdog.htm>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called pcwd_usb.
+
+ Most people will say N.
+
endmenu
#
-# Makefile for the kernel character device drivers.
+# Makefile for the WatchDog device drivers.
#
# Only one watchdog can succeed. We probe the hardware watchdog
obj-$(CONFIG_AMD7XX_TCO) += amd7xx_tco.o
obj-$(CONFIG_INDYDOG) += indydog.o
obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o
+obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
MODULE_DESCRIPTION("sma cpu5 watchdog driver");
MODULE_SUPPORTED_DEVICE("sma cpu5 watchdog");
MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
MODULE_PARM(port, "i");
MODULE_PARM_DESC(port, "base address of watchdog card, default is 0x91");
MODULE_AUTHOR("Rodolfo Giometti");
MODULE_DESCRIPTION("Driver for Eurotech CPU-1220/1410 on board watchdog");
MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
MODULE_AUTHOR("Charles Howes <chowes@vsol.net>");
MODULE_DESCRIPTION("IB700 SBC watchdog driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
/* end of ib700wdt.c */
MODULE_AUTHOR("Fernando Fuganti <fuganti@conectiva.com.br>");
MODULE_DESCRIPTION("MachZ ZF-Logic Watchdog driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
#ifdef CONFIG_WATCHDOG_NOWAYOUT
static int nowayout = 1;
module_init(mixcomwd_init);
module_exit(mixcomwd_exit);
+MODULE_AUTHOR("Gergely Madarasz <gorgo@itc.hu>");
+MODULE_DESCRIPTION("MixCom Watchdog driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
module_init(pcwatchdog_init);
module_exit(pcwatchdog_exit);
+MODULE_AUTHOR("Ken Hollis <kenji@bitgate.com>");
+MODULE_DESCRIPTION("Berkshire ISA-PC Watchdog driver");
MODULE_LICENSE("GPL");
-
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS_MISCDEV(TEMP_MINOR);
--- /dev/null
+/*
+ * Berkshire USB-PC Watchdog Card Driver
+ *
+ * (c) Copyright 2004 Wim Van Sebroeck <wim@iguana.be>.
+ *
+ * Based on source code of the following authors:
+ * Ken Hollis <kenji@bitgate.com>,
+ * Alan Cox <alan@redhat.com>,
+ * Matt Domsch <Matt_Domsch@dell.com>,
+ * Rob Radez <rob@osinvestor.com>,
+ * Greg Kroah-Hartman <greg@kroah.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ * Thanks also to Simon Machell at Berkshire Products Inc. for
+ * providing the test hardware. More info is available at
+ * http://www.berkprod.com/ or http://www.pcwatchdog.com/
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/completion.h>
+#include <asm/uaccess.h>
+#include <linux/usb.h>
+
+
+#ifdef CONFIG_USB_DEBUG
+ static int debug = 1;
+#else
+ static int debug;
+#endif
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG PFX format "\n" , ## arg); } while (0)
+
+
+/* Module and Version Information */
+#define DRIVER_VERSION "v1.00 (28/02/2004)"
+#define DRIVER_AUTHOR "Wim Van Sebroeck <wim@iguana.be>"
+#define DRIVER_DESC "Berkshire USB-PC Watchdog driver"
+#define DRIVER_LICENSE "GPL"
+#define DRIVER_NAME "pcwd_usb"
+#define PFX DRIVER_NAME ": "
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS_MISCDEV(TEMP_MINOR);
+
+/* Module Parameters */
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+#define WATCHDOG_HEARTBEAT 2 /* 2 sec default heartbeat */
+static int heartbeat = WATCHDOG_HEARTBEAT;
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/* The vendor and product id's for the USB-PC Watchdog card */
+#define USB_PCWD_VENDOR_ID 0x0c98
+#define USB_PCWD_PRODUCT_ID 0x1140
+
+/* table of devices that work with this driver */
+static struct usb_device_id usb_pcwd_table [] = {
+ { USB_DEVICE(USB_PCWD_VENDOR_ID, USB_PCWD_PRODUCT_ID) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, usb_pcwd_table);
+
+/* according to documentation max. time to process a command for the USB
+ * watchdog card is 100 or 200 ms, so we give it 250 ms to do it's job */
+#define USB_COMMAND_TIMEOUT 250
+
+/* Watchdog's internal commands */
+#define CMD_READ_TEMP 0x02 /* Read Temperature; Re-trigger Watchdog */
+#define CMD_TRIGGER CMD_READ_TEMP
+#define CMD_GET_STATUS 0x04 /* Get Status Information */
+#define CMD_GET_FIRMWARE_VERSION 0x08 /* Get Firmware Version */
+#define CMD_GET_DIP_SWITCH_SETTINGS 0x0c /* Get Dip Switch Settings */
+#define CMD_READ_WATCHDOG_TIMEOUT 0x18 /* Read Current Watchdog Time */
+#define CMD_WRITE_WATCHDOG_TIMEOUT 0x19 /* Write Current Watchdog Time */
+#define CMD_ENABLE_WATCHDOG 0x30 /* Enable / Disable Watchdog */
+#define CMD_DISABLE_WATCHDOG CMD_ENABLE_WATCHDOG
+
+/* Some defines that I like to be somewhere else like include/linux/usb_hid.h */
+#define HID_REQ_SET_REPORT 0x09
+#define HID_DT_REPORT (USB_TYPE_CLASS | 0x02)
+
+/* We can only use 1 card due to the /dev/watchdog restriction */
+static int cards_found;
+
+/* some internal variables */
+static unsigned long is_active;
+static char expect_release;
+
+/* Structure to hold all of our device specific stuff */
+struct usb_pcwd_private {
+ struct usb_device * udev; /* save off the usb device pointer */
+ struct usb_interface * interface; /* the interface for this device */
+
+ unsigned int interface_number; /* the interface number used for cmd's */
+
+ unsigned char * intr_buffer; /* the buffer to intr data */
+ dma_addr_t intr_dma; /* the dma address for the intr buffer */
+ size_t intr_size; /* the size of the intr buffer */
+ struct urb * intr_urb; /* the urb used for the intr pipe */
+
+ unsigned char cmd_command; /* The command that is reported back */
+ unsigned char cmd_data_msb; /* The data MSB that is reported back */
+ unsigned char cmd_data_lsb; /* The data LSB that is reported back */
+ atomic_t cmd_received; /* true if we received a report after a command */
+
+ int exists; /* Wether or not the device exists */
+ struct semaphore sem; /* locks this structure */
+};
+static struct usb_pcwd_private *usb_pcwd_device;
+
+/* prevent races between open() and disconnect() */
+static DECLARE_MUTEX (disconnect_sem);
+
+/* local function prototypes */
+static int usb_pcwd_probe (struct usb_interface *interface, const struct usb_device_id *id);
+static void usb_pcwd_disconnect (struct usb_interface *interface);
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver usb_pcwd_driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ .probe = usb_pcwd_probe,
+ .disconnect = usb_pcwd_disconnect,
+ .id_table = usb_pcwd_table,
+};
+
+
+static void usb_pcwd_intr_done(struct urb *urb, struct pt_regs *regs)
+{
+ struct usb_pcwd_private *usb_pcwd = (struct usb_pcwd_private *)urb->context;
+ unsigned char *data = usb_pcwd->intr_buffer;
+ int retval;
+
+ switch (urb->status) {
+ case 0: /* success */
+ break;
+ case -ECONNRESET: /* unlink */
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ return;
+ /* -EPIPE: should clear the halt */
+ default: /* error */
+ dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ goto resubmit;
+ }
+
+ dbg("received following data cmd=0x%02x msb=0x%02x lsb=0x%02x",
+ data[0], data[1], data[2]);
+
+ usb_pcwd->cmd_command = data[0];
+ usb_pcwd->cmd_data_msb = data[1];
+ usb_pcwd->cmd_data_lsb = data[2];
+
+ /* notify anyone waiting that the cmd has finished */
+ atomic_set (&usb_pcwd->cmd_received, 1);
+
+resubmit:
+ retval = usb_submit_urb (urb, GFP_ATOMIC);
+ if (retval)
+ printk(KERN_ERR PFX "can't resubmit intr, usb_submit_urb failed with result %d\n",
+ retval);
+}
+
+static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, unsigned char cmd,
+ unsigned char *msb, unsigned char *lsb)
+{
+ int got_response, count;
+ unsigned char buf[6];
+
+ /* We will not send any commands if the USB PCWD device does not exist */
+ if ((!usb_pcwd) || (!usb_pcwd->exists))
+ return -1;
+
+ /* The USB PC Watchdog uses a 6 byte report format. The board currently uses
+ * only 3 of the six bytes of the report. */
+ buf[0] = cmd; /* Byte 0 = CMD */
+ buf[1] = *msb; /* Byte 1 = Data MSB */
+ buf[2] = *lsb; /* Byte 2 = Data LSB */
+ buf[3] = buf[4] = buf[5] = 0; /* All other bytes not used */
+
+ dbg("sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x",
+ buf[0], buf[1], buf[2]);
+
+ atomic_set (&usb_pcwd->cmd_received, 0);
+
+ if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0),
+ HID_REQ_SET_REPORT, HID_DT_REPORT,
+ 0x0200, usb_pcwd->interface_number, buf, sizeof(buf),
+ HZ) != sizeof(buf)) {
+ dbg("usb_pcwd_send_command: error in usb_control_msg for cmd 0x%x 0x%x 0x%x\n", cmd, *msb, *lsb);
+ }
+ /* wait till the usb card processed the command,
+ * with a max. timeout of USB_COMMAND_TIMEOUT */
+ got_response = 0;
+ for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response); count++) {
+ mdelay(1);
+ if (atomic_read (&usb_pcwd->cmd_received))
+ got_response = 1;
+ }
+
+ if ((got_response) && (cmd == usb_pcwd->cmd_command)) {
+ /* read back response */
+ *msb = usb_pcwd->cmd_data_msb;
+ *lsb = usb_pcwd->cmd_data_lsb;
+ }
+
+ return got_response;
+}
+
+static int usb_pcwd_start(struct usb_pcwd_private *usb_pcwd)
+{
+ unsigned char msb = 0x00;
+ unsigned char lsb = 0x00;
+ int retval;
+
+ /* Enable Watchdog */
+ retval = usb_pcwd_send_command(usb_pcwd, CMD_ENABLE_WATCHDOG, &msb, &lsb);
+
+ if ((retval == 0) || (lsb == 0)) {
+ printk(KERN_ERR PFX "Card did not acknowledge enable attempt\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int usb_pcwd_stop(struct usb_pcwd_private *usb_pcwd)
+{
+ unsigned char msb = 0xA5;
+ unsigned char lsb = 0xC3;
+ int retval;
+
+ /* Disable Watchdog */
+ retval = usb_pcwd_send_command(usb_pcwd, CMD_DISABLE_WATCHDOG, &msb, &lsb);
+
+ if ((retval == 0) || (lsb != 0)) {
+ printk(KERN_ERR PFX "Card did not acknowledge disable attempt\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int usb_pcwd_keepalive(struct usb_pcwd_private *usb_pcwd)
+{
+ unsigned char dummy;
+
+ /* Re-trigger Watchdog */
+ usb_pcwd_send_command(usb_pcwd, CMD_TRIGGER, &dummy, &dummy);
+
+ return 0;
+}
+
+static int usb_pcwd_set_heartbeat(struct usb_pcwd_private *usb_pcwd, int t)
+{
+ unsigned char msb = t / 256;
+ unsigned char lsb = t % 256;
+
+ if ((t < 0x0001) || (t > 0xFFFF))
+ return -EINVAL;
+
+ /* Write new heartbeat to watchdog */
+ usb_pcwd_send_command(usb_pcwd, CMD_WRITE_WATCHDOG_TIMEOUT, &msb, &lsb);
+
+ heartbeat = t;
+ return 0;
+}
+
+static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd, int *temperature)
+{
+ unsigned char msb, lsb;
+
+ usb_pcwd_send_command(usb_pcwd, CMD_READ_TEMP, &msb, &lsb);
+
+ /*
+ * Convert celsius to fahrenheit, since this was
+ * the decided 'standard' for this return value.
+ */
+ *temperature = (lsb * 9 / 5) + 32;
+
+ return 0;
+}
+
+/*
+ * /dev/watchdog handling
+ */
+
+static ssize_t usb_pcwd_write(struct file *file, const char *data,
+ size_t len, loff_t *ppos)
+{
+ /* Can't seek (pwrite) on this device */
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+
+ /* See if we got the magic character 'V' and reload the timer */
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ /* note: just in case someone wrote the magic character
+ * five months ago... */
+ expect_release = 0;
+
+ /* scan to see whether or not we got the magic character */
+ for (i = 0; i != len; i++) {
+ char c;
+ if(get_user(c, data+i))
+ return -EFAULT;
+ if (c == 'V')
+ expect_release = 42;
+ }
+ }
+
+ /* someone wrote to us, we should reload the timer */
+ usb_pcwd_keepalive(usb_pcwd_device);
+ }
+ return len;
+}
+
+static int usb_pcwd_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ static struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING |
+ WDIOF_SETTIMEOUT |
+ WDIOF_MAGICCLOSE,
+ .firmware_version = 1,
+ .identity = DRIVER_NAME,
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user((struct watchdog_info *) arg, &ident,
+ sizeof (ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, (int *) arg);
+
+ case WDIOC_GETTEMP:
+ {
+ int temperature;
+
+ if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
+ return -EFAULT;
+
+ return put_user(temperature, (int *) arg);
+ }
+
+ case WDIOC_KEEPALIVE:
+ usb_pcwd_keepalive(usb_pcwd_device);
+ return 0;
+
+ case WDIOC_SETOPTIONS:
+ {
+ int new_options, retval = -EINVAL;
+
+ if (get_user (new_options, (int *) arg))
+ return -EFAULT;
+
+ if (new_options & WDIOS_DISABLECARD) {
+ usb_pcwd_stop(usb_pcwd_device);
+ retval = 0;
+ }
+
+ if (new_options & WDIOS_ENABLECARD) {
+ usb_pcwd_start(usb_pcwd_device);
+ retval = 0;
+ }
+
+ return retval;
+ }
+
+ case WDIOC_SETTIMEOUT:
+ {
+ int new_heartbeat;
+
+ if (get_user(new_heartbeat, (int *) arg))
+ return -EFAULT;
+
+ if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat))
+ return -EINVAL;
+
+ usb_pcwd_keepalive(usb_pcwd_device);
+ /* Fall */
+ }
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(heartbeat, (int *)arg);
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static int usb_pcwd_open(struct inode *inode, struct file *file)
+{
+ /* /dev/watchdog can only be opened once */
+ if (test_and_set_bit(0, &is_active))
+ return -EBUSY;
+
+ /* Activate */
+ usb_pcwd_start(usb_pcwd_device);
+ usb_pcwd_keepalive(usb_pcwd_device);
+ return 0;
+}
+
+static int usb_pcwd_release(struct inode *inode, struct file *file)
+{
+ /*
+ * Shut off the timer.
+ */
+ if (expect_release == 42) {
+ usb_pcwd_stop(usb_pcwd_device);
+ } else {
+ printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+ usb_pcwd_keepalive(usb_pcwd_device);
+ }
+ clear_bit(0, &is_active);
+ expect_release = 0;
+ return 0;
+}
+
+/*
+ * /dev/temperature handling
+ */
+
+static ssize_t usb_pcwd_temperature_read(struct file *file, char *data,
+ size_t len, loff_t *ppos)
+{
+ int temperature;
+
+ /* Can't seek (pwrite) on this device */
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+
+ if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature))
+ return -EFAULT;
+
+ if (copy_to_user (data, &temperature, 1))
+ return -EFAULT;
+
+ return 1;
+}
+
+static int usb_pcwd_temperature_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int usb_pcwd_temperature_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+/*
+ * Notify system
+ */
+
+static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
+{
+ if (code==SYS_DOWN || code==SYS_HALT) {
+ /* Turn the WDT off */
+ usb_pcwd_stop(usb_pcwd_device);
+ }
+
+ return NOTIFY_DONE;
+}
+
+/*
+ * Kernel Interfaces
+ */
+
+static struct file_operations usb_pcwd_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = usb_pcwd_write,
+ .ioctl = usb_pcwd_ioctl,
+ .open = usb_pcwd_open,
+ .release = usb_pcwd_release,
+};
+
+static struct miscdevice usb_pcwd_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &usb_pcwd_fops,
+};
+
+static struct file_operations usb_pcwd_temperature_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = usb_pcwd_temperature_read,
+ .open = usb_pcwd_temperature_open,
+ .release = usb_pcwd_temperature_release,
+};
+
+static struct miscdevice usb_pcwd_temperature_miscdev = {
+ .minor = TEMP_MINOR,
+ .name = "temperature",
+ .fops = &usb_pcwd_temperature_fops,
+};
+
+static struct notifier_block usb_pcwd_notifier = {
+ .notifier_call = usb_pcwd_notify_sys,
+};
+
+/**
+ * usb_pcwd_delete
+ */
+static inline void usb_pcwd_delete (struct usb_pcwd_private *usb_pcwd)
+{
+ if (usb_pcwd->intr_urb != NULL)
+ usb_free_urb (usb_pcwd->intr_urb);
+ if (usb_pcwd->intr_buffer != NULL)
+ usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size,
+ usb_pcwd->intr_buffer, usb_pcwd->intr_dma);
+ kfree (usb_pcwd);
+}
+
+/**
+ * usb_pcwd_probe
+ *
+ * Called by the usb core when a new device is connected that it thinks
+ * this driver might be interested in.
+ */
+static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(interface);
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ struct usb_pcwd_private *usb_pcwd = NULL;
+ int pipe, maxp;
+ int retval = -ENOMEM;
+ int got_fw_rev;
+ unsigned char fw_rev_major, fw_rev_minor;
+ char fw_ver_str[20];
+ unsigned char option_switches, dummy;
+
+ /* See if the device offered us matches what we can accept */
+ if ((udev->descriptor.idVendor != USB_PCWD_VENDOR_ID) ||
+ (udev->descriptor.idProduct != USB_PCWD_PRODUCT_ID)) {
+ return -ENODEV;
+ }
+
+ cards_found++;
+ if (cards_found > 1) {
+ printk(KERN_ERR PFX "This driver only supports 1 device\n");
+ return -ENODEV;
+ }
+
+ /* get the active interface descriptor */
+ iface_desc = &interface->altsetting[interface->act_altsetting];
+
+ /* check out that we have a HID device */
+ if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) {
+ printk(KERN_ERR PFX "The device isn't a Human Interface Device\n");
+ return -ENODEV;
+ }
+
+ /* check out the endpoint: it has to be Interrupt & IN */
+ endpoint = &iface_desc->endpoint[0].desc;
+
+ if (!((endpoint->bEndpointAddress & USB_DIR_IN) &&
+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_INT))) {
+ /* we didn't find a Interrupt endpoint with direction IN */
+ printk(KERN_ERR PFX "Couldn't find an INTR & IN endpoint\n");
+ return -ENODEV;
+ }
+
+ /* get a handle to the interrupt data pipe */
+ pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
+ maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+
+ /* allocate memory for our device and initialize it */
+ usb_pcwd = kmalloc (sizeof(struct usb_pcwd_private), GFP_KERNEL);
+ if (usb_pcwd == NULL) {
+ printk(KERN_ERR PFX "Out of memory\n");
+ goto error;
+ }
+ memset (usb_pcwd, 0x00, sizeof (*usb_pcwd));
+
+ usb_pcwd_device = usb_pcwd;
+
+ init_MUTEX (&usb_pcwd->sem);
+ usb_pcwd->udev = udev;
+ usb_pcwd->interface = interface;
+ usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber;
+ usb_pcwd->intr_size = (endpoint->wMaxPacketSize > 8 ? endpoint->wMaxPacketSize : 8);
+
+ /* set up the memory buffer's */
+ if (!(usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, SLAB_ATOMIC, &usb_pcwd->intr_dma))) {
+ printk(KERN_ERR PFX "Out of memory\n");
+ goto error;
+ }
+
+ /* allocate the urb's */
+ usb_pcwd->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!usb_pcwd->intr_urb) {
+ printk(KERN_ERR PFX "Out of memory\n");
+ goto error;
+ }
+
+ /* initialise the intr urb's */
+ usb_fill_int_urb(usb_pcwd->intr_urb, udev, pipe,
+ usb_pcwd->intr_buffer, usb_pcwd->intr_size,
+ usb_pcwd_intr_done, usb_pcwd, endpoint->bInterval);
+ usb_pcwd->intr_urb->transfer_dma = usb_pcwd->intr_dma;
+ usb_pcwd->intr_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ /* register our interrupt URB with the USB system */
+ if (usb_submit_urb(usb_pcwd->intr_urb, GFP_KERNEL)) {
+ printk(KERN_ERR PFX "Problem registering interrupt URB\n");
+ retval = -EIO; /* failure */
+ goto error;
+ }
+
+ /* The device exists and can be communicated with */
+ usb_pcwd->exists = 1;
+
+ /* disable card */
+ usb_pcwd_stop(usb_pcwd);
+
+ /* Get the Firmware Version */
+ got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor);
+ if (got_fw_rev) {
+ sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor);
+ } else {
+ sprintf(fw_ver_str, "<card no answer>");
+ }
+
+ printk(KERN_INFO PFX "Found card (Firmware: %s) with temp option\n",
+ fw_ver_str);
+
+ /* Get switch settings */
+ usb_pcwd_send_command(usb_pcwd, CMD_GET_DIP_SWITCH_SETTINGS, &dummy, &option_switches);
+
+ printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n",
+ option_switches,
+ ((option_switches & 0x10) ? "ON" : "OFF"),
+ ((option_switches & 0x08) ? "ON" : "OFF"));
+
+ /* Check that the heartbeat value is within it's range ; if not reset to the default */
+ if (heartbeat < 1 || heartbeat > 0xFFFF) {
+ heartbeat = WATCHDOG_HEARTBEAT;
+ printk(KERN_INFO PFX "heartbeat value must be 0<heartbeat<65536, using %d\n",
+ heartbeat);
+ }
+
+ /* Calculate the watchdog's heartbeat */
+ usb_pcwd_set_heartbeat(usb_pcwd, heartbeat);
+
+ retval = register_reboot_notifier(&usb_pcwd_notifier);
+ if (retval != 0) {
+ printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+ retval);
+ goto error;
+ }
+
+ retval = misc_register(&usb_pcwd_miscdev);
+ if (retval != 0) {
+ printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, retval);
+ goto err_out_unregister_reboot;
+ }
+
+ retval = misc_register(&usb_pcwd_temperature_miscdev);
+ if (retval != 0) {
+ printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+ TEMP_MINOR, retval);
+ goto err_out_misc_deregister;
+ }
+
+ /* we can register the device now, as it is ready */
+ usb_set_intfdata (interface, usb_pcwd);
+
+ printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
+ heartbeat, nowayout);
+
+ return 0;
+
+err_out_misc_deregister:
+ misc_deregister(&usb_pcwd_miscdev);
+err_out_unregister_reboot:
+ unregister_reboot_notifier(&usb_pcwd_notifier);
+error:
+ usb_pcwd_delete (usb_pcwd);
+ usb_pcwd_device = NULL;
+ return retval;
+}
+
+
+/**
+ * usb_pcwd_disconnect
+ *
+ * Called by the usb core when the device is removed from the system.
+ *
+ * This routine guarantees that the driver will not submit any more urbs
+ * by clearing dev->udev.
+ */
+static void usb_pcwd_disconnect(struct usb_interface *interface)
+{
+ struct usb_pcwd_private *usb_pcwd;
+
+ /* prevent races with open() */
+ down (&disconnect_sem);
+
+ usb_pcwd = usb_get_intfdata (interface);
+ usb_set_intfdata (interface, NULL);
+
+ down (&usb_pcwd->sem);
+
+ /* Stop the timer before we leave */
+ if (!nowayout)
+ usb_pcwd_stop(usb_pcwd);
+
+ /* We should now stop communicating with the USB PCWD device */
+ usb_pcwd->exists = 0;
+
+ /* Deregister */
+ misc_deregister(&usb_pcwd_temperature_miscdev);
+ misc_deregister(&usb_pcwd_miscdev);
+ unregister_reboot_notifier(&usb_pcwd_notifier);
+
+ up (&usb_pcwd->sem);
+
+ /* Delete the USB PCWD device */
+ usb_pcwd_delete(usb_pcwd);
+
+ cards_found--;
+
+ up (&disconnect_sem);
+
+ printk(KERN_INFO PFX "USB PC Watchdog disconnected\n");
+}
+
+
+
+/**
+ * usb_pcwd_init
+ */
+static int __init usb_pcwd_init(void)
+{
+ int result;
+
+ /* register this driver with the USB subsystem */
+ result = usb_register(&usb_pcwd_driver);
+ if (result) {
+ printk(KERN_ERR PFX "usb_register failed. Error number %d\n",
+ result);
+ return result;
+ }
+
+ printk(KERN_INFO PFX DRIVER_DESC " " DRIVER_VERSION "\n");
+ return 0;
+}
+
+
+/**
+ * usb_pcwd_exit
+ */
+static void __exit usb_pcwd_exit(void)
+{
+ /* deregister this driver with the USB subsystem */
+ usb_deregister(&usb_pcwd_driver);
+}
+
+
+module_init (usb_pcwd_init);
+module_exit (usb_pcwd_exit);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
MODULE_AUTHOR("Zwane Mwaikambo <zwane@commfireservices.com>");
MODULE_DESCRIPTION("Driver for National Semiconductor PC87307/PC97307 watchdog component");
MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pádraig Brady <P@draigBrady.com>");
MODULE_DESCRIPTION("w38627hf WDT driver");
-
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
MODULE_AUTHOR("Scott and Bill Jennings");
MODULE_DESCRIPTION("Driver for watchdog timer in w83877f chip");
MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
MODULE_AUTHOR("Phil Blundell <pb@nexus.co.uk>");
MODULE_DESCRIPTION("Footbridge watchdog driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
module_param(soft_margin, int, 0);
MODULE_PARM_DESC(soft_margin,"Watchdog timeout in seconds");
module_init(nwwatchdog_init);
module_exit(nwwatchdog_exit);
+MODULE_AUTHOR("Woody Suwalski <woody@netwinder.org>");
MODULE_DESCRIPTION("W83977AF Watchdog driver");
MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
MODULE_AUTHOR("JP Nollmann, Alan Cox");
MODULE_DESCRIPTION("Driver for the ICS PCI watchdog cards");
MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS_MISCDEV(TEMP_MINOR);
This option is not needed for userspace programs like gscanbus
to show this information.
+config IEEE1394_EXTRA_CONFIG_ROMS
+ bool "Build in extra config rom entries for certain functionality"
+ depends on IEEE1394
+ help
+ Some IEEE1394 functionality depends on extra config rom entries
+ being available in the host adapters CSR. These options will
+ allow you to choose which ones.
+
+config IEEE1394_CONFIG_ROM_IP1394
+ bool "IP-1394 Entry"
+ depends on IEEE1394_EXTRA_CONFIG_ROMS && IEEE1394
+ help
+ Adds an entry for using IP-over-1394. If you want to use your
+ IEEE1394 bus as a network for IP systems (including interacting
+ with MacOSX and WinXP IP-over-1394), enable this option and the
+ eth1394 option below.
+
comment "Device Drivers"
depends on IEEE1394
config IEEE1394_ETH1394
tristate "Ethernet over 1394"
depends on IEEE1394 && EXPERIMENTAL
+ select IEEE1394_CONFIG_ROM_IP1394
+ select IEEE1394_EXTRA_CONFIG_ROMS
help
This driver implements a functional majority of RFC 2734: IPv4 over
1394. It will provide IP connectivity with implementations of RFC
ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
highlevel.o csr.o nodemgr.o oui.o dma.o iso.o \
- csr1212.o
+ csr1212.o config_roms.o
obj-$(CONFIG_IEEE1394) += ieee1394.o
obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o
ah->host = host;
ah->ohci = host->hostdata;
- hpsb_set_hostinfo_key(&amdtp_highlevel, host, ah->ohci->id);
+ hpsb_set_hostinfo_key(&amdtp_highlevel, host, ah->host->id);
- minor = IEEE1394_MINOR_BLOCK_AMDTP * 16 + ah->ohci->id;
+ minor = IEEE1394_MINOR_BLOCK_AMDTP * 16 + ah->host->id;
INIT_LIST_HEAD(&ah->stream_list);
spin_lock_init(&ah->stream_list_lock);
devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
- S_IFCHR|S_IRUSR|S_IWUSR, "amdtp/%d", ah->ohci->id);
+ S_IFCHR|S_IRUSR|S_IWUSR, "amdtp/%d", ah->host->id);
}
static void amdtp_remove_host(struct hpsb_host *host)
struct amdtp_host *ah = hpsb_get_hostinfo(&amdtp_highlevel, host);
if (ah)
- devfs_remove("amdtp/%d", ah->ohci->id);
+ devfs_remove("amdtp/%d", ah->host->id);
return;
}
--- /dev/null
+/*
+ * IEEE 1394 for Linux
+ *
+ * ConfigROM entries
+ *
+ * Copyright (C) 2004 Ben Collins
+ *
+ * This code is licensed under the GPL. See the file COPYING in the root
+ * directory of the kernel sources for details.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+
+#include "csr1212.h"
+#include "ieee1394.h"
+#include "ieee1394_types.h"
+#include "hosts.h"
+#include "ieee1394_core.h"
+#include "highlevel.h"
+#include "csr.h"
+#include "config_roms.h"
+
+struct hpsb_config_rom_entry {
+ const char *name;
+
+ /* Base initialization, called at module load */
+ int (*init)(void);
+
+ /* Add entry to specified host */
+ int (*add)(struct hpsb_host *host);
+
+ /* Remove entry from specified host */
+ void (*remove)(struct hpsb_host *host);
+
+ /* Cleanup called at module exit */
+ void (*cleanup)(void);
+
+ /* The flag added to host->config_roms */
+ unsigned int flag;
+};
+
+
+int hpsb_default_host_entry(struct hpsb_host *host)
+{
+ struct csr1212_keyval *root;
+ struct csr1212_keyval *vend_id = NULL;
+ struct csr1212_keyval *text = NULL;
+ char csr_name[128];
+ int ret;
+
+ sprintf(csr_name, "Linux - %s", host->driver->name);
+ root = host->csr.rom->root_kv;
+
+ vend_id = csr1212_new_immediate(CSR1212_KV_ID_VENDOR, host->csr.guid_hi >> 8);
+ text = csr1212_new_string_descriptor_leaf(csr_name);
+
+ if (!vend_id || !text) {
+ if (vend_id)
+ csr1212_release_keyval(vend_id);
+ if (text)
+ csr1212_release_keyval(text);
+ csr1212_destroy_csr(host->csr.rom);
+ return -ENOMEM;
+ }
+
+ ret = csr1212_associate_keyval(vend_id, text);
+ csr1212_release_keyval(text);
+ ret |= csr1212_attach_keyval_to_directory(root, vend_id);
+ if (ret != CSR1212_SUCCESS) {
+ csr1212_release_keyval(vend_id);
+ csr1212_destroy_csr(host->csr.rom);
+ return -ENOMEM;
+ }
+
+ host->update_config_rom = 1;
+
+ return 0;
+}
+
+
+#ifdef CONFIG_IEEE1394_CONFIG_ROM_IP1394
+#include "eth1394.h"
+
+static struct csr1212_keyval *ip1394_ud;
+
+static int config_rom_ip1394_init(void)
+{
+ struct csr1212_keyval *spec_id = NULL;
+ struct csr1212_keyval *spec_desc = NULL;
+ struct csr1212_keyval *ver = NULL;
+ struct csr1212_keyval *ver_desc = NULL;
+ int ret = -ENOMEM;
+
+ ip1394_ud = csr1212_new_directory(CSR1212_KV_ID_UNIT);
+
+ spec_id = csr1212_new_immediate(CSR1212_KV_ID_SPECIFIER_ID,
+ ETHER1394_GASP_SPECIFIER_ID);
+ spec_desc = csr1212_new_string_descriptor_leaf("IANA");
+ ver = csr1212_new_immediate(CSR1212_KV_ID_VERSION,
+ ETHER1394_GASP_VERSION);
+ ver_desc = csr1212_new_string_descriptor_leaf("IPv4");
+
+ if (!ip1394_ud || !spec_id || !spec_desc || !ver || !ver_desc)
+ goto ip1394_fail;
+
+ if (csr1212_associate_keyval(spec_id, spec_desc) == CSR1212_SUCCESS &&
+ csr1212_associate_keyval(ver, ver_desc) == CSR1212_SUCCESS &&
+ csr1212_attach_keyval_to_directory(ip1394_ud, spec_id) == CSR1212_SUCCESS &&
+ csr1212_attach_keyval_to_directory(ip1394_ud, ver) == CSR1212_SUCCESS)
+ ret = 0;
+
+ip1394_fail:
+ if (ret && ip1394_ud) {
+ csr1212_release_keyval(ip1394_ud);
+ ip1394_ud = NULL;
+ }
+
+ if (spec_id)
+ csr1212_release_keyval(spec_id);
+ if (spec_desc)
+ csr1212_release_keyval(spec_desc);
+ if (ver)
+ csr1212_release_keyval(ver);
+ if (ver_desc)
+ csr1212_release_keyval(ver_desc);
+
+ return ret;
+}
+
+static void config_rom_ip1394_cleanup(void)
+{
+ if (ip1394_ud) {
+ csr1212_release_keyval(ip1394_ud);
+ ip1394_ud = NULL;
+ }
+}
+
+static int config_rom_ip1394_add(struct hpsb_host *host)
+{
+ if (!ip1394_ud)
+ return -ENODEV;
+
+ if (csr1212_attach_keyval_to_directory(host->csr.rom->root_kv,
+ ip1394_ud) != CSR1212_SUCCESS)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void config_rom_ip1394_remove(struct hpsb_host *host)
+{
+ csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, ip1394_ud);
+}
+
+static struct hpsb_config_rom_entry ip1394_entry = {
+ .name = "ip1394",
+ .init = config_rom_ip1394_init,
+ .add = config_rom_ip1394_add,
+ .remove = config_rom_ip1394_remove,
+ .cleanup = config_rom_ip1394_cleanup,
+ .flag = HPSB_CONFIG_ROM_ENTRY_IP1394,
+};
+#endif /* CONFIG_IEEE1394_CONFIG_ROM_IP1394 */
+
+
+static struct hpsb_config_rom_entry *const config_rom_entries[] = {
+#ifdef CONFIG_IEEE1394_CONFIG_ROM_IP1394
+ &ip1394_entry,
+#endif
+ NULL,
+};
+
+
+int hpsb_init_config_roms(void)
+{
+ int i, error = 0;
+
+ for (i = 0; config_rom_entries[i]; i++) {
+ if (!config_rom_entries[i]->init)
+ continue;
+
+ if (config_rom_entries[i]->init()) {
+ HPSB_ERR("Failed to initialize config rom entry `%s'",
+ config_rom_entries[i]->name);
+ error = -1;
+ } else
+ HPSB_DEBUG("Initialized config rom entry `%s'",
+ config_rom_entries[i]->name);
+ }
+
+ return error;
+}
+
+void hpsb_cleanup_config_roms(void)
+{
+ int i;
+
+ for (i = 0; config_rom_entries[i]; i++) {
+ if (config_rom_entries[i]->cleanup)
+ config_rom_entries[i]->cleanup();
+ }
+}
+
+int hpsb_add_extra_config_roms(struct hpsb_host *host)
+{
+ int i, error = 0;
+
+ for (i = 0; config_rom_entries[i]; i++) {
+ if (config_rom_entries[i]->add(host)) {
+ HPSB_ERR("fw-host%d: Failed to attach config rom entry `%s'",
+ host->id, config_rom_entries[i]->name);
+ error = -1;
+ } else {
+ host->config_roms |= config_rom_entries[i]->flag;
+ host->update_config_rom = 1;
+ }
+ }
+
+ return error;
+}
+
+void hpsb_remove_extra_config_roms(struct hpsb_host *host)
+{
+ int i;
+
+ for (i = 0; config_rom_entries[i]; i++) {
+ if (!(host->config_roms & config_rom_entries[i]->flag))
+ continue;
+
+ config_rom_entries[i]->remove(host);
+
+ host->config_roms &= ~config_rom_entries[i]->flag;
+ host->update_config_rom = 1;
+ }
+}
--- /dev/null
+#ifndef _IEEE1394_CONFIG_ROMS_H
+#define _IEEE1394_CONFIG_ROMS_H
+
+#include "ieee1394_types.h"
+#include "hosts.h"
+
+/* The default host entry. This must succeed. */
+int hpsb_default_host_entry(struct hpsb_host *host);
+
+/* Initialize all config roms */
+int hpsb_init_config_roms(void);
+
+/* Cleanup all config roms */
+void hpsb_cleanup_config_roms(void);
+
+/* Add extra config roms to specified host */
+int hpsb_add_extra_config_roms(struct hpsb_host *host);
+
+/* Remove extra config roms from specified host */
+void hpsb_remove_extra_config_roms(struct hpsb_host *host);
+
+
+/* List of flags to check if a host contains a certain extra config rom
+ * entry. Available in the host->config_roms member. */
+#define HPSB_CONFIG_ROM_ENTRY_IP1394 0x00000001
+
+#endif /* _IEEE1394_CONFIG_ROMS_H */
if (k->key.type == CSR1212_KV_TYPE_DIRECTORY) {
/* If the current entry is a directory, then move all
* the entries to the destruction list. */
- tail->next = k->value.directory.dentries_head;
- if (k->value.directory.dentries_head)
+ if (k->value.directory.dentries_head) {
+ tail->next = k->value.directory.dentries_head;
k->value.directory.dentries_head->prev = tail;
- tail = k->value.directory.dentries_tail;
+ tail = k->value.directory.dentries_tail;
+ }
}
free_keyval(k);
k = a;
case CSR1212_KV_TYPE_DIRECTORY:
for (i = 0; i < kvi_len; i++) {
csr1212_quad_t ki = kvi->data[i];
+
+ /* Some devices put null entries in their unit
+ * directories. If we come across such and entry,
+ * then skip it. */
+ if (ki == 0x0)
+ continue;
ret = csr1212_parse_dir_entry(kv, ki,
(kv->offset +
quads_to_bytes(i + 1)),
video->ohci = ohci;
/* lower 2 bits of id indicate which of four "plugs"
per host */
- video->id = ohci->id << 2;
+ video->id = ohci->host->id << 2;
if (format == DV1394_NTSC)
video->id |= mode;
else
);
devfs_remove("ieee1394/%s", buf);
- list_del(&video->list);
kfree(video);
}
static void dv1394_remove_host (struct hpsb_host *host)
{
- struct ti_ohci *ohci;
- struct video_card *video = NULL;
+ struct video_card *video;
unsigned long flags;
- struct list_head *lh, *templh;
- int n;
+ int id = host->id;
/* We only work with the OHCI-1394 driver */
if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
return;
- ohci = (struct ti_ohci *)host->hostdata;
+ /* find the corresponding video_cards */
+ do {
+ struct video_card *tmp_vid;
+ video = NULL;
- /* find the corresponding video_cards */
- spin_lock_irqsave(&dv1394_cards_lock, flags);
- if (!list_empty(&dv1394_cards)) {
- list_for_each_safe(lh, templh, &dv1394_cards) {
- video = list_entry(lh, struct video_card, list);
- if ((video->id >> 2) == ohci->id)
- dv1394_un_init(video);
+ spin_lock_irqsave(&dv1394_cards_lock, flags);
+ list_for_each_entry(tmp_vid, &dv1394_cards, list) {
+ if ((tmp_vid->id >> 2) == id) {
+ list_del(&tmp_vid->list);
+ video = tmp_vid;
+ break;
+ }
}
- }
- spin_unlock_irqrestore(&dv1394_cards_lock, flags);
+ spin_unlock_irqrestore(&dv1394_cards_lock, flags);
- n = (video->id >> 2);
+ if (video)
+ dv1394_un_init(video);
+ } while (video != NULL);
- devfs_remove("ieee1394/dv/host%d/NTSC", n);
- devfs_remove("ieee1394/dv/host%d/PAL", n);
- devfs_remove("ieee1394/dv/host%d", n);
+ devfs_remove("ieee1394/dv/host%d/NTSC", id);
+ devfs_remove("ieee1394/dv/host%d/PAL", id);
+ devfs_remove("ieee1394/dv/host%d", id);
}
static void dv1394_add_host (struct hpsb_host *host)
{
struct ti_ohci *ohci;
+ int id = host->id;
/* We only work with the OHCI-1394 driver */
if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
ohci = (struct ti_ohci *)host->hostdata;
- devfs_mk_dir("ieee1394/dv/host%d", ohci->id);
- devfs_mk_dir("ieee1394/dv/host%d/NTSC", ohci->id);
- devfs_mk_dir("ieee1394/dv/host%d/PAL", ohci->id);
+ devfs_mk_dir("ieee1394/dv/host%d", id);
+ devfs_mk_dir("ieee1394/dv/host%d/NTSC", id);
+ devfs_mk_dir("ieee1394/dv/host%d/PAL", id);
dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
static void dv1394_host_reset(struct hpsb_host *host)
{
struct ti_ohci *ohci;
- struct video_card *video = NULL;
+ struct video_card *video = NULL, *tmp_vid;
unsigned long flags;
/* We only work with the OHCI-1394 driver */
/* find the corresponding video_cards */
spin_lock_irqsave(&dv1394_cards_lock, flags);
- if (!list_empty(&dv1394_cards)) {
- list_for_each_entry(video, &dv1394_cards, list) {
- if ((video->id >> 2) == ohci->id)
- break;
+ list_for_each_entry(tmp_vid, &dv1394_cards, list) {
+ if ((tmp_vid->id >> 2) == host->id) {
+ video = tmp_vid;
+ break;
}
}
spin_unlock_irqrestore(&dv1394_cards_lock, flags);
#include "iso.h"
#include "nodemgr.h"
#include "eth1394.h"
+#include "config_roms.h"
#define ETH1394_PRINT_G(level, fmt, args...) \
printk(level "%s: " fmt, driver_name, ## args)
#define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__)
static char version[] __devinitdata =
- "$Rev: 1133 $ Ben Collins <bcollins@debian.org>";
+ "$Rev: 1175 $ Ben Collins <bcollins@debian.org>";
struct fragment_info {
struct list_head list;
struct list_head frag_info;
};
-static struct csr1212_keyval *eth1394_ud = NULL;
-
struct pdg_list {
struct list_head list; /* partial datagram list per node */
unsigned int sz; /* partial datagram list size per node */
{}
};
+MODULE_DEVICE_TABLE(ieee1394, eth1394_id_table);
+
static struct hpsb_protocol_driver eth1394_proto_driver = {
.name = "IPv4 over 1394 Driver",
.id_table = eth1394_id_table,
struct net_device *dev = NULL;
struct eth1394_priv *priv;
static int version_printed = 0;
-
u64 fifo_addr;
+ if (!(host->config_roms & HPSB_CONFIG_ROM_ENTRY_IP1394))
+ return;
+
fifo_addr = hpsb_allocate_and_register_addrspace(ð1394_highlevel,
host,
&addr_ops,
priv->bc_state = ETHER1394_BC_RUNNING;
}
- if (csr1212_attach_keyval_to_directory(host->csr.rom->root_kv,
- eth1394_ud) != CSR1212_SUCCESS) {
- ETH1394_PRINT (KERN_ERR, dev->name,
- "Cannot attach IP 1394 Unit Directory to "
- "Config ROM\n");
- goto out;
- }
- hi->host->update_config_rom = 1;
return;
out:
if (priv->iso != NULL)
hpsb_iso_shutdown(priv->iso);
- csr1212_detach_keyval_from_directory(hi->host->csr.rom->root_kv,
- eth1394_ud);
- hi->host->update_config_rom = 1;
-
if (hi->dev) {
unregister_netdev (hi->dev);
free_netdev(hi->dev);
p = hpsb_alloc_packet(0);
if (p) {
p->host = host;
- p->data = NULL;
p->generation = get_hpsb_generation(host);
p->type = hpsb_async;
}
| (1 << 8) | (TCODE_WRITEB << 4);
p->header[3] = tx_len << 16;
- p->data_size = tx_len + (tx_len % 4 ? 4 - (tx_len % 4) : 0);
+ p->data_size = (tx_len + 3) & ~3;
p->data = (quadlet_t*)data;
return 0;
case ETHTOOL_GDRVINFO: {
struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
strcpy (info.driver, driver_name);
- strcpy (info.version, "$Rev: 1133 $");
+ strcpy (info.version, "$Rev: 1175 $");
/* FIXME XXX provide sane businfo */
strcpy (info.bus_info, "ieee1394");
if (copy_to_user (useraddr, &info, sizeof (info)))
static int __init ether1394_init_module (void)
{
- int ret;
- struct csr1212_keyval *spec_id = NULL;
- struct csr1212_keyval *spec_desc = NULL;
- struct csr1212_keyval *ver = NULL;
- struct csr1212_keyval *ver_desc = NULL;
-
packet_task_cache = kmem_cache_create("packet_task", sizeof(struct packet_task),
0, 0, NULL, NULL);
- eth1394_ud = csr1212_new_directory(CSR1212_KV_ID_UNIT);
- spec_id = csr1212_new_immediate(CSR1212_KV_ID_SPECIFIER_ID,
- ETHER1394_GASP_SPECIFIER_ID);
- spec_desc = csr1212_new_string_descriptor_leaf("IANA");
- ver = csr1212_new_immediate(CSR1212_KV_ID_VERSION,
- ETHER1394_GASP_VERSION);
- ver_desc = csr1212_new_string_descriptor_leaf("IPv4");
-
- if ((!eth1394_ud) ||
- (!spec_id) ||
- (!spec_desc) ||
- (!ver) ||
- (!ver_desc)) {
- ret = -ENOMEM;
- goto out;
- }
-
- ret = csr1212_associate_keyval(spec_id, spec_desc);
- if (ret != CSR1212_SUCCESS)
- goto out;
-
- ret = csr1212_associate_keyval(ver, ver_desc);
- if (ret != CSR1212_SUCCESS)
- goto out;
-
- ret = csr1212_attach_keyval_to_directory(eth1394_ud, spec_id);
- if (ret != CSR1212_SUCCESS)
- goto out;
-
- ret = csr1212_attach_keyval_to_directory(eth1394_ud, ver);
- if (ret != CSR1212_SUCCESS)
- goto out;
-
/* Register ourselves as a highlevel driver */
hpsb_register_highlevel(ð1394_highlevel);
- ret = hpsb_register_protocol(ð1394_proto_driver);
-
-out:
- if ((ret != 0) && eth1394_ud) {
- csr1212_release_keyval(eth1394_ud);
- }
- if (spec_id)
- csr1212_release_keyval(spec_id);
- if (spec_desc)
- csr1212_release_keyval(spec_desc);
- if (ver)
- csr1212_release_keyval(ver);
- if (ver_desc)
- csr1212_release_keyval(ver_desc);
-
- return ret;
+ return hpsb_register_protocol(ð1394_proto_driver);
}
static void __exit ether1394_exit_module (void)
hpsb_unregister_protocol(ð1394_proto_driver);
hpsb_unregister_highlevel(ð1394_highlevel);
kmem_cache_destroy(packet_task_cache);
-
- if (eth1394_ud) {
- csr1212_release_keyval(eth1394_ud);
- }
}
module_init(ether1394_init_module);
#ifndef __ETH1394_H
#define __ETH1394_H
+#include <linux/netdevice.h>
+
#include "ieee1394.h"
/* Register for incoming packets. This is 4096 bytes, which supports up to
#include "highlevel.h"
#include "nodemgr.h"
#include "csr.h"
+#include "config_roms.h"
static void delayed_reset_bus(unsigned long __reset_info)
* Return Value: a pointer to the &hpsb_host if succesful, %NULL if
* no memory was available.
*/
+static DECLARE_MUTEX(host_num_alloc);
struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
struct device *dev)
h->topology_map = h->csr.topology_map + 3;
h->speed_map = (u8 *)(h->csr.speed_map + 2);
- while (1) {
- if (!nodemgr_for_each_host(&hostnum, alloc_hostnum_cb)) {
- h->id = hostnum;
- break;
- }
+ down(&host_num_alloc);
+ while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb))
hostnum++;
- }
+
+ h->id = hostnum;
memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
h->device.parent = dev;
class_device_register(&h->class_dev);
get_device(&h->device);
+ up(&host_num_alloc);
+
return h;
}
-void hpsb_add_host(struct hpsb_host *host)
+int hpsb_add_host(struct hpsb_host *host)
{
- highlevel_add_host(host);
+ if (hpsb_default_host_entry(host))
+ return -ENOMEM;
+
+ hpsb_add_extra_config_roms(host);
+
+ highlevel_add_host(host);
+
+ return 0;
}
void hpsb_remove_host(struct hpsb_host *host)
highlevel_remove_host(host);
+ hpsb_remove_extra_config_roms(host);
+
class_device_unregister(&host->class_dev);
device_unregister(&host->device);
}
int update_config_rom;
struct timer_list delayed_reset;
+ unsigned int config_roms;
+
struct list_head addr_space;
};
struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
struct device *dev);
-void hpsb_add_host(struct hpsb_host *host);
+int hpsb_add_host(struct hpsb_host *host);
void hpsb_remove_host(struct hpsb_host *h);
/* The following 2 functions are deprecated and will be removed when the
#define ACK_BUSY_X 0x4
#define ACK_BUSY_A 0x5
#define ACK_BUSY_B 0x6
+#define ACK_TARDY 0xb
+#define ACK_CONFLICT_ERROR 0xc
#define ACK_DATA_ERROR 0xd
#define ACK_TYPE_ERROR 0xe
+#define ACK_ADDRESS_ERROR 0xf
/* Non-standard "ACK codes" for internal use */
#define ACKX_NONE (-1)
#include "nodemgr.h"
#include "dma.h"
#include "iso.h"
+#include "config_roms.h"
/*
* Disable the nodemgr detection and config rom reading functionality.
void hpsb_set_packet_complete_task(struct hpsb_packet *packet,
void (*routine)(void *), void *data)
{
- BUG_ON(packet->complete_routine != NULL);
+ WARN_ON(packet->complete_routine != NULL);
packet->complete_routine = routine;
packet->complete_data = data;
return;
*/
struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
{
- struct hpsb_packet *packet = NULL;
- void *data = NULL;
-
- packet = kmem_cache_alloc(hpsb_packet_cache, GFP_ATOMIC);
- if (packet == NULL)
- return NULL;
-
- memset(packet, 0, sizeof(struct hpsb_packet));
- packet->header = packet->embedded_header;
-
- if (data_size) {
- data = kmalloc(data_size + 8, GFP_ATOMIC);
- if (data == NULL) {
+ struct hpsb_packet *packet = NULL;
+ void *data = NULL;
+ int gfp_flags = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
+
+ packet = kmem_cache_alloc(hpsb_packet_cache, gfp_flags);
+ if (packet == NULL)
+ return NULL;
+
+ memset(packet, 0, sizeof(*packet));
+
+ packet->header = packet->embedded_header;
+ INIT_LIST_HEAD(&packet->list);
+ packet->state = hpsb_unused;
+ packet->generation = -1;
+ atomic_set(&packet->refcnt, 1);
+
+ if (data_size) {
+ data_size = (data_size + 3) & ~3;
+ data = kmalloc(data_size + 8, gfp_flags);
+ if (data == NULL) {
kmem_cache_free(hpsb_packet_cache, packet);
- return NULL;
- }
-
- packet->data = data;
- packet->data_size = data_size;
- }
+ return NULL;
+ }
- INIT_LIST_HEAD(&packet->list);
- packet->complete_routine = NULL;
- packet->complete_data = NULL;
- packet->state = hpsb_unused;
- packet->generation = -1;
+ packet->data = data;
+ packet->data_size = data_size;
+ }
- return packet;
+ return packet;
}
* hpsb_free_packet - free packet and data associated with it
* @packet: packet to free (is NULL safe)
*
- * This function will free packet->data, packet->header and finally the packet
- * itself.
+ * This function will free packet->data and finally the packet itself.
*/
void hpsb_free_packet(struct hpsb_packet *packet)
{
- if (!packet) return;
-
- kfree(packet->data);
- kmem_cache_free(hpsb_packet_cache, packet);
+ if (packet && atomic_dec_and_test(&packet->refcnt)) {
+ kfree(packet->data);
+ kmem_cache_free(hpsb_packet_cache, packet);
+ }
}
void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
int ackcode)
{
- unsigned long flags;
-
- packet->ack_code = ackcode;
+ packet->ack_code = ackcode;
- if (packet->no_waiter) {
- /* must not have a tlabel allocated */
- hpsb_free_packet(packet);
- return;
- }
+ if (packet->no_waiter) {
+ /* must not have a tlabel allocated */
+ hpsb_free_packet(packet);
+ return;
+ }
- if (ackcode != ACK_PENDING || !packet->expect_response) {
- packet->state = hpsb_complete;
- queue_packet_complete(packet);
- return;
- }
+ if (ackcode != ACK_PENDING || !packet->expect_response) {
+ atomic_dec(&packet->refcnt);
+ list_del(&packet->list);
+ packet->state = hpsb_complete;
+ queue_packet_complete(packet);
+ return;
+ }
- packet->state = hpsb_pending;
- packet->sendtime = jiffies;
+ if (packet->state == hpsb_complete) {
+ hpsb_free_packet(packet);
+ return;
+ }
- spin_lock_irqsave(&host->pending_pkt_lock, flags);
- list_add_tail(&packet->list, &host->pending_packets);
- spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
+ atomic_dec(&packet->refcnt);
+ packet->state = hpsb_pending;
+ packet->sendtime = jiffies;
mod_timer(&host->timeout, jiffies + host->timeout_interval);
}
*/
int hpsb_send_packet(struct hpsb_packet *packet)
{
- struct hpsb_host *host = packet->host;
+ struct hpsb_host *host = packet->host;
if (host->is_shutdown)
return -EINVAL;
packet->state = hpsb_queued;
+ if (!packet->no_waiter || packet->expect_response) {
+ unsigned long flags;
+
+ atomic_inc(&packet->refcnt);
+ spin_lock_irqsave(&host->pending_pkt_lock, flags);
+ list_add_tail(&packet->list, &host->pending_packets);
+ spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
+ }
+
if (packet->node_id == host->node_id)
{ /* it is a local request, so handle it locally */
quadlet_t *data;
break;
}
- packet->state = hpsb_complete;
+ if (packet->state == hpsb_queued) {
+ packet->sendtime = jiffies;
+ packet->ack_code = ACK_PENDING;
+ }
+
+ packet->state = hpsb_complete;
queue_packet_complete(packet);
}
complete_and_exit(&khpsbpkt_complete, 0);
}
+
static int __init ieee1394_init(void)
{
int i;
+ if (hpsb_init_config_roms()) {
+ HPSB_ERR("Failed to initialize some config rom entries.\n");
+ HPSB_ERR("Some features may not be available\n");
+ }
+
khpsbpkt_pid = kernel_thread(hpsbpkt_thread, NULL, CLONE_KERNEL);
if (khpsbpkt_pid < 0) {
HPSB_ERR("Failed to start hpsbpkt thread!\n");
devfs_mk_dir("ieee1394");
hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet),
- 0, 0, NULL, NULL);
+ 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
bus_register(&ieee1394_bus_type);
for (i = 0; fw_bus_attrs[i]; i++)
kmem_cache_destroy(hpsb_packet_cache);
+ hpsb_cleanup_config_roms();
+
unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
devfs_remove("ieee1394");
}
#include <linux/slab.h>
#include <linux/devfs_fs_kernel.h>
+#include <asm/atomic.h>
#include <asm/semaphore.h>
#include "hosts.h"
struct hpsb_host *host;
unsigned int generation;
+ atomic_t refcnt;
+
/* Function (and possible data to pass to it) to call when this
* packet is completed. */
void (*complete_routine)(void *);
return -EAGAIN;
}
+ case ACK_ADDRESS_ERROR:
+ return -EINVAL;
+
+ case ACK_TARDY:
+ case ACK_CONFLICT_ERROR:
case ACKX_NONE:
case ACKX_SEND_ERROR:
case ACKX_ABORTED:
if (length == 0)
return NULL;
- packet = hpsb_alloc_packet(length + (length % 4 ? 4 - (length % 4) : 0));
+ packet = hpsb_alloc_packet((length + 3) & ~3);
if (!packet)
return NULL;
if (length == 0)
return NULL;
- packet = hpsb_alloc_packet(length + (length % 4 ? 4 - (length % 4) : 0));
+ packet = hpsb_alloc_packet((length + 3) & ~3);
if (!packet)
return NULL;
if (length == 0)
return NULL;
- packet = hpsb_alloc_packet(length + (length % 4 ? 4 - (length % 4) : 0));
+ packet = hpsb_alloc_packet((length + 3) & ~3);
if (!packet)
return NULL;
static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci)
{
- return (bus_info_data[2] >> 8) & 0x3;
+ return (CSR1212_BE32_TO_CPU(bus_info_data[2]) >> 8) & 0x3;
}
static struct csr1212_bus_ops nodemgr_csr_ops = {
}
-static void nodemgr_ud_update_pdrv(struct unit_directory *ud)
+static void nodemgr_update_pdrv(struct node_entry *ne)
{
- struct device *dev;
+ struct unit_directory *ud;
struct hpsb_protocol_driver *pdrv;
+ struct class *class = &nodemgr_ud_class;
+ struct class_device *cdev;
- if (!get_device(&ud->device))
- return;
-
- list_for_each_entry(dev, &ud->device.children, node)
- nodemgr_ud_update_pdrv(container_of(dev, struct unit_directory, device));
+ down_read(&class->subsys.rwsem);
+ list_for_each_entry(cdev, &class->children, node) {
+ ud = container_of(cdev, struct unit_directory, class_dev);
+ if (ud->ne != ne || !ud->device.driver)
+ continue;
- if (ud->device.driver) {
pdrv = container_of(ud->device.driver, struct hpsb_protocol_driver, driver);
if (pdrv->update && pdrv->update(ud)) {
up_write(&ud->device.bus->subsys.rwsem);
}
}
-
- put_device(&ud->device);
+ up_read(&class->subsys.rwsem);
}
static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation)
{
- struct device *dev, *udev;
+ struct device *dev;
if (ne->host != hi->host || ne->in_limbo)
return;
if (ne->needs_probe)
nodemgr_process_root_directory(hi, ne);
else if (ne->generation == generation)
- list_for_each_entry(udev, &dev->children, node)
- nodemgr_ud_update_pdrv(container_of(udev, struct unit_directory, device));
+ nodemgr_update_pdrv(ne);
else
nodemgr_suspend_ne(ne);
#endif
#ifdef OHCI1394_DEBUG
-#define DBGMSG(card, fmt, args...) \
-printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
+#define DBGMSG(fmt, args...) \
+printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
#else
-#define DBGMSG(card, fmt, args...)
+#define DBGMSG(fmt, args...)
#endif
#ifdef CONFIG_IEEE1394_OHCI_DMA_DEBUG
printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
/* print card specific information */
-#define PRINT(level, card, fmt, args...) \
-printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
+#define PRINT(level, fmt, args...) \
+printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
static char version[] __devinitdata =
- "$Rev: 1131 $ Ben Collins <bcollins@debian.org>";
+ "$Rev: 1172 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */
static int phys_dma = 1;
r = reg_read(ohci, OHCI1394_PhyControl);
if (i >= OHCI_LOOP_COUNT)
- PRINT (KERN_ERR, ohci->id, "Get PHY Reg timeout [0x%08x/0x%08x/%d]",
+ PRINT (KERN_ERR, "Get PHY Reg timeout [0x%08x/0x%08x/%d]",
r, r & 0x80000000, i);
spin_unlock_irqrestore (&ohci->phy_reg_lock, flags);
}
if (i == OHCI_LOOP_COUNT)
- PRINT (KERN_ERR, ohci->id, "Set PHY Reg timeout [0x%08x/0x%08x/%d]",
+ PRINT (KERN_ERR, "Set PHY Reg timeout [0x%08x/0x%08x/%d]",
r, r & 0x00004000, i);
spin_unlock_irqrestore (&ohci->phy_reg_lock, flags);
if ((self_id_count & 0x80000000) ||
((self_id_count & 0x00FF0000) != (q0 & 0x00FF0000))) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"Error in reception of SelfID packets [0x%08x/0x%08x] (count: %d)",
self_id_count, q0, ohci->self_id_errors);
set_phy_reg_mask (ohci, 1, 0x40);
ohci->self_id_errors++;
} else {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"Too many errors on SelfID error reception, giving up!");
}
return;
}
if (q0 == ~q1) {
- DBGMSG (ohci->id, "SelfID packet 0x%x received", q0);
+ DBGMSG ("SelfID packet 0x%x received", q0);
hpsb_selfid_received(host, cpu_to_be32(q0));
if (((q0 & 0x3f000000) >> 24) == phyid)
- DBGMSG (ohci->id, "SelfID for this node is 0x%08x", q0);
+ DBGMSG ("SelfID for this node is 0x%08x", q0);
} else {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"SelfID is inconsistent [0x%08x/0x%08x]", q0, q1);
}
q += 2;
size -= 2;
}
- DBGMSG(ohci->id, "SelfID complete");
+ DBGMSG("SelfID complete");
return;
}
break;
mdelay(1);
}
- DBGMSG (ohci->id, "Soft reset finished");
+ DBGMSG ("Soft reset finished");
}
static int run_context(struct ti_ohci *ohci, int reg, char *msg)
/* check that the node id is valid */
nodeId = reg_read(ohci, OHCI1394_NodeID);
if (!(nodeId&0x80000000)) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"Running dma failed because Node ID is not valid");
return -1;
}
/* check that the node number != 63 */
if ((nodeId&0x3f)==63) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"Running dma failed because Node ID == 63");
return -1;
}
/* Run the dma context */
reg_write(ohci, reg, 0x8000);
- if (msg) PRINT(KERN_DEBUG, ohci->id, "%s", msg);
+ if (msg) PRINT(KERN_DEBUG, "%s", msg);
return 0;
}
/* Run context */
reg_write(ohci, d->ctrlSet, 0x00008000);
- DBGMSG(ohci->id, "Receive DMA ctx=%d initialized", d->ctx);
+ DBGMSG("Receive DMA ctx=%d initialized", d->ctx);
}
/* Initialize the dma transmit context */
reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << d->ctx);
}
- DBGMSG(ohci->id, "Transmit DMA ctx=%d initialized", d->ctx);
+ DBGMSG("Transmit DMA ctx=%d initialized", d->ctx);
}
/* Count the number of available iso contexts */
reg_write(ohci, reg, 0xffffffff);
tmp = reg_read(ohci, reg);
- DBGMSG(ohci->id,"Iso contexts reg: %08x implemented: %08x", reg, tmp);
+ DBGMSG("Iso contexts reg: %08x implemented: %08x", reg, tmp);
/* Count the number of contexts */
for (i=0; i<32; i++) {
#else
sprintf (irq_buf, "%s", __irq_itoa(ohci->dev->irq));
#endif
- PRINT(KERN_INFO, ohci->id, "OHCI-1394 %d.%d (PCI): IRQ=[%s] "
+ PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%s] "
"MMIO=[%lx-%lx] Max Packet=[%d]",
((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10),
((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), irq_buf,
u32 cycleTimer;
int idx = d->prg_ind;
- DBGMSG(ohci->id, "Inserting packet for node " NODE_BUS_FMT
+ DBGMSG("Inserting packet for node " NODE_BUS_FMT
", tlabel=%d, tcode=0x%x, speed=%d",
NODE_BUS_ARGS(ohci->host, packet->node_id), packet->tlabel,
packet->tcode, packet->speed_code);
(((((cycleTimer>>25)&0x7)+1)&0x7)<<13) |
((cycleTimer&0x01fff000)>>12));
- DBGMSG(ohci->id, "cycleTimer: %08x timeStamp: %08x",
+ DBGMSG("cycleTimer: %08x timeStamp: %08x",
cycleTimer, d->prg_cpu[idx]->begin.status);
} else
d->prg_cpu[idx]->begin.status = 0;
if (cross_bound((unsigned long)packet->data,
packet->data_size)>0) {
/* FIXME: do something about it */
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"%s: packet data addr: %p size %Zd bytes "
"cross page boundary", __FUNCTION__,
packet->data, packet->data_size);
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"
+ DBGMSG("Iso xmit context info: header[%08x %08x]\n"
" begin=%08x %08x %08x %08x\n"
" %08x %08x %08x %08x\n"
" end =%08x %08x %08x %08x",
}
if (d->free_prgs == 0)
- DBGMSG(ohci->id, "Transmit DMA FIFO ctx=%d is full... waiting", d->ctx);
+ DBGMSG("Transmit DMA FIFO ctx=%d is full... waiting", d->ctx);
/* Is the context running ? (should be unless it is
the first packet to be sent in this context) */
if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) {
- DBGMSG(ohci->id,"Starting transmit DMA ctx=%d",d->ctx);
+ DBGMSG("Starting transmit DMA ctx=%d",d->ctx);
reg_write(ohci, d->cmdPtr, d->prg_bus[idx]|z);
run_context(ohci, d->ctrlSet, NULL);
}
else {
/* Wake up the dma context if necessary */
if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
- DBGMSG(ohci->id,"Waking transmit DMA ctx=%d",d->ctx);
+ DBGMSG("Waking transmit DMA ctx=%d",d->ctx);
}
/* do this always, to avoid race condition */
unsigned long flags;
if (packet->data_size > ohci->max_packet_size) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"Transmit packet size %Zd is too big",
packet->data_size);
return -EOVERFLOW;
if (ohci->it_legacy_context.ohci == NULL) {
if (in_interrupt()) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"legacy IT context cannot be initialized during interrupt");
return -EINVAL;
}
if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context,
DMA_CTX_ISO, 0, IT_NUM_DESC,
OHCI1394_IsoXmitContextBase) < 0) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"error initializing legacy IT context");
return -ENOMEM;
}
break;
case SET_BUS_ID:
- PRINT(KERN_ERR, ohci->id, "devctl command SET_BUS_ID err");
+ PRINT(KERN_ERR, "devctl command SET_BUS_ID err");
break;
case ACT_CYCLE_MASTER:
/*
* enable cycleTimer, cycleMaster
*/
- DBGMSG(ohci->id, "Cycle master enabled");
+ DBGMSG("Cycle master enabled");
reg_write(ohci, OHCI1394_LinkControlSet,
OHCI1394_LinkControl_CycleTimerEnable |
OHCI1394_LinkControl_CycleMaster);
break;
case CANCEL_REQUESTS:
- DBGMSG(ohci->id, "Cancel request received");
+ DBGMSG("Cancel request received");
dma_trm_reset(&ohci->at_req_context);
dma_trm_reset(&ohci->at_resp_context);
break;
u64 mask;
if (arg<0 || arg>63) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"%s: IS0 listen channel %d is out of range",
__FUNCTION__, arg);
return -EFAULT;
DMA_CTX_ISO, 0, IR_NUM_DESC,
IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
OHCI1394_IsoRcvContextBase) < 0) {
- PRINT(KERN_ERR, ohci->id, "%s: failed to allocate an IR context",
+ PRINT(KERN_ERR, "%s: failed to allocate an IR context",
__FUNCTION__);
return -ENOMEM;
}
ohci->ir_legacy_channels = 0;
initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
- DBGMSG(ohci->id, "ISO receive legacy context activated");
+ DBGMSG("ISO receive legacy context activated");
}
mask = (u64)0x1<<arg;
spin_lock_irqsave(&ohci->IR_channel_lock, flags);
if (ohci->ISO_channel_usage & mask) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"%s: IS0 listen channel %d is already used",
__FUNCTION__, arg);
spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
1<<arg);
spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
- DBGMSG(ohci->id, "Listening enabled on channel %d", arg);
+ DBGMSG("Listening enabled on channel %d", arg);
break;
}
case ISO_UNLISTEN_CHANNEL:
u64 mask;
if (arg<0 || arg>63) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"%s: IS0 unlisten channel %d is out of range",
__FUNCTION__, arg);
return -EFAULT;
spin_lock_irqsave(&ohci->IR_channel_lock, flags);
if (!(ohci->ISO_channel_usage & mask)) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"%s: IS0 unlisten channel %d is not used",
__FUNCTION__, arg);
spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
1<<arg);
spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
- DBGMSG(ohci->id, "Listening disabled on channel %d", arg);
+ DBGMSG("Listening disabled on channel %d", arg);
if (ohci->ir_legacy_channels == 0) {
stop_dma_rcv_ctx(&ohci->ir_legacy_context);
free_dma_rcv_ctx(&ohci->ir_legacy_context);
- DBGMSG(ohci->id, "ISO receive legacy context deactivated");
+ DBGMSG("ISO receive legacy context deactivated");
}
break;
}
/* one block per page of data in the DMA buffer, minus the final guard page */
recv->nblocks = iso->buf_size/PAGE_SIZE - 1;
if (recv->nblocks < 3) {
- DBGMSG(ohci->id, "ohci_iso_recv_init: DMA buffer too small");
+ DBGMSG("ohci_iso_recv_init: DMA buffer too small");
goto err;
}
if (recv->buf_stride*iso->buf_packets > iso->buf_size ||
recv->buf_stride > PAGE_SIZE) {
/* this shouldn't happen, but anyway... */
- DBGMSG(ohci->id, "ohci_iso_recv_init: problem choosing a buffer stride");
+ DBGMSG("ohci_iso_recv_init: problem choosing a buffer stride");
goto err;
}
}
/* write the DMA program */
ohci_iso_recv_program(iso);
- DBGMSG(ohci->id, "ohci_iso_recv_init: %s mode, DMA buffer is %lu pages"
+ DBGMSG("ohci_iso_recv_init: %s mode, DMA buffer is %lu pages"
" (%u bytes), using %u blocks, buf_stride %u, block_irq_interval %d",
recv->dma_mode == BUFFER_FILL_MODE ?
"buffer-fill" : "packet-per-buffer",
static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
{
struct ohci_iso_recv *recv = iso->hostdata;
+ struct ti_ohci *ohci = recv->ohci;
u32 command, contextMatch;
reg_write(recv->ohci, recv->ContextControlClear, 0xFFFFFFFF);
/* check RUN */
if (!(reg_read(recv->ohci, recv->ContextControlSet) & 0x8000)) {
- PRINT(KERN_ERR, recv->ohci->id,
+ PRINT(KERN_ERR,
"Error starting IR DMA (ContextControl 0x%08x)\n",
reg_read(recv->ohci, recv->ContextControlSet));
return -1;
{
int wake = 0;
int runaway = 0;
+ struct ti_ohci *ohci = recv->ohci;
while (1) {
/* we expect the next parsable packet to begin at recv->dma_offset */
/* don't loop indefinitely */
if (runaway++ > 100000) {
atomic_inc(&iso->overflows);
- PRINT(KERN_ERR, recv->ohci->id,
+ PRINT(KERN_ERR,
"IR DMA error - Runaway during buffer parsing!\n");
break;
}
len = p[recv->dma_offset+2] | (p[recv->dma_offset+3] << 8);
if (len > 4096) {
- PRINT(KERN_ERR, recv->ohci->id,
+ PRINT(KERN_ERR,
"IR DMA error - bogus 'len' value %u\n", len);
}
static void ohci_iso_recv_bufferfill_task(struct hpsb_iso *iso, struct ohci_iso_recv *recv)
{
int loop;
+ struct ti_ohci *ohci = recv->ohci;
/* loop over all blocks */
for (loop = 0; loop < recv->nblocks; loop++) {
if (event != 0x11) {
atomic_inc(&iso->overflows);
- PRINT(KERN_ERR, recv->ohci->id,
+ PRINT(KERN_ERR,
"IR DMA error - OHCI error code 0x%02x\n", event);
}
if ((recv->block_dma+1) % recv->nblocks == recv->block_reader) {
atomic_inc(&iso->overflows);
- DBGMSG(recv->ohci->id, "ISO reception overflow - "
+ DBGMSG("ISO reception overflow - "
"ran out of DMA blocks");
}
}
{
int count;
int wake = 0;
+ struct ti_ohci *ohci = recv->ohci;
/* loop over the entire buffer */
for (count = 0; count < recv->nblocks; count++) {
packet_len = recv->buf_stride - rescount;
} else if (event == 0x02) {
- PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - packet too long for buffer\n");
+ PRINT(KERN_ERR, "IR DMA error - packet too long for buffer\n");
} else if (event) {
- PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - OHCI error code 0x%02x\n", event);
+ PRINT(KERN_ERR, "IR DMA error - OHCI error code 0x%02x\n", event);
}
/* sync our view of the buffer */
static void ohci_iso_xmit_stop(struct hpsb_iso *iso)
{
struct ohci_iso_xmit *xmit = iso->hostdata;
+ struct ti_ohci *ohci = xmit->ohci;
/* disable interrupts */
reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskClear, 1 << xmit->task.context);
/* halt DMA */
if (ohci1394_stop_context(xmit->ohci, xmit->ContextControlClear, NULL)) {
/* XXX the DMA context will lock up if you try to send too much data! */
- PRINT(KERN_ERR, xmit->ohci->id,
+ PRINT(KERN_ERR,
"you probably exceeded the OHCI card's bandwidth limit - "
"reload the module and reduce xmit bandwidth");
}
{
struct hpsb_iso *iso = (struct hpsb_iso*) data;
struct ohci_iso_xmit *xmit = iso->hostdata;
+ struct ti_ohci *ohci = xmit->ohci;
int wake = 0;
int count;
}
if (event != 0x11)
- PRINT(KERN_ERR, xmit->ohci->id,
+ PRINT(KERN_ERR,
"IT DMA error - OHCI error code 0x%02x\n", event);
/* at least one packet went out, so wake up the writer */
static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info)
{
struct ohci_iso_xmit *xmit = iso->hostdata;
+ struct ti_ohci *ohci = xmit->ohci;
int next_i, prev_i;
struct iso_xmit_cmd *next, *prev;
/* check that the packet doesn't cross a page boundary
(we could allow this if we added OUTPUT_MORE descriptor support) */
if (cross_bound(info->offset, info->len)) {
- PRINT(KERN_ERR, xmit->ohci->id,
+ PRINT(KERN_ERR,
"rawiso xmit: packet %u crosses a page boundary",
iso->first_packet);
return -EINVAL;
static int ohci_iso_xmit_start(struct hpsb_iso *iso, int cycle)
{
struct ohci_iso_xmit *xmit = iso->hostdata;
+ struct ti_ohci *ohci = xmit->ohci;
/* clear out the control register */
reg_write(xmit->ohci, xmit->ContextControlClear, 0xFFFFFFFF);
/* check the RUN bit */
if (!(reg_read(xmit->ohci, xmit->ContextControlSet) & 0x8000)) {
- PRINT(KERN_ERR, xmit->ohci->id, "Error starting IT DMA (ContextControl 0x%08x)\n",
+ PRINT(KERN_ERR, "Error starting IT DMA (ContextControl 0x%08x)\n",
reg_read(xmit->ohci, xmit->ContextControlSet));
return -1;
}
{
unsigned long flags;
LIST_HEAD(packet_list);
+ struct ti_ohci *ohci = d->ohci;
- ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
+ ohci1394_stop_context(ohci, d->ctrlClear, NULL);
/* Lock the context, reset it and release it. Move the packets
* that were pending in the context to packet_list and free
while (!list_empty(&packet_list)) {
struct hpsb_packet *p = driver_packet(packet_list.next);
- PRINT(KERN_INFO, d->ohci->id,
+ PRINT(KERN_INFO,
"AT dma reset ctx=%d, aborting transmission", d->ctx);
list_del(&p->driver_list);
- hpsb_packet_sent(d->ohci->host, p, ACKX_ABORTED);
+ hpsb_packet_sent(ohci->host, p, ACKX_ABORTED);
}
}
* we just return, and clean up in the ohci1394_pci_remove
* function. */
if (event == ~(u32) 0) {
- DBGMSG(ohci->id, "Device removed.");
+ DBGMSG("Device removed.");
return IRQ_NONE;
}
- DBGMSG(ohci->id, "IntEvent: %08x", event);
+ DBGMSG("IntEvent: %08x", event);
if (event & OHCI1394_unrecoverableError) {
int ctx;
- PRINT(KERN_ERR, ohci->id, "Unrecoverable error!");
+ PRINT(KERN_ERR, "Unrecoverable error!");
if (reg_read(ohci, OHCI1394_AsReqTrContextControlSet) & 0x800)
- PRINT(KERN_ERR, ohci->id, "Async Req Tx Context died: "
+ PRINT(KERN_ERR, "Async Req Tx Context died: "
"ctrl[%08x] cmdptr[%08x]",
reg_read(ohci, OHCI1394_AsReqTrContextControlSet),
reg_read(ohci, OHCI1394_AsReqTrCommandPtr));
if (reg_read(ohci, OHCI1394_AsRspTrContextControlSet) & 0x800)
- PRINT(KERN_ERR, ohci->id, "Async Rsp Tx Context died: "
+ PRINT(KERN_ERR, "Async Rsp Tx Context died: "
"ctrl[%08x] cmdptr[%08x]",
reg_read(ohci, OHCI1394_AsRspTrContextControlSet),
reg_read(ohci, OHCI1394_AsRspTrCommandPtr));
if (reg_read(ohci, OHCI1394_AsReqRcvContextControlSet) & 0x800)
- PRINT(KERN_ERR, ohci->id, "Async Req Rcv Context died: "
+ PRINT(KERN_ERR, "Async Req Rcv Context died: "
"ctrl[%08x] cmdptr[%08x]",
reg_read(ohci, OHCI1394_AsReqRcvContextControlSet),
reg_read(ohci, OHCI1394_AsReqRcvCommandPtr));
if (reg_read(ohci, OHCI1394_AsRspRcvContextControlSet) & 0x800)
- PRINT(KERN_ERR, ohci->id, "Async Rsp Rcv Context died: "
+ PRINT(KERN_ERR, "Async Rsp Rcv Context died: "
"ctrl[%08x] cmdptr[%08x]",
reg_read(ohci, OHCI1394_AsRspRcvContextControlSet),
reg_read(ohci, OHCI1394_AsRspRcvCommandPtr));
for (ctx = 0; ctx < ohci->nb_iso_xmit_ctx; ctx++) {
if (reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)) & 0x800)
- PRINT(KERN_ERR, ohci->id, "Iso Xmit %d Context died: "
+ PRINT(KERN_ERR, "Iso Xmit %d Context died: "
"ctrl[%08x] cmdptr[%08x]", ctx,
reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)),
reg_read(ohci, OHCI1394_IsoXmitCommandPtr + (16 * ctx)));
for (ctx = 0; ctx < ohci->nb_iso_rcv_ctx; ctx++) {
if (reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)) & 0x800)
- PRINT(KERN_ERR, ohci->id, "Iso Recv %d Context died: "
+ PRINT(KERN_ERR, "Iso Recv %d Context died: "
"ctrl[%08x] cmdptr[%08x] match[%08x]", ctx,
reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)),
reg_read(ohci, OHCI1394_IsoRcvCommandPtr + (32 * ctx)),
/* We subscribe to the cycleInconsistent event only to
* clear the corresponding event bit... otherwise,
* isochronous cycleMatch DMA won't work. */
- DBGMSG(ohci->id, "OHCI1394_cycleInconsistent");
+ DBGMSG("OHCI1394_cycleInconsistent");
event &= ~OHCI1394_cycleInconsistent;
}
* to solve this problem. This mainly effects nForce2. */
if (loop_count > 10000) {
ohci_devctl(host, RESET_BUS, LONG_RESET);
- DBGMSG(ohci->id, "Detected bus-reset loop. Forced a bus reset!");
+ DBGMSG("Detected bus-reset loop. Forced a bus reset!");
loop_count = 0;
}
}
spin_unlock_irqrestore(&ohci->event_lock, flags);
if (!host->in_bus_reset) {
- DBGMSG(ohci->id, "irq_handler: Bus reset requested");
+ DBGMSG("irq_handler: Bus reset requested");
/* Subsystem call */
hpsb_bus_reset(ohci->host);
event &= ~OHCI1394_busReset;
}
- /* XXX: We need a way to also queue the OHCI1394_reqTxComplete,
- * but for right now we simply run it upon reception, to make sure
- * we get sent acks before response packets. This sucks mainly
- * because it halts the interrupt handler. */
if (event & OHCI1394_reqTxComplete) {
struct dma_trm_ctx *d = &ohci->at_req_context;
- DBGMSG(ohci->id, "Got reqTxComplete interrupt "
+ DBGMSG("Got reqTxComplete interrupt "
"status=0x%08X", reg_read(ohci, d->ctrlSet));
if (reg_read(ohci, d->ctrlSet) & 0x800)
ohci1394_stop_context(ohci, d->ctrlClear,
"reqTxComplete");
else
- dma_trm_tasklet ((unsigned long)d);
+ tasklet_schedule(&d->task);
event &= ~OHCI1394_reqTxComplete;
}
if (event & OHCI1394_respTxComplete) {
struct dma_trm_ctx *d = &ohci->at_resp_context;
- DBGMSG(ohci->id, "Got respTxComplete interrupt "
+ DBGMSG("Got respTxComplete interrupt "
"status=0x%08X", reg_read(ohci, d->ctrlSet));
if (reg_read(ohci, d->ctrlSet) & 0x800)
ohci1394_stop_context(ohci, d->ctrlClear,
}
if (event & OHCI1394_RQPkt) {
struct dma_rcv_ctx *d = &ohci->ar_req_context;
- DBGMSG(ohci->id, "Got RQPkt interrupt status=0x%08X",
+ DBGMSG("Got RQPkt interrupt status=0x%08X",
reg_read(ohci, d->ctrlSet));
if (reg_read(ohci, d->ctrlSet) & 0x800)
ohci1394_stop_context(ohci, d->ctrlClear, "RQPkt");
}
if (event & OHCI1394_RSPkt) {
struct dma_rcv_ctx *d = &ohci->ar_resp_context;
- DBGMSG(ohci->id, "Got RSPkt interrupt status=0x%08X",
+ DBGMSG("Got RSPkt interrupt status=0x%08X",
reg_read(ohci, d->ctrlSet));
if (reg_read(ohci, d->ctrlSet) & 0x800)
ohci1394_stop_context(ohci, d->ctrlClear, "RSPkt");
node_id = reg_read(ohci, OHCI1394_NodeID);
if (!(node_id & 0x80000000)) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"SelfID received, but NodeID invalid "
"(probably new bus reset occurred): %08X",
node_id);
phyid = node_id & 0x0000003f;
isroot = (node_id & 0x40000000) != 0;
- DBGMSG(ohci->id,
- "SelfID interrupt received "
+ DBGMSG("SelfID interrupt received "
"(phyid %d, %s)", phyid,
(isroot ? "root" : "not root"));
reg_write(ohci,OHCI1394_PhyReqFilterLoSet, 0x00000000);
}
- DBGMSG(ohci->id, "PhyReqFilter=%08x%08x",
+ DBGMSG("PhyReqFilter=%08x%08x",
reg_read(ohci,OHCI1394_PhyReqFilterHiSet),
reg_read(ohci,OHCI1394_PhyReqFilterLoSet));
hpsb_selfid_complete(host, phyid, isroot);
} else
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"SelfID received outside of bus reset sequence");
selfid_not_valid:
/* Make sure we handle everything, just in case we accidentally
* enabled an interrupt that we didn't write a handler for. */
if (event)
- PRINT(KERN_ERR, ohci->id, "Unhandled interrupt(s) 0x%08x",
+ PRINT(KERN_ERR, "Unhandled interrupt(s) 0x%08x",
event);
return IRQ_HANDLED;
static void insert_dma_buffer(struct dma_rcv_ctx *d, int idx)
{
struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
- DBGMSG(ohci->id, "Inserting dma buf ctx=%d idx=%d", d->ctx, idx);
+ DBGMSG("Inserting dma buf ctx=%d idx=%d", d->ctx, idx);
d->prg_cpu[idx]->status = cpu_to_le32(d->buf_size);
d->prg_cpu[idx]->branchAddress &= le32_to_cpu(0xfffffff0);
/* wake up the dma context if necessary */
if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
- PRINT(KERN_INFO, ohci->id,
+ PRINT(KERN_INFO,
"Waking dma ctx=%d ... processing is probably too slow",
d->ctx);
}
* over more than one descriptor. The next case is where
* it's all in the first descriptor. */
if ((offset + length) > d->buf_size) {
- DBGMSG(ohci->id,"Split packet rcv'd");
+ DBGMSG("Split packet rcv'd");
if (length > d->split_buf_size) {
ohci1394_stop_context(ohci, d->ctrlClear,
"Split packet size exceeded");
/* Other part of packet not written yet.
* this should never happen I think
* anyway we'll get it on the next call. */
- PRINT(KERN_INFO, ohci->id,
+ PRINT(KERN_INFO,
"Got only half a packet!");
d->buf_ind = idx;
d->buf_offset = offset;
buf_ptr += offset/4;
}
} else {
- DBGMSG(ohci->id,"Single packet rcv'd");
+ DBGMSG("Single packet rcv'd");
memcpy(d->spb, buf_ptr, length);
offset += length;
buf_ptr += length/4;
if (tcode != OHCI1394_TCODE_PHY) {
if (!ohci->no_swap_incoming)
packet_swab(d->spb, tcode);
- DBGMSG(ohci->id, "Packet received from node"
+ DBGMSG("Packet received from node"
" %d ack=0x%02X spd=%d tcode=0x%X"
" length=%d ctx=%d tlabel=%d",
(d->spb[1]>>16)&0x3f,
}
#ifdef OHCI1394_DEBUG
else
- PRINT (KERN_DEBUG, ohci->id, "Got phy packet ctx=%d ... discarded",
+ PRINT (KERN_DEBUG, "Got phy packet ctx=%d ... discarded",
d->ctx);
#endif
#ifdef OHCI1394_DEBUG
if (datasize)
if (((le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf) == 0xa)
- DBGMSG(ohci->id,
- "Stream packet sent to channel %d tcode=0x%X "
+ DBGMSG("Stream packet sent to channel %d tcode=0x%X "
"ack=0x%X spd=%d dataLength=%d ctx=%d",
(le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>8)&0x3f,
(le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf,
le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])>>16,
d->ctx);
else
- DBGMSG(ohci->id,
- "Packet sent to node %d tcode=0x%X tLabel="
+ DBGMSG("Packet sent to node %d tcode=0x%X tLabel="
"0x%02X ack=0x%X spd=%d dataLength=%d ctx=%d",
(le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])>>16)&0x3f,
(le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf,
le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3])>>16,
d->ctx);
else
- DBGMSG(ohci->id,
- "Packet sent to node %d tcode=0x%X tLabel="
+ DBGMSG("Packet sent to node %d tcode=0x%X tLabel="
"0x%02X ack=0x%X spd=%d data=0x%08X ctx=%d",
(le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])
>>16)&0x3f,
case EVT_NO_STATUS: /* that should never happen */
case EVT_RESERVED_A: /* that should never happen */
case EVT_LONG_PACKET: /* that should never happen */
- PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f);
+ PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f);
ack = ACKX_SEND_ERROR;
break;
case EVT_MISSING_ACK:
ack = ACKX_SEND_ERROR;
break;
case EVT_OVERRUN: /* that should never happen */
- PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f);
+ PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f);
ack = ACKX_SEND_ERROR;
break;
case EVT_DESCRIPTOR_READ:
ack = ACKX_SEND_ERROR;
break;
case EVT_BUS_RESET: /* that should never happen */
- PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f);
+ PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f);
ack = ACKX_SEND_ERROR;
break;
case EVT_TIMEOUT:
break;
case EVT_RESERVED_B: /* that should never happen */
case EVT_RESERVED_C: /* that should never happen */
- PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f);
+ PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f);
ack = ACKX_SEND_ERROR;
break;
case EVT_UNKNOWN:
ack = ACKX_SEND_ERROR;
break;
default:
- PRINT(KERN_ERR, ohci->id, "Unhandled OHCI evt_* error 0x%x", status & 0x1f);
+ PRINT(KERN_ERR, "Unhandled OHCI evt_* error 0x%x", status & 0x1f);
ack = ACKX_SEND_ERROR;
BUG();
}
static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
{
int i;
+ struct ti_ohci *ohci = d->ohci;
- if (d->ohci == NULL)
+ if (ohci == NULL)
return;
- DBGMSG(d->ohci->id, "Freeing dma_rcv_ctx %d", d->ctx);
+ DBGMSG("Freeing dma_rcv_ctx %d", d->ctx);
if (d->buf_cpu) {
for (i=0; i<d->num_desc; i++)
if (d->buf_cpu[i] && d->buf_bus[i]) {
pci_free_consistent(
- d->ohci->dev, d->buf_size,
+ ohci->dev, d->buf_size,
d->buf_cpu[i], d->buf_bus[i]);
OHCI_DMA_FREE("consistent dma_rcv buf[%d]", i);
}
d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL);
if (d->buf_cpu == NULL || d->buf_bus == NULL) {
- PRINT(KERN_ERR, ohci->id, "Failed to allocate dma buffer");
+ PRINT(KERN_ERR, "Failed to allocate dma buffer");
free_dma_rcv_ctx(d);
return -ENOMEM;
}
d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL);
if (d->prg_cpu == NULL || d->prg_bus == NULL) {
- PRINT(KERN_ERR, ohci->id, "Failed to allocate dma prg");
+ PRINT(KERN_ERR, "Failed to allocate dma prg");
free_dma_rcv_ctx(d);
return -ENOMEM;
}
d->spb = kmalloc(d->split_buf_size, GFP_KERNEL);
if (d->spb == NULL) {
- PRINT(KERN_ERR, ohci->id, "Failed to allocate split buffer");
+ PRINT(KERN_ERR, "Failed to allocate split buffer");
free_dma_rcv_ctx(d);
return -ENOMEM;
}
if (d->buf_cpu[i] != NULL) {
memset(d->buf_cpu[i], 0, d->buf_size);
} else {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"Failed to allocate dma buffer");
free_dma_rcv_ctx(d);
return -ENOMEM;
if (d->prg_cpu[i] != NULL) {
memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd));
} else {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"Failed to allocate dma prg");
free_dma_rcv_ctx(d);
return -ENOMEM;
dma_rcv_tasklet, (unsigned long) d);
if (ohci1394_register_iso_tasklet(ohci,
&ohci->ir_legacy_tasklet) < 0) {
- PRINT(KERN_ERR, ohci->id, "No IR DMA context available");
+ PRINT(KERN_ERR, "No IR DMA context available");
free_dma_rcv_ctx(d);
return -EBUSY;
}
static void free_dma_trm_ctx(struct dma_trm_ctx *d)
{
int i;
+ struct ti_ohci *ohci = d->ohci;
- if (d->ohci == NULL)
+ if (ohci == NULL)
return;
- DBGMSG(d->ohci->id, "Freeing dma_trm_ctx %d", d->ctx);
+ DBGMSG("Freeing dma_trm_ctx %d", d->ctx);
if (d->prg_cpu) {
for (i=0; i<d->num_desc; i++)
d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL);
if (d->prg_cpu == NULL || d->prg_bus == NULL) {
- PRINT(KERN_ERR, ohci->id, "Failed to allocate at dma prg");
+ PRINT(KERN_ERR, "Failed to allocate at dma prg");
free_dma_trm_ctx(d);
return -ENOMEM;
}
if (d->prg_cpu[i] != NULL) {
memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg));
} else {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"Failed to allocate at dma prg");
free_dma_trm_ctx(d);
return -ENOMEM;
dma_trm_tasklet, (unsigned long) d);
if (ohci1394_register_iso_tasklet(ohci,
&ohci->it_legacy_tasklet) < 0) {
- PRINT(KERN_ERR, ohci->id, "No IT DMA context available");
+ PRINT(KERN_ERR, "No IT DMA context available");
free_dma_trm_ctx(d);
return -EBUSY;
}
static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
- struct csr1212_keyval *root;
- struct csr1212_keyval *vend_id = NULL;
- struct csr1212_keyval *text = NULL;
- int ret;
-
static int version_printed = 0;
struct hpsb_host *host;
if (!host) FAIL(-ENOMEM, "Failed to allocate host structure");
ohci = host->hostdata;
- ohci->id = host->id;
ohci->dev = dev;
ohci->host = host;
ohci->init_state = OHCI_INIT_ALLOC_HOST;
* clearly says it's 2kb, so this shouldn't be a problem. */
ohci_base = pci_resource_start(dev, 0);
if (pci_resource_len(dev, 0) != OHCI1394_REGISTER_SIZE)
- PRINT(KERN_WARNING, ohci->id, "Unexpected PCI resource length of %lx!",
+ PRINT(KERN_WARNING, "Unexpected PCI resource length of %lx!",
pci_resource_len(dev, 0));
/* Seems PCMCIA handles this internally. Not sure why. Seems
if (ohci->registers == NULL)
FAIL(-ENXIO, "Failed to remap registers - card not accessible");
ohci->init_state = OHCI_INIT_HAVE_IOMAPPING;
- DBGMSG(ohci->id, "Remapped memory spaces reg 0x%p", ohci->registers);
+ DBGMSG("Remapped memory spaces reg 0x%p", ohci->registers);
/* csr_config rom allocation */
ohci->csr_config_rom_cpu =
ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER;
if ((unsigned long)ohci->selfid_buf_cpu & 0x1fff)
- PRINT(KERN_INFO, ohci->id, "SelfID buffer %p is not aligned on "
+ PRINT(KERN_INFO, "SelfID buffer %p is not aligned on "
"8Kb boundary... may cause problems on some CXD3222 chip",
ohci->selfid_buf_cpu);
/* Determine the number of available IR and IT contexts. */
ohci->nb_iso_rcv_ctx =
get_nb_iso_ctx(ohci, OHCI1394_IsoRecvIntMaskSet);
- DBGMSG(ohci->id, "%d iso receive contexts available",
+ DBGMSG("%d iso receive contexts available",
ohci->nb_iso_rcv_ctx);
ohci->nb_iso_xmit_ctx =
get_nb_iso_ctx(ohci, OHCI1394_IsoXmitIntMaskSet);
- DBGMSG(ohci->id, "%d iso transmit contexts available",
+ DBGMSG("%d iso transmit contexts available",
ohci->nb_iso_xmit_ctx);
/* Set the usage bits for non-existent contexts so they can't
ohci->init_state = OHCI_INIT_HAVE_IRQ;
ohci_initialize(ohci);
- /* Setup initial root directory entries */
- root = host->csr.rom->root_kv;
-
- vend_id = csr1212_new_immediate(CSR1212_KV_ID_VENDOR,
- reg_read(ohci, OHCI1394_GUIDHi) >> 8);
- text = csr1212_new_string_descriptor_leaf("Linux 1394 - OHCI");
-
- if (!vend_id || !text) {
- if (vend_id) {
- csr1212_release_keyval(vend_id);
- }
- if (text) {
- csr1212_release_keyval(text);
- }
- FAIL(-ENOMEM, "Failed to allocate memory for mandatory ConfigROM entries!");
- }
-
- ret = csr1212_associate_keyval(vend_id, text);
- csr1212_release_keyval(text);
- if(ret != CSR1212_SUCCESS) {
- csr1212_release_keyval(vend_id);
- FAIL(ret, "Failed to associate text descriptor to vendor id");
- }
-
- ret = csr1212_attach_keyval_to_directory(root, vend_id);
- if(ret != CSR1212_SUCCESS) {
- csr1212_release_keyval(vend_id);
- FAIL(ret, "Failed to attach vendor id to root directory");
- }
-
- host->update_config_rom = 1;
-
/* Set certain csr values */
host->csr.guid_hi = reg_read(ohci, OHCI1394_GUIDHi);
host->csr.guid_lo = reg_read(ohci, OHCI1394_GUIDLo);
host->csr.lnk_spd = reg_read(ohci, OHCI1394_BusOptions) & 0x7;
/* Tell the highlevel this host is ready */
- hpsb_add_host(host);
+ if (hpsb_add_host(host))
+ FAIL(-ENOMEM, "Failed to register host with highlevel");
+
ohci->init_state = OHCI_INIT_DONE;
return 0;
while (reg_read(ohci, reg) & 0x400) {
i++;
if (i>5000) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR,
"Runaway loop while stopping context: %s...", msg ? msg : "");
return 1;
}
mb();
udelay(10);
}
- if (msg) PRINT(KERN_ERR, ohci->id, "%s: dma prg stopped", msg);
+ if (msg) PRINT(KERN_ERR, "%s: dma prg stopped", msg);
return 0;
}
};
struct ti_ohci {
- int id; /* sequential card number */
-
struct pci_dev *dev;
enum {
return error; \
} while (0)
- struct csr1212_keyval *root;
- struct csr1212_keyval *vend_id = NULL;
- struct csr1212_keyval *text = NULL;
- int ret;
-
char irq_buf[16];
struct hpsb_host *host;
struct ti_lynx *lynx; /* shortcut to currently handled device */
else
host->csr.lnk_spd = be32_to_cpu(lynx->bus_info_block[2]) & 0x7;
- /* Setup initial root directory entries */
- root = host->csr.rom->root_kv;
-
- vend_id = csr1212_new_immediate(CSR1212_KV_ID_VENDOR,
- be32_to_cpu(lynx->bus_info_block[3]) >> 8);
- text = csr1212_new_string_descriptor_leaf("Linux 1394 - PCI-Lynx");
-
- if (!vend_id || !text) {
- if (vend_id)
- csr1212_release_keyval(vend_id);
- if (text)
- csr1212_release_keyval(text);
+ if (hpsb_add_host(host)) {
error = -ENOMEM;
- FAIL("Failed to allocate memory for mandatory ConfigROM entries!");
- }
-
- ret = csr1212_associate_keyval(vend_id, text);
- csr1212_release_keyval(text); /* no longer needed locally. */
- if(ret != CSR1212_SUCCESS) {
- csr1212_release_keyval(vend_id);
- error = ret;
- FAIL("Failed to associate text descriptor to vendor id");
- }
-
- ret = csr1212_attach_keyval_to_directory(root, vend_id);
- csr1212_release_keyval(vend_id); /* no longer needed locally. */
- if(ret != CSR1212_SUCCESS) {
- error = ret;
- FAIL("Failed to attach vendor id to root directory");
+ FAIL("Failed to register host with highlevel");
}
- host->update_config_rom = 1;
- hpsb_add_host(host);
lynx->state = is_host;
- return ret;
+ return 0;
#undef FAIL
}
#include "sbp2.h"
static char version[] __devinitdata =
- "$Rev: 1144 $ Ben Collins <bcollins@debian.org>";
+ "$Rev: 1170 $ Ben Collins <bcollins@debian.org>";
/*
* Module load parameter definitions
*/
sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
+ /* Make sure we unblock requests (since this is likely after a bus
+ * reset). */
+ scsi_unblock_requests(scsi_id->scsi_host);
+
return 0;
}
}
}
- scsi_unblock_requests(scsi_id->scsi_host);
-
return;
}
{
int i;
- DBGMSG(d->ohci->id, "Freeing dma_iso_ctx %d", d->ctx);
+ DBGMSG(d->ohci->host->id, "Freeing dma_iso_ctx %d", d->ctx);
ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
if (d->iso_tasklet.link.next != NULL)
d = kmalloc(sizeof(struct dma_iso_ctx), GFP_KERNEL);
if (d == NULL) {
- PRINT(KERN_ERR, ohci->id, "Failed to allocate dma_iso_ctx");
+ PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma_iso_ctx");
return NULL;
}
if (dma_region_alloc(&d->dma, d->num_desc * d->buf_size, ohci->dev,
PCI_DMA_BIDIRECTIONAL)) {
- PRINT(KERN_ERR, ohci->id, "Failed to allocate dma buffer");
+ PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma buffer");
free_dma_iso_ctx(d);
return NULL;
}
(unsigned long) d);
if (ohci1394_register_iso_tasklet(ohci, &d->iso_tasklet) < 0) {
- PRINT(KERN_ERR, ohci->id, "no free iso %s contexts",
+ PRINT(KERN_ERR, ohci->host->id, "no free iso %s contexts",
type == OHCI_ISO_RECEIVE ? "receive" : "transmit");
free_dma_iso_ctx(d);
return NULL;
d->prg_reg = kmalloc(d->num_desc * sizeof(struct dma_prog_region),
GFP_KERNEL);
if (d->prg_reg == NULL) {
- PRINT(KERN_ERR, ohci->id, "Failed to allocate ir prg regs");
+ PRINT(KERN_ERR, ohci->host->id, "Failed to allocate ir prg regs");
free_dma_iso_ctx(d);
return NULL;
}
GFP_KERNEL);
if (d->ir_prg == NULL) {
- PRINT(KERN_ERR, ohci->id, "Failed to allocate dma ir prg");
+ PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma ir prg");
free_dma_iso_ctx(d);
return NULL;
}
for (i = 0;i < d->num_desc; i++) {
if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd *
sizeof(struct dma_cmd), ohci->dev)) {
- PRINT(KERN_ERR, ohci->id, "Failed to allocate dma ir prg");
+ PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma ir prg");
free_dma_iso_ctx(d);
return NULL;
}
GFP_KERNEL);
if (d->it_prg == NULL) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Failed to allocate dma it prg");
free_dma_iso_ctx(d);
return NULL;
d->packet_size = packet_size;
if (PAGE_SIZE % packet_size || packet_size>4096) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Packet size %d (page_size: %ld) "
"not yet supported\n",
packet_size, PAGE_SIZE);
for (i = 0; i < d->num_desc; i++) {
if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd *
sizeof(struct it_dma_prg), ohci->dev)) {
- PRINT(KERN_ERR, ohci->id, "Failed to allocate dma it prg");
+ PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma it prg");
free_dma_iso_ctx(d);
return NULL;
}
GFP_KERNEL);
if (d->buffer_status == NULL) {
- PRINT(KERN_ERR, ohci->id, "Failed to allocate buffer_status");
+ PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_status");
free_dma_iso_ctx(d);
return NULL;
}
if (d->buffer_time == NULL) {
- PRINT(KERN_ERR, ohci->id, "Failed to allocate buffer_time");
+ PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_time");
free_dma_iso_ctx(d);
return NULL;
}
if (d->last_used_cmd == NULL) {
- PRINT(KERN_ERR, ohci->id, "Failed to allocate last_used_cmd");
+ PRINT(KERN_ERR, ohci->host->id, "Failed to allocate last_used_cmd");
free_dma_iso_ctx(d);
return NULL;
}
if (d->next_buffer == NULL) {
- PRINT(KERN_ERR, ohci->id, "Failed to allocate next_buffer");
+ PRINT(KERN_ERR, ohci->host->id, "Failed to allocate next_buffer");
free_dma_iso_ctx(d);
return NULL;
}
spin_lock_init(&d->lock);
- PRINT(KERN_INFO, ohci->id, "Iso %s DMA: %d buffers "
+ PRINT(KERN_INFO, ohci->host->id, "Iso %s DMA: %d buffers "
"of size %d allocated for a frame size %d, each with %d prgs",
(type == OHCI_ISO_RECEIVE) ? "receive" : "transmit",
d->num_desc, d->buf_size, d->frame_size, d->nb_cmd);
for (i=0; i<ISO_CHANNELS; i++) {
if (!(ohci->ISO_channel_usage & mask)) {
v.channel = i;
- PRINT(KERN_INFO, ohci->id, "Found free channel %d", i);
+ PRINT(KERN_INFO, ohci->host->id, "Found free channel %d", i);
break;
}
mask = mask << 1;
}
if (v.channel<0 || v.channel>(ISO_CHANNELS-1)) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Iso channel %d out of bounds", v.channel);
return -EFAULT;
}
(u32)(ohci->ISO_channel_usage>>32),
(u32)(ohci->ISO_channel_usage&0xffffffff));
if (ohci->ISO_channel_usage & mask) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Channel %d is already taken", v.channel);
return -EFAULT;
}
ohci->ISO_channel_usage |= mask;
if (v.buf_size == 0 || v.buf_size > VIDEO1394_MAX_SIZE) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Invalid %d length buffer requested",v.buf_size);
return -EFAULT;
}
if (v.nb_buffers == 0 || v.nb_buffers > VIDEO1394_MAX_SIZE) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Invalid %d buffers requested",v.nb_buffers);
return -EFAULT;
}
if (v.nb_buffers * v.buf_size > VIDEO1394_MAX_SIZE) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"%d buffers of size %d bytes is too big",
v.nb_buffers, v.buf_size);
return -EFAULT;
v.channel, 0);
if (d == NULL) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Couldn't allocate ir context");
return -EFAULT;
}
v.buf_size = d->buf_size;
list_add_tail(&d->link, &ctx->context_list);
- PRINT(KERN_INFO, ohci->id,
+ PRINT(KERN_INFO, ohci->host->id,
"iso context %d listen on channel %d",
d->ctx, v.channel);
}
v.channel, v.packet_size);
if (d == NULL) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Couldn't allocate it context");
return -EFAULT;
}
list_add_tail(&d->link, &ctx->context_list);
- PRINT(KERN_INFO, ohci->id,
+ PRINT(KERN_INFO, ohci->host->id,
"Iso context %d talk on channel %d", d->ctx,
v.channel);
}
return -EFAULT;
if (channel<0 || channel>(ISO_CHANNELS-1)) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Iso channel %d out of bound", channel);
return -EFAULT;
}
mask = (u64)0x1<<channel;
if (!(ohci->ISO_channel_usage & mask)) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Channel %d is not being used", channel);
return -EFAULT;
}
d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel);
if (d == NULL) return -EFAULT;
- PRINT(KERN_INFO, ohci->id, "Iso context %d "
+ PRINT(KERN_INFO, ohci->host->id, "Iso context %d "
"stop talking on channel %d", d->ctx, channel);
free_dma_iso_ctx(d);
d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
if ((v.buffer<0) || (v.buffer>d->num_desc)) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
return -EFAULT;
}
spin_lock_irqsave(&d->lock,flags);
if (d->buffer_status[v.buffer]==VIDEO1394_BUFFER_QUEUED) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Buffer %d is already used",v.buffer);
spin_unlock_irqrestore(&d->lock,flags);
return -EFAULT;
if (!(reg_read(ohci, d->ctrlSet) & 0x8000))
{
- DBGMSG(ohci->id, "Starting iso DMA ctx=%d",d->ctx);
+ DBGMSG(ohci->host->id, "Starting iso DMA ctx=%d",d->ctx);
/* Tell the controller where the first program is */
reg_write(ohci, d->cmdPtr,
else {
/* Wake up dma context if necessary */
if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
- PRINT(KERN_INFO, ohci->id,
+ PRINT(KERN_INFO, ohci->host->id,
"Waking up iso dma ctx=%d", d->ctx);
reg_write(ohci, d->ctrlSet, 0x1000);
}
d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
if ((v.buffer<0) || (v.buffer>d->num_desc)) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
return -EFAULT;
}
d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
break;
default:
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Buffer %d is not queued",v.buffer);
spin_unlock_irqrestore(&d->lock, flags);
return -EFAULT;
d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
if ((v.buffer<0) || (v.buffer>d->num_desc)) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
return -EFAULT;
}
spin_lock_irqsave(&d->lock,flags);
if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Buffer %d is already used",v.buffer);
spin_unlock_irqrestore(&d->lock,flags);
if (qv.packet_sizes)
if (!(reg_read(ohci, d->ctrlSet) & 0x8000))
{
- DBGMSG(ohci->id, "Starting iso transmit DMA ctx=%d",
+ DBGMSG(ohci->host->id, "Starting iso transmit DMA ctx=%d",
d->ctx);
put_timestamp(ohci, d, d->last_buffer);
else {
/* Wake up dma context if necessary */
if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
- PRINT(KERN_INFO, ohci->id,
+ PRINT(KERN_INFO, ohci->host->id,
"Waking up iso transmit dma ctx=%d",
d->ctx);
put_timestamp(ohci, d, d->last_buffer);
d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
if ((v.buffer<0) || (v.buffer>d->num_desc)) {
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
return -EFAULT;
}
d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
return 0;
default:
- PRINT(KERN_ERR, ohci->id,
+ PRINT(KERN_ERR, ohci->host->id,
"Buffer %d is not queued",v.buffer);
return -EFAULT;
}
lock_kernel();
if (ctx->current_ctx == NULL) {
- PRINT(KERN_ERR, ctx->ohci->id, "Current iso context not set");
+ PRINT(KERN_ERR, ctx->ohci->host->id, "Current iso context not set");
} else
res = dma_region_mmap(&ctx->current_ctx->dma, file, vma);
unlock_kernel();
ctx = kmalloc(sizeof(struct file_ctx), GFP_KERNEL);
if (ctx == NULL) {
- PRINT(KERN_ERR, ohci->id, "Cannot malloc file_ctx");
+ PRINT(KERN_ERR, ohci->host->id, "Cannot malloc file_ctx");
return -ENOMEM;
}
mask = (u64) 1 << d->channel;
if (!(ohci->ISO_channel_usage & mask))
- PRINT(KERN_ERR, ohci->id, "On release: Channel %d "
+ PRINT(KERN_ERR, ohci->host->id, "On release: Channel %d "
"is not being used", d->channel);
else
ohci->ISO_channel_usage &= ~mask;
- PRINT(KERN_INFO, ohci->id, "On release: Iso %s context "
+ PRINT(KERN_INFO, ohci->host->id, "On release: Iso %s context "
"%d stop listening on channel %d",
d->type == OHCI_ISO_RECEIVE ? "receive" : "transmit",
d->ctx, d->channel);
ohci = (struct ti_ohci *)host->hostdata;
if (!hpsb_create_hostinfo(&video1394_highlevel, host, 0)) {
- PRINT(KERN_ERR, ohci->id, "Cannot allocate hostinfo");
+ PRINT(KERN_ERR, ohci->host->id, "Cannot allocate hostinfo");
return;
}
hpsb_set_hostinfo(&video1394_highlevel, host, ohci);
- hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->id);
+ hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
- minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->id;
+ minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
S_IFCHR | S_IRUSR | S_IWUSR,
- "%s/%d", VIDEO1394_DRIVER_NAME, ohci->id);
+ "%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
}
struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
if (ohci)
- devfs_remove("%s/%d", VIDEO1394_DRIVER_NAME, ohci->id);
+ devfs_remove("%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
return;
}
video1394_cdev.owner = THIS_MODULE;
kobject_set_name(&video1394_cdev.kobj, VIDEO1394_DRIVER_NAME);
ret = cdev_add(&video1394_cdev, IEEE1394_VIDEO1394_DEV, 16);
- if (cdev_add(&video1394_cdev, IEEE1394_VIDEO1394_DEV, 16)) {
+ if (ret) {
PRINT_G(KERN_ERR, "video1394: unable to get minor device block");
return ret;
}
}
static struct pnp_driver fcpnp_driver = {
- name: "fcpnp",
- probe: fcpnp_probe,
- remove: __devexit_p(fcpnp_remove),
- id_table: fcpnp_ids,
+ .name = "fcpnp",
+ .probe = fcpnp_probe,
+ .remove = __devexit_p(fcpnp_remove),
+ .id_table = fcpnp_ids,
};
#endif
}
static struct pci_driver fcpci_driver = {
- name: "fcpci",
- probe: fcpci_probe,
- remove: __devexit_p(fcpci_remove),
- id_table: fcpci_ids,
+ .name = "fcpci",
+ .probe = fcpci_probe,
+ .remove = __devexit_p(fcpci_remove),
+ .id_table = fcpci_ids,
};
static int __init hisax_fcpcipnp_init(void)
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/bio.h>
+#include <linux/blkdev.h>
#include <linux/mempool.h>
#include <linux/slab.h>
#include <linux/crypto.h>
-#include <linux/spinlock.h>
#include <linux/workqueue.h>
+#include <asm/atomic.h>
#include <asm/scatterlist.h>
#include "dm.h"
+#define PFX "crypt: "
+
/*
* per bio private data
*/
int key_size;
if (argc != 5) {
- ti->error = "dm-crypt: Not enough arguments";
+ ti->error = PFX "Not enough arguments";
return -EINVAL;
}
mode = strsep(&tmp, "-");
if (tmp)
- DMWARN("dm-crypt: Unexpected additional cipher options");
+ DMWARN(PFX "Unexpected additional cipher options");
key_size = strlen(argv[1]) >> 1;
cc = kmalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL);
if (cc == NULL) {
ti->error =
- "dm-crypt: Cannot allocate transparent encryption context";
+ PFX "Cannot allocate transparent encryption context";
return -ENOMEM;
}
else if (strcmp(mode, "ecb") == 0)
cc->iv_generator = NULL;
else {
- ti->error = "dm-crypt: Invalid chaining mode";
+ ti->error = PFX "Invalid chaining mode";
goto bad1;
}
tfm = crypto_alloc_tfm(cipher, crypto_flags);
if (!tfm) {
- ti->error = "dm-crypt: Error allocating crypto tfm";
+ ti->error = PFX "Error allocating crypto tfm";
goto bad1;
}
+ if (crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER) {
+ ti->error = PFX "Expected cipher algorithm";
+ goto bad2;
+ }
- if (tfm->crt_u.cipher.cit_decrypt_iv && tfm->crt_u.cipher.cit_encrypt_iv)
+ if (tfm->crt_cipher.cit_decrypt_iv && tfm->crt_cipher.cit_encrypt_iv)
/* at least a 32 bit sector number should fit in our buffer */
cc->iv_size = max(crypto_tfm_alg_ivsize(tfm),
(unsigned int)(sizeof(u32) / sizeof(u8)));
else {
cc->iv_size = 0;
if (cc->iv_generator) {
- DMWARN("dm-crypt: Selected cipher does not support IVs");
+ DMWARN(PFX "Selected cipher does not support IVs");
cc->iv_generator = NULL;
}
}
cc->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
mempool_free_slab, _crypt_io_pool);
if (!cc->io_pool) {
- ti->error = "dm-crypt: Cannot allocate crypt io mempool";
+ ti->error = PFX "Cannot allocate crypt io mempool";
goto bad2;
}
cc->page_pool = mempool_create(MIN_POOL_PAGES, mempool_alloc_page,
mempool_free_page, NULL);
if (!cc->page_pool) {
- ti->error = "dm-crypt: Cannot allocate page mempool";
+ ti->error = PFX "Cannot allocate page mempool";
goto bad3;
}
cc->key_size = key_size;
if ((key_size == 0 && strcmp(argv[1], "-") != 0)
|| crypt_decode_key(cc->key, argv[1], key_size) < 0) {
- ti->error = "dm-crypt: Error decoding key";
+ ti->error = PFX "Error decoding key";
goto bad4;
}
- if (tfm->crt_u.cipher.cit_setkey(tfm, cc->key, key_size) < 0) {
- ti->error = "dm-crypt: Error setting key";
+ if (tfm->crt_cipher.cit_setkey(tfm, cc->key, key_size) < 0) {
+ ti->error = PFX "Error setting key";
goto bad4;
}
if (sscanf(argv[2], SECTOR_FORMAT, &cc->iv_offset) != 1) {
- ti->error = "dm-crypt: Invalid iv_offset sector";
+ ti->error = PFX "Invalid iv_offset sector";
goto bad4;
}
if (sscanf(argv[4], SECTOR_FORMAT, &cc->start) != 1) {
- ti->error = "dm-crypt: Invalid device sector";
+ ti->error = PFX "Invalid device sector";
goto bad4;
}
if (dm_get_device(ti, argv[3], cc->start, ti->len,
dm_table_get_mode(ti->table), &cc->dev)) {
- ti->error = "dm-crypt: Device lookup failed";
+ ti->error = PFX "Device lookup failed";
goto bad4;
}
return NULL;
}
}
- } else
- clone = bio_clone(bio, GFP_NOIO);
+ } else {
+ /*
+ * The block layer might modify the bvec array, so always
+ * copy the required bvecs because we need the original
+ * one in order to decrypt the whole bio data *afterwards*.
+ */
+ clone = bio_alloc(GFP_NOIO, bio_segments(bio));
+ if (clone) {
+ clone->bi_idx = 0;
+ clone->bi_vcnt = bio_segments(bio);
+ clone->bi_size = bio->bi_size;
+ memcpy(clone->bi_io_vec, bio_iovec(bio),
+ sizeof(struct bio_vec) * clone->bi_vcnt);
+ }
+ }
if (!clone)
return NULL;
case STATUSTYPE_TABLE:
cipher = crypto_tfm_alg_name(cc->tfm);
- switch(cc->tfm->crt_u.cipher.cit_mode) {
+ switch(cc->tfm->crt_cipher.cit_mode) {
case CRYPTO_TFM_MODE_CBC:
mode = "plain";
break;
_kcryptd_workqueue = create_workqueue("kcryptd");
if (!_kcryptd_workqueue) {
r = -ENOMEM;
- DMERR("couldn't create kcryptd");
+ DMERR(PFX "couldn't create kcryptd");
goto bad1;
}
r = dm_register_target(&crypt_target);
if (r < 0) {
- DMERR("crypt: register failed %d", r);
+ DMERR(PFX "register failed %d", r);
goto bad2;
}
int r = dm_unregister_target(&crypt_target);
if (r < 0)
- DMERR("crypt: unregister failed %d", r);
+ DMERR(PFX "unregister failed %d", r);
destroy_workqueue(_kcryptd_workqueue);
kmem_cache_destroy(_crypt_io_pool);
for ( ; i > 0 ; i--)
__free_page(bio->bi_io_vec[i-1].bv_page);
out_free_bio:
- while ( j < conf->raid_disks )
- bio_put(r1_bio->bios[++j]);
+ while ( ++j < conf->raid_disks )
+ bio_put(r1_bio->bios[j]);
r1bio_pool_free(r1_bio, conf->mddev);
return NULL;
}
* ------------------------------------------------------------------------
*/
-#define ZR050_VERSION "v0.7"
+#define ZR050_VERSION "v0.7.1"
#include <linux/version.h>
#include <linux/module.h>
zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1
/* volume control settings */
- zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol >> 1);
+ /*zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);*/
zr36050_write(ptr, ZR050_SF_HI, ptr->scalefact >> 8);
zr36050_write(ptr, ZR050_SF_LO, ptr->scalefact & 0xff);
/* setup misc. data for compression (target code sizes) */
/* size of compressed code to reach without header data */
- sum = ptr->total_code_vol - sum;
+ sum = ptr->real_code_vol - sum;
bitcnt = sum << 3; /* need the size in bits */
tmp = bitcnt >> 16;
dprintk(3,
"%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
- ptr->name, sum, ptr->total_code_vol, bitcnt, tmp);
+ ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
zr36050_write(ptr, ZR050_TCV_NET_HI, tmp >> 8);
zr36050_write(ptr, ZR050_TCV_NET_MH, tmp & 0xff);
tmp = bitcnt & 0xffff;
struct vfe_polarity *pol)
{
struct zr36050 *ptr = (struct zr36050 *) codec->data;
+ int size;
- dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) call\n",
+ dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) q%d call\n",
ptr->name, norm->HStart, norm->VStart,
cap->x, cap->y, cap->width, cap->height,
- cap->decimation);
+ cap->decimation, cap->quality);
/* if () return -EINVAL;
* trust the master driver that it knows what it does - so
* we allow invalid startx/y and norm for now ... */
ptr->width = cap->width / (cap->decimation & 0xff);
ptr->height = cap->height / ((cap->decimation >> 8) & 0xff);
+ /* (KM) JPEG quality */
+ size = ptr->width * ptr->height;
+ size *= 16; /* size in bits */
+ /* apply quality setting */
+ size = size * cap->quality / 200;
+
+ /* Minimum: 1kb */
+ if (size < 8192)
+ size = 8192;
+ /* Maximum: 7/8 of code buffer */
+ if (size > ptr->total_code_vol * 7)
+ size = ptr->total_code_vol * 7;
+
+ ptr->real_code_vol = size >> 3; /* in bytes */
+
+ /* Set max_block_vol here (previously in zr36050_init, moved
+ * here for consistency with zr36060 code */
+ zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);
+
return 0;
}
if (size != sizeof(int))
return -EFAULT;
ptr->total_code_vol = *ival;
+ /* (Kieran Morrissey)
+ * code copied from zr36060.c to ensure proper bitrate */
+ ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
break;
case CODEC_G_JPEG_SCALE: /* get scaling factor */
__u16 bitrate_ctrl;
__u32 total_code_vol;
+ __u32 real_code_vol;
__u16 max_block_vol;
__u8 h_samp_ratio[8];
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
+#include <asm/eeh.h> /* for eeh_add_device() */
#include <asm/rtas.h> /* rtas_call */
#include <asm/pci-bridge.h> /* for pci_controller */
#include "../pci.h" /* for pci_add_new_bus*/
}
dev = rpaphp_find_pci_dev(slot->dn->child);
+ eeh_add_device(dev);
} else {
/* slot is not enabled */
err("slot doesn't have pci_dev structure\n");
}
/* remove the device from the pci core */
+ eeh_remove_device(slot->dev);
pci_remove_bus_device(slot->dev);
pci_dev_put(slot->dev);
+if ARCH_S390
+
comment "S/390 block device drivers"
depends on ARCH_S390
ioctl functions specific to the dasd driver.
This is only needed if you want to use applications written for
linux-2.4 dasd channel measurement facility interface.
+
+endif
if (count == 0)
return 0;
- /* value comes in units of 128 µsec */
+ /* value comes in units of 128 µsec */
ret = time_to_nsec(value);
do_div(ret, count);
registered BusLogic Host Adapters.
*/
-static void __init BusLogic_UnregisterHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
+static void BusLogic_UnregisterHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
{
if (HostAdapter == BusLogic_FirstRegisteredHostAdapter)
{
};
static const struct keyspan_device_details usa19hs_device_details = {
- product_id: keyspan_usa19hs_product_id,
- msg_format: msg_usa90,
- num_ports: 1,
- indat_endp_flip: 0,
- outdat_endp_flip: 0,
- indat_endpoints: {0x81},
- outdat_endpoints: {0x01},
- inack_endpoints: {-1},
- outcont_endpoints: {0x02},
- instat_endpoint: 0x82,
- glocont_endpoint: -1,
- calculate_baud_rate: keyspan_usa19hs_calc_baud,
- baudclk: KEYSPAN_USA19HS_BAUDCLK,
+ .product_id = keyspan_usa19hs_product_id,
+ .msg_format = msg_usa90,
+ .num_ports = 1,
+ .indat_endp_flip = 0,
+ .outdat_endp_flip = 0,
+ .indat_endpoints = {0x81},
+ .outdat_endpoints = {0x01},
+ .inack_endpoints = {-1},
+ .outcont_endpoints = {0x02},
+ .instat_endpoint = 0x82,
+ .glocont_endpoint = -1,
+ .calculate_baud_rate = keyspan_usa19hs_calc_baud,
+ .baudclk = KEYSPAN_USA19HS_BAUDCLK,
};
static const struct keyspan_device_details usa28_device_details = {
static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx,
int height, int width);
static int fbcon_switch(struct vc_data *vc);
-static int fbcon_blank(struct vc_data *vc, int blank);
+static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch);
static int fbcon_font_op(struct vc_data *vc, struct console_font_op *op);
static int fbcon_set_palette(struct vc_data *vc, unsigned char *table);
static int fbcon_scrolldelta(struct vc_data *vc, int lines);
return 1;
}
-static int fbcon_blank(struct vc_data *vc, int blank)
+static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
{
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
struct display *p = &fb_display[vc->vc_num];
- if (blank < 0) /* Entering graphics mode */
- return 0;
+ if (mode_switch) {
+ struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+ struct fb_var_screeninfo var = info->var;
+
+ if (blank) {
+ fbcon_cursor(vc, CM_ERASE);
+ return 0;
+ }
+ var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
+ fb_set_var(info, &var);
+ }
fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
}
static int
-promcon_blank(struct vc_data *conp, int blank)
+promcon_blank(struct vc_data *conp, int blank, int mode_switch)
{
if (blank) {
promcon_puts("\033[H\033[J\033[7m \033[m\b", 15);
return 0;
}
-static int sticon_blank(struct vc_data *c, int blank)
+static int sticon_blank(struct vc_data *c, int blank, int mode_switch)
{
- switch (blank) {
- case 0: /* unblank */
- vga_is_gfx = 0;
- /* Tell console.c that it has to restore the screen itself */
- return 1;
- case 1: /* normal blanking */
- default: /* VESA blanking */
- if (vga_is_gfx)
- return 0;
- sticon_set_origin(c);
- sti_clear(sticon_sti, 0,0, c->vc_rows, c->vc_cols, BLANK);
- return 1;
- case -1: /* Entering graphic mode */
- sti_clear(sticon_sti, 0,0, c->vc_rows, c->vc_cols, BLANK);
- vga_is_gfx = 1;
+ if (blank == 0) {
+ if (mode_switch)
+ vga_is_gfx = 0;
return 1;
}
- return 1; /* console needs to restore screen itself */
+ sticon_set_origin(c);
+ sti_clear(sticon_sti, 0,0, c->vc_rows, c->vc_cols, BLANK);
+ if (mode_switch)
+ vga_is_gfx = 1;
+ return 1;
}
static int sticon_scrolldelta(struct vc_data *conp, int lines)
static void vgacon_deinit(struct vc_data *c);
static void vgacon_cursor(struct vc_data *c, int mode);
static int vgacon_switch(struct vc_data *c);
-static int vgacon_blank(struct vc_data *c, int blank);
+static int vgacon_blank(struct vc_data *c, int blank, int mode_switch);
static int vgacon_font_op(struct vc_data *c, struct console_font_op *op);
static int vgacon_set_palette(struct vc_data *vc, unsigned char *table);
static int vgacon_scrolldelta(struct vc_data *c, int lines);
}
}
-static int vgacon_blank(struct vc_data *c, int blank)
+static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
{
switch (blank) {
case 0: /* Unblank */
/* Tell console.c that it has to restore the screen itself */
return 1;
case 1: /* Normal blanking */
- if (vga_video_type == VIDEO_TYPE_VGAC) {
+ case -1: /* Obsolete */
+ if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
vga_pal_blank(&state);
vga_palette_blanked = 1;
return 0;
vgacon_set_origin(c);
scr_memsetw((void *) vga_vram_base, BLANK,
c->vc_screenbuf_size);
- return 1;
- case -1: /* Entering graphic mode */
- scr_memsetw((void *) vga_vram_base, BLANK,
- c->vc_screenbuf_size);
- vga_is_gfx = 1;
+ if (mode_switch)
+ vga_is_gfx = 1;
return 1;
default: /* VESA blanking */
if (vga_video_type == VIDEO_TYPE_VGAC) {
{
int err;
- if (memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
+ if ((var->activate & FB_ACTIVATE_FORCE) ||
+ memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
if (!info->fbops->fb_check_var) {
*var = info->var;
return 0;
#
# Makefile for the Intel 810/815 framebuffer driver
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definitions are now in the main makefile...
-
obj-$(CONFIG_FB_I810) += i810fb.o
#
# Makefile for the Kyro framebuffer driver
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definitions are now in the main makefile...
obj-$(CONFIG_FB_KYRO) += kyrofb.o
#
# Makefile for the linux BeOS filesystem routines.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definitions are now in the main makefile...
-
obj-$(CONFIG_BEFS_FS) += befs.o
read_unlock(&tasklist_lock);
if (!task)
goto out;
- if (!thread_group_leader(task))
- goto out_drop_task;
inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
- if (!inode)
- goto out_drop_task;
+
+ if (!inode) {
+ put_task_struct(task);
+ goto out;
+ }
inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
inode->i_op = &proc_tgid_base_inode_operations;
inode->i_fop = &proc_tgid_base_operations;
goto out;
}
return NULL;
-out_drop_task:
- put_task_struct(task);
out:
return ERR_PTR(-ENOENT);
}
struct pt_regs;
+extern int sys_request_irq(unsigned int,
+ irqreturn_t (*)(int, void *, struct pt_regs *),
+ unsigned long, const char *, void *);
+extern void sys_free_irq(unsigned int, void *);
+
/*
* various flags for request_irq() - the Amiga now uses the standard
* mechanism like all other architectures - SA_INTERRUPT and SA_SHIRQ
asmlinkage int sys_ptrace(long request, long pid, long addr, long data);
asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
struct pt_regs;
-int sys_request_irq(unsigned int,
- irqreturn_t (*)(int, void *, struct pt_regs *),
- unsigned long, const char *, void *);
-void sys_free_irq(unsigned int, void *);
struct sigaction;
asmlinkage long sys_rt_sigaction(int sig,
const struct sigaction __user *act,
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* Start Change Log
- * 2001/10/27 : engebret : Created.
- * End Change Log
- */
-
-#ifndef _EEH_H
-#define _EEH_H
+#ifndef _PPC64_EEH_H
+#define _PPC64_EEH_H
#include <linux/string.h>
+#include <linux/init.h>
struct pci_dev;
* a bad page fault if the address is used directly (i.e. these addresses are
* never actually mapped. Translation between IO <-> EEH region is 1 to 1.
*/
-#define IO_TOKEN_TO_ADDR(token) (((unsigned long)(token) & ~(0xfUL << REGION_SHIFT)) | \
- (IO_REGION_ID << REGION_SHIFT))
-#define IO_ADDR_TO_TOKEN(addr) (((unsigned long)(addr) & ~(0xfUL << REGION_SHIFT)) | \
- (EEH_REGION_ID << REGION_SHIFT))
+#define IO_TOKEN_TO_ADDR(token) \
+ (((unsigned long)(token) & ~(0xfUL << REGION_SHIFT)) | \
+ (IO_REGION_ID << REGION_SHIFT))
+
+#define IO_ADDR_TO_TOKEN(addr) \
+ (((unsigned long)(addr) & ~(0xfUL << REGION_SHIFT)) | \
+ (EEH_REGION_ID << REGION_SHIFT))
/* Values for eeh_mode bits in device_node */
#define EEH_MODE_SUPPORTED (1<<0)
#define EEH_MODE_NOCHECK (1<<1)
-/* This is for profiling only */
-extern unsigned long eeh_total_mmio_ffs;
-
-void eeh_init(void);
-int eeh_get_state(unsigned long ea);
+extern void __init eeh_init(void);
unsigned long eeh_check_failure(void *token, unsigned long val);
void *eeh_ioremap(unsigned long addr, void *vaddr);
+void __init pci_addr_cache_build(void);
+
+/**
+ * eeh_add_device - perform EEH initialization for the indicated pci device
+ * @dev: pci device for which to set up EEH
+ *
+ * This routine can be used to perform EEH initialization for PCI
+ * devices that were added after system boot (e.g. hotplug, dlpar).
+ * Whether this actually enables EEH or not for this device depends
+ * on the type of the device, on earlier boot command-line
+ * arguments & etc.
+ */
+void eeh_add_device(struct pci_dev *);
+
+/**
+ * eeh_remove_device - undo EEH setup for the indicated pci device
+ * @dev: pci device to be removed
+ *
+ * This routine should be when a device is removed from a running
+ * system (e.g. by hotplug or dlpar).
+ */
+void eeh_remove_device(struct pci_dev *);
#define EEH_DISABLE 0
#define EEH_ENABLE 1
#define EEH_RELEASE_DMA 3
int eeh_set_option(struct pci_dev *dev, int options);
-/* Given a PCI device check if eeh should be configured or not.
- * This may look at firmware properties and/or kernel cmdline options.
- */
-int is_eeh_configured(struct pci_dev *dev);
-
-/* Translate a (possible) eeh token to a physical addr.
- * If "token" is not an eeh token it is simply returned under
- * the assumption that it is already a physical addr.
- */
-unsigned long eeh_token_to_phys(unsigned long token);
-
-/* EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
+/*
+ * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
*
* Order this macro for performance.
* If EEH is off for a device and it is a memory BAR, ioremap will
* If this macro yields TRUE, the caller relays to eeh_check_failure()
* which does further tests out of line.
*/
-/* #define EEH_POSSIBLE_IO_ERROR(val) (~(val) == 0) */
-/* #define EEH_POSSIBLE_ERROR(addr, vaddr, val) ((vaddr) != (addr) && EEH_POSSIBLE_IO_ERROR(val) */
-/* This version is rearranged to collect some profiling data */
-#define EEH_POSSIBLE_IO_ERROR(val) (~(val) == 0 && ++eeh_total_mmio_ffs)
-#define EEH_POSSIBLE_ERROR(addr, vaddr, val) (EEH_POSSIBLE_IO_ERROR(val) && (vaddr) != (addr))
+#define EEH_POSSIBLE_IO_ERROR(val, type) ((val) == (type)~0)
+
+/* The vaddr will equal the addr if EEH checking is disabled for
+ * this device. This is because eeh_ioremap() will not have
+ * remapped to 0xA0, and thus both vaddr and addr will be 0xE0...
+ */
+#define EEH_POSSIBLE_ERROR(addr, vaddr, val, type) \
+ ((vaddr) != (addr) && EEH_POSSIBLE_IO_ERROR(val, type))
/*
* MMIO read/write operations with EEH support.
- *
- * addr: 64b token of the form 0xA0PPBBDDyyyyyyyy
- * 0xA0 : Unmapped MMIO region
- * PP : PHB index (starting at zero)
- * BB : PCI Bus number under given PHB
- * DD : PCI devfn under given bus
- * yyyyyyyy : Virtual address offset
- *
- * An actual virtual address is produced from this token
- * by masking into the form:
- * 0xE0000000yyyyyyyy
*/
static inline u8 eeh_readb(void *addr) {
volatile u8 *vaddr = (volatile u8 *)IO_TOKEN_TO_ADDR(addr);
u8 val = in_8(vaddr);
- if (EEH_POSSIBLE_ERROR(addr, vaddr, val))
+ if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u8))
return eeh_check_failure(addr, val);
return val;
}
volatile u8 *vaddr = (volatile u8 *)IO_TOKEN_TO_ADDR(addr);
out_8(vaddr, val);
}
+
static inline u16 eeh_readw(void *addr) {
volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr);
u16 val = in_le16(vaddr);
- if (EEH_POSSIBLE_ERROR(addr, vaddr, val))
+ if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u16))
return eeh_check_failure(addr, val);
return val;
}
volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr);
out_le16(vaddr, val);
}
+static inline u16 eeh_raw_readw(void *addr) {
+ volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr);
+ u16 val = in_be16(vaddr);
+ if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u16))
+ return eeh_check_failure(addr, val);
+ return val;
+}
+static inline void eeh_raw_writew(u16 val, void *addr) {
+ volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr);
+ out_be16(vaddr, val);
+}
+
static inline u32 eeh_readl(void *addr) {
volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr);
u32 val = in_le32(vaddr);
- if (EEH_POSSIBLE_ERROR(addr, vaddr, val))
+ if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u32))
return eeh_check_failure(addr, val);
return val;
}
volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr);
out_le32(vaddr, val);
}
+static inline u32 eeh_raw_readl(void *addr) {
+ volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr);
+ u32 val = in_be32(vaddr);
+ if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u32))
+ return eeh_check_failure(addr, val);
+ return val;
+}
+static inline void eeh_raw_writel(u32 val, void *addr) {
+ volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr);
+ out_be32(vaddr, val);
+}
+
static inline u64 eeh_readq(void *addr) {
volatile u64 *vaddr = (volatile u64 *)IO_TOKEN_TO_ADDR(addr);
u64 val = in_le64(vaddr);
- if (EEH_POSSIBLE_ERROR(addr, vaddr, val))
+ if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u64))
return eeh_check_failure(addr, val);
return val;
}
volatile u64 *vaddr = (volatile u64 *)IO_TOKEN_TO_ADDR(addr);
out_le64(vaddr, val);
}
+static inline u64 eeh_raw_readq(void *addr) {
+ volatile u64 *vaddr = (volatile u64 *)IO_TOKEN_TO_ADDR(addr);
+ u64 val = in_be64(vaddr);
+ if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u64))
+ return eeh_check_failure(addr, val);
+ return val;
+}
+static inline void eeh_raw_writeq(u64 val, void *addr) {
+ volatile u64 *vaddr = (volatile u64 *)IO_TOKEN_TO_ADDR(addr);
+ out_be64(vaddr, val);
+}
static inline void eeh_memset_io(void *addr, int c, unsigned long n) {
void *vaddr = (void *)IO_TOKEN_TO_ADDR(addr);
static inline void eeh_memcpy_fromio(void *dest, void *src, unsigned long n) {
void *vsrc = (void *)IO_TOKEN_TO_ADDR(src);
memcpy(dest, vsrc, n);
- /* look for ffff's here at dest[n] */
+ /* Look for ffff's here at dest[n]. Assume that at least 4 bytes
+ * were copied. Check all four bytes.
+ */
+ if ((n >= 4) &&
+ (EEH_POSSIBLE_ERROR(src, vsrc, (*((u32 *) dest+n-4)), u32))) {
+ eeh_check_failure(src, (*((u32 *) dest+n-4)));
+ }
}
+
static inline void eeh_memcpy_toio(void *dest, void *src, unsigned long n) {
void *vdest = (void *)IO_TOKEN_TO_ADDR(dest);
memcpy(vdest, src, n);
if (_IO_IS_ISA(port) && !_IO_HAS_ISA_BUS)
return ~0;
val = in_8((u8 *)(port+pci_io_base));
- if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR(val))
- return eeh_check_failure((void*)(port+pci_io_base), val);
+ if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR(val, u8))
+ return eeh_check_failure((void*)(port), val);
return val;
}
if (_IO_IS_ISA(port) && !_IO_HAS_ISA_BUS)
return ~0;
val = in_le16((u16 *)(port+pci_io_base));
- if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR(val))
- return eeh_check_failure((void*)(port+pci_io_base), val);
+ if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR(val, u16))
+ return eeh_check_failure((void*)(port), val);
return val;
}
if (_IO_IS_ISA(port) && !_IO_HAS_ISA_BUS)
return ~0;
val = in_le32((u32 *)(port+pci_io_base));
- if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR(val))
- return eeh_check_failure((void*)(port+pci_io_base), val);
+ if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR(val, u32))
+ return eeh_check_failure((void*)(port), val);
return val;
}
return out_le32((u32 *)(port+pci_io_base), val);
}
-#endif /* _EEH_H */
+/* in-string eeh macros */
+static inline void eeh_insb(unsigned long port, void * buf, int ns) {
+ _insb((u8 *)(port+pci_io_base), buf, ns);
+ if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR((*(((u8*)buf)+ns-1)), u8))
+ eeh_check_failure((void*)(port), *(u8*)buf);
+}
+
+static inline void eeh_insw_ns(unsigned long port, void * buf, int ns) {
+ _insw_ns((u16 *)(port+pci_io_base), buf, ns);
+ if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR((*(((u16*)buf)+ns-1)), u16))
+ eeh_check_failure((void*)(port), *(u16*)buf);
+}
+
+static inline void eeh_insl_ns(unsigned long port, void * buf, int nl) {
+ _insl_ns((u32 *)(port+pci_io_base), buf, nl);
+ if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR((*(((u32*)buf)+nl-1)), u32))
+ eeh_check_failure((void*)(port), *(u32*)buf);
+}
+
+#endif /* _PPC64_EEH_H */
#define outb(data,addr) writeb(data,((unsigned long)(addr)))
#define outw(data,addr) writew(data,((unsigned long)(addr)))
#define outl(data,addr) writel(data,((unsigned long)(addr)))
+/*
+ * The *_ns versions below don't do byte-swapping.
+ * Neither do the standard versions now, these are just here
+ * for older code.
+ */
+#define insw_ns(port, buf, ns) _insw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
+#define insl_ns(port, buf, nl) _insl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
#else
#define __raw_readb(addr) (*(volatile unsigned char *)(addr))
#define __raw_readw(addr) (*(volatile unsigned short *)(addr))
* They are only used in practice for transferring buffers which
* are arrays of bytes, and byte-swapping is not appropriate in
* that case. - paulus */
-#define insb(port, buf, ns) _insb((u8 *)((port)+pci_io_base), (buf), (ns))
-#define outsb(port, buf, ns) _outsb((u8 *)((port)+pci_io_base), (buf), (ns))
-#define insw(port, buf, ns) _insw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
-#define outsw(port, buf, ns) _outsw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
-#define insl(port, buf, nl) _insl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
-#define outsl(port, buf, nl) _outsl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
+#define insb(port, buf, ns) eeh_insb((port), (buf), (ns))
+#define insw(port, buf, ns) eeh_insw_ns((port), (buf), (ns))
+#define insl(port, buf, nl) eeh_insl_ns((port), (buf), (nl))
+#define insw_ns(port, buf, ns) eeh_insw_ns((port), (buf), (ns))
+#define insl_ns(port, buf, nl) eeh_insl_ns((port), (buf), (nl))
+
+#define outsb(port, buf, ns) _outsb((u8 *)((port)+pci_io_base), (buf), (ns))
+#define outsw(port, buf, ns) _outsw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
+#define outsl(port, buf, nl) _outsl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
+
#endif
#define readb_relaxed(addr) readb(addr)
* Neither do the standard versions now, these are just here
* for older code.
*/
-#define insw_ns(port, buf, ns) _insw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
#define outsw_ns(port, buf, ns) _outsw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
-#define insl_ns(port, buf, nl) _insl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
#define outsl_ns(port, buf, nl) _outsl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
/*
* 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
+ * These routines do not perform EEH-related I/O address translation,
+ * and should not be used directly by device drivers. Use inb/readb
+ * instead.
*/
static inline int in_8(volatile unsigned char *addr)
{
return nid;
}
+#define pfn_to_nid(pfn) phys_to_nid((unsigned long)(pfn) << PAGE_SHIFT)
+
#define kvaddr_to_nid(kaddr) phys_to_nid(__pa(kaddr))
#define NODE_DATA(nid) (node_data[nid])
int (*con_scroll)(struct vc_data *, int, int, int, int);
void (*con_bmove)(struct vc_data *, int, int, int, int, int, int);
int (*con_switch)(struct vc_data *);
- int (*con_blank)(struct vc_data *, int);
+ int (*con_blank)(struct vc_data *, int, int);
int (*con_font_op)(struct vc_data *, struct console_font_op *);
int (*con_resize)(struct vc_data *, unsigned int, unsigned int);
int (*con_set_palette)(struct vc_data *, unsigned char *);
#define FB_ACTIVATE_VBL 16 /* activate values on next vbl */
#define FB_CHANGE_CMAP_VBL 32 /* change colormap on vbl */
#define FB_ACTIVATE_ALL 64 /* change all VCs on this fb */
+#define FB_ACTIVATE_FORCE 128 /* force apply even when no change*/
#define FB_ACCELF_TEXT 1 /* text mode acceleration */
memcpy(skb->nf_bridge->data, skb->data - header_size, header_size);
}
+/* This is called by the IP fragmenting code and it ensures there is
+ * enough room for the encapsulating header (if there is one). */
+static inline
+int nf_bridge_pad(struct sk_buff *skb)
+{
+ if (skb->protocol == __constant_htons(ETH_P_IP))
+ return 0;
+ if (skb->nf_bridge) {
+ if (skb->protocol == __constant_htons(ETH_P_8021Q))
+ return 4;
+ }
+ return 0;
+}
+
struct bridge_skb_cb {
union {
__u32 ipv4;
void vc_disallocate(unsigned int console);
void reset_palette(int currcons);
void set_palette(int currcons);
-void do_blank_screen(int gfx_mode);
+void do_blank_screen(int entering_gfx);
+void do_unblank_screen(int leaving_gfx);
void unblank_screen(void);
void poke_blanked_console(void);
int con_font_op(int currcons, struct console_font_op *op);
menu "General setup"
config SWAP
- bool "Support for paging of anonymous memory"
+ bool "Support for paging of anonymous memory (swap)"
depends on MMU
default y
help
#include <linux/sysrq.h>
#include <linux/init.h>
#include <linux/pm.h>
+#include <linux/workqueue.h>
-
-/**
- * handle_poweroff - sysrq callback for power down
- * @key: key pressed (unused)
- * @pt_regs: register state (unused)
- * @kbd: keyboard state (unused)
- * @tty: tty involved (unused)
- *
+/*
* When the user hits Sys-Rq o to power down the machine this is the
* callback we use.
*/
-static void handle_poweroff (int key, struct pt_regs *pt_regs,
- struct tty_struct *tty)
+static void do_poweroff(void *dummy)
{
if (pm_power_off)
pm_power_off();
}
+static DECLARE_WORK(poweroff_work, do_poweroff, 0);
+
+static void handle_poweroff(int key, struct pt_regs *pt_regs,
+ struct tty_struct *tty)
+{
+ schedule_work(&poweroff_work);
+}
+
static struct sysrq_key_op sysrq_poweroff_op = {
.handler = handle_poweroff,
.help_msg = "powerOff",
.action_msg = "Power Off\n"
};
-
static int pm_sysrq_init(void)
{
register_sysrq_key('o', &sysrq_poweroff_op);
free_pages((unsigned long) pagedir_nosave, pagedir_order);
spin_unlock_irq(&suspend_pagedir_lock);
+
+ device_resume();
+ PRINTK( "Fixing swap signatures... " );
mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
+ PRINTK( "ok\n" );
}
/*
oldalarm = it_old.it_value.tv_sec;
/* ehhh.. We can't return 0 if we have an alarm pending.. */
/* And we'd better return too much than too little anyway */
- if ((!oldalarm && it_old.it_value.tv_usec) || it_old.it_value.tv_usec > 1+1000000/HZ)
+ if ((!oldalarm && it_old.it_value.tv_usec) || it_old.it_value.tv_usec >= 500000)
oldalarm++;
return oldalarm;
}
if (tovec->bv_page == fromvec->bv_page)
continue;
- vfrom = page_address(fromvec->bv_page) + fromvec->bv_offset;
+ /*
+ * fromvec->bv_offset and fromvec->bv_len might have been
+ * modified by the block layer, so use the original copy,
+ * bounce_copy_vec already uses tovec->bv_len
+ */
+ vfrom = page_address(fromvec->bv_page) + tovec->bv_offset;
bounce_copy_vec(tovec, vfrom);
}
*
* 09Apr2002 akpm@zip.com.au
* Initial version
+ * 29Feb2004 kaos@sgi.com
+ * Move worker thread creation to kthread to avoid chewing
+ * up stack space with nested calls to kernel_thread.
*/
#include <linux/sched.h>
#include <linux/suspend.h>
#include <linux/fs.h> // Needed by writeback.h
#include <linux/writeback.h> // Prototypes pdflush_operation()
+#include <linux/kthread.h>
/*
static int __pdflush(struct pdflush_work *my_work)
{
- daemonize("pdflush");
-
current->flags |= PF_FLUSHER;
my_work->fn = NULL;
my_work->who = current;
static void start_one_pdflush_thread(void)
{
- kernel_thread(pdflush, NULL, CLONE_KERNEL);
+ kthread_run(pdflush, NULL, "pdflush");
}
static int __init pdflush_init(void)
return -ENOMEM;
vpriv->xoff = 0;
vpriv->old_pop = vcc->pop;
- LEC_VCC_PRIV(vcc) = vpriv;
+ vcc->user_back = vpriv;
vcc->pop = lec_pop;
lec_vcc_added(dev_lec[ioc_data.dev_num]->priv,
&ioc_data, vcc, vcc->push);
if (vpriv->xoff)
netif_wake_queue(dev);
kfree(vpriv);
- LEC_VCC_PRIV(vcc) = NULL;
+ vcc->user_back = NULL;
vcc->push = entry->old_push;
vcc_release_async(vcc, -EPIPE);
vcc = NULL;
return -ENOMEM;
vpriv->xoff = 0;
vpriv->old_pop = vcc->pop;
- LEC_VCC_PRIV(vcc) = vpriv;
+ vcc->user_back = vpriv;
vcc->pop = lec_pop;
lec_arp_get(priv);
to_add = make_entry(priv, mac_addr);
return -EINVAL;
if (!netif_device_present(dev))
return -ENODEV;
- dev_mc_add(dev, ifr->ifr_hwaddr.sa_data,
- dev->addr_len, 1);
- return 0;
+ return dev_mc_add(dev, ifr->ifr_hwaddr.sa_data,
+ dev->addr_len, 1);
case SIOCDELMULTI:
if (!dev->set_multicast_list ||
return -EINVAL;
if (!netif_device_present(dev))
return -ENODEV;
- dev_mc_delete(dev, ifr->ifr_hwaddr.sa_data,
- dev->addr_len, 1);
- return 0;
+ return dev_mc_delete(dev, ifr->ifr_hwaddr.sa_data,
+ dev->addr_len, 1);
case SIOCGIFINDEX:
ifr->ifr_ifindex = dev->ifindex;
#include <net/inetpeer.h>
#include <linux/igmp.h>
#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_bridge.h>
#include <linux/mroute.h>
#include <linux/netlink.h>
int ptr;
struct net_device *dev;
struct sk_buff *skb2;
- unsigned int mtu, hlen, left, len;
+ unsigned int mtu, hlen, left, len, ll_rs;
int offset;
int not_last_frag;
struct rtable *rt = (struct rtable*)skb->dst;
left = skb->len - hlen; /* Space per frame */
ptr = raw + hlen; /* Where to start from */
+#ifdef CONFIG_BRIDGE_NETFILTER
+ /* for bridged IP traffic encapsulated inside f.e. a vlan header,
+ * we need to make room for the encapsulating header */
+ ll_rs = LL_RESERVED_SPACE(rt->u.dst.dev + nf_bridge_pad(skb));
+ mtu -= nf_bridge_pad(skb);
+#else
+ ll_rs = LL_RESERVED_SPACE(rt->u.dst.dev);
+#endif
/*
* Fragment the datagram.
*/
* Allocate buffer.
*/
- if ((skb2 = alloc_skb(len+hlen+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) {
+ if ((skb2 = alloc_skb(len+hlen+ll_rs, GFP_ATOMIC)) == NULL) {
NETDEBUG(printk(KERN_INFO "IP: frag: no memory for new fragment!\n"));
err = -ENOMEM;
goto fail;
*/
ip_copy_metadata(skb2, skb);
- skb_reserve(skb2, LL_RESERVED_SPACE(rt->u.dst.dev));
+ skb_reserve(skb2, ll_rs);
skb_put(skb2, len + hlen);
skb2->nh.raw = skb2->data;
skb2->h.raw = skb2->data + hlen;
#
# Makefile for the IPVS modules on top of IPv4.
#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definition is now in the main makefile...
-
# IPVS transport protocol load balancing support
ip_vs_proto-objs-y :=
panic("IP: failed to allocate ip_dst_cache\n");
goal = num_physpages >> (26 - PAGE_SHIFT);
- if (!rhash_entries)
- goal = min(10, goal);
- else
+ if (rhash_entries)
goal = (rhash_entries * sizeof(struct rt_hash_bucket)) >> PAGE_SHIFT;
for (order = 0; (1UL << order) < goal; order++)
/* NOTHING */;
else
goal = num_physpages >> (23 - PAGE_SHIFT);
- if (!thash_entries)
- goal = min(10UL, goal);
- else
+ if (thash_entries)
goal = (thash_entries * sizeof(struct tcp_ehash_bucket)) >> PAGE_SHIFT;
for (order = 0; (1UL << order) < goal; order++)
;
if ((err = sock_create(PF_INET, type, proto, &sock)) < 0) {
printk("RPC: can't create socket (%d).\n", -err);
- goto failed;
+ return NULL;
}
/* If the caller has the capability, bind to a reserved port */
skpair=unix_peer(sk);
if (skpair!=NULL) {
- if (sk->sk_type == SOCK_STREAM) {
+ if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
unix_state_wlock(skpair);
/* No more writes */
skpair->sk_shutdown = SHUTDOWN_MASK;
struct unix_sock *u = unix_sk(sk);
err = -EOPNOTSUPP;
- if (sock->type!=SOCK_STREAM)
- goto out; /* Only stream sockets accept */
+ if (sock->type!=SOCK_STREAM && sock->type!=SOCK_SEQPACKET)
+ goto out; /* Only stream/seqpacket sockets accept */
err = -EINVAL;
if (!u->addr)
goto out; /* No listens on an unbound socket */
return err;
}
-extern struct proto_ops unix_stream_ops;
-extern struct proto_ops unix_dgram_ops;
+static int unix_release(struct socket *);
+static int unix_bind(struct socket *, struct sockaddr *, int);
+static int unix_stream_connect(struct socket *, struct sockaddr *,
+ int addr_len, int flags);
+static int unix_socketpair(struct socket *, struct socket *);
+static int unix_accept(struct socket *, struct socket *, int);
+static int unix_getname(struct socket *, struct sockaddr *, int *, int);
+static unsigned int unix_poll(struct file *, struct socket *, poll_table *);
+static int unix_ioctl(struct socket *, unsigned int, unsigned long);
+static int unix_shutdown(struct socket *, int);
+static int unix_stream_sendmsg(struct kiocb *, struct socket *,
+ struct msghdr *, size_t);
+static int unix_stream_recvmsg(struct kiocb *, struct socket *,
+ struct msghdr *, size_t, int);
+static int unix_dgram_sendmsg(struct kiocb *, struct socket *,
+ struct msghdr *, size_t);
+static int unix_dgram_recvmsg(struct kiocb *, struct socket *,
+ struct msghdr *, size_t, int);
+static int unix_dgram_connect(struct socket *, struct sockaddr *,
+ int, int);
+
+static struct proto_ops unix_stream_ops = {
+ .family = PF_UNIX,
+ .owner = THIS_MODULE,
+ .release = unix_release,
+ .bind = unix_bind,
+ .connect = unix_stream_connect,
+ .socketpair = unix_socketpair,
+ .accept = unix_accept,
+ .getname = unix_getname,
+ .poll = unix_poll,
+ .ioctl = unix_ioctl,
+ .listen = unix_listen,
+ .shutdown = unix_shutdown,
+ .setsockopt = sock_no_setsockopt,
+ .getsockopt = sock_no_getsockopt,
+ .sendmsg = unix_stream_sendmsg,
+ .recvmsg = unix_stream_recvmsg,
+ .mmap = sock_no_mmap,
+ .sendpage = sock_no_sendpage,
+};
+
+static struct proto_ops unix_dgram_ops = {
+ .family = PF_UNIX,
+ .owner = THIS_MODULE,
+ .release = unix_release,
+ .bind = unix_bind,
+ .connect = unix_dgram_connect,
+ .socketpair = unix_socketpair,
+ .accept = sock_no_accept,
+ .getname = unix_getname,
+ .poll = datagram_poll,
+ .ioctl = unix_ioctl,
+ .listen = sock_no_listen,
+ .shutdown = unix_shutdown,
+ .setsockopt = sock_no_setsockopt,
+ .getsockopt = sock_no_getsockopt,
+ .sendmsg = unix_dgram_sendmsg,
+ .recvmsg = unix_dgram_recvmsg,
+ .mmap = sock_no_mmap,
+ .sendpage = sock_no_sendpage,
+};
+
+static struct proto_ops unix_seqpacket_ops = {
+ .family = PF_UNIX,
+ .owner = THIS_MODULE,
+ .release = unix_release,
+ .bind = unix_bind,
+ .connect = unix_stream_connect,
+ .socketpair = unix_socketpair,
+ .accept = unix_accept,
+ .getname = unix_getname,
+ .poll = datagram_poll,
+ .ioctl = unix_ioctl,
+ .listen = unix_listen,
+ .shutdown = unix_shutdown,
+ .setsockopt = sock_no_setsockopt,
+ .getsockopt = sock_no_getsockopt,
+ .sendmsg = unix_dgram_sendmsg,
+ .recvmsg = unix_dgram_recvmsg,
+ .mmap = sock_no_mmap,
+ .sendpage = sock_no_sendpage,
+};
static struct sock * unix_create1(struct socket *sock)
{
case SOCK_DGRAM:
sock->ops = &unix_dgram_ops;
break;
+ case SOCK_SEQPACKET:
+ sock->ops = &unix_seqpacket_ops;
+ break;
default:
return -ESOCKTNOSUPPORT;
}
sock_hold(sk);
unix_peer(newsk) = sk;
newsk->sk_state = TCP_ESTABLISHED;
- newsk->sk_type = SOCK_STREAM;
+ newsk->sk_type = sk->sk_type;
newsk->sk_peercred.pid = current->tgid;
newsk->sk_peercred.uid = current->euid;
newsk->sk_peercred.gid = current->egid;
int err;
err = -EOPNOTSUPP;
- if (sock->type!=SOCK_STREAM)
+ if (sock->type!=SOCK_STREAM && sock->type!=SOCK_SEQPACKET)
goto out;
err = -EINVAL;
unix_state_wunlock(sk);
sk->sk_state_change(sk);
- if (other && sk->sk_type == SOCK_STREAM) {
+ if (other &&
+ (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) {
+
int peer_mode = 0;
if (mode&RCV_SHUTDOWN)
mask |= POLLIN | POLLRDNORM;
/* Connection-based need to check for termination and startup */
- if (sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_CLOSE)
+ if ((sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) && sk->sk_state == TCP_CLOSE)
mask |= POLLHUP;
/*
return 0;
}
-struct seq_operations unix_seq_ops = {
+static struct seq_operations unix_seq_ops = {
.start = unix_seq_start,
.next = unix_seq_next,
.stop = unix_seq_stop,
#endif
-struct proto_ops unix_stream_ops = {
- .family = PF_UNIX,
- .owner = THIS_MODULE,
- .release = unix_release,
- .bind = unix_bind,
- .connect = unix_stream_connect,
- .socketpair = unix_socketpair,
- .accept = unix_accept,
- .getname = unix_getname,
- .poll = unix_poll,
- .ioctl = unix_ioctl,
- .listen = unix_listen,
- .shutdown = unix_shutdown,
- .setsockopt = sock_no_setsockopt,
- .getsockopt = sock_no_getsockopt,
- .sendmsg = unix_stream_sendmsg,
- .recvmsg = unix_stream_recvmsg,
- .mmap = sock_no_mmap,
- .sendpage = sock_no_sendpage,
-};
-
-struct proto_ops unix_dgram_ops = {
- .family = PF_UNIX,
- .owner = THIS_MODULE,
- .release = unix_release,
- .bind = unix_bind,
- .connect = unix_dgram_connect,
- .socketpair = unix_socketpair,
- .accept = sock_no_accept,
- .getname = unix_getname,
- .poll = datagram_poll,
- .ioctl = unix_ioctl,
- .listen = sock_no_listen,
- .shutdown = unix_shutdown,
- .setsockopt = sock_no_setsockopt,
- .getsockopt = sock_no_getsockopt,
- .sendmsg = unix_dgram_sendmsg,
- .recvmsg = unix_dgram_recvmsg,
- .mmap = sock_no_mmap,
- .sendpage = sock_no_sendpage,
-};
-
-struct net_proto_family unix_family_ops = {
+static struct net_proto_family unix_family_ops = {
.family = PF_UNIX,
.create = unix_create,
.owner = THIS_MODULE,
#if KERNEL_ELFDATA != HOST_ELFDATA
-static void __endian(const void *src, void *dest, unsigned int size)
+static inline void __endian(const void *src, void *dest, unsigned int size)
{
unsigned int i;
for (i = 0; i < size; i++)