## Automatically generated incremental diff ## From: linux-2.6.4-rc1 ## To: linux-2.6.4-rc2 ## Robot: $Id: make-incremental-diff,v 1.12 2004/01/06 07:19:36 hpa Exp $ diff -urN linux-2.6.4-rc1/Documentation/00-INDEX linux-2.6.4-rc2/Documentation/00-INDEX --- linux-2.6.4-rc1/Documentation/00-INDEX 2004-02-17 19:57:20.000000000 -0800 +++ linux-2.6.4-rc2/Documentation/00-INDEX 2004-03-03 22:48:06.000000000 -0800 @@ -1,7 +1,7 @@ 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. @@ -26,10 +26,14 @@ - 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 @@ -42,6 +46,10 @@ - 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/ @@ -53,25 +61,31 @@ 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/ @@ -81,47 +95,51 @@ 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/ @@ -133,27 +151,27 @@ 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 @@ -165,11 +183,11 @@ 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/ @@ -181,29 +199,31 @@ 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 @@ -217,9 +237,9 @@ 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 @@ -230,7 +250,7 @@ - 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. @@ -238,4 +258,3 @@ - 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. - diff -urN linux-2.6.4-rc1/Documentation/networking/arcnet.txt linux-2.6.4-rc2/Documentation/networking/arcnet.txt --- linux-2.6.4-rc1/Documentation/networking/arcnet.txt 2004-02-17 19:57:13.000000000 -0800 +++ linux-2.6.4-rc2/Documentation/networking/arcnet.txt 2004-03-03 22:48:06.000000000 -0800 @@ -186,7 +186,6 @@ to the chipset support if you wish. make config - make dep make clean make zImage make modules diff -urN linux-2.6.4-rc1/Documentation/s390/CommonIO linux-2.6.4-rc2/Documentation/s390/CommonIO --- linux-2.6.4-rc1/Documentation/s390/CommonIO 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/Documentation/s390/CommonIO 2004-03-03 22:48:06.000000000 -0800 @@ -14,15 +14,6 @@ Default is off. -* cio_notoper_msg = yes | no - - Determines whether messages of the type "Device 0.0.4711 became 'not - operational'" should be shown during startup; after startup, they will always - be shown. - - Default is on. - - * cio_ignore = {all} | { | } | {! | !} diff -urN linux-2.6.4-rc1/Documentation/s390/driver-model.txt linux-2.6.4-rc2/Documentation/s390/driver-model.txt --- linux-2.6.4-rc1/Documentation/s390/driver-model.txt 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/Documentation/s390/driver-model.txt 2004-03-03 22:48:06.000000000 -0800 @@ -31,6 +31,9 @@ devtype: The device type / model, if applicable. +availability: Can be 'good' or 'boxed'; 'no path' or 'no device' for + disconnected devices. + online: An interface to set the device online and offline. In the special case of the device being disconnected (see the notify function under 1.2), piping 0 to online will focibly delete diff -urN linux-2.6.4-rc1/Documentation/sound/oss/rme96xx linux-2.6.4-rc2/Documentation/sound/oss/rme96xx --- linux-2.6.4-rc1/Documentation/sound/oss/rme96xx 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/Documentation/sound/oss/rme96xx 2004-03-03 22:48:06.000000000 -0800 @@ -0,0 +1,767 @@ +Beta release of the rme96xx (driver for RME 96XX cards like the +"Hammerfall" and the "Hammerfall light") + +Important: The driver module has to be installed on a freshly rebooted system, +otherwise the driver might not be able to acquire its buffers. + +features: + + - OSS programming interface (i.e. runs with standard OSS soundsoftware) + - OSS/Multichannel interface (OSS multichannel is done by just aquiring + more than 2 channels). The driver does not use more than one device + ( yet .. this feature may be implemented later ) + - more than one RME card supported + +The driver uses a specific multichannel interface, which I will document +when the driver gets stable. (take a look at the defines in rme96xx.h, +which adds blocked multichannel formats i.e instead of +lrlrlrlr --> llllrrrr etc. + +Use the "rmectrl" programm to look at the status of the card .. +or use xrmectrl, a GUI interface for the ctrl program. + +What you can do with the rmectrl program is to set the stereo device for +OSS emulation (e.g. if you use SPDIF out). + +You do: + +./ctrl offset 24 24 + +which makes the stereo device use channels 25 and 26. + +Guenter Geiger + +copy the first part of the attached source code into rmectrl.c +and the second part into xrmectrl (or get the program from +http://gige.xdv.org/pages/soft/pages/rme) + +to compile: gcc -o rmectrl rmectrl.c +------------------------------ snip ------------------------------------ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rme96xx.h" + +/* + remctrl.c + (C) 2000 Guenter Geiger + HP20020201 - Heiko Purnhagen +*/ + +/* # define DEVICE_NAME "/dev/mixer" */ +# define DEVICE_NAME "/dev/mixer1" + + +void usage(void) +{ + fprintf(stderr,"usage: rmectrl [/dev/mixer] [command [options]]\n\n"); + fprintf(stderr,"where command is one of:\n"); + fprintf(stderr," help show this help\n"); + fprintf(stderr," status show status bits\n"); + fprintf(stderr," control show control bits\n"); + fprintf(stderr," mix show mixer/offset status\n"); + fprintf(stderr," master set sync master\n"); + fprintf(stderr," pro set spdif out pro\n"); + fprintf(stderr," emphasis set spdif out emphasis\n"); + fprintf(stderr," dolby set spdif out no audio\n"); + fprintf(stderr," optout set spdif out optical\n"); + fprintf(stderr," wordclock set sync wordclock\n"); + fprintf(stderr," spdifin set spdif in (0=optical,1=coax,2=intern)\n"); + fprintf(stderr," syncref set sync source (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n"); + fprintf(stderr," adat1cd set ADAT1 on internal CD\n"); + fprintf(stderr," offset set dev (0..3) offset (0..25)\n"); + exit(-1); +} + + +int main(int argc, char* argv[]) +{ + int cards; + int ret; + int i; + double ft; + int fd, fdwr; + int param,orig; + rme_status_t stat; + rme_ctrl_t ctrl; + char *device; + int argidx; + + if (argc < 2) + usage(); + + if (*argv[1]=='/') { + device = argv[1]; + argidx = 2; + } + else { + device = DEVICE_NAME; + argidx = 1; + } + + fprintf(stdout,"mixer device %s\n",device); + if ((fd = open(device,O_RDONLY)) < 0) { + fprintf(stdout,"opening device failed\n"); + exit(-1); + } + + if ((fdwr = open(device,O_WRONLY)) < 0) { + fprintf(stdout,"opening device failed\n"); + exit(-1); + } + + if (argc < argidx+1) + usage(); + + if (!strcmp(argv[argidx],"help")) + usage(); + if (!strcmp(argv[argidx],"-h")) + usage(); + if (!strcmp(argv[argidx],"--help")) + usage(); + + if (!strcmp(argv[argidx],"status")) { + ioctl(fd,SOUND_MIXER_PRIVATE2,&stat); + fprintf(stdout,"stat.irq %d\n",stat.irq); + fprintf(stdout,"stat.lockmask %d\n",stat.lockmask); + fprintf(stdout,"stat.sr48 %d\n",stat.sr48); + fprintf(stdout,"stat.wclock %d\n",stat.wclock); + fprintf(stdout,"stat.bufpoint %d\n",stat.bufpoint); + fprintf(stdout,"stat.syncmask %d\n",stat.syncmask); + fprintf(stdout,"stat.doublespeed %d\n",stat.doublespeed); + fprintf(stdout,"stat.tc_busy %d\n",stat.tc_busy); + fprintf(stdout,"stat.tc_out %d\n",stat.tc_out); + fprintf(stdout,"stat.crystalrate %d (0=64k 3=96k 4=88.2k 5=48k 6=44.1k 7=32k)\n",stat.crystalrate); + fprintf(stdout,"stat.spdif_error %d\n",stat.spdif_error); + fprintf(stdout,"stat.bufid %d\n",stat.bufid); + fprintf(stdout,"stat.tc_valid %d\n",stat.tc_valid); + exit (0); + } + + if (!strcmp(argv[argidx],"control")) { + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + fprintf(stdout,"ctrl.start %d\n",ctrl.start); + fprintf(stdout,"ctrl.latency %d (0=64 .. 7=8192)\n",ctrl.latency); + fprintf(stdout,"ctrl.master %d\n",ctrl.master); + fprintf(stdout,"ctrl.ie %d\n",ctrl.ie); + fprintf(stdout,"ctrl.sr48 %d\n",ctrl.sr48); + fprintf(stdout,"ctrl.spare %d\n",ctrl.spare); + fprintf(stdout,"ctrl.doublespeed %d\n",ctrl.doublespeed); + fprintf(stdout,"ctrl.pro %d\n",ctrl.pro); + fprintf(stdout,"ctrl.emphasis %d\n",ctrl.emphasis); + fprintf(stdout,"ctrl.dolby %d\n",ctrl.dolby); + fprintf(stdout,"ctrl.opt_out %d\n",ctrl.opt_out); + fprintf(stdout,"ctrl.wordclock %d\n",ctrl.wordclock); + fprintf(stdout,"ctrl.spdif_in %d (0=optical,1=coax,2=intern)\n",ctrl.spdif_in); + fprintf(stdout,"ctrl.sync_ref %d (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n",ctrl.sync_ref); + fprintf(stdout,"ctrl.spdif_reset %d\n",ctrl.spdif_reset); + fprintf(stdout,"ctrl.spdif_select %d\n",ctrl.spdif_select); + fprintf(stdout,"ctrl.spdif_clock %d\n",ctrl.spdif_clock); + fprintf(stdout,"ctrl.spdif_write %d\n",ctrl.spdif_write); + fprintf(stdout,"ctrl.adat1_cd %d\n",ctrl.adat1_cd); + exit (0); + } + + if (!strcmp(argv[argidx],"mix")) { + rme_mixer mix; + int i; + + for (i=0; i<4; i++) { + mix.devnr = i; + ioctl(fd,SOUND_MIXER_PRIVATE1,&mix); + if (mix.devnr == i) { + fprintf(stdout,"devnr %d\n",mix.devnr); + fprintf(stdout,"mix.i_offset %2d (0-25)\n",mix.i_offset); + fprintf(stdout,"mix.o_offset %2d (0-25)\n",mix.o_offset); + } + } + exit (0); + } + +/* the control flags */ + + if (argc < argidx+2) + usage(); + + if (!strcmp(argv[argidx],"master")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("master = %d\n",val); + ctrl.master = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"pro")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("pro = %d\n",val); + ctrl.pro = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"emphasis")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("emphasis = %d\n",val); + ctrl.emphasis = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"dolby")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("dolby = %d\n",val); + ctrl.dolby = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"optout")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("optout = %d\n",val); + ctrl.opt_out = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"wordclock")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("wordclock = %d\n",val); + ctrl.wordclock = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"spdifin")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("spdifin = %d\n",val); + ctrl.spdif_in = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"syncref")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("syncref = %d\n",val); + ctrl.sync_ref = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"adat1cd")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("adat1cd = %d\n",val); + ctrl.adat1_cd = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + +/* setting offset */ + + if (argc < argidx+4) + usage(); + + if (!strcmp(argv[argidx],"offset")) { + rme_mixer mix; + + mix.devnr = atoi(argv[argidx+1]); + + mix.i_offset = atoi(argv[argidx+2]); + mix.o_offset = atoi(argv[argidx+3]); + ioctl(fdwr,SOUND_MIXER_PRIVATE1,&mix); + fprintf(stdout,"devnr %d\n",mix.devnr); + fprintf(stdout,"mix.i_offset to %d\n",mix.i_offset); + fprintf(stdout,"mix.o_offset to %d\n",mix.o_offset); + exit (0); + } + + usage(); + exit (0); /* to avoid warning */ +} + + +---------------------------- -------------------------------- +#!/usr/bin/wish + +# xrmectrl +# (C) 2000 Guenter Geiger +# HP20020201 - Heiko Purnhagen + +#set defaults "-relief ridged" +set CTRLPROG "./rmectrl" +if {$argc} { + set CTRLPROG "$CTRLPROG $argv" +} +puts "CTRLPROG $CTRLPROG" + +frame .butts +button .butts.exit -text "Exit" -command "exit" -relief ridge +#button .butts.state -text "State" -command "get_all" + +pack .butts.exit -side left +pack .butts -side bottom + + +# +# STATUS +# + +frame .status + +# Sampling Rate + +frame .status.sr +label .status.sr.text -text "Sampling Rate" -justify left +radiobutton .status.sr.441 -selectcolor red -text "44.1 kHz" -width 10 -anchor nw -variable srate -value 44100 -font times +radiobutton .status.sr.480 -selectcolor red -text "48 kHz" -width 10 -anchor nw -variable srate -value 48000 -font times +radiobutton .status.sr.882 -selectcolor red -text "88.2 kHz" -width 10 -anchor nw -variable srate -value 88200 -font times +radiobutton .status.sr.960 -selectcolor red -text "96 kHz" -width 10 -anchor nw -variable srate -value 96000 -font times + +pack .status.sr.text .status.sr.441 .status.sr.480 .status.sr.882 .status.sr.960 -side top -padx 3 + +# Lock + +frame .status.lock +label .status.lock.text -text "Lock" -justify left +checkbutton .status.lock.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatlock1 -font times +checkbutton .status.lock.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatlock2 -font times +checkbutton .status.lock.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatlock3 -font times + +pack .status.lock.text .status.lock.adat1 .status.lock.adat2 .status.lock.adat3 -side top -padx 3 + +# Sync + +frame .status.sync +label .status.sync.text -text "Sync" -justify left +checkbutton .status.sync.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatsync1 -font times +checkbutton .status.sync.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatsync2 -font times +checkbutton .status.sync.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatsync3 -font times + +pack .status.sync.text .status.sync.adat1 .status.sync.adat2 .status.sync.adat3 -side top -padx 3 + +# Timecode + +frame .status.tc +label .status.tc.text -text "Timecode" -justify left +checkbutton .status.tc.busy -selectcolor red -text "busy" -anchor nw -width 10 -variable tcbusy -font times +checkbutton .status.tc.out -selectcolor red -text "out" -anchor nw -width 10 -variable tcout -font times +checkbutton .status.tc.valid -selectcolor red -text "valid" -anchor nw -width 10 -variable tcvalid -font times + +pack .status.tc.text .status.tc.busy .status.tc.out .status.tc.valid -side top -padx 3 + +# SPDIF In + +frame .status.spdif +label .status.spdif.text -text "SPDIF In" -justify left +label .status.spdif.sr -text "--.- kHz" -anchor n -width 10 -font times +checkbutton .status.spdif.error -selectcolor red -text "Input Lock" -anchor nw -width 10 -variable spdiferr -font times + +pack .status.spdif.text .status.spdif.sr .status.spdif.error -side top -padx 3 + +pack .status.sr .status.lock .status.sync .status.tc .status.spdif -side left -fill x -anchor n -expand 1 + + +# +# CONTROL +# + +proc setprof {} { + global CTRLPROG + global spprof + exec $CTRLPROG pro $spprof +} + +proc setemph {} { + global CTRLPROG + global spemph + exec $CTRLPROG emphasis $spemph +} + +proc setnoaud {} { + global CTRLPROG + global spnoaud + exec $CTRLPROG dolby $spnoaud +} + +proc setoptical {} { + global CTRLPROG + global spoptical + exec $CTRLPROG optout $spoptical +} + +proc setspdifin {} { + global CTRLPROG + global spdifin + exec $CTRLPROG spdifin [expr $spdifin - 1] +} + +proc setsyncsource {} { + global CTRLPROG + global syncsource + exec $CTRLPROG syncref [expr $syncsource -1] +} + + +proc setmaster {} { + global CTRLPROG + global master + exec $CTRLPROG master $master +} + +proc setwordclock {} { + global CTRLPROG + global wordclock + exec $CTRLPROG wordclock $wordclock +} + +proc setadat1cd {} { + global CTRLPROG + global adat1cd + exec $CTRLPROG adat1cd $adat1cd +} + + +frame .control + +# SPDIF In & SPDIF Out + + +frame .control.spdif + +frame .control.spdif.in +label .control.spdif.in.text -text "SPDIF In" -justify left +radiobutton .control.spdif.in.input1 -text "Optical" -anchor nw -width 13 -variable spdifin -value 1 -command setspdifin -selectcolor blue -font times +radiobutton .control.spdif.in.input2 -text "Coaxial" -anchor nw -width 13 -variable spdifin -value 2 -command setspdifin -selectcolor blue -font times +radiobutton .control.spdif.in.input3 -text "Intern " -anchor nw -width 13 -variable spdifin -command setspdifin -value 3 -selectcolor blue -font times + +checkbutton .control.spdif.in.adat1cd -text "ADAT1 Intern" -anchor nw -width 13 -variable adat1cd -command setadat1cd -selectcolor blue -font times + +pack .control.spdif.in.text .control.spdif.in.input1 .control.spdif.in.input2 .control.spdif.in.input3 .control.spdif.in.adat1cd + +label .control.spdif.space + +frame .control.spdif.out +label .control.spdif.out.text -text "SPDIF Out" -justify left +checkbutton .control.spdif.out.pro -text "Professional" -anchor nw -width 13 -variable spprof -command setprof -selectcolor blue -font times +checkbutton .control.spdif.out.emphasis -text "Emphasis" -anchor nw -width 13 -variable spemph -command setemph -selectcolor blue -font times +checkbutton .control.spdif.out.dolby -text "NoAudio" -anchor nw -width 13 -variable spnoaud -command setnoaud -selectcolor blue -font times +checkbutton .control.spdif.out.optout -text "Optical Out" -anchor nw -width 13 -variable spoptical -command setoptical -selectcolor blue -font times + +pack .control.spdif.out.optout .control.spdif.out.dolby .control.spdif.out.emphasis .control.spdif.out.pro .control.spdif.out.text -side bottom + +pack .control.spdif.in .control.spdif.space .control.spdif.out -side top -fill y -padx 3 -expand 1 + +# Sync Mode & Sync Source + +frame .control.sync +frame .control.sync.mode +label .control.sync.mode.text -text "Sync Mode" -justify left +checkbutton .control.sync.mode.master -text "Master" -anchor nw -width 13 -variable master -command setmaster -selectcolor blue -font times +checkbutton .control.sync.mode.wc -text "Wordclock" -anchor nw -width 13 -variable wordclock -command setwordclock -selectcolor blue -font times + +pack .control.sync.mode.text .control.sync.mode.master .control.sync.mode.wc + +label .control.sync.space + +frame .control.sync.src +label .control.sync.src.text -text "Sync Source" -justify left +radiobutton .control.sync.src.input1 -text "ADAT1" -anchor nw -width 13 -variable syncsource -value 1 -command setsyncsource -selectcolor blue -font times +radiobutton .control.sync.src.input2 -text "ADAT2" -anchor nw -width 13 -variable syncsource -value 2 -command setsyncsource -selectcolor blue -font times +radiobutton .control.sync.src.input3 -text "ADAT3" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 3 -selectcolor blue -font times +radiobutton .control.sync.src.input4 -text "SPDIF" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 4 -selectcolor blue -font times + +pack .control.sync.src.input4 .control.sync.src.input3 .control.sync.src.input2 .control.sync.src.input1 .control.sync.src.text -side bottom + +pack .control.sync.mode .control.sync.space .control.sync.src -side top -fill y -padx 3 -expand 1 + +label .control.space -text "" -width 10 + +# Buffer Size + +frame .control.buf +label .control.buf.text -text "Buffer Size (Latency)" -justify left +radiobutton .control.buf.b1 -selectcolor red -text "64 (1.5 ms)" -width 13 -anchor nw -variable ssrate -value 1 -font times +radiobutton .control.buf.b2 -selectcolor red -text "128 (3 ms)" -width 13 -anchor nw -variable ssrate -value 2 -font times +radiobutton .control.buf.b3 -selectcolor red -text "256 (6 ms)" -width 13 -anchor nw -variable ssrate -value 3 -font times +radiobutton .control.buf.b4 -selectcolor red -text "512 (12 ms)" -width 13 -anchor nw -variable ssrate -value 4 -font times +radiobutton .control.buf.b5 -selectcolor red -text "1024 (23 ms)" -width 13 -anchor nw -variable ssrate -value 5 -font times +radiobutton .control.buf.b6 -selectcolor red -text "2048 (46 ms)" -width 13 -anchor nw -variable ssrate -value 6 -font times +radiobutton .control.buf.b7 -selectcolor red -text "4096 (93 ms)" -width 13 -anchor nw -variable ssrate -value 7 -font times +radiobutton .control.buf.b8 -selectcolor red -text "8192 (186 ms)" -width 13 -anchor nw -variable ssrate -value 8 -font times + +pack .control.buf.text .control.buf.b1 .control.buf.b2 .control.buf.b3 .control.buf.b4 .control.buf.b5 .control.buf.b6 .control.buf.b7 .control.buf.b8 -side top -padx 3 + +# Offset + +frame .control.offset + +frame .control.offset.in +label .control.offset.in.text -text "Offset In" -justify left +label .control.offset.in.off0 -text "dev\#0: -" -anchor nw -width 10 -font times +label .control.offset.in.off1 -text "dev\#1: -" -anchor nw -width 10 -font times +label .control.offset.in.off2 -text "dev\#2: -" -anchor nw -width 10 -font times +label .control.offset.in.off3 -text "dev\#3: -" -anchor nw -width 10 -font times + +pack .control.offset.in.text .control.offset.in.off0 .control.offset.in.off1 .control.offset.in.off2 .control.offset.in.off3 + +label .control.offset.space + +frame .control.offset.out +label .control.offset.out.text -text "Offset Out" -justify left +label .control.offset.out.off0 -text "dev\#0: -" -anchor nw -width 10 -font times +label .control.offset.out.off1 -text "dev\#1: -" -anchor nw -width 10 -font times +label .control.offset.out.off2 -text "dev\#2: -" -anchor nw -width 10 -font times +label .control.offset.out.off3 -text "dev\#3: -" -anchor nw -width 10 -font times + +pack .control.offset.out.off3 .control.offset.out.off2 .control.offset.out.off1 .control.offset.out.off0 .control.offset.out.text -side bottom + +pack .control.offset.in .control.offset.space .control.offset.out -side top -fill y -padx 3 -expand 1 + + +pack .control.spdif .control.sync .control.space .control.buf .control.offset -side left -fill both -anchor n -expand 1 + + +label .statustext -text Status -justify center -relief ridge +label .controltext -text Control -justify center -relief ridge + +label .statusspace +label .controlspace + +pack .statustext .status .statusspace .controltext .control .controlspace -side top -anchor nw -fill both -expand 1 + + +proc get_bit {output sstr} { + set idx1 [string last [concat $sstr 1] $output] + set idx1 [expr $idx1 != -1] + return $idx1 +} + +proc get_val {output sstr} { + set val [string wordend $output [string last $sstr $output]] + set val [string range $output $val [expr $val+1]] + return $val +} + +proc get_val2 {output sstr} { + set val [string wordend $output [string first $sstr $output]] + set val [string range $output $val [expr $val+2]] + return $val +} + +proc get_control {} { + global spprof + global spemph + global spnoaud + global spoptical + global spdifin + global ssrate + global master + global wordclock + global syncsource + global CTRLPROG + + set f [open "| $CTRLPROG control" r+] + set ooo [read $f 1000] + close $f +# puts $ooo + + set spprof [ get_bit $ooo "pro"] + set spemph [ get_bit $ooo "emphasis"] + set spnoaud [ get_bit $ooo "dolby"] + set spoptical [ get_bit $ooo "opt_out"] + set spdifin [ expr [ get_val $ooo "spdif_in"] + 1] + set ssrate [ expr [ get_val $ooo "latency"] + 1] + set master [ expr [ get_val $ooo "master"]] + set wordclock [ expr [ get_val $ooo "wordclock"]] + set syncsource [ expr [ get_val $ooo "sync_ref"] + 1] +} + +proc get_status {} { + global srate + global ctrlcom + + global adatlock1 + global adatlock2 + global adatlock3 + + global adatsync1 + global adatsync2 + global adatsync3 + + global tcbusy + global tcout + global tcvalid + + global spdiferr + global crystal + global .status.spdif.text + global CTRLPROG + + + set f [open "| $CTRLPROG status" r+] + set ooo [read $f 1000] + close $f +# puts $ooo + +# samplerate + + set idx1 [string last "sr48 1" $ooo] + set idx2 [string last "doublespeed 1" $ooo] + if {$idx1 >= 0} { + set fact1 48000 + } else { + set fact1 44100 + } + + if {$idx2 >= 0} { + set fact2 2 + } else { + set fact2 1 + } + set srate [expr $fact1 * $fact2] +# ADAT lock + + set val [get_val $ooo lockmask] + set adatlock1 0 + set adatlock2 0 + set adatlock3 0 + if {[expr $val & 1]} { + set adatlock3 1 + } + if {[expr $val & 2]} { + set adatlock2 1 + } + if {[expr $val & 4]} { + set adatlock1 1 + } + +# ADAT sync + set val [get_val $ooo syncmask] + set adatsync1 0 + set adatsync2 0 + set adatsync3 0 + + if {[expr $val & 1]} { + set adatsync3 1 + } + if {[expr $val & 2]} { + set adatsync2 1 + } + if {[expr $val & 4]} { + set adatsync1 1 + } + +# TC busy + + set tcbusy [get_bit $ooo "busy"] + set tcout [get_bit $ooo "out"] + set tcvalid [get_bit $ooo "valid"] + set spdiferr [expr [get_bit $ooo "spdif_error"] == 0] + +# 000=64kHz, 100=88.2kHz, 011=96kHz +# 111=32kHz, 110=44.1kHz, 101=48kHz + + set val [get_val $ooo crystalrate] + + set crystal "--.- kHz" + if {$val == 0} { + set crystal "64 kHz" + } + if {$val == 4} { + set crystal "88.2 kHz" + } + if {$val == 3} { + set crystal "96 kHz" + } + if {$val == 7} { + set crystal "32 kHz" + } + if {$val == 6} { + set crystal "44.1 kHz" + } + if {$val == 5} { + set crystal "48 kHz" + } + .status.spdif.sr configure -text $crystal +} + +proc get_offset {} { + global inoffset + global outoffset + global CTRLPROG + + set f [open "| $CTRLPROG mix" r+] + set ooo [read $f 1000] + close $f +# puts $ooo + + if { [string match "*devnr*" $ooo] } { + set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] + set val [get_val2 $ooo i_offset] + .control.offset.in.off0 configure -text "dev\#0: $val" + set val [get_val2 $ooo o_offset] + .control.offset.out.off0 configure -text "dev\#0: $val" + } else { + .control.offset.in.off0 configure -text "dev\#0: -" + .control.offset.out.off0 configure -text "dev\#0: -" + } + if { [string match "*devnr*" $ooo] } { + set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] + set val [get_val2 $ooo i_offset] + .control.offset.in.off1 configure -text "dev\#1: $val" + set val [get_val2 $ooo o_offset] + .control.offset.out.off1 configure -text "dev\#1: $val" + } else { + .control.offset.in.off1 configure -text "dev\#1: -" + .control.offset.out.off1 configure -text "dev\#1: -" + } + if { [string match "*devnr*" $ooo] } { + set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] + set val [get_val2 $ooo i_offset] + .control.offset.in.off2 configure -text "dev\#2: $val" + set val [get_val2 $ooo o_offset] + .control.offset.out.off2 configure -text "dev\#2: $val" + } else { + .control.offset.in.off2 configure -text "dev\#2: -" + .control.offset.out.off2 configure -text "dev\#2: -" + } + if { [string match "*devnr*" $ooo] } { + set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] + set val [get_val2 $ooo i_offset] + .control.offset.in.off3 configure -text "dev\#3: $val" + set val [get_val2 $ooo o_offset] + .control.offset.out.off3 configure -text "dev\#3: $val" + } else { + .control.offset.in.off3 configure -text "dev\#3: -" + .control.offset.out.off3 configure -text "dev\#3: -" + } +} + + +proc get_all {} { +get_status +get_control +get_offset +} + +# main +while {1} { + after 200 + get_all + update +} diff -urN linux-2.6.4-rc1/Documentation/sound/rme96xx linux-2.6.4-rc2/Documentation/sound/rme96xx --- linux-2.6.4-rc1/Documentation/sound/rme96xx 2004-02-17 19:57:14.000000000 -0800 +++ linux-2.6.4-rc2/Documentation/sound/rme96xx 1969-12-31 16:00:00.000000000 -0800 @@ -1,767 +0,0 @@ -Beta release of the rme96xx (driver for RME 96XX cards like the -"Hammerfall" and the "Hammerfall light") - -Important: The driver module has to be installed on a freshly rebooted system, -otherwise the driver might not be able to acquire its buffers. - -features: - - - OSS programming interface (i.e. runs with standard OSS soundsoftware) - - OSS/Multichannel interface (OSS multichannel is done by just aquiring - more than 2 channels). The driver does not use more than one device - ( yet .. this feature may be implemented later ) - - more than one RME card supported - -The driver uses a specific multichannel interface, which I will document -when the driver gets stable. (take a look at the defines in rme96xx.h, -which adds blocked multichannel formats i.e instead of -lrlrlrlr --> llllrrrr etc. - -Use the "rmectrl" programm to look at the status of the card .. -or use xrmectrl, a GUI interface for the ctrl program. - -What you can do with the rmectrl program is to set the stereo device for -OSS emulation (e.g. if you use SPDIF out). - -You do: - -./ctrl offset 24 24 - -which makes the stereo device use channels 25 and 26. - -Guenter Geiger - -copy the first part of the attached source code into rmectrl.c -and the second part into xrmectrl (or get the program from -http://gige.xdv.org/pages/soft/pages/rme) - -to compile: gcc -o rmectrl rmectrl.c ------------------------------- snip ------------------------------------ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "rme96xx.h" - -/* - remctrl.c - (C) 2000 Guenter Geiger - HP20020201 - Heiko Purnhagen -*/ - -/* # define DEVICE_NAME "/dev/mixer" */ -# define DEVICE_NAME "/dev/mixer1" - - -void usage(void) -{ - fprintf(stderr,"usage: rmectrl [/dev/mixer] [command [options]]\n\n"); - fprintf(stderr,"where command is one of:\n"); - fprintf(stderr," help show this help\n"); - fprintf(stderr," status show status bits\n"); - fprintf(stderr," control show control bits\n"); - fprintf(stderr," mix show mixer/offset status\n"); - fprintf(stderr," master set sync master\n"); - fprintf(stderr," pro set spdif out pro\n"); - fprintf(stderr," emphasis set spdif out emphasis\n"); - fprintf(stderr," dolby set spdif out no audio\n"); - fprintf(stderr," optout set spdif out optical\n"); - fprintf(stderr," wordclock set sync wordclock\n"); - fprintf(stderr," spdifin set spdif in (0=optical,1=coax,2=intern)\n"); - fprintf(stderr," syncref set sync source (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n"); - fprintf(stderr," adat1cd set ADAT1 on internal CD\n"); - fprintf(stderr," offset set dev (0..3) offset (0..25)\n"); - exit(-1); -} - - -int main(int argc, char* argv[]) -{ - int cards; - int ret; - int i; - double ft; - int fd, fdwr; - int param,orig; - rme_status_t stat; - rme_ctrl_t ctrl; - char *device; - int argidx; - - if (argc < 2) - usage(); - - if (*argv[1]=='/') { - device = argv[1]; - argidx = 2; - } - else { - device = DEVICE_NAME; - argidx = 1; - } - - fprintf(stdout,"mixer device %s\n",device); - if ((fd = open(device,O_RDONLY)) < 0) { - fprintf(stdout,"opening device failed\n"); - exit(-1); - } - - if ((fdwr = open(device,O_WRONLY)) < 0) { - fprintf(stdout,"opening device failed\n"); - exit(-1); - } - - if (argc < argidx+1) - usage(); - - if (!strcmp(argv[argidx],"help")) - usage(); - if (!strcmp(argv[argidx],"-h")) - usage(); - if (!strcmp(argv[argidx],"--help")) - usage(); - - if (!strcmp(argv[argidx],"status")) { - ioctl(fd,SOUND_MIXER_PRIVATE2,&stat); - fprintf(stdout,"stat.irq %d\n",stat.irq); - fprintf(stdout,"stat.lockmask %d\n",stat.lockmask); - fprintf(stdout,"stat.sr48 %d\n",stat.sr48); - fprintf(stdout,"stat.wclock %d\n",stat.wclock); - fprintf(stdout,"stat.bufpoint %d\n",stat.bufpoint); - fprintf(stdout,"stat.syncmask %d\n",stat.syncmask); - fprintf(stdout,"stat.doublespeed %d\n",stat.doublespeed); - fprintf(stdout,"stat.tc_busy %d\n",stat.tc_busy); - fprintf(stdout,"stat.tc_out %d\n",stat.tc_out); - fprintf(stdout,"stat.crystalrate %d (0=64k 3=96k 4=88.2k 5=48k 6=44.1k 7=32k)\n",stat.crystalrate); - fprintf(stdout,"stat.spdif_error %d\n",stat.spdif_error); - fprintf(stdout,"stat.bufid %d\n",stat.bufid); - fprintf(stdout,"stat.tc_valid %d\n",stat.tc_valid); - exit (0); - } - - if (!strcmp(argv[argidx],"control")) { - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - fprintf(stdout,"ctrl.start %d\n",ctrl.start); - fprintf(stdout,"ctrl.latency %d (0=64 .. 7=8192)\n",ctrl.latency); - fprintf(stdout,"ctrl.master %d\n",ctrl.master); - fprintf(stdout,"ctrl.ie %d\n",ctrl.ie); - fprintf(stdout,"ctrl.sr48 %d\n",ctrl.sr48); - fprintf(stdout,"ctrl.spare %d\n",ctrl.spare); - fprintf(stdout,"ctrl.doublespeed %d\n",ctrl.doublespeed); - fprintf(stdout,"ctrl.pro %d\n",ctrl.pro); - fprintf(stdout,"ctrl.emphasis %d\n",ctrl.emphasis); - fprintf(stdout,"ctrl.dolby %d\n",ctrl.dolby); - fprintf(stdout,"ctrl.opt_out %d\n",ctrl.opt_out); - fprintf(stdout,"ctrl.wordclock %d\n",ctrl.wordclock); - fprintf(stdout,"ctrl.spdif_in %d (0=optical,1=coax,2=intern)\n",ctrl.spdif_in); - fprintf(stdout,"ctrl.sync_ref %d (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n",ctrl.sync_ref); - fprintf(stdout,"ctrl.spdif_reset %d\n",ctrl.spdif_reset); - fprintf(stdout,"ctrl.spdif_select %d\n",ctrl.spdif_select); - fprintf(stdout,"ctrl.spdif_clock %d\n",ctrl.spdif_clock); - fprintf(stdout,"ctrl.spdif_write %d\n",ctrl.spdif_write); - fprintf(stdout,"ctrl.adat1_cd %d\n",ctrl.adat1_cd); - exit (0); - } - - if (!strcmp(argv[argidx],"mix")) { - rme_mixer mix; - int i; - - for (i=0; i<4; i++) { - mix.devnr = i; - ioctl(fd,SOUND_MIXER_PRIVATE1,&mix); - if (mix.devnr == i) { - fprintf(stdout,"devnr %d\n",mix.devnr); - fprintf(stdout,"mix.i_offset %2d (0-25)\n",mix.i_offset); - fprintf(stdout,"mix.o_offset %2d (0-25)\n",mix.o_offset); - } - } - exit (0); - } - -/* the control flags */ - - if (argc < argidx+2) - usage(); - - if (!strcmp(argv[argidx],"master")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("master = %d\n",val); - ctrl.master = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"pro")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("pro = %d\n",val); - ctrl.pro = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"emphasis")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("emphasis = %d\n",val); - ctrl.emphasis = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"dolby")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("dolby = %d\n",val); - ctrl.dolby = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"optout")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("optout = %d\n",val); - ctrl.opt_out = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"wordclock")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("wordclock = %d\n",val); - ctrl.wordclock = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"spdifin")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("spdifin = %d\n",val); - ctrl.spdif_in = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"syncref")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("syncref = %d\n",val); - ctrl.sync_ref = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"adat1cd")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("adat1cd = %d\n",val); - ctrl.adat1_cd = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - -/* setting offset */ - - if (argc < argidx+4) - usage(); - - if (!strcmp(argv[argidx],"offset")) { - rme_mixer mix; - - mix.devnr = atoi(argv[argidx+1]); - - mix.i_offset = atoi(argv[argidx+2]); - mix.o_offset = atoi(argv[argidx+3]); - ioctl(fdwr,SOUND_MIXER_PRIVATE1,&mix); - fprintf(stdout,"devnr %d\n",mix.devnr); - fprintf(stdout,"mix.i_offset to %d\n",mix.i_offset); - fprintf(stdout,"mix.o_offset to %d\n",mix.o_offset); - exit (0); - } - - usage(); - exit (0); /* to avoid warning */ -} - - ----------------------------- -------------------------------- -#!/usr/bin/wish - -# xrmectrl -# (C) 2000 Guenter Geiger -# HP20020201 - Heiko Purnhagen - -#set defaults "-relief ridged" -set CTRLPROG "./rmectrl" -if {$argc} { - set CTRLPROG "$CTRLPROG $argv" -} -puts "CTRLPROG $CTRLPROG" - -frame .butts -button .butts.exit -text "Exit" -command "exit" -relief ridge -#button .butts.state -text "State" -command "get_all" - -pack .butts.exit -side left -pack .butts -side bottom - - -# -# STATUS -# - -frame .status - -# Sampling Rate - -frame .status.sr -label .status.sr.text -text "Sampling Rate" -justify left -radiobutton .status.sr.441 -selectcolor red -text "44.1 kHz" -width 10 -anchor nw -variable srate -value 44100 -font times -radiobutton .status.sr.480 -selectcolor red -text "48 kHz" -width 10 -anchor nw -variable srate -value 48000 -font times -radiobutton .status.sr.882 -selectcolor red -text "88.2 kHz" -width 10 -anchor nw -variable srate -value 88200 -font times -radiobutton .status.sr.960 -selectcolor red -text "96 kHz" -width 10 -anchor nw -variable srate -value 96000 -font times - -pack .status.sr.text .status.sr.441 .status.sr.480 .status.sr.882 .status.sr.960 -side top -padx 3 - -# Lock - -frame .status.lock -label .status.lock.text -text "Lock" -justify left -checkbutton .status.lock.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatlock1 -font times -checkbutton .status.lock.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatlock2 -font times -checkbutton .status.lock.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatlock3 -font times - -pack .status.lock.text .status.lock.adat1 .status.lock.adat2 .status.lock.adat3 -side top -padx 3 - -# Sync - -frame .status.sync -label .status.sync.text -text "Sync" -justify left -checkbutton .status.sync.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatsync1 -font times -checkbutton .status.sync.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatsync2 -font times -checkbutton .status.sync.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatsync3 -font times - -pack .status.sync.text .status.sync.adat1 .status.sync.adat2 .status.sync.adat3 -side top -padx 3 - -# Timecode - -frame .status.tc -label .status.tc.text -text "Timecode" -justify left -checkbutton .status.tc.busy -selectcolor red -text "busy" -anchor nw -width 10 -variable tcbusy -font times -checkbutton .status.tc.out -selectcolor red -text "out" -anchor nw -width 10 -variable tcout -font times -checkbutton .status.tc.valid -selectcolor red -text "valid" -anchor nw -width 10 -variable tcvalid -font times - -pack .status.tc.text .status.tc.busy .status.tc.out .status.tc.valid -side top -padx 3 - -# SPDIF In - -frame .status.spdif -label .status.spdif.text -text "SPDIF In" -justify left -label .status.spdif.sr -text "--.- kHz" -anchor n -width 10 -font times -checkbutton .status.spdif.error -selectcolor red -text "Input Lock" -anchor nw -width 10 -variable spdiferr -font times - -pack .status.spdif.text .status.spdif.sr .status.spdif.error -side top -padx 3 - -pack .status.sr .status.lock .status.sync .status.tc .status.spdif -side left -fill x -anchor n -expand 1 - - -# -# CONTROL -# - -proc setprof {} { - global CTRLPROG - global spprof - exec $CTRLPROG pro $spprof -} - -proc setemph {} { - global CTRLPROG - global spemph - exec $CTRLPROG emphasis $spemph -} - -proc setnoaud {} { - global CTRLPROG - global spnoaud - exec $CTRLPROG dolby $spnoaud -} - -proc setoptical {} { - global CTRLPROG - global spoptical - exec $CTRLPROG optout $spoptical -} - -proc setspdifin {} { - global CTRLPROG - global spdifin - exec $CTRLPROG spdifin [expr $spdifin - 1] -} - -proc setsyncsource {} { - global CTRLPROG - global syncsource - exec $CTRLPROG syncref [expr $syncsource -1] -} - - -proc setmaster {} { - global CTRLPROG - global master - exec $CTRLPROG master $master -} - -proc setwordclock {} { - global CTRLPROG - global wordclock - exec $CTRLPROG wordclock $wordclock -} - -proc setadat1cd {} { - global CTRLPROG - global adat1cd - exec $CTRLPROG adat1cd $adat1cd -} - - -frame .control - -# SPDIF In & SPDIF Out - - -frame .control.spdif - -frame .control.spdif.in -label .control.spdif.in.text -text "SPDIF In" -justify left -radiobutton .control.spdif.in.input1 -text "Optical" -anchor nw -width 13 -variable spdifin -value 1 -command setspdifin -selectcolor blue -font times -radiobutton .control.spdif.in.input2 -text "Coaxial" -anchor nw -width 13 -variable spdifin -value 2 -command setspdifin -selectcolor blue -font times -radiobutton .control.spdif.in.input3 -text "Intern " -anchor nw -width 13 -variable spdifin -command setspdifin -value 3 -selectcolor blue -font times - -checkbutton .control.spdif.in.adat1cd -text "ADAT1 Intern" -anchor nw -width 13 -variable adat1cd -command setadat1cd -selectcolor blue -font times - -pack .control.spdif.in.text .control.spdif.in.input1 .control.spdif.in.input2 .control.spdif.in.input3 .control.spdif.in.adat1cd - -label .control.spdif.space - -frame .control.spdif.out -label .control.spdif.out.text -text "SPDIF Out" -justify left -checkbutton .control.spdif.out.pro -text "Professional" -anchor nw -width 13 -variable spprof -command setprof -selectcolor blue -font times -checkbutton .control.spdif.out.emphasis -text "Emphasis" -anchor nw -width 13 -variable spemph -command setemph -selectcolor blue -font times -checkbutton .control.spdif.out.dolby -text "NoAudio" -anchor nw -width 13 -variable spnoaud -command setnoaud -selectcolor blue -font times -checkbutton .control.spdif.out.optout -text "Optical Out" -anchor nw -width 13 -variable spoptical -command setoptical -selectcolor blue -font times - -pack .control.spdif.out.optout .control.spdif.out.dolby .control.spdif.out.emphasis .control.spdif.out.pro .control.spdif.out.text -side bottom - -pack .control.spdif.in .control.spdif.space .control.spdif.out -side top -fill y -padx 3 -expand 1 - -# Sync Mode & Sync Source - -frame .control.sync -frame .control.sync.mode -label .control.sync.mode.text -text "Sync Mode" -justify left -checkbutton .control.sync.mode.master -text "Master" -anchor nw -width 13 -variable master -command setmaster -selectcolor blue -font times -checkbutton .control.sync.mode.wc -text "Wordclock" -anchor nw -width 13 -variable wordclock -command setwordclock -selectcolor blue -font times - -pack .control.sync.mode.text .control.sync.mode.master .control.sync.mode.wc - -label .control.sync.space - -frame .control.sync.src -label .control.sync.src.text -text "Sync Source" -justify left -radiobutton .control.sync.src.input1 -text "ADAT1" -anchor nw -width 13 -variable syncsource -value 1 -command setsyncsource -selectcolor blue -font times -radiobutton .control.sync.src.input2 -text "ADAT2" -anchor nw -width 13 -variable syncsource -value 2 -command setsyncsource -selectcolor blue -font times -radiobutton .control.sync.src.input3 -text "ADAT3" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 3 -selectcolor blue -font times -radiobutton .control.sync.src.input4 -text "SPDIF" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 4 -selectcolor blue -font times - -pack .control.sync.src.input4 .control.sync.src.input3 .control.sync.src.input2 .control.sync.src.input1 .control.sync.src.text -side bottom - -pack .control.sync.mode .control.sync.space .control.sync.src -side top -fill y -padx 3 -expand 1 - -label .control.space -text "" -width 10 - -# Buffer Size - -frame .control.buf -label .control.buf.text -text "Buffer Size (Latency)" -justify left -radiobutton .control.buf.b1 -selectcolor red -text "64 (1.5 ms)" -width 13 -anchor nw -variable ssrate -value 1 -font times -radiobutton .control.buf.b2 -selectcolor red -text "128 (3 ms)" -width 13 -anchor nw -variable ssrate -value 2 -font times -radiobutton .control.buf.b3 -selectcolor red -text "256 (6 ms)" -width 13 -anchor nw -variable ssrate -value 3 -font times -radiobutton .control.buf.b4 -selectcolor red -text "512 (12 ms)" -width 13 -anchor nw -variable ssrate -value 4 -font times -radiobutton .control.buf.b5 -selectcolor red -text "1024 (23 ms)" -width 13 -anchor nw -variable ssrate -value 5 -font times -radiobutton .control.buf.b6 -selectcolor red -text "2048 (46 ms)" -width 13 -anchor nw -variable ssrate -value 6 -font times -radiobutton .control.buf.b7 -selectcolor red -text "4096 (93 ms)" -width 13 -anchor nw -variable ssrate -value 7 -font times -radiobutton .control.buf.b8 -selectcolor red -text "8192 (186 ms)" -width 13 -anchor nw -variable ssrate -value 8 -font times - -pack .control.buf.text .control.buf.b1 .control.buf.b2 .control.buf.b3 .control.buf.b4 .control.buf.b5 .control.buf.b6 .control.buf.b7 .control.buf.b8 -side top -padx 3 - -# Offset - -frame .control.offset - -frame .control.offset.in -label .control.offset.in.text -text "Offset In" -justify left -label .control.offset.in.off0 -text "dev\#0: -" -anchor nw -width 10 -font times -label .control.offset.in.off1 -text "dev\#1: -" -anchor nw -width 10 -font times -label .control.offset.in.off2 -text "dev\#2: -" -anchor nw -width 10 -font times -label .control.offset.in.off3 -text "dev\#3: -" -anchor nw -width 10 -font times - -pack .control.offset.in.text .control.offset.in.off0 .control.offset.in.off1 .control.offset.in.off2 .control.offset.in.off3 - -label .control.offset.space - -frame .control.offset.out -label .control.offset.out.text -text "Offset Out" -justify left -label .control.offset.out.off0 -text "dev\#0: -" -anchor nw -width 10 -font times -label .control.offset.out.off1 -text "dev\#1: -" -anchor nw -width 10 -font times -label .control.offset.out.off2 -text "dev\#2: -" -anchor nw -width 10 -font times -label .control.offset.out.off3 -text "dev\#3: -" -anchor nw -width 10 -font times - -pack .control.offset.out.off3 .control.offset.out.off2 .control.offset.out.off1 .control.offset.out.off0 .control.offset.out.text -side bottom - -pack .control.offset.in .control.offset.space .control.offset.out -side top -fill y -padx 3 -expand 1 - - -pack .control.spdif .control.sync .control.space .control.buf .control.offset -side left -fill both -anchor n -expand 1 - - -label .statustext -text Status -justify center -relief ridge -label .controltext -text Control -justify center -relief ridge - -label .statusspace -label .controlspace - -pack .statustext .status .statusspace .controltext .control .controlspace -side top -anchor nw -fill both -expand 1 - - -proc get_bit {output sstr} { - set idx1 [string last [concat $sstr 1] $output] - set idx1 [expr $idx1 != -1] - return $idx1 -} - -proc get_val {output sstr} { - set val [string wordend $output [string last $sstr $output]] - set val [string range $output $val [expr $val+1]] - return $val -} - -proc get_val2 {output sstr} { - set val [string wordend $output [string first $sstr $output]] - set val [string range $output $val [expr $val+2]] - return $val -} - -proc get_control {} { - global spprof - global spemph - global spnoaud - global spoptical - global spdifin - global ssrate - global master - global wordclock - global syncsource - global CTRLPROG - - set f [open "| $CTRLPROG control" r+] - set ooo [read $f 1000] - close $f -# puts $ooo - - set spprof [ get_bit $ooo "pro"] - set spemph [ get_bit $ooo "emphasis"] - set spnoaud [ get_bit $ooo "dolby"] - set spoptical [ get_bit $ooo "opt_out"] - set spdifin [ expr [ get_val $ooo "spdif_in"] + 1] - set ssrate [ expr [ get_val $ooo "latency"] + 1] - set master [ expr [ get_val $ooo "master"]] - set wordclock [ expr [ get_val $ooo "wordclock"]] - set syncsource [ expr [ get_val $ooo "sync_ref"] + 1] -} - -proc get_status {} { - global srate - global ctrlcom - - global adatlock1 - global adatlock2 - global adatlock3 - - global adatsync1 - global adatsync2 - global adatsync3 - - global tcbusy - global tcout - global tcvalid - - global spdiferr - global crystal - global .status.spdif.text - global CTRLPROG - - - set f [open "| $CTRLPROG status" r+] - set ooo [read $f 1000] - close $f -# puts $ooo - -# samplerate - - set idx1 [string last "sr48 1" $ooo] - set idx2 [string last "doublespeed 1" $ooo] - if {$idx1 >= 0} { - set fact1 48000 - } else { - set fact1 44100 - } - - if {$idx2 >= 0} { - set fact2 2 - } else { - set fact2 1 - } - set srate [expr $fact1 * $fact2] -# ADAT lock - - set val [get_val $ooo lockmask] - set adatlock1 0 - set adatlock2 0 - set adatlock3 0 - if {[expr $val & 1]} { - set adatlock3 1 - } - if {[expr $val & 2]} { - set adatlock2 1 - } - if {[expr $val & 4]} { - set adatlock1 1 - } - -# ADAT sync - set val [get_val $ooo syncmask] - set adatsync1 0 - set adatsync2 0 - set adatsync3 0 - - if {[expr $val & 1]} { - set adatsync3 1 - } - if {[expr $val & 2]} { - set adatsync2 1 - } - if {[expr $val & 4]} { - set adatsync1 1 - } - -# TC busy - - set tcbusy [get_bit $ooo "busy"] - set tcout [get_bit $ooo "out"] - set tcvalid [get_bit $ooo "valid"] - set spdiferr [expr [get_bit $ooo "spdif_error"] == 0] - -# 000=64kHz, 100=88.2kHz, 011=96kHz -# 111=32kHz, 110=44.1kHz, 101=48kHz - - set val [get_val $ooo crystalrate] - - set crystal "--.- kHz" - if {$val == 0} { - set crystal "64 kHz" - } - if {$val == 4} { - set crystal "88.2 kHz" - } - if {$val == 3} { - set crystal "96 kHz" - } - if {$val == 7} { - set crystal "32 kHz" - } - if {$val == 6} { - set crystal "44.1 kHz" - } - if {$val == 5} { - set crystal "48 kHz" - } - .status.spdif.sr configure -text $crystal -} - -proc get_offset {} { - global inoffset - global outoffset - global CTRLPROG - - set f [open "| $CTRLPROG mix" r+] - set ooo [read $f 1000] - close $f -# puts $ooo - - if { [string match "*devnr*" $ooo] } { - set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] - set val [get_val2 $ooo i_offset] - .control.offset.in.off0 configure -text "dev\#0: $val" - set val [get_val2 $ooo o_offset] - .control.offset.out.off0 configure -text "dev\#0: $val" - } else { - .control.offset.in.off0 configure -text "dev\#0: -" - .control.offset.out.off0 configure -text "dev\#0: -" - } - if { [string match "*devnr*" $ooo] } { - set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] - set val [get_val2 $ooo i_offset] - .control.offset.in.off1 configure -text "dev\#1: $val" - set val [get_val2 $ooo o_offset] - .control.offset.out.off1 configure -text "dev\#1: $val" - } else { - .control.offset.in.off1 configure -text "dev\#1: -" - .control.offset.out.off1 configure -text "dev\#1: -" - } - if { [string match "*devnr*" $ooo] } { - set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] - set val [get_val2 $ooo i_offset] - .control.offset.in.off2 configure -text "dev\#2: $val" - set val [get_val2 $ooo o_offset] - .control.offset.out.off2 configure -text "dev\#2: $val" - } else { - .control.offset.in.off2 configure -text "dev\#2: -" - .control.offset.out.off2 configure -text "dev\#2: -" - } - if { [string match "*devnr*" $ooo] } { - set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] - set val [get_val2 $ooo i_offset] - .control.offset.in.off3 configure -text "dev\#3: $val" - set val [get_val2 $ooo o_offset] - .control.offset.out.off3 configure -text "dev\#3: $val" - } else { - .control.offset.in.off3 configure -text "dev\#3: -" - .control.offset.out.off3 configure -text "dev\#3: -" - } -} - - -proc get_all {} { -get_status -get_control -get_offset -} - -# main -while {1} { - after 200 - get_all - update -} diff -urN linux-2.6.4-rc1/MAINTAINERS linux-2.6.4-rc2/MAINTAINERS --- linux-2.6.4-rc1/MAINTAINERS 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/MAINTAINERS 2004-03-03 22:48:06.000000000 -0800 @@ -2395,7 +2395,7 @@ 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 diff -urN linux-2.6.4-rc1/Makefile linux-2.6.4-rc2/Makefile --- linux-2.6.4-rc1/Makefile 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/Makefile 2004-03-03 22:48:06.000000000 -0800 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 4 -EXTRAVERSION =-rc1 +EXTRAVERSION =-rc2 NAME=Feisty Dunnart # *DOCUMENTATION* diff -urN linux-2.6.4-rc1/README linux-2.6.4-rc2/README --- linux-2.6.4-rc1/README 2004-02-17 19:59:22.000000000 -0800 +++ linux-2.6.4-rc2/README 2004-03-03 22:48:06.000000000 -0800 @@ -172,24 +172,15 @@ 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 . - - 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 @@ -200,11 +191,11 @@ 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 @@ -262,8 +253,9 @@ 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..kernel.org/pub/linux/utils/kernel/ksymoops. Alternately you can do the dump lookup by hand: diff -urN linux-2.6.4-rc1/arch/alpha/kernel/semaphore.c linux-2.6.4-rc2/arch/alpha/kernel/semaphore.c --- linux-2.6.4-rc1/arch/alpha/kernel/semaphore.c 2004-02-17 19:58:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/alpha/kernel/semaphore.c 2004-03-03 22:48:06.000000000 -0800 @@ -9,31 +9,39 @@ #include /* - * Semaphores are implemented using a two-way counter: - * - * The "count" variable is decremented for each process that tries to sleep, - * while the "waking" variable is incremented when the "up()" code goes to - * wake up waiting processes. - * - * Notably, the inline "up()" and "down()" functions can efficiently test - * if they need to do any extra work (up needs to do something only if count - * was negative before the increment operation. - * - * waking_non_zero() (from asm/semaphore.h) must execute atomically. - * - * When __up() is called, the count was negative before incrementing it, - * and we need to wake up somebody. - * - * This routine adds one to the count of processes that need to wake up and - * exit. ALL waiting processes actually wake up but only the one that gets - * to the "waking" field first will gate through and acquire the semaphore. - * The others will go back to sleep. + * This is basically the PPC semaphore scheme ported to use + * the Alpha ll/sc sequences, so see the PPC code for + * credits. + */ + +/* + * Atomically update sem->count. + * This does the equivalent of the following: * - * Note that these functions are only called when there is contention on the - * lock, and as such all this is the "non-critical" part of the whole - * semaphore business. The critical part is the inline stuff in - * where we want to avoid any extra jumps and calls. + * old_count = sem->count; + * tmp = MAX(old_count, 0) + incr; + * sem->count = tmp; + * return old_count; */ +static inline int __sem_update_count(struct semaphore *sem, int incr) +{ + long old_count, tmp = 0; + + __asm__ __volatile__( + "1: ldl_l %0,%2\n" + " cmovgt %0,%0,%1\n" + " addl %1,%3,%1\n" + " stl_c %1,%2\n" + " beq %1,2f\n" + " mb\n" + ".subsection 2\n" + "2: br 1b\n" + ".previous" + : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count) + : "Ir" (incr), "1" (tmp), "m" (sem->count)); + + return old_count; +} /* * Perform the "down" function. Return zero for semaphore acquired, @@ -55,134 +63,77 @@ void __down_failed(struct semaphore *sem) { - DECLARE_WAITQUEUE(wait, current); + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); #ifdef CONFIG_DEBUG_SEMAPHORE printk("%s(%d): down failed(%p)\n", - current->comm, current->pid, sem); + tsk->comm, tsk->pid, sem); #endif - current->state = TASK_UNINTERRUPTIBLE; + tsk->state = TASK_UNINTERRUPTIBLE; wmb(); add_wait_queue_exclusive(&sem->wait, &wait); - /* At this point we know that sem->count is negative. In order - to avoid racing with __up, we must check for wakeup before - going to sleep the first time. */ - - while (1) { - long ret, tmp; - - /* An atomic conditional decrement of sem->waking. */ - __asm__ __volatile__( - "1: ldl_l %1,%2\n" - " blt %1,2f\n" - " subl %1,1,%0\n" - " stl_c %0,%2\n" - " beq %0,3f\n" - "2:\n" - ".subsection 2\n" - "3: br 1b\n" - ".previous" - : "=r"(ret), "=&r"(tmp), "=m"(sem->waking) - : "0"(0)); - - if (ret) - break; - + /* + * Try to get the semaphore. If the count is > 0, then we've + * got the semaphore; we decrement count and exit the loop. + * If the count is 0 or negative, we set it to -1, indicating + * that we are asleep, and then sleep. + */ + while (__sem_update_count(sem, -1) <= 0) { schedule(); - set_task_state(current, TASK_UNINTERRUPTIBLE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); } - remove_wait_queue(&sem->wait, &wait); - current->state = TASK_RUNNING; + tsk->state = TASK_RUNNING; + + /* + * If there are any more sleepers, wake one of them up so + * that it can either get the semaphore, or set count to -1 + * indicating that there are still processes sleeping. + */ + wake_up(&sem->wait); #ifdef CONFIG_DEBUG_SEMAPHORE printk("%s(%d): down acquired(%p)\n", - current->comm, current->pid, sem); + tsk->comm, tsk->pid, sem); #endif } int __down_failed_interruptible(struct semaphore *sem) { - DECLARE_WAITQUEUE(wait, current); - long ret; + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + long ret = 0; #ifdef CONFIG_DEBUG_SEMAPHORE printk("%s(%d): down failed(%p)\n", - current->comm, current->pid, sem); + tsk->comm, tsk->pid, sem); #endif - current->state = TASK_INTERRUPTIBLE; + tsk->state = TASK_INTERRUPTIBLE; wmb(); add_wait_queue_exclusive(&sem->wait, &wait); - while (1) { - long tmp, tmp2, tmp3; - - /* We must undo the sem->count down_interruptible decrement - simultaneously and atomically with the sem->waking - adjustment, otherwise we can race with __up. This is - accomplished by doing a 64-bit ll/sc on two 32-bit words. - - "Equivalent" C. Note that we have to do this all without - (taken) branches in order to be a valid ll/sc sequence. - - do { - tmp = ldq_l; - ret = 0; - if (tmp >= 0) { // waking >= 0 - tmp += 0xffffffff00000000; // waking -= 1 - ret = 1; - } - else if (pending) { - // count += 1, but since -1 + 1 carries into the - // high word, we have to be more careful here. - tmp = (tmp & 0xffffffff00000000) - | ((tmp + 1) & 0x00000000ffffffff); - ret = -EINTR; - } - tmp = stq_c = tmp; - } while (tmp == 0); - */ - - __asm__ __volatile__( - "1: ldq_l %1,%4\n" - " lda %0,0\n" - " cmovne %5,%6,%0\n" - " addq %1,1,%2\n" - " and %1,%7,%3\n" - " andnot %2,%7,%2\n" - " cmovge %1,1,%0\n" - " or %3,%2,%2\n" - " addq %1,%7,%3\n" - " cmovne %5,%2,%1\n" - " cmovge %2,%3,%1\n" - " stq_c %1,%4\n" - " beq %1,3f\n" - "2:\n" - ".subsection 2\n" - "3: br 1b\n" - ".previous" - : "=&r"(ret), "=&r"(tmp), "=&r"(tmp2), - "=&r"(tmp3), "=m"(*sem) - : "r"(signal_pending(current)), "r"(-EINTR), - "r"(0xffffffff00000000)); - - /* At this point we have ret - 1 got the lock - 0 go to sleep - -EINTR interrupted */ - if (ret != 0) + while (__sem_update_count(sem, -1) <= 0) { + if (signal_pending(current)) { + /* + * A signal is pending - give up trying. + * Set sem->count to 0 if it is negative, + * since we are no longer sleeping. + */ + __sem_update_count(sem, 0); + ret = -EINTR; break; - + } schedule(); - set_task_state(current, TASK_INTERRUPTIBLE); + set_task_state(tsk, TASK_INTERRUPTIBLE); } remove_wait_queue(&sem->wait, &wait); - current->state = TASK_RUNNING; + tsk->state = TASK_RUNNING; wake_up(&sem->wait); #ifdef CONFIG_DEBUG_SEMAPHORE @@ -190,14 +141,21 @@ current->comm, current->pid, (ret < 0 ? "interrupted" : "acquired"), sem); #endif - - /* Convert "got the lock" to 0==success. */ - return (ret < 0 ? ret : 0); + return ret; } void __up_wakeup(struct semaphore *sem) { + /* + * Note that we incremented count in up() before we came here, + * but that was ineffective since the result was <= 0, and + * any negative value of count is equivalent to 0. + * This ends up setting count to 1, unless count is now > 0 + * (i.e. because some other cpu has called up() in the meantime), + * in which case we just increment count. + */ + __sem_update_count(sem, 1); wake_up(&sem->wait); } diff -urN linux-2.6.4-rc1/arch/arm/kernel/Makefile linux-2.6.4-rc2/arch/arm/kernel/Makefile --- linux-2.6.4-rc1/arch/arm/kernel/Makefile 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/arm/kernel/Makefile 2004-03-03 22:48:06.000000000 -0800 @@ -29,7 +29,7 @@ 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 diff -urN linux-2.6.4-rc1/arch/arm/kernel/time.c linux-2.6.4-rc2/arch/arm/kernel/time.c --- linux-2.6.4-rc1/arch/arm/kernel/time.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/arm/kernel/time.c 2004-03-03 22:48:06.000000000 -0800 @@ -178,7 +178,7 @@ int ret; ret = sysdev_class_register(&leds_sysclass); if (ret == 0) - ret = sys_device_register(&leds_device); + ret = sysdev_register(&leds_device); return ret; } diff -urN linux-2.6.4-rc1/arch/arm/mach-integrator/integrator_ap.c linux-2.6.4-rc2/arch/arm/mach-integrator/integrator_ap.c --- linux-2.6.4-rc1/arch/arm/mach-integrator/integrator_ap.c 2004-02-17 19:59:16.000000000 -0800 +++ linux-2.6.4-rc2/arch/arm/mach-integrator/integrator_ap.c 2004-03-03 22:48:06.000000000 -0800 @@ -173,7 +173,7 @@ { int ret = sysdev_class_register(&irq_class); if (ret == 0) - ret = sys_device_register(&irq_device); + ret = sysdev_register(&irq_device); return ret; } diff -urN linux-2.6.4-rc1/arch/arm/mach-sa1100/irq.c linux-2.6.4-rc2/arch/arm/mach-sa1100/irq.c --- linux-2.6.4-rc1/arch/arm/mach-sa1100/irq.c 2004-02-17 19:59:43.000000000 -0800 +++ linux-2.6.4-rc2/arch/arm/mach-sa1100/irq.c 2004-03-03 22:48:06.000000000 -0800 @@ -278,7 +278,7 @@ static int __init sa1100irq_init_devicefs(void) { sysdev_class_register(&sa1100irq_sysclass); - return sys_device_register(&sa1100irq_device); + return sysdev_register(&sa1100irq_device); } device_initcall(sa1100irq_init_devicefs); diff -urN linux-2.6.4-rc1/arch/arm26/mm/Makefile linux-2.6.4-rc2/arch/arm26/mm/Makefile --- linux-2.6.4-rc1/arch/arm26/mm/Makefile 2004-02-17 19:57:19.000000000 -0800 +++ linux-2.6.4-rc2/arch/arm26/mm/Makefile 2004-03-03 22:48:06.000000000 -0800 @@ -1,12 +1,5 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/h8300/mm/Makefile linux-2.6.4-rc2/arch/h8300/mm/Makefile --- linux-2.6.4-rc1/arch/h8300/mm/Makefile 2004-02-17 19:59:44.000000000 -0800 +++ linux-2.6.4-rc2/arch/h8300/mm/Makefile 2004-03-03 22:48:06.000000000 -0800 @@ -1,10 +1,5 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/h8300/platform/h8300h/Makefile linux-2.6.4-rc2/arch/h8300/platform/h8300h/Makefile --- linux-2.6.4-rc1/arch/h8300/platform/h8300h/Makefile 2004-02-17 19:59:06.000000000 -0800 +++ linux-2.6.4-rc2/arch/h8300/platform/h8300h/Makefile 2004-03-03 22:48:06.000000000 -0800 @@ -6,10 +6,6 @@ #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 diff -urN linux-2.6.4-rc1/arch/h8300/platform/h8300h/aki3068net/Makefile linux-2.6.4-rc2/arch/h8300/platform/h8300h/aki3068net/Makefile --- linux-2.6.4-rc1/arch/h8300/platform/h8300h/aki3068net/Makefile 2004-02-17 19:57:42.000000000 -0800 +++ linux-2.6.4-rc2/arch/h8300/platform/h8300h/aki3068net/Makefile 2004-03-03 22:48:06.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/h8300/platform/h8300h/generic/Makefile linux-2.6.4-rc2/arch/h8300/platform/h8300h/generic/Makefile --- linux-2.6.4-rc1/arch/h8300/platform/h8300h/generic/Makefile 2004-02-17 19:57:17.000000000 -0800 +++ linux-2.6.4-rc2/arch/h8300/platform/h8300h/generic/Makefile 2004-03-03 22:48:06.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/h8300/platform/h8300h/h8max/Makefile linux-2.6.4-rc2/arch/h8300/platform/h8300h/h8max/Makefile --- linux-2.6.4-rc1/arch/h8300/platform/h8300h/h8max/Makefile 2004-02-17 19:57:11.000000000 -0800 +++ linux-2.6.4-rc2/arch/h8300/platform/h8300h/h8max/Makefile 2004-03-03 22:48:06.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/h8300/platform/h8s/Makefile linux-2.6.4-rc2/arch/h8300/platform/h8s/Makefile --- linux-2.6.4-rc1/arch/h8300/platform/h8s/Makefile 2004-02-17 19:59:19.000000000 -0800 +++ linux-2.6.4-rc2/arch/h8300/platform/h8s/Makefile 2004-03-03 22:48:06.000000000 -0800 @@ -6,10 +6,6 @@ #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 diff -urN linux-2.6.4-rc1/arch/h8300/platform/h8s/edosk2674/Makefile linux-2.6.4-rc2/arch/h8300/platform/h8s/edosk2674/Makefile --- linux-2.6.4-rc1/arch/h8300/platform/h8s/edosk2674/Makefile 2004-02-17 19:58:36.000000000 -0800 +++ linux-2.6.4-rc2/arch/h8300/platform/h8s/edosk2674/Makefile 2004-03-03 22:48:06.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/h8300/platform/h8s/generic/Makefile linux-2.6.4-rc2/arch/h8300/platform/h8s/generic/Makefile --- linux-2.6.4-rc1/arch/h8300/platform/h8s/generic/Makefile 2004-02-17 19:57:57.000000000 -0800 +++ linux-2.6.4-rc2/arch/h8300/platform/h8s/generic/Makefile 2004-03-03 22:48:06.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/i386/defconfig linux-2.6.4-rc2/arch/i386/defconfig --- linux-2.6.4-rc1/arch/i386/defconfig 2004-02-17 19:58:41.000000000 -0800 +++ linux-2.6.4-rc2/arch/i386/defconfig 2004-03-03 22:48:06.000000000 -0800 @@ -21,6 +21,7 @@ # 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 @@ -44,6 +45,7 @@ # 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 @@ -59,6 +61,7 @@ # 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 @@ -105,7 +108,9 @@ # 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) @@ -137,6 +142,7 @@ 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 @@ -164,7 +170,6 @@ # CONFIG_EISA is not set # CONFIG_MCA is not set # CONFIG_SCx200 is not set -CONFIG_HOTPLUG=y # # PCMCIA/CardBus support @@ -261,6 +266,7 @@ # # 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 @@ -368,10 +374,13 @@ # 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 @@ -397,7 +406,7 @@ # CONFIG_FUSION is not set # -# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# IEEE 1394 (FireWire) support # CONFIG_IEEE1394=y @@ -406,6 +415,7 @@ # # CONFIG_IEEE1394_VERBOSEDEBUG is not set # CONFIG_IEEE1394_OUI_DB is not set +# CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set # # Device Drivers @@ -423,7 +433,7 @@ # 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 # @@ -432,6 +442,10 @@ # CONFIG_I2O is not set # +# Macintosh device drivers +# + +# # Networking support # CONFIG_NET=y @@ -595,10 +609,11 @@ # 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 @@ -666,7 +681,7 @@ # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set +# CONFIG_ISDN is not set # # Telephony Support @@ -742,7 +757,8 @@ # 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 @@ -785,6 +801,7 @@ # 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 @@ -884,6 +901,7 @@ # # 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 @@ -976,7 +994,6 @@ # 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 @@ -1070,7 +1087,6 @@ 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 @@ -1083,6 +1099,7 @@ # 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 @@ -1111,7 +1128,6 @@ # 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 # @@ -1173,6 +1189,7 @@ # 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 diff -urN linux-2.6.4-rc1/arch/i386/kernel/apic.c linux-2.6.4-rc2/arch/i386/kernel/apic.c --- linux-2.6.4-rc1/arch/i386/kernel/apic.c 2004-02-17 19:59:55.000000000 -0800 +++ linux-2.6.4-rc2/arch/i386/kernel/apic.c 2004-03-03 22:48:06.000000000 -0800 @@ -248,12 +248,6 @@ */ reg0 = apic_read(APIC_ID); Dprintk("Getting ID: %x\n", reg0); - apic_write(APIC_ID, reg0 ^ APIC_ID_MASK); - reg1 = apic_read(APIC_ID); - Dprintk("Getting ID: %x\n", reg1); - apic_write(APIC_ID, reg0); - if (reg1 != (reg0 ^ APIC_ID_MASK)) - return 0; /* * The next two are just to see if we have sane values. @@ -595,7 +589,7 @@ error = sysdev_class_register(&lapic_sysclass); if (!error) - error = sys_device_register(&device_lapic); + error = sysdev_register(&device_lapic); return error; } device_initcall(init_lapic_sysfs); diff -urN linux-2.6.4-rc1/arch/i386/kernel/cpu/cpufreq/powernow-k8.c linux-2.6.4-rc2/arch/i386/kernel/cpu/cpufreq/powernow-k8.c --- linux-2.6.4-rc1/arch/i386/kernel/cpu/cpufreq/powernow-k8.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/i386/kernel/cpu/cpufreq/powernow-k8.c 2004-03-03 22:48:06.000000000 -0800 @@ -8,6 +8,8 @@ * * Based on the powernow-k7.c module written by Dave Jones. * (C) 2003 Dave Jones on behalf of SuSE Labs + * (C) 2004 Dominik Brodowski + * (C) 2004 Pavel Machek * Licensed under the terms of the GNU GPL License version 2. * Based upon datasheets & sample CPUs kindly provided by AMD. * @@ -34,10 +36,6 @@ #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 */ @@ -636,13 +634,22 @@ 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; diff -urN linux-2.6.4-rc1/arch/i386/kernel/i8259.c linux-2.6.4-rc2/arch/i386/kernel/i8259.c --- linux-2.6.4-rc1/arch/i386/kernel/i8259.c 2004-02-17 19:59:29.000000000 -0800 +++ linux-2.6.4-rc2/arch/i386/kernel/i8259.c 2004-03-03 22:48:06.000000000 -0800 @@ -258,7 +258,7 @@ { int error = sysdev_class_register(&i8259_sysdev_class); if (!error) - error = sys_device_register(&device_i8259A); + error = sysdev_register(&device_i8259A); return error; } @@ -401,7 +401,7 @@ { int error = sysdev_class_register(&timer_sysclass); if (!error) - error = sys_device_register(&device_timer); + error = sysdev_register(&device_timer); return error; } diff -urN linux-2.6.4-rc1/arch/i386/kernel/nmi.c linux-2.6.4-rc2/arch/i386/kernel/nmi.c --- linux-2.6.4-rc1/arch/i386/kernel/nmi.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/i386/kernel/nmi.c 2004-03-03 22:48:06.000000000 -0800 @@ -248,7 +248,7 @@ error = sysdev_class_register(&nmi_sysclass); if (!error) - error = sys_device_register(&device_lapic_nmi); + error = sysdev_register(&device_lapic_nmi); return error; } /* must come after the local APIC's device_initcall() */ diff -urN linux-2.6.4-rc1/arch/i386/kernel/time.c linux-2.6.4-rc2/arch/i386/kernel/time.c --- linux-2.6.4-rc1/arch/i386/kernel/time.c 2004-02-17 19:57:56.000000000 -0800 +++ linux-2.6.4-rc2/arch/i386/kernel/time.c 2004-03-03 22:48:07.000000000 -0800 @@ -346,7 +346,7 @@ { int error = sysdev_class_register(&pit_sysclass); if (!error) - error = sys_device_register(&device_i8253); + error = sysdev_register(&device_i8253); return error; } diff -urN linux-2.6.4-rc1/arch/i386/mach-voyager/Makefile linux-2.6.4-rc2/arch/i386/mach-voyager/Makefile --- linux-2.6.4-rc1/arch/i386/mach-voyager/Makefile 2004-02-17 19:57:16.000000000 -0800 +++ linux-2.6.4-rc2/arch/i386/mach-voyager/Makefile 2004-03-03 22:48:07.000000000 -0800 @@ -1,11 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/i386/oprofile/nmi_int.c linux-2.6.4-rc2/arch/i386/oprofile/nmi_int.c --- linux-2.6.4-rc1/arch/i386/oprofile/nmi_int.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/i386/oprofile/nmi_int.c 2004-03-03 22:48:07.000000000 -0800 @@ -65,14 +65,14 @@ { int error; if (!(error = sysdev_class_register(&oprofile_sysclass))) - error = sys_device_register(&device_oprofile); + error = sysdev_register(&device_oprofile); return error; } static void __exit exit_driverfs(void) { - sys_device_unregister(&device_oprofile); + sysdev_unregister(&device_oprofile); sysdev_class_unregister(&oprofile_sysclass); } @@ -88,7 +88,7 @@ } -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; @@ -110,6 +110,15 @@ } +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; @@ -156,8 +165,6 @@ { 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); @@ -177,6 +184,10 @@ * 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; diff -urN linux-2.6.4-rc1/arch/ia64/Kconfig linux-2.6.4-rc2/arch/ia64/Kconfig --- linux-2.6.4-rc1/arch/ia64/Kconfig 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/ia64/Kconfig 2004-03-03 22:48:07.000000000 -0800 @@ -288,39 +288,6 @@ int default "18" -choice - prompt "Huge TLB page size" - depends on HUGETLB_PAGE - default HUGETLB_PAGE_SIZE_16MB - -config HUGETLB_PAGE_SIZE_4GB - depends on MCKINLEY - bool "4GB" - -config HUGETLB_PAGE_SIZE_1GB - depends on MCKINLEY - bool "1GB" - -config HUGETLB_PAGE_SIZE_256MB - bool "256MB" - -config HUGETLB_PAGE_SIZE_64MB - bool "64MB" - -config HUGETLB_PAGE_SIZE_16MB - bool "16MB" - -config HUGETLB_PAGE_SIZE_4MB - bool "4MB" - -config HUGETLB_PAGE_SIZE_1MB - bool "1MB" - -config HUGETLB_PAGE_SIZE_256KB - bool "256KB" - -endchoice - config IA64_PAL_IDLE bool "Use PAL_HALT_LIGHT in idle loop" help diff -urN linux-2.6.4-rc1/arch/ia64/kernel/head.S linux-2.6.4-rc2/arch/ia64/kernel/head.S --- linux-2.6.4-rc1/arch/ia64/kernel/head.S 2004-02-17 19:58:39.000000000 -0800 +++ linux-2.6.4-rc2/arch/ia64/kernel/head.S 2004-03-03 22:48:07.000000000 -0800 @@ -816,6 +816,19 @@ br.ret.sptk.many rp END(ia64_delay_loop) +GLOBAL_ENTRY(ia64_invoke_kernel_thread_helper) + .prologue + .save rp, r0 // this is the end of the call-chain + .body + alloc r2 = ar.pfs, 0, 0, 2, 0 + mov out0 = r9 + mov out1 = r11;; + br.call.sptk.many rp = kernel_thread_helper;; + mov out0 = r8 + br.call.sptk.many rp = sys_exit;; +1: br.sptk.few 1b // not reached +END(ia64_invoke_kernel_thread_helper) + #ifdef CONFIG_IA64_BRL_EMU /* diff -urN linux-2.6.4-rc1/arch/ia64/kernel/iosapic.c linux-2.6.4-rc2/arch/ia64/kernel/iosapic.c --- linux-2.6.4-rc1/arch/ia64/kernel/iosapic.c 2004-02-17 19:57:51.000000000 -0800 +++ linux-2.6.4-rc2/arch/ia64/kernel/iosapic.c 2004-03-03 22:48:07.000000000 -0800 @@ -103,6 +103,7 @@ static struct iosapic_intr_info { char *addr; /* base address of IOSAPIC */ + u32 low32; /* current value of low word of Redirection table entry */ unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ char rte_index; /* IOSAPIC RTE index (-1 => not an IOSAPIC interrupt) */ unsigned char dmode : 3; /* delivery mode (see iosapic.h) */ @@ -213,6 +214,7 @@ writel(high32, addr + IOSAPIC_WINDOW); writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); writel(low32, addr + IOSAPIC_WINDOW); + iosapic_intr_info[vector].low32 = low32; } static void @@ -239,9 +241,10 @@ spin_lock_irqsave(&iosapic_lock, flags); { writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); - low32 = readl(addr + IOSAPIC_WINDOW); - low32 |= (1 << IOSAPIC_MASK_SHIFT); /* set only the mask bit */ + /* set only the mask bit */ + low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK; + writel(low32, addr + IOSAPIC_WINDOW); } spin_unlock_irqrestore(&iosapic_lock, flags); @@ -264,9 +267,7 @@ spin_lock_irqsave(&iosapic_lock, flags); { writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); - low32 = readl(addr + IOSAPIC_WINDOW); - - low32 &= ~(1 << IOSAPIC_MASK_SHIFT); /* clear only the mask bit */ + low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK; writel(low32, addr + IOSAPIC_WINDOW); } spin_unlock_irqrestore(&iosapic_lock, flags); @@ -307,9 +308,7 @@ { /* get current delivery mode by reading the low32 */ writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); - low32 = readl(addr + IOSAPIC_WINDOW); - - low32 &= ~(7 << IOSAPIC_DELIVERY_SHIFT); + low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT); if (redir) /* change delivery mode to lowest priority */ low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT); @@ -317,6 +316,7 @@ /* change delivery mode to fixed */ low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT); + iosapic_intr_info[vec].low32 = low32; writel(IOSAPIC_RTE_HIGH(rte_index), addr + IOSAPIC_REG_SELECT); writel(high32, addr + IOSAPIC_WINDOW); writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); diff -urN linux-2.6.4-rc1/arch/ia64/kernel/irq.c linux-2.6.4-rc2/arch/ia64/kernel/irq.c --- linux-2.6.4-rc1/arch/ia64/kernel/irq.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/ia64/kernel/irq.c 2004-03-03 22:48:07.000000000 -0800 @@ -455,7 +455,6 @@ unsigned int status; int cpu; - irq_enter(); cpu = smp_processor_id(); /* for CONFIG_PREEMPT, this must come after irq_enter()! */ kstat_cpu(cpu).irqs[irq]++; @@ -525,7 +524,6 @@ desc->handler->end(irq); spin_unlock(&desc->lock); } - irq_exit(); return 1; } diff -urN linux-2.6.4-rc1/arch/ia64/kernel/irq_ia64.c linux-2.6.4-rc2/arch/ia64/kernel/irq_ia64.c --- linux-2.6.4-rc1/arch/ia64/kernel/irq_ia64.c 2004-02-17 19:57:30.000000000 -0800 +++ linux-2.6.4-rc2/arch/ia64/kernel/irq_ia64.c 2004-03-03 22:48:07.000000000 -0800 @@ -120,6 +120,7 @@ * 16 (without this, it would be ~240, which could easily lead * to kernel stack overflows). */ + irq_enter(); saved_tpr = ia64_getreg(_IA64_REG_CR_TPR); ia64_srlz_d(); while (vector != IA64_SPURIOUS_INT_VECTOR) { @@ -143,8 +144,7 @@ * handler needs to be able to wait for further keyboard interrupts, which can't * come through until ia64_eoi() has been done. */ - if (local_softirq_pending()) - do_softirq(); + irq_exit(); } #ifdef CONFIG_SMP diff -urN linux-2.6.4-rc1/arch/ia64/kernel/ivt.S linux-2.6.4-rc2/arch/ia64/kernel/ivt.S --- linux-2.6.4-rc1/arch/ia64/kernel/ivt.S 2004-02-17 19:57:16.000000000 -0800 +++ linux-2.6.4-rc2/arch/ia64/kernel/ivt.S 2004-03-03 22:48:07.000000000 -0800 @@ -118,10 +118,11 @@ #ifdef CONFIG_HUGETLB_PAGE extr.u r26=r25,2,6 ;; - cmp.eq p8,p0=HPAGE_SHIFT,r26 + cmp.ne p8,p0=r18,r26 + sub r27=r26,r18 ;; (p8) dep r25=r18,r25,2,6 -(p8) shr r22=r22,HPAGE_SHIFT-PAGE_SHIFT +(p8) shr r22=r22,r27 #endif ;; cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5? diff -urN linux-2.6.4-rc1/arch/ia64/kernel/perfmon.c linux-2.6.4-rc2/arch/ia64/kernel/perfmon.c --- linux-2.6.4-rc1/arch/ia64/kernel/perfmon.c 2004-02-17 19:59:31.000000000 -0800 +++ linux-2.6.4-rc2/arch/ia64/kernel/perfmon.c 2004-03-03 22:48:07.000000000 -0800 @@ -82,7 +82,7 @@ #define PFM_REG_IMPL 0x1 /* register implemented */ #define PFM_REG_END 0x2 /* end marker */ #define PFM_REG_MONITOR (0x1<<4|PFM_REG_IMPL) /* a PMC with a pmc.pm field only */ -#define PFM_REG_COUNTING (0x2<<4|PFM_REG_MONITOR|PFM_REG_IMPL) /* a monitor + pmc.oi+ PMD used as a counter */ +#define PFM_REG_COUNTING (0x2<<4|PFM_REG_MONITOR) /* a monitor + pmc.oi+ PMD used as a counter */ #define PFM_REG_CONTROL (0x4<<4|PFM_REG_IMPL) /* PMU control register */ #define PFM_REG_CONFIG (0x8<<4|PFM_REG_IMPL) /* configuration register */ #define PFM_REG_BUFFER (0xc<<4|PFM_REG_IMPL) /* PMD used as buffer */ @@ -109,14 +109,15 @@ #define PMD_PMD_DEP(i) pmu_conf.pmd_desc[i].dep_pmd[0] #define PMC_PMD_DEP(i) pmu_conf.pmc_desc[i].dep_pmd[0] -/* k assumed unsigned (up to 64 registers) */ -#define IBR_IS_IMPL(k) (k< IA64_NUM_DBG_REGS) -#define DBR_IS_IMPL(k) (k< IA64_NUM_DBG_REGS) +#define PFM_NUM_IBRS IA64_NUM_DBG_REGS +#define PFM_NUM_DBRS IA64_NUM_DBG_REGS #define CTX_OVFL_NOBLOCK(c) ((c)->ctx_fl_block == 0) #define CTX_HAS_SMPL(c) ((c)->ctx_fl_is_sampling) #define PFM_CTX_TASK(h) (h)->ctx_task +#define PMU_PMC_OI 5 /* position of pmc.oi bit */ + /* XXX: does not support more than 64 PMDs */ #define CTX_USED_PMD(ctx, mask) (ctx)->ctx_used_pmds[0] |= (mask) #define CTX_IS_USED_PMD(ctx, c) (((ctx)->ctx_used_pmds[0] & (1UL << (c))) != 0UL) @@ -218,6 +219,8 @@ /* * debugging */ +#define PFM_DEBUGGING 1 +#ifdef PFM_DEBUGGING #define DPRINT(a) \ do { \ if (unlikely(pfm_sysctl.debug >0)) { printk("%s.%d: CPU%d [%d] ", __FUNCTION__, __LINE__, smp_processor_id(), current->pid); printk a; } \ @@ -227,18 +230,7 @@ do { \ if (unlikely(pfm_sysctl.debug > 0 && pfm_sysctl.debug_ovfl >0)) { printk("%s.%d: CPU%d [%d] ", __FUNCTION__, __LINE__, smp_processor_id(), current->pid); printk a; } \ } while (0) -/* - * Architected PMC structure - */ -typedef struct { - unsigned long pmc_plm:4; /* privilege level mask */ - unsigned long pmc_ev:1; /* external visibility */ - unsigned long pmc_oi:1; /* overflow interrupt */ - unsigned long pmc_pm:1; /* privileged monitor */ - unsigned long pmc_ig1:1; /* reserved */ - unsigned long pmc_es:8; /* event select */ - unsigned long pmc_ig2:48; /* reserved */ -} pfm_monitor_t; +#endif /* * 64-bit software counter structure @@ -469,20 +461,13 @@ #define PFM_CMD_STOP 0x08 /* command does not work on zombie context */ -#define PFM_CMD_IDX(cmd) (cmd) -#define PFM_CMD_IS_VALID(cmd) ((PFM_CMD_IDX(cmd) >= 0) && (PFM_CMD_IDX(cmd) < PFM_CMD_COUNT) \ - && pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func != NULL) - -#define PFM_CMD_NAME(cmd) pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_name -#define PFM_CMD_READ_ARG(cmd) (pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_ARG_READ) -#define PFM_CMD_RW_ARG(cmd) (pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_ARG_RW) -#define PFM_CMD_USE_FD(cmd) (pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_FD) -#define PFM_CMD_STOPPED(cmd) (pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_STOP) +#define PFM_CMD_NAME(cmd) pfm_cmd_tab[(cmd)].cmd_name +#define PFM_CMD_READ_ARG(cmd) (pfm_cmd_tab[(cmd)].cmd_flags & PFM_CMD_ARG_READ) +#define PFM_CMD_RW_ARG(cmd) (pfm_cmd_tab[(cmd)].cmd_flags & PFM_CMD_ARG_RW) +#define PFM_CMD_USE_FD(cmd) (pfm_cmd_tab[(cmd)].cmd_flags & PFM_CMD_FD) +#define PFM_CMD_STOPPED(cmd) (pfm_cmd_tab[(cmd)].cmd_flags & PFM_CMD_STOP) #define PFM_CMD_ARG_MANY -1 /* cannot be zero */ -#define PFM_CMD_NARG(cmd) (pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_narg) -#define PFM_CMD_ARG_SIZE(cmd) (pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_argsize) -#define PFM_CMD_GETSIZE(cmd) (pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_getsize) typedef struct { int debug; /* turn on/off debugging via syslog */ @@ -2834,10 +2819,11 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { struct thread_struct *thread = NULL; + struct task_struct *task; pfarg_reg_t *req = (pfarg_reg_t *)arg; - unsigned long value; - unsigned long smpl_pmds, reset_pmds; - unsigned int cnum, reg_flags, flags; + unsigned long value, pmc_pm; + unsigned long smpl_pmds, reset_pmds, impl_pmds; + unsigned int cnum, reg_flags, flags, pmc_type; int i, can_access_pmu = 0, is_loaded, is_system; int is_monitor, is_counting, state; int ret = -EINVAL; @@ -2846,12 +2832,13 @@ state = ctx->ctx_state; is_loaded = state == PFM_CTX_LOADED ? 1 : 0; is_system = ctx->ctx_fl_system; + task = ctx->ctx_task; + impl_pmds = pmu_conf.impl_pmds[0]; if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL; - if (is_loaded) { - thread = &ctx->ctx_task->thread; + thread = &task->thread; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. @@ -2861,7 +2848,7 @@ DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; + can_access_pmu = GET_PMU_OWNER() == task || is_system ? 1 : 0; } for (i = 0; i < count; i++, req++) { @@ -2873,16 +2860,24 @@ reset_pmds = req->reg_reset_pmds[0]; flags = 0; - is_counting = PMC_IS_COUNTING(cnum); - is_monitor = PMC_IS_MONITOR(cnum); + + if (cnum >= PMU_MAX_PMCS) { + DPRINT(("pmc%u is invalid\n", cnum)); + goto error; + } + + pmc_type = pmu_conf.pmc_desc[cnum].type; + pmc_pm = (value >> pmu_conf.pmc_desc[cnum].pm_pos) & 0x1; + is_counting = (pmc_type & PFM_REG_COUNTING) == PFM_REG_COUNTING ? 1 : 0; + is_monitor = (pmc_type & PFM_REG_MONITOR) == PFM_REG_MONITOR ? 1 : 0; /* * we reject all non implemented PMC as well * as attempts to modify PMC[0-3] which are used * as status registers by the PMU */ - if (PMC_IS_IMPL(cnum) == 0 || PMC_IS_CONTROL(cnum)) { - DPRINT(("pmc%u is unimplemented or invalid\n", cnum)); + if ((pmc_type & PFM_REG_IMPL) == 0 || (pmc_type & PFM_REG_CONTROL) == PFM_REG_CONTROL) { + DPRINT(("pmc%u is unimplemented or no-access pmc_type=%x\n", cnum, pmc_type)); goto error; } /* @@ -2890,21 +2885,20 @@ * - system-wide session: PMCx.pm=1 (privileged monitor) * - per-task : PMCx.pm=0 (user monitor) */ - if ((is_monitor || is_counting) && value != PMC_DFL_VAL(cnum) && PFM_CHECK_PMC_PM(ctx, cnum, value)) { - DPRINT(("pmc%u pmc_pm=%ld fl_system=%d\n", + if (is_monitor && value != PMC_DFL_VAL(cnum) && is_system ^ pmc_pm) { + DPRINT(("pmc%u pmc_pm=%lu is_system=%d\n", cnum, - PMC_PM(cnum, value), - ctx->ctx_fl_system)); + pmc_pm, + is_system)); goto error; } if (is_counting) { - pfm_monitor_t *p = (pfm_monitor_t *)&value; /* * enforce generation of overflow interrupt. Necessary on all * CPUs. */ - p->pmc_oi = 1; + value |= 1 << PMU_PMC_OI; if (reg_flags & PFM_REGFL_OVFL_NOTIFY) { flags |= PFM_REGFL_OVFL_NOTIFY; @@ -2913,13 +2907,13 @@ if (reg_flags & PFM_REGFL_RANDOM) flags |= PFM_REGFL_RANDOM; /* verify validity of smpl_pmds */ - if ((smpl_pmds & pmu_conf.impl_pmds[0]) != smpl_pmds) { + if ((smpl_pmds & impl_pmds) != smpl_pmds) { DPRINT(("invalid smpl_pmds 0x%lx for pmc%u\n", smpl_pmds, cnum)); goto error; } /* verify validity of reset_pmds */ - if ((reset_pmds & pmu_conf.impl_pmds[0]) != reset_pmds) { + if ((reset_pmds & impl_pmds) != reset_pmds) { DPRINT(("invalid reset_pmds 0x%lx for pmc%u\n", reset_pmds, cnum)); goto error; } @@ -2935,7 +2929,7 @@ * execute write checker, if any */ if (PMC_WR_FUNC(cnum)) { - ret = PMC_WR_FUNC(cnum)(ctx->ctx_task, ctx, cnum, &value, regs); + ret = PMC_WR_FUNC(cnum)(task, ctx, cnum, &value, regs); if (ret) goto error; ret = -EINVAL; } @@ -2997,7 +2991,7 @@ * * The value in ctx_pmcs[] can only be changed in pfm_write_pmcs(). * - * The value in t->pmc[] may be modified on overflow, i.e., when + * The value in thread->pmcs[] may be modified on overflow, i.e., when * monitoring needs to be stopped. */ if (is_monitor) CTX_USED_MONITOR(ctx, 1UL << cnum); @@ -3056,11 +3050,6 @@ return 0; error: PFM_REG_RETFLAG_SET(req->reg_flags, PFM_REG_RETFL_EINVAL); - - req->reg_flags = PFM_REG_RETFL_EINVAL; - - DPRINT(("pmc[%u]=0x%lx error %d\n", cnum, value, ret)); - return ret; } @@ -3068,6 +3057,7 @@ pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { struct thread_struct *thread = NULL; + struct task_struct *task; pfarg_reg_t *req = (pfarg_reg_t *)arg; unsigned long value, hw_value, ovfl_mask; unsigned int cnum; @@ -3080,25 +3070,26 @@ is_loaded = state == PFM_CTX_LOADED ? 1 : 0; is_system = ctx->ctx_fl_system; ovfl_mask = pmu_conf.ovfl_val; + task = ctx->ctx_task; - if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL; + if (unlikely(state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE)) return -EINVAL; /* * on both UP and SMP, we can only write to the PMC when the task is * the owner of the local PMU. */ - if (is_loaded) { - thread = &ctx->ctx_task->thread; + if (likely(is_loaded)) { + thread = &task->thread; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (is_system && ctx->ctx_cpu != smp_processor_id()) { + if (unlikely(is_system && ctx->ctx_cpu != smp_processor_id())) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; + can_access_pmu = GET_PMU_OWNER() == task || is_system ? 1 : 0; } for (i = 0; i < count; i++, req++) { @@ -3118,7 +3109,7 @@ if (PMD_WR_FUNC(cnum)) { unsigned long v = value; - ret = PMD_WR_FUNC(cnum)(ctx->ctx_task, ctx, cnum, &v, regs); + ret = PMD_WR_FUNC(cnum)(task, ctx, cnum, &v, regs); if (ret) goto abort_mission; value = v; @@ -3243,16 +3234,6 @@ * for now, we have only one possibility for error */ PFM_REG_RETFLAG_SET(req->reg_flags, PFM_REG_RETFL_EINVAL); - - /* - * we change the return value to EFAULT in case we cannot write register return code. - * The caller first must correct this error, then a resubmission of the request will - * eventually yield the EINVAL. - */ - req->reg_flags = PFM_REG_RETFL_EINVAL; - - DPRINT(("pmd[%u]=0x%lx ret %d\n", cnum, value, ret)); - return ret; } @@ -3269,11 +3250,12 @@ pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { struct thread_struct *thread = NULL; - unsigned long val = 0UL, lval, ovfl_mask; + struct task_struct *task; + unsigned long val = 0UL, lval, ovfl_mask, sval; pfarg_reg_t *req = (pfarg_reg_t *)arg; unsigned int cnum, reg_flags = 0; int i, can_access_pmu = 0, state; - int is_loaded, is_system; + int is_loaded, is_system, is_counting; int ret = -EINVAL; /* @@ -3285,32 +3267,33 @@ is_loaded = state == PFM_CTX_LOADED ? 1 : 0; is_system = ctx->ctx_fl_system; ovfl_mask = pmu_conf.ovfl_val; + task = ctx->ctx_task; if (state == PFM_CTX_ZOMBIE) return -EINVAL; - if (is_loaded) { - thread = &ctx->ctx_task->thread; + if (likely(is_loaded)) { + thread = &task->thread; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (is_system && ctx->ctx_cpu != smp_processor_id()) { + if (unlikely(is_system && ctx->ctx_cpu != smp_processor_id())) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } /* * this can be true when not self-monitoring only in UP */ - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; + can_access_pmu = GET_PMU_OWNER() == task || is_system ? 1 : 0; if (can_access_pmu) ia64_srlz_d(); } - DPRINT(("enter loaded=%d access_pmu=%d ctx_state=%d\n", + DPRINT(("loaded=%d access_pmu=%d ctx_state=%d\n", is_loaded, can_access_pmu, - ctx->ctx_state)); + state)); /* * on both UP and SMP, we can only read the PMD from the hardware register when @@ -3319,11 +3302,10 @@ for (i = 0; i < count; i++, req++) { - lval = 0UL; cnum = req->reg_num; reg_flags = req->reg_flags; - if (!PMD_IS_IMPL(cnum)) goto error; + if (unlikely(!PMD_IS_IMPL(cnum))) goto error; /* * we can only read the register that we use. That includes * the one we explicitely initialize AND the one we want included @@ -3332,7 +3314,11 @@ * Having this restriction allows optimization in the ctxsw routine * without compromising security (leaks) */ - if (!CTX_IS_USED_PMD(ctx, cnum)) goto error; + if (unlikely(!CTX_IS_USED_PMD(ctx, cnum))) goto error; + + sval = ctx->ctx_pmds[cnum].val; + lval = ctx->ctx_pmds[cnum].lval; + is_counting = PMD_IS_COUNTING(cnum); /* * If the task is not the current one, then we check if the @@ -3347,23 +3333,21 @@ * if context is zombie, then task does not exist anymore. * In this case, we use the full value saved in the context (pfm_flush_regs()). */ - val = state == PFM_CTX_LOADED ? thread->pmds[cnum] : 0UL; + val = is_loaded ? thread->pmds[cnum] : 0UL; } - if (PMD_IS_COUNTING(cnum)) { + if (is_counting) { /* * XXX: need to check for overflow when loaded */ val &= ovfl_mask; - val += ctx->ctx_pmds[cnum].val; - - lval = ctx->ctx_pmds[cnum].lval; + val += sval; } /* * execute read checker, if any */ - if (PMD_RD_FUNC(cnum)) { + if (unlikely(PMD_RD_FUNC(cnum))) { unsigned long v = val; ret = PMD_RD_FUNC(cnum)(ctx->ctx_task, ctx, cnum, &v, regs); if (ret) goto error; @@ -3373,12 +3357,7 @@ PFM_REG_RETFLAG_SET(reg_flags, 0); - DPRINT(("pmd[%u]=0x%lx loaded=%d access_pmu=%d ctx_state=%d\n", - cnum, - val, - is_loaded, - can_access_pmu, - ctx->ctx_state)); + DPRINT(("pmd[%u]=0x%lx\n", cnum, val)); /* * update register return value, abort all if problem during copy. @@ -3393,12 +3372,7 @@ return 0; error: - PFM_REG_RETFLAG_SET(reg_flags, PFM_REG_RETFL_EINVAL); - - req->reg_flags = PFM_REG_RETFL_EINVAL; - - DPRINT(("error pmd[%u]=0x%lx\n", cnum, val)); - + PFM_REG_RETFLAG_SET(req->reg_flags, PFM_REG_RETFL_EINVAL); return ret; } @@ -3628,7 +3602,7 @@ prefetch(ctx->ctx_smpl_hdr); rst_ctrl.bits.mask_monitoring = 0; - rst_ctrl.bits.reset_ovfl_pmds = 1; + rst_ctrl.bits.reset_ovfl_pmds = 0; if (state == PFM_CTX_LOADED) ret = pfm_buf_fmt_restart_active(fmt, task, &rst_ctrl, ctx->ctx_smpl_hdr, regs); @@ -3748,6 +3722,7 @@ pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { struct thread_struct *thread = NULL; + struct task_struct *task; pfarg_dbreg_t *req = (pfarg_dbreg_t *)arg; unsigned long flags; dbreg_t dbreg; @@ -3762,6 +3737,7 @@ state = ctx->ctx_state; is_loaded = state == PFM_CTX_LOADED ? 1 : 0; is_system = ctx->ctx_fl_system; + task = ctx->ctx_task; if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL; @@ -3770,17 +3746,17 @@ * the owner of the local PMU. */ if (is_loaded) { - thread = &ctx->ctx_task->thread; + thread = &task->thread; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (is_system && ctx->ctx_cpu != smp_processor_id()) { + if (unlikely(is_system && ctx->ctx_cpu != smp_processor_id())) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; + can_access_pmu = GET_PMU_OWNER() == task || is_system ? 1 : 0; } /* @@ -3796,7 +3772,7 @@ * don't bother if we are loaded and task is being debugged */ if (is_loaded && (thread->flags & IA64_THREAD_DBG_VALID) != 0) { - DPRINT(("debug registers already in use for [%d]\n", ctx->ctx_task->pid)); + DPRINT(("debug registers already in use for [%d]\n", task->pid)); return -EBUSY; } @@ -3837,7 +3813,7 @@ * is shared by all processes running on it */ if (first_time && can_access_pmu) { - DPRINT(("[%d] clearing ibrs, dbrs\n", ctx->ctx_task->pid)); + DPRINT(("[%d] clearing ibrs, dbrs\n", task->pid)); for (i=0; i < pmu_conf.num_ibrs; i++) { ia64_set_ibr(i, 0UL); ia64_srlz_i(); @@ -3860,7 +3836,7 @@ ret = -EINVAL; - if ((mode == PFM_CODE_RR && !IBR_IS_IMPL(rnum)) || ((mode == PFM_DATA_RR) && !DBR_IS_IMPL(rnum))) { + if ((mode == PFM_CODE_RR && rnum >= PFM_NUM_IBRS) || ((mode == PFM_DATA_RR) && rnum >= PFM_NUM_DBRS)) { DPRINT(("invalid register %u val=0x%lx mode=%d i=%d count=%d\n", rnum, dbreg.val, mode, i, count)); @@ -4434,6 +4410,7 @@ struct task_struct *task = PFM_CTX_TASK(ctx); struct pt_regs *tregs; int state, is_system; + int ret; DPRINT(("ctx_state=%d task [%d]\n", ctx->ctx_state, task ? task->pid : -1)); @@ -4451,7 +4428,8 @@ /* * clear psr and dcr bits */ - pfm_stop(ctx, NULL, 0, regs); + ret = pfm_stop(ctx, NULL, 0, regs); + if (ret) return ret; ctx->ctx_state = state = PFM_CTX_UNLOADED; @@ -4760,37 +4738,45 @@ void *args_k = NULL; long ret; /* will expand int return types */ size_t base_sz, sz, xtra_sz = 0; - int narg, completed_args = 0, call_made = 0; + int narg, completed_args = 0, call_made = 0, cmd_flags; + int (*func)(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs); + int (*getsize)(void *arg, size_t *sz); #define PFM_MAX_ARGSIZE 4096 /* - * reject any call if perfmon was disabled at initialization time - mask*/ - if (PFM_IS_DISABLED()) return -ENOSYS; + * reject any call if perfmon was disabled at initialization + */ + if (unlikely(PFM_IS_DISABLED())) return -ENOSYS; - if (unlikely(PFM_CMD_IS_VALID(cmd) == 0)) { + if (unlikely(cmd < 0 || cmd >= PFM_CMD_COUNT)) { DPRINT(("[%d] invalid cmd=%d\n", current->pid, cmd)); return -EINVAL; } - DPRINT(("cmd=%s idx=%d valid=%d narg=0x%x argsz=%lu count=%d\n", + func = pfm_cmd_tab[cmd].cmd_func; + narg = pfm_cmd_tab[cmd].cmd_narg; + base_sz = pfm_cmd_tab[cmd].cmd_argsize; + getsize = pfm_cmd_tab[cmd].cmd_getsize; + cmd_flags = pfm_cmd_tab[cmd].cmd_flags; + + if (unlikely(func == NULL)) { + DPRINT(("[%d] invalid cmd=%d\n", current->pid, cmd)); + return -EINVAL; + } + + DPRINT(("cmd=%s idx=%d narg=0x%x argsz=%lu count=%d\n", PFM_CMD_NAME(cmd), - PFM_CMD_IDX(cmd), - PFM_CMD_IS_VALID(cmd), - PFM_CMD_NARG(cmd), - PFM_CMD_ARG_SIZE(cmd), + cmd, + narg, + base_sz, count)); /* * check if number of arguments matches what the command expects */ - narg = PFM_CMD_NARG(cmd); - if ((narg == PFM_CMD_ARG_MANY && count <= 0) || (narg > 0 && narg != count)) + if (unlikely((narg == PFM_CMD_ARG_MANY && count <= 0) || (narg > 0 && narg != count))) return -EINVAL; - /* get single argument size */ - base_sz = PFM_CMD_ARG_SIZE(cmd); - restart_args: sz = xtra_sz + base_sz*count; /* @@ -4804,7 +4790,7 @@ /* * allocate default-sized argument buffer */ - if (count && args_k == NULL) { + if (likely(count && args_k == NULL)) { args_k = kmalloc(PFM_MAX_ARGSIZE, GFP_KERNEL); if (args_k == NULL) return -ENOMEM; } @@ -4824,11 +4810,11 @@ /* * check if command supports extra parameters */ - if (completed_args == 0 && PFM_CMD_GETSIZE(cmd)) { + if (completed_args == 0 && getsize) { /* * get extra parameters size (based on main argument) */ - ret = PFM_CMD_GETSIZE(cmd)(args_k, &xtra_sz); + ret = (*getsize)(args_k, &xtra_sz); if (ret) goto error_args; completed_args = 1; @@ -4836,45 +4822,45 @@ DPRINT(("[%d] restart_args sz=%lu xtra_sz=%lu\n", current->pid, sz, xtra_sz)); /* retry if necessary */ - if (xtra_sz) goto restart_args; + if (likely(xtra_sz)) goto restart_args; } - if (PFM_CMD_USE_FD(cmd)) { - - ret = -EBADF; + if (unlikely((cmd_flags & PFM_CMD_FD) == 0)) goto skip_fd; - file = fget(fd); - if (file == NULL) { - DPRINT(("[%d] invalid fd %d\n", current->pid, fd)); - goto error_args; - } - if (PFM_IS_FILE(file) == 0) { - DPRINT(("[%d] fd %d not related to perfmon\n", current->pid, fd)); - goto error_args; - } + ret = -EBADF; + file = fget(fd); + if (unlikely(file == NULL)) { + DPRINT(("[%d] invalid fd %d\n", current->pid, fd)); + goto error_args; + } + if (unlikely(PFM_IS_FILE(file) == 0)) { + DPRINT(("[%d] fd %d not related to perfmon\n", current->pid, fd)); + goto error_args; + } - ctx = (pfm_context_t *)file->private_data; - if (ctx == NULL) { - DPRINT(("[%d] no context for fd %d\n", current->pid, fd)); - goto error_args; - } + ctx = (pfm_context_t *)file->private_data; + if (unlikely(ctx == NULL)) { + DPRINT(("[%d] no context for fd %d\n", current->pid, fd)); + goto error_args; + } + prefetch(&ctx->ctx_state); - PROTECT_CTX(ctx, flags); + PROTECT_CTX(ctx, flags); - /* - * check task is stopped - */ - ret = pfm_check_task_state(ctx, cmd, flags); - if (ret) goto abort_locked; - } + /* + * check task is stopped + */ + ret = pfm_check_task_state(ctx, cmd, flags); + if (unlikely(ret)) goto abort_locked; - ret = (*pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func)(ctx, args_k, count, regs); +skip_fd: + ret = (*func)(ctx, args_k, count, regs); call_made = 1; abort_locked: - if (ctx) { + if (likely(ctx)) { DPRINT(("[%d] context unlocked\n", current->pid)); UNPROTECT_CTX(ctx, flags); fput(file); @@ -4907,7 +4893,7 @@ if (CTX_HAS_SMPL(ctx)) { rst_ctrl.bits.mask_monitoring = 0; - rst_ctrl.bits.reset_ovfl_pmds = 1; + rst_ctrl.bits.reset_ovfl_pmds = 0; if (state == PFM_CTX_LOADED) ret = pfm_buf_fmt_restart_active(fmt, current, &rst_ctrl, ctx->ctx_smpl_hdr, regs); @@ -5096,7 +5082,7 @@ msg->pfm_ovfl_msg.msg_ovfl_pmds[1] = 0UL; msg->pfm_ovfl_msg.msg_ovfl_pmds[2] = 0UL; msg->pfm_ovfl_msg.msg_ovfl_pmds[3] = 0UL; - msg->pfm_ovfl_msg.msg_tstamp = ia64_get_itc(); /* relevant on UP only */ + msg->pfm_ovfl_msg.msg_tstamp = 0UL; } DPRINT(("ovfl msg: msg=%p no_msg=%d fd=%d pid=%d ovfl_pmds=0x%lx\n", @@ -5119,10 +5105,12 @@ printk(KERN_ERR "perfmon: pfm_end_notify_user no more notification msgs\n"); return -1; } + /* no leak */ + memset(msg, 0, sizeof(*msg)); msg->pfm_end_msg.msg_type = PFM_MSG_END; msg->pfm_end_msg.msg_ctx_fd = ctx->ctx_fd; - msg->pfm_ovfl_msg.msg_tstamp = ia64_get_itc(); /* relevant on UP only */ + msg->pfm_ovfl_msg.msg_tstamp = 0UL; DPRINT(("end msg: msg=%p no_msg=%d ctx_fd=%d pid=%d\n", msg, @@ -5141,8 +5129,8 @@ { pfm_ovfl_arg_t ovfl_arg; unsigned long mask; - unsigned long old_val, ovfl_val; - unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL, smpl_pmds = 0UL; + unsigned long old_val, ovfl_val, new_val; + unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL, smpl_pmds = 0UL, reset_pmds; unsigned long tstamp; pfm_ovfl_ctrl_t ovfl_ctrl; unsigned int i, has_smpl; @@ -5155,21 +5143,19 @@ */ if (unlikely((pmc0 & 0x1) == 0)) goto sanity_check; - tstamp = ia64_get_itc(); - + tstamp = ia64_get_itc(); mask = pmc0 >> PMU_FIRST_COUNTER; ovfl_val = pmu_conf.ovfl_val; + has_smpl = CTX_HAS_SMPL(ctx); DPRINT_ovfl(("pmc0=0x%lx pid=%d iip=0x%lx, %s " - "used_pmds=0x%lx reload_pmcs=0x%lx\n", + "used_pmds=0x%lx\n", pmc0, task ? task->pid: -1, (regs ? regs->cr_iip : 0), CTX_OVFL_NOBLOCK(ctx) ? "nonblocking" : "blocking", - ctx->ctx_used_pmds[0], - ctx->ctx_reload_pmcs[0])); + ctx->ctx_used_pmds[0])); - has_smpl = CTX_HAS_SMPL(ctx); /* * first we update the virtual counters @@ -5180,29 +5166,31 @@ /* skip pmd which did not overflow */ if ((mask & 0x1) == 0) continue; - DPRINT_ovfl(("pmd[%d] overflowed hw_pmd=0x%lx ctx_pmd=0x%lx\n", - i, ia64_get_pmd(i), ctx->ctx_pmds[i].val)); - /* * Note that the pmd is not necessarily 0 at this point as qualified events * may have happened before the PMU was frozen. The residual count is not * taken into consideration here but will be with any read of the pmd via * pfm_read_pmds(). */ - old_val = ctx->ctx_pmds[i].val; - ctx->ctx_pmds[i].val += 1 + ovfl_val; + old_val = new_val = ctx->ctx_pmds[i].val; + new_val += 1 + ovfl_val; + ctx->ctx_pmds[i].val = new_val; /* * check for overflow condition */ - if (likely(old_val > ctx->ctx_pmds[i].val)) { + if (likely(old_val > new_val)) { ovfl_pmds |= 1UL << i; if (PMC_OVFL_NOTIFY(ctx, i)) ovfl_notify |= 1UL << i; } - DPRINT_ovfl(("ctx_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx ovfl_pmds=0x%lx ovfl_notify=0x%lx smpl_pmds=0x%lx\n", - i, ctx->ctx_pmds[i].val, old_val, - ia64_get_pmd(i) & ovfl_val, ovfl_pmds, ovfl_notify, smpl_pmds)); + DPRINT_ovfl(("ctx_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx ovfl_pmds=0x%lx ovfl_notify=0x%lx\n", + i, + new_val, + old_val, + ia64_get_pmd(i) & ovfl_val, + ovfl_pmds, + ovfl_notify)); } /* @@ -5214,6 +5202,7 @@ * reset all control bits */ ovfl_ctrl.val = 0; + reset_pmds = 0UL; /* * if a sampling format module exists, then we "cache" the overflow by @@ -5225,7 +5214,7 @@ int j, k, ret = 0; int this_cpu = smp_processor_id(); - pmd_mask = ovfl_pmds >> PMU_FIRST_COUNTER; + pmd_mask = ovfl_pmds >> PMU_FIRST_COUNTER; prefetch(ctx->ctx_smpl_hdr); @@ -5275,7 +5264,10 @@ ovfl_ctrl.bits.notify_user |= ovfl_arg.ovfl_ctrl.bits.notify_user; ovfl_ctrl.bits.block_task |= ovfl_arg.ovfl_ctrl.bits.block_task; ovfl_ctrl.bits.mask_monitoring |= ovfl_arg.ovfl_ctrl.bits.mask_monitoring; - ovfl_ctrl.bits.reset_ovfl_pmds |= ovfl_arg.ovfl_ctrl.bits.reset_ovfl_pmds; /* yes or no */ + /* + * build the bitmask of pmds to reset now + */ + if (ovfl_arg.ovfl_ctrl.bits.reset_ovfl_pmds) reset_pmds |= mask; pfm_stats[this_cpu].pfm_smpl_handler_cycles += end_cycles - start_cycles; } @@ -5287,6 +5279,10 @@ current->pid, pmd_mask<pid, + ovfl_pmds, + reset_pmds)); /* - * if we (still) have some overflowed PMD but no notification is requested - * then we use the short reset period. + * reset the requested PMD registers using the short reset values */ - if (ovfl_ctrl.bits.reset_ovfl_pmds) { - unsigned long bm = ovfl_pmds; + if (reset_pmds) { + unsigned long bm = reset_pmds; pfm_reset_regs(ctx, &bm, PFM_PMD_SHORT_RESET); } diff -urN linux-2.6.4-rc1/arch/ia64/kernel/perfmon_default_smpl.c linux-2.6.4-rc2/arch/ia64/kernel/perfmon_default_smpl.c --- linux-2.6.4-rc1/arch/ia64/kernel/perfmon_default_smpl.c 2004-02-17 19:59:16.000000000 -0800 +++ linux-2.6.4-rc2/arch/ia64/kernel/perfmon_default_smpl.c 2004-03-03 22:48:07.000000000 -0800 @@ -178,6 +178,7 @@ ent->tstamp = stamp; ent->cpu = smp_processor_id(); ent->set = arg->active_set; + ent->tgid = current->tgid; /* * selectively store PMDs in increasing index number diff -urN linux-2.6.4-rc1/arch/ia64/kernel/process.c linux-2.6.4-rc2/arch/ia64/kernel/process.c --- linux-2.6.4-rc1/arch/ia64/kernel/process.c 2004-02-17 19:57:52.000000000 -0800 +++ linux-2.6.4-rc2/arch/ia64/kernel/process.c 2004-03-03 22:48:07.000000000 -0800 @@ -259,10 +259,12 @@ * * We get here through the following call chain: * - * - * sys_clone - * do_fork - * copy_thread + * from user-level: from kernel: + * + * + * sys_clone : + * do_fork do_fork + * copy_thread copy_thread * * This means that the stack layout is as follows: * @@ -276,9 +278,6 @@ * | | <-- sp (lowest addr) * +---------------------+ * - * Note: if we get called through kernel_thread() then the memory above "(highest addr)" - * is valid kernel stack memory that needs to be copied as well. - * * Observe that we copy the unat values that are in pt_regs and switch_stack. Spilling an * integer to address X causes bit N in ar.unat to be set to the NaT bit of the register, * with N=(X & 0x1ff)/8. Thus, copying the unat value preserves the NaT bits ONLY if the @@ -291,9 +290,9 @@ unsigned long user_stack_base, unsigned long user_stack_size, struct task_struct *p, struct pt_regs *regs) { - unsigned long rbs, child_rbs, rbs_size, stack_offset, stack_top, stack_used; - struct switch_stack *child_stack, *stack; extern char ia64_ret_from_clone, ia32_ret_from_clone; + struct switch_stack *child_stack, *stack; + unsigned long rbs, child_rbs, rbs_size; struct pt_regs *child_ptregs; int retval = 0; @@ -306,16 +305,13 @@ return 0; #endif - stack_top = (unsigned long) current + IA64_STK_OFFSET; stack = ((struct switch_stack *) regs) - 1; - stack_used = stack_top - (unsigned long) stack; - stack_offset = IA64_STK_OFFSET - stack_used; - child_stack = (struct switch_stack *) ((unsigned long) p + stack_offset); - child_ptregs = (struct pt_regs *) (child_stack + 1); + child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1; + child_stack = (struct switch_stack *) child_ptregs - 1; /* copy parent's switch_stack & pt_regs to child: */ - memcpy(child_stack, stack, stack_used); + memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack)); rbs = (unsigned long) current + IA64_RBS_OFFSET; child_rbs = (unsigned long) p + IA64_RBS_OFFSET; @@ -324,7 +320,7 @@ /* copy the parent's register backing store to the child: */ memcpy((void *) child_rbs, (void *) rbs, rbs_size); - if (user_mode(child_ptregs)) { + if (likely(user_mode(child_ptregs))) { if ((clone_flags & CLONE_SETTLS) && !IS_IA32_PROCESS(regs)) child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ if (user_stack_base) { @@ -341,14 +337,14 @@ * been taken care of by the caller of sys_clone() * already. */ - child_ptregs->r12 = (unsigned long) (child_ptregs + 1); /* kernel sp */ + child_ptregs->r12 = (unsigned long) child_ptregs - 16; /* kernel sp */ child_ptregs->r13 = (unsigned long) p; /* set `current' pointer */ } + child_stack->ar_bspstore = child_rbs + rbs_size; if (IS_IA32_PROCESS(regs)) child_stack->b0 = (unsigned long) &ia32_ret_from_clone; else child_stack->b0 = (unsigned long) &ia64_ret_from_clone; - child_stack->ar_bspstore = child_rbs + rbs_size; /* copy parts of thread_struct: */ p->thread.ksp = (unsigned long) child_stack - 16; @@ -358,8 +354,8 @@ * therefore we must specify them explicitly here and not include them in * IA64_PSR_BITS_TO_CLEAR. */ - child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) - & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); + child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) + & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); /* * NOTE: The calling convention considers all floating point @@ -578,27 +574,43 @@ pid_t kernel_thread (int (*fn)(void *), void *arg, unsigned long flags) { - struct task_struct *parent = current; - int result; - pid_t tid; + extern void ia64_invoke_kernel_thread_helper (void); + unsigned long *helper_fptr = (unsigned long *) &ia64_invoke_kernel_thread_helper; + struct { + struct switch_stack sw; + struct pt_regs pt; + } regs; + + memset(®s, 0, sizeof(regs)); + regs.pt.cr_iip = helper_fptr[0]; /* set entry point (IP) */ + regs.pt.r1 = helper_fptr[1]; /* set GP */ + regs.pt.r9 = (unsigned long) fn; /* 1st argument */ + regs.pt.r11 = (unsigned long) arg; /* 2nd argument */ + /* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read. */ + regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN; + regs.pt.cr_ifs = 1UL << 63; /* mark as valid, empty frame */ + regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR); + regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET; + + return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s.pt, 0, NULL, NULL); +} +EXPORT_SYMBOL(kernel_thread); - tid = clone(flags | CLONE_VM | CLONE_UNTRACED, 0); - if (parent != current) { +/* This gets called from kernel_thread() via ia64_invoke_thread_helper(). */ +int +kernel_thread_helper (int (*fn)(void *), void *arg) +{ #ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(ia64_task_regs(current))) { - /* A kernel thread is always a 64-bit process. */ - current->thread.map_base = DEFAULT_MAP_BASE; - current->thread.task_size = DEFAULT_TASK_SIZE; - ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob); - ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1); - } -#endif - result = (*fn)(arg); - _exit(result); + if (IS_IA32_PROCESS(ia64_task_regs(current))) { + /* A kernel thread is always a 64-bit process. */ + current->thread.map_base = DEFAULT_MAP_BASE; + current->thread.task_size = DEFAULT_TASK_SIZE; + ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob); + ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1); } - return tid; +#endif + return (*fn)(arg); } -EXPORT_SYMBOL(kernel_thread); /* * Flush thread state. This is called when a thread does an execve(). diff -urN linux-2.6.4-rc1/arch/ia64/mm/hugetlbpage.c linux-2.6.4-rc2/arch/ia64/mm/hugetlbpage.c --- linux-2.6.4-rc1/arch/ia64/mm/hugetlbpage.c 2004-02-17 19:58:01.000000000 -0800 +++ linux-2.6.4-rc2/arch/ia64/mm/hugetlbpage.c 2004-03-03 22:48:07.000000000 -0800 @@ -1,7 +1,11 @@ /* * IA-64 Huge TLB Page Support for Kernel. * - * Copyright (C) 2002, Rohit Seth + * Copyright (C) 2002-2004 Rohit Seth + * Copyright (C) 2003-2004 Ken Chen + * + * Sep, 2003: add numa support + * Feb, 2004: dynamic hugetlb page size via boot parameter */ #include @@ -18,11 +22,10 @@ #include #include -#define TASK_HPAGE_BASE (REGION_HPAGE << REGION_SHIFT) - static long htlbpagemem; int htlbpage_max; static long htlbzone_pages; +unsigned int hpage_shift=HPAGE_SHIFT_DEFAULT; static struct list_head hugepage_freelists[MAX_NUMNODES]; static spinlock_t htlbpage_lock = SPIN_LOCK_UNLOCKED; @@ -407,7 +410,7 @@ return -EINVAL; /* This code assumes that REGION_HPAGE != 0. */ if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1))) - addr = TASK_HPAGE_BASE; + addr = HPAGE_REGION_BASE; else addr = ALIGN(addr, HPAGE_SIZE); for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { @@ -520,6 +523,35 @@ } __setup("hugepages=", hugetlb_setup); +static int __init hugetlb_setup_sz(char *str) +{ + u64 tr_pages; + unsigned long long size; + + if (ia64_pal_vm_page_size(&tr_pages, NULL) != 0) + /* + * shouldn't happen, but just in case. + */ + tr_pages = 0x15557000UL; + + size = memparse(str, &str); + if (*str || (size & (size-1)) || !(tr_pages & size) || + size <= PAGE_SIZE || + size >= (1UL << PAGE_SHIFT << MAX_ORDER)) { + printk(KERN_WARNING "Invalid huge page size specified\n"); + return 1; + } + + hpage_shift = __ffs(size); + /* + * boot cpu already executed ia64_mmu_init, and has HPAGE_SHIFT_DEFAULT + * override here with new page shift. + */ + ia64_set_rr(HPAGE_REGION_BASE, hpage_shift << 2); + return 1; +} +__setup("hugepagesz=", hugetlb_setup_sz); + static int __init hugetlb_init(void) { int i; @@ -540,7 +572,7 @@ printk("Total HugeTLB memory allocated, %ld\n", htlbpagemem); return 0; } -module_init(hugetlb_init); +__initcall(hugetlb_init); int hugetlb_report_meminfo(char *buf) { diff -urN linux-2.6.4-rc1/arch/ia64/mm/init.c linux-2.6.4-rc2/arch/ia64/mm/init.c --- linux-2.6.4-rc1/arch/ia64/mm/init.c 2004-02-17 19:57:39.000000000 -0800 +++ linux-2.6.4-rc2/arch/ia64/mm/init.c 2004-03-03 22:48:07.000000000 -0800 @@ -342,6 +342,10 @@ ia64_tlb_init(); +#ifdef CONFIG_HUGETLB_PAGE + ia64_set_rr(HPAGE_REGION_BASE, HPAGE_SHIFT << 2); +#endif + #ifdef CONFIG_IA64_MCA cpu = smp_processor_id(); diff -urN linux-2.6.4-rc1/arch/m68k/amiga/amiints.c linux-2.6.4-rc2/arch/m68k/amiga/amiints.c --- linux-2.6.4-rc1/arch/m68k/amiga/amiints.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/m68k/amiga/amiints.c 2004-02-17 19:59:58.000000000 -0800 @@ -49,7 +49,6 @@ #include #include #include -#include extern int cia_request_irq(struct ciabase *base,int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), diff -urN linux-2.6.4-rc1/arch/m68k/bvme6000/bvmeints.c linux-2.6.4-rc2/arch/m68k/bvme6000/bvmeints.c --- linux-2.6.4-rc1/arch/m68k/bvme6000/bvmeints.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/m68k/bvme6000/bvmeints.c 2004-02-17 19:57:16.000000000 -0800 @@ -20,7 +20,6 @@ #include #include #include -#include static irqreturn_t bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp); diff -urN linux-2.6.4-rc1/arch/m68k/hp300/time.c linux-2.6.4-rc2/arch/m68k/hp300/time.c --- linux-2.6.4-rc1/arch/m68k/hp300/time.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/m68k/hp300/time.c 2004-02-17 19:59:04.000000000 -0800 @@ -17,7 +17,6 @@ #include #include #include -#include #include "ints.h" /* Clock hardware definitions */ diff -urN linux-2.6.4-rc1/arch/m68k/kernel/setup.c linux-2.6.4-rc2/arch/m68k/kernel/setup.c --- linux-2.6.4-rc1/arch/m68k/kernel/setup.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/m68k/kernel/setup.c 2004-03-03 22:48:07.000000000 -0800 @@ -39,7 +39,6 @@ #endif #ifdef CONFIG_SUN3X #include -extern void sun_serial_setup(void); #endif unsigned long m68k_machtype; diff -urN linux-2.6.4-rc1/arch/m68k/mac/iop.c linux-2.6.4-rc2/arch/m68k/mac/iop.c --- linux-2.6.4-rc1/arch/m68k/mac/iop.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/m68k/mac/iop.c 2004-03-03 22:48:07.000000000 -0800 @@ -118,7 +118,6 @@ #include #include #include -#include /*#define DEBUG_IOP*/ diff -urN linux-2.6.4-rc1/arch/m68k/mac/macints.c linux-2.6.4-rc2/arch/m68k/mac/macints.c --- linux-2.6.4-rc1/arch/m68k/mac/macints.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/m68k/mac/macints.c 2004-03-03 22:48:07.000000000 -0800 @@ -133,7 +133,6 @@ #include #include #include -#include #define DEBUG_SPURIOUS #define SHUTUP_SONIC diff -urN linux-2.6.4-rc1/arch/m68k/mac/oss.c linux-2.6.4-rc2/arch/m68k/mac/oss.c --- linux-2.6.4-rc1/arch/m68k/mac/oss.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/m68k/mac/oss.c 2004-02-17 19:57:53.000000000 -0800 @@ -26,7 +26,6 @@ #include #include #include -#include int oss_present; volatile struct mac_oss *oss; diff -urN linux-2.6.4-rc1/arch/m68k/mac/psc.c linux-2.6.4-rc2/arch/m68k/mac/psc.c --- linux-2.6.4-rc1/arch/m68k/mac/psc.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/m68k/mac/psc.c 2004-02-17 19:58:14.000000000 -0800 @@ -24,7 +24,6 @@ #include #include #include -#include #define DEBUG_PSC diff -urN linux-2.6.4-rc1/arch/m68k/mac/via.c linux-2.6.4-rc2/arch/m68k/mac/via.c --- linux-2.6.4-rc1/arch/m68k/mac/via.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/m68k/mac/via.c 2004-03-03 22:48:07.000000000 -0800 @@ -32,7 +32,6 @@ #include #include #include -#include volatile __u8 *via1, *via2; #if 0 diff -urN linux-2.6.4-rc1/arch/m68k/q40/q40ints.c linux-2.6.4-rc2/arch/m68k/q40/q40ints.c --- linux-2.6.4-rc1/arch/m68k/q40/q40ints.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/m68k/q40/q40ints.c 2004-02-17 19:59:21.000000000 -0800 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff -urN linux-2.6.4-rc1/arch/m68k/sun3/sun3ints.c linux-2.6.4-rc2/arch/m68k/sun3/sun3ints.c --- linux-2.6.4-rc1/arch/m68k/sun3/sun3ints.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/m68k/sun3/sun3ints.c 2004-02-17 19:59:56.000000000 -0800 @@ -15,7 +15,6 @@ #include #include #include -#include #include extern void sun3_leds (unsigned char); diff -urN linux-2.6.4-rc1/arch/mips/au1000/csb250/Makefile linux-2.6.4-rc2/arch/mips/au1000/csb250/Makefile --- linux-2.6.4-rc1/arch/mips/au1000/csb250/Makefile 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/mips/au1000/csb250/Makefile 2004-03-03 22:48:07.000000000 -0800 @@ -4,10 +4,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/mips/au1000/hydrogen3/Makefile linux-2.6.4-rc2/arch/mips/au1000/hydrogen3/Makefile --- linux-2.6.4-rc1/arch/mips/au1000/hydrogen3/Makefile 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/mips/au1000/hydrogen3/Makefile 2004-03-03 22:48:07.000000000 -0800 @@ -5,10 +5,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/mips/au1000/mtx-1/Makefile linux-2.6.4-rc2/arch/mips/au1000/mtx-1/Makefile --- linux-2.6.4-rc1/arch/mips/au1000/mtx-1/Makefile 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/mips/au1000/mtx-1/Makefile 2004-03-03 22:48:07.000000000 -0800 @@ -6,9 +6,5 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/mips/au1000/pb1550/Makefile linux-2.6.4-rc2/arch/mips/au1000/pb1550/Makefile --- linux-2.6.4-rc1/arch/mips/au1000/pb1550/Makefile 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/mips/au1000/pb1550/Makefile 2004-03-03 22:48:07.000000000 -0800 @@ -5,10 +5,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/mips/au1000/xxs1500/Makefile linux-2.6.4-rc2/arch/mips/au1000/xxs1500/Makefile --- linux-2.6.4-rc1/arch/mips/au1000/xxs1500/Makefile 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/mips/au1000/xxs1500/Makefile 2004-03-03 22:48:07.000000000 -0800 @@ -5,9 +5,5 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/mips/kernel/gdb-stub.c linux-2.6.4-rc2/arch/mips/kernel/gdb-stub.c --- linux-2.6.4-rc1/arch/mips/kernel/gdb-stub.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/mips/kernel/gdb-stub.c 2004-03-03 22:48:07.000000000 -0800 @@ -95,7 +95,7 @@ * Example: * $ cd ~/linux * $ make menuconfig - * $ make dep; make vmlinux + * $ make * * Step 3: * Download the kernel to the remote target and start diff -urN linux-2.6.4-rc1/arch/mips/kernel/i8259.c linux-2.6.4-rc2/arch/mips/kernel/i8259.c --- linux-2.6.4-rc1/arch/mips/kernel/i8259.c 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/mips/kernel/i8259.c 2004-03-03 22:48:07.000000000 -0800 @@ -242,7 +242,7 @@ { int error = sysdev_class_register(&i8259_sysdev_class); if (!error) - error = sys_device_register(&device_i8259A); + error = sysdev_register(&device_i8259A); return error; } diff -urN linux-2.6.4-rc1/arch/mips/momentum/jaguar_atx/Makefile linux-2.6.4-rc2/arch/mips/momentum/jaguar_atx/Makefile --- linux-2.6.4-rc1/arch/mips/momentum/jaguar_atx/Makefile 2004-03-03 22:47:59.000000000 -0800 +++ linux-2.6.4-rc2/arch/mips/momentum/jaguar_atx/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/mips/tx4927/common/Makefile linux-2.6.4-rc2/arch/mips/tx4927/common/Makefile --- linux-2.6.4-rc1/arch/mips/tx4927/common/Makefile 2004-02-17 19:57:18.000000000 -0800 +++ linux-2.6.4-rc2/arch/mips/tx4927/common/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/ppc/platforms/pmac_pic.c linux-2.6.4-rc2/arch/ppc/platforms/pmac_pic.c --- linux-2.6.4-rc1/arch/ppc/platforms/pmac_pic.c 2004-02-17 19:59:24.000000000 -0800 +++ linux-2.6.4-rc2/arch/ppc/platforms/pmac_pic.c 2004-03-03 22:48:08.000000000 -0800 @@ -646,7 +646,7 @@ printk(KERN_DEBUG "Registering pmac pic with sysfs...\n"); sysdev_class_register(&pmacpic_sysclass); - sys_device_register(&device_pmacpic); + sysdev_register(&device_pmacpic); sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic); return 0; } diff -urN linux-2.6.4-rc1/arch/ppc/syslib/open_pic.c linux-2.6.4-rc2/arch/ppc/syslib/open_pic.c --- linux-2.6.4-rc1/arch/ppc/syslib/open_pic.c 2004-02-17 19:58:16.000000000 -0800 +++ linux-2.6.4-rc2/arch/ppc/syslib/open_pic.c 2004-03-03 22:48:08.000000000 -0800 @@ -1032,7 +1032,7 @@ printk(KERN_ERR "Failed registering openpic sys class\n"); return -ENODEV; } - rc = sys_device_register(&device_openpic); + rc = sysdev_register(&device_openpic); if (rc) { printk(KERN_ERR "Failed registering openpic sys device\n"); return -ENODEV; diff -urN linux-2.6.4-rc1/arch/ppc/syslib/open_pic2.c linux-2.6.4-rc2/arch/ppc/syslib/open_pic2.c --- linux-2.6.4-rc1/arch/ppc/syslib/open_pic2.c 2004-02-17 19:57:21.000000000 -0800 +++ linux-2.6.4-rc2/arch/ppc/syslib/open_pic2.c 2004-03-03 22:48:08.000000000 -0800 @@ -699,7 +699,7 @@ printk(KERN_ERR "Failed registering openpic sys class\n"); return -ENODEV; } - rc = sys_device_register(&device_openpic2); + rc = sysdev_register(&device_openpic2); if (rc) { printk(KERN_ERR "Failed registering openpic sys device\n"); return -ENODEV; diff -urN linux-2.6.4-rc1/arch/ppc64/configs/g5_defconfig linux-2.6.4-rc2/arch/ppc64/configs/g5_defconfig --- linux-2.6.4-rc1/arch/ppc64/configs/g5_defconfig 2004-02-17 19:57:14.000000000 -0800 +++ linux-2.6.4-rc2/arch/ppc64/configs/g5_defconfig 2004-03-03 22:48:08.000000000 -0800 @@ -26,6 +26,7 @@ # 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 @@ -56,15 +57,16 @@ 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 @@ -77,7 +79,6 @@ # CONFIG_BINFMT_MISC is not set CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y -CONFIG_HOTPLUG=y # # PCMCIA/CardBus support @@ -128,6 +129,7 @@ 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 @@ -277,6 +279,7 @@ # 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 @@ -284,7 +287,7 @@ # CONFIG_FUSION is not set # -# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# IEEE 1394 (FireWire) support # CONFIG_IEEE1394=y @@ -318,11 +321,11 @@ # # 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 @@ -439,6 +442,7 @@ # 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 @@ -488,7 +492,7 @@ # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set +# CONFIG_ISDN is not set # # Telephony Support @@ -556,7 +560,8 @@ # # 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 # @@ -676,6 +681,7 @@ # 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 @@ -919,7 +925,6 @@ 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 @@ -933,6 +938,7 @@ # 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 @@ -964,7 +970,6 @@ 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 # @@ -1037,9 +1042,11 @@ # 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 diff -urN linux-2.6.4-rc1/arch/ppc64/kernel/iommu.c linux-2.6.4-rc2/arch/ppc64/kernel/iommu.c --- linux-2.6.4-rc1/arch/ppc64/kernel/iommu.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/ppc64/kernel/iommu.c 2004-03-03 22:48:08.000000000 -0800 @@ -1,12 +1,12 @@ /* - * arch/ppc64/kernel/pci_iommu.c + * arch/ppc64/kernel/iommu.c * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * * Rewrite, cleanup, new allocation schemes, virtual merging: * Copyright (C) 2004 Olof Johansson, IBM Corporation * and Ben. Herrenschmidt, IBM Corporation * - * Dynamic DMA mapping support, platform-independent parts. + * Dynamic DMA mapping support, bus-independent parts. * * 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 @@ -60,41 +60,57 @@ __setup("iommu=", setup_iommu); static unsigned long iommu_range_alloc(struct iommu_table *tbl, unsigned long npages, - unsigned long *handle) + unsigned long *handle) { unsigned long n, end, i, start; - unsigned long hint; unsigned long limit; int largealloc = npages > 15; + int pass = 0; - if (handle && *handle) - hint = *handle; - else - hint = largealloc ? tbl->it_largehint : tbl->it_hint; + /* This allocator was derived from x86_64's bit string search */ - /* Most of this is stolen from x86_64's bit string search function */ + /* Sanity check */ + if (unlikely(npages) == 0) { + if (printk_ratelimit()) + WARN_ON(1); + return NO_TCE; + } - start = hint; + if (handle && *handle) + start = *handle; + else + start = largealloc ? tbl->it_largehint : tbl->it_hint; - /* Use only half of the table for small allocs (less than 15 pages). */ + /* Use only half of the table for small allocs (15 pages or less) */ + limit = largealloc ? tbl->it_mapsize : tbl->it_halfpoint; - limit = largealloc ? tbl->it_mapsize : tbl->it_mapsize >> 1; + if (largealloc && start < tbl->it_halfpoint) + start = tbl->it_halfpoint; - if (largealloc && start < (tbl->it_mapsize >> 1)) - start = tbl->it_mapsize >> 1; + /* The case below can happen if we have a small segment appended + * to a large, or when the previous alloc was at the very end of + * the available space. If so, go back to the initial start. + */ + if (start >= limit) + start = largealloc ? tbl->it_largehint : tbl->it_hint; again: n = find_next_zero_bit(tbl->it_map, limit, start); - end = n + npages; - if (end >= limit) { - if (hint) { - start = largealloc ? tbl->it_mapsize >> 1 : 0; - hint = 0; + + if (unlikely(end >= limit)) { + if (likely(pass++ < 2)) { + /* First failure, just rescan the half of the table. + * Second failure, rescan the other half of the table. + */ + start = (largealloc ^ pass) ? tbl->it_halfpoint : 0; + limit = pass ? tbl->it_mapsize : limit; goto again; - } else + } else { + /* Third failure, give up */ return NO_TCE; + } } for (i = n; i < end; i++) @@ -106,16 +122,17 @@ for (i = n; i < end; i++) __set_bit(i, tbl->it_map); - /* Bump the hint to a new PHB cache line, which - * is 16 entries wide on all pSeries machines. - */ - if (largealloc) - tbl->it_largehint = (end+tbl->it_blocksize-1) & - ~(tbl->it_blocksize-1); - else - tbl->it_hint = (end+tbl->it_blocksize-1) & - ~(tbl->it_blocksize-1); + /* Bump the hint to a new block for small allocs. */ + if (largealloc) { + /* Don't bump to new block to avoid fragmentation */ + tbl->it_largehint = end; + } else { + /* Overflow will be taken care of at the next allocation */ + tbl->it_hint = (end + tbl->it_blocksize - 1) & + ~(tbl->it_blocksize - 1); + } + /* Update handle for SG allocations */ if (handle) *handle = end; @@ -123,35 +140,38 @@ } dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page, - unsigned int npages, int direction, - unsigned long *handle) + unsigned int npages, int direction) { unsigned long entry, flags; - dma_addr_t retTce = NO_TCE; + dma_addr_t ret = NO_TCE; spin_lock_irqsave(&(tbl->it_lock), flags); - /* Allocate a range of entries into the table */ - entry = iommu_range_alloc(tbl, npages, handle); + entry = iommu_range_alloc(tbl, npages, NULL); + if (unlikely(entry == NO_TCE)) { spin_unlock_irqrestore(&(tbl->it_lock), flags); return NO_TCE; } - - /* We got the tces we wanted */ + entry += tbl->it_offset; /* Offset into real TCE table */ - retTce = entry << PAGE_SHIFT; /* Set the return dma address */ + ret = entry << PAGE_SHIFT; /* Set the return dma address */ /* Put the TCEs in the HW table */ - ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & PAGE_MASK, direction); + ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & PAGE_MASK, + direction); + - /* Flush/invalidate TLBs if necessary */ + /* Flush/invalidate TLB caches if necessary */ if (ppc_md.tce_flush) ppc_md.tce_flush(tbl); spin_unlock_irqrestore(&(tbl->it_lock), flags); - return retTce; + /* Make sure updates are seen by hardware */ + mb(); + + return ret; } static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, @@ -168,7 +188,7 @@ if (printk_ratelimit()) { printk(KERN_INFO "iommu_free: invalid entry\n"); printk(KERN_INFO "\tentry = 0x%lx\n", entry); - printk(KERN_INFO "\tdma_ddr = 0x%lx\n", (u64)dma_addr); + printk(KERN_INFO "\tdma_addr = 0x%lx\n", (u64)dma_addr); printk(KERN_INFO "\tTable = 0x%lx\n", (u64)tbl); printk(KERN_INFO "\tbus# = 0x%lx\n", (u64)tbl->it_busno); printk(KERN_INFO "\tmapsize = 0x%lx\n", (u64)tbl->it_mapsize); @@ -194,68 +214,30 @@ __iommu_free(tbl, dma_addr, npages); - /* Flush/invalidate TLBs if necessary */ + /* Make sure TLB cache is flushed if the HW needs it. We do + * not do an mb() here on purpose, it is not needed on any of + * the current platforms. + */ if (ppc_md.tce_flush) ppc_md.tce_flush(tbl); spin_unlock_irqrestore(&(tbl->it_lock), flags); } -/* - * Build a iommu_table structure. This contains a bit map which - * is used to manage allocation of the tce space. - */ -struct iommu_table *iommu_init_table(struct iommu_table *tbl) -{ - unsigned long sz; - static int welcomed = 0; - - /* it_size is in pages, it_mapsize in number of entries */ - tbl->it_mapsize = tbl->it_size * tbl->it_entrysize; - - if (systemcfg->platform == PLATFORM_POWERMAC) - tbl->it_mapsize = tbl->it_size * (PAGE_SIZE / sizeof(unsigned int)); - else - tbl->it_mapsize = tbl->it_size * (PAGE_SIZE / sizeof(union tce_entry)); - - /* sz is the number of bytes needed for the bitmap */ - sz = (tbl->it_mapsize + 7) >> 3; - - tbl->it_map = (unsigned long *)__get_free_pages(GFP_ATOMIC, get_order(sz)); - - if (!tbl->it_map) - panic("iommu_init_table: Can't allocate memory, size %ld bytes\n", sz); - - memset(tbl->it_map, 0, sz); - - tbl->it_hint = 0; - tbl->it_largehint = 0; - spin_lock_init(&tbl->it_lock); - - if (!welcomed) { - printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n", - novmerge ? "disabled" : "enabled"); - welcomed = 1; - } - - return tbl; -} - - -int iommu_alloc_sg(struct iommu_table *tbl, struct scatterlist *sglist, int nelems, - int direction, unsigned long *handle) +int iommu_alloc_sg(struct iommu_table *tbl, struct device *dev, + struct scatterlist *sglist, int nelems, int direction) { dma_addr_t dma_next, dma_addr; - unsigned long flags, vaddr, npages, entry; - struct scatterlist *s, *outs, *segstart, *ps; + unsigned long flags; + struct scatterlist *s, *outs, *segstart; int outcount; + unsigned long handle; - /* Initialize some stuffs */ outs = s = segstart = &sglist[0]; outcount = 1; - ps = NULL; + handle = 0; - /* Init first segment length for error handling */ + /* Init first segment length for backout at failure */ outs->dma_length = 0; DBG("mapping %d elements:\n", nelems); @@ -263,13 +245,21 @@ spin_lock_irqsave(&(tbl->it_lock), flags); for (s = outs; nelems; nelems--, s++) { + unsigned long vaddr, npages, entry, slen; + + slen = s->length; + /* Sanity check */ + if (slen == 0) { + dma_next = 0; + continue; + } /* Allocate iommu entries for that segment */ vaddr = (unsigned long)page_address(s->page) + s->offset; - npages = PAGE_ALIGN(vaddr + s->length) - (vaddr & PAGE_MASK); + npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK); npages >>= PAGE_SHIFT; - entry = iommu_range_alloc(tbl, npages, handle); + entry = iommu_range_alloc(tbl, npages, &handle); - DBG(" - vaddr: %lx, size: %lx\n", vaddr, s->length); + DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen); /* Handle failure */ if (unlikely(entry == NO_TCE)) { @@ -293,13 +283,10 @@ /* If we are in an open segment, try merging */ if (segstart != s) { DBG(" - trying merge...\n"); - /* We cannot merge is: + /* We cannot merge if: * - allocated dma_addr isn't contiguous to previous allocation - * - current entry has an offset into the page - * - previous entry didn't end on a page boundary */ - if (novmerge || (dma_addr != dma_next) || s->offset || - (ps->offset + ps->length) % PAGE_SIZE) { + if (novmerge || (dma_addr != dma_next)) { /* Can't merge: create a new segment */ segstart = s; outcount++; outs++; @@ -310,31 +297,28 @@ } } - /* If we are beginning a new segment, fill entries */ if (segstart == s) { + /* This is a new segment, fill entries */ DBG(" - filling new segment.\n"); outs->dma_address = dma_addr; - outs->dma_length = s->length; + outs->dma_length = slen; } /* Calculate next page pointer for contiguous check */ - dma_next = (dma_addr & PAGE_MASK) + (npages << PAGE_SHIFT); + dma_next = dma_addr + slen; DBG(" - dma next is: %lx\n", dma_next); - - /* Keep a pointer to the previous entry */ - ps = s; } - /* Make sure the update is visible to hardware. */ - mb(); - - /* Flush/invalidate TLBs if necessary */ + /* Flush/invalidate TLB caches if necessary */ if (ppc_md.tce_flush) ppc_md.tce_flush(tbl); spin_unlock_irqrestore(&(tbl->it_lock), flags); + /* Make sure updates are seen by hardware */ + mb(); + DBG("mapped %d elements:\n", outcount); /* For the sake of iommu_free_sg, we clear out the length in the @@ -348,25 +332,26 @@ return outcount; failure: - spin_unlock_irqrestore(&(tbl->it_lock), flags); for (s = &sglist[0]; s <= outs; s++) { if (s->dma_length != 0) { + unsigned long vaddr, npages; + vaddr = s->dma_address & PAGE_MASK; npages = (PAGE_ALIGN(s->dma_address + s->dma_length) - vaddr) >> PAGE_SHIFT; - iommu_free(tbl, vaddr, npages); + __iommu_free(tbl, vaddr, npages); } } + spin_unlock_irqrestore(&(tbl->it_lock), flags); return 0; } -void iommu_free_sg(struct iommu_table *tbl, struct scatterlist *sglist, int nelems, - int direction) +void iommu_free_sg(struct iommu_table *tbl, struct scatterlist *sglist, + int nelems) { unsigned long flags; - /* Lock the whole operation to try to free as a "chunk" */ spin_lock_irqsave(&(tbl->it_lock), flags); while (nelems--) { @@ -381,9 +366,49 @@ sglist++; } - /* Flush/invalidate TLBs if necessary */ + /* Flush/invalidate TLBs if necessary. As for iommu_free(), we + * do not do an mb() here, the affected platforms do not need it + * when freeing. + */ if (ppc_md.tce_flush) ppc_md.tce_flush(tbl); spin_unlock_irqrestore(&(tbl->it_lock), flags); } + +/* + * Build a iommu_table structure. This contains a bit map which + * is used to manage allocation of the tce space. + */ +struct iommu_table *iommu_init_table(struct iommu_table *tbl) +{ + unsigned long sz; + static int welcomed = 0; + + /* it_size is in pages, it_mapsize in number of entries */ + tbl->it_mapsize = (tbl->it_size << PAGE_SHIFT) / tbl->it_entrysize; + + /* Set aside 1/4 of the table for large allocations. */ + tbl->it_halfpoint = tbl->it_mapsize * 3 / 4; + + /* number of bytes needed for the bitmap */ + sz = (tbl->it_mapsize + 7) >> 3; + + tbl->it_map = (unsigned long *)__get_free_pages(GFP_ATOMIC, get_order(sz)); + if (!tbl->it_map) + panic("iommu_init_table: Can't allocate %ld bytes\n", sz); + + memset(tbl->it_map, 0, sz); + + tbl->it_hint = 0; + tbl->it_largehint = tbl->it_halfpoint; + spin_lock_init(&tbl->it_lock); + + if (!welcomed) { + printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n", + novmerge ? "disabled" : "enabled"); + welcomed = 1; + } + + return tbl; +} diff -urN linux-2.6.4-rc1/arch/ppc64/kernel/pSeries_htab.c linux-2.6.4-rc2/arch/ppc64/kernel/pSeries_htab.c --- linux-2.6.4-rc1/arch/ppc64/kernel/pSeries_htab.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/ppc64/kernel/pSeries_htab.c 2004-03-03 22:48:08.000000000 -0800 @@ -103,7 +103,7 @@ __asm__ __volatile__ ("ptesync" : : : "memory"); - return i; + return i | (secondary << 3); } static long pSeries_hpte_remove(unsigned long hpte_group) diff -urN linux-2.6.4-rc1/arch/ppc64/kernel/pSeries_lpar.c linux-2.6.4-rc2/arch/ppc64/kernel/pSeries_lpar.c --- linux-2.6.4-rc1/arch/ppc64/kernel/pSeries_lpar.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/ppc64/kernel/pSeries_lpar.c 2004-03-03 22:48:08.000000000 -0800 @@ -379,7 +379,10 @@ if (lpar_rc != H_Success) return -2; - return slot; + /* Because of iSeries, we have to pass down the secondary + * bucket bit here as well + */ + return (slot & 7) | (secondary << 3); } static spinlock_t pSeries_lpar_tlbie_lock = SPIN_LOCK_UNLOCKED; diff -urN linux-2.6.4-rc1/arch/ppc64/kernel/pci_iommu.c linux-2.6.4-rc2/arch/ppc64/kernel/pci_iommu.c --- linux-2.6.4-rc1/arch/ppc64/kernel/pci_iommu.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/ppc64/kernel/pci_iommu.c 2004-03-03 22:48:08.000000000 -0800 @@ -99,10 +99,7 @@ memset(ret, 0, size); /* Set up tces to cover the allocated range */ - mapping = iommu_alloc(tbl, ret, npages, PCI_DMA_BIDIRECTIONAL, NULL); - - /* Make sure the update is visible to hardware. */ - mb(); + mapping = iommu_alloc(tbl, ret, npages, PCI_DMA_BIDIRECTIONAL); if (mapping == NO_TCE) { free_pages((unsigned long)ret, order); @@ -145,7 +142,6 @@ dma_addr_t dma_handle = NO_TCE; unsigned long uaddr; unsigned int npages; - unsigned long handle = 0; BUG_ON(direction == PCI_DMA_NONE); @@ -156,7 +152,7 @@ tbl = devnode_table(hwdev); if (tbl) { - dma_handle = iommu_alloc(tbl, vaddr, npages, direction, &handle); + dma_handle = iommu_alloc(tbl, vaddr, npages, direction); if (dma_handle == NO_TCE) { if (printk_ratelimit()) { printk(KERN_INFO "iommu_alloc failed, tbl %p vaddr %p npages %d\n", @@ -166,8 +162,6 @@ dma_handle |= (uaddr & ~PAGE_MASK); } - mb(); - return dma_handle; } @@ -194,7 +188,6 @@ int direction) { struct iommu_table * tbl; - unsigned long handle; BUG_ON(direction == PCI_DMA_NONE); @@ -205,9 +198,7 @@ if (!tbl) return 0; - handle = 0; - - return iommu_alloc_sg(tbl, sglist, nelems, direction, &handle); + return iommu_alloc_sg(tbl, &pdev->dev, sglist, nelems, direction); } void pci_iommu_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, @@ -221,7 +212,7 @@ if (!tbl) return; - iommu_free_sg(tbl, sglist, nelems, direction); + iommu_free_sg(tbl, sglist, nelems); } /* We support DMA to/from any memory page via the iommu */ diff -urN linux-2.6.4-rc1/arch/ppc64/kernel/pmac_setup.c linux-2.6.4-rc2/arch/ppc64/kernel/pmac_setup.c --- linux-2.6.4-rc1/arch/ppc64/kernel/pmac_setup.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/ppc64/kernel/pmac_setup.c 2004-03-03 22:48:08.000000000 -0800 @@ -95,6 +95,7 @@ PMAC_MB_INFO_MODEL, 0); unsigned int mbflags = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_FLAGS, 0); + extern unsigned long ppc_tb_freq; if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, (long)&mbname) != 0) @@ -127,20 +128,11 @@ seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname); seq_printf(m, "pmac flags\t: %08x\n", mbflags); - /* Checks "l2cr-value" property in the registry */ - np = find_devices("cpus"); - if (np == 0) - np = find_type_devices("cpu"); - if (np != 0) { - unsigned int *l2cr = (unsigned int *) - get_property(np, "l2cr-value", NULL); - if (l2cr != 0) { - seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr); - } - } - /* Indicate newworld */ seq_printf(m, "pmac-generation\t: NewWorld\n"); + + /* Indicate timebase value */ + seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq); } diff -urN linux-2.6.4-rc1/arch/ppc64/kernel/pmac_time.c linux-2.6.4-rc2/arch/ppc64/kernel/pmac_time.c --- linux-2.6.4-rc1/arch/ppc64/kernel/pmac_time.c 2004-02-17 19:58:43.000000000 -0800 +++ linux-2.6.4-rc2/arch/ppc64/kernel/pmac_time.c 2004-03-03 22:48:08.000000000 -0800 @@ -39,6 +39,8 @@ extern void setup_default_decr(void); +extern unsigned long ppc_tb_freq; + /* Apparently the RTC stores seconds since 1 Jan 1904 */ #define RTC_OFFSET 2082844800 @@ -151,6 +153,7 @@ tb_to_us = mulhwu_scale_factor(freq, 1000000); div128_by_32( 1024*1024, 0, tb_ticks_per_sec, &divres ); tb_to_xs = divres.result_low; + ppc_tb_freq = freq; setup_default_decr(); } diff -urN linux-2.6.4-rc1/arch/ppc64/kernel/prom.c linux-2.6.4-rc2/arch/ppc64/kernel/prom.c --- linux-2.6.4-rc1/arch/ppc64/kernel/prom.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/ppc64/kernel/prom.c 2004-03-03 22:48:08.000000000 -0800 @@ -516,6 +516,9 @@ return mem; } +#ifdef CONFIG_PMAC_DART +static int dart_force_on; +#endif static unsigned long __init prom_initialize_lmb(unsigned long mem) @@ -539,10 +542,12 @@ prom_print(opt); prom_print(RELOC("\n")); opt += 6; - while(*opt && *opt == ' ') + while (*opt && *opt == ' ') opt++; if (!strncmp(opt, RELOC("off"), 3)) nodart = 1; + else if (!strncmp(opt, RELOC("force"), 5)) + RELOC(dart_force_on) = 1; } #else nodart = 1; @@ -763,8 +768,10 @@ extern unsigned long dart_tablebase; extern unsigned long dart_tablesize; - /* Only reserve DART space if machine has more than 2Gb of RAM */ - if (lmb_end_of_DRAM() <= 0x80000000ull) + /* Only reserve DART space if machine has more than 2GB of RAM + * or if requested with iommu=on on cmdline. + */ + if (lmb_end_of_DRAM() <= 0x80000000ull && !RELOC(dart_force_on)) return; /* 512 pages is max DART tablesize. */ diff -urN linux-2.6.4-rc1/arch/ppc64/kernel/vio.c linux-2.6.4-rc2/arch/ppc64/kernel/vio.c --- linux-2.6.4-rc1/arch/ppc64/kernel/vio.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/ppc64/kernel/vio.c 2004-03-03 22:48:08.000000000 -0800 @@ -29,6 +29,8 @@ #define DBGENTER() pr_debug("%s entered\n", __FUNCTION__) +extern struct subsystem devices_subsys; /* needed for vio_find_name() */ + struct iommu_table *vio_build_iommu_table(struct vio_dev *dev); static int vio_num_address_cells; @@ -157,8 +159,7 @@ node_vroot = find_devices("vdevice"); if ((node_vroot == NULL) || (node_vroot->child == NULL)) { - printk(KERN_INFO "VIO: missing or empty /vdevice node; no virtual IO" - " devices present.\n"); + /* this machine doesn't do virtual IO, and that's ok */ return 0; } @@ -260,7 +261,7 @@ /* init generic 'struct device' fields: */ viodev->dev.parent = &vio_bus_device->dev; viodev->dev.bus = &vio_bus_type; - snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%lx", viodev->unit_address); + snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", viodev->unit_address); viodev->dev.release = vio_dev_release; /* register with generic device framework */ @@ -299,6 +300,42 @@ } EXPORT_SYMBOL(vio_get_attribute); +/* vio_find_name() - internal because only vio.c knows how we formatted the + * kobject name + * XXX once vio_bus_type.devices is actually used as a kset in + * drivers/base/bus.c, this function should be removed in favor of + * "device_find(kobj_name, &vio_bus_type)" + */ +static struct vio_dev *vio_find_name(const char *kobj_name) +{ + struct kobject *found; + + found = kset_find_obj(&devices_subsys.kset, kobj_name); + if (!found) + return NULL; + + return to_vio_dev(container_of(found, struct device, kobj)); +} + +/** + * vio_find_node - find an already-registered vio_dev + * @vnode: device_node of the virtual device we're looking for + */ +struct vio_dev *vio_find_node(struct device_node *vnode) +{ + uint32_t *unit_address; + char kobj_name[BUS_ID_SIZE]; + + /* construct the kobject name from the device node */ + unit_address = (uint32_t *)get_property(vnode, "reg", NULL); + if (!unit_address) + return NULL; + snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address); + + return vio_find_name(kobj_name); +} +EXPORT_SYMBOL(vio_find_node); + /** * vio_build_iommu_table: - gets the dma information from OF and builds the TCE tree. * @dev: the virtual device. @@ -395,7 +432,7 @@ tbl = dev->iommu_table; if (tbl) { - dma_handle = iommu_alloc(tbl, vaddr, npages, direction, NULL); + dma_handle = iommu_alloc(tbl, vaddr, npages, direction); dma_handle |= (uaddr & ~PAGE_MASK); } @@ -424,7 +461,6 @@ int direction) { struct iommu_table *tbl; - unsigned long handle; BUG_ON(direction == PCI_DMA_NONE); @@ -435,7 +471,7 @@ if (!tbl) return 0; - return iommu_alloc_sg(tbl, sglist, nelems, direction, &handle); + return iommu_alloc_sg(tbl, &vdev->dev, sglist, nelems, direction); } EXPORT_SYMBOL(vio_map_sg); @@ -448,7 +484,7 @@ tbl = vdev->iommu_table; if (tbl) - iommu_free_sg(tbl, sglist, nelems, direction); + iommu_free_sg(tbl, sglist, nelems); } EXPORT_SYMBOL(vio_unmap_sg); @@ -480,7 +516,7 @@ /* Page allocation succeeded */ memset(ret, 0, npages << PAGE_SHIFT); /* Set up tces to cover the allocated range */ - tce = iommu_alloc(tbl, ret, npages, PCI_DMA_BIDIRECTIONAL, NULL); + tce = iommu_alloc(tbl, ret, npages, PCI_DMA_BIDIRECTIONAL); if (tce == NO_TCE) { PPCDBG(PPCDBG_TCE, "vio_alloc_consistent: iommu_alloc failed\n" ); free_pages((unsigned long)ret, order); diff -urN linux-2.6.4-rc1/arch/ppc64/mm/hash_low.S linux-2.6.4-rc2/arch/ppc64/mm/hash_low.S --- linux-2.6.4-rc1/arch/ppc64/mm/hash_low.S 2004-02-17 19:59:16.000000000 -0800 +++ linux-2.6.4-rc2/arch/ppc64/mm/hash_low.S 2004-03-03 22:48:08.000000000 -0800 @@ -176,7 +176,6 @@ beq- htab_pte_insert_failure /* Now try secondary slot */ - ori r30,r30,_PAGE_SECONDARY /* page number in r5 */ rldicl r5,r31,64-PTE_SHIFT,PTE_SHIFT @@ -215,8 +214,8 @@ b htab_insert_pte htab_pte_insert_ok: - /* Insert slot number in PTE */ - rldimi r30,r3,12,63-14 + /* Insert slot number & secondary bit in PTE */ + rldimi r30,r3,12,63-15 /* Write out the PTE with a normal write * (maybe add eieio may be good still ?) diff -urN linux-2.6.4-rc1/arch/ppc64/mm/numa.c linux-2.6.4-rc2/arch/ppc64/mm/numa.c --- linux-2.6.4-rc1/arch/ppc64/mm/numa.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/ppc64/mm/numa.c 2004-03-03 22:48:08.000000000 -0800 @@ -33,7 +33,10 @@ 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) { diff -urN linux-2.6.4-rc1/arch/s390/kernel/compat_ioctl.c linux-2.6.4-rc2/arch/s390/kernel/compat_ioctl.c --- linux-2.6.4-rc1/arch/s390/kernel/compat_ioctl.c 2004-02-17 19:58:39.000000000 -0800 +++ linux-2.6.4-rc2/arch/s390/kernel/compat_ioctl.c 2004-03-03 22:48:08.000000000 -0800 @@ -49,7 +49,16 @@ COMPATIBLE_IOCTL(BIODASDRLSE) COMPATIBLE_IOCTL(BIODASDSLCK) COMPATIBLE_IOCTL(BIODASDINFO) +COMPATIBLE_IOCTL(BIODASDINFO2) COMPATIBLE_IOCTL(BIODASDFMT) +COMPATIBLE_IOCTL(BIODASDPRRST) +COMPATIBLE_IOCTL(BIODASDQUIESCE) +COMPATIBLE_IOCTL(BIODASDRESUME) +COMPATIBLE_IOCTL(BIODASDPRRD) +COMPATIBLE_IOCTL(BIODASDPSRD) +COMPATIBLE_IOCTL(BIODASDGATTR) +COMPATIBLE_IOCTL(BIODASDSATTR) + #endif #if defined(CONFIG_S390_TAPE) || defined(CONFIG_S390_TAPE_MODULE) diff -urN linux-2.6.4-rc1/arch/s390/kernel/compat_linux.c linux-2.6.4-rc2/arch/s390/kernel/compat_linux.c --- linux-2.6.4-rc1/arch/s390/kernel/compat_linux.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/s390/kernel/compat_linux.c 2004-03-03 22:48:08.000000000 -0800 @@ -1161,8 +1161,7 @@ put_user(reclen, &dirent->d_reclen); copy_to_user(dirent->d_name, name, namlen); put_user(0, dirent->d_name + namlen); - ((char *) dirent) += reclen; - buf->current_dir = dirent; + buf->current_dir = ((void *)dirent) + reclen; buf->count -= reclen; return 0; } diff -urN linux-2.6.4-rc1/arch/s390/kernel/compat_ptrace.h linux-2.6.4-rc2/arch/s390/kernel/compat_ptrace.h --- linux-2.6.4-rc1/arch/s390/kernel/compat_ptrace.h 2004-02-17 19:57:25.000000000 -0800 +++ linux-2.6.4-rc2/arch/s390/kernel/compat_ptrace.h 2004-03-03 22:48:08.000000000 -0800 @@ -3,23 +3,20 @@ #include "compat_linux.h" /* needed for _psw_t32 */ -typedef struct -{ +typedef struct { __u32 cr[3]; -} per_cr_words32 __attribute__((packed)); +} per_cr_words32; -typedef struct -{ +typedef struct { __u16 perc_atmid; /* 0x096 */ __u32 address; /* 0x098 */ __u8 access_id; /* 0x0a1 */ -} per_lowcore_words32 __attribute__((packed)); +} per_lowcore_words32; -typedef struct -{ +typedef struct { union { per_cr_words32 words; - } control_regs __attribute__((packed)); + } control_regs; /* * Use these flags instead of setting em_instruction_fetch * directly they are used so that single stepping can be @@ -37,7 +34,7 @@ union { per_lowcore_words32 words; } lowcore; -} per_struct32 __attribute__((packed)); +} per_struct32; struct user_regs_struct32 { diff -urN linux-2.6.4-rc1/arch/s390/kernel/s390_ksyms.c linux-2.6.4-rc2/arch/s390/kernel/s390_ksyms.c --- linux-2.6.4-rc1/arch/s390/kernel/s390_ksyms.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/s390/kernel/s390_ksyms.c 2004-03-03 22:48:08.000000000 -0800 @@ -29,6 +29,7 @@ EXPORT_SYMBOL_NOVERS(_oi_bitmap); EXPORT_SYMBOL_NOVERS(_ni_bitmap); EXPORT_SYMBOL_NOVERS(_zb_findmap); +EXPORT_SYMBOL_NOVERS(_sb_findmap); EXPORT_SYMBOL_NOVERS(__copy_from_user_asm); EXPORT_SYMBOL_NOVERS(__copy_to_user_asm); EXPORT_SYMBOL_NOVERS(__clear_user_asm); @@ -92,5 +93,4 @@ EXPORT_SYMBOL_NOVERS(do_call_softirq); EXPORT_SYMBOL(sys_wait4); EXPORT_SYMBOL(cpcmd); -EXPORT_SYMBOL(smp_call_function_on); EXPORT_SYMBOL(sys_ioctl); diff -urN linux-2.6.4-rc1/arch/s390/kernel/smp.c linux-2.6.4-rc2/arch/s390/kernel/smp.c --- linux-2.6.4-rc1/arch/s390/kernel/smp.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/s390/kernel/smp.c 2004-03-03 22:48:08.000000000 -0800 @@ -203,10 +203,11 @@ put_cpu(); return 0; } +EXPORT_SYMBOL(smp_call_function_on); static inline void do_send_stop(void) { - u32 dummy; + unsigned long dummy; int i, rc; /* stop all processors */ @@ -222,7 +223,7 @@ static inline void do_store_status(void) { unsigned long low_core_addr; - u32 dummy; + unsigned long dummy; int i, rc; /* store status of all processors in their lowcores (real 0) */ @@ -619,7 +620,7 @@ if (lowcore_ptr[i] == NULL || async_stack == 0ULL) panic("smp_boot_cpus failed to allocate memory\n"); - memcpy(lowcore_ptr[i], &S390_lowcore, sizeof(struct _lowcore)); + *(lowcore_ptr[i]) = S390_lowcore; lowcore_ptr[i]->async_stack = async_stack + (ASYNC_SIZE); } set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]); diff -urN linux-2.6.4-rc1/arch/s390/kernel/traps.c linux-2.6.4-rc2/arch/s390/kernel/traps.c --- linux-2.6.4-rc1/arch/s390/kernel/traps.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/s390/kernel/traps.c 2004-03-03 22:48:08.000000000 -0800 @@ -616,8 +616,6 @@ pgm_check_table[9] = ÷_exception; pgm_check_table[0x10] = &do_segment_exception; pgm_check_table[0x11] = &do_page_exception; - pgm_check_table[0x10] = &do_segment_exception; - pgm_check_table[0x11] = &do_page_exception; pgm_check_table[0x12] = &translation_exception; pgm_check_table[0x13] = &special_op_exception; #ifndef CONFIG_ARCH_S390X diff -urN linux-2.6.4-rc1/arch/s390/mm/cmm.c linux-2.6.4-rc2/arch/s390/mm/cmm.c --- linux-2.6.4-rc1/arch/s390/mm/cmm.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/s390/mm/cmm.c 2004-03-03 22:48:08.000000000 -0800 @@ -87,8 +87,7 @@ pa->index = 0; *list = pa; } - if (page < 0x80000000UL) - diag10(page); + diag10(page); pa->pages[pa->index++] = page; (*counter)++; pages--; diff -urN linux-2.6.4-rc1/arch/s390/mm/init.c linux-2.6.4-rc2/arch/s390/mm/init.c --- linux-2.6.4-rc1/arch/s390/mm/init.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/s390/mm/init.c 2004-03-03 22:48:08.000000000 -0800 @@ -42,9 +42,9 @@ void diag10(unsigned long addr) { -#ifdef __s390x__ - if (addr >= 0x80000000) + if (addr >= 0x7ff00000) return; +#ifdef __s390x__ asm volatile ("sam31\n\t" "diag %0,%0,0x10\n\t" "sam64" : : "a" (addr) ); diff -urN linux-2.6.4-rc1/arch/sh/boards/adx/Makefile linux-2.6.4-rc2/arch/sh/boards/adx/Makefile --- linux-2.6.4-rc1/arch/sh/boards/adx/Makefile 2004-02-17 19:59:16.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/adx/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/bigsur/Makefile linux-2.6.4-rc2/arch/sh/boards/bigsur/Makefile --- linux-2.6.4-rc1/arch/sh/boards/bigsur/Makefile 2004-02-17 19:58:04.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/bigsur/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/cat68701/Makefile linux-2.6.4-rc2/arch/sh/boards/cat68701/Makefile --- linux-2.6.4-rc1/arch/sh/boards/cat68701/Makefile 2004-02-17 19:57:14.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/cat68701/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/cqreek/Makefile linux-2.6.4-rc2/arch/sh/boards/cqreek/Makefile --- linux-2.6.4-rc1/arch/sh/boards/cqreek/Makefile 2004-02-17 19:57:18.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/cqreek/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/dmida/Makefile linux-2.6.4-rc2/arch/sh/boards/dmida/Makefile --- linux-2.6.4-rc1/arch/sh/boards/dmida/Makefile 2004-02-17 19:57:15.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/dmida/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -2,10 +2,6 @@ # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/dreamcast/Makefile linux-2.6.4-rc2/arch/sh/boards/dreamcast/Makefile --- linux-2.6.4-rc1/arch/sh/boards/dreamcast/Makefile 2004-02-17 19:57:21.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/dreamcast/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/ec3104/Makefile linux-2.6.4-rc2/arch/sh/boards/ec3104/Makefile --- linux-2.6.4-rc1/arch/sh/boards/ec3104/Makefile 2004-02-17 19:58:48.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/ec3104/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/harp/Makefile linux-2.6.4-rc2/arch/sh/boards/harp/Makefile --- linux-2.6.4-rc1/arch/sh/boards/harp/Makefile 2004-02-17 19:57:16.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/harp/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/hp6xx/hp620/Makefile linux-2.6.4-rc2/arch/sh/boards/hp6xx/hp620/Makefile --- linux-2.6.4-rc1/arch/sh/boards/hp6xx/hp620/Makefile 2004-02-17 19:59:46.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/hp6xx/hp620/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/hp6xx/hp680/Makefile linux-2.6.4-rc2/arch/sh/boards/hp6xx/hp680/Makefile --- linux-2.6.4-rc1/arch/sh/boards/hp6xx/hp680/Makefile 2004-02-17 19:58:47.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/hp6xx/hp680/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/hp6xx/hp690/Makefile linux-2.6.4-rc2/arch/sh/boards/hp6xx/hp690/Makefile --- linux-2.6.4-rc1/arch/sh/boards/hp6xx/hp690/Makefile 2004-02-17 19:57:11.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/hp6xx/hp690/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/mpc1211/Makefile linux-2.6.4-rc2/arch/sh/boards/mpc1211/Makefile --- linux-2.6.4-rc1/arch/sh/boards/mpc1211/Makefile 2004-02-17 19:57:11.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/mpc1211/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/overdrive/Makefile linux-2.6.4-rc2/arch/sh/boards/overdrive/Makefile --- linux-2.6.4-rc1/arch/sh/boards/overdrive/Makefile 2004-02-17 19:59:25.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/overdrive/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/saturn/Makefile linux-2.6.4-rc2/arch/sh/boards/saturn/Makefile --- linux-2.6.4-rc1/arch/sh/boards/saturn/Makefile 2004-02-17 19:57:53.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/saturn/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/se/770x/Makefile linux-2.6.4-rc2/arch/sh/boards/se/770x/Makefile --- linux-2.6.4-rc1/arch/sh/boards/se/770x/Makefile 2004-02-17 19:59:06.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/se/770x/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/se/7751/Makefile linux-2.6.4-rc2/arch/sh/boards/se/7751/Makefile --- linux-2.6.4-rc1/arch/sh/boards/se/7751/Makefile 2004-02-17 19:59:35.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/se/7751/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/sh2000/Makefile linux-2.6.4-rc2/arch/sh/boards/sh2000/Makefile --- linux-2.6.4-rc1/arch/sh/boards/sh2000/Makefile 2004-02-17 19:59:25.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/sh2000/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/snapgear/Makefile linux-2.6.4-rc2/arch/sh/boards/snapgear/Makefile --- linux-2.6.4-rc1/arch/sh/boards/snapgear/Makefile 2004-02-17 19:59:29.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/snapgear/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/systemh/Makefile linux-2.6.4-rc2/arch/sh/boards/systemh/Makefile --- linux-2.6.4-rc1/arch/sh/boards/systemh/Makefile 2004-02-17 19:57:30.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/systemh/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/boards/unknown/Makefile linux-2.6.4-rc2/arch/sh/boards/unknown/Makefile --- linux-2.6.4-rc1/arch/sh/boards/unknown/Makefile 2004-02-17 19:58:55.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/boards/unknown/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/cchips/hd6446x/hd64461/Makefile linux-2.6.4-rc2/arch/sh/cchips/hd6446x/hd64461/Makefile --- linux-2.6.4-rc1/arch/sh/cchips/hd6446x/hd64461/Makefile 2004-02-17 19:58:42.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/cchips/hd6446x/hd64461/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sh/cchips/hd6446x/hd64465/Makefile linux-2.6.4-rc2/arch/sh/cchips/hd6446x/hd64465/Makefile --- linux-2.6.4-rc1/arch/sh/cchips/hd6446x/hd64465/Makefile 2004-02-17 19:59:26.000000000 -0800 +++ linux-2.6.4-rc2/arch/sh/cchips/hd6446x/hd64465/Makefile 2004-03-03 22:48:08.000000000 -0800 @@ -1,10 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/arch/sparc/kernel/setup.c linux-2.6.4-rc2/arch/sparc/kernel/setup.c --- linux-2.6.4-rc1/arch/sparc/kernel/setup.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/sparc/kernel/setup.c 2004-03-03 22:48:09.000000000 -0800 @@ -233,7 +233,6 @@ extern unsigned long start, end; extern void panic_setup(char *, int *); extern void srmmu_end_memory(unsigned long, unsigned long *); -extern void sun_serial_setup(void); extern unsigned short root_flags; extern unsigned short root_dev; diff -urN linux-2.6.4-rc1/arch/sparc64/Kconfig linux-2.6.4-rc2/arch/sparc64/Kconfig --- linux-2.6.4-rc1/arch/sparc64/Kconfig 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/sparc64/Kconfig 2004-03-03 22:48:09.000000000 -0800 @@ -450,28 +450,6 @@ 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" @@ -633,6 +611,15 @@ Say Y here if you are developing drivers or trying to debug and identify kernel problems. +config DEBUG_STACK_USAGE + bool "Enable stack utilization instrumentation" + depends on DEBUG_KERNEL + help + Enables the display of the minimum amount of free stack which each + task has ever had available in the sysrq-T and sysrq-P debug output. + + This option will slow down process creation somewhat. + config DEBUG_SLAB bool "Debug memory allocations" depends on DEBUG_KERNEL diff -urN linux-2.6.4-rc1/arch/sparc64/defconfig linux-2.6.4-rc2/arch/sparc64/defconfig --- linux-2.6.4-rc1/arch/sparc64/defconfig 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/sparc64/defconfig 2004-03-03 22:48:09.000000000 -0800 @@ -905,7 +905,6 @@ # # Old SIR device drivers # -# CONFIG_IRPORT_SIR is not set # # Old Serial dongle support @@ -1657,6 +1656,7 @@ # Kernel hacking # CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_SLAB is not set CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUG_SPINLOCK is not set diff -urN linux-2.6.4-rc1/arch/sparc64/mm/init.c linux-2.6.4-rc2/arch/sparc64/mm/init.c --- linux-2.6.4-rc1/arch/sparc64/mm/init.c 2004-02-17 19:57:26.000000000 -0800 +++ linux-2.6.4-rc2/arch/sparc64/mm/init.c 2004-03-03 22:48:09.000000000 -0800 @@ -1423,7 +1423,6 @@ /* paging_init() sets up the page tables */ -extern void sun_serial_setup(void); extern void cheetah_ecache_flush_init(void); static unsigned long last_valid_pfn; @@ -1548,15 +1547,6 @@ inherit_locked_prom_mappings(1); -#ifdef CONFIG_SUN_SERIAL - /* This does not logically belong here, but we need to call it at - * the moment we are able to use the bootmem allocator. This _has_ - * to be done after the prom_mappings above so since - * __alloc_bootmem() doesn't work correctly until then. - */ - sun_serial_setup(); -#endif - /* We only created DTLB mapping of this stuff. */ spitfire_flush_dtlb_nucleus_page(alias_base); if (second_alias_page) diff -urN linux-2.6.4-rc1/arch/x86_64/Makefile linux-2.6.4-rc2/arch/x86_64/Makefile --- linux-2.6.4-rc1/arch/x86_64/Makefile 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/x86_64/Makefile 2004-03-03 22:48:09.000000000 -0800 @@ -38,7 +38,7 @@ 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 diff -urN linux-2.6.4-rc1/arch/x86_64/defconfig linux-2.6.4-rc2/arch/x86_64/defconfig --- linux-2.6.4-rc1/arch/x86_64/defconfig 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/x86_64/defconfig 2004-03-03 22:48:09.000000000 -0800 @@ -27,6 +27,7 @@ # 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 @@ -106,6 +107,7 @@ 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 @@ -119,7 +121,6 @@ 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 @@ -168,6 +169,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_LBD=y +# CONFIG_DCSSBLK is not set # # ATA/ATAPI/MFM/RLL support @@ -306,7 +308,7 @@ # CONFIG_FUSION_CTL is not set # -# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# IEEE 1394 (FireWire) support # # CONFIG_IEEE1394 is not set @@ -489,7 +491,7 @@ # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set +# CONFIG_ISDN is not set # # Telephony Support @@ -562,7 +564,8 @@ 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 @@ -718,7 +721,6 @@ 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 @@ -731,6 +733,7 @@ # 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 @@ -761,7 +764,6 @@ # 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 # diff -urN linux-2.6.4-rc1/arch/x86_64/kernel/apic.c linux-2.6.4-rc2/arch/x86_64/kernel/apic.c --- linux-2.6.4-rc1/arch/x86_64/kernel/apic.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/x86_64/kernel/apic.c 2004-03-03 22:48:09.000000000 -0800 @@ -553,7 +553,7 @@ /* XXX: remove suspend/resume procs if !apic_pm_state.active? */ error = sysdev_class_register(&lapic_sysclass); if (!error) - error = sys_device_register(&device_lapic); + error = sysdev_register(&device_lapic); return error; } device_initcall(init_lapic_sysfs); diff -urN linux-2.6.4-rc1/arch/x86_64/kernel/i8259.c linux-2.6.4-rc2/arch/x86_64/kernel/i8259.c --- linux-2.6.4-rc1/arch/x86_64/kernel/i8259.c 2004-02-17 19:57:17.000000000 -0800 +++ linux-2.6.4-rc2/arch/x86_64/kernel/i8259.c 2004-03-03 22:48:09.000000000 -0800 @@ -423,14 +423,14 @@ static struct sys_device device_timer = { .id = 0, - .cls &timer_sysclass, + .cls = &timer_sysclass, }; static int __init init_timer_sysfs(void) { int error = sysdev_class_register(&timer_sysclass); if (!error) - error = sys_device_register(&device_timer); + error = sysdev_register(&device_timer); return error; } diff -urN linux-2.6.4-rc1/arch/x86_64/kernel/mce.c linux-2.6.4-rc2/arch/x86_64/kernel/mce.c --- linux-2.6.4-rc1/arch/x86_64/kernel/mce.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/x86_64/kernel/mce.c 2004-03-03 22:48:09.000000000 -0800 @@ -73,7 +73,9 @@ 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"); @@ -133,7 +135,7 @@ 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; } @@ -448,7 +450,7 @@ return -EIO; err = sysdev_class_register(&mce_sysclass); if (!err) - err = sys_device_register(&device_mce); + err = sysdev_register(&device_mce); if (!err) { /* could create per CPU objects, but is not worth it. */ sysdev_create_file(&device_mce, &attr_disabled_banks); diff -urN linux-2.6.4-rc1/arch/x86_64/kernel/nmi.c linux-2.6.4-rc2/arch/x86_64/kernel/nmi.c --- linux-2.6.4-rc1/arch/x86_64/kernel/nmi.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/x86_64/kernel/nmi.c 2004-03-03 22:48:09.000000000 -0800 @@ -241,7 +241,7 @@ error = sysdev_class_register(&nmi_sysclass); if (!error) - error = sys_device_register(&device_lapic_nmi); + error = sysdev_register(&device_lapic_nmi); return error; } /* must come after the local APIC's device_initcall() */ diff -urN linux-2.6.4-rc1/arch/x86_64/kernel/setup.c linux-2.6.4-rc2/arch/x86_64/kernel/setup.c --- linux-2.6.4-rc1/arch/x86_64/kernel/setup.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/x86_64/kernel/setup.c 2004-03-03 22:48:09.000000000 -0800 @@ -610,8 +610,7 @@ * 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; diff -urN linux-2.6.4-rc1/arch/x86_64/kernel/time.c linux-2.6.4-rc2/arch/x86_64/kernel/time.c --- linux-2.6.4-rc1/arch/x86_64/kernel/time.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/x86_64/kernel/time.c 2004-03-03 22:48:09.000000000 -0800 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -353,11 +354,11 @@ } 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; } @@ -399,8 +400,19 @@ 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; @@ -420,7 +432,7 @@ purposes. */ rdtscll(a); - return (a * vxtime.tsc_quot) >> 32; + return cycles_2_ns(a); } unsigned long get_cmos_time(void) @@ -527,6 +539,8 @@ vxtime.tsc_quot = (1000L << 32) / cpu_khz; } + set_cyc2ns_scale(cpu_khz_ref / 1000); + return 0; } @@ -725,6 +739,8 @@ 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); @@ -788,7 +804,7 @@ { int error = sysdev_class_register(&pit_sysclass); if (!error) - error = sys_device_register(&device_i8253); + error = sysdev_register(&device_i8253); return error; } diff -urN linux-2.6.4-rc1/arch/x86_64/kernel/traps.c linux-2.6.4-rc2/arch/x86_64/kernel/traps.c --- linux-2.6.4-rc1/arch/x86_64/kernel/traps.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/x86_64/kernel/traps.c 2004-03-03 22:48:09.000000000 -0800 @@ -351,9 +351,24 @@ 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 "); diff -urN linux-2.6.4-rc1/arch/x86_64/kernel/x8664_ksyms.c linux-2.6.4-rc2/arch/x86_64/kernel/x8664_ksyms.c --- linux-2.6.4-rc1/arch/x86_64/kernel/x8664_ksyms.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/arch/x86_64/kernel/x8664_ksyms.c 2004-03-03 22:48:09.000000000 -0800 @@ -196,6 +196,7 @@ #ifdef CONFIG_SMP EXPORT_SYMBOL(cpu_sibling_map); +EXPORT_SYMBOL(smp_num_siblings); #endif extern void do_softirq_thunk(void); diff -urN linux-2.6.4-rc1/crypto/Makefile linux-2.6.4-rc2/crypto/Makefile --- linux-2.6.4-rc1/crypto/Makefile 2004-02-17 19:59:44.000000000 -0800 +++ linux-2.6.4-rc2/crypto/Makefile 2004-03-03 22:48:09.000000000 -0800 @@ -4,7 +4,7 @@ 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 diff -urN linux-2.6.4-rc1/crypto/cipher.c linux-2.6.4-rc2/crypto/cipher.c --- linux-2.6.4-rc1/crypto/cipher.c 2004-02-17 19:58:02.000000000 -0800 +++ linux-2.6.4-rc2/crypto/cipher.c 2004-03-03 22:48:09.000000000 -0800 @@ -4,7 +4,6 @@ * Cipher operations. * * Copyright (c) 2002 James Morris - * Generic scatterwalk code by Adam J. Richter . * * 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 @@ -17,30 +16,13 @@ #include #include #include -#include -#include #include #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) { @@ -57,108 +39,6 @@ } -/* 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, @@ -191,19 +71,21 @@ 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; @@ -212,8 +94,8 @@ } } -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; @@ -226,10 +108,9 @@ 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)); @@ -239,7 +120,7 @@ } 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); } diff -urN linux-2.6.4-rc1/crypto/internal.h linux-2.6.4-rc2/crypto/internal.h --- linux-2.6.4-rc1/crypto/internal.h 2004-02-17 19:57:12.000000000 -0800 +++ linux-2.6.4-rc2/crypto/internal.h 2004-03-03 22:48:09.000000000 -0800 @@ -11,6 +11,7 @@ */ #ifndef _CRYPTO_INTERNAL_H #define _CRYPTO_INTERNAL_H +#include #include #include #include diff -urN linux-2.6.4-rc1/crypto/scatterwalk.c linux-2.6.4-rc2/crypto/scatterwalk.c --- linux-2.6.4-rc1/crypto/scatterwalk.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/crypto/scatterwalk.c 2004-03-03 22:48:09.000000000 -0800 @@ -0,0 +1,124 @@ +/* + * Cryptographic API. + * + * Cipher operations. + * + * Copyright (c) 2002 James Morris + * 2002 Adam J. Richter + * 2004 Jean-Luc Cooke + * + * 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 +#include +#include +#include +#include +#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; +} diff -urN linux-2.6.4-rc1/crypto/scatterwalk.h linux-2.6.4-rc2/crypto/scatterwalk.h --- linux-2.6.4-rc1/crypto/scatterwalk.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/crypto/scatterwalk.h 2004-03-03 22:48:09.000000000 -0800 @@ -0,0 +1,50 @@ +/* + * Cryptographic API. + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 Adam J. Richter + * Copyright (c) 2004 Jean-Luc Cooke + * + * 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 +#include + +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 */ diff -urN linux-2.6.4-rc1/drivers/Kconfig linux-2.6.4-rc2/drivers/Kconfig --- linux-2.6.4-rc1/drivers/Kconfig 2004-02-17 19:59:31.000000000 -0800 +++ linux-2.6.4-rc2/drivers/Kconfig 2004-03-03 22:48:09.000000000 -0800 @@ -42,7 +42,7 @@ source "drivers/i2c/Kconfig" -# source "drivers/misc/Kconfig" +source "drivers/misc/Kconfig" source "drivers/media/Kconfig" diff -urN linux-2.6.4-rc1/drivers/base/Kconfig linux-2.6.4-rc2/drivers/base/Kconfig --- linux-2.6.4-rc1/drivers/base/Kconfig 2004-02-17 19:57:17.000000000 -0800 +++ linux-2.6.4-rc2/drivers/base/Kconfig 2004-03-03 22:48:09.000000000 -0800 @@ -8,4 +8,15 @@ require hotplug firmware loading support, but a module built outside the kernel tree does. +config DEBUG_DRIVER + bool "Driver Core verbose debug messages" + depends on DEBUG_KERNEL + help + Say Y here if you want the Driver core to produce a bunch of + debug messages to the system log. Select this if you are having a + problem with the driver core and want to see more of what is + going on. + + If you are unsure about this, say N here. + endmenu diff -urN linux-2.6.4-rc1/drivers/base/bus.c linux-2.6.4-rc2/drivers/base/bus.c --- linux-2.6.4-rc1/drivers/base/bus.c 2004-02-17 19:57:20.000000000 -0800 +++ linux-2.6.4-rc2/drivers/base/bus.c 2004-03-03 22:48:09.000000000 -0800 @@ -8,7 +8,10 @@ * */ -#undef DEBUG +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include diff -urN linux-2.6.4-rc1/drivers/base/class.c linux-2.6.4-rc2/drivers/base/class.c --- linux-2.6.4-rc1/drivers/base/class.c 2004-02-17 19:59:50.000000000 -0800 +++ linux-2.6.4-rc2/drivers/base/class.c 2004-03-03 22:48:09.000000000 -0800 @@ -10,7 +10,10 @@ * */ -#undef DEBUG +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include diff -urN linux-2.6.4-rc1/drivers/base/class_simple.c linux-2.6.4-rc2/drivers/base/class_simple.c --- linux-2.6.4-rc1/drivers/base/class_simple.c 2004-02-17 19:57:30.000000000 -0800 +++ linux-2.6.4-rc2/drivers/base/class_simple.c 2004-03-03 22:48:09.000000000 -0800 @@ -8,7 +8,10 @@ * */ -#define DEBUG 1 +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include diff -urN linux-2.6.4-rc1/drivers/base/core.c linux-2.6.4-rc2/drivers/base/core.c --- linux-2.6.4-rc1/drivers/base/core.c 2004-02-17 19:57:14.000000000 -0800 +++ linux-2.6.4-rc2/drivers/base/core.c 2004-03-03 22:48:09.000000000 -0800 @@ -8,7 +8,10 @@ * */ -#undef DEBUG +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include diff -urN linux-2.6.4-rc1/drivers/base/cpu.c linux-2.6.4-rc2/drivers/base/cpu.c --- linux-2.6.4-rc1/drivers/base/cpu.c 2004-02-17 19:57:22.000000000 -0800 +++ linux-2.6.4-rc2/drivers/base/cpu.c 2004-03-03 22:48:09.000000000 -0800 @@ -29,7 +29,7 @@ cpu->sysdev.id = num; cpu->sysdev.cls = &cpu_sysdev_class; - error = sys_device_register(&cpu->sysdev); + error = sysdev_register(&cpu->sysdev); if (!error && root) error = sysfs_create_link(&root->sysdev.kobj, &cpu->sysdev.kobj, diff -urN linux-2.6.4-rc1/drivers/base/driver.c linux-2.6.4-rc2/drivers/base/driver.c --- linux-2.6.4-rc1/drivers/base/driver.c 2004-02-17 19:59:20.000000000 -0800 +++ linux-2.6.4-rc2/drivers/base/driver.c 2004-03-03 22:48:09.000000000 -0800 @@ -8,7 +8,10 @@ * */ -#undef DEBUG +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include diff -urN linux-2.6.4-rc1/drivers/base/firmware_class.c linux-2.6.4-rc2/drivers/base/firmware_class.c --- linux-2.6.4-rc1/drivers/base/firmware_class.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/base/firmware_class.c 2004-03-03 22:48:09.000000000 -0800 @@ -27,6 +27,7 @@ FW_STATUS_LOADING, FW_STATUS_DONE, FW_STATUS_ABORT, + FW_STATUS_READY, }; static int loading_timeout = 10; /* In seconds */ @@ -96,6 +97,9 @@ 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) @@ -263,6 +267,8 @@ kfree(fw_priv); kfree(class_dev); + + module_put(THIS_MODULE); } static void @@ -325,6 +331,7 @@ 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) @@ -338,6 +345,9 @@ 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; @@ -356,6 +366,7 @@ goto error_unreg; } + set_bit(FW_STATUS_READY, &fw_priv->status); *class_dev_p = class_dev; goto out; @@ -409,6 +420,7 @@ 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); diff -urN linux-2.6.4-rc1/drivers/base/init.c linux-2.6.4-rc2/drivers/base/init.c --- linux-2.6.4-rc1/drivers/base/init.c 2004-02-17 19:57:15.000000000 -0800 +++ linux-2.6.4-rc2/drivers/base/init.c 2004-03-03 22:48:09.000000000 -0800 @@ -15,7 +15,7 @@ extern int classes_init(void); extern int firmware_init(void); extern int platform_bus_init(void); -extern int sys_bus_init(void); +extern int system_bus_init(void); extern int cpu_dev_init(void); /** @@ -37,6 +37,6 @@ * core core pieces. */ platform_bus_init(); - sys_bus_init(); + system_bus_init(); cpu_dev_init(); } diff -urN linux-2.6.4-rc1/drivers/base/node.c linux-2.6.4-rc2/drivers/base/node.c --- linux-2.6.4-rc1/drivers/base/node.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/base/node.c 2004-03-03 22:48:09.000000000 -0800 @@ -69,7 +69,7 @@ node->cpumap = node_to_cpumask(num); node->sysdev.id = num; node->sysdev.cls = &node_class; - error = sys_device_register(&node->sysdev); + error = sysdev_register(&node->sysdev); if (!error){ sysdev_create_file(&node->sysdev, &attr_cpumap); diff -urN linux-2.6.4-rc1/drivers/base/power/main.c linux-2.6.4-rc2/drivers/base/power/main.c --- linux-2.6.4-rc1/drivers/base/power/main.c 2004-02-17 19:59:14.000000000 -0800 +++ linux-2.6.4-rc2/drivers/base/power/main.c 2004-03-03 22:48:09.000000000 -0800 @@ -19,7 +19,10 @@ * ancestral dependencies that the subsystem list maintains. */ -#undef DEBUG +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include "power.h" diff -urN linux-2.6.4-rc1/drivers/base/power/shutdown.c linux-2.6.4-rc2/drivers/base/power/shutdown.c --- linux-2.6.4-rc1/drivers/base/power/shutdown.c 2004-02-17 19:58:34.000000000 -0800 +++ linux-2.6.4-rc2/drivers/base/power/shutdown.c 2004-03-03 22:48:09.000000000 -0800 @@ -8,7 +8,10 @@ * */ -#undef DEBUG +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include @@ -54,7 +57,7 @@ down_write(&devices_subsys.rwsem); list_for_each_entry_reverse(dev,&devices_subsys.kset.list,kobj.entry) { - pr_debug("shutting down %s: ",dev->name); + pr_debug("shutting down %s: ",dev->bus_id); if (dev->driver && dev->driver->shutdown) { pr_debug("Ok\n"); dev->driver->shutdown(dev); diff -urN linux-2.6.4-rc1/drivers/base/sys.c linux-2.6.4-rc2/drivers/base/sys.c --- linux-2.6.4-rc1/drivers/base/sys.c 2004-02-17 19:57:11.000000000 -0800 +++ linux-2.6.4-rc2/drivers/base/sys.c 2004-03-03 22:48:09.000000000 -0800 @@ -8,11 +8,14 @@ * * This exports a 'system' bus type. * By default, a 'sys' bus gets added to the root of the system. There will - * always be core system devices. Devices can use sys_device_register() to + * always be core system devices. Devices can use sysdev_register() to * add themselves as children of the system bus. */ -#undef DEBUG +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include @@ -164,11 +167,11 @@ /** - * sys_device_register - add a system device to the tree + * sysdev_register - add a system device to the tree * @sysdev: device in question * */ -int sys_device_register(struct sys_device * sysdev) +int sysdev_register(struct sys_device * sysdev) { int error; struct sysdev_class * cls = sysdev->cls; @@ -212,7 +215,7 @@ return error; } -void sys_device_unregister(struct sys_device * sysdev) +void sysdev_unregister(struct sys_device * sysdev) { struct sysdev_driver * drv; @@ -384,11 +387,11 @@ } -int __init sys_bus_init(void) +int __init system_bus_init(void) { system_subsys.kset.kobj.parent = &devices_subsys.kset.kobj; return subsystem_register(&system_subsys); } -EXPORT_SYMBOL(sys_device_register); -EXPORT_SYMBOL(sys_device_unregister); +EXPORT_SYMBOL(sysdev_register); +EXPORT_SYMBOL(sysdev_unregister); diff -urN linux-2.6.4-rc1/drivers/block/viodasd.c linux-2.6.4-rc2/drivers/block/viodasd.c --- linux-2.6.4-rc1/drivers/block/viodasd.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/block/viodasd.c 2004-03-03 22:48:09.000000000 -0800 @@ -70,7 +70,6 @@ MAX_DISK_NAME = sizeof(((struct gendisk *)0)->disk_name) }; -static int viodasd_max_disk; static spinlock_t viodasd_spinlock = SPIN_LOCK_UNLOCKED; #define VIOMAXREQ 16 @@ -209,7 +208,6 @@ (int)we.rc, we.sub_result, err->msg); return -EIO; } - viodasd_max_disk = we.max_disk; return 0; } @@ -483,7 +481,17 @@ if (we.rc != 0) return; - viodasd_max_disk = we.max_disk; + if (we.max_disk > (MAX_DISKNO - 1)) { + static int warned; + + if (warned == 0) { + warned++; + printk(VIOD_KERN_INFO + "Only examining the first %d " + "of %d disks connected\n", + MAX_DISKNO, we.max_disk + 1); + } + } /* Send the close event to OS/400. We DON'T expect a response */ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, @@ -744,21 +752,8 @@ /* Initialize our request handler */ vio_setHandler(viomajorsubtype_blockio, handle_block_event); - viodasd_max_disk = MAX_DISKNO - 1; - for (i = 0; (i <= viodasd_max_disk) && (i < MAX_DISKNO); i++) { - /* - * Note that probe_disk has side effects: - * a) it updates the size of the disk - * b) it updates viodasd_max_disk - * c) it registers the disk if it has not done so already - */ + for (i = 0; i < MAX_DISKNO; i++) probe_disk(&viodasd_devices[i]); - } - - if (viodasd_max_disk > (MAX_DISKNO - 1)) - printk(VIOD_KERN_INFO - "Only examining the first %d of %d disks connected\n", - MAX_DISKNO, viodasd_max_disk + 1); return 0; } diff -urN linux-2.6.4-rc1/drivers/bluetooth/bluecard_cs.c linux-2.6.4-rc2/drivers/bluetooth/bluecard_cs.c --- linux-2.6.4-rc1/drivers/bluetooth/bluecard_cs.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/bluetooth/bluecard_cs.c 2004-03-03 22:48:09.000000000 -0800 @@ -226,7 +226,7 @@ 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; } @@ -379,7 +379,7 @@ int i, len; if (!info) { - printk(KERN_WARNING "bluecard_cs: Call of receive for unknown device.\n"); + BT_ERR("Unknown device"); return; } @@ -397,7 +397,7 @@ 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; } } @@ -439,7 +439,7 @@ 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); @@ -506,7 +506,7 @@ 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; } @@ -574,7 +574,7 @@ 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; } @@ -664,7 +664,7 @@ 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; } @@ -780,7 +780,7 @@ /* 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; } @@ -799,7 +799,7 @@ 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; } @@ -825,7 +825,7 @@ 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); diff -urN linux-2.6.4-rc1/drivers/bluetooth/bt3c_cs.c linux-2.6.4-rc2/drivers/bluetooth/bt3c_cs.c --- linux-2.6.4-rc1/drivers/bluetooth/bt3c_cs.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/bluetooth/bt3c_cs.c 2004-03-03 22:48:09.000000000 -0800 @@ -195,7 +195,7 @@ unsigned long flags; if (!info) { - printk(KERN_WARNING "bt3c_cs: Call of write_wakeup for unknown device.\n"); + BT_ERR("Unknown device"); return; } @@ -222,7 +222,7 @@ 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); @@ -241,7 +241,7 @@ int size = 0, avail; if (!info) { - printk(KERN_WARNING "bt3c_cs: Call of receive for unknown device.\n"); + BT_ERR("Unknown device"); return; } @@ -260,7 +260,7 @@ 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; } } @@ -292,7 +292,7 @@ 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)); @@ -362,7 +362,7 @@ 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; } @@ -375,16 +375,16 @@ 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); } @@ -441,7 +441,7 @@ 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; } @@ -499,7 +499,7 @@ 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; } @@ -536,7 +536,7 @@ /* 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; } @@ -555,7 +555,7 @@ 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; } @@ -571,7 +571,7 @@ 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); @@ -769,7 +769,7 @@ 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; } diff -urN linux-2.6.4-rc1/drivers/bluetooth/btuart_cs.c linux-2.6.4-rc2/drivers/bluetooth/btuart_cs.c --- linux-2.6.4-rc1/drivers/bluetooth/btuart_cs.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/bluetooth/btuart_cs.c 2004-03-03 22:48:09.000000000 -0800 @@ -148,7 +148,7 @@ 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; } @@ -195,7 +195,7 @@ int boguscount = 0; if (!info) { - printk(KERN_WARNING "btuart_cs: Call of receive for unknown device.\n"); + BT_ERR("Unknown device"); return; } @@ -209,7 +209,7 @@ 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; } } @@ -238,7 +238,7 @@ 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)); @@ -309,7 +309,7 @@ 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; } @@ -325,7 +325,7 @@ switch (iir) { case UART_IIR_RLSI: - printk(KERN_NOTICE "btuart_cs: RLSI\n"); + BT_ERR("RLSI"); break; case UART_IIR_RDI: /* Receive interrupt */ @@ -338,7 +338,7 @@ } break; default: - printk(KERN_NOTICE "btuart_cs: Unhandled IIR=%#x\n", iir); + BT_ERR("Unhandled IIR=%#x", iir); break; } @@ -365,7 +365,7 @@ int divisor; if (!info) { - printk(KERN_WARNING "btuart_cs: Call of change speed for unknown device.\n"); + BT_ERR("Unknown device"); return; } @@ -447,7 +447,7 @@ 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; } @@ -531,7 +531,7 @@ /* 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; } @@ -550,7 +550,7 @@ 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; } @@ -578,7 +578,7 @@ 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); @@ -777,7 +777,7 @@ 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; } diff -urN linux-2.6.4-rc1/drivers/bluetooth/dtl1_cs.c linux-2.6.4-rc2/drivers/bluetooth/dtl1_cs.c --- linux-2.6.4-rc1/drivers/bluetooth/dtl1_cs.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/bluetooth/dtl1_cs.c 2004-03-03 22:48:09.000000000 -0800 @@ -150,7 +150,7 @@ 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; } @@ -201,9 +201,9 @@ 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"); @@ -226,7 +226,7 @@ int boguscount = 0; if (!info) { - printk(KERN_WARNING "dtl1_cs: Call of receive for unknown device.\n"); + BT_ERR("Unknown device"); return; } @@ -238,7 +238,7 @@ /* 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; @@ -283,7 +283,7 @@ 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; } @@ -313,7 +313,7 @@ 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; } @@ -329,7 +329,7 @@ switch (iir) { case UART_IIR_RLSI: - printk(KERN_NOTICE "dtl1_cs: RLSI\n"); + BT_ERR("RLSI"); break; case UART_IIR_RDI: /* Receive interrupt */ @@ -342,7 +342,7 @@ } break; default: - printk(KERN_NOTICE "dtl1_cs: Unhandled IIR=%#x\n", iir); + BT_ERR("Unhandled IIR=%#x", iir); break; } @@ -410,7 +410,7 @@ 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; } @@ -510,7 +510,7 @@ /* 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; } @@ -529,7 +529,7 @@ 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; } @@ -557,7 +557,7 @@ 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); diff -urN linux-2.6.4-rc1/drivers/char/cyclades.c linux-2.6.4-rc2/drivers/char/cyclades.c --- linux-2.6.4-rc1/drivers/char/cyclades.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/cyclades.c 2004-03-03 22:48:09.000000000 -0800 @@ -5411,6 +5411,7 @@ 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; diff -urN linux-2.6.4-rc1/drivers/char/epca.c linux-2.6.4-rc2/drivers/char/epca.c --- linux-2.6.4-rc1/drivers/char/epca.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/epca.c 2004-03-03 22:48:09.000000000 -0800 @@ -1644,6 +1644,7 @@ 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; diff -urN linux-2.6.4-rc1/drivers/char/esp.c linux-2.6.4-rc2/drivers/char/esp.c --- linux-2.6.4-rc1/drivers/char/esp.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/esp.c 2004-03-03 22:48:09.000000000 -0800 @@ -2491,6 +2491,7 @@ 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; diff -urN linux-2.6.4-rc1/drivers/char/isicom.c linux-2.6.4-rc2/drivers/char/isicom.c --- linux-2.6.4-rc1/drivers/char/isicom.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/isicom.c 2004-03-03 22:48:09.000000000 -0800 @@ -1627,6 +1627,7 @@ 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; diff -urN linux-2.6.4-rc1/drivers/char/lp.c linux-2.6.4-rc2/drivers/char/lp.c --- linux-2.6.4-rc1/drivers/char/lp.c 2004-02-17 19:57:12.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/lp.c 2004-03-03 22:48:09.000000000 -0800 @@ -862,10 +862,9 @@ } static struct parport_driver lp_driver = { - "lp", - lp_attach, - lp_detach, - NULL + .name = "lp", + .attach = lp_attach, + .detach = lp_detach, }; int __init lp_init (void) diff -urN linux-2.6.4-rc1/drivers/char/misc.c linux-2.6.4-rc2/drivers/char/misc.c --- linux-2.6.4-rc1/drivers/char/misc.c 2004-02-17 19:59:29.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/misc.c 2004-03-03 22:48:09.000000000 -0800 @@ -212,6 +212,9 @@ int misc_register(struct miscdevice * misc) { struct miscdevice *c; + struct class_device *class; + dev_t dev; + int err; down(&misc_sem); list_for_each_entry(c, &misc_list, list) { @@ -240,19 +243,30 @@ snprintf(misc->devfs_name, sizeof(misc->devfs_name), "misc/%s", misc->name); } + dev = MKDEV(MISC_MAJOR, misc->minor); - class_simple_device_add(misc_class, MKDEV(MISC_MAJOR, misc->minor), - misc->dev, misc->name); - devfs_mk_cdev(MKDEV(MISC_MAJOR, misc->minor), - S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, misc->devfs_name); + class = class_simple_device_add(misc_class, dev, + misc->dev, misc->name); + if (IS_ERR(class)) { + err = PTR_ERR(class); + goto out; + } + + err = devfs_mk_cdev(dev, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, + misc->devfs_name); + if (err) { + class_simple_device_remove(dev); + goto out; + } /* * Add it to the front, so that later devices can "override" * earlier defaults */ list_add(&misc->list, &misc_list); + out: up(&misc_sem); - return 0; + return err; } /** diff -urN linux-2.6.4-rc1/drivers/char/moxa.c linux-2.6.4-rc2/drivers/char/moxa.c --- linux-2.6.4-rc1/drivers/char/moxa.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/moxa.c 2004-03-03 22:48:09.000000000 -0800 @@ -309,6 +309,7 @@ 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; diff -urN linux-2.6.4-rc1/drivers/char/pcxx.c linux-2.6.4-rc2/drivers/char/pcxx.c --- linux-2.6.4-rc1/drivers/char/pcxx.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/pcxx.c 2004-03-03 22:48:09.000000000 -0800 @@ -1150,6 +1150,7 @@ 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; diff -urN linux-2.6.4-rc1/drivers/char/riscom8.c linux-2.6.4-rc2/drivers/char/riscom8.c --- linux-2.6.4-rc1/drivers/char/riscom8.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/riscom8.c 2004-03-03 22:48:09.000000000 -0800 @@ -1687,6 +1687,7 @@ 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; diff -urN linux-2.6.4-rc1/drivers/char/tipar.c linux-2.6.4-rc2/drivers/char/tipar.c --- linux-2.6.4-rc1/drivers/char/tipar.c 2004-02-17 19:58:48.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/tipar.c 2004-03-03 22:48:09.000000000 -0800 @@ -463,10 +463,9 @@ } static struct parport_driver tipar_driver = { - "tipar", - tipar_attach, - tipar_detach, - NULL + .name = "tipar", + .attach = tipar_attach, + .detach = tipar_detach, }; int __init diff -urN linux-2.6.4-rc1/drivers/char/vt.c linux-2.6.4-rc2/drivers/char/vt.c --- linux-2.6.4-rc1/drivers/char/vt.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/vt.c 2004-03-03 22:48:09.000000000 -0800 @@ -2743,12 +2743,12 @@ * 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; } } @@ -2776,7 +2776,7 @@ 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; @@ -2794,7 +2794,7 @@ 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); @@ -2808,14 +2808,14 @@ } 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; @@ -2839,7 +2839,7 @@ } 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) @@ -2849,6 +2849,17 @@ } /* + * 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 diff -urN linux-2.6.4-rc1/drivers/char/vt_ioctl.c linux-2.6.4-rc2/drivers/char/vt_ioctl.c --- linux-2.6.4-rc1/drivers/char/vt_ioctl.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/vt_ioctl.c 2004-03-03 22:48:09.000000000 -0800 @@ -497,7 +497,7 @@ */ acquire_console_sem(); if (arg == KD_TEXT) - unblank_screen(); + do_unblank_screen(1); else do_blank_screen(1); release_console_sem(); @@ -1103,7 +1103,7 @@ 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); } @@ -1138,7 +1138,7 @@ 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); } diff -urN linux-2.6.4-rc1/drivers/char/watchdog/Kconfig linux-2.6.4-rc2/drivers/char/watchdog/Kconfig --- linux-2.6.4-rc1/drivers/char/watchdog/Kconfig 2004-02-17 19:58:38.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/Kconfig 2004-03-03 22:48:09.000000000 -0800 @@ -339,6 +339,30 @@ 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 # @@ -455,4 +479,26 @@ 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 . + + To compile this driver as a module, choose M here: the + module will be called pcwd_usb. + + Most people will say N. + endmenu diff -urN linux-2.6.4-rc1/drivers/char/watchdog/Makefile linux-2.6.4-rc2/drivers/char/watchdog/Makefile --- linux-2.6.4-rc1/drivers/char/watchdog/Makefile 2004-02-17 19:58:48.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/Makefile 2004-03-03 22:48:09.000000000 -0800 @@ -1,5 +1,5 @@ # -# Makefile for the kernel character device drivers. +# Makefile for the WatchDog device drivers. # # Only one watchdog can succeed. We probe the hardware watchdog @@ -35,3 +35,4 @@ obj-$(CONFIG_AMD7XX_TCO) += amd7xx_tco.o obj-$(CONFIG_INDYDOG) += indydog.o obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o +obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o diff -urN linux-2.6.4-rc1/drivers/char/watchdog/cpu5wdt.c linux-2.6.4-rc2/drivers/char/watchdog/cpu5wdt.c --- linux-2.6.4-rc1/drivers/char/watchdog/cpu5wdt.c 2004-02-17 19:57:21.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/cpu5wdt.c 2004-03-03 22:48:09.000000000 -0800 @@ -293,6 +293,7 @@ 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"); diff -urN linux-2.6.4-rc1/drivers/char/watchdog/eurotechwdt.c linux-2.6.4-rc2/drivers/char/watchdog/eurotechwdt.c --- linux-2.6.4-rc1/drivers/char/watchdog/eurotechwdt.c 2004-02-17 19:57:16.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/eurotechwdt.c 2004-03-03 22:48:09.000000000 -0800 @@ -503,3 +503,4 @@ MODULE_AUTHOR("Rodolfo Giometti"); MODULE_DESCRIPTION("Driver for Eurotech CPU-1220/1410 on board watchdog"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.4-rc1/drivers/char/watchdog/ib700wdt.c linux-2.6.4-rc2/drivers/char/watchdog/ib700wdt.c --- linux-2.6.4-rc1/drivers/char/watchdog/ib700wdt.c 2004-02-17 19:59:27.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/ib700wdt.c 2004-03-03 22:48:09.000000000 -0800 @@ -350,5 +350,6 @@ MODULE_AUTHOR("Charles Howes "); MODULE_DESCRIPTION("IB700 SBC watchdog driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); /* end of ib700wdt.c */ diff -urN linux-2.6.4-rc1/drivers/char/watchdog/machzwd.c linux-2.6.4-rc2/drivers/char/watchdog/machzwd.c --- linux-2.6.4-rc1/drivers/char/watchdog/machzwd.c 2004-02-17 19:57:17.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/machzwd.c 2004-03-03 22:48:09.000000000 -0800 @@ -98,6 +98,7 @@ MODULE_AUTHOR("Fernando Fuganti "); MODULE_DESCRIPTION("MachZ ZF-Logic Watchdog driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); #ifdef CONFIG_WATCHDOG_NOWAYOUT static int nowayout = 1; diff -urN linux-2.6.4-rc1/drivers/char/watchdog/mixcomwd.c linux-2.6.4-rc2/drivers/char/watchdog/mixcomwd.c --- linux-2.6.4-rc1/drivers/char/watchdog/mixcomwd.c 2004-02-17 19:57:21.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/mixcomwd.c 2004-03-03 22:48:09.000000000 -0800 @@ -302,4 +302,7 @@ module_init(mixcomwd_init); module_exit(mixcomwd_exit); +MODULE_AUTHOR("Gergely Madarasz "); +MODULE_DESCRIPTION("MixCom Watchdog driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.4-rc1/drivers/char/watchdog/pcwd.c linux-2.6.4-rc2/drivers/char/watchdog/pcwd.c --- linux-2.6.4-rc1/drivers/char/watchdog/pcwd.c 2004-02-17 19:57:15.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/pcwd.c 2004-03-03 22:48:09.000000000 -0800 @@ -705,5 +705,8 @@ module_init(pcwatchdog_init); module_exit(pcwatchdog_exit); +MODULE_AUTHOR("Ken Hollis "); +MODULE_DESCRIPTION("Berkshire ISA-PC Watchdog driver"); MODULE_LICENSE("GPL"); - +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +MODULE_ALIAS_MISCDEV(TEMP_MINOR); diff -urN linux-2.6.4-rc1/drivers/char/watchdog/pcwd_usb.c linux-2.6.4-rc2/drivers/char/watchdog/pcwd_usb.c --- linux-2.6.4-rc1/drivers/char/watchdog/pcwd_usb.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/pcwd_usb.c 2004-03-03 22:48:09.000000000 -0800 @@ -0,0 +1,810 @@ +/* + * Berkshire USB-PC Watchdog Card Driver + * + * (c) Copyright 2004 Wim Van Sebroeck . + * + * Based on source code of the following authors: + * Ken Hollis , + * Alan Cox , + * Matt Domsch , + * Rob Radez , + * Greg Kroah-Hartman + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#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 " +#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. (0context; + 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, ""); + } + + 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 0udev. + */ +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); diff -urN linux-2.6.4-rc1/drivers/char/watchdog/sa1100_wdt.c linux-2.6.4-rc2/drivers/char/watchdog/sa1100_wdt.c --- linux-2.6.4-rc1/drivers/char/watchdog/sa1100_wdt.c 2004-02-17 19:57:52.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/sa1100_wdt.c 2004-03-03 22:48:09.000000000 -0800 @@ -218,3 +218,4 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.4-rc1/drivers/char/watchdog/sc1200wdt.c linux-2.6.4-rc2/drivers/char/watchdog/sc1200wdt.c --- linux-2.6.4-rc1/drivers/char/watchdog/sc1200wdt.c 2004-02-17 19:57:18.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/sc1200wdt.c 2004-03-03 22:48:09.000000000 -0800 @@ -486,3 +486,4 @@ MODULE_AUTHOR("Zwane Mwaikambo "); MODULE_DESCRIPTION("Driver for National Semiconductor PC87307/PC97307 watchdog component"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.4-rc1/drivers/char/watchdog/w83627hf_wdt.c linux-2.6.4-rc2/drivers/char/watchdog/w83627hf_wdt.c --- linux-2.6.4-rc1/drivers/char/watchdog/w83627hf_wdt.c 2004-02-17 19:58:10.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/w83627hf_wdt.c 2004-03-03 22:48:09.000000000 -0800 @@ -321,4 +321,4 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Pádraig Brady "); MODULE_DESCRIPTION("w38627hf WDT driver"); - +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.4-rc1/drivers/char/watchdog/w83877f_wdt.c linux-2.6.4-rc2/drivers/char/watchdog/w83877f_wdt.c --- linux-2.6.4-rc1/drivers/char/watchdog/w83877f_wdt.c 2004-02-17 19:58:32.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/w83877f_wdt.c 2004-03-03 22:48:09.000000000 -0800 @@ -427,3 +427,4 @@ MODULE_AUTHOR("Scott and Bill Jennings"); MODULE_DESCRIPTION("Driver for watchdog timer in w83877f chip"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.4-rc1/drivers/char/watchdog/wdt285.c linux-2.6.4-rc2/drivers/char/watchdog/wdt285.c --- linux-2.6.4-rc1/drivers/char/watchdog/wdt285.c 2004-02-17 19:57:20.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/wdt285.c 2004-03-03 22:48:09.000000000 -0800 @@ -222,6 +222,7 @@ MODULE_AUTHOR("Phil Blundell "); 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"); diff -urN linux-2.6.4-rc1/drivers/char/watchdog/wdt977.c linux-2.6.4-rc2/drivers/char/watchdog/wdt977.c --- linux-2.6.4-rc1/drivers/char/watchdog/wdt977.c 2004-02-17 19:59:11.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/wdt977.c 2004-03-03 22:48:09.000000000 -0800 @@ -365,5 +365,7 @@ module_init(nwwatchdog_init); module_exit(nwwatchdog_exit); +MODULE_AUTHOR("Woody Suwalski "); MODULE_DESCRIPTION("W83977AF Watchdog driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.4-rc1/drivers/char/watchdog/wdt_pci.c linux-2.6.4-rc2/drivers/char/watchdog/wdt_pci.c --- linux-2.6.4-rc1/drivers/char/watchdog/wdt_pci.c 2004-02-17 19:58:33.000000000 -0800 +++ linux-2.6.4-rc2/drivers/char/watchdog/wdt_pci.c 2004-03-03 22:48:09.000000000 -0800 @@ -653,3 +653,5 @@ 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); diff -urN linux-2.6.4-rc1/drivers/ide/arm/icside.c linux-2.6.4-rc2/drivers/ide/arm/icside.c --- linux-2.6.4-rc1/drivers/ide/arm/icside.c 2004-02-17 19:57:58.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ide/arm/icside.c 2004-03-03 22:48:09.000000000 -0800 @@ -1,13 +1,7 @@ /* * linux/drivers/ide/arm/icside.c * - * Copyright (c) 1996-2002 Russell King. - * - * Changelog: - * 08-Jun-1996 RMK Created - * 12-Sep-1997 RMK Added interrupt enable/disable - * 17-Apr-1999 RMK Added support for V6 EASI - * 22-May-1999 RMK Added support for V6 DMA + * Copyright (c) 1996-2003 Russell King. */ #include @@ -237,7 +231,7 @@ sg->length = rq->nr_sectors * SECTOR_SIZE; nents = 1; } else { - nents = blk_rq_map_sg(&drive->queue, rq, sg); + nents = blk_rq_map_sg(drive->queue, rq, sg); if (rq_data_dir(rq) == READ) hwif->sg_dma_direction = DMA_FROM_DEVICE; @@ -487,33 +481,31 @@ set_dma_sg(hwif->hw.dma, hwif->sg_table, hwif->sg_nents); set_dma_mode(hwif->hw.dma, dma_mode); + drive->waiting_for_dma = 1; + return 0; } static int icside_dma_read(ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; - task_ioreg_t cmd = WIN_NOP; + task_ioreg_t cmd; if (icside_dma_common(drive, rq, DMA_MODE_READ)) return 1; - drive->waiting_for_dma = 1; - if (drive->media != ide_disk) return 0; BUG_ON(HWGROUP(drive)->handler != NULL); - ide_set_handler(drive, icside_dmaintr, 2*WAIT_CMD, NULL); - /* * FIX ME to use only ACB ide_task_t args Struct */ #if 0 { ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; + cmd = args->tfRegister[IDE_COMMAND_OFFSET]; } #else if (rq->flags & REQ_DRIVE_TASKFILE) { @@ -526,35 +518,31 @@ } #endif /* issue cmd to drive */ - HWIF(drive)->OUTB(cmd, IDE_COMMAND_REG); + ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL); return icside_dma_begin(drive); } -int icside_dma_write(ide_drive_t *drive) +static int icside_dma_write(ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; - task_ioreg_t cmd = WIN_NOP; + task_ioreg_t cmd; if (icside_dma_common(drive, rq, DMA_MODE_WRITE)) return 1; - drive->waiting_for_dma = 1; - if (drive->media != ide_disk) return 0; BUG_ON(HWGROUP(drive)->handler != NULL); - ide_set_handler(drive, icside_dmaintr, 2*WAIT_CMD, NULL); - /* * FIX ME to use only ACB ide_task_t args Struct */ #if 0 { ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; + cmd = args->tfRegister[IDE_COMMAND_OFFSET]; } #else if (rq->flags & REQ_DRIVE_TASKFILE) { @@ -566,8 +554,9 @@ cmd = WIN_WRITEDMA; } #endif + /* issue cmd to drive */ - HWIF(drive)->OUTB(cmd, IDE_COMMAND_REG); + ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL); return icside_dma_begin(drive); } @@ -787,7 +776,7 @@ state->hwif[0] = hwif; state->hwif[1] = mate; - ec->irq_data = state; + ec->irq_data = state; ec->ops = &icside_ops_arcin_v6; hwif->maskproc = icside_maskproc; @@ -797,7 +786,7 @@ hwif->serialized = 1; hwif->config_data = slot_port; hwif->select_data = sel; - hwif->hw.dma = ec->dma; + hwif->hw.dma = ec->dma; mate->maskproc = icside_maskproc; mate->channel = 1; @@ -806,7 +795,7 @@ mate->serialized = 1; mate->config_data = slot_port; mate->select_data = sel | 1; - mate->hw.dma = ec->dma; + mate->hw.dma = ec->dma; if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) { icside_dma_init(hwif); diff -urN linux-2.6.4-rc1/drivers/ide/pci/pdc202xx_old.c linux-2.6.4-rc2/drivers/ide/pci/pdc202xx_old.c --- linux-2.6.4-rc1/drivers/ide/pci/pdc202xx_old.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ide/pci/pdc202xx_old.c 2004-03-03 22:48:09.000000000 -0800 @@ -397,37 +397,18 @@ u8 ultra_66 = ((id->dma_ultra & 0x0010) || (id->dma_ultra & 0x0008)) ? 1 : 0; - switch(dev->device) { - case PCI_DEVICE_ID_PROMISE_20267: - case PCI_DEVICE_ID_PROMISE_20265: - case PCI_DEVICE_ID_PROMISE_20263: - case PCI_DEVICE_ID_PROMISE_20262: - cable = pdc202xx_old_cable_detect(hwif); -#if PDC202_DEBUG_CABLE - printk(KERN_DEBUG "%s: %s-pin cable, %s-pin cable, %d\n", - hwif->name, hwif->udma_four ? "80" : "40", - cable ? "40" : "80", cable); -#endif /* PDC202_DEBUG_CABLE */ - break; - case PCI_DEVICE_ID_PROMISE_20246: - ultra_66 = 0; - break; - default: - BUG(); - } - - if ((ultra_66) && (cable)) { -#ifdef DEBUG - printk(KERN_DEBUG "ULTRA 66/100/133: %s channel of Ultra 66/100/133 " - "requires an 80-pin cable for Ultra66 operation.\n", - hwif->channel ? "Secondary" : "Primary"); - printk(KERN_DEBUG " Switching to Ultra33 mode.\n"); -#endif /* DEBUG */ + if (dev->device != PCI_DEVICE_ID_PROMISE_20246) + cable = pdc202xx_old_cable_detect(hwif); + else + ultra_66 = 0; + + if (ultra_66 && cable) { printk(KERN_WARNING "Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary"); printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); } - pdc_old_disable_66MHz_clock(drive->hwif); + if (dev->device != PCI_DEVICE_ID_PROMISE_20246) + pdc_old_disable_66MHz_clock(drive->hwif); drive_pci = 0x60 + (drive->dn << 2); pci_read_config_dword(dev, drive_pci, &drive_conf); diff -urN linux-2.6.4-rc1/drivers/ide/pci/pdc202xx_old.h linux-2.6.4-rc2/drivers/ide/pci/pdc202xx_old.h --- linux-2.6.4-rc1/drivers/ide/pci/pdc202xx_old.h 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ide/pci/pdc202xx_old.h 2004-03-03 22:48:09.000000000 -0800 @@ -5,8 +5,6 @@ #include #include -#define DISPLAY_PDC202XX_TIMINGS - #ifndef SPLIT_BYTE #define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) #endif @@ -171,32 +169,6 @@ #endif /* PDC202XX_DECODE_REGISTER_INFO */ -#define set_2regs(a, b) \ - do { \ - hwif->OUTB((a + adj), indexreg); \ - hwif->OUTB(b, datareg); \ - } while(0) - -#define set_ultra(a, b, c) \ - do { \ - set_2regs(0x10,(a)); \ - set_2regs(0x11,(b)); \ - set_2regs(0x12,(c)); \ - } while(0) - -#define set_ata2(a, b) \ - do { \ - set_2regs(0x0e,(a)); \ - set_2regs(0x0f,(b)); \ - } while(0) - -#define set_pio(a, b, c) \ - do { \ - set_2regs(0x0c,(a)); \ - set_2regs(0x0d,(b)); \ - set_2regs(0x13,(c)); \ - } while(0) - #define DISPLAY_PDC202XX_TIMINGS static void init_setup_pdc202ata4(struct pci_dev *dev, ide_pci_device_t *d); diff -urN linux-2.6.4-rc1/drivers/ieee1394/Kconfig linux-2.6.4-rc2/drivers/ieee1394/Kconfig --- linux-2.6.4-rc1/drivers/ieee1394/Kconfig 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/Kconfig 2004-03-03 22:48:09.000000000 -0800 @@ -47,6 +47,23 @@ 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 @@ -108,6 +125,8 @@ 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 diff -urN linux-2.6.4-rc1/drivers/ieee1394/Makefile linux-2.6.4-rc2/drivers/ieee1394/Makefile --- linux-2.6.4-rc1/drivers/ieee1394/Makefile 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/Makefile 2004-03-03 22:48:09.000000000 -0800 @@ -4,7 +4,7 @@ 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 diff -urN linux-2.6.4-rc1/drivers/ieee1394/amdtp.c linux-2.6.4-rc2/drivers/ieee1394/amdtp.c --- linux-2.6.4-rc1/drivers/ieee1394/amdtp.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/amdtp.c 2004-03-03 22:48:09.000000000 -0800 @@ -1227,15 +1227,15 @@ 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) @@ -1243,7 +1243,7 @@ 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; } diff -urN linux-2.6.4-rc1/drivers/ieee1394/config_roms.c linux-2.6.4-rc2/drivers/ieee1394/config_roms.c --- linux-2.6.4-rc1/drivers/ieee1394/config_roms.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/config_roms.c 2004-03-03 22:48:09.000000000 -0800 @@ -0,0 +1,236 @@ +/* + * 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 +#include + +#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; + } +} diff -urN linux-2.6.4-rc1/drivers/ieee1394/config_roms.h linux-2.6.4-rc2/drivers/ieee1394/config_roms.h --- linux-2.6.4-rc1/drivers/ieee1394/config_roms.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/config_roms.h 2004-03-03 22:48:09.000000000 -0800 @@ -0,0 +1,27 @@ +#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 */ diff -urN linux-2.6.4-rc1/drivers/ieee1394/csr1212.c linux-2.6.4-rc2/drivers/ieee1394/csr1212.c --- linux-2.6.4-rc1/drivers/ieee1394/csr1212.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/csr1212.c 2004-03-03 22:48:09.000000000 -0800 @@ -704,10 +704,11 @@ 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; @@ -1347,6 +1348,12 @@ 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)), diff -urN linux-2.6.4-rc1/drivers/ieee1394/dv1394.c linux-2.6.4-rc2/drivers/ieee1394/dv1394.c --- linux-2.6.4-rc1/drivers/ieee1394/dv1394.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/dv1394.c 2004-03-03 22:48:09.000000000 -0800 @@ -2222,7 +2222,7 @@ 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 @@ -2302,47 +2302,49 @@ ); 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); - - devfs_remove("ieee1394/dv/host%d/NTSC", n); - devfs_remove("ieee1394/dv/host%d/PAL", n); - devfs_remove("ieee1394/dv/host%d", n); + if (video) + dv1394_un_init(video); + } while (video != NULL); + + 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)) @@ -2350,9 +2352,9 @@ 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); @@ -2369,7 +2371,7 @@ 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 */ @@ -2381,10 +2383,10 @@ /* 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); diff -urN linux-2.6.4-rc1/drivers/ieee1394/eth1394.c linux-2.6.4-rc2/drivers/ieee1394/eth1394.c --- linux-2.6.4-rc1/drivers/ieee1394/eth1394.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/eth1394.c 2004-03-03 22:48:09.000000000 -0800 @@ -76,6 +76,7 @@ #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) @@ -88,7 +89,7 @@ #define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__) static char version[] __devinitdata = - "$Rev: 1133 $ Ben Collins "; + "$Rev: 1175 $ Ben Collins "; struct fragment_info { struct list_head list; @@ -106,8 +107,6 @@ 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 */ @@ -461,6 +460,8 @@ {} }; +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, @@ -553,9 +554,11 @@ 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, @@ -634,14 +637,6 @@ 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: @@ -668,10 +663,6 @@ 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); @@ -1483,7 +1474,6 @@ p = hpsb_alloc_packet(0); if (p) { p->host = host; - p->data = NULL; p->generation = get_hpsb_generation(host); p->type = hpsb_async; } @@ -1514,7 +1504,7 @@ | (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; @@ -1807,7 +1797,7 @@ 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))) @@ -1830,67 +1820,13 @@ 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) @@ -1898,10 +1834,6 @@ 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); diff -urN linux-2.6.4-rc1/drivers/ieee1394/eth1394.h linux-2.6.4-rc2/drivers/ieee1394/eth1394.h --- linux-2.6.4-rc1/drivers/ieee1394/eth1394.h 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/eth1394.h 2004-03-03 22:48:09.000000000 -0800 @@ -24,6 +24,8 @@ #ifndef __ETH1394_H #define __ETH1394_H +#include + #include "ieee1394.h" /* Register for incoming packets. This is 4096 bytes, which supports up to diff -urN linux-2.6.4-rc1/drivers/ieee1394/hosts.c linux-2.6.4-rc2/drivers/ieee1394/hosts.c --- linux-2.6.4-rc1/drivers/ieee1394/hosts.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/hosts.c 2004-03-03 22:48:09.000000000 -0800 @@ -27,6 +27,7 @@ #include "highlevel.h" #include "nodemgr.h" #include "csr.h" +#include "config_roms.h" static void delayed_reset_bus(unsigned long __reset_info) @@ -103,6 +104,7 @@ * 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) @@ -148,14 +150,12 @@ 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; @@ -169,12 +169,21 @@ 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) @@ -184,6 +193,8 @@ highlevel_remove_host(host); + hpsb_remove_extra_config_roms(host); + class_device_unregister(&host->class_dev); device_unregister(&host->device); } diff -urN linux-2.6.4-rc1/drivers/ieee1394/hosts.h linux-2.6.4-rc2/drivers/ieee1394/hosts.h --- linux-2.6.4-rc1/drivers/ieee1394/hosts.h 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/hosts.h 2004-03-03 22:48:09.000000000 -0800 @@ -66,6 +66,8 @@ int update_config_rom; struct timer_list delayed_reset; + unsigned int config_roms; + struct list_head addr_space; }; @@ -191,7 +193,7 @@ 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 diff -urN linux-2.6.4-rc1/drivers/ieee1394/ieee1394.h linux-2.6.4-rc2/drivers/ieee1394/ieee1394.h --- linux-2.6.4-rc1/drivers/ieee1394/ieee1394.h 2004-02-17 19:57:21.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/ieee1394.h 2004-03-03 22:48:09.000000000 -0800 @@ -36,8 +36,11 @@ #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) diff -urN linux-2.6.4-rc1/drivers/ieee1394/ieee1394_core.c linux-2.6.4-rc2/drivers/ieee1394/ieee1394_core.c --- linux-2.6.4-rc1/drivers/ieee1394/ieee1394_core.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/ieee1394_core.c 2004-03-03 22:48:09.000000000 -0800 @@ -44,6 +44,7 @@ #include "nodemgr.h" #include "dma.h" #include "iso.h" +#include "config_roms.h" /* * Disable the nodemgr detection and config rom reading functionality. @@ -92,7 +93,7 @@ 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; @@ -120,34 +121,35 @@ */ 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; } @@ -155,15 +157,14 @@ * 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); + } } @@ -402,28 +403,30 @@ 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); } @@ -492,7 +495,7 @@ */ 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; @@ -502,6 +505,15 @@ 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; @@ -658,7 +670,12 @@ 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); } @@ -1024,10 +1041,16 @@ 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"); @@ -1044,7 +1067,7 @@ 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++) @@ -1083,6 +1106,8 @@ kmem_cache_destroy(hpsb_packet_cache); + hpsb_cleanup_config_roms(); + unregister_chrdev_region(IEEE1394_CORE_DEV, 256); devfs_remove("ieee1394"); } diff -urN linux-2.6.4-rc1/drivers/ieee1394/ieee1394_core.h linux-2.6.4-rc2/drivers/ieee1394/ieee1394_core.h --- linux-2.6.4-rc1/drivers/ieee1394/ieee1394_core.h 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/ieee1394_core.h 2004-03-03 22:48:09.000000000 -0800 @@ -4,6 +4,7 @@ #include #include +#include #include #include "hosts.h" @@ -59,6 +60,8 @@ 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 *); diff -urN linux-2.6.4-rc1/drivers/ieee1394/ieee1394_transactions.c linux-2.6.4-rc2/drivers/ieee1394/ieee1394_transactions.c --- linux-2.6.4-rc1/drivers/ieee1394/ieee1394_transactions.c 2004-02-17 19:57:22.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/ieee1394_transactions.c 2004-03-03 22:48:09.000000000 -0800 @@ -239,6 +239,11 @@ 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: @@ -263,7 +268,7 @@ 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; @@ -291,7 +296,7 @@ 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; @@ -325,7 +330,7 @@ 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; diff -urN linux-2.6.4-rc1/drivers/ieee1394/nodemgr.c linux-2.6.4-rc2/drivers/ieee1394/nodemgr.c --- linux-2.6.4-rc1/drivers/ieee1394/nodemgr.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/nodemgr.c 2004-03-03 22:48:09.000000000 -0800 @@ -79,7 +79,7 @@ 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 = { @@ -1286,18 +1286,19 @@ } -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)) { @@ -1306,14 +1307,13 @@ 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; @@ -1330,8 +1330,7 @@ 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); diff -urN linux-2.6.4-rc1/drivers/ieee1394/ohci1394.c linux-2.6.4-rc2/drivers/ieee1394/ohci1394.c --- linux-2.6.4-rc1/drivers/ieee1394/ohci1394.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/ohci1394.c 2004-03-03 22:48:09.000000000 -0800 @@ -134,10 +134,10 @@ #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 @@ -158,11 +158,11 @@ 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 "; + "$Rev: 1172 $ Ben Collins "; /* Module Parameters */ static int phys_dma = 1; @@ -241,7 +241,7 @@ 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); @@ -268,7 +268,7 @@ } 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); @@ -305,7 +305,7 @@ 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); @@ -315,7 +315,7 @@ 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; @@ -337,19 +337,19 @@ } 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; } @@ -364,7 +364,7 @@ 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) @@ -374,14 +374,14 @@ /* 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; } @@ -389,7 +389,7 @@ /* 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; } @@ -451,7 +451,7 @@ /* 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 */ @@ -474,7 +474,7 @@ 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 */ @@ -486,7 +486,7 @@ 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++) { @@ -600,7 +600,7 @@ #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, @@ -635,7 +635,7 @@ 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); @@ -653,7 +653,7 @@ (((((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; @@ -709,7 +709,7 @@ 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); @@ -773,7 +773,7 @@ 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", @@ -827,19 +827,19 @@ } 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 */ @@ -856,7 +856,7 @@ 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; @@ -874,7 +874,7 @@ 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; } @@ -882,7 +882,7 @@ 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; } @@ -974,7 +974,7 @@ 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: @@ -985,7 +985,7 @@ /* * enable cycleTimer, cycleMaster */ - DBGMSG(ohci->id, "Cycle master enabled"); + DBGMSG("Cycle master enabled"); reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_CycleTimerEnable | OHCI1394_LinkControl_CycleMaster); @@ -1000,7 +1000,7 @@ 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; @@ -1010,7 +1010,7 @@ 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; @@ -1022,14 +1022,14 @@ 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<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); @@ -1055,7 +1055,7 @@ 1<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: @@ -1063,7 +1063,7 @@ 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; @@ -1074,7 +1074,7 @@ 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); @@ -1092,12 +1092,12 @@ 1<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; } @@ -1209,7 +1209,7 @@ /* 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; } @@ -1245,7 +1245,7 @@ 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; } } @@ -1289,7 +1289,7 @@ /* 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", @@ -1430,6 +1430,7 @@ 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); @@ -1508,7 +1509,7 @@ /* 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; @@ -1591,6 +1592,7 @@ { 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 */ @@ -1607,7 +1609,7 @@ /* 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; } @@ -1626,7 +1628,7 @@ 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); } @@ -1694,6 +1696,7 @@ 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++) { @@ -1716,7 +1719,7 @@ 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); } @@ -1739,7 +1742,7 @@ 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"); } } @@ -1752,6 +1755,7 @@ { int count; int wake = 0; + struct ti_ohci *ohci = recv->ohci; /* loop over the entire buffer */ for (count = 0; count < recv->nblocks; count++) { @@ -1779,9 +1783,9 @@ 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 */ @@ -1911,6 +1915,7 @@ 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); @@ -1918,7 +1923,7 @@ /* 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"); } @@ -1943,6 +1948,7 @@ { 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; @@ -1963,7 +1969,7 @@ } 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 */ @@ -1986,6 +1992,7 @@ 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; @@ -1997,7 +2004,7 @@ /* 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; @@ -2081,6 +2088,7 @@ 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); @@ -2118,7 +2126,7 @@ /* 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; } @@ -2192,8 +2200,9 @@ { 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 @@ -2217,10 +2226,10 @@ 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); } } @@ -2270,43 +2279,43 @@ * 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))); @@ -2314,7 +2323,7 @@ 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)), @@ -2328,7 +2337,7 @@ /* 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; } @@ -2359,7 +2368,7 @@ * 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; } @@ -2368,7 +2377,7 @@ } 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); @@ -2376,24 +2385,20 @@ 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, @@ -2404,7 +2409,7 @@ } 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"); @@ -2414,7 +2419,7 @@ } 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"); @@ -2443,7 +2448,7 @@ 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); @@ -2453,8 +2458,7 @@ 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")); @@ -2484,13 +2488,13 @@ 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: @@ -2500,7 +2504,7 @@ /* 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; @@ -2510,7 +2514,7 @@ 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); @@ -2519,7 +2523,7 @@ /* 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); } @@ -2606,7 +2610,7 @@ * 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"); @@ -2621,7 +2625,7 @@ /* 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; @@ -2654,7 +2658,7 @@ 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; @@ -2671,7 +2675,7 @@ 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, @@ -2688,7 +2692,7 @@ } #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 @@ -2733,8 +2737,7 @@ #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, @@ -2742,8 +2745,7 @@ 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, @@ -2752,8 +2754,7 @@ 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, @@ -2773,7 +2774,7 @@ 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: @@ -2783,7 +2784,7 @@ 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: @@ -2792,7 +2793,7 @@ 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: @@ -2803,7 +2804,7 @@ 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: @@ -2811,7 +2812,7 @@ 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(); } @@ -2855,17 +2856,18 @@ 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; inum_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); } @@ -2912,7 +2914,7 @@ 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; } @@ -2924,7 +2926,7 @@ 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; } @@ -2934,7 +2936,7 @@ 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; } @@ -2952,7 +2954,7 @@ 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; @@ -2964,7 +2966,7 @@ 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; @@ -2979,7 +2981,7 @@ 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; } @@ -3005,11 +3007,12 @@ 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; inum_desc; i++) @@ -3047,7 +3050,7 @@ 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; } @@ -3065,7 +3068,7 @@ 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; @@ -3080,7 +3083,7 @@ 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; } @@ -3157,11 +3160,6 @@ 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; @@ -3179,7 +3177,6 @@ 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; @@ -3223,7 +3220,7 @@ * 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 @@ -3239,7 +3236,7 @@ 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 = @@ -3261,7 +3258,7 @@ 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); @@ -3315,12 +3312,12 @@ /* 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 @@ -3346,38 +3343,6 @@ 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); @@ -3386,7 +3351,9 @@ 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; @@ -3582,7 +3549,7 @@ 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; } @@ -3590,7 +3557,7 @@ 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; } diff -urN linux-2.6.4-rc1/drivers/ieee1394/ohci1394.h linux-2.6.4-rc2/drivers/ieee1394/ohci1394.h --- linux-2.6.4-rc1/drivers/ieee1394/ohci1394.h 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/ohci1394.h 2004-03-03 22:48:09.000000000 -0800 @@ -149,8 +149,6 @@ }; struct ti_ohci { - int id; /* sequential card number */ - struct pci_dev *dev; enum { diff -urN linux-2.6.4-rc1/drivers/ieee1394/pcilynx.c linux-2.6.4-rc2/drivers/ieee1394/pcilynx.c --- linux-2.6.4-rc1/drivers/ieee1394/pcilynx.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/pcilynx.c 2004-03-03 22:48:09.000000000 -0800 @@ -1516,11 +1516,6 @@ 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 */ @@ -1890,42 +1885,14 @@ 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 } diff -urN linux-2.6.4-rc1/drivers/ieee1394/sbp2.c linux-2.6.4-rc2/drivers/ieee1394/sbp2.c --- linux-2.6.4-rc1/drivers/ieee1394/sbp2.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/sbp2.c 2004-03-03 22:48:09.000000000 -0800 @@ -78,7 +78,7 @@ #include "sbp2.h" static char version[] __devinitdata = - "$Rev: 1144 $ Ben Collins "; + "$Rev: 1170 $ Ben Collins "; /* * Module load parameter definitions @@ -677,6 +677,10 @@ */ 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; } @@ -2544,8 +2548,6 @@ } } - scsi_unblock_requests(scsi_id->scsi_host); - return; } diff -urN linux-2.6.4-rc1/drivers/ieee1394/video1394.c linux-2.6.4-rc2/drivers/ieee1394/video1394.c --- linux-2.6.4-rc1/drivers/ieee1394/video1394.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/ieee1394/video1394.c 2004-03-03 22:48:09.000000000 -0800 @@ -155,7 +155,7 @@ { 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) @@ -200,7 +200,7 @@ 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; } @@ -221,7 +221,7 @@ 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; } @@ -236,7 +236,7 @@ (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; @@ -246,7 +246,7 @@ 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; } @@ -264,7 +264,7 @@ 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; } @@ -277,7 +277,7 @@ 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; } @@ -293,7 +293,7 @@ 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; @@ -303,7 +303,7 @@ 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); @@ -321,7 +321,7 @@ 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; } @@ -339,22 +339,22 @@ 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; } @@ -365,7 +365,7 @@ 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); @@ -725,7 +725,7 @@ for (i=0; iISO_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; @@ -733,7 +733,7 @@ } 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; } @@ -743,26 +743,26 @@ (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; @@ -774,7 +774,7 @@ v.channel, 0); if (d == NULL) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Couldn't allocate ir context"); return -EFAULT; } @@ -785,7 +785,7 @@ 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); } @@ -795,7 +795,7 @@ 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; } @@ -808,7 +808,7 @@ 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); } @@ -829,13 +829,13 @@ 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<ISO_channel_usage & mask)) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Channel %d is not being used", channel); return -EFAULT; } @@ -849,7 +849,7 @@ 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); @@ -866,7 +866,7 @@ 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; } @@ -874,7 +874,7 @@ 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; @@ -895,7 +895,7 @@ 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, @@ -907,7 +907,7 @@ 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); } @@ -928,7 +928,7 @@ 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; } @@ -970,7 +970,7 @@ 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; @@ -1011,7 +1011,7 @@ 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; } @@ -1038,7 +1038,7 @@ 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) @@ -1075,7 +1075,7 @@ 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); @@ -1089,7 +1089,7 @@ 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); @@ -1114,7 +1114,7 @@ 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; } @@ -1140,7 +1140,7 @@ 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; } @@ -1166,7 +1166,7 @@ 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(); @@ -1186,7 +1186,7 @@ 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; } @@ -1213,11 +1213,11 @@ 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); @@ -1278,17 +1278,17 @@ 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); } @@ -1297,7 +1297,7 @@ 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; } @@ -1459,7 +1459,7 @@ 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; } diff -urN linux-2.6.4-rc1/drivers/input/serio/i8042.c linux-2.6.4-rc2/drivers/input/serio/i8042.c --- linux-2.6.4-rc1/drivers/input/serio/i8042.c 2004-02-17 19:57:15.000000000 -0800 +++ linux-2.6.4-rc2/drivers/input/serio/i8042.c 2004-03-03 22:48:09.000000000 -0800 @@ -957,7 +957,7 @@ mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); if (sysdev_class_register(&kbc_sysclass) == 0) { - if (sys_device_register(&device_i8042) == 0) + if (sysdev_register(&device_i8042) == 0) i8042_sysdev_initialized = 1; else sysdev_class_unregister(&kbc_sysclass); @@ -980,7 +980,7 @@ pm_unregister(i8042_pm_dev); if (i8042_sysdev_initialized) { - sys_device_unregister(&device_i8042); + sysdev_unregister(&device_i8042); sysdev_class_unregister(&kbc_sysclass); } diff -urN linux-2.6.4-rc1/drivers/isdn/hisax/hisax_fcpcipnp.c linux-2.6.4-rc2/drivers/isdn/hisax/hisax_fcpcipnp.c --- linux-2.6.4-rc1/drivers/isdn/hisax/hisax_fcpcipnp.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/isdn/hisax/hisax_fcpcipnp.c 2004-03-03 22:48:10.000000000 -0800 @@ -971,10 +971,10 @@ } 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 @@ -988,10 +988,10 @@ } 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) diff -urN linux-2.6.4-rc1/drivers/isdn/icn/icn.c linux-2.6.4-rc2/drivers/isdn/icn/icn.c --- linux-2.6.4-rc1/drivers/isdn/icn/icn.c 2004-02-17 19:59:56.000000000 -0800 +++ linux-2.6.4-rc2/drivers/isdn/icn/icn.c 2004-03-03 22:48:10.000000000 -0800 @@ -504,19 +504,19 @@ case 3: { char *t = status + 6; - char *s = strpbrk(t, ","); + char *s = strchr(t, ','); *s++ = '\0'; strlcpy(cmd.parm.setup.phone, t, sizeof(cmd.parm.setup.phone)); - s = strpbrk(t = s, ","); + s = strchr(t = s, ','); *s++ = '\0'; if (!strlen(t)) cmd.parm.setup.si1 = 0; else cmd.parm.setup.si1 = simple_strtoul(t, NULL, 10); - s = strpbrk(t = s, ","); + s = strchr(t = s, ','); *s++ = '\0'; if (!strlen(t)) cmd.parm.setup.si2 = 0; diff -urN linux-2.6.4-rc1/drivers/isdn/isdnloop/isdnloop.c linux-2.6.4-rc2/drivers/isdn/isdnloop/isdnloop.c --- linux-2.6.4-rc1/drivers/isdn/isdnloop/isdnloop.c 2004-02-17 19:57:11.000000000 -0800 +++ linux-2.6.4-rc2/drivers/isdn/isdnloop/isdnloop.c 2004-03-03 22:48:10.000000000 -0800 @@ -122,17 +122,17 @@ isdnloop_parse_setup(char *setup, isdn_ctrl * cmd) { char *t = setup; - char *s = strpbrk(t, ","); + char *s = strchr(t, ','); *s++ = '\0'; strlcpy(cmd->parm.setup.phone, t, sizeof(cmd->parm.setup.phone)); - s = strpbrk(t = s, ","); + s = strchr(t = s, ','); *s++ = '\0'; if (!strlen(t)) cmd->parm.setup.si1 = 0; else cmd->parm.setup.si1 = simple_strtoul(t, NULL, 10); - s = strpbrk(t = s, ","); + s = strchr(t = s, ','); *s++ = '\0'; if (!strlen(t)) cmd->parm.setup.si2 = 0; diff -urN linux-2.6.4-rc1/drivers/md/dm-crypt.c linux-2.6.4-rc2/drivers/md/dm-crypt.c --- linux-2.6.4-rc1/drivers/md/dm-crypt.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/md/dm-crypt.c 2004-03-03 22:48:10.000000000 -0800 @@ -8,15 +8,18 @@ #include #include #include +#include #include #include #include -#include #include +#include #include #include "dm.h" +#define PFX "crypt: " + /* * per bio private data */ @@ -416,7 +419,7 @@ int key_size; if (argc != 5) { - ti->error = "dm-crypt: Not enough arguments"; + ti->error = PFX "Not enough arguments"; return -EINVAL; } @@ -425,14 +428,14 @@ 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; } @@ -441,7 +444,7 @@ 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; } @@ -452,18 +455,22 @@ 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; } } @@ -471,14 +478,14 @@ 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; } @@ -486,28 +493,28 @@ 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; } @@ -586,8 +593,21 @@ 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; @@ -682,7 +702,7 @@ 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; @@ -739,13 +759,13 @@ _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; } @@ -763,7 +783,7 @@ 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); diff -urN linux-2.6.4-rc1/drivers/md/raid1.c linux-2.6.4-rc2/drivers/md/raid1.c --- linux-2.6.4-rc1/drivers/md/raid1.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/md/raid1.c 2004-03-03 22:48:10.000000000 -0800 @@ -104,8 +104,8 @@ 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; } diff -urN linux-2.6.4-rc1/drivers/media/video/c-qcam.c linux-2.6.4-rc2/drivers/media/video/c-qcam.c --- linux-2.6.4-rc1/drivers/media/video/c-qcam.c 2004-02-17 19:57:47.000000000 -0800 +++ linux-2.6.4-rc2/drivers/media/video/c-qcam.c 2004-03-03 22:48:10.000000000 -0800 @@ -818,10 +818,9 @@ } static struct parport_driver cqcam_driver = { - "cqcam", - cq_attach, - cq_detach, - NULL + .name = "cqcam", + .attach = cq_attach, + .detach = cq_detach, }; static int __init cqcam_init (void) diff -urN linux-2.6.4-rc1/drivers/media/video/cpia_pp.c linux-2.6.4-rc2/drivers/media/video/cpia_pp.c --- linux-2.6.4-rc1/drivers/media/video/cpia_pp.c 2004-02-17 19:57:12.000000000 -0800 +++ linux-2.6.4-rc2/drivers/media/video/cpia_pp.c 2004-03-03 22:48:10.000000000 -0800 @@ -803,10 +803,9 @@ } static struct parport_driver cpia_pp_driver = { - "cpia_pp", - cpia_pp_attach, - cpia_pp_detach, - NULL + .name = "cpia_pp", + .attach = cpia_pp_attach, + .detach = cpia_pp_detach, }; int cpia_pp_init(void) @@ -853,11 +852,6 @@ } } } -#if defined(CONFIG_KMOD) && defined(CONFIG_PNP_PARPORT_MODULE) - if(parport_enumerate() && !parport_enumerate()->probe_info.model) { - request_module("parport_probe"); - } -#endif return cpia_pp_init(); } diff -urN linux-2.6.4-rc1/drivers/media/video/w9966.c linux-2.6.4-rc2/drivers/media/video/w9966.c --- linux-2.6.4-rc1/drivers/media/video/w9966.c 2004-02-17 19:57:20.000000000 -0800 +++ linux-2.6.4-rc2/drivers/media/video/w9966.c 2004-03-03 22:48:10.000000000 -0800 @@ -959,10 +959,9 @@ static struct parport_driver w9966_ppd = { - W9966_DRIVERNAME, - w9966_attach, - w9966_detach, - NULL + .name = W9966_DRIVERNAME, + .attach = w9966_attach, + .detach = w9966_detach, }; // Module entry point diff -urN linux-2.6.4-rc1/drivers/media/video/zr36050.c linux-2.6.4-rc2/drivers/media/video/zr36050.c --- linux-2.6.4-rc1/drivers/media/video/zr36050.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/media/video/zr36050.c 2004-03-03 22:48:10.000000000 -0800 @@ -24,7 +24,7 @@ * ------------------------------------------------------------------------ */ -#define ZR050_VERSION "v0.7" +#define ZR050_VERSION "v0.7.1" #include #include @@ -479,7 +479,7 @@ 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); @@ -521,13 +521,13 @@ /* 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; @@ -629,17 +629,37 @@ 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; } @@ -697,6 +717,9 @@ 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 */ diff -urN linux-2.6.4-rc1/drivers/media/video/zr36050.h linux-2.6.4-rc2/drivers/media/video/zr36050.h --- linux-2.6.4-rc1/drivers/media/video/zr36050.h 2004-02-17 19:57:20.000000000 -0800 +++ linux-2.6.4-rc2/drivers/media/video/zr36050.h 2004-03-03 22:48:10.000000000 -0800 @@ -44,6 +44,7 @@ __u16 bitrate_ctrl; __u32 total_code_vol; + __u32 real_code_vol; __u16 max_block_vol; __u8 h_samp_ratio[8]; diff -urN linux-2.6.4-rc1/drivers/misc/Kconfig linux-2.6.4-rc2/drivers/misc/Kconfig --- linux-2.6.4-rc1/drivers/misc/Kconfig 2004-02-17 19:57:19.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/Kconfig 2004-03-03 22:48:10.000000000 -0800 @@ -4,5 +4,22 @@ menu "Misc devices" +config IBM_ASM + tristate "Device driver for IBM RSA service processor" + depends on X86 + default n + ---help--- + This option enables device driver support for in-band access to the + IBM RSA (Condor) service processor in eServer xSeries systems. + The ibmasm device driver allows user space application to access + ASM (Advanced Systems Management) functions on the service + processor. The driver is meant to be used in conjunction with + a user space API. + The ibmasm driver also enables the OS to use the UART on the + service processor board as a regular serial port. + + + If unsure, say N. + endmenu diff -urN linux-2.6.4-rc1/drivers/misc/Makefile linux-2.6.4-rc2/drivers/misc/Makefile --- linux-2.6.4-rc1/drivers/misc/Makefile 2004-02-17 19:59:31.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/Makefile 2004-03-03 22:48:10.000000000 -0800 @@ -2,3 +2,5 @@ # Makefile for misc devices that really don't fit anywhere else. # obj- := misc.o # Dummy rule to force built-in.o to be made + +obj-$(CONFIG_IBM_ASM) += ibmasm/ diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/Makefile linux-2.6.4-rc2/drivers/misc/ibmasm/Makefile --- linux-2.6.4-rc1/drivers/misc/ibmasm/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/Makefile 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,13 @@ + +obj-$(CONFIG_IBM_ASM) := ibmasm.o + +ibmasm-objs := module.o \ + ibmasmfs.o \ + event.o \ + command.o \ + remote.o \ + heartbeat.o \ + r_heartbeat.o \ + dot_command.o \ + lowlevel.o \ + uart.o diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/command.c linux-2.6.4-rc2/drivers/misc/ibmasm/command.c --- linux-2.6.4-rc1/drivers/misc/ibmasm/command.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/command.c 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,175 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include "ibmasm.h" + +static void exec_next_command(struct service_processor *sp); +static void free_command(struct kobject *kobj); + +static struct kobj_type ibmasm_cmd_kobj_type = { + .release = free_command, +}; + + +struct command *ibmasm_new_command(size_t buffer_size) +{ + struct command *cmd; + + if (buffer_size > IBMASM_CMD_MAX_BUFFER_SIZE) + return NULL; + + cmd = kmalloc(sizeof(struct command), GFP_KERNEL); + if (cmd == NULL) + return NULL; + + memset(cmd, 0, sizeof(*cmd)); + + cmd->buffer = kmalloc(buffer_size, GFP_KERNEL); + if (cmd->buffer == NULL) { + kfree(cmd); + return NULL; + } + memset(cmd->buffer, 0, buffer_size); + cmd->buffer_size = buffer_size; + + kobject_init(&cmd->kobj); + cmd->kobj.ktype = &ibmasm_cmd_kobj_type; + + cmd->status = IBMASM_CMD_PENDING; + init_waitqueue_head(&cmd->wait); + INIT_LIST_HEAD(&cmd->queue_node); + + return cmd; +} + +static void free_command(struct kobject *kobj) +{ + struct command *cmd = to_command(kobj); + + list_del(&cmd->queue_node); + kfree(cmd->buffer); + kfree(cmd); +} + +static void enqueue_command(struct service_processor *sp, struct command *cmd) +{ + list_add_tail(&cmd->queue_node, &sp->command_queue); +} + +static struct command *dequeue_command(struct service_processor *sp) +{ + struct command *cmd; + struct list_head *next; + + if (list_empty(&sp->command_queue)) + return NULL; + + next = sp->command_queue.next; + list_del_init(next); + cmd = list_entry(next, struct command, queue_node); + + return cmd; +} + +static inline void do_exec_command(struct service_processor *sp) +{ + if (ibmasm_send_i2o_message(sp)) { + sp->current_command->status = IBMASM_CMD_FAILED; + exec_next_command(sp); + } +} + +/** + * exec_command + * send a command to a service processor + * Commands are executed sequentially. One command (sp->current_command) + * is sent to the service processor. Once the interrupt handler gets a + * message of type command_response, the message is copied into + * the current commands buffer, + */ +void ibmasm_exec_command(struct service_processor *sp, struct command *cmd) +{ + unsigned long flags; + + spin_lock_irqsave(&sp->lock, flags); + + if (!sp->current_command) { + command_get(cmd); + sp->current_command = cmd; + spin_unlock_irqrestore(&sp->lock, flags); + + do_exec_command(sp); + } else { + enqueue_command(sp, cmd); + spin_unlock_irqrestore(&sp->lock, flags); + } +} + +static void exec_next_command(struct service_processor *sp) +{ + unsigned long flags; + + wake_up(&sp->current_command->wait); + command_put(sp->current_command); + + spin_lock_irqsave(&sp->lock, flags); + sp->current_command = dequeue_command(sp); + if (sp->current_command) { + command_get(sp->current_command); + spin_unlock_irqrestore(&sp->lock, flags); + do_exec_command(sp); + } else { + spin_unlock_irqrestore(&sp->lock, flags); + } +} + +/** + * Sleep until a command has failed or a response has been received + * and the command status been updated by the interrupt handler. + * (see receive_response). + */ +void ibmasm_wait_for_response(struct command *cmd, int timeout) +{ + wait_event_interruptible_timeout(cmd->wait, + cmd->status == IBMASM_CMD_COMPLETE || + cmd->status == IBMASM_CMD_FAILED, + timeout * HZ); +} + +/** + * receive_command_response + * called by the interrupt handler when a dot command of type command_response + * was received. + */ +void ibmasm_receive_command_response(struct service_processor *sp, void *response, size_t size) +{ + struct command *cmd = sp->current_command; + + if (!sp->current_command) + return; + + memcpy(cmd->buffer, response, min(size, cmd->buffer_size)); + cmd->status = IBMASM_CMD_COMPLETE; + exec_next_command(sp); +} diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/dot_command.c linux-2.6.4-rc2/drivers/misc/ibmasm/dot_command.c --- linux-2.6.4-rc1/drivers/misc/ibmasm/dot_command.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/dot_command.c 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,146 @@ +/* + * IBM ASM Service Processor Device Driver + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include "ibmasm.h" +#include "dot_command.h" + +/** + * Dispatch an incoming message to the specific handler for the message. + * Called from interrupt context. + */ +void ibmasm_receive_message(struct service_processor *sp, void *message, int message_size) +{ + u32 size; + struct dot_command_header *header = (struct dot_command_header *)message; + + size = get_dot_command_size(message); + if (size > message_size) + size = message_size; + + switch (header->type) { + case sp_event: + ibmasm_receive_event(sp, message, size); + break; + case sp_command_response: + ibmasm_receive_command_response(sp, message, size); + break; + case sp_heartbeat: + ibmasm_receive_heartbeat(sp, message, size); + break; + default: + dev_err(sp->dev, "Received unknown message from service processor\n"); + } +} + + +#define INIT_BUFFER_SIZE 32 + + +/** + * send the 4.3.5.10 dot command (driver VPD) to the service processor + */ +int ibmasm_send_driver_vpd(struct service_processor *sp) +{ + struct command *command; + struct dot_command_header *header; + u8 *vpd_command; + u8 *vpd_data; + int result = 0; + + command = ibmasm_new_command(INIT_BUFFER_SIZE); + if (command == NULL) + return -ENOMEM; + + header = (struct dot_command_header *)command->buffer; + header->type = sp_write; + header->command_size = 4; + header->data_size = 16; + header->status = 0; + header->reserved = 0; + + vpd_command = command->buffer + sizeof(struct dot_command_header); + vpd_command[0] = 0x4; + vpd_command[1] = 0x3; + vpd_command[2] = 0x5; + vpd_command[3] = 0xa; + + vpd_data = vpd_command + header->command_size; + vpd_data[0] = 0; + strcat(vpd_data, IBMASM_DRIVER_VPD); + vpd_data[10] = 0; + vpd_data[15] = 0; + + ibmasm_exec_command(sp, command); + ibmasm_wait_for_response(command, IBMASM_CMD_TIMEOUT_NORMAL); + + if (command->status != IBMASM_CMD_COMPLETE) + result = -ENODEV; + + command_put(command); + + return result; +} + +struct os_state_command { + struct dot_command_header header; + unsigned char command[3]; + unsigned char data; +}; + +/** + * send the 4.3.6 dot command (os state) to the service processor + * During driver init this function is called with os state "up". + * This causes the service processor to start sending heartbeats the + * driver. + * During driver exit the function is called with os state "down", + * causing the service processor to stop the heartbeats. + */ +int ibmasm_send_os_state(struct service_processor *sp, int os_state) +{ + struct command *cmd; + struct os_state_command *os_state_cmd; + int result = 0; + + cmd = ibmasm_new_command(sizeof(struct os_state_command)); + if (cmd == NULL) + return -ENOMEM; + + os_state_cmd = (struct os_state_command *)cmd->buffer; + os_state_cmd->header.type = sp_write; + os_state_cmd->header.command_size = 3; + os_state_cmd->header.data_size = 1; + os_state_cmd->header.status = 0; + os_state_cmd->command[0] = 4; + os_state_cmd->command[1] = 3; + os_state_cmd->command[2] = 6; + os_state_cmd->data = os_state; + + ibmasm_exec_command(sp, cmd); + ibmasm_wait_for_response(cmd, IBMASM_CMD_TIMEOUT_NORMAL); + + if (cmd->status != IBMASM_CMD_COMPLETE) + result = -ENODEV; + + command_put(cmd); + return result; +} diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/dot_command.h linux-2.6.4-rc2/drivers/misc/ibmasm/dot_command.h --- linux-2.6.4-rc1/drivers/misc/ibmasm/dot_command.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/dot_command.h 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,78 @@ +/* + * IBM ASM Service Processor Device Driver + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#ifndef __DOT_COMMAND_H__ +#define __DOT_COMMAND_H__ + +/* + * dot commands are the protocol used to communicate with the service + * processor. + * They consist of header, a command of variable length and data of + * variable length. + */ + +/* dot command types */ +#define sp_write 0 +#define sp_write_next 1 +#define sp_read 2 +#define sp_read_next 3 +#define sp_command_response 4 +#define sp_event 5 +#define sp_heartbeat 6 + +#pragma pack(1) +struct dot_command_header { + u8 type; + u8 command_size; + u16 data_size; + u8 status; + u8 reserved; +}; +#pragma pack() + +static inline size_t get_dot_command_size(void *buffer) +{ + struct dot_command_header *cmd = (struct dot_command_header *)buffer; + return sizeof(struct dot_command_header) + cmd->command_size + cmd->data_size; +} + +static inline unsigned int get_dot_command_timeout(void *buffer) +{ + struct dot_command_header *header = (struct dot_command_header *)buffer; + unsigned char *cmd = buffer + sizeof(struct dot_command_header); + + /* dot commands 6.3.1, 7.1 and 8.x need a longer timeout */ + + if (header->command_size == 3) { + if ((cmd[0] == 6) && (cmd[1] == 3) && (cmd[2] == 1)) + return IBMASM_CMD_TIMEOUT_EXTRA; + } else if (header->command_size == 2) { + if ((cmd[0] == 7) && (cmd[1] == 1)) + return IBMASM_CMD_TIMEOUT_EXTRA; + if (cmd[0] == 8) + return IBMASM_CMD_TIMEOUT_EXTRA; + } + return IBMASM_CMD_TIMEOUT_NORMAL; +} + +#endif /* __DOT_COMMAND_H__ */ diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/event.c linux-2.6.4-rc2/drivers/misc/ibmasm/event.c --- linux-2.6.4-rc1/drivers/misc/ibmasm/event.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/event.c 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,169 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include "ibmasm.h" + +/* + * ASM service processor event handling routines. + * + * Events are signalled to the device drivers through interrupts. + * They have the format of dot commands, with the type field set to + * sp_event. + * The driver does not interpret the events, it simply stores them in a + * circular buffer. + */ + + +static void wake_up_event_readers(struct service_processor *sp) +{ + struct event_reader *reader; + + list_for_each_entry(reader, &sp->event_buffer->readers, node) + wake_up_interruptible(&reader->wait); +} + +/** + * receive_event + * Called by the interrupt handler when a dot command of type sp_event is + * received. + * Store the event in the circular event buffer, wake up any sleeping + * event readers. + * There is no reader marker in the buffer, therefore readers are + * responsible for keeping up with the writer, or they will loose events. + */ +void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int data_size) +{ + struct event_buffer *buffer = sp->event_buffer; + struct ibmasm_event *event; + unsigned long flags; + + data_size = min(data_size, IBMASM_EVENT_MAX_SIZE); + + spin_lock_irqsave(&sp->lock, flags); + /* copy the event into the next slot in the circular buffer */ + event = &buffer->events[buffer->next_index]; + memcpy(event->data, data, data_size); + event->data_size = data_size; + event->serial_number = buffer->next_serial_number; + + /* advance indices in the buffer */ + buffer->next_index = (buffer->next_index + 1) % IBMASM_NUM_EVENTS; + buffer->next_serial_number++; + spin_unlock_irqrestore(&sp->lock, flags); + + wake_up_event_readers(sp); +} + +static inline int event_available(struct event_buffer *b, struct event_reader *r) +{ + return (r->next_serial_number < b->next_serial_number); +} + +/** + * get_next_event + * Called by event readers (initiated from user space through the file + * system). + * Sleeps until a new event is available. + */ +int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader) +{ + struct event_buffer *buffer = sp->event_buffer; + struct ibmasm_event *event; + unsigned int index; + unsigned long flags; + + if (wait_event_interruptible(reader->wait, event_available(buffer, reader))) + return -ERESTARTSYS; + + if (!event_available(buffer, reader)) + return 0; + + spin_lock_irqsave(&sp->lock, flags); + + index = buffer->next_index; + event = &buffer->events[index]; + while (event->serial_number < reader->next_serial_number) { + index = (index + 1) % IBMASM_NUM_EVENTS; + event = &buffer->events[index]; + } + memcpy(reader->data, event->data, event->data_size); + reader->data_size = event->data_size; + reader->next_serial_number = event->serial_number + 1; + + spin_unlock_irqrestore(&sp->lock, flags); + + return event->data_size; +} + +void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader) +{ + unsigned long flags; + + reader->next_serial_number = sp->event_buffer->next_serial_number; + init_waitqueue_head(&reader->wait); + spin_lock_irqsave(&sp->lock, flags); + list_add(&reader->node, &sp->event_buffer->readers); + spin_unlock_irqrestore(&sp->lock, flags); +} + +void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader) +{ + unsigned long flags; + + wake_up_interruptible(&reader->wait); + + spin_lock_irqsave(&sp->lock, flags); + list_del(&reader->node); + spin_unlock_irqrestore(&sp->lock, flags); +} + +int ibmasm_event_buffer_init(struct service_processor *sp) +{ + struct event_buffer *buffer; + struct ibmasm_event *event; + int i; + + buffer = kmalloc(sizeof(struct event_buffer), GFP_KERNEL); + if (!buffer) + return 1; + + buffer->next_index = 0; + buffer->next_serial_number = 1; + + event = buffer->events; + for (i=0; iserial_number = 0; + + INIT_LIST_HEAD(&buffer->readers); + + sp->event_buffer = buffer; + + return 0; +} + +void ibmasm_event_buffer_exit(struct service_processor *sp) +{ + wake_up_event_readers(sp); + kfree(sp->event_buffer); +} diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/heartbeat.c linux-2.6.4-rc2/drivers/misc/ibmasm/heartbeat.c --- linux-2.6.4-rc1/drivers/misc/ibmasm/heartbeat.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/heartbeat.c 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,91 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include +#include "ibmasm.h" +#include "dot_command.h" + +static int suspend_heartbeats = 0; + +/* + * Once the driver indicates to the service processor that it is running + * - see send_os_state() - the service processor sends periodic heartbeats + * to the driver. The driver must respond to the heartbeats or else the OS + * will be rebooted. + * In the case of a panic the interrupt handler continues to work and thus + * continues to respond to heartbeats, making the service processor believe + * the OS is still running and thus preventing a reboot. + * To prevent this from happening a callback is added the panic_notifier_list. + * Before responding to a heartbeat the driver checks if a panic has happened, + * if yes it suspends heartbeat, causing the service processor to reboot as + * expected. + */ +static int panic_happened(struct notifier_block *n, unsigned long val, void *v) +{ + suspend_heartbeats = 1; + return 0; +} + +static struct notifier_block panic_notifier = { panic_happened, NULL, 1 }; + +void ibmasm_register_panic_notifier(void) +{ + notifier_chain_register(&panic_notifier_list, &panic_notifier); +} + +void ibmasm_unregister_panic_notifier(void) +{ + notifier_chain_unregister(&panic_notifier_list, &panic_notifier); +} + + +int ibmasm_heartbeat_init(struct service_processor *sp) +{ + sp->heartbeat = ibmasm_new_command(HEARTBEAT_BUFFER_SIZE); + if (sp->heartbeat == NULL) + return -ENOMEM; + + return 0; +} + +void ibmasm_heartbeat_exit(struct service_processor *sp) +{ + command_put(sp->heartbeat); +} + +void ibmasm_receive_heartbeat(struct service_processor *sp, void *message, size_t size) +{ + struct command *cmd = sp->heartbeat; + struct dot_command_header *header = (struct dot_command_header *)cmd->buffer; + + if (suspend_heartbeats) + return; + + /* return the received dot command to sender */ + cmd->status = IBMASM_CMD_PENDING; + size = min(size, cmd->buffer_size); + memcpy(cmd->buffer, message, size); + header->type = sp_write; + ibmasm_exec_command(sp, cmd); +} diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/i2o.h linux-2.6.4-rc2/drivers/misc/ibmasm/i2o.h --- linux-2.6.4-rc1/drivers/misc/ibmasm/i2o.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/i2o.h 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,77 @@ +/* + * IBM ASM Service Processor Device Driver + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#pragma pack(1) +struct i2o_header { + u8 version; + u8 message_flags; + u16 message_size; + u8 target; + u8 initiator_and_target; + u8 initiator; + u8 function; + u32 initiator_context; +}; +#pragma pack() + +#define I2O_HEADER_TEMPLATE \ + { .version = 0x01, \ + .message_flags = 0x00, \ + .function = 0xFF, \ + .initiator = 0x00, \ + .initiator_and_target = 0x40, \ + .target = 0x00, \ + .initiator_context = 0x0 } + +#define I2O_MESSAGE_SIZE 0x1000 +#define I2O_COMMAND_SIZE (I2O_MESSAGE_SIZE - sizeof(struct i2o_header)) + +#pragma pack(1) +struct i2o_message { + struct i2o_header header; + void *data; +}; +#pragma pack() + +static inline unsigned short outgoing_message_size(unsigned int data_size) +{ + unsigned int size; + unsigned short i2o_size; + + if (data_size > I2O_COMMAND_SIZE) + data_size = I2O_COMMAND_SIZE; + + size = sizeof(struct i2o_header) + data_size; + + i2o_size = size / sizeof(u32); + + if (size % sizeof(u32)) + i2o_size++; + + return i2o_size; +} + +static inline u32 incoming_data_size(struct i2o_message *i2o_message) +{ + return (sizeof(u32) * i2o_message->header.message_size); +} diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/ibmasm.h linux-2.6.4-rc2/drivers/misc/ibmasm/ibmasm.h --- linux-2.6.4-rc1/drivers/misc/ibmasm/ibmasm.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/ibmasm.h 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,224 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Driver identification */ +#define DRIVER_NAME "ibmasm" +#define DRIVER_VERSION "0.4" +#define DRIVER_AUTHOR "Max Asbock" +#define DRIVER_DESC "IBM ASM Service Processor Driver" + +#define err(msg) printk(KERN_ERR "%s: " msg "\n", DRIVER_NAME) +#define info(msg) printk(KERN_INFO "%s: " msg "\n", DRIVER_NAME) + + +#define IBMASM_CMD_PENDING 0 +#define IBMASM_CMD_COMPLETE 1 +#define IBMASM_CMD_FAILED 2 + +#define IBMASM_CMD_TIMEOUT_NORMAL 45 +#define IBMASM_CMD_TIMEOUT_EXTRA 240 + +#define IBMASM_CMD_MAX_BUFFER_SIZE 0x4000 + +#define REVERSE_HEARTBEAT_TIMEOUT 120 + +#define HEARTBEAT_BUFFER_SIZE 0x400 + +#ifdef IA64 +#define IBMASM_DRIVER_VPD "Lin64 6.08 " +#else +#define IBMASM_DRIVER_VPD "Lin32 6.08 " +#endif + +#define SYSTEM_STATE_OS_UP 5 +#define SYSTEM_STATE_OS_DOWN 4 + +#define IBMASM_NAME_SIZE 16 + +#define IBMASM_NUM_EVENTS 10 +#define IBMASM_EVENT_MAX_SIZE 2048u + + +struct command { + struct list_head queue_node; + wait_queue_head_t wait; + unsigned char *buffer; + size_t buffer_size; + int status; + struct kobject kobj; +}; +#define to_command(c) container_of(c, struct command, kobj) + +static inline void command_put(struct command *cmd) +{ + kobject_put(&cmd->kobj); +} + +static inline void command_get(struct command *cmd) +{ + kobject_get(&cmd->kobj); +} + + +struct ibmasm_event { + unsigned int serial_number; + unsigned int data_size; + unsigned char data[IBMASM_EVENT_MAX_SIZE]; +}; + +struct event_buffer { + struct ibmasm_event events[IBMASM_NUM_EVENTS]; + unsigned int next_serial_number; + unsigned int next_index; + struct list_head readers; +}; + +struct event_reader { + unsigned int next_serial_number; + wait_queue_head_t wait; + struct list_head node; + unsigned int data_size; + unsigned char data[IBMASM_EVENT_MAX_SIZE]; +}; + +struct reverse_heartbeat { + wait_queue_head_t wait; + unsigned int stopped; +}; + + +/* remote console events */ +struct mouse_event { + long x; + long y; + unsigned char buttons; + unsigned char transitions; +}; + +struct keyboard_event { + unsigned long key_code; + unsigned char key_down; +}; + +struct remote_event { + unsigned long type; + union { + struct mouse_event mouse; + struct keyboard_event keyboard; + } data; +}; + +#define DRIVER_REMOTE_QUEUE_SIZE 240 + +struct remote_queue { + struct remote_event *start; + struct remote_event *end; + struct remote_event *reader; + struct remote_event *writer; + unsigned int size; + int open; + wait_queue_head_t wait; +}; + + +struct service_processor { + struct list_head node; + spinlock_t lock; + void *base_address; + unsigned int irq; + struct command *current_command; + struct command *heartbeat; + struct list_head command_queue; + struct event_buffer *event_buffer; + char dirname[IBMASM_NAME_SIZE]; + char devname[IBMASM_NAME_SIZE]; + unsigned int number; + struct remote_queue remote_queue; + int serial_line; + struct device *dev; +}; + +/* command processing */ +extern struct command *ibmasm_new_command(size_t buffer_size); +extern void ibmasm_exec_command(struct service_processor *sp, struct command *cmd); +extern void ibmasm_wait_for_response(struct command *cmd, int timeout); +extern void ibmasm_receive_command_response(struct service_processor *sp, void *response, size_t size); + +/* event processing */ +extern int ibmasm_event_buffer_init(struct service_processor *sp); +extern void ibmasm_event_buffer_exit(struct service_processor *sp); +extern void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int data_size); +extern void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader); +extern void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader); +extern int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader); + +/* heartbeat - from SP to OS */ +extern void ibmasm_register_panic_notifier(void); +extern void ibmasm_unregister_panic_notifier(void); +extern int ibmasm_heartbeat_init(struct service_processor *sp); +extern void ibmasm_heartbeat_exit(struct service_processor *sp); +extern void ibmasm_receive_heartbeat(struct service_processor *sp, void *message, size_t size); + +/* reverse heartbeat - from OS to SP */ +extern void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb); +extern int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb); +extern void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb); + +/* dot commands */ +extern void ibmasm_receive_message(struct service_processor *sp, void *data, int data_size); +extern int ibmasm_send_driver_vpd(struct service_processor *sp); +extern int ibmasm_send_os_state(struct service_processor *sp, int os_state); + +/* low level message processing */ +extern int ibmasm_send_i2o_message(struct service_processor *sp); +extern irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id, struct pt_regs *regs); + +/* remote console */ +extern void ibmasm_handle_mouse_interrupt(struct service_processor *sp); +extern int ibmasm_init_remote_queue(struct service_processor *sp); +extern void ibmasm_free_remote_queue(struct service_processor *sp); +extern void ibmasm_advance_reader(struct remote_queue *q, unsigned int n); +extern size_t ibmasm_events_available(struct remote_queue *q); + +/* file system */ +extern int ibmasmfs_register(void); +extern void ibmasmfs_unregister(void); +extern void ibmasmfs_add_sp(struct service_processor *sp); + +/* uart */ +extern void ibmasm_register_uart(struct service_processor *sp); +extern void ibmasm_unregister_uart(struct service_processor *sp); diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/ibmasmfs.c linux-2.6.4-rc2/drivers/misc/ibmasm/ibmasmfs.c --- linux-2.6.4-rc1/drivers/misc/ibmasm/ibmasmfs.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/ibmasmfs.c 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,717 @@ +/* + * IBM ASM Service Processor Device Driver + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +/* + * Parts of this code are based on an article by Jonathan Corbet + * that appeared in Linux Weekly News. + */ + + +/* + * The IBMASM file virtual filesystem. It creates the following hierarchy + * dymamically when mounted from user space: + * + * /ibmasm + * |-- 0 + * | |-- command + * | |-- event + * | |-- reverse_heartbeat + * | `-- remote_video + * | |-- connected + * | |-- depth + * | |-- events + * | |-- height + * | `-- width + * . + * . + * . + * `-- n + * |-- command + * |-- event + * |-- reverse_heartbeat + * `-- remote_video + * |-- connected + * |-- depth + * |-- events + * |-- height + * `-- width + * + * For each service processor the following files are created: + * + * command: execute dot commands + * write: execute a dot command on the service processor + * read: return the result of a previously executed dot command + * + * events: listen for service processor events + * read: sleep (interruptible) until an event occurs + * write: wakeup sleeping event listener + * + * reverse_heartbeat: send a heartbeat to the service processor + * read: sleep (interruptible) until the reverse heartbeat fails + * write: wakeup sleeping heartbeat listener + * + * remote_video/width + * remote_video/height + * remote_video/width: control remote display settings + * write: set value + * read: read value + * + * remote_video/connected + * read: return "1" if web browser VNC java applet is connected, + * "0" otherwise + * + * remote_video/events + * read: sleep until a remote mouse or keyboard event occurs, then return + * then event. + */ + +#include +#include +#include +#include +#include "ibmasm.h" +#include "remote.h" +#include "dot_command.h" + +#define IBMASMFS_MAGIC 0x66726f67 + +static LIST_HEAD(service_processors); + +static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode); +static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root); +static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent); + + +static struct super_block *ibmasmfs_get_super(struct file_system_type *fst, + int flags, const char *name, void *data) +{ + return get_sb_single(fst, flags, data, ibmasmfs_fill_super); +} + +static struct super_operations ibmasmfs_s_ops = { + .statfs = simple_statfs, + .drop_inode = generic_delete_inode, +}; + +static struct file_operations *ibmasmfs_dir_ops = &simple_dir_operations; + +static struct file_system_type ibmasmfs_type = { + .owner = THIS_MODULE, + .name = "ibmasmfs", + .get_sb = ibmasmfs_get_super, + .kill_sb = kill_litter_super, +}; + +static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent) +{ + struct inode *root; + struct dentry *root_dentry; + + sb->s_blocksize = PAGE_CACHE_SIZE; + sb->s_blocksize_bits = PAGE_CACHE_SHIFT; + sb->s_magic = IBMASMFS_MAGIC; + sb->s_op = &ibmasmfs_s_ops; + + root = ibmasmfs_make_inode (sb, S_IFDIR | 0500); + if (!root) + return -ENOMEM; + + root->i_op = &simple_dir_inode_operations; + root->i_fop = ibmasmfs_dir_ops; + + root_dentry = d_alloc_root(root); + if (!root_dentry) { + iput(root); + return -ENOMEM; + } + sb->s_root = root_dentry; + + ibmasmfs_create_files(sb, root_dentry); + return 0; +} + +static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode) +{ + struct inode *ret = new_inode(sb); + + if (ret) { + ret->i_mode = mode; + ret->i_uid = ret->i_gid = 0; + ret->i_blksize = PAGE_CACHE_SIZE; + ret->i_blocks = 0; + ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME; + } + return ret; +} + +static struct dentry *ibmasmfs_create_file (struct super_block *sb, + struct dentry *parent, + const char *name, + struct file_operations *fops, + void *data, + int mode) +{ + struct dentry *dentry; + struct inode *inode; + struct qstr qname; + + qname.name = name; + qname.len = strlen (name); + qname.hash = full_name_hash(name, qname.len); + + dentry = d_alloc(parent, &qname); + if (!dentry) + return NULL; + + inode = ibmasmfs_make_inode(sb, S_IFREG | mode); + if (!inode) { + dput(dentry); + return NULL; + } + + inode->i_fop = fops; + inode->u.generic_ip = data; + + d_add(dentry, inode); + return dentry; +} + +static struct dentry *ibmasmfs_create_dir (struct super_block *sb, + struct dentry *parent, + const char *name) +{ + struct dentry *dentry; + struct inode *inode; + struct qstr qname; + + qname.name = name; + qname.len = strlen (name); + qname.hash = full_name_hash(name, qname.len); + dentry = d_alloc(parent, &qname); + if (!dentry) + return NULL; + + inode = ibmasmfs_make_inode(sb, S_IFDIR | 0500); + if (!inode) { + dput(dentry); + return NULL; + } + + inode->i_op = &simple_dir_inode_operations; + inode->i_fop = ibmasmfs_dir_ops; + + d_add(dentry, inode); + return dentry; +} + +int ibmasmfs_register() +{ + return register_filesystem(&ibmasmfs_type); +} + +void ibmasmfs_unregister() +{ + unregister_filesystem(&ibmasmfs_type); +} + +void ibmasmfs_add_sp(struct service_processor *sp) +{ + list_add(&sp->node, &service_processors); +} + +/* struct to save state between command file operations */ +struct ibmasmfs_command_data { + struct service_processor *sp; + struct command *command; +}; + +/* struct to save state between event file operations */ +struct ibmasmfs_event_data { + struct service_processor *sp; + struct event_reader reader; + int active; +}; + +/* struct to save state between reverse heartbeat file operations */ +struct ibmasmfs_heartbeat_data { + struct service_processor *sp; + struct reverse_heartbeat heartbeat; + int active; +}; + +static int command_file_open(struct inode *inode, struct file *file) +{ + struct ibmasmfs_command_data *command_data; + + if (!inode->u.generic_ip) + return -ENODEV; + + command_data = kmalloc(sizeof(struct ibmasmfs_command_data), GFP_KERNEL); + if (!command_data) + return -ENOMEM; + + command_data->command = NULL; + command_data->sp = inode->u.generic_ip; + file->private_data = command_data; + return 0; +} + +static int command_file_close(struct inode *inode, struct file *file) +{ + struct ibmasmfs_command_data *command_data = file->private_data; + + if (command_data->command) + command_put(command_data->command); + + kfree(command_data); + return 0; +} + +static ssize_t command_file_read(struct file *file, char *buf, size_t count, loff_t *offset) +{ + struct ibmasmfs_command_data *command_data = file->private_data; + struct command *cmd; + int len; + unsigned long flags; + + if (*offset < 0) + return -EINVAL; + if (count == 0 || count > IBMASM_CMD_MAX_BUFFER_SIZE) + return 0; + if (*offset != 0) + return 0; + + spin_lock_irqsave(&command_data->sp->lock, flags); + cmd = command_data->command; + if (cmd == NULL) { + spin_unlock_irqrestore(&command_data->sp->lock, flags); + return 0; + } + command_data->command = NULL; + spin_unlock_irqrestore(&command_data->sp->lock, flags); + + if (cmd->status != IBMASM_CMD_COMPLETE) { + command_put(cmd); + return -EIO; + } + len = min(count, cmd->buffer_size); + if (copy_to_user(buf, cmd->buffer, len)) { + command_put(cmd); + return -EFAULT; + } + command_put(cmd); + + return len; +} + +static ssize_t command_file_write(struct file *file, const char *ubuff, size_t count, loff_t *offset) +{ + struct ibmasmfs_command_data *command_data = file->private_data; + struct command *cmd; + unsigned long flags; + + if (*offset < 0) + return -EINVAL; + if (count == 0 || count > IBMASM_CMD_MAX_BUFFER_SIZE) + return 0; + if (*offset != 0) + return 0; + + /* commands are executed sequentially, only one command at a time */ + if (command_data->command) + return -EAGAIN; + + cmd = ibmasm_new_command(count); + if (!cmd) + return -ENOMEM; + + if (copy_from_user((void *)cmd->buffer, (void *)ubuff, count)) { + command_put(cmd); + return -EFAULT; + } + + spin_lock_irqsave(&command_data->sp->lock, flags); + if (command_data->command) { + spin_unlock_irqrestore(&command_data->sp->lock, flags); + command_put(cmd); + return -EAGAIN; + } + command_data->command = cmd; + spin_unlock_irqrestore(&command_data->sp->lock, flags); + + ibmasm_exec_command(command_data->sp, cmd); + ibmasm_wait_for_response(cmd, get_dot_command_timeout(cmd->buffer)); + + return count; +} + +static int event_file_open(struct inode *inode, struct file *file) +{ + struct ibmasmfs_event_data *event_data; + struct service_processor *sp; + + if (!inode->u.generic_ip) + return -ENODEV; + + sp = inode->u.generic_ip; + + event_data = kmalloc(sizeof(struct ibmasmfs_event_data), GFP_KERNEL); + if (!event_data) + return -ENOMEM; + + ibmasm_event_reader_register(sp, &event_data->reader); + + event_data->sp = sp; + file->private_data = event_data; + return 0; +} + +static int event_file_close(struct inode *inode, struct file *file) +{ + struct ibmasmfs_event_data *event_data = file->private_data; + + ibmasm_event_reader_unregister(event_data->sp, &event_data->reader); + kfree(event_data); + return 0; +} + +static ssize_t event_file_read(struct file *file, char *buf, size_t count, loff_t *offset) +{ + struct ibmasmfs_event_data *event_data = file->private_data; + struct event_reader *reader = &event_data->reader; + int ret; + + if (*offset < 0) + return -EINVAL; + if (count == 0 || count > IBMASM_EVENT_MAX_SIZE) + return 0; + if (*offset != 0) + return 0; + + ret = ibmasm_get_next_event(event_data->sp, reader); + if (ret <= 0) + return ret; + + if (count < reader->data_size) + return -EINVAL; + + if (copy_to_user(buf, reader->data, reader->data_size)) + return -EFAULT; + + return reader->data_size; +} + +static ssize_t event_file_write(struct file *file, const char *buf, size_t count, loff_t *offset) +{ + struct ibmasmfs_event_data *event_data = file->private_data; + + if (*offset < 0) + return -EINVAL; + if (count != 1) + return 0; + if (*offset != 0) + return 0; + + wake_up_interruptible(&event_data->reader.wait); + return 0; +} + +static int r_heartbeat_file_open(struct inode *inode, struct file *file) +{ + struct ibmasmfs_heartbeat_data *rhbeat; + + if (!inode->u.generic_ip) + return -ENODEV; + + rhbeat = kmalloc(sizeof(struct ibmasmfs_heartbeat_data), GFP_KERNEL); + if (!rhbeat) + return -ENOMEM; + + rhbeat->sp = (struct service_processor *)inode->u.generic_ip; + rhbeat->active = 0; + ibmasm_init_reverse_heartbeat(rhbeat->sp, &rhbeat->heartbeat); + file->private_data = rhbeat; + return 0; +} + +static int r_heartbeat_file_close(struct inode *inode, struct file *file) +{ + struct ibmasmfs_heartbeat_data *rhbeat = file->private_data; + + kfree(rhbeat); + return 0; +} + +static ssize_t r_heartbeat_file_read(struct file *file, char *buf, size_t count, loff_t *offset) +{ + struct ibmasmfs_heartbeat_data *rhbeat = file->private_data; + unsigned long flags; + int result; + + if (*offset < 0) + return -EINVAL; + if (count == 0 || count > 1024) + return 0; + if (*offset != 0) + return 0; + + /* allow only one reverse heartbeat per process */ + spin_lock_irqsave(&rhbeat->sp->lock, flags); + if (rhbeat->active) { + spin_unlock_irqrestore(&rhbeat->sp->lock, flags); + return -EBUSY; + } + rhbeat->active = 1; + spin_unlock_irqrestore(&rhbeat->sp->lock, flags); + + result = ibmasm_start_reverse_heartbeat(rhbeat->sp, &rhbeat->heartbeat); + rhbeat->active = 0; + + return result; +} + +static ssize_t r_heartbeat_file_write(struct file *file, const char *buf, size_t count, loff_t *offset) +{ + struct ibmasmfs_heartbeat_data *rhbeat = file->private_data; + + if (*offset < 0) + return -EINVAL; + if (count != 1) + return 0; + if (*offset != 0) + return 0; + + if (rhbeat->active) + ibmasm_stop_reverse_heartbeat(&rhbeat->heartbeat); + + return 1; +} + +static int remote_settings_file_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->u.generic_ip; + return 0; +} + +static int remote_settings_file_close(struct inode *inode, struct file *file) +{ + return 0; +} + +static ssize_t remote_settings_file_read(struct file *file, char *buf, size_t count, loff_t *offset) +{ + unsigned long address = (unsigned long)file->private_data; + unsigned char *page; + int retval; + int len = 0; + unsigned int value; + + if (*offset < 0) + return -EINVAL; + if (count == 0 || count > 1024) + return 0; + if (*offset != 0) + return 0; + + page = (unsigned char *)__get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + value = readl(address); + len = sprintf(page, "%d\n", value); + + if (copy_to_user(buf, page, len)) { + retval = -EFAULT; + goto exit; + } + *offset += len; + retval = len; + +exit: + free_page((unsigned long)page); + return retval; +} + +static ssize_t remote_settings_file_write(struct file *file, const char *ubuff, size_t count, loff_t *offset) +{ + unsigned long address = (unsigned long)file->private_data; + char *buff; + unsigned int value; + + if (*offset < 0) + return -EINVAL; + if (count == 0 || count > 1024) + return 0; + if (*offset != 0) + return 0; + + buff = kmalloc (count + 1, GFP_KERNEL); + if (!buff) + return -ENOMEM; + + memset(buff, 0x0, count + 1); + + if (copy_from_user((void *)buff, (void *)ubuff, count)) { + kfree(buff); + return -EFAULT; + } + + value = simple_strtoul(buff, NULL, 10); + writel(value, address); + kfree(buff); + + return count; +} + +static int remote_event_file_open(struct inode *inode, struct file *file) +{ + struct service_processor *sp; + unsigned long flags; + struct remote_queue *q; + + file->private_data = inode->u.generic_ip; + sp = file->private_data; + q = &sp->remote_queue; + + /* allow only one event reader */ + spin_lock_irqsave(&sp->lock, flags); + if (q->open) { + spin_unlock_irqrestore(&sp->lock, flags); + return -EBUSY; + } + q->open = 1; + spin_unlock_irqrestore(&sp->lock, flags); + + enable_mouse_interrupts(sp); + + return 0; +} + +static int remote_event_file_close(struct inode *inode, struct file *file) +{ + struct service_processor *sp = file->private_data; + + disable_mouse_interrupts(sp); + wake_up_interruptible(&sp->remote_queue.wait); + sp->remote_queue.open = 0; + + return 0; +} + +static ssize_t remote_event_file_read(struct file *file, char *buf, size_t count, loff_t *offset) +{ + struct service_processor *sp = file->private_data; + struct remote_queue *q = &sp->remote_queue; + size_t data_size; + struct remote_event *reader = q->reader; + size_t num_events; + + if (*offset < 0) + return -EINVAL; + if (count == 0 || count > 1024) + return 0; + if (*offset != 0) + return 0; + + if (wait_event_interruptible(q->wait, q->reader != q->writer)) + return -ERESTARTSYS; + + /* only get multiples of struct remote_event */ + num_events = min((count/sizeof(struct remote_event)), ibmasm_events_available(q)); + if (!num_events) + return 0; + + data_size = num_events * sizeof(struct remote_event); + + if (copy_to_user(buf, reader, data_size)) + return -EFAULT; + + ibmasm_advance_reader(q, num_events); + + return data_size; +} + + +static struct file_operations command_fops = { + .open = command_file_open, + .release = command_file_close, + .read = command_file_read, + .write = command_file_write, +}; + +static struct file_operations event_fops = { + .open = event_file_open, + .release = event_file_close, + .read = event_file_read, + .write event_file_write, +}; + +static struct file_operations r_heartbeat_fops = { + .open = r_heartbeat_file_open, + .release = r_heartbeat_file_close, + .read = r_heartbeat_file_read, + .write = r_heartbeat_file_write, +}; + +static struct file_operations remote_settings_fops = { + .open = remote_settings_file_open, + .release = remote_settings_file_close, + .read = remote_settings_file_read, + .write = remote_settings_file_write, +}; + +static struct file_operations remote_event_fops = { + .open = remote_event_file_open, + .release = remote_event_file_close, + .read = remote_event_file_read, +}; + + +static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root) +{ + struct list_head *entry; + struct service_processor *sp; + + list_for_each(entry, &service_processors) { + struct dentry *dir; + struct dentry *remote_dir; + sp = list_entry(entry, struct service_processor, node); + dir = ibmasmfs_create_dir(sb, root, sp->dirname); + if (!dir) + continue; + + ibmasmfs_create_file(sb, dir, "command", &command_fops, sp, S_IRUSR|S_IWUSR); + ibmasmfs_create_file(sb, dir, "event", &event_fops, sp, S_IRUSR|S_IWUSR); + ibmasmfs_create_file(sb, dir, "reverse_heartbeat", &r_heartbeat_fops, sp, S_IRUSR|S_IWUSR); + + remote_dir = ibmasmfs_create_dir(sb, dir, "remote_video"); + if (!remote_dir) + continue; + + ibmasmfs_create_file(sb, remote_dir, "width", &remote_settings_fops, (void *)display_width(sp), S_IRUSR|S_IWUSR); + ibmasmfs_create_file(sb, remote_dir, "height", &remote_settings_fops, (void *)display_height(sp), S_IRUSR|S_IWUSR); + ibmasmfs_create_file(sb, remote_dir, "depth", &remote_settings_fops, (void *)display_depth(sp), S_IRUSR|S_IWUSR); + ibmasmfs_create_file(sb, remote_dir, "connected", &remote_settings_fops, (void *)vnc_status(sp), S_IRUSR); + ibmasmfs_create_file(sb, remote_dir, "events", &remote_event_fops, (void *)sp, S_IRUSR); + } +} diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/lowlevel.c linux-2.6.4-rc2/drivers/misc/ibmasm/lowlevel.c --- linux-2.6.4-rc1/drivers/misc/ibmasm/lowlevel.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/lowlevel.c 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,81 @@ +/* + * IBM ASM Service Processor Device Driver + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include "ibmasm.h" +#include "lowlevel.h" +#include "i2o.h" +#include "dot_command.h" +#include "remote.h" + +static struct i2o_header header = I2O_HEADER_TEMPLATE; + + +int ibmasm_send_i2o_message(struct service_processor *sp) +{ + u32 mfa; + unsigned int command_size; + struct i2o_message *message; + struct command *command = sp->current_command; + + mfa = get_mfa_inbound(sp->base_address); + if (!mfa) + return 1; + + command_size = get_dot_command_size(command->buffer); + header.message_size = outgoing_message_size(command_size); + + message = get_i2o_message(sp->base_address, mfa); + + memcpy(&message->header, &header, sizeof(struct i2o_header)); + memcpy(&message->data, command->buffer, command_size); + + set_mfa_inbound(sp->base_address, mfa); + + return 0; +} + +irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id, struct pt_regs *regs) +{ + u32 mfa; + struct service_processor *sp = (struct service_processor *)dev_id; + void *base_address = sp->base_address; + + if (!sp_interrupt_pending(base_address)) + return IRQ_NONE; + + if (mouse_interrupt_pending(sp)) { + ibmasm_handle_mouse_interrupt(sp); + mfa = get_mfa_outbound(base_address); + clear_mouse_interrupt(sp); + set_mfa_outbound(base_address, mfa); + return IRQ_HANDLED; + } + + mfa = get_mfa_outbound(base_address); + if (valid_mfa(mfa)) { + struct i2o_message *msg = get_i2o_message(base_address, mfa); + ibmasm_receive_message(sp, &msg->data, incoming_data_size(msg)); + } + set_mfa_outbound(base_address, mfa); + return IRQ_HANDLED; +} diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/lowlevel.h linux-2.6.4-rc2/drivers/misc/ibmasm/lowlevel.h --- linux-2.6.4-rc1/drivers/misc/ibmasm/lowlevel.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/lowlevel.h 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,137 @@ +/* + * IBM ASM Service Processor Device Driver + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +/* Condor service processor specific hardware definitions */ + +#ifndef __IBMASM_CONDOR_H__ +#define __IBMASM_CONDOR_H__ + +#include + +#define VENDORID_IBM 0x1014 +#define DEVICEID_RSA 0x010F + +#define GET_MFA_ADDR(x) (x & 0xFFFFFF00) + +#define MAILBOX_FULL(x) (x & 0x00000001) + +#define NO_MFAS_AVAILABLE 0xFFFFFFFF + + +#define INBOUND_QUEUE_PORT 0x40 /* contains address of next free MFA */ +#define OUTBOUND_QUEUE_PORT 0x44 /* contains address of posted MFA */ + +#define SP_INTR_MASK 0x00000008 +#define UART_INTR_MASK 0x00000010 + +#define INTR_STATUS_REGISTER 0x13A0 +#define INTR_CONTROL_REGISTER 0x13A4 + +#define SCOUT_COM_A_BASE 0x0000 +#define SCOUT_COM_B_BASE 0x0100 +#define SCOUT_COM_C_BASE 0x0200 +#define SCOUT_COM_D_BASE 0x0300 + +static inline int sp_interrupt_pending(void *base_address) +{ + return SP_INTR_MASK & readl(base_address + INTR_STATUS_REGISTER); +} + +static inline int uart_interrupt_pending(void *base_address) +{ + return UART_INTR_MASK & readl(base_address + INTR_STATUS_REGISTER); +} + +static inline void ibmasm_enable_interrupts(void *base_address, int mask) +{ + void *ctrl_reg = base_address + INTR_CONTROL_REGISTER; + writel( readl(ctrl_reg) & ~mask, ctrl_reg); +} + +static inline void ibmasm_disable_interrupts(void *base_address, int mask) +{ + void *ctrl_reg = base_address + INTR_CONTROL_REGISTER; + writel( readl(ctrl_reg) | mask, ctrl_reg); +} + +static inline void enable_sp_interrupts(void *base_address) +{ + ibmasm_enable_interrupts(base_address, SP_INTR_MASK); +} + +static inline void disable_sp_interrupts(void *base_address) +{ + ibmasm_disable_interrupts(base_address, SP_INTR_MASK); +} + +static inline void enable_uart_interrupts(void *base_address) +{ + ibmasm_enable_interrupts(base_address, UART_INTR_MASK); +} + +static inline void disable_uart_interrupts(void *base_address) +{ + ibmasm_disable_interrupts(base_address, UART_INTR_MASK); +} + +#define valid_mfa(mfa) ( (mfa) != NO_MFAS_AVAILABLE ) + +static inline u32 get_mfa_outbound(void *base_address) +{ + int retry; + u32 mfa; + + for (retry=0; retry<=10; retry++) { + mfa = readl(base_address + OUTBOUND_QUEUE_PORT); + if (valid_mfa(mfa)) + break; + } + return mfa; +} + +static inline void set_mfa_outbound(void *base_address, u32 mfa) +{ + writel(mfa, base_address + OUTBOUND_QUEUE_PORT); +} + +static inline u32 get_mfa_inbound(void *base_address) +{ + u32 mfa = readl(base_address + INBOUND_QUEUE_PORT); + + if (MAILBOX_FULL(mfa)) + return 0; + + return mfa; +} + +static inline void set_mfa_inbound(void *base_address, u32 mfa) +{ + writel(mfa, base_address + INBOUND_QUEUE_PORT); +} + +static inline struct i2o_message *get_i2o_message(void *base_address, u32 mfa) +{ + return (struct i2o_message *)(GET_MFA_ADDR(mfa) + base_address); +} + +#endif /* __IBMASM_CONDOR_H__ */ diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/module.c linux-2.6.4-rc2/drivers/misc/ibmasm/module.c --- linux-2.6.4-rc1/drivers/misc/ibmasm/module.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/module.c 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,210 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + * This driver is based on code originally written by Pete Reynolds + * and others. + * + */ + +/* + * The ASM device driver does the following things: + * + * 1) When loaded it sends a message to the service processor, + * indicating that an OS is * running. This causes the service processor + * to send periodic heartbeats to the OS. + * + * 2) Answers the periodic heartbeats sent by the service processor. + * Failure to do so would result in system reboot. + * + * 3) Acts as a pass through for dot commands sent from user applications. + * The interface for this is the ibmasmfs file system. + * + * 4) Allows user applications to register for event notification. Events + * are sent to the driver through interrupts. They can be read from user + * space through the ibmasmfs file system. + * + * 5) Allows user space applications to send heartbeats to the service + * processor (aka reverse heartbeats). Again this happens through ibmasmfs. + * + * 6) Handles remote mouse and keyboard event interrupts and makes them + * available to user applications through ibmasmfs. + * + */ + +#include +#include +#include "ibmasm.h" +#include "lowlevel.h" +#include "remote.h" + + +static int __init ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int result = -ENOMEM; + struct service_processor *sp; + + sp = kmalloc(sizeof(struct service_processor), GFP_KERNEL); + if (sp == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory\n"); + return result; + } + memset(sp, 0, sizeof(struct service_processor)); + + pci_set_drvdata(pdev, (void *)sp); + sp->dev = &pdev->dev; + sp->number = pdev->bus->number; + snprintf(sp->dirname, IBMASM_NAME_SIZE, "%d", sp->number); + snprintf(sp->devname, IBMASM_NAME_SIZE, "%s%d", DRIVER_NAME, sp->number); + + if (ibmasm_event_buffer_init(sp)) { + dev_err(sp->dev, "Failed to allocate event buffer\n"); + goto error_eventbuffer; + } + + if (ibmasm_heartbeat_init(sp)) { + dev_err(sp->dev, "Failed to allocate heartbeat command\n"); + goto error_heartbeat; + } + + sp->irq = pdev->irq; + sp->base_address = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + if (sp->base_address == 0) { + dev_err(sp->dev, "Failed to ioremap pci memory\n"); + result = -ENODEV; + goto error_ioremap; + } + + result = ibmasm_init_remote_queue(sp); + if (result) { + dev_err(sp->dev, "Failed to initialize remote queue\n"); + goto error_remote_queue; + } + + sp->lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&sp->command_queue); + + result = request_irq(sp->irq, ibmasm_interrupt_handler, SA_SHIRQ, sp->devname, (void*)sp); + if (result) { + dev_err(sp->dev, "Failed to register interrupt handler\n"); + goto error_request_irq; + } + + enable_sp_interrupts(sp->base_address); + disable_mouse_interrupts(sp); + + result = ibmasm_send_driver_vpd(sp); + if (result) { + dev_err(sp->dev, "Failed to send driver VPD to service processor\n"); + goto error_send_message; + } + result = ibmasm_send_os_state(sp, SYSTEM_STATE_OS_UP); + if (result) { + dev_err(sp->dev, "Failed to send OS state to service processor\n"); + goto error_send_message; + } + ibmasmfs_add_sp(sp); + + ibmasm_register_uart(sp); + + return 0; + +error_send_message: + disable_sp_interrupts(sp->base_address); + free_irq(sp->irq, (void *)sp); +error_request_irq: + ibmasm_free_remote_queue(sp); +error_remote_queue: + iounmap(sp->base_address); +error_ioremap: + ibmasm_heartbeat_exit(sp); +error_heartbeat: + ibmasm_event_buffer_exit(sp); +error_eventbuffer: + kfree(sp); + + return result; +} + +static void __exit ibmasm_remove_one(struct pci_dev *pdev) +{ + struct service_processor *sp = (struct service_processor *)pci_get_drvdata(pdev); + + ibmasm_unregister_uart(sp); + ibmasm_send_os_state(sp, SYSTEM_STATE_OS_DOWN); + disable_sp_interrupts(sp->base_address); + disable_mouse_interrupts(sp); + free_irq(sp->irq, (void *)sp); + ibmasm_heartbeat_exit(sp); + ibmasm_free_remote_queue(sp); + iounmap(sp->base_address); + ibmasm_event_buffer_exit(sp); + kfree(sp); +} + +static struct pci_device_id ibmasm_pci_table[] = +{ + { PCI_DEVICE(VENDORID_IBM, DEVICEID_RSA) }, + {}, +}; + +static struct pci_driver ibmasm_driver = { + .name = DRIVER_NAME, + .id_table = ibmasm_pci_table, + .probe = ibmasm_init_one, + .remove = __devexit_p(ibmasm_remove_one), +}; + +static void __exit ibmasm_exit (void) +{ + ibmasm_unregister_panic_notifier(); + ibmasmfs_unregister(); + pci_unregister_driver(&ibmasm_driver); + info(DRIVER_DESC " version " DRIVER_VERSION " unloaded"); +} + +static int __init ibmasm_init(void) +{ + int result; + + result = ibmasmfs_register(); + if (result) { + err("Failed to register ibmasmfs file system"); + return result; + } + result = pci_register_driver(&ibmasm_driver); + if (result <= 0) { + pci_unregister_driver(&ibmasm_driver); + ibmasmfs_unregister(); + return -ENODEV; + } + ibmasm_register_panic_notifier(); + info(DRIVER_DESC " version " DRIVER_VERSION " loaded"); + return 0; +} + +module_init(ibmasm_init); +module_exit(ibmasm_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/r_heartbeat.c linux-2.6.4-rc2/drivers/misc/ibmasm/r_heartbeat.c --- linux-2.6.4-rc1/drivers/misc/ibmasm/r_heartbeat.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/r_heartbeat.c 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,98 @@ + +/* + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include "ibmasm.h" +#include "dot_command.h" + +/* + * Reverse Heartbeat, i.e. heartbeats sent from the driver to the + * service processor. + * These heartbeats are initiated by user level programs. + */ + +/* the reverse heartbeat dot command */ +#pragma pack(1) +static struct { + struct dot_command_header header; + unsigned char command[3]; +} rhb_dot_cmd = { + .header = { + .type = sp_read, + .command_size = 3, + .data_size = 0, + .status = 0 + }, + .command = { 4, 3, 6 } +}; +#pragma pack() + +void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb) +{ + init_waitqueue_head(&rhb->wait); + rhb->stopped = 0; +} + +/** + * start_reverse_heartbeat + * Loop forever, sending a reverse heartbeat dot command to the service + * processor, then sleeping. The loop comes to an end if the service + * processor fails to respond 3 times or we were interrupted. + */ +int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb) +{ + struct command *cmd; + int times_failed = 0; + int result = 1; + + cmd = ibmasm_new_command(sizeof rhb_dot_cmd); + if (!cmd) + return -ENOMEM; + + while (times_failed < 3) { + memcpy(cmd->buffer, (void *)&rhb_dot_cmd, sizeof rhb_dot_cmd); + cmd->status = IBMASM_CMD_PENDING; + ibmasm_exec_command(sp, cmd); + ibmasm_wait_for_response(cmd, IBMASM_CMD_TIMEOUT_NORMAL); + + if (cmd->status != IBMASM_CMD_COMPLETE) + times_failed++; + + wait_event_interruptible_timeout(rhb->wait, + rhb->stopped, + REVERSE_HEARTBEAT_TIMEOUT * HZ); + + if (signal_pending(current) || rhb->stopped) { + result = -EINTR; + break; + } + } + command_put(cmd); + rhb->stopped = 0; + + return result; +} + +void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb) +{ + rhb->stopped = 1; + wake_up_interruptible(&rhb->wait); +} diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/remote.c linux-2.6.4-rc2/drivers/misc/ibmasm/remote.c --- linux-2.6.4-rc1/drivers/misc/ibmasm/remote.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/remote.c 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,152 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +/* Remote mouse and keyboard event handling functions */ + +#include "ibmasm.h" +#include "remote.h" + +int ibmasm_init_remote_queue(struct service_processor *sp) +{ + struct remote_queue *q = &sp->remote_queue; + + disable_mouse_interrupts(sp); + + q->open = 0; + q->size = 0; + + q->start = kmalloc(DRIVER_REMOTE_QUEUE_SIZE * sizeof(struct remote_event), GFP_KERNEL); + if (q->start == 0) + return -ENOMEM; + + q->end = q->start + DRIVER_REMOTE_QUEUE_SIZE; + q->reader = q->start; + q->writer = q->start; + q->size = DRIVER_REMOTE_QUEUE_SIZE; + init_waitqueue_head(&q->wait); + + return 0; +} + +void ibmasm_free_remote_queue(struct service_processor *sp) +{ + kfree(sp->remote_queue.start); +} + +void ibmasm_advance_reader(struct remote_queue *q, unsigned int n) +{ + q->reader += n; + if (q->reader >= q->end) + q->reader -= q->size; +} + +size_t ibmasm_events_available(struct remote_queue *q) +{ + ssize_t diff = q->writer - q->reader; + + return (diff >= 0) ? diff : q->end - q->reader; +} + + +static int space_free(struct remote_queue *q) +{ + if (q->reader == q->writer) + return q->size - 1; + + return ( (q->reader + q->size - q->writer) % q->size ) - 1; +} + +static void set_mouse_event(struct remote_input *input, struct mouse_event *mouse) +{ + static char last_buttons = 0; + + mouse->x = input->data.mouse.x; + mouse->y = input->data.mouse.y; + + if (input->mouse_buttons == REMOTE_MOUSE_DOUBLE_CLICK) { + mouse->buttons = REMOTE_MOUSE_DOUBLE_CLICK; + last_buttons = 0; + return; + } + mouse->transitions = last_buttons ^ input->mouse_buttons; + mouse->buttons = input->mouse_buttons; + + last_buttons = input->mouse_buttons; +} + +static void set_keyboard_event(struct remote_input *input, struct keyboard_event *keyboard) +{ + keyboard->key_code = input->data.keyboard.key_code; + keyboard->key_down = input->data.keyboard.key_down; +} + +static int add_to_driver_queue(struct remote_queue *q, struct remote_input *input) +{ + struct remote_event *event = q->writer; + + if (space_free(q) < 1) { + return 1; + } + + switch(input->type) { + case (INPUT_TYPE_MOUSE): + event->type = INPUT_TYPE_MOUSE; + set_mouse_event(input, &event->data.mouse); + break; + case (INPUT_TYPE_KEYBOARD): + event->type = INPUT_TYPE_KEYBOARD; + set_keyboard_event(input, &event->data.keyboard); + break; + default: + return 0; + } + event->type = input->type; + + q->writer++; + if (q->writer == q->end) + q->writer = q->start; + + return 0; +} + + +void ibmasm_handle_mouse_interrupt(struct service_processor *sp) +{ + unsigned long reader; + unsigned long writer; + struct remote_input input; + + reader = get_queue_reader(sp); + writer = get_queue_writer(sp); + + while (reader != writer) { + memcpy(&input, (void *)get_queue_entry(sp, reader), sizeof(struct remote_input)); + + if (add_to_driver_queue(&sp->remote_queue, &input)) + break; + + reader = advance_queue_reader(sp, reader); + } + wake_up_interruptible(&sp->remote_queue.wait); +} diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/remote.h linux-2.6.4-rc2/drivers/misc/ibmasm/remote.h --- linux-2.6.4-rc1/drivers/misc/ibmasm/remote.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/remote.h 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,119 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + * Orignally written by Pete Reynolds + */ + +#ifndef _IBMASM_REMOTE_H_ +#define _IBMASM_REMOTE_H_ + +#include + +/* pci offsets */ +#define CONDOR_MOUSE_DATA 0x000AC000 +#define CONDOR_MOUSE_ISR_CONTROL 0x00 +#define CONDOR_MOUSE_ISR_STATUS 0x04 +#define CONDOR_MOUSE_Q_READER 0x08 +#define CONDOR_MOUSE_Q_WRITER 0x0C +#define CONDOR_MOUSE_Q_BEGIN 0x10 +#define CONDOR_MOUSE_MAX_X 0x14 +#define CONDOR_MOUSE_MAX_Y 0x18 + +#define CONDOR_INPUT_DESKTOP_INFO 0x1F0 +#define CONDOR_INPUT_DISPLAY_RESX 0x1F4 +#define CONDOR_INPUT_DISPLAY_RESY 0x1F8 +#define CONDOR_INPUT_DISPLAY_BITS 0x1FC +#define CONDOR_OUTPUT_VNC_STATUS 0x200 + +#define CONDOR_MOUSE_INTR_STATUS_MASK 0x00000001 + +#define INPUT_TYPE_MOUSE 0x1 +#define INPUT_TYPE_KEYBOARD 0x2 + + +/* mouse button states received from SP */ +#define REMOTE_MOUSE_DOUBLE_CLICK 0xF0 +#define REMOTE_MOUSE_BUTTON_LEFT 0x01 +#define REMOTE_MOUSE_BUTTON_MIDDLE 0x02 +#define REMOTE_MOUSE_BUTTON_RIGHT 0x04 + + +struct mouse_input { + unsigned short y; + unsigned short x; +}; + + +struct keyboard_input { + unsigned short key_code; + unsigned char key_flag; + unsigned char key_down; +}; + + + +struct remote_input { + union { + struct mouse_input mouse; + struct keyboard_input keyboard; + } data; + + unsigned char type; + unsigned char pad1; + unsigned char mouse_buttons; + unsigned char pad3; +}; + +#define mouse_addr(sp) sp->base_address + CONDOR_MOUSE_DATA +#define display_width(sp) mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESX +#define display_height(sp) mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESY +#define display_depth(sp) mouse_addr(sp) + CONDOR_INPUT_DISPLAY_BITS +#define vnc_status(sp) mouse_addr(sp) + CONDOR_OUTPUT_VNC_STATUS + +#define mouse_interrupt_pending(sp) readl(mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS) +#define clear_mouse_interrupt(sp) writel(0, mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS) +#define enable_mouse_interrupts(sp) writel(1, mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL) +#define disable_mouse_interrupts(sp) writel(0, mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL) + +/* remote input queue operations */ +#define REMOTE_QUEUE_SIZE 60 + +#define get_queue_writer(sp) readl(mouse_addr(sp) + CONDOR_MOUSE_Q_WRITER) +#define get_queue_reader(sp) readl(mouse_addr(sp) + CONDOR_MOUSE_Q_READER) +#define set_queue_reader(sp, reader) writel(reader, mouse_addr(sp) + CONDOR_MOUSE_Q_READER) + +#define queue_begin mouse_addr(sp) + CONDOR_MOUSE_Q_BEGIN + +#define get_queue_entry(sp, read_index) \ + queue_begin + read_index * sizeof(struct remote_input) + +static inline int advance_queue_reader(struct service_processor *sp, unsigned long reader) +{ + reader++; + if (reader == REMOTE_QUEUE_SIZE) + reader = 0; + + set_queue_reader(sp, reader); + return reader; +} + +#endif /* _IBMASM_REMOTE_H_ */ diff -urN linux-2.6.4-rc1/drivers/misc/ibmasm/uart.c linux-2.6.4-rc2/drivers/misc/ibmasm/uart.c --- linux-2.6.4-rc1/drivers/misc/ibmasm/uart.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/misc/ibmasm/uart.c 2004-03-03 22:48:10.000000000 -0800 @@ -0,0 +1,72 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include +#include +#include +#include +#include +#include "ibmasm.h" +#include "lowlevel.h" + + +void ibmasm_register_uart(struct service_processor *sp) +{ + struct serial_struct serial; + unsigned char *iomem_base; + + iomem_base = sp->base_address + SCOUT_COM_B_BASE; + + /* read the uart scratch register to determine if the UART + * is dedicated to the service processor or if the OS can use it + */ + if (0 == readl(iomem_base + UART_SCR)) { + dev_info(sp->dev, "IBM SP UART not registered, owned by service processor\n"); + sp->serial_line = -1; + return; + } + + memset(&serial, 0, sizeof(serial)); + serial.irq = sp->irq; + serial.baud_base = 3686400 / 16; + serial.flags = UPF_AUTOPROBE | UPF_SHARE_IRQ; + serial.io_type = UPIO_MEM; + serial.iomem_base = iomem_base; + + sp->serial_line = register_serial(&serial); + if (sp->serial_line < 0) { + dev_err(sp->dev, "Failed to register serial port\n"); + return; + } + enable_uart_interrupts(sp->base_address); +} + +void ibmasm_unregister_uart(struct service_processor *sp) +{ + if (sp->serial_line < 0) + return; + + disable_uart_interrupts(sp->base_address); + unregister_serial(sp->serial_line); +} diff -urN linux-2.6.4-rc1/drivers/mtd/afs.c linux-2.6.4-rc2/drivers/mtd/afs.c --- linux-2.6.4-rc1/drivers/mtd/afs.c 2004-02-17 19:59:28.000000000 -0800 +++ linux-2.6.4-rc2/drivers/mtd/afs.c 2004-03-03 22:48:10.000000000 -0800 @@ -57,6 +57,17 @@ u32 checksum; /* Image checksum (inc. this struct) */ }; +static u32 word_sum(void *words, int num) +{ + u32 *p = words; + u32 sum = 0; + + while (num--) + sum += *p++; + + return sum; +} + static int afs_read_footer(struct mtd_info *mtd, u_int *img_start, u_int *iis_start, u_int off, u_int mask) @@ -85,6 +96,12 @@ ret = 0; /* + * Check the checksum. + */ + if (word_sum(&fs, sizeof(fs) / sizeof(u32)) != 0xffffffff) + ret = 0; + + /* * Don't touch the SIB. */ if (fs.type == 2) @@ -114,16 +131,35 @@ afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr) { size_t sz; - int ret; + int ret, i; memset(iis, 0, sizeof(*iis)); ret = mtd->read(mtd, ptr, sizeof(*iis), &sz, (u_char *) iis); - if (ret >= 0 && sz != sizeof(*iis)) - ret = -EINVAL; if (ret < 0) - printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", - ptr, ret); + goto failed; + + if (sz != sizeof(*iis)) { + ret = -EINVAL; + goto failed; + } + + ret = 0; + + /* + * Validate the name - it must be NUL terminated. + */ + for (i = 0; i < sizeof(iis->name); i++) + if (iis->name[i] == '\0') + break; + if (i < sizeof(iis->name)) + ret = 1; + + return ret; + + failed: + printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", + ptr, ret); return ret; } @@ -160,6 +196,8 @@ ret = afs_read_iis(mtd, &iis, iis_ptr); if (ret < 0) break; + if (ret == 0) + continue; sz += sizeof(struct mtd_partition); sz += strlen(iis.name) + 1; @@ -194,6 +232,8 @@ ret = afs_read_iis(mtd, &iis, iis_ptr); if (ret < 0) break; + if (ret == 0) + continue; strcpy(str, iis.name); size = mtd->erasesize + off - img_ptr; diff -urN linux-2.6.4-rc1/drivers/mtd/maps/integrator-flash.c linux-2.6.4-rc2/drivers/mtd/maps/integrator-flash.c --- linux-2.6.4-rc1/drivers/mtd/maps/integrator-flash.c 2004-02-17 19:59:07.000000000 -0800 +++ linux-2.6.4-rc2/drivers/mtd/maps/integrator-flash.c 2004-03-03 22:48:10.000000000 -0800 @@ -1,8 +1,9 @@ /*====================================================================== - drivers/mtd/maps/armflash.c: ARM Flash Layout/Partitioning + drivers/mtd/maps/integrator-flash.c: ARM Integrator flash map driver Copyright (C) 2000 ARM Limited + Copyright (C) 2003 Deep Blue Solutions Ltd. 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 @@ -21,7 +22,7 @@ This is access code for flashes using ARM's flash partitioning standards. - $Id: integrator-flash.c,v 1.12 2003/05/20 20:59:30 dwmw2 Exp $ + $Id: integrator-flash.c,v 1.15 2004/02/27 22:37:39 rmk Exp $ ======================================================================*/ @@ -64,7 +65,7 @@ info->plat->set_vpp(on); } -static const char *probes[] = { "RedBoot", "afs", NULL }; +static const char *probes[] = { "cmdlinepart", "RedBoot", "afs", NULL }; static int armflash_probe(struct device *_dev) { diff -urN linux-2.6.4-rc1/drivers/mtd/maps/lubbock-flash.c linux-2.6.4-rc2/drivers/mtd/maps/lubbock-flash.c --- linux-2.6.4-rc1/drivers/mtd/maps/lubbock-flash.c 2004-02-17 19:58:43.000000000 -0800 +++ linux-2.6.4-rc2/drivers/mtd/maps/lubbock-flash.c 2004-03-03 22:48:10.000000000 -0800 @@ -74,7 +74,7 @@ lubbock_maps[flashboot].name = "Lubbock Boot ROM"; for (i = 0; i < 2; i++) { - lubbock_maps[i].virt = (unsigned long)__ioremap(lubbock_maps[i].phys, WINDOW_SIZE, 0); + lubbock_maps[i].virt = (unsigned long)ioremap(lubbock_maps[i].phys, WINDOW_SIZE); if (!lubbock_maps[i].virt) { printk(KERN_WARNING "Failed to ioremap %s\n", lubbock_maps[i].name); if (!ret) @@ -97,8 +97,8 @@ } mymtds[i]->owner = THIS_MODULE; - int ret = parse_mtd_partitions(mymtds[i], probes, - &parsed_parts[i], 0); + ret = parse_mtd_partitions(mymtds[i], probes, + &parsed_parts[i], 0); if (ret > 0) nr_parsed_parts[i] = ret; diff -urN linux-2.6.4-rc1/drivers/net/Kconfig linux-2.6.4-rc2/drivers/net/Kconfig --- linux-2.6.4-rc1/drivers/net/Kconfig 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/net/Kconfig 2004-03-03 22:48:10.000000000 -0800 @@ -1676,25 +1676,23 @@ select CRC32 select MII help - If you have a VIA "rhine" based network card (Rhine-I (3043), - Rhine-2 (VT86c100A) or Rhine-III (VT6105)), say Y here. + If you have a VIA "Rhine" based network card (Rhine-I (VT86C100A), + Rhine-II (VT6102), or Rhine-III (VT6105)), say Y here. Rhine-type + Ethernet functions can also be found integrated on South Bridges + (e.g. VT8235). - To compile this driver as a module, choose M here and read - . The module + To compile this driver as a module, choose M here. The module will be called via-rhine. config VIA_RHINE_MMIO - bool "Use MMIO instead of PIO (EXPERIMENTAL)" - depends on VIA_RHINE && EXPERIMENTAL + bool "Use MMIO instead of PIO" + depends on VIA_RHINE help This instructs the driver to use PCI shared memory (MMIO) instead of programmed I/O ports (PIO). Enabling this gives an improvement in processing time in parts of the driver. - It is not known if this works reliably on all "rhine" based cards, - but it has been tested successfully on some DFE-530TX adapters. - - If unsure, say N. + If unsure, say Y. config LAN_SAA9730 bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)" diff -urN linux-2.6.4-rc1/drivers/net/hp100.c linux-2.6.4-rc2/drivers/net/hp100.c --- linux-2.6.4-rc1/drivers/net/hp100.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/net/hp100.c 2004-03-03 22:48:10.000000000 -0800 @@ -201,6 +201,7 @@ { "HWP1990" }, /* HP J2577 */ { "CPX0301" }, /* ReadyLink ENET100-VG4 */ { "CPX0401" }, /* FreedomLine 100/VG */ + { "" } /* Mandatory final entry ! */ }; MODULE_DEVICE_TABLE(eisa, hp100_eisa_tbl); #endif @@ -326,16 +327,21 @@ return str; } -static __init int hp100_isa_probe1(struct net_device *dev, int addr) +static __init int hp100_isa_probe1(struct net_device *dev, int ioaddr) { const char *sig; int i; - if (!request_region(addr, HP100_REGION_SIZE, "hp100")) + if (!request_region(ioaddr, HP100_REGION_SIZE, "hp100")) goto err; - sig = hp100_read_id(addr); - release_region(addr, HP100_REGION_SIZE); + if (hp100_inw(HW_ID) != HP100_HW_ID_CASCADE) { + release_region(ioaddr, HP100_REGION_SIZE); + goto err; + } + + sig = hp100_read_id(ioaddr); + release_region(ioaddr, HP100_REGION_SIZE); if (sig == NULL) goto err; @@ -347,7 +353,7 @@ } if (i < ARRAY_SIZE(hp100_isa_tbl)) - return hp100_probe1(dev, addr, HP100_BUS_ISA, NULL); + return hp100_probe1(dev, ioaddr, HP100_BUS_ISA, NULL); err: return -ENODEV; diff -urN linux-2.6.4-rc1/drivers/net/hydra.c linux-2.6.4-rc2/drivers/net/hydra.c --- linux-2.6.4-rc1/drivers/net/hydra.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/net/hydra.c 2004-03-03 22:48:10.000000000 -0800 @@ -142,10 +142,6 @@ ei_status.reg_offset = hydra_offsets; dev->open = &hydra_open; dev->stop = &hydra_close; -#ifdef MODULE - ei_status.priv = (unsigned long)root_hydra_dev; - root_hydra_dev = dev; -#endif NS8390_init(dev, 0); err = register_netdev(dev); diff -urN linux-2.6.4-rc1/drivers/net/ibmveth.c linux-2.6.4-rc2/drivers/net/ibmveth.c --- linux-2.6.4-rc1/drivers/net/ibmveth.c 2004-03-03 22:48:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/net/ibmveth.c 2004-03-03 22:48:10.000000000 -0800 @@ -52,7 +52,7 @@ #include #include #include -#include +#include #include #include #include @@ -66,16 +66,16 @@ printk(KERN_INFO "%s: " fmt, __FILE__, ## args) #define ibmveth_error_printk(fmt, args...) \ - printk(KERN_ERR "(%s:%3.3d ua:%lx) ERROR: " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args) + printk(KERN_ERR "(%s:%3.3d ua:%x) ERROR: " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args) #ifdef DEBUG #define ibmveth_debug_printk_no_adapter(fmt, args...) \ printk(KERN_DEBUG "(%s:%3.3d): " fmt, __FILE__, __LINE__ , ## args) #define ibmveth_debug_printk(fmt, args...) \ - printk(KERN_DEBUG "(%s:%3.3d ua:%lx): " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args) + printk(KERN_DEBUG "(%s:%3.3d ua:%x): " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args) #define ibmveth_assert(expr) \ if(!(expr)) { \ - printk(KERN_DEBUG "assertion failed (%s:%3.3d ua:%lx): %s\n", __FILE__, __LINE__, adapter->vdev->unit_address, #expr); \ + printk(KERN_DEBUG "assertion failed (%s:%3.3d ua:%x): %s\n", __FILE__, __LINE__, adapter->vdev->unit_address, #expr); \ BUG(); \ } #else @@ -869,7 +869,7 @@ unsigned int *mcastFilterSize_p; - ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%lx\n", + ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%x\n", dev->unit_address); mac_addr_p = (unsigned int *) vio_get_attribute(dev, VETH_MAC_ADDR, 0); @@ -913,7 +913,7 @@ adapter->mac_addr = 0; memcpy(&adapter->mac_addr, mac_addr_p, 6); - adapter->liobn = dev->tce_table->index; + adapter->liobn = dev->iommu_table->it_index; netdev->irq = dev->irq; netdev->open = ibmveth_open; @@ -1014,7 +1014,7 @@ seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version); - seq_printf(seq, "Unit Address: 0x%lx\n", adapter->vdev->unit_address); + seq_printf(seq, "Unit Address: 0x%x\n", adapter->vdev->unit_address); seq_printf(seq, "LIOBN: 0x%lx\n", adapter->liobn); seq_printf(seq, "Current MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", current_mac[0], current_mac[1], current_mac[2], diff -urN linux-2.6.4-rc1/drivers/net/r8169.c linux-2.6.4-rc2/drivers/net/r8169.c --- linux-2.6.4-rc1/drivers/net/r8169.c 2004-02-17 19:58:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/net/r8169.c 2004-03-03 22:48:10.000000000 -0800 @@ -871,7 +871,6 @@ void *ioaddr) { unsigned long dirty_tx, tx_left = 0; - int entry = tp->cur_tx % NUM_TX_DESC; assert(dev != NULL); assert(tp != NULL); @@ -881,14 +880,18 @@ tx_left = tp->cur_tx - dirty_tx; while (tx_left > 0) { + int entry = dirty_tx % NUM_TX_DESC; + if ((tp->TxDescArray[entry].status & OWNbit) == 0) { - dev_kfree_skb_irq(tp-> - Tx_skbuff[dirty_tx % NUM_TX_DESC]); - tp->Tx_skbuff[dirty_tx % NUM_TX_DESC] = NULL; + struct sk_buff *skb = tp->Tx_skbuff[entry]; + + tp->stats.tx_bytes += skb->len >= ETH_ZLEN ? + skb->len : ETH_ZLEN; tp->stats.tx_packets++; + dev_kfree_skb_irq(skb); + tp->Tx_skbuff[entry] = NULL; dirty_tx++; tx_left--; - entry++; } } diff -urN linux-2.6.4-rc1/drivers/net/wireless/airo_cs.c linux-2.6.4-rc2/drivers/net/wireless/airo_cs.c --- linux-2.6.4-rc1/drivers/net/wireless/airo_cs.c 2004-02-17 19:59:14.000000000 -0800 +++ linux-2.6.4-rc2/drivers/net/wireless/airo_cs.c 2004-03-03 22:48:11.000000000 -0800 @@ -264,11 +264,8 @@ if (*linkp == NULL) return; - if (link->state & DEV_CONFIG) { + if (link->state & DEV_CONFIG) airo_release(link); - if (link->state & DEV_STALE_CONFIG) - return; - } if ( ((local_info_t*)link->priv)->eth_dev ) { stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 ); @@ -504,18 +501,6 @@ { DEBUG(0, "airo_release(0x%p)\n", link); - /* - If the device is currently in use, we won't release until it - is actually closed, because until then, we can't be sure that - no one will try to access the device or its data structures. - */ - if (link->open) { - DEBUG(1, "airo_cs: release postponed, '%s' still open\n", - link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - return; - } - /* Unlink the device chain */ link->dev = NULL; @@ -533,9 +518,6 @@ if (link->irq.AssignedIRQ) pcmcia_release_irq(link->handle, &link->irq); link->state &= ~DEV_CONFIG; - - if (link->state & DEV_STALE_CONFIG) - airo_detach(link); } /*====================================================================== diff -urN linux-2.6.4-rc1/drivers/net/wireless/netwave_cs.c linux-2.6.4-rc2/drivers/net/wireless/netwave_cs.c --- linux-2.6.4-rc1/drivers/net/wireless/netwave_cs.c 2004-02-17 19:59:45.000000000 -0800 +++ linux-2.6.4-rc2/drivers/net/wireless/netwave_cs.c 2004-03-03 22:48:11.000000000 -0800 @@ -544,14 +544,8 @@ the release() function is called, that will trigger a proper detach(). */ - if (link->state & DEV_CONFIG) { + if (link->state & DEV_CONFIG) netwave_release(link); - if (link->state & DEV_STALE_CONFIG) { - DEBUG(1, "netwave_cs: detach postponed, '%s' still " - "locked\n", link->dev->dev_name); - return; - } - } /* Break the link with Card Services */ if (link->handle) @@ -1130,17 +1124,6 @@ DEBUG(0, "netwave_release(0x%p)\n", link); - /* - If the device is currently in use, we won't release until it - is actually closed. - */ - if (link->open) { - printk(KERN_DEBUG "netwave_cs: release postponed, '%s' still open\n", - link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - return; - } - /* Don't bother checking to see if these succeed or not */ if (link->win) { iounmap(priv->ramBase); @@ -1151,9 +1134,6 @@ pcmcia_release_irq(link->handle, &link->irq); link->state &= ~DEV_CONFIG; - - if (link->state & DEV_STALE_CONFIG) - netwave_detach(link); } /* @@ -1703,8 +1683,7 @@ link->open--; netif_stop_queue(dev); - if (link->state & DEV_STALE_CONFIG) - netwave_release(link); + return 0; } diff -urN linux-2.6.4-rc1/drivers/net/wireless/ray_cs.c linux-2.6.4-rc2/drivers/net/wireless/ray_cs.c --- linux-2.6.4-rc1/drivers/net/wireless/ray_cs.c 2004-02-17 19:57:29.000000000 -0800 +++ linux-2.6.4-rc2/drivers/net/wireless/ray_cs.c 2004-03-03 22:48:11.000000000 -0800 @@ -454,11 +454,8 @@ the release() function is called, that will trigger a proper detach(). */ - if (link->state & DEV_CONFIG) { + if (link->state & DEV_CONFIG) ray_release(link); - if(link->state & DEV_STALE_CONFIG) - return; - } /* Break the link with Card Services */ if (link->handle) @@ -872,15 +869,7 @@ int i; DEBUG(1, "ray_release(0x%p)\n", link); - /* If the device is currently in use, we won't release until it - is actually closed. - */ - if (link->open) { - DEBUG(1, "ray_cs: release postponed, '%s' still open\n", - link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - return; - } + del_timer(&local->timer); link->state &= ~DEV_CONFIG; @@ -900,9 +889,6 @@ if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseIRQ ret = %x\n",i); DEBUG(2,"ray_release ending\n"); - - if (link->state & DEV_STALE_CONFIG) - ray_detach(link); } /*============================================================================= @@ -1724,8 +1710,6 @@ link->open--; netif_stop_queue(dev); - if (link->state & DEV_STALE_CONFIG) - ray_release(link); /* In here, we should stop the hardware (stop card from beeing active) * and set local->card_status to CARD_AWAITING_PARAM, so that while the diff -urN linux-2.6.4-rc1/drivers/net/wireless/wavelan_cs.c linux-2.6.4-rc2/drivers/net/wireless/wavelan_cs.c --- linux-2.6.4-rc1/drivers/net/wireless/wavelan_cs.c 2004-02-17 19:58:14.000000000 -0800 +++ linux-2.6.4-rc2/drivers/net/wireless/wavelan_cs.c 2004-03-03 22:48:11.000000000 -0800 @@ -4155,18 +4155,6 @@ printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link); #endif - /* If the device is currently in use, we won't release until it is - * actually closed. */ - if(link->open) - { -#ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG "%s: wv_pcmcia_release: release postponed, device still open\n", - dev->name); -#endif - link->state |= DEV_STALE_CONFIG; - return; - } - /* Don't bother checking to see if these succeed or not */ iounmap((u_char *)dev->mem_start); pcmcia_release_window(link->win); @@ -4179,9 +4167,6 @@ #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name); #endif - - if (link->state & DEV_STALE_CONFIG) - wavelan_detach(link); } /************************ INTERRUPT HANDLING ************************/ @@ -4634,10 +4619,6 @@ /* Power down the module */ hacr_write(base, HACR_DEFAULT & (~HACR_PWR_STAT)); } - else - /* The card is no more there (flag is activated in wv_pcmcia_release) */ - if(link->state & DEV_STALE_CONFIG) - wv_pcmcia_release(link); #ifdef DEBUG_CALLBACK_TRACE printk(KERN_DEBUG "%s: <-wavelan_close()\n", dev->name); @@ -4802,14 +4783,6 @@ { /* Some others haven't done their job : give them another chance */ wv_pcmcia_release(link); - if(link->state & DEV_STALE_CONFIG) - { -#ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG "wavelan_detach: detach postponed," - " '%s' still locked\n", link->dev->dev_name); -#endif - return; - } } /* Break the link with Card Services */ diff -urN linux-2.6.4-rc1/drivers/net/wireless/wl3501_cs.c linux-2.6.4-rc2/drivers/net/wireless/wl3501_cs.c --- linux-2.6.4-rc1/drivers/net/wireless/wl3501_cs.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/net/wireless/wl3501_cs.c 2004-03-03 22:48:11.000000000 -0800 @@ -1306,10 +1306,6 @@ /* Mask interrupts from the SUTRO */ wl3501_block_interrupt(this); - if (link->state & DEV_STALE_CONFIG) { - link->state |= DEV_RELEASE_PENDING; - wl3501_release(link); - } rc = 0; printk(KERN_INFO "%s: WL3501 closed\n", dev->name); out: @@ -2220,15 +2216,6 @@ { struct net_device *dev = link->priv; - /* If the device is currently in use, we won't release until it is - * actually closed. */ - if (link->open) { - dprintk(1, "release postponed, '%s' still open", - link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - goto out; - } - /* Unlink the device chain */ if (link->dev) { unregister_netdev(dev); @@ -2240,11 +2227,6 @@ pcmcia_release_io(link->handle, &link->io); pcmcia_release_irq(link->handle, &link->irq); link->state &= ~DEV_CONFIG; - - if (link->state & DEV_STALE_CONFIG) - wl3501_detach(link); -out: - return; } /** diff -urN linux-2.6.4-rc1/drivers/parport/Makefile linux-2.6.4-rc2/drivers/parport/Makefile --- linux-2.6.4-rc1/drivers/parport/Makefile 2004-02-17 19:57:12.000000000 -0800 +++ linux-2.6.4-rc2/drivers/parport/Makefile 2004-03-03 22:48:11.000000000 -0800 @@ -2,7 +2,7 @@ # Makefile for the kernel Parallel port device drivers. # -parport-objs := share.o ieee1284.o ieee1284_ops.o init.o procfs.o +parport-objs := share.o ieee1284.o ieee1284_ops.o procfs.o ifeq ($(CONFIG_PARPORT_1284),y) parport-objs += daisy.o probe.o diff -urN linux-2.6.4-rc1/drivers/parport/daisy.c linux-2.6.4-rc2/drivers/parport/daisy.c --- linux-2.6.4-rc1/drivers/parport/daisy.c 2004-02-17 19:57:21.000000000 -0800 +++ linux-2.6.4-rc2/drivers/parport/daisy.c 2004-03-03 22:48:11.000000000 -0800 @@ -19,6 +19,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include @@ -79,6 +80,7 @@ extra->portnum = real->portnum; extra->physport = real; extra->muxport = muxport; + real->slaves[muxport-1] = extra; } return extra; @@ -93,7 +95,9 @@ static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" }; int num_ports; int i; + int last_try = 0; +again: /* Because this is called before any other devices exist, * we don't have to claim exclusive access. */ @@ -126,7 +130,7 @@ /* Analyse that port too. We won't recurse forever because of the 'port->muxport < 0' test above. */ - parport_announce_port (extra); + parport_daisy_init(extra); } } @@ -148,6 +152,21 @@ kfree (deviceid); } + if (!detected && !last_try) { + /* No devices were detected. Perhaps they are in some + funny state; let's try to reset them and see if + they wake up. */ + parport_daisy_fini (port); + parport_write_control (port, PARPORT_CONTROL_SELECT); + udelay (50); + parport_write_control (port, + PARPORT_CONTROL_SELECT | + PARPORT_CONTROL_INIT); + udelay (50); + last_try = 1; + goto again; + } + return detected; } @@ -634,3 +653,13 @@ spin_unlock(&topology_lock); return res; } + +EXPORT_SYMBOL(parport_open); +EXPORT_SYMBOL(parport_close); +EXPORT_SYMBOL(parport_device_num); +EXPORT_SYMBOL(parport_device_coords); +EXPORT_SYMBOL(parport_daisy_deselect_all); +EXPORT_SYMBOL(parport_daisy_select); +EXPORT_SYMBOL(parport_daisy_init); +EXPORT_SYMBOL(parport_find_device); +EXPORT_SYMBOL(parport_find_class); diff -urN linux-2.6.4-rc1/drivers/parport/ieee1284.c linux-2.6.4-rc2/drivers/parport/ieee1284.c --- linux-2.6.4-rc1/drivers/parport/ieee1284.c 2004-02-17 19:57:15.000000000 -0800 +++ linux-2.6.4-rc2/drivers/parport/ieee1284.c 2004-03-03 22:48:11.000000000 -0800 @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -806,3 +807,15 @@ return old; } + +/* Exported symbols for modules. */ + +EXPORT_SYMBOL(parport_negotiate); +EXPORT_SYMBOL(parport_write); +EXPORT_SYMBOL(parport_read); +EXPORT_SYMBOL(parport_ieee1284_wakeup); +EXPORT_SYMBOL(parport_wait_peripheral); +EXPORT_SYMBOL(parport_poll_peripheral); +EXPORT_SYMBOL(parport_wait_event); +EXPORT_SYMBOL(parport_set_timeout); +EXPORT_SYMBOL(parport_ieee1284_interrupt); diff -urN linux-2.6.4-rc1/drivers/parport/ieee1284_ops.c linux-2.6.4-rc2/drivers/parport/ieee1284_ops.c --- linux-2.6.4-rc1/drivers/parport/ieee1284_ops.c 2004-02-17 19:59:45.000000000 -0800 +++ linux-2.6.4-rc2/drivers/parport/ieee1284_ops.c 2004-03-03 22:48:11.000000000 -0800 @@ -15,6 +15,7 @@ #include +#include #include #include #include @@ -908,4 +909,13 @@ return ret; } - +EXPORT_SYMBOL(parport_ieee1284_ecp_write_data); +EXPORT_SYMBOL(parport_ieee1284_ecp_read_data); +EXPORT_SYMBOL(parport_ieee1284_ecp_write_addr); +EXPORT_SYMBOL(parport_ieee1284_write_compat); +EXPORT_SYMBOL(parport_ieee1284_read_nibble); +EXPORT_SYMBOL(parport_ieee1284_read_byte); +EXPORT_SYMBOL(parport_ieee1284_epp_write_data); +EXPORT_SYMBOL(parport_ieee1284_epp_read_data); +EXPORT_SYMBOL(parport_ieee1284_epp_write_addr); +EXPORT_SYMBOL(parport_ieee1284_epp_read_addr); diff -urN linux-2.6.4-rc1/drivers/parport/init.c linux-2.6.4-rc2/drivers/parport/init.c --- linux-2.6.4-rc1/drivers/parport/init.c 2004-02-17 19:58:21.000000000 -0800 +++ linux-2.6.4-rc2/drivers/parport/init.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,229 +0,0 @@ -/* Parallel-port initialisation code. - * - * Authors: David Campbell - * Tim Waugh - * Jose Renau - * - * based on work by Grant Guenther - * and Philip Blundell - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef MODULE -static int io[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 }; -#ifdef CONFIG_PARPORT_PC -static int io_hi[PARPORT_MAX+1] __initdata = - { [0 ... PARPORT_MAX] = PARPORT_IOHI_AUTO }; -#endif -static int irq[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_IRQ_PROBEONLY }; -static int dma[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_DMA_NONE }; - -extern int parport_pc_init(int *io, int *io_hi, int *irq, int *dma); -extern int parport_sunbpp_init(void); -extern int parport_amiga_init(void); -extern int parport_mfc3_init(void); -extern int parport_atari_init(void); - -static int parport_setup_ptr __initdata = 0; - -/* - * Acceptable parameters: - * - * parport=0 - * parport=auto - * parport=0xBASE[,IRQ[,DMA]] - * - * IRQ/DMA may be numeric or 'auto' or 'none' - */ -static int __init parport_setup (char *str) -{ - char *endptr; - char *sep; - int val; - - if (!str || !*str || (*str == '0' && !*(str+1))) { - /* Disable parport if "parport=0" in cmdline */ - io[0] = PARPORT_DISABLE; - return 1; - } - - if (!strncmp (str, "auto", 4)) { - irq[0] = PARPORT_IRQ_AUTO; - dma[0] = PARPORT_DMA_AUTO; - return 1; - } - - val = simple_strtoul (str, &endptr, 0); - if (endptr == str) { - printk (KERN_WARNING "parport=%s not understood\n", str); - return 1; - } - - if (parport_setup_ptr == PARPORT_MAX) { - printk(KERN_ERR "parport=%s ignored, too many ports\n", str); - return 1; - } - - io[parport_setup_ptr] = val; - irq[parport_setup_ptr] = PARPORT_IRQ_NONE; - dma[parport_setup_ptr] = PARPORT_DMA_NONE; - - sep = strchr (str, ','); - if (sep++) { - if (!strncmp (sep, "auto", 4)) - irq[parport_setup_ptr] = PARPORT_IRQ_AUTO; - else if (strncmp (sep, "none", 4)) { - val = simple_strtoul (sep, &endptr, 0); - if (endptr == sep) { - printk (KERN_WARNING - "parport=%s: irq not understood\n", - str); - return 1; - } - irq[parport_setup_ptr] = val; - } - } - - sep = strchr (sep, ','); - if (sep++) { - if (!strncmp (sep, "auto", 4)) - dma[parport_setup_ptr] = PARPORT_DMA_AUTO; - else if (!strncmp (sep, "nofifo", 6)) - dma[parport_setup_ptr] = PARPORT_DMA_NOFIFO; - else if (strncmp (sep, "none", 4)) { - val = simple_strtoul (sep, &endptr, 0); - if (endptr == sep) { - printk (KERN_WARNING - "parport=%s: dma not understood\n", - str); - return 1; - } - dma[parport_setup_ptr] = val; - } - } - - parport_setup_ptr++; - return 1; -} - -__setup ("parport=", parport_setup); - -#endif - -#ifdef MODULE -int init_module(void) -{ -#ifdef CONFIG_SYSCTL - parport_default_proc_register (); -#endif - return 0; -} - -void cleanup_module(void) -{ -#ifdef CONFIG_SYSCTL - parport_default_proc_unregister (); -#endif -} - -#else - -int __init parport_init (void) -{ - if (io[0] == PARPORT_DISABLE) - return 1; - -#ifdef CONFIG_SYSCTL - parport_default_proc_register (); -#endif - -#ifdef CONFIG_PARPORT_PC - parport_pc_init(io, io_hi, irq, dma); -#endif -#ifdef CONFIG_PARPORT_AMIGA - parport_amiga_init(); -#endif -#ifdef CONFIG_PARPORT_MFC3 - parport_mfc3_init(); -#endif -#ifdef CONFIG_PARPORT_ATARI - parport_atari_init(); -#endif -#ifdef CONFIG_PARPORT_ARC - parport_arc_init(); -#endif -#ifdef CONFIG_PARPORT_SUNBPP - parport_sunbpp_init(); -#endif - return 0; -} - -__initcall(parport_init); - -#endif - -/* Exported symbols for modules. */ - -EXPORT_SYMBOL(parport_claim); -EXPORT_SYMBOL(parport_claim_or_block); -EXPORT_SYMBOL(parport_release); -EXPORT_SYMBOL(parport_register_port); -EXPORT_SYMBOL(parport_announce_port); -EXPORT_SYMBOL(parport_unregister_port); -EXPORT_SYMBOL(parport_register_driver); -EXPORT_SYMBOL(parport_unregister_driver); -EXPORT_SYMBOL(parport_register_device); -EXPORT_SYMBOL(parport_unregister_device); -EXPORT_SYMBOL(parport_enumerate); -EXPORT_SYMBOL(parport_get_port); -EXPORT_SYMBOL(parport_put_port); -EXPORT_SYMBOL(parport_find_number); -EXPORT_SYMBOL(parport_find_base); -EXPORT_SYMBOL(parport_negotiate); -EXPORT_SYMBOL(parport_write); -EXPORT_SYMBOL(parport_read); -EXPORT_SYMBOL(parport_ieee1284_wakeup); -EXPORT_SYMBOL(parport_wait_peripheral); -EXPORT_SYMBOL(parport_poll_peripheral); -EXPORT_SYMBOL(parport_wait_event); -EXPORT_SYMBOL(parport_set_timeout); -EXPORT_SYMBOL(parport_ieee1284_interrupt); -EXPORT_SYMBOL(parport_ieee1284_ecp_write_data); -EXPORT_SYMBOL(parport_ieee1284_ecp_read_data); -EXPORT_SYMBOL(parport_ieee1284_ecp_write_addr); -EXPORT_SYMBOL(parport_ieee1284_write_compat); -EXPORT_SYMBOL(parport_ieee1284_read_nibble); -EXPORT_SYMBOL(parport_ieee1284_read_byte); -EXPORT_SYMBOL(parport_ieee1284_epp_write_data); -EXPORT_SYMBOL(parport_ieee1284_epp_read_data); -EXPORT_SYMBOL(parport_ieee1284_epp_write_addr); -EXPORT_SYMBOL(parport_ieee1284_epp_read_addr); -EXPORT_SYMBOL(parport_proc_register); -EXPORT_SYMBOL(parport_proc_unregister); -EXPORT_SYMBOL(parport_device_proc_register); -EXPORT_SYMBOL(parport_device_proc_unregister); -EXPORT_SYMBOL(parport_default_proc_register); -EXPORT_SYMBOL(parport_default_proc_unregister); -EXPORT_SYMBOL(parport_parse_irqs); -EXPORT_SYMBOL(parport_parse_dmas); -#ifdef CONFIG_PARPORT_1284 -EXPORT_SYMBOL(parport_open); -EXPORT_SYMBOL(parport_close); -EXPORT_SYMBOL(parport_device_id); -EXPORT_SYMBOL(parport_device_num); -EXPORT_SYMBOL(parport_device_coords); -EXPORT_SYMBOL(parport_daisy_deselect_all); -EXPORT_SYMBOL(parport_daisy_select); -EXPORT_SYMBOL(parport_daisy_init); -EXPORT_SYMBOL(parport_find_device); -EXPORT_SYMBOL(parport_find_class); -#endif diff -urN linux-2.6.4-rc1/drivers/parport/parport_amiga.c linux-2.6.4-rc2/drivers/parport/parport_amiga.c --- linux-2.6.4-rc1/drivers/parport/parport_amiga.c 2004-02-17 19:58:51.000000000 -0800 +++ linux-2.6.4-rc2/drivers/parport/parport_amiga.c 2004-03-03 22:48:11.000000000 -0800 @@ -234,7 +234,7 @@ /* ----------- Initialisation code --------------------------------- */ -int __init parport_amiga_init(void) +static int __init parport_amiga_init(void) { struct parport *p; int err; @@ -262,26 +262,24 @@ this_port = p; printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name); /* XXX: set operating mode */ - parport_proc_register(p); - parport_announce_port(p); return 0; out_irq: - parport_unregister_port(p); + parport_put_port(p); out_port: release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100); out_mem: return err; } -void __exit parport_amiga_exit(void) +static void __exit parport_amiga_exit(void) { + parport_remove_port(this_port); if (this_port->irq != PARPORT_IRQ_NONE) free_irq(IRQ_AMIGA_CIAA_FLG, this_port); - parport_proc_unregister(this_port); - parport_unregister_port(this_port); + parport_put_port(this_port); release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100); } diff -urN linux-2.6.4-rc1/drivers/parport/parport_arc.c linux-2.6.4-rc2/drivers/parport/parport_arc.c --- linux-2.6.4-rc1/drivers/parport/parport_arc.c 2004-02-17 19:57:11.000000000 -0800 +++ linux-2.6.4-rc2/drivers/parport/parport_arc.c 2004-03-03 22:48:11.000000000 -0800 @@ -104,7 +104,7 @@ /* --- Initialisation code -------------------------------- */ -int parport_arc_init(void) +static int parport_arc_init(void) { /* Archimedes hardware provides only one port, at a fixed address */ struct parport *p; @@ -129,10 +129,11 @@ printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n", p->irq); - parport_proc_register(p); /* Tell the high-level drivers about the port. */ parport_announce_port (p); return 1; } + +module_init(parport_arc_init) diff -urN linux-2.6.4-rc1/drivers/parport/parport_atari.c linux-2.6.4-rc2/drivers/parport/parport_atari.c --- linux-2.6.4-rc1/drivers/parport/parport_atari.c 2004-02-17 19:57:18.000000000 -0800 +++ linux-2.6.4-rc2/drivers/parport/parport_atari.c 2004-03-03 22:48:11.000000000 -0800 @@ -185,8 +185,7 @@ }; -int __init -parport_atari_init(void) +static int __init parport_atari_init(void) { struct parport *p; unsigned long flags; @@ -208,43 +207,34 @@ IRQ_MFP_BUSY, PARPORT_DMA_NONE, &parport_atari_ops); if (!p) - return 0; + return -ENODEV; if (request_irq(IRQ_MFP_BUSY, parport_atari_interrupt, IRQ_TYPE_SLOW, p->name, p)) { - parport_unregister_port (p); - return 0; + parport_put_port (p); + return -ENODEV; } this_port = p; printk(KERN_INFO "%s: Atari built-in port using irq\n", p->name); - parport_proc_register(p); - parport_announce_port (p); - return 1; + return 0; } - return 0; + return -ENODEV; } -#ifdef MODULE +static void __exit parport_atari_exit(void) +{ + parport_remove_port(this_port); + if (this_port->irq != PARPORT_IRQ_NONE) + free_irq(IRQ_MFP_BUSY, this_port); + parport_put_port(this_port); +} MODULE_AUTHOR("Andreas Schwab"); MODULE_DESCRIPTION("Parport Driver for Atari builtin Port"); MODULE_SUPPORTED_DEVICE("Atari builtin Parallel Port"); MODULE_LICENSE("GPL"); -int -init_module(void) -{ - return parport_atari_init() ? 0 : -ENODEV; -} - -void -cleanup_module(void) -{ - if (this_port->irq != PARPORT_IRQ_NONE) - free_irq(IRQ_MFP_BUSY, this_port); - parport_proc_unregister(this_port); - parport_unregister_port(this_port); -} -#endif +module_init(parport_atari_init) +module_exit(parport_atari_exit) diff -urN linux-2.6.4-rc1/drivers/parport/parport_gsc.c linux-2.6.4-rc2/drivers/parport/parport_gsc.c --- linux-2.6.4-rc1/drivers/parport/parport_gsc.c 2004-02-17 19:59:21.000000000 -0800 +++ linux-2.6.4-rc2/drivers/parport/parport_gsc.c 2004-03-03 22:48:11.000000000 -0800 @@ -412,7 +412,6 @@ } #undef printmode printk("]\n"); - parport_proc_register(p); if (p->irq != PARPORT_IRQ_NONE) { if (request_irq (p->irq, parport_gsc_interrupt, @@ -483,17 +482,17 @@ if (p) { struct parport_gsc_private *priv = p->private_data; struct parport_operations *ops = p->ops; + parport_remove_port(p); if (p->dma != PARPORT_DMA_NONE) free_dma(p->dma); if (p->irq != PARPORT_IRQ_NONE) free_irq(p->irq, p); - parport_proc_unregister(p); if (priv->dma_buf) pci_free_consistent(priv->dev, PAGE_SIZE, priv->dma_buf, priv->dma_handle); kfree (p->private_data); - parport_unregister_port(p); + parport_put_port(p); kfree (ops); /* hope no-one cached it */ } } diff -urN linux-2.6.4-rc1/drivers/parport/parport_mfc3.c linux-2.6.4-rc2/drivers/parport/parport_mfc3.c --- linux-2.6.4-rc1/drivers/parport/parport_mfc3.c 2004-02-17 19:57:24.000000000 -0800 +++ linux-2.6.4-rc2/drivers/parport/parport_mfc3.c 2004-03-03 22:48:11.000000000 -0800 @@ -320,7 +320,7 @@ /* ----------- Initialisation code --------------------------------- */ -int __init parport_mfc3_init(void) +static int __init parport_mfc3_init(void) { struct parport *p; int pias = 0; @@ -360,7 +360,6 @@ this_port[pias++] = p; printk(KERN_INFO "%s: Multiface III port using irq\n", p->name); /* XXX: set operating mode */ - parport_proc_register(p); p->private_data = (void *)piabase; parport_announce_port (p); @@ -370,7 +369,7 @@ continue; out_irq: - parport_unregister_port(p); + parport_put_port(p); out_port: release_mem_region(piabase, sizeof(struct pia)); } @@ -378,20 +377,20 @@ return pias ? 0 : -ENODEV; } -void __exit parport_mfc3_exit(void) +static void __exit parport_mfc3_exit(void) { int i; for (i = 0; i < MAX_MFC; i++) { if (!this_port[i]) continue; + parport_remove_port(this_port[i]); if (!this_port[i]->irq != PARPORT_IRQ_NONE) { if (--use_cnt == 0) free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops); } - parport_proc_unregister(this_port[i]); - parport_unregister_port(this_port[i]); release_mem_region(ZTWO_PADDR(this_port[i]->private_data), sizeof(struct pia)); + parport_put_port(this_port[i]); } } @@ -403,4 +402,3 @@ module_init(parport_mfc3_init) module_exit(parport_mfc3_exit) - diff -urN linux-2.6.4-rc1/drivers/parport/parport_pc.c linux-2.6.4-rc2/drivers/parport/parport_pc.c --- linux-2.6.4-rc1/drivers/parport/parport_pc.c 2004-02-17 19:59:45.000000000 -0800 +++ linux-2.6.4-rc2/drivers/parport/parport_pc.c 2004-03-03 22:48:11.000000000 -0800 @@ -2107,6 +2107,9 @@ /* --- Initialisation code -------------------------------- */ +static LIST_HEAD(ports_list); +static spinlock_t ports_lock = SPIN_LOCK_UNLOCKED; + struct parport *parport_pc_probe_port (unsigned long int base, unsigned long int base_hi, int irq, int dma, @@ -2114,39 +2117,30 @@ { struct parport_pc_private *priv; struct parport_operations *ops; - struct parport tmp; - struct parport *p = &tmp; + struct parport *p; int probedirq = PARPORT_IRQ_NONE; struct resource *base_res; struct resource *ECR_res = NULL; struct resource *EPP_res = NULL; - char *fake_name = "parport probe"; - /* - * Chicken and Egg problem. request_region() wants the name of - * the owner, but this instance will not know that name until - * after the parport_register_port() call. Give request_region() - * a fake name until after parport_register_port(), then use - * rename_region() to set correct name. - */ - base_res = request_region(base, 3, fake_name); - if (base_res == NULL) - return NULL; + ops = kmalloc(sizeof (struct parport_operations), GFP_KERNEL); + if (!ops) + goto out1; + priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL); - if (!priv) { - printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base); - release_region(base, 3); - return NULL; - } - ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); - if (!ops) { - printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n", - base); - release_region(base, 3); - kfree (priv); - return NULL; - } - memcpy (ops, &parport_pc_ops, sizeof (struct parport_operations)); + if (!priv) + goto out2; + + /* a misnomer, actually - it's allocate and reserve parport number */ + p = parport_register_port(base, irq, dma, ops); + if (!p) + goto out3; + + base_res = request_region(base, 3, p->name); + if (!base_res) + goto out4; + + memcpy(ops, &parport_pc_ops, sizeof (struct parport_operations)); priv->ctr = 0xc; priv->ctr_writable = ~0x10; priv->ecr = 0; @@ -2154,59 +2148,37 @@ priv->dma_buf = 0; priv->dma_handle = 0; priv->dev = dev; - p->base = base; + INIT_LIST_HEAD(&priv->list); + priv->port = p; p->base_hi = base_hi; - p->irq = irq; - p->dma = dma; p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT; - p->ops = ops; p->private_data = priv; - p->physport = p; if (base_hi) { - ECR_res = request_region(base_hi, 3, fake_name); + ECR_res = request_region(base_hi, 3, p->name); if (ECR_res) parport_ECR_present(p); } if (base != 0x3bc) { - EPP_res = request_region(base+0x3, 5, fake_name); + EPP_res = request_region(base+0x3, 5, p->name); if (EPP_res) if (!parport_EPP_supported(p)) parport_ECPEPP_supported(p); } if (!parport_SPP_supported (p)) /* No port. */ - goto errout; + goto out5; if (priv->ecr) parport_ECPPS2_supported(p); else - parport_PS2_supported (p); + parport_PS2_supported(p); - if (!(p = parport_register_port(base, PARPORT_IRQ_NONE, - PARPORT_DMA_NONE, ops))) - goto errout; - - /* - * Now the real name is known... Replace the fake name - * in the resources with the correct one. - */ - rename_region(base_res, p->name); - if (ECR_res) - rename_region(ECR_res, p->name); - if (EPP_res) - rename_region(EPP_res, p->name); - - p->base_hi = base_hi; - p->modes = tmp.modes; p->size = (p->modes & PARPORT_MODE_EPP)?8:3; - p->private_data = priv; printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base); if (p->base_hi && priv->ecr) printk(" (0x%lx)", p->base_hi); - p->irq = irq; - p->dma = dma; if (p->irq == PARPORT_IRQ_AUTO) { p->irq = PARPORT_IRQ_NONE; parport_irq_probe(p); @@ -2269,7 +2241,6 @@ printk("]\n"); if (probedirq != PARPORT_IRQ_NONE) printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq); - parport_proc_register(p); /* If No ECP release the ports grabbed above. */ if (ECR_res && (p->modes & PARPORT_MODE_ECP) == 0) { @@ -2330,28 +2301,40 @@ /* Now that we've told the sharing engine about the port, and found out its characteristics, let the high-level drivers know about it. */ + spin_lock(&ports_lock); + list_add(&priv->list, &ports_list); + spin_unlock(&ports_lock); parport_announce_port (p); return p; -errout: - release_region(p->base, 3); +out5: if (ECR_res) release_region(base_hi, 3); if (EPP_res) release_region(base+0x3, 5); - + release_region(base, 3); +out4: + parport_put_port(p); +out3: kfree (priv); +out2: kfree (ops); +out1: return NULL; } +EXPORT_SYMBOL (parport_pc_probe_port); + void parport_pc_unregister_port (struct parport *p) { -#ifdef CONFIG_PARPORT_PC_FIFO struct parport_pc_private *priv = p->private_data; -#endif /* CONFIG_PARPORT_PC_FIFO */ struct parport_operations *ops = p->ops; + + parport_remove_port(p); + spin_lock(&ports_lock); + list_del_init(&priv->list); + spin_unlock(&ports_lock); if (p->dma != PARPORT_DMA_NONE) free_dma(p->dma); if (p->irq != PARPORT_IRQ_NONE) @@ -2361,7 +2344,6 @@ release_region(p->base + 3, p->size - 3); if (p->modes & PARPORT_MODE_ECP) release_region(p->base_hi, 3); - parport_proc_unregister(p); #ifdef CONFIG_PARPORT_PC_FIFO if (priv->dma_buf) pci_free_consistent(priv->dev, PAGE_SIZE, @@ -2369,10 +2351,12 @@ priv->dma_handle); #endif /* CONFIG_PARPORT_PC_FIFO */ kfree (p->private_data); - parport_unregister_port(p); + parport_put_port(p); kfree (ops); /* hope no-one cached it */ } +EXPORT_SYMBOL (parport_pc_unregister_port); + #ifdef CONFIG_PCI /* ITE support maintained by Rich Liu */ @@ -2931,45 +2915,57 @@ return count; } -int __init parport_pc_init (int *io, int *io_hi, int *irq, int *dma) -{ - int count = 0, i = 0; - /* try to activate any PnP parports first */ - pnp_register_driver(&parport_pc_pnp_driver); +/* + * Piles of crap below pretend to be a parser for module and kernel + * parameters. Say "thank you" to whoever had come up with that + * syntax and keep in mind that code below is a cleaned up version. + */ - if (io && *io) { - /* Only probe the ports we were given. */ - user_specified = 1; - do { - if ((*io_hi) == PARPORT_IOHI_AUTO) - *io_hi = 0x400 + *io; - if (parport_pc_probe_port(*(io++), *(io_hi++), - *(irq++), *(dma++), NULL)) - count++; - } while (*io && (++i < PARPORT_PC_MAX_PORTS)); - } else { - count += parport_pc_find_ports (irq[0], dma[0]); +static int __initdata io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 }; +static int __initdata io_hi[PARPORT_PC_MAX_PORTS+1] = + { [0 ... PARPORT_PC_MAX_PORTS] = PARPORT_IOHI_AUTO }; +static int __initdata dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE }; +static int __initdata irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY }; + +static int __init parport_parse_param(const char *s, int *val, + int automatic, int none, int nofifo) +{ + if (!s) + return 0; + if (!strncmp(s, "auto", 4)) + *val = automatic; + else if (!strncmp(s, "none", 4)) + *val = none; + else if (nofifo && !strncmp(s, "nofifo", 4)) + *val = nofifo; + else { + char *ep; + unsigned long r = simple_strtoul(s, &ep, 0); + if (ep != s) + *val = r; + else { + printk(KERN_ERR "parport: bad specifier `%s'\n", s); + return -1; + } } + return 0; +} - return count; +static int __init parport_parse_irq(const char *irqstr, int *val) +{ + return parport_parse_param(irqstr, val, PARPORT_IRQ_AUTO, + PARPORT_IRQ_NONE, 0); } -/* Exported symbols. */ -EXPORT_SYMBOL (parport_pc_probe_port); -EXPORT_SYMBOL (parport_pc_unregister_port); +static int __init parport_parse_dma(const char *dmastr, int *val) +{ + return parport_parse_param(dmastr, val, PARPORT_DMA_AUTO, + PARPORT_DMA_NONE, PARPORT_DMA_NOFIFO); +} #ifdef MODULE -static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 }; -static int io_hi[PARPORT_PC_MAX_PORTS+1] = - { [0 ... PARPORT_PC_MAX_PORTS] = PARPORT_IOHI_AUTO }; -static int dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE }; -static int irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY }; -static const char *irq[PARPORT_PC_MAX_PORTS] = { NULL, }; -static const char *dma[PARPORT_PC_MAX_PORTS] = { NULL, }; - -MODULE_AUTHOR("Phil Blundell, Tim Waugh, others"); -MODULE_DESCRIPTION("PC-style parallel port driver"); -MODULE_LICENSE("GPL"); +static const char *irq[PARPORT_PC_MAX_PORTS]; +static const char *dma[PARPORT_PC_MAX_PORTS]; MODULE_PARM_DESC(io, "Base I/O address (SPP regs)"); MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i"); @@ -2985,22 +2981,22 @@ MODULE_PARM(verbose_probing, "i"); #endif -int init_module(void) -{ - /* Work out how many ports we have, then get parport_share to parse - the irq values. */ +static int __init parse_parport_params(void) +{ unsigned int i; - int ret; - for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++); - if (i) { - if (parport_parse_irqs(i, irq, irqval)) return 1; - if (parport_parse_dmas(i, dma, dmaval)) return 1; + int val; + + for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++) { + if (parport_parse_irq(irq[i], &val)) + return 1; + irqval[i] = val; + if (parport_parse_dma(dma[i], &val)) + return 1; + dmaval[i] = val; } - else { + if (!io[0]) { /* The user can make us use any IRQs or DMAs we find. */ - int val; - - if (irq[0] && !parport_parse_irqs (1, irq, &val)) + if (irq[0] && !parport_parse_irq(irq[0], &val)) switch (val) { case PARPORT_IRQ_NONE: case PARPORT_IRQ_AUTO: @@ -3013,7 +3009,7 @@ "to specify one\n"); } - if (dma[0] && !parport_parse_dmas (1, dma, &val)) + if (dma[0] && !parport_parse_dma(dma[0], &val)) switch (val) { case PARPORT_DMA_NONE: case PARPORT_DMA_AUTO: @@ -3026,29 +3022,144 @@ "to specify one\n"); } } + return 0; +} - ret = !parport_pc_init (io, io_hi, irqval, dmaval); - if (ret && registered_parport) - pci_unregister_driver (&parport_pc_pci_driver); +#else - return ret; +static int parport_setup_ptr __initdata = 0; + +/* + * Acceptable parameters: + * + * parport=0 + * parport=auto + * parport=0xBASE[,IRQ[,DMA]] + * + * IRQ/DMA may be numeric or 'auto' or 'none' + */ +static int __init parport_setup (char *str) +{ + char *endptr; + char *sep; + int val; + + if (!str || !*str || (*str == '0' && !*(str+1))) { + /* Disable parport if "parport=0" in cmdline */ + io[0] = PARPORT_DISABLE; + return 1; + } + + if (!strncmp (str, "auto", 4)) { + irqval[0] = PARPORT_IRQ_AUTO; + dmaval[0] = PARPORT_DMA_AUTO; + return 1; + } + + val = simple_strtoul (str, &endptr, 0); + if (endptr == str) { + printk (KERN_WARNING "parport=%s not understood\n", str); + return 1; + } + + if (parport_setup_ptr == PARPORT_PC_MAX_PORTS) { + printk(KERN_ERR "parport=%s ignored, too many ports\n", str); + return 1; + } + + io[parport_setup_ptr] = val; + irqval[parport_setup_ptr] = PARPORT_IRQ_NONE; + dmaval[parport_setup_ptr] = PARPORT_DMA_NONE; + + sep = strchr(str, ','); + if (sep++) { + if (parport_parse_irq(sep, &val)) + return 1; + irqval[parport_setup_ptr] = val; + sep = strchr(sep, ','); + if (sep++) { + if (parport_parse_dma(sep, &val)) + return 1; + dmaval[parport_setup_ptr] = val; + } + } + parport_setup_ptr++; + return 1; } -void cleanup_module(void) +static int __init parse_parport_params(void) { - /* We ought to keep track of which ports are actually ours. */ - struct parport *p = parport_enumerate(), *tmp; + return io[0] == PARPORT_DISABLE; +} - if (!user_specified) - pci_unregister_driver (&parport_pc_pci_driver); +__setup ("parport=", parport_setup); +#endif - while (p) { - tmp = p->next; - if (p->modes & PARPORT_MODE_PCSPP) - parport_pc_unregister_port (p); +/* "Parser" ends here */ - p = tmp; +static int __init parport_pc_init(void) +{ + int count = 0; + + if (parse_parport_params()) + return -EINVAL; + + /* try to activate any PnP parports first */ + pnp_register_driver(&parport_pc_pnp_driver); + + if (io[0]) { + int i; + /* Only probe the ports we were given. */ + user_specified = 1; + for (i = 0; i < PARPORT_PC_MAX_PORTS; i++) { + if (!io[i]) + break; + if ((io_hi[i]) == PARPORT_IOHI_AUTO) + io_hi[i] = 0x400 + io[i]; + if (parport_pc_probe_port(io[i], io_hi[i], + irqval[i], dmaval[i], NULL)) + count++; + } + } else { + count += parport_pc_find_ports (irqval[0], dmaval[0]); + if (!count && registered_parport) + pci_unregister_driver (&parport_pc_pci_driver); + } + + if (!count) { + pnp_unregister_driver (&parport_pc_pnp_driver); + return -ENODEV; + } + + return 0; +} + +static void __exit parport_pc_exit(void) +{ + if (registered_parport) + pci_unregister_driver (&parport_pc_pci_driver); + + spin_lock(&ports_lock); + while (!list_empty(&ports_list)) { + struct parport_pc_private *priv; + struct parport *port; + priv = list_entry(ports_list.next, + struct parport_pc_private, list); + port = priv->port; + spin_unlock(&ports_lock); + parport_pc_unregister_port(port); + spin_lock(&ports_lock); } + spin_unlock(&ports_lock); pnp_unregister_driver (&parport_pc_pnp_driver); } -#endif + + +MODULE_AUTHOR("Phil Blundell, Tim Waugh, others"); +MODULE_DESCRIPTION("PC-style parallel port driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Phil Blundell, Tim Waugh, others"); +MODULE_DESCRIPTION("PC-style parallel port driver"); +MODULE_LICENSE("GPL"); +module_init(parport_pc_init) +module_exit(parport_pc_exit) diff -urN linux-2.6.4-rc1/drivers/parport/parport_sunbpp.c linux-2.6.4-rc2/drivers/parport/parport_sunbpp.c --- linux-2.6.4-rc1/drivers/parport/parport_sunbpp.c 2004-02-17 19:57:16.000000000 -0800 +++ linux-2.6.4-rc2/drivers/parport/parport_sunbpp.c 2004-03-03 22:48:11.000000000 -0800 @@ -286,39 +286,49 @@ .owner = THIS_MODULE, }; +typedef struct { + struct list_head list; + struct parport *port; +} Node; +/* no locks, everything's serialized */ +static LIST_HEAD(port_list); + static int __init init_one_port(struct sbus_dev *sdev) { struct parport *p; /* at least in theory there may be a "we don't dma" case */ struct parport_operations *ops; unsigned long base; - int irq, dma, err, size; + int irq, dma, err = 0, size; struct bpp_regs *regs; unsigned char value_tcr; + Node *node; dprintk((KERN_DEBUG "init_one_port(%p): ranges, alloc_io, ", sdev)); + node = kmalloc(sizeof(Node), GFP_KERNEL); + if (!node) + goto out0; + irq = sdev->irqs[0]; base = sbus_ioremap(&sdev->resource[0], 0, sdev->reg_addrs[0].reg_size, "sunbpp"); + if (!base) + goto out1; + size = sdev->reg_addrs[0].reg_size; dma = PARPORT_DMA_NONE; dprintk(("alloc(ppops), ")); ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); - if (!ops) { - sbus_iounmap(base, size); - return 0; - } + if (!ops) + goto out2; memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations)); dprintk(("register_port\n")); - if (!(p = parport_register_port(base, irq, dma, ops))) { - kfree(ops); - sbus_iounmap(base, size); - return 0; - } + if (!(p = parport_register_port(base, irq, dma, ops))) + goto out3; p->size = size; @@ -327,14 +337,10 @@ if ((err = request_irq(p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p)) != 0) { dprintk(("ERROR %d\n", err)); - parport_unregister_port(p); - kfree(ops); - sbus_iounmap(base, size); - return err; - } else { - dprintk(("OK\n")); - parport_sunbpp_enable_irq(p); + goto out4; } + dprintk(("OK\n")); + parport_sunbpp_enable_irq(p); regs = (struct bpp_regs *)p->base; dprintk((KERN_DEBUG "forward\n")); @@ -343,17 +349,25 @@ sbus_writeb(value_tcr, ®s->p_tcr); printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); - parport_proc_register(p); + node->port = p; + list_add(&node->list, &port_list); parport_announce_port (p); return 1; + +out4: + parport_put_port(p); +out3: + kfree(ops); +out2: + sbus_iounmap(base, size); +out1: + kfree(node); +out0: + return err; } -#ifdef MODULE -int init_module(void) -#else -int __init parport_sunbpp_init(void) -#endif +static int __init parport_sunbpp_init(void) { struct sbus_bus *sbus; struct sbus_dev *sdev; @@ -368,34 +382,30 @@ return count ? 0 : -ENODEV; } -#ifdef MODULE -MODULE_AUTHOR("Derrick J Brashear"); -MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port"); -MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port"); - -void -cleanup_module(void) +static void __exit parport_sunbpp_exit(void) { - struct parport *p = parport_enumerate(); - - while (p) { - struct parport *next = p->next; - - if (1/*p->modes & PARPORT_MODE_PCSPP*/) { - struct parport_operations *ops = p->ops; - - if (p->irq != PARPORT_IRQ_NONE) { - parport_sunbpp_disable_irq(p); - free_irq(p->irq, p); - } - sbus_iounmap(p->base, p->size); - parport_proc_unregister(p); - parport_unregister_port(p); - kfree (ops); + while (!list_empty(port_list)) { + Node *node = list_entry(port_list.next, Node, list); + struct parport *p = node->port; + struct parport_operations *ops = p->ops; + parport_remove_port(p); + + if (p->irq != PARPORT_IRQ_NONE) { + parport_sunbpp_disable_irq(p); + free_irq(p->irq, p); } - p = next; + sbus_iounmap(p->base, p->size); + parport_put_port(p); + kfree (ops); + list_del(&node->list); + kfree (node); } } -#endif +MODULE_AUTHOR("Derrick J Brashear"); +MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port"); +MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port"); MODULE_LICENSE("GPL"); + +module_init(parport_sunbpp_init) +module_exit(parport_sunbpp_exit) diff -urN linux-2.6.4-rc1/drivers/parport/probe.c linux-2.6.4-rc2/drivers/parport/probe.c --- linux-2.6.4-rc1/drivers/parport/probe.c 2004-02-17 19:57:21.000000000 -0800 +++ linux-2.6.4-rc2/drivers/parport/probe.c 2004-03-03 22:48:11.000000000 -0800 @@ -5,6 +5,7 @@ * Philip Blundell */ +#include #include #include #include @@ -212,3 +213,4 @@ parport_close (dev); return retval; } +EXPORT_SYMBOL(parport_device_id); diff -urN linux-2.6.4-rc1/drivers/parport/procfs.c linux-2.6.4-rc2/drivers/parport/procfs.c --- linux-2.6.4-rc1/drivers/parport/procfs.c 2004-02-17 19:57:20.000000000 -0800 +++ linux-2.6.4-rc2/drivers/parport/procfs.c 2004-03-03 22:48:11.000000000 -0800 @@ -14,6 +14,8 @@ #include #include +#include +#include #include #include #include @@ -479,21 +481,20 @@ return 0; } -int parport_default_proc_register(void) +static int __init parport_default_proc_register(void) { parport_default_sysctl_table.sysctl_header = register_sysctl_table(parport_default_sysctl_table.dev_dir, 0); return 0; } -int parport_default_proc_unregister(void) +static void __exit parport_default_proc_unregister(void) { if (parport_default_sysctl_table.sysctl_header) { unregister_sysctl_table(parport_default_sysctl_table. sysctl_header); parport_default_sysctl_table.sysctl_header = NULL; } - return 0; } #else /* no sysctl or no procfs*/ @@ -518,13 +519,19 @@ return 0; } -int parport_default_proc_register (void) +static int __init parport_default_proc_register (void) { return 0; } -int parport_default_proc_unregister (void) +static void __exit parport_default_proc_unregister (void) { return 0; } #endif + +EXPORT_SYMBOL(parport_device_proc_register); +EXPORT_SYMBOL(parport_device_proc_unregister); + +module_init(parport_default_proc_register) +module_exit(parport_default_proc_unregister) diff -urN linux-2.6.4-rc1/drivers/parport/share.c linux-2.6.4-rc2/drivers/parport/share.c --- linux-2.6.4-rc1/drivers/parport/share.c 2004-02-17 19:57:58.000000000 -0800 +++ linux-2.6.4-rc2/drivers/parport/share.c 2004-03-03 22:48:11.000000000 -0800 @@ -41,14 +41,14 @@ unsigned long parport_default_timeslice = PARPORT_DEFAULT_TIMESLICE; int parport_default_spintime = DEFAULT_SPIN_TIME; -static struct parport *portlist = NULL, *portlist_tail = NULL; +static LIST_HEAD(portlist); static spinlock_t parportlist_lock = SPIN_LOCK_UNLOCKED; /* list of all allocated ports, sorted by ->number */ static LIST_HEAD(all_ports); static spinlock_t full_list_lock = SPIN_LOCK_UNLOCKED; -static struct parport_driver *driver_chain = NULL; +static LIST_HEAD(drivers); static DECLARE_MUTEX(registration_lock); @@ -105,16 +105,16 @@ { /* caller has exclusive registration_lock */ struct parport_driver *drv; - for (drv = driver_chain; drv; drv = drv->next) + list_for_each_entry(drv, &drivers, list) drv->attach(port); } /* Call detach(port) for each registered driver. */ static void detach_driver_chain(struct parport *port) { - /* caller has exclusive registration_lock */ struct parport_driver *drv; - for (drv = driver_chain; drv; drv = drv->next) + /* caller has exclusive registration_lock */ + list_for_each_entry(drv, &drivers, list) drv->detach (port); } @@ -155,22 +155,13 @@ { struct parport *port; - if (!portlist) + if (list_empty(&portlist)) get_lowlevel_driver (); - /* We have to take the portlist lock for this to be sure - * that port is valid for the duration of the callback. */ - - /* This is complicated by the fact that attach must be allowed - * to block, so we can't be holding any spinlocks when we call - * it. But we need to hold a spinlock to iterate over the - * list of ports.. */ - down(®istration_lock); - for (port = portlist; port; port = port->next) + list_for_each_entry(port, &portlist, list) drv->attach(port); - drv->next = driver_chain; - driver_chain = drv; + list_add(&drv->list, &drivers); up(®istration_lock); return 0; @@ -193,33 +184,14 @@ * finished by the time this function returns. **/ -void parport_unregister_driver (struct parport_driver *arg) +void parport_unregister_driver (struct parport_driver *drv) { - struct parport_driver *drv, *olddrv = NULL; + struct parport *port; down(®istration_lock); - drv = driver_chain; - while (drv) { - if (drv == arg) { - struct parport *port; - - if (olddrv) - olddrv->next = drv->next; - else - driver_chain = drv->next; - - /* Call the driver's detach routine for each - * port to clean up any resources that the - * attach routine acquired. */ - for (port = portlist; port; port = port->next) - drv->detach (port); - up(®istration_lock); - - return; - } - olddrv = drv; - drv = drv->next; - } + list_del_init(&drv->list); + list_for_each_entry(port, &portlist, list) + drv->detach(port); up(®istration_lock); } @@ -278,28 +250,6 @@ } /** - * parport_enumerate - return a list of the system's parallel ports - * - * This returns the head of the list of parallel ports in the - * system, as a &struct parport. The structure that is returned - * describes the first port in the list, and its 'next' member - * points to the next port, or %NULL if it's the last port. - * - * If there are no parallel ports in the system, - * parport_enumerate() will return %NULL. - **/ - -struct parport *parport_enumerate(void) -{ - /* Don't use this: use parport_register_driver instead. */ - - if (!portlist) - get_lowlevel_driver (); - - return portlist; -} - -/** * parport_register_port - register a parallel port * @base: base I/O address * @irq: IRQ line @@ -322,7 +272,7 @@ * parport_announce_port(). * * The @ops structure is allocated by the caller, and must not be - * deallocated before calling parport_unregister_port(). + * deallocated before calling parport_remove_port(). * * If there is no memory to allocate a new parport structure, * this function will return %NULL. @@ -350,7 +300,7 @@ tmp->dma = dma; tmp->muxport = tmp->daisy = tmp->muxsel = -1; tmp->modes = 0; - tmp->next = NULL; + INIT_LIST_HEAD(&tmp->list); tmp->devices = tmp->cad = NULL; tmp->flags = 0; tmp->ops = ops; @@ -413,49 +363,36 @@ void parport_announce_port (struct parport *port) { + int i; #ifdef CONFIG_PARPORT_1284 /* Analyse the IEEE1284.3 topology of the port. */ - if (parport_daisy_init (port) == 0) { - /* No devices were detected. Perhaps they are in some - funny state; let's try to reset them and see if - they wake up. */ - parport_daisy_fini (port); - parport_write_control (port, PARPORT_CONTROL_SELECT); - udelay (50); - parport_write_control (port, - PARPORT_CONTROL_SELECT | - PARPORT_CONTROL_INIT); - udelay (50); - parport_daisy_init (port); - } + parport_daisy_init(port); #endif + parport_proc_register(port); down(®istration_lock); - /* We are locked against anyone else performing alterations, but - * because of parport_enumerate people can still _read_ the list - * while we are changing it; so be careful.. - * - * It's okay to have portlist_tail a little bit out of sync - * since it's only used for changing the list, not for reading - * from it. - */ - spin_lock_irq(&parportlist_lock); - if (portlist_tail) - portlist_tail->next = port; - portlist_tail = port; - if (!portlist) - portlist = port; + list_add_tail(&port->list, &portlist); + for (i = 1; i < 3; i++) { + struct parport *slave = port->slaves[i-1]; + if (slave) + list_add_tail(&slave->list, &portlist); + } spin_unlock_irq(&parportlist_lock); - /* Let drivers know that a new port has arrived. */ + /* Let drivers know that new port(s) has arrived. */ attach_driver_chain (port); + for (i = 1; i < 3; i++) { + struct parport *slave = port->slaves[i-1]; + if (slave) + attach_driver_chain(slave); + } up(®istration_lock); } /** - * parport_unregister_port - deregister a parallel port + * parport_remove_port - deregister a parallel port * @port: parallel port to deregister * * When a parallel port driver is forcibly unloaded, or a @@ -473,44 +410,46 @@ * with @port as the parameter. **/ -void parport_unregister_port(struct parport *port) +void parport_remove_port(struct parport *port) { - struct parport *p; + int i; down(®istration_lock); - port->ops = &dead_ops; /* Spread the word. */ detach_driver_chain (port); #ifdef CONFIG_PARPORT_1284 /* Forget the IEEE1284.3 topology of the port. */ - parport_daisy_fini (port); + parport_daisy_fini(port); + for (i = 1; i < 3; i++) { + struct parport *slave = port->slaves[i-1]; + if (!slave) + continue; + detach_driver_chain(slave); + parport_daisy_fini(slave); + } #endif + port->ops = &dead_ops; spin_lock(&parportlist_lock); - - /* We are protected from other people changing the list, but - * they can still see it (using parport_enumerate). So be - * careful about the order of writes.. */ - if (portlist == port) { - if ((portlist = port->next) == NULL) - portlist_tail = NULL; - } else { - for (p = portlist; (p != NULL) && (p->next != port); - p=p->next); - if (p) { - if ((p->next = port->next) == NULL) - portlist_tail = p; - } - else printk (KERN_WARNING - "%s not found in port list!\n", port->name); + list_del_init(&port->list); + for (i = 1; i < 3; i++) { + struct parport *slave = port->slaves[i-1]; + if (slave) + list_del_init(&slave->list); } spin_unlock(&parportlist_lock); + up(®istration_lock); - /* Yes, parport_enumerate _is_ unsafe. Don't use it. */ - parport_put_port (port); + parport_proc_unregister(port); + + for (i = 1; i < 3; i++) { + struct parport *slave = port->slaves[i-1]; + if (slave) + parport_put_port(slave); + } } /** @@ -607,9 +546,8 @@ /* We up our own module reference count, and that of the port on which a device is to be registered, to ensure that neither of us gets unloaded while we sleep in (e.g.) - kmalloc. To be absolutely safe, we have to require that - our caller doesn't sleep in between parport_enumerate and - parport_register_device.. */ + kmalloc. + */ if (!try_module_get(port->ops->owner)) { return NULL; } @@ -751,11 +689,6 @@ module_put(port->ops->owner); parport_put_port (port); - - /* Yes, that's right, someone _could_ still have a pointer to - * port, if they used parport_enumerate. That's why they - * shouldn't use it (and use parport_register_driver instead).. - */ } /** @@ -774,15 +707,16 @@ { struct parport *port, *result = NULL; - if (!portlist) + if (list_empty(&portlist)) get_lowlevel_driver (); spin_lock (&parportlist_lock); - for (port = portlist; port; port = port->next) + list_for_each_entry(port, &portlist, list) { if (port->number == number) { result = parport_get_port (port); break; } + } spin_unlock (&parportlist_lock); return result; } @@ -803,15 +737,16 @@ { struct parport *port, *result = NULL; - if (!portlist) + if (list_empty(&portlist)) get_lowlevel_driver (); spin_lock (&parportlist_lock); - for (port = portlist; port; port = port->next) + list_for_each_entry(port, &portlist, list) { if (port->base == base) { result = parport_get_port (port); break; } + } spin_unlock (&parportlist_lock); return result; } @@ -1060,41 +995,21 @@ } } -static int parport_parse_params (int nports, const char *str[], int val[], - int automatic, int none, int nofifo) -{ - unsigned int i; - for (i = 0; i < nports && str[i]; i++) { - if (!strncmp(str[i], "auto", 4)) - val[i] = automatic; - else if (!strncmp(str[i], "none", 4)) - val[i] = none; - else if (nofifo && !strncmp(str[i], "nofifo", 4)) - val[i] = nofifo; - else { - char *ep; - unsigned long r = simple_strtoul(str[i], &ep, 0); - if (ep != str[i]) - val[i] = r; - else { - printk(KERN_ERR "parport: bad specifier `%s'\n", str[i]); - return -1; - } - } - } - - return 0; -} +/* Exported symbols for modules. */ -int parport_parse_irqs(int nports, const char *irqstr[], int irqval[]) -{ - return parport_parse_params (nports, irqstr, irqval, PARPORT_IRQ_AUTO, - PARPORT_IRQ_NONE, 0); -} +EXPORT_SYMBOL(parport_claim); +EXPORT_SYMBOL(parport_claim_or_block); +EXPORT_SYMBOL(parport_release); +EXPORT_SYMBOL(parport_register_port); +EXPORT_SYMBOL(parport_announce_port); +EXPORT_SYMBOL(parport_remove_port); +EXPORT_SYMBOL(parport_register_driver); +EXPORT_SYMBOL(parport_unregister_driver); +EXPORT_SYMBOL(parport_register_device); +EXPORT_SYMBOL(parport_unregister_device); +EXPORT_SYMBOL(parport_get_port); +EXPORT_SYMBOL(parport_put_port); +EXPORT_SYMBOL(parport_find_number); +EXPORT_SYMBOL(parport_find_base); -int parport_parse_dmas(int nports, const char *dmastr[], int dmaval[]) -{ - return parport_parse_params (nports, dmastr, dmaval, PARPORT_DMA_AUTO, - PARPORT_DMA_NONE, PARPORT_DMA_NOFIFO); -} MODULE_LICENSE("GPL"); diff -urN linux-2.6.4-rc1/drivers/pci/hotplug/Kconfig linux-2.6.4-rc2/drivers/pci/hotplug/Kconfig --- linux-2.6.4-rc1/drivers/pci/hotplug/Kconfig 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/hotplug/Kconfig 2004-03-03 22:48:11.000000000 -0800 @@ -135,23 +135,14 @@ When in doubt, say N. config HOTPLUG_PCI_PCIE_POLL_EVENT_MODE - bool "Use polling mechanism for hot-plug events." + bool "Use polling mechanism for hot-plug events (for testing purpose)" depends on HOTPLUG_PCI_PCIE help Say Y here if you want to use the polling mechanism for hot-plug - events. + events for early platform testing. When in doubt, say N. -config HOTPLUG_PCI_PCIE_PHPRM_NONACPI - bool "Non-ACPI: Use $HPRT for resource/configuration" - depends on HOTPLUG_PCI_PCIE - help - Say Y here if Hotplug resource/configuration information is provided - by platform BIOS $HPRT or bridge resource information, not by ACPI. - - When in doubt, say N. - config HOTPLUG_PCI_SHPC tristate "SHPC PCI Hotplug driver" depends on HOTPLUG_PCI @@ -165,33 +156,24 @@ When in doubt, say N. config HOTPLUG_PCI_SHPC_POLL_EVENT_MODE - bool "Use polling mechanism for hot-plug events" + bool "Use polling mechanism for hot-plug events (for testing purpose)" depends on HOTPLUG_PCI_SHPC help Say Y here if you want to use the polling mechanism for hot-plug - events. - - When in doubt, say N. - -config HOTPLUG_PCI_SHPC_PHPRM_NONACPI - bool "Non-ACPI: Use $HPRT for resource/configuration" - depends on HOTPLUG_PCI_SHPC - help - Say Y here if Hotplug resource/configuration information is provided - by platform BIOS $HPRT or bridge resource information, not by ACPI. + events for early platform testing. When in doubt, say N. config HOTPLUG_PCI_SHPC_PHPRM_LEGACY bool "For AMD SHPC only: Use $HRT for resource/configuration" - depends on HOTPLUG_PCI_SHPC && HOTPLUG_PCI_SHPC_PHPRM_NONACPI + depends on HOTPLUG_PCI_SHPC && !ACPI_BUS help Say Y here for AMD SHPC. You have to select this option if you are - using this driver on AMD platform with SHPC. + using this driver on platform with AMD SHPC. config HOTPLUG_PCI_RPA tristate "RPA PCI Hotplug driver" - depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 + depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE help Say Y here if you have a a RPA system that supports PCI Hotplug. diff -urN linux-2.6.4-rc1/drivers/pci/hotplug/Makefile linux-2.6.4-rc2/drivers/pci/hotplug/Makefile --- linux-2.6.4-rc1/drivers/pci/hotplug/Makefile 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/hotplug/Makefile 2004-03-03 22:48:11.000000000 -0800 @@ -25,6 +25,8 @@ cpqphp_ctrl.o \ cpqphp_sysfs.o \ cpqphp_pci.o +cpqphp-$(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM) += cpqphp_nvram.o +cpqphp-objs += $(cpqphp-y) ibmphp-objs := ibmphp_core.o \ ibmphp_ebda.o \ @@ -48,38 +50,23 @@ pciehp_pci.o \ pciehp_sysfs.o \ pciehp_hpc.o +ifdef CONFIG_ACPI_BUS + pciehp-objs += pciehprm_acpi.o +else + pciehp-objs += pciehprm_nonacpi.o +endif shpchp-objs := shpchp_core.o \ shpchp_ctrl.o \ shpchp_pci.o \ shpchp_sysfs.o \ shpchp_hpc.o - -ifdef CONFIG_HOTPLUG_PCI_ACPI - EXTRA_CFLAGS += -D_LINUX -I$(TOPDIR)/drivers/acpi - ifdef CONFIG_ACPI_DEBUG - EXTRA_CFLAGS += -DACPI_DEBUG_OUTPUT - endif -endif - -ifeq ($(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM),y) - cpqphp-objs += cpqphp_nvram.o -endif - -ifeq ($(CONFIG_HOTPLUG_PCI_PCIE_PHPRM_NONACPI),y) - pciehp-objs += pciehprm_nonacpi.o -else - pciehp-objs += pciehprm_acpi.o - EXTRA_CFLAGS += -D_LINUX -I$(TOPDIR)/drivers/acpi -I$(TOPDIR)/drivers/acpi/include -endif - -ifeq ($(CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY),y) - shpchp-objs += shpchprm_legacy.o +ifdef CONFIG_ACPI_BUS + shpchp-objs += shpchprm_acpi.o else - ifeq ($(CONFIG_HOTPLUG_PCI_SHPC_PHPRM_NONACPI),y) - shpchp-objs += shpchprm_nonacpi.o - else - shpchp-objs += shpchprm_acpi.o - EXTRA_CFLAGS += -D_LINUX -I$(TOPDIR)/drivers/acpi - endif + ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY + shpchp-objs += shpchprm_legacy.o + else + shpchp-objs += shpchprm_nonacpi.o + endif endif diff -urN linux-2.6.4-rc1/drivers/pci/hotplug/cpqphp.h linux-2.6.4-rc2/drivers/pci/hotplug/cpqphp.h --- linux-2.6.4-rc1/drivers/pci/hotplug/cpqphp.h 2004-02-17 19:59:14.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/hotplug/cpqphp.h 2004-03-03 22:48:11.000000000 -0800 @@ -444,6 +444,7 @@ /* Global variables */ extern int cpqhp_debug; +extern int cpqhp_legacy_mode; extern struct controller *cpqhp_ctrl_list; extern struct pci_func *cpqhp_slot_list[256]; diff -urN linux-2.6.4-rc1/drivers/pci/hotplug/cpqphp_core.c linux-2.6.4-rc2/drivers/pci/hotplug/cpqphp_core.c --- linux-2.6.4-rc1/drivers/pci/hotplug/cpqphp_core.c 2004-02-17 19:57:11.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/hotplug/cpqphp_core.c 2004-03-03 22:48:11.000000000 -0800 @@ -49,6 +49,7 @@ /* Global variables */ int cpqhp_debug; +int cpqhp_legacy_mode; struct controller *cpqhp_ctrl_list; /* = NULL */ struct pci_func *cpqhp_slot_list[256]; @@ -1169,6 +1170,10 @@ */ // The next line is required for cpqhp_find_available_resources ctrl->interrupt = pdev->irq; + if (ctrl->interrupt < 0x10) { + cpqhp_legacy_mode = 1; + dbg("System seems to be configured for Full Table Mapped MPS mode\n"); + } ctrl->cfgspc_irq = 0; pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ctrl->cfgspc_irq); diff -urN linux-2.6.4-rc1/drivers/pci/hotplug/cpqphp_ctrl.c linux-2.6.4-rc2/drivers/pci/hotplug/cpqphp_ctrl.c --- linux-2.6.4-rc1/drivers/pci/hotplug/cpqphp_ctrl.c 2004-02-17 19:57:24.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/hotplug/cpqphp_ctrl.c 2004-03-03 22:48:11.000000000 -0800 @@ -3020,33 +3020,34 @@ } } } // End of base register loop - -#if !defined(CONFIG_X86_IO_APIC) - // Figure out which interrupt pin this function uses - rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_INTERRUPT_PIN, &temp_byte); - - // If this function needs an interrupt and we are behind a bridge - // and the pin is tied to something that's alread mapped, - // set this one the same - if (temp_byte && resources->irqs && - (resources->irqs->valid_INT & - (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) { - // We have to share with something already set up - IRQ = resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03]; - } else { - // Program IRQ based on card type - rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); - - if (class_code == PCI_BASE_CLASS_STORAGE) { - IRQ = cpqhp_disk_irq; + if (cpqhp_legacy_mode) { + // Figure out which interrupt pin this function uses + rc = pci_bus_read_config_byte (pci_bus, devfn, + PCI_INTERRUPT_PIN, &temp_byte); + + // If this function needs an interrupt and we are behind a bridge + // and the pin is tied to something that's alread mapped, + // set this one the same + if (temp_byte && resources->irqs && + (resources->irqs->valid_INT & + (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) { + // We have to share with something already set up + IRQ = resources->irqs->interrupt[(temp_byte + + resources->irqs->barber_pole - 1) & 0x03]; } else { - IRQ = cpqhp_nic_irq; + // Program IRQ based on card type + rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); + + if (class_code == PCI_BASE_CLASS_STORAGE) { + IRQ = cpqhp_disk_irq; + } else { + IRQ = cpqhp_nic_irq; + } } - } - // IRQ Line - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ); -#endif + // IRQ Line + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ); + } if (!behind_bridge) { rc = cpqhp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ); diff -urN linux-2.6.4-rc1/drivers/pci/hotplug/cpqphp_pci.c linux-2.6.4-rc2/drivers/pci/hotplug/cpqphp_pci.c --- linux-2.6.4-rc1/drivers/pci/hotplug/cpqphp_pci.c 2004-02-17 19:59:30.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/hotplug/cpqphp_pci.c 2004-03-03 22:48:11.000000000 -0800 @@ -151,32 +151,32 @@ */ int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num) { -#if !defined(CONFIG_X86_IO_APIC) int rc; u16 temp_word; struct pci_dev fakedev; struct pci_bus fakebus; - fakedev.devfn = dev_num << 3; - fakedev.bus = &fakebus; - fakebus.number = bus_num; - dbg("%s: dev %d, bus %d, pin %d, num %d\n", - __FUNCTION__, dev_num, bus_num, int_pin, irq_num); - rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num); - dbg("%s: rc %d\n", __FUNCTION__, rc); - if (!rc) - return !rc; - - // set the Edge Level Control Register (ELCR) - temp_word = inb(0x4d0); - temp_word |= inb(0x4d1) << 8; - - temp_word |= 0x01 << irq_num; - - // This should only be for x86 as it sets the Edge Level Control Register - outb((u8) (temp_word & 0xFF), 0x4d0); - outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1); -#endif + if (cpqhp_legacy_mode) { + fakedev.devfn = dev_num << 3; + fakedev.bus = &fakebus; + fakebus.number = bus_num; + dbg("%s: dev %d, bus %d, pin %d, num %d\n", + __FUNCTION__, dev_num, bus_num, int_pin, irq_num); + rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num); + dbg("%s: rc %d\n", __FUNCTION__, rc); + if (!rc) + return !rc; + + // set the Edge Level Control Register (ELCR) + temp_word = inb(0x4d0); + temp_word |= inb(0x4d1) << 8; + + temp_word |= 0x01 << irq_num; + + // This should only be for x86 as it sets the Edge Level Control Register + outb((u8) (temp_word & 0xFF), 0x4d0); + outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1); + } return 0; } diff -urN linux-2.6.4-rc1/drivers/pci/hotplug/pci_hotplug_core.c linux-2.6.4-rc2/drivers/pci/hotplug/pci_hotplug_core.c --- linux-2.6.4-rc1/drivers/pci/hotplug/pci_hotplug_core.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/hotplug/pci_hotplug_core.c 2004-03-03 22:48:11.000000000 -0800 @@ -104,8 +104,19 @@ .release = &hotplug_slot_release, }; -decl_subsys(pci_hotplug_slots, &hotplug_slot_ktype, NULL); - +/* + * We create a struct subsystem on our own and not use decl_subsys so + * we can have a sane name "slots" in sysfs, yet still keep a good + * global variable name "pci_hotplug_slots_subsys. + * If the decl_subsys() #define ever changes, this declaration will + * need to be update to make sure everything is initialized properly. + */ +struct subsystem pci_hotplug_slots_subsys = { + .kset = { + .kobj = { .name = "slots" }, + .ktype = &hotplug_slot_ktype, + } +}; /* these strings match up with the values in pci_bus_speed */ static char *pci_bus_speed_strings[] = { @@ -281,7 +292,7 @@ } static struct hotplug_slot_attribute hotplug_slot_attr_latch = { - .attr = {.name = "latch", .mode = S_IFREG | S_IRUGO | S_IWUSR}, + .attr = {.name = "latch", .mode = S_IFREG | S_IRUGO}, .show = latch_read_file, }; @@ -300,7 +311,7 @@ } static struct hotplug_slot_attribute hotplug_slot_attr_presence = { - .attr = {.name = "adapter", .mode = S_IFREG | S_IRUGO | S_IWUSR}, + .attr = {.name = "adapter", .mode = S_IFREG | S_IRUGO}, .show = presence_read_file, }; @@ -350,7 +361,7 @@ } static struct hotplug_slot_attribute hotplug_slot_attr_max_bus_speed = { - .attr = {.name = "max_bus_speed", .mode = S_IFREG | S_IRUGO | S_IWUSR}, + .attr = {.name = "max_bus_speed", .mode = S_IFREG | S_IRUGO}, .show = max_bus_speed_read_file, }; @@ -376,7 +387,7 @@ } static struct hotplug_slot_attribute hotplug_slot_attr_cur_bus_speed = { - .attr = {.name = "cur_bus_speed", .mode = S_IFREG | S_IRUGO | S_IWUSR}, + .attr = {.name = "cur_bus_speed", .mode = S_IFREG | S_IRUGO}, .show = cur_bus_speed_read_file, }; diff -urN linux-2.6.4-rc1/drivers/pci/hotplug/pciehp_ctrl.c linux-2.6.4-rc2/drivers/pci/hotplug/pciehp_ctrl.c --- linux-2.6.4-rc1/drivers/pci/hotplug/pciehp_ctrl.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/hotplug/pciehp_ctrl.c 2004-03-03 22:48:11.000000000 -0800 @@ -188,11 +188,13 @@ /* * Card Present */ + info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); taskInfo->event_type = INT_PRESENCE_ON; } else { /* * Not Present */ + info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); taskInfo->event_type = INT_PRESENCE_OFF; } diff -urN linux-2.6.4-rc1/drivers/pci/hotplug/pciehprm_acpi.c linux-2.6.4-rc2/drivers/pci/hotplug/pciehprm_acpi.c --- linux-2.6.4-rc1/drivers/pci/hotplug/pciehprm_acpi.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/hotplug/pciehprm_acpi.c 2004-03-03 22:48:11.000000000 -0800 @@ -1188,6 +1188,9 @@ static void pciehprm_free_bridges ( struct acpi_bridge *ab) { + if (!ab) + return; + if (ab->child) pciehprm_free_bridges (ab->child); diff -urN linux-2.6.4-rc1/drivers/pci/hotplug/shpchp.h linux-2.6.4-rc2/drivers/pci/hotplug/shpchp.h --- linux-2.6.4-rc1/drivers/pci/hotplug/shpchp.h 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/hotplug/shpchp.h 2004-03-03 22:48:12.000000000 -0800 @@ -154,9 +154,6 @@ /* Define AMD SHPC ID */ #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 -/* Define SHPC CAP ID - not defined in kernel yet */ -#define PCI_CAP_ID_SHPC 0x0C - #define INT_BUTTON_IGNORE 0 #define INT_PRESENCE_ON 1 #define INT_PRESENCE_OFF 2 @@ -390,8 +387,8 @@ /* Sleep for up to 1 second */ schedule_timeout(1*HZ); } else { - /* Sleep for up to 1.5 second */ - schedule_timeout(1.5*HZ); + /* Sleep for up to 2 seconds */ + schedule_timeout(2*HZ); } set_current_state(TASK_RUNNING); remove_wait_queue(&ctrl->queue, &wait); diff -urN linux-2.6.4-rc1/drivers/pci/hotplug/shpchp_ctrl.c linux-2.6.4-rc2/drivers/pci/hotplug/shpchp_ctrl.c --- linux-2.6.4-rc1/drivers/pci/hotplug/shpchp_ctrl.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/hotplug/shpchp_ctrl.c 2004-03-03 22:48:12.000000000 -0800 @@ -192,11 +192,13 @@ /* * Card Present */ + info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); taskInfo->event_type = INT_PRESENCE_ON; } else { /* * Not Present */ + info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); taskInfo->event_type = INT_PRESENCE_OFF; } diff -urN linux-2.6.4-rc1/drivers/pci/hotplug/shpchp_hpc.c linux-2.6.4-rc2/drivers/pci/hotplug/shpchp_hpc.c --- linux-2.6.4-rc1/drivers/pci/hotplug/shpchp_hpc.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/hotplug/shpchp_hpc.c 2004-03-03 22:48:12.000000000 -0800 @@ -1071,9 +1071,14 @@ if (!shpchp_poll_mode) { ctrl = (struct controller *)dev_id; php_ctlr = ctrl->hpc_ctlr_handle; - } else + } else { php_ctlr = (struct php_ctlr_state_s *) dev_id; + ctrl = (struct controller *)php_ctlr->callback_instance_id; + } + if (!ctrl) + return IRQ_NONE; + if (!php_ctlr || !php_ctlr->creg) return IRQ_NONE; @@ -1085,18 +1090,20 @@ dbg("%s: shpc_isr proceeds\n", __FUNCTION__); dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); - /* Mask Global Interrupt Mask - see implementation note on p. 139 */ - /* of SHPC spec rev 1.0*/ - temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); - dbg("%s: Before masking global interrupt, temp_dword = %x\n", - __FUNCTION__, temp_dword); - temp_dword |= 0x00000001; - dbg("%s: After masking global interrupt, temp_dword = %x\n", - __FUNCTION__, temp_dword); - writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); + if(!shpchp_poll_mode) { + /* Mask Global Interrupt Mask - see implementation note on p. 139 */ + /* of SHPC spec rev 1.0*/ + temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + dbg("%s: Before masking global interrupt, temp_dword = %x\n", + __FUNCTION__, temp_dword); + temp_dword |= 0x00000001; + dbg("%s: After masking global interrupt, temp_dword = %x\n", + __FUNCTION__, temp_dword); + writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); - intr_loc2 = readl(php_ctlr->creg + INTR_LOC); - dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); + intr_loc2 = readl(php_ctlr->creg + INTR_LOC); + dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); + } if (intr_loc & 0x0001) { /* @@ -1159,14 +1166,16 @@ dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); } } - /* Unmask Global Interrupt Mask */ - temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); - dbg("%s: 2-Before unmasking global interrupt, temp_dword = %x\n", - __FUNCTION__, temp_dword); - temp_dword &= 0xfffffffe; - dbg("%s: 2-After unmasking global interrupt, temp_dword = %x\n", - __FUNCTION__, temp_dword); - writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); + if (!shpchp_poll_mode) { + /* Unmask Global Interrupt Mask */ + temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + dbg("%s: 2-Before unmasking global interrupt, temp_dword = %x\n", + __FUNCTION__, temp_dword); + temp_dword &= 0xfffffffe; + dbg("%s: 2-After unmasking global interrupt, temp_dword = %x\n", + __FUNCTION__, temp_dword); + writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); + } return IRQ_HANDLED; } diff -urN linux-2.6.4-rc1/drivers/pci/hotplug/shpchprm_acpi.c linux-2.6.4-rc2/drivers/pci/hotplug/shpchprm_acpi.c --- linux-2.6.4-rc1/drivers/pci/hotplug/shpchprm_acpi.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/hotplug/shpchprm_acpi.c 2004-03-03 22:48:12.000000000 -0800 @@ -1187,6 +1187,9 @@ static void shpchprm_free_bridges ( struct acpi_bridge *ab) { + if (!ab) + return; + if (ab->child) shpchprm_free_bridges (ab->child); diff -urN linux-2.6.4-rc1/drivers/pci/pci.c linux-2.6.4-rc2/drivers/pci/pci.c --- linux-2.6.4-rc1/drivers/pci/pci.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/pci.c 2004-03-03 22:48:12.000000000 -0800 @@ -535,11 +535,6 @@ return 0; err_out: - printk (KERN_WARNING "PCI: Unable to reserve %s region #%d:%lx@%lx for device %s\n", - pci_resource_flags(pdev, i) & IORESOURCE_IO ? "I/O" : "mem", - i + 1, /* PCI BAR # */ - pci_resource_len(pdev, i), pci_resource_start(pdev, i), - pci_name(pdev)); while(--i >= 0) pci_release_region(pdev, i); diff -urN linux-2.6.4-rc1/drivers/pci/probe.c linux-2.6.4-rc2/drivers/pci/probe.c --- linux-2.6.4-rc1/drivers/pci/probe.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/probe.c 2004-03-03 22:48:12.000000000 -0800 @@ -366,6 +366,8 @@ child = pci_alloc_child_bus(bus, dev, busnr); child->primary = buses & 0xFF; child->subordinate = (buses >> 16) & 0xFF; + child->bridge_ctl = bctl; + cmax = pci_scan_child_bus(child); if (cmax > max) max = cmax; } else { @@ -400,6 +402,8 @@ pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses); if (!is_cardbus) { + child->bridge_ctl = PCI_BRIDGE_CTL_NO_ISA; + /* Now we can scan all subordinate buses... */ max = pci_scan_child_bus(child); } else { diff -urN linux-2.6.4-rc1/drivers/pci/quirks.c linux-2.6.4-rc2/drivers/pci/quirks.c --- linux-2.6.4-rc1/drivers/pci/quirks.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/quirks.c 2004-03-03 22:48:12.000000000 -0800 @@ -826,7 +826,8 @@ case 0x24df: case 0x25a3: case 0x25b0: - case 0x2562: + case 0x2651: + case 0x2652: break; default: /* we do not handle this PCI device */ diff -urN linux-2.6.4-rc1/drivers/pci/setup-bus.c linux-2.6.4-rc2/drivers/pci/setup-bus.c --- linux-2.6.4-rc1/drivers/pci/setup-bus.c 2004-02-17 19:59:46.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/setup-bus.c 2004-03-03 22:48:12.000000000 -0800 @@ -43,13 +43,15 @@ #define CARDBUS_IO_SIZE (4096) #define CARDBUS_MEM_SIZE (32*1024*1024) -static int __devinit +static void __devinit pbus_assign_resources_sorted(struct pci_bus *bus) { struct pci_dev *dev; struct resource *res; struct resource_list head, *list, *tmp; - int idx, found_vga = 0; + int idx; + + bus->bridge_ctl &= ~PCI_BRIDGE_CTL_VGA; head.next = NULL; list_for_each_entry(dev, &bus->devices, bus_list) { @@ -57,7 +59,7 @@ if (class == PCI_CLASS_DISPLAY_VGA || class == PCI_CLASS_NOT_DEFINED_VGA) - found_vga = 1; + bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA; pdev_sort_resources(dev, &head); } @@ -70,8 +72,6 @@ list = list->next; kfree(tmp); } - - return found_vga; } static void __devinit @@ -211,10 +211,7 @@ /* Clear out the upper 32 bits of PREF base. */ pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0); - /* Check if we have VGA behind the bridge. - Enable ISA in either case (FIXME!). */ - l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ? 0x0c : 0x04; - pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, l); + pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); } /* Check whether the bridge supports optional I/O and @@ -498,13 +495,14 @@ pci_bus_assign_resources(struct pci_bus *bus) { struct pci_bus *b; - int found_vga = pbus_assign_resources_sorted(bus); struct pci_dev *dev; - if (found_vga) { + pbus_assign_resources_sorted(bus); + + if (bus->bridge_ctl & PCI_BRIDGE_CTL_VGA) { /* Propagate presence of the VGA to upstream bridges */ for (b = bus; b->parent; b = b->parent) { - b->resource[0]->flags |= IORESOURCE_BUS_HAS_VGA; + b->bridge_ctl |= PCI_BRIDGE_CTL_VGA; } } list_for_each_entry(dev, &bus->devices, bus_list) { diff -urN linux-2.6.4-rc1/drivers/pci/setup-res.c linux-2.6.4-rc2/drivers/pci/setup-res.c --- linux-2.6.4-rc1/drivers/pci/setup-res.c 2004-02-17 19:59:19.000000000 -0800 +++ linux-2.6.4-rc2/drivers/pci/setup-res.c 2004-03-03 22:48:12.000000000 -0800 @@ -143,8 +143,9 @@ } if (ret) { - printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n", - resno, res->start, res->end, pci_name(dev)); + printk(KERN_ERR "PCI: Failed to allocate %s resource #%d:%lx@%lx for %s\n", + res->flags & IORESOURCE_IO ? "I/O" : "mem", + resno, size, res->start, pci_name(dev)); } else if (resno < PCI_BRIDGE_RESOURCES) { pci_update_resource(dev, res, resno); } diff -urN linux-2.6.4-rc1/drivers/s390/block/Kconfig linux-2.6.4-rc2/drivers/s390/block/Kconfig --- linux-2.6.4-rc1/drivers/s390/block/Kconfig 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/block/Kconfig 2004-03-03 22:48:12.000000000 -0800 @@ -1,3 +1,5 @@ +if ARCH_S390 + comment "S/390 block device drivers" depends on ARCH_S390 @@ -62,3 +64,5 @@ 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 diff -urN linux-2.6.4-rc1/drivers/s390/block/dasd_eckd.c linux-2.6.4-rc2/drivers/s390/block/dasd_eckd.c --- linux-2.6.4-rc1/drivers/s390/block/dasd_eckd.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/block/dasd_eckd.c 2004-03-03 22:48:12.000000000 -0800 @@ -7,7 +7,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.50 $ + * $Revision: 1.51 $ */ #include @@ -85,7 +85,7 @@ ret = dasd_generic_probe (cdev, &dasd_eckd_discipline); if (ret) return ret; - ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); + ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP | CCWDEV_ALLOW_FORCE); return 0; } diff -urN linux-2.6.4-rc1/drivers/s390/block/xpram.c linux-2.6.4-rc2/drivers/s390/block/xpram.c --- linux-2.6.4-rc1/drivers/s390/block/xpram.c 2004-02-17 19:58:53.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/block/xpram.c 2004-03-03 22:48:12.000000000 -0800 @@ -74,9 +74,10 @@ */ static int devs = XPRAM_DEVS; static unsigned int sizes[XPRAM_MAX_DEVS]; +static unsigned int sizes_count; module_param(devs, int, 0); -MODULE_PARM(sizes,"1-" __MODULE_STRING(XPRAM_MAX_DEVS) "i"); +module_param_array(sizes, int, sizes_count, 0); MODULE_PARM_DESC(devs, "number of devices (\"partitions\"), " \ "the default is " __MODULE_STRING(XPRAM_DEVS) "\n"); @@ -492,7 +493,7 @@ } unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME); devfs_remove("slram"); - sys_device_unregister(&xpram_sys_device); + sysdev_unregister(&xpram_sys_device); sysdev_class_unregister(&xpram_sysclass); } @@ -515,14 +516,14 @@ if (rc) return rc; - rc = sys_device_register(&xpram_sys_device); + rc = sysdev_register(&xpram_sys_device); if (rc) { sysdev_class_unregister(&xpram_sysclass); return rc; } rc = xpram_setup_blkdev(); if (rc) - sys_device_unregister(&xpram_sys_device); + sysdev_unregister(&xpram_sys_device); return rc; } diff -urN linux-2.6.4-rc1/drivers/s390/char/Makefile linux-2.6.4-rc2/drivers/s390/char/Makefile --- linux-2.6.4-rc1/drivers/s390/char/Makefile 2004-02-17 19:57:48.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/char/Makefile 2004-03-03 22:48:12.000000000 -0800 @@ -18,6 +18,6 @@ tape-$(CONFIG_S390_TAPE_BLOCK) += tape_block.o tape-$(CONFIG_PROC_FS) += tape_proc.o -tape-objs := tape_core.o tape_std.o tape_char.o $(tape-y) +tape-objs := tape_core.o tape_std.o tape_char.o tape_class.o $(tape-y) obj-$(CONFIG_S390_TAPE) += tape.o obj-$(CONFIG_S390_TAPE_34XX) += tape_34xx.o diff -urN linux-2.6.4-rc1/drivers/s390/char/sclp.c linux-2.6.4-rc2/drivers/s390/char/sclp.c --- linux-2.6.4-rc1/drivers/s390/char/sclp.c 2004-02-17 19:58:33.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/char/sclp.c 2004-03-03 22:48:12.000000000 -0800 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -334,6 +335,8 @@ unsigned long psw_mask; unsigned long cr0, cr0_sync; + /* Need to irq_enter() to prevent BH from executing. */ + irq_enter(); /* * save cr0 * enable service signal external interruption (cr0.22) @@ -362,6 +365,7 @@ /* restore cr0 */ __ctl_load(cr0, 0, 0); + irq_exit(); } /* @@ -467,29 +471,45 @@ * SCLP quiesce event handler */ #ifdef CONFIG_SMP -static cpumask_t cpu_quiesce_map; - static void do_load_quiesce_psw(void * __unused) { psw_t quiesce_psw; + unsigned long status; + int i; - cpu_clear(smp_processor_id(), cpu_quiesce_map); - if (smp_processor_id() == 0) { - /* Wait for all other cpus to enter do_load_quiesce_psw */ - while (!cpus_empty(cpu_quiesce_map)); - /* Quiesce the last cpu with the special psw */ - quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT; - quiesce_psw.addr = 0xfff; - __load_psw(quiesce_psw); + if (smp_processor_id() != 0) + signal_processor(smp_processor_id(), sigp_stop); + /* Wait for all other cpus to enter stopped state */ + i = 1; + while (i < NR_CPUS) { + if (!cpu_online(i)) { + i++; + continue; + } + switch (signal_processor_ps(&status, 0, i, sigp_sense)) { + case sigp_order_code_accepted: + case sigp_status_stored: + /* Check for stopped and check stop state */ + if (test_bit(6, &status) || test_bit(4, &status)) + i++; + break; + case sigp_busy: + break; + case sigp_not_operational: + i++; + break; + } } - signal_processor(smp_processor_id(), sigp_stop); + /* Quiesce the last cpu with the special psw */ + quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT; + quiesce_psw.addr = 0xfff; + __load_psw(quiesce_psw); } static void do_machine_quiesce(void) { - cpu_quiesce_map = cpu_online_map; on_each_cpu(do_load_quiesce_psw, NULL, 0, 0); } #else diff -urN linux-2.6.4-rc1/drivers/s390/char/tape.h linux-2.6.4-rc2/drivers/s390/char/tape.h --- linux-2.6.4-rc1/drivers/s390/char/tape.h 2004-02-17 19:58:43.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/char/tape.h 2004-03-03 22:48:12.000000000 -0800 @@ -60,12 +60,6 @@ #define TAPEBLOCK_HSEC_S2B 2 #define TAPEBLOCK_RETRIES 5 -/* Event types for hotplug */ -#define TAPE_HOTPLUG_CHAR_ADD 1 -#define TAPE_HOTPLUG_BLOCK_ADD 2 -#define TAPE_HOTPLUG_CHAR_REMOVE 3 -#define TAPE_HOTPLUG_BLOCK_REMOVE 4 - enum tape_medium_state { MS_UNKNOWN, MS_LOADED, @@ -205,6 +199,8 @@ struct list_head node; struct ccw_device * cdev; + struct cdev * nt; + struct cdev * rt; /* Device discipline information. */ struct tape_discipline * discipline; diff -urN linux-2.6.4-rc1/drivers/s390/char/tape_block.c linux-2.6.4-rc2/drivers/s390/char/tape_block.c --- linux-2.6.4-rc1/drivers/s390/char/tape_block.c 2004-02-17 19:58:55.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/char/tape_block.c 2004-03-03 22:48:12.000000000 -0800 @@ -259,9 +259,6 @@ INIT_WORK(&blkdat->requeue_task, tapeblock_requeue, tape_get_device_reference(device)); - /* Will vanish */ - tape_hotplug_event(device, tapeblock_major, TAPE_HOTPLUG_BLOCK_ADD); - return 0; cleanup_queue: @@ -274,8 +271,6 @@ void tapeblock_cleanup_device(struct tape_device *device) { - tape_hotplug_event(device, tapeblock_major, TAPE_HOTPLUG_BLOCK_REMOVE); - flush_scheduled_work(); device->blk_data.requeue_task.data = tape_put_device(device); diff -urN linux-2.6.4-rc1/drivers/s390/char/tape_char.c linux-2.6.4-rc2/drivers/s390/char/tape_char.c --- linux-2.6.4-rc1/drivers/s390/char/tape_char.c 2004-02-17 19:59:05.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/char/tape_char.c 2004-03-03 22:48:12.000000000 -0800 @@ -20,6 +20,7 @@ #include "tape.h" #include "tape_std.h" +#include "tape_class.h" #define PRINTK_HEADER "TAPE_CHAR: " @@ -47,20 +48,50 @@ static int tapechar_major = TAPECHAR_MAJOR; +struct cdev * +tapechar_register_tape_dev(struct tape_device *device, char *name, int i) +{ + struct cdev * cdev; + char devname[11]; + + sprintf(devname, "%s%i", name, i / 2); + cdev = register_tape_dev( + &device->cdev->dev, + MKDEV(tapechar_major, i), + &tape_fops, + devname + ); + + return ((IS_ERR(cdev)) ? NULL : cdev); +} + /* * This function is called for every new tapedevice */ int tapechar_setup_device(struct tape_device * device) { - tape_hotplug_event(device, tapechar_major, TAPE_HOTPLUG_CHAR_ADD); + device->nt = tapechar_register_tape_dev( + device, + "ntibm", + device->first_minor + ); + device->rt = tapechar_register_tape_dev( + device, + "rtibm", + device->first_minor + 1 + ); + return 0; } void tapechar_cleanup_device(struct tape_device *device) { - tape_hotplug_event(device, tapechar_major, TAPE_HOTPLUG_CHAR_REMOVE); + unregister_tape_dev(device->rt); + device->rt = NULL; + unregister_tape_dev(device->nt); + device->nt = NULL; } /* @@ -461,20 +492,17 @@ int tapechar_init (void) { - int rc; + dev_t dev; - /* Register the tape major number to the kernel */ - rc = register_chrdev(tapechar_major, "tape", &tape_fops); - if (rc < 0) { - PRINT_ERR("can't get major %d\n", tapechar_major); - DBF_EVENT(3, "TCHAR:initfail\n"); - return rc; - } - if (tapechar_major == 0) - tapechar_major = rc; /* accept dynamic major number */ - PRINT_ERR("Tape gets major %d for char device\n", tapechar_major); - DBF_EVENT(3, "Tape gets major %d for char device\n", rc); - DBF_EVENT(3, "TCHAR:init ok\n"); + if (alloc_chrdev_region(&dev, 0, 256, "tape") != 0) + return -1; + + tapechar_major = MAJOR(dev); + PRINT_INFO("tape gets major %d for character devices\n", MAJOR(dev)); + +#ifdef TAPE390_INTERNAL_CLASS + tape_setup_class(); +#endif return 0; } @@ -484,5 +512,10 @@ void tapechar_exit(void) { - unregister_chrdev (tapechar_major, "tape"); +#ifdef TAPE390_INTERNAL_CLASS + tape_cleanup_class(); +#endif + PRINT_INFO("tape releases major %d for character devices\n", + tapechar_major); + unregister_chrdev_region(MKDEV(tapechar_major, 0), 256); } diff -urN linux-2.6.4-rc1/drivers/s390/char/tape_class.c linux-2.6.4-rc2/drivers/s390/char/tape_class.c --- linux-2.6.4-rc1/drivers/s390/char/tape_class.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/char/tape_class.c 2004-03-03 22:48:12.000000000 -0800 @@ -0,0 +1,100 @@ +/* + * Tape class device support + * + * Author: Stefan Bader + * Based on simple class device code by Greg K-H + */ +#include "tape_class.h" + +#ifndef TAPE390_INTERNAL_CLASS +MODULE_AUTHOR("Stefan Bader "); +MODULE_DESCRIPTION("Tape class"); +MODULE_LICENSE("GPL"); +#endif + +struct class_simple *tape_class; + +/* + * Register a tape device and return a pointer to the cdev structure. + * + * device + * The pointer to the struct device of the physical (base) device. + * drivername + * The pointer to the drivers name for it's character devices. + * dev + * The intended major/minor number. The major number may be 0 to + * get a dynamic major number. + * fops + * The pointer to the drivers file operations for the tape device. + * devname + * The pointer to the name of the character device. + */ +struct cdev *register_tape_dev( + struct device * device, + dev_t dev, + struct file_operations *fops, + char * devname +) { + struct cdev * cdev; + int rc; + char * s; + + cdev = cdev_alloc(); + if (!cdev) + return ERR_PTR(-ENOMEM); + + cdev->owner = fops->owner; + cdev->ops = fops; + cdev->dev = dev; + strcpy(cdev->kobj.name, devname); + for (s = strchr(cdev->kobj.name, '/'); s; s = strchr(s, '/')) + *s = '!'; + + rc = cdev_add(cdev, cdev->dev, 1); + if (rc) { + kobject_put(&cdev->kobj); + return ERR_PTR(rc); + } + class_simple_device_add(tape_class, cdev->dev, device, "%s", devname); + + return cdev; +} +EXPORT_SYMBOL(register_tape_dev); + +void unregister_tape_dev(struct cdev *cdev) +{ + if (cdev != NULL) { + class_simple_device_remove(cdev->dev); + cdev_del(cdev); + } +} +EXPORT_SYMBOL(unregister_tape_dev); + + +#ifndef TAPE390_INTERNAL_CLASS +static int __init tape_init(void) +#else +int tape_setup_class(void) +#endif +{ + tape_class = class_simple_create(THIS_MODULE, "tape390"); + return 0; +} + +#ifndef TAPE390_INTERNAL_CLASS +static void __exit tape_exit(void) +#else +void tape_cleanup_class(void) +#endif +{ + class_simple_destroy(tape_class); + tape_class = NULL; +} + +#ifndef TAPE390_INTERNAL_CLASS +postcore_initcall(tape_init); +module_exit(tape_exit); +#else +EXPORT_SYMBOL(tape_setup_class); +EXPORT_SYMBOL(tape_cleanup_class); +#endif diff -urN linux-2.6.4-rc1/drivers/s390/char/tape_class.h linux-2.6.4-rc2/drivers/s390/char/tape_class.h --- linux-2.6.4-rc1/drivers/s390/char/tape_class.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/char/tape_class.h 2004-03-03 22:48:12.000000000 -0800 @@ -0,0 +1,54 @@ +/* + * Tape class device support + * + * Author: Stefan Bader + * Based on simple class device code by Greg K-H + */ +#ifndef __TAPE_CLASS_H__ +#define __TAPE_CLASS_H__ + +#if 0 +#include +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#define TAPE390_INTERNAL_CLASS + +/* + * Register a tape device and return a pointer to the cdev structure. + * + * device + * The pointer to the struct device of the physical (base) device. + * drivername + * The pointer to the drivers name for it's character devices. + * dev + * The intended major/minor number. The major number may be 0 to + * get a dynamic major number. + * fops + * The pointer to the drivers file operations for the tape device. + * devname + * The pointer to the name of the character device. + */ +struct cdev *register_tape_dev( + struct device * device, + dev_t dev, + struct file_operations *fops, + char * devname +); +void unregister_tape_dev(struct cdev *cdev); + +#ifdef TAPE390_INTERNAL_CLASS +int tape_setup_class(void); +void tape_cleanup_class(void); +#endif + +#endif /* __TAPE_CLASS_H__ */ diff -urN linux-2.6.4-rc1/drivers/s390/char/tape_core.c linux-2.6.4-rc2/drivers/s390/char/tape_core.c --- linux-2.6.4-rc1/drivers/s390/char/tape_core.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/char/tape_core.c 2004-03-03 22:48:12.000000000 -0800 @@ -237,10 +237,7 @@ rc = 0; for (retries = 0; retries < 5; retries++) { - if (retries < 2) - rc = ccw_device_halt(device->cdev, (long) request); - else - rc = ccw_device_clear(device->cdev, (long) request); + rc = ccw_device_clear(device->cdev, (long) request); if (rc == 0) { /* Termination successful */ request->rc = -EIO; @@ -1016,63 +1013,6 @@ } /* - * Hutplug event support. - */ -void -tape_hotplug_event(struct tape_device *device, int devmaj, int action) { -#ifdef CONFIG_HOTPLUG - char *argv[3]; - char *envp[8]; - char busid[20]; - char major[20]; - char minor[20]; - - /* Call the busid DEVNO to be compatible with old tape.agent. */ - sprintf(busid, "DEVNO=%s", device->cdev->dev.bus_id); - sprintf(major, "MAJOR=%d", devmaj); - sprintf(minor, "MINOR=%d", device->first_minor); - - argv[0] = hotplug_path; - argv[1] = "tape"; - argv[2] = NULL; - - envp[0] = "HOME=/"; - envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; - - switch (action) { - case TAPE_HOTPLUG_CHAR_ADD: - case TAPE_HOTPLUG_BLOCK_ADD: - envp[2] = "ACTION=add"; - break; - case TAPE_HOTPLUG_CHAR_REMOVE: - case TAPE_HOTPLUG_BLOCK_REMOVE: - envp[2] = "ACTION=remove"; - break; - default: - BUG(); - } - switch (action) { - case TAPE_HOTPLUG_CHAR_ADD: - case TAPE_HOTPLUG_CHAR_REMOVE: - envp[3] = "INTERFACE=char"; - break; - case TAPE_HOTPLUG_BLOCK_ADD: - case TAPE_HOTPLUG_BLOCK_REMOVE: - envp[3] = "INTERFACE=block"; - break; - default: - BUG(); - } - envp[4] = busid; - envp[5] = major; - envp[6] = minor; - envp[7] = NULL; - - call_usermodehelper(argv[0], argv, envp, 0); -#endif -} - -/* * Tape init function. */ static int @@ -1083,7 +1023,7 @@ #ifdef DBF_LIKE_HELL debug_set_level(tape_dbf_area, 6); #endif - DBF_EVENT(3, "tape init: ($Revision: 1.41 $)\n"); + DBF_EVENT(3, "tape init: ($Revision: 1.44 $)\n"); tape_proc_init(); tapechar_init (); tapeblock_init (); @@ -1108,7 +1048,7 @@ MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and " "Michael Holzheu (cotte@de.ibm.com,holzheu@de.ibm.com)"); MODULE_DESCRIPTION("Linux on zSeries channel attached " - "tape device driver ($Revision: 1.41 $)"); + "tape device driver ($Revision: 1.44 $)"); MODULE_LICENSE("GPL"); module_init(tape_init); diff -urN linux-2.6.4-rc1/drivers/s390/cio/ccwgroup.c linux-2.6.4-rc2/drivers/s390/cio/ccwgroup.c --- linux-2.6.4-rc1/drivers/s390/cio/ccwgroup.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/cio/ccwgroup.c 2004-03-03 22:48:12.000000000 -0800 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/ccwgroup.c * bus driver for ccwgroup - * $Revision: 1.23 $ + * $Revision: 1.24 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -293,22 +293,28 @@ ccwgroup_online_store (struct device *dev, const char *buf, size_t count) { struct ccwgroup_device *gdev; + struct ccwgroup_driver *gdrv; unsigned int value; + int ret; gdev = to_ccwgroupdev(dev); if (!dev->driver) return count; - value = simple_strtoul(buf, 0, 0); + gdrv = to_ccwgroupdrv (gdev->dev.driver); + if (!try_module_get(gdrv->owner)) + return -EINVAL; + value = simple_strtoul(buf, 0, 0); + ret = count; if (value == 1) ccwgroup_set_online(gdev); else if (value == 0) ccwgroup_set_offline(gdev); else - return -EINVAL; - - return count; + ret = -EINVAL; + module_put(gdrv->owner); + return ret; } static ssize_t diff -urN linux-2.6.4-rc1/drivers/s390/cio/cmf.c linux-2.6.4-rc2/drivers/s390/cio/cmf.c --- linux-2.6.4-rc1/drivers/s390/cio/cmf.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/cio/cmf.c 2004-03-03 22:48:12.000000000 -0800 @@ -1,5 +1,5 @@ /* - * linux/drivers/s390/cio/cmf.c ($Revision: 1.11 $) + * linux/drivers/s390/cio/cmf.c ($Revision: 1.13 $) * * Linux on zSeries Channel Measurement Facility support * @@ -138,7 +138,7 @@ if (count == 0) return 0; - /* value comes in units of 128 5sec */ + /* value comes in units of 128 µsec */ ret = time_to_nsec(value); do_div(ret, count); @@ -390,12 +390,13 @@ WARN_ON(!list_empty(&cmb_area.list)); spin_unlock(&cmb_area.lock); - mem = kmalloc(size, GFP_KERNEL | GFP_DMA); + mem = (void*)__get_free_pages(GFP_KERNEL | GFP_DMA, + get_order(size)); spin_lock(&cmb_area.lock); if (cmb_area.mem) { /* ok, another thread was faster */ - kfree(mem); + free_pages((unsigned long)mem, get_order(size)); } else if (!mem) { /* no luck */ ret = -ENOMEM; @@ -435,8 +436,10 @@ list_del_init(&priv->cmb_list); if (list_empty(&cmb_area.list)) { + ssize_t size; + size = sizeof(struct cmb) * cmb_area.num_channels; cmf_activate(NULL, 0); - kfree(cmb_area.mem); + free_pages((unsigned long)cmb_area.mem, get_order(size)); cmb_area.mem = NULL; } out: @@ -595,11 +598,22 @@ u32 reserved[7]; }; +/* kmalloc only guarantees 8 byte alignment, but we need cmbe + * pointers to be naturally aligned. Make sure to allocate + * enough space for two cmbes */ +static inline struct cmbe* cmbe_align(struct cmbe *c) +{ + unsigned long addr; + addr = ((unsigned long)c + sizeof (struct cmbe) - sizeof(long)) & + ~(sizeof (struct cmbe) - sizeof(long)); + return (struct cmbe*)addr; +} + static int alloc_cmbe (struct ccw_device *cdev) { struct cmbe *cmbe; - cmbe = kmalloc (sizeof (*cmbe), GFP_KERNEL /* | GFP_DMA ? */); + cmbe = kmalloc (sizeof (*cmbe) * 2, GFP_KERNEL); if (!cmbe) return -ENOMEM; @@ -647,7 +661,7 @@ if (!cdev->private->cmb) return -EINVAL; - mba = mme ? (unsigned long)cdev->private->cmb : 0; + mba = mme ? (unsigned long) cmbe_align(cdev->private->cmb) : 0; return set_schib_wait(cdev, mme, 1, mba); } @@ -669,7 +683,7 @@ return 0; } - cmb = *(struct cmbe*)cdev->private->cmb; + cmb = *cmbe_align(cdev->private->cmb); spin_unlock_irqrestore(cdev->ccwlock, flags); switch (index) { @@ -720,7 +734,7 @@ return -ENODEV; } - cmb = *(struct cmbe*)cdev->private->cmb; + cmb = *cmbe_align(cdev->private->cmb); time = get_clock() - cdev->private->cmb_start_time; spin_unlock_irqrestore(cdev->ccwlock, flags); @@ -760,7 +774,7 @@ { struct cmbe *cmb; spin_lock_irq(cdev->ccwlock); - cmb = cdev->private->cmb; + cmb = cmbe_align(cdev->private->cmb); if (cmb) memset (cmb, 0, sizeof (*cmb)); cdev->private->cmb_start_time = get_clock(); diff -urN linux-2.6.4-rc1/drivers/s390/cio/css.h linux-2.6.4-rc2/drivers/s390/cio/css.h --- linux-2.6.4-rc1/drivers/s390/cio/css.h 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/cio/css.h 2004-03-03 22:48:12.000000000 -0800 @@ -74,6 +74,7 @@ unsigned int fast:1; /* post with "channel end" */ unsigned int repall:1; /* report every interrupt status */ unsigned int pgroup:1; /* do path grouping */ + unsigned int force:1; /* allow forced online */ } __attribute__ ((packed)) options; struct { unsigned int pgid_single:1; /* use single path for Set PGID */ diff -urN linux-2.6.4-rc1/drivers/s390/cio/device.c linux-2.6.4-rc2/drivers/s390/cio/device.c --- linux-2.6.4-rc1/drivers/s390/cio/device.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/cio/device.c 2004-03-03 22:48:12.000000000 -0800 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/device.c * bus driver for ccw devices - * $Revision: 1.103 $ + * $Revision: 1.107 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -263,10 +263,10 @@ if (!cdev) return -ENODEV; - if (!cdev->online || !cdev->drv) + if (!cdev->online) return -EINVAL; - if (cdev->drv->set_offline) { + if (cdev->drv && cdev->drv->set_offline) { ret = cdev->drv->set_offline(cdev); if (ret != 0) return ret; @@ -292,7 +292,7 @@ if (!cdev) return -ENODEV; - if (cdev->online || !cdev->drv) + if (cdev->online) return -EINVAL; spin_lock_irq(cdev->ccwlock); @@ -307,7 +307,8 @@ } if (cdev->private->state != DEV_STATE_ONLINE) return -ENODEV; - if (!cdev->drv->set_online || cdev->drv->set_online(cdev) == 0) { + if (!cdev->drv || !cdev->drv->set_online || + cdev->drv->set_online(cdev) == 0) { cdev->online = 1; return 0; } @@ -326,52 +327,54 @@ online_store (struct device *dev, const char *buf, size_t count) { struct ccw_device *cdev = to_ccwdev(dev); - int i; + int i, force; char *tmp; - if (!cdev->drv) - return count; if (atomic_compare_and_swap(0, 1, &cdev->private->onoff)) return -EAGAIN; - i = simple_strtoul(buf, &tmp, 16); - if (i == 1 && cdev->drv->set_online) + if (cdev->drv && !try_module_get(cdev->drv->owner)) { + atomic_set(&cdev->private->onoff, 0); + return -EINVAL; + } + if (!strncmp(buf, "force\n", count)) { + force = 1; + i = 1; + } else { + force = 0; + i = simple_strtoul(buf, &tmp, 16); + } + if (i == 1) { + /* Do device recognition, if needed. */ + if (cdev->id.cu_type == 0) { + ccw_device_recognition(cdev); + wait_event(cdev->private->wait_q, + dev_fsm_final_state(cdev)); + } ccw_device_set_online(cdev); - else if (i == 0 && cdev->drv->set_offline) { + } else if (i == 0) { if (cdev->private->state == DEV_STATE_DISCONNECTED) ccw_device_remove_disconnected(cdev); else ccw_device_set_offline(cdev); } - atomic_set(&cdev->private->onoff, 0); - return count; -} - -static void ccw_device_unbox_recog(void *data); - -static ssize_t -stlck_store(struct device *dev, const char *buf, size_t count) -{ - struct ccw_device *cdev = to_ccwdev(dev); - int ret; - - /* We don't care what was piped to the attribute 8) */ - ret = ccw_device_stlck(cdev); - if (ret != 0) { - printk(KERN_WARNING - "Unconditional reserve failed on device %s, rc=%d\n", - dev->bus_id, ret); - return ret; + if (force && cdev->private->state == DEV_STATE_BOXED) { + int ret; + ret = ccw_device_stlck(cdev); + if (ret) + goto out; + /* Do device recognition, if needed. */ + if (cdev->id.cu_type == 0) { + ccw_device_recognition(cdev); + wait_event(cdev->private->wait_q, + dev_fsm_final_state(cdev)); + } + ccw_device_set_online(cdev); } - - /* - * Device was successfully unboxed. - * Trigger removal of stlck attribute and device recognition. - */ - INIT_WORK(&cdev->private->kick_work, - ccw_device_unbox_recog, (void *) cdev); - queue_work(ccw_device_work, &cdev->private->kick_work); - + out: + if (cdev->drv) + module_put(cdev->drv->owner); + atomic_set(&cdev->private->onoff, 0); return count; } @@ -403,33 +406,9 @@ static DEVICE_ATTR(devtype, 0444, devtype_show, NULL); static DEVICE_ATTR(cutype, 0444, cutype_show, NULL); static DEVICE_ATTR(online, 0644, online_show, online_store); -static DEVICE_ATTR(steal_lock, 0200, NULL, stlck_store); extern struct device_attribute dev_attr_cmb_enable; static DEVICE_ATTR(availability, 0444, available_show, NULL); -/* A device has been unboxed. Start device recognition. */ -static void -ccw_device_unbox_recog(void *data) -{ - struct ccw_device *cdev; - - cdev = (struct ccw_device *)data; - if (!cdev) - return; - - /* Remove stlck attribute. */ - device_remove_file(&cdev->dev, &dev_attr_steal_lock); - - spin_lock_irq(cdev->ccwlock); - - /* Device is no longer boxed. */ - cdev->private->state = DEV_STATE_NOT_OPER; - - /* Finally start device recognition. */ - ccw_device_recognition(cdev); - spin_unlock_irq(cdev->ccwlock); -} - static struct attribute * subch_attrs[] = { &dev_attr_chpids.attr, &dev_attr_pimpampom.attr, @@ -471,22 +450,6 @@ sysfs_remove_group(&dev->kobj, &ccwdev_attr_group); } -/* - * Add a "steal lock" attribute to boxed devices. - * This allows to trigger an unconditional reserve ccw to eckd dasds - * (if the device is something else, there should be no problems more than - * a command reject; we don't have any means of finding out the device's - * type if it was boxed at ipl/attach for older devices and under VM). - */ -void -ccw_device_add_stlck(void *data) -{ - struct ccw_device *cdev; - - cdev = (struct ccw_device *)data; - device_create_file(&cdev->dev, &dev_attr_steal_lock); -} - /* this is a simple abstraction for device_register that sets the * correct bus type and adds the bus specific files */ int @@ -565,8 +528,6 @@ if (ret) printk(KERN_WARNING "%s: could not add attributes to %s\n", __func__, sch->dev.bus_id); - if (cdev->private->state == DEV_STATE_BOXED) - device_create_file(&cdev->dev, &dev_attr_steal_lock); put_device(&cdev->dev); out: put_device(&sch->dev); @@ -935,6 +896,7 @@ pr_debug("ccw_device_offline returned %d, device %s\n", ret, cdev->dev.bus_id); } + ccw_device_set_timeout(cdev, 0); cdev->drv = 0; return 0; } diff -urN linux-2.6.4-rc1/drivers/s390/cio/device.h linux-2.6.4-rc2/drivers/s390/cio/device.h --- linux-2.6.4-rc1/drivers/s390/cio/device.h 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/cio/device.h 2004-03-03 22:48:12.000000000 -0800 @@ -102,7 +102,6 @@ int ccw_device_call_handler(struct ccw_device *); -void ccw_device_add_stlck(void *); int ccw_device_stlck(struct ccw_device *); /* qdio needs this. */ diff -urN linux-2.6.4-rc1/drivers/s390/cio/device_fsm.c linux-2.6.4-rc2/drivers/s390/cio/device_fsm.c --- linux-2.6.4-rc1/drivers/s390/cio/device_fsm.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/cio/device_fsm.c 2004-03-03 22:48:12.000000000 -0800 @@ -317,14 +317,10 @@ cdev->private->state = state; - if (state == DEV_STATE_BOXED) { + if (state == DEV_STATE_BOXED) CIO_DEBUG(KERN_WARNING, 2, "Boxed device %04x on subchannel %04x\n", cdev->private->devno, sch->irq); - INIT_WORK(&cdev->private->kick_work, - ccw_device_add_stlck, (void *) cdev); - queue_work(ccw_device_work, &cdev->private->kick_work); - } if (cdev->private->flags.donotify) { cdev->private->flags.donotify = 0; @@ -377,7 +373,8 @@ struct subchannel *sch; int ret; - if (cdev->private->state != DEV_STATE_NOT_OPER) + if ((cdev->private->state != DEV_STATE_NOT_OPER) && + (cdev->private->state != DEV_STATE_BOXED)) return -EINVAL; sch = to_subchannel(cdev->dev.parent); ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc); @@ -492,7 +489,8 @@ struct subchannel *sch; int ret; - if (cdev->private->state != DEV_STATE_OFFLINE) + if ((cdev->private->state != DEV_STATE_OFFLINE) && + (cdev->private->state != DEV_STATE_BOXED)) return -EINVAL; sch = to_subchannel(cdev->dev.parent); if (css_init_done && !get_device(&cdev->dev)) @@ -615,6 +613,13 @@ struct subchannel *sch; sch = to_subchannel(cdev->dev.parent); + if (sch->driver->notify && + sch->driver->notify(&sch->dev, sch->lpm ? CIO_GONE : CIO_NO_PATH)) { + ccw_device_set_timeout(cdev, 0); + cdev->private->state = DEV_STATE_DISCONNECTED; + wake_up(&cdev->private->wait_q); + return; + } cdev->private->state = DEV_STATE_NOT_OPER; cio_disable_subchannel(sch); if (sch->schib.scsw.actl != 0) { @@ -627,21 +632,6 @@ wake_up(&cdev->private->wait_q); } -static void -ccw_device_disconnected_notoper(struct ccw_device *cdev, - enum dev_event dev_event) -{ - struct subchannel *sch; - - sch = to_subchannel(cdev->dev.parent); - cdev->private->state = DEV_STATE_NOT_OPER; - cio_disable_subchannel(sch); - device_unregister(&sch->dev); - sch->schib.pmcw.intparm = 0; - cio_modify(sch); - wake_up(&cdev->private->wait_q); -} - /* * Handle path verification event. */ @@ -1103,7 +1093,7 @@ }, /* special states for devices gone not operational */ [DEV_STATE_DISCONNECTED] { - [DEV_EVENT_NOTOPER] ccw_device_disconnected_notoper, + [DEV_EVENT_NOTOPER] ccw_device_nop, [DEV_EVENT_INTERRUPT] ccw_device_start_id, [DEV_EVENT_TIMEOUT] ccw_device_bug, [DEV_EVENT_VERIFY] ccw_device_nop, diff -urN linux-2.6.4-rc1/drivers/s390/cio/device_ops.c linux-2.6.4-rc2/drivers/s390/cio/device_ops.c --- linux-2.6.4-rc1/drivers/s390/cio/device_ops.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/cio/device_ops.c 2004-03-03 22:48:12.000000000 -0800 @@ -38,6 +38,7 @@ cdev->private->options.fast = (flags & CCWDEV_EARLY_NOTIFICATION) != 0; cdev->private->options.repall = (flags & CCWDEV_REPORT_ALL) != 0; cdev->private->options.pgroup = (flags & CCWDEV_DO_PATHGROUP) != 0; + cdev->private->options.force = (flags & CCWDEV_ALLOW_FORCE) != 0; return 0; } @@ -453,6 +454,9 @@ if (!cdev) return -ENODEV; + if (cdev->drv && !cdev->private->options.force) + return -EINVAL; + sch = to_subchannel(cdev->dev.parent); CIO_TRACE_EVENT(2, "stl lock"); diff -urN linux-2.6.4-rc1/drivers/s390/net/ctcmain.c linux-2.6.4-rc2/drivers/s390/net/ctcmain.c --- linux-2.6.4-rc1/drivers/s390/net/ctcmain.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/net/ctcmain.c 2004-03-03 22:48:12.000000000 -0800 @@ -1,5 +1,5 @@ /* - * $Id: ctcmain.c,v 1.54 2004/02/18 12:35:59 ptiedem Exp $ + * $Id: ctcmain.c,v 1.56 2004/02/27 17:53:26 mschwide Exp $ * * CTC / ESCON network driver * @@ -36,7 +36,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.54 $ + * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.56 $ * */ @@ -319,7 +319,7 @@ print_banner(void) { static int printed = 0; - char vbuf[] = "$Revision: 1.54 $"; + char vbuf[] = "$Revision: 1.56 $"; char *version = vbuf; if (printed) @@ -3161,6 +3161,7 @@ } static struct ccwgroup_driver ctc_group_driver = { + .owner = THIS_MODULE, .name = "ctc", .max_slaves = 2, .driver_id = 0xC3E3C3, diff -urN linux-2.6.4-rc1/drivers/s390/net/lcs.c linux-2.6.4-rc2/drivers/s390/net/lcs.c --- linux-2.6.4-rc1/drivers/s390/net/lcs.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/net/lcs.c 2004-03-03 22:48:12.000000000 -0800 @@ -11,7 +11,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Martin Schwidefsky * - * $Revision: 1.66 $ $Date: 2004/02/19 13:46:01 $ + * $Revision: 1.67 $ $Date: 2004/02/26 18:26:50 $ * * 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 @@ -58,7 +58,7 @@ /** * initialization string for output */ -#define VERSION_LCS_C "$Revision: 1.66 $" +#define VERSION_LCS_C "$Revision: 1.67 $" static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")"; @@ -1926,6 +1926,7 @@ * LCS ccwgroup driver registration */ static struct ccwgroup_driver lcs_group_driver = { + .owner = THIS_MODULE, .name = "lcs", .max_slaves = 2, .driver_id = 0xD3C3E2, diff -urN linux-2.6.4-rc1/drivers/s390/net/qeth.c linux-2.6.4-rc2/drivers/s390/net/qeth.c --- linux-2.6.4-rc1/drivers/s390/net/qeth.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/s390/net/qeth.c 2004-03-03 22:48:12.000000000 -0800 @@ -10773,6 +10773,7 @@ } static struct ccwgroup_driver qeth_ccwgroup_driver = { + .owner = THIS_MODULE, .name = "qeth", .driver_id = 0xD8C5E3C8, .probe = qeth_probe_device, diff -urN linux-2.6.4-rc1/drivers/scsi/BusLogic.c linux-2.6.4-rc2/drivers/scsi/BusLogic.c --- linux-2.6.4-rc1/drivers/scsi/BusLogic.c 2004-02-17 19:59:33.000000000 -0800 +++ linux-2.6.4-rc2/drivers/scsi/BusLogic.c 2004-03-03 22:48:12.000000000 -0800 @@ -189,7 +189,7 @@ 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) { diff -urN linux-2.6.4-rc1/drivers/scsi/ata_piix.c linux-2.6.4-rc2/drivers/scsi/ata_piix.c --- linux-2.6.4-rc1/drivers/scsi/ata_piix.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/scsi/ata_piix.c 2004-03-03 22:48:12.000000000 -0800 @@ -80,7 +80,9 @@ * and enhanced mode, with queueing and other fancy stuff. * This is distinguished by PCI class code. */ - { 0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, + { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich5_sata }, + { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich5_sata }, { } /* terminate list */ diff -urN linux-2.6.4-rc1/drivers/scsi/libata-core.c linux-2.6.4-rc2/drivers/scsi/libata-core.c --- linux-2.6.4-rc1/drivers/scsi/libata-core.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/scsi/libata-core.c 2004-03-03 22:48:12.000000000 -0800 @@ -2005,6 +2005,14 @@ goto out; } + /* hack alert! We cannot use the supplied completion + * function from inside the ->eh_strategy_handler() thread. + * libata is the only user of ->eh_strategy_handler() in + * any kernel, so the default scsi_done() assumes it is + * not being called from the SCSI EH. + */ + qc->scsidone = scsi_finish_command; + switch (qc->tf.protocol) { case ATA_PROT_DMA_READ: case ATA_PROT_DMA_WRITE: diff -urN linux-2.6.4-rc1/drivers/scsi/scsi.c linux-2.6.4-rc2/drivers/scsi/scsi.c --- linux-2.6.4-rc1/drivers/scsi/scsi.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/scsi/scsi.c 2004-03-03 22:48:12.000000000 -0800 @@ -847,6 +847,7 @@ cmd->done(cmd); } +EXPORT_SYMBOL(scsi_finish_command); /* * Function: scsi_adjust_queue_depth() diff -urN linux-2.6.4-rc1/drivers/scsi/scsi_priv.h linux-2.6.4-rc2/drivers/scsi/scsi_priv.h --- linux-2.6.4-rc1/drivers/scsi/scsi_priv.h 2004-02-17 19:58:43.000000000 -0800 +++ linux-2.6.4-rc2/drivers/scsi/scsi_priv.h 2004-03-03 22:48:12.000000000 -0800 @@ -77,7 +77,6 @@ extern int scsi_setup_command_freelist(struct Scsi_Host *shost); extern void scsi_destroy_command_freelist(struct Scsi_Host *shost); extern void scsi_done(struct scsi_cmnd *cmd); -extern void scsi_finish_command(struct scsi_cmnd *cmd); extern int scsi_retry_command(struct scsi_cmnd *cmd); extern int scsi_insert_special_req(struct scsi_request *sreq, int); extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, diff -urN linux-2.6.4-rc1/drivers/usb/class/usblp.c linux-2.6.4-rc2/drivers/usb/class/usblp.c --- linux-2.6.4-rc1/drivers/usb/class/usblp.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/usb/class/usblp.c 2004-03-03 22:48:12.000000000 -0800 @@ -603,7 +603,7 @@ { DECLARE_WAITQUEUE(wait, current); struct usblp *usblp = file->private_data; - int timeout, err = 0, transfer_length; + int timeout, err = 0, transfer_length = 0; size_t writecount = 0; while (writecount < count) { @@ -654,6 +654,16 @@ continue; } + /* We must increment writecount here, and not at the + * end of the loop. Otherwise, the final loop iteration may + * be skipped, leading to incomplete printer output. + */ + writecount += transfer_length; + if (writecount == count) { + up(&usblp->sem); + break; + } + transfer_length=(count - writecount); if (transfer_length > USBLP_BUF_SIZE) transfer_length = USBLP_BUF_SIZE; @@ -677,8 +687,6 @@ break; } up (&usblp->sem); - - writecount += transfer_length; } return count; diff -urN linux-2.6.4-rc1/drivers/usb/host/ohci-hcd.c linux-2.6.4-rc2/drivers/usb/host/ohci-hcd.c --- linux-2.6.4-rc1/drivers/usb/host/ohci-hcd.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/usb/host/ohci-hcd.c 2004-03-03 22:48:12.000000000 -0800 @@ -229,11 +229,21 @@ goto fail; } + /* in case of unlink-during-submit */ + spin_lock (&urb->lock); + if (urb->status != -EINPROGRESS) { + spin_unlock (&urb->lock); + + finish_urb (ohci, urb, 0); + retval = 0; + goto fail; + } + /* schedule the ed if needed */ if (ed->state == ED_IDLE) { retval = ed_schedule (ohci, ed); if (retval < 0) - goto fail; + goto fail0; if (ed->type == PIPE_ISOCHRONOUS) { u16 frame = OHCI_FRAME_NO(ohci->hcca); @@ -257,6 +267,8 @@ urb->hcpriv = urb_priv; td_submit_urb (ohci, urb); +fail0: + spin_unlock (&urb->lock); fail: if (retval) urb_free_priv (ohci, urb_priv); diff -urN linux-2.6.4-rc1/drivers/usb/host/ohci-q.c linux-2.6.4-rc2/drivers/usb/host/ohci-q.c --- linux-2.6.4-rc1/drivers/usb/host/ohci-q.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/usb/host/ohci-q.c 2004-03-03 22:48:12.000000000 -0800 @@ -331,19 +331,6 @@ periodic_unlink (ohci, ed); break; } - - /* NOTE: Except for a couple of exceptionally clean unlink cases - * (like unlinking the only c/b ED, with no TDs) HCs may still be - * caching this operational ED (or its address). Safe unlinking - * involves not marking it ED_IDLE till INTR_SF; we always do that - * if td_list isn't empty. Otherwise the race is small; but ... - */ - if (ed->state == ED_OPER) { - ed->state = ED_IDLE; - ed->hwINFO &= ~(ED_SKIP | ED_DEQUEUE); - ed->hwHeadP &= ~ED_H; - wmb (); - } } @@ -665,6 +652,7 @@ /* start periodic dma if needed */ if (periodic) { + wmb (); ohci->hc_control |= OHCI_CTRL_PLE|OHCI_CTRL_IE; writel (ohci->hc_control, &ohci->regs->control); } @@ -1053,7 +1041,7 @@ /* clean schedule: unlink EDs that are no longer busy */ if (list_empty (&ed->td_list)) - ed_deschedule (ohci, ed); + start_ed_unlink (ohci, ed); /* ... reenabling halted EDs only after fault cleanup */ else if ((ed->hwINFO & (ED_SKIP | ED_DEQUEUE)) == ED_SKIP) { td = list_entry (ed->td_list.next, struct td, td_list); diff -urN linux-2.6.4-rc1/drivers/usb/host/ohci-sa1111.c linux-2.6.4-rc2/drivers/usb/host/ohci-sa1111.c --- linux-2.6.4-rc1/drivers/usb/host/ohci-sa1111.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/usb/host/ohci-sa1111.c 2004-03-03 22:48:12.000000000 -0800 @@ -105,7 +105,7 @@ } #endif -static void usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r) +static irqreturn_t usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r) { struct usb_hcd *hcd = __hcd; // unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS); @@ -121,6 +121,12 @@ #endif usb_hcd_irq(irq, hcd, r); + + /* + * SA1111 seems to re-assert its interrupt immediately + * after processing an interrupt. Always return IRQ_HANDLED. + */ + return IRQ_HANDLED; } /*-------------------------------------------------------------------------*/ diff -urN linux-2.6.4-rc1/drivers/usb/misc/uss720.c linux-2.6.4-rc2/drivers/usb/misc/uss720.c --- linux-2.6.4-rc1/drivers/usb/misc/uss720.c 2004-02-17 19:57:12.000000000 -0800 +++ linux-2.6.4-rc2/drivers/usb/misc/uss720.c 2004-03-03 22:48:13.000000000 -0800 @@ -592,7 +592,6 @@ goto probe_abort_port; } #endif - parport_proc_register(pp); parport_announce_port(pp); usb_set_intfdata (intf, pp); @@ -600,7 +599,7 @@ #if 0 probe_abort_port: - parport_unregister_port(pp); + parport_put_port(pp); #endif probe_abort: kfree(priv); @@ -615,12 +614,12 @@ usb_set_intfdata (intf, NULL); if (pp) { priv = pp->private_data; + parport_remove_port(pp); #if 0 usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe); #endif priv->usbdev = NULL; - parport_proc_unregister(pp); - parport_unregister_port(pp); + parport_put_port(pp); kfree(priv); } } diff -urN linux-2.6.4-rc1/drivers/usb/serial/keyspan.h linux-2.6.4-rc2/drivers/usb/serial/keyspan.h --- linux-2.6.4-rc1/drivers/usb/serial/keyspan.h 2004-02-17 19:58:42.000000000 -0800 +++ linux-2.6.4-rc2/drivers/usb/serial/keyspan.h 2004-03-03 22:48:13.000000000 -0800 @@ -359,19 +359,19 @@ }; 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 = { diff -urN linux-2.6.4-rc1/drivers/video/Kconfig linux-2.6.4-rc2/drivers/video/Kconfig --- linux-2.6.4-rc1/drivers/video/Kconfig 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/video/Kconfig 2004-03-03 22:48:13.000000000 -0800 @@ -55,7 +55,7 @@ config FB_PM2 tristate "Permedia2 support" - depends on FB && (AMIGA || PCI) && BROKEN + depends on FB && (AMIGA || PCI) help This is the frame buffer device driver for the Permedia2 AGP frame buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a @@ -66,21 +66,7 @@ bool "enable FIFO disconnect feature" depends on FB_PM2 && PCI help - Support the Permedia2 FIFOI disconnect feature (see CONFIG_FB_PM2). - -config FB_PM2_PCI - bool "generic Permedia2 PCI board support" - depends on FB_PM2 && PCI - help - Say Y to enable support for Permedia2 AGP frame buffer card from - 3Dlabs (aka `Graphic Blaster Exxtreme') on the PCI bus. - -config FB_PM2_CVPPC - bool "Phase5 CVisionPPC/BVisionPPC support" - depends on FB_PM2 && AMIGA - help - Say Y to enable support for the Amiga Phase 5 CVisionPPC BVisionPPC - framebuffer cards. Phase 5 is no longer with us, alas. + Support the Permedia2 FIFO disconnect feature (see CONFIG_FB_PM2). config FB_ACORN bool "Acorn VIDC support" diff -urN linux-2.6.4-rc1/drivers/video/Makefile linux-2.6.4-rc2/drivers/video/Makefile --- linux-2.6.4-rc1/drivers/video/Makefile 2004-02-17 19:57:16.000000000 -0800 +++ linux-2.6.4-rc2/drivers/video/Makefile 2004-03-03 22:48:13.000000000 -0800 @@ -15,7 +15,7 @@ obj-$(CONFIG_FB_ACORN) += acornfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_AMIGA) += amifb.o c2p.o -obj-$(CONFIG_FB_PM2) += pm2fb.o +obj-$(CONFIG_FB_PM2) += pm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_PM3) += pm3fb.o obj-$(CONFIG_FB_APOLLO) += dnfb.o cfbfillrect.o cfbimgblt.o obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o diff -urN linux-2.6.4-rc1/drivers/video/aty/radeon_base.c linux-2.6.4-rc2/drivers/video/aty/radeon_base.c --- linux-2.6.4-rc1/drivers/video/aty/radeon_base.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/video/aty/radeon_base.c 2004-03-03 22:48:13.000000000 -0800 @@ -1320,6 +1320,16 @@ * not sure which model starts having FP2_GEN_CNTL, I assume anything more * recent than an r(v)100... */ +#if 0 + /* XXX I had reports of flicker happening with the cinema display + * on TMDS1 that seem to be fixed if I also forbit odd dividers in + * this case. This could just be a bandwidth calculation issue, I + * haven't implemented the bandwidth code yet, but in the meantime, + * forcing uses_dvo to 1 fixes it and shouln't have bad side effects, + * I haven't seen a case were were absolutely needed an odd PLL + * divider. I'll find a better fix once I have more infos on the + * real cause of the problem. + */ while (rinfo->has_CRTC2) { u32 fp2_gen_cntl = INREG(FP2_GEN_CNTL); u32 disp_output_cntl; @@ -1353,6 +1363,9 @@ uses_dvo = 1; break; } +#else + uses_dvo = 1; +#endif if (freq > rinfo->pll.ppll_max) freq = rinfo->pll.ppll_max; if (freq*12 < rinfo->pll.ppll_min) diff -urN linux-2.6.4-rc1/drivers/video/console/fbcon.c linux-2.6.4-rc2/drivers/video/console/fbcon.c --- linux-2.6.4-rc1/drivers/video/console/fbcon.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/video/console/fbcon.c 2004-03-03 22:48:13.000000000 -0800 @@ -159,7 +159,7 @@ 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); @@ -1697,14 +1697,23 @@ 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); diff -urN linux-2.6.4-rc1/drivers/video/console/promcon.c linux-2.6.4-rc2/drivers/video/console/promcon.c --- linux-2.6.4-rc1/drivers/video/console/promcon.c 2004-02-17 19:58:27.000000000 -0800 +++ linux-2.6.4-rc2/drivers/video/console/promcon.c 2004-03-03 22:48:13.000000000 -0800 @@ -463,7 +463,7 @@ } 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); diff -urN linux-2.6.4-rc1/drivers/video/console/sticon.c linux-2.6.4-rc2/drivers/video/console/sticon.c --- linux-2.6.4-rc1/drivers/video/console/sticon.c 2004-02-17 19:58:53.000000000 -0800 +++ linux-2.6.4-rc2/drivers/video/console/sticon.c 2004-03-03 22:48:13.000000000 -0800 @@ -250,26 +250,18 @@ 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) diff -urN linux-2.6.4-rc1/drivers/video/console/vgacon.c linux-2.6.4-rc2/drivers/video/console/vgacon.c --- linux-2.6.4-rc1/drivers/video/console/vgacon.c 2004-02-17 19:57:46.000000000 -0800 +++ linux-2.6.4-rc2/drivers/video/console/vgacon.c 2004-03-03 22:48:13.000000000 -0800 @@ -76,7 +76,7 @@ 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); @@ -661,7 +661,7 @@ } } -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 */ @@ -678,7 +678,8 @@ /* 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; @@ -686,11 +687,8 @@ 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) { diff -urN linux-2.6.4-rc1/drivers/video/cvisionppc.h linux-2.6.4-rc2/drivers/video/cvisionppc.h --- linux-2.6.4-rc1/drivers/video/cvisionppc.h 2004-02-17 19:58:32.000000000 -0800 +++ linux-2.6.4-rc2/drivers/video/cvisionppc.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,51 +0,0 @@ -/* - * Phase5 CybervisionPPC (TVP4020) definitions for the Permedia2 framebuffer - * driver. - * - * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) - * -------------------------------------------------------------------------- - * $Id: cvisionppc.h,v 1.8 1999/01/28 13:18:07 illo Exp $ - * -------------------------------------------------------------------------- - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -#ifndef CVISIONPPC_H -#define CVISIONPPC_H - -#ifndef PM2FB_H -#include "pm2fb.h" -#endif - -struct cvppc_par { - unsigned char* pci_config; - unsigned char* pci_bridge; - u32 user_flags; -}; - -#define CSPPC_PCI_BRIDGE 0xfffe0000 -#define CSPPC_BRIDGE_ENDIAN 0x0000 -#define CSPPC_BRIDGE_INT 0x0010 - -#define CVPPC_PCI_CONFIG 0xfffc0000 -#define CVPPC_ROM_ADDRESS 0xe2000001 -#define CVPPC_REGS_REGION 0xef000000 -#define CVPPC_FB_APERTURE_ONE 0xe0000000 -#define CVPPC_FB_APERTURE_TWO 0xe1000000 -#define CVPPC_FB_SIZE 0x00800000 -#define CVPPC_MEM_CONFIG_OLD 0xed61fcaa /* FIXME Fujitsu?? */ -#define CVPPC_MEM_CONFIG_NEW 0xed41c532 /* FIXME USA?? */ -#define CVPPC_MEMCLOCK 83000 /* in KHz */ - -/* CVPPC_BRIDGE_ENDIAN */ -#define CSPPCF_BRIDGE_BIG_ENDIAN 0x02 - -/* CVPPC_BRIDGE_INT */ -#define CSPPCF_BRIDGE_ACTIVE_INT2 0x01 - -#endif /* CVISIONPPC_H */ - -/***************************************************************************** - * That's all folks! - *****************************************************************************/ diff -urN linux-2.6.4-rc1/drivers/video/fbmem.c linux-2.6.4-rc2/drivers/video/fbmem.c --- linux-2.6.4-rc1/drivers/video/fbmem.c 2004-03-03 22:48:01.000000000 -0800 +++ linux-2.6.4-rc2/drivers/video/fbmem.c 2004-03-03 22:48:13.000000000 -0800 @@ -955,7 +955,8 @@ { 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; diff -urN linux-2.6.4-rc1/drivers/video/i810/Makefile linux-2.6.4-rc2/drivers/video/i810/Makefile --- linux-2.6.4-rc1/drivers/video/i810/Makefile 2004-02-17 19:57:22.000000000 -0800 +++ linux-2.6.4-rc2/drivers/video/i810/Makefile 2004-03-03 22:48:13.000000000 -0800 @@ -1,12 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/drivers/video/kyro/Makefile linux-2.6.4-rc2/drivers/video/kyro/Makefile --- linux-2.6.4-rc1/drivers/video/kyro/Makefile 2004-02-17 19:59:33.000000000 -0800 +++ linux-2.6.4-rc2/drivers/video/kyro/Makefile 2004-03-03 22:48:13.000000000 -0800 @@ -1,11 +1,6 @@ # # 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 diff -urN linux-2.6.4-rc1/drivers/video/pm2fb.c linux-2.6.4-rc2/drivers/video/pm2fb.c --- linux-2.6.4-rc1/drivers/video/pm2fb.c 2004-02-17 19:59:57.000000000 -0800 +++ linux-2.6.4-rc2/drivers/video/pm2fb.c 2004-03-03 22:48:13.000000000 -0800 @@ -1,25 +1,30 @@ /* * Permedia2 framebuffer driver. + * + * 2.5/2.6 driver: + * Copyright (c) 2003 Jim Hague (jim.hague@acm.org) + * + * based on 2.4 driver: * Copyright (c) 1998-2000 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) * Copyright (c) 1999 Jakub Jelinek (jakub@redhat.com) - * Based on linux/drivers/video/skeletonfb.c by Geert Uytterhoeven. - * -------------------------------------------------------------------------- - * $Id: pm2fb.c,v 1.213 2000/09/19 01:03:19 illo Exp $ - * -------------------------------------------------------------------------- - * History: - * 1999/05/09 added Jim Hague's 'var' kernel option (thanks Jim!) - * 2002/04/23 Jim Hague - * * Integrated Illo's last changes, No changelist available. - * Major items: acceleration support, hardware cursor code - * (not yet enabled). - * * Fixed -vsync, added lowhsync/lowvsync overrides for use with - * XFree GLINT driver. - * -------------------------------------------------------------------------- - * TODO multiple boards support - * -------------------------------------------------------------------------- + * + * and additional input from James Simmon's port of Hannu Mallat's tdfx + * driver. + * + * $Id$ + * + * I have a Creative Graphics Blaster Exxtreme card - pm2fb on x86. + * I have no access to other pm2fb implementations, and cannot test + * on them. Therefore for now I am omitting Sparc and CVision code. + * + * Multiple boards support has been on the TODO list for ages. + * Don't expect this to change. + * * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * */ #include @@ -30,43 +35,24 @@ #include #include #include -#include #include -#include #include -#include -#include #include #include -#include -#include -#include -#include