2.6.7-rc1-mm1 --- diff/Documentation/BK-usage/bk-kernel-howto.txt 2004-05-27 13:41:08.000000000 +0100 +++ source/Documentation/BK-usage/bk-kernel-howto.txt 2004-05-27 18:34:14.000000000 +0100 @@ -279,5 +279,5 @@ for my long-lived kernel branch? A. Yes. This requires BK 3.x, though. - bk export -tpatch -r`bk repogca http://linux.bkbits.net/linux-2.5`,+ + bk export -tpatch -r`bk repogca bk://linux.bkbits.net/linux-2.5`,+ --- diff/Documentation/BK-usage/gcapatch 2004-05-27 13:41:08.000000000 +0100 +++ source/Documentation/BK-usage/gcapatch 2004-05-27 18:34:14.000000000 +0100 @@ -5,4 +5,4 @@ # Usage: gcapatch > foo.patch # -bk export -tpatch -hdu -r`bk repogca http://linux.bkbits.net/linux-2.5`,+ +bk export -tpatch -hdu -r`bk repogca bk://linux.bkbits.net/linux-2.5`,+ --- diff/Documentation/binfmt_misc.txt 2004-05-19 22:10:50.000000000 +0100 +++ source/Documentation/binfmt_misc.txt 2004-05-27 18:34:14.000000000 +0100 @@ -15,7 +15,7 @@ mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc To actually register a new binary type, you have to set up a string looking like -:name:type:offset:magic:mask:interpreter: (where you can choose the ':' upon +:name:type:offset:magic:mask:interpreter:flags (where you can choose the ':' upon your needs) and echo it to /proc/sys/fs/binfmt_misc/register. Here is what the fields mean: - 'name' is an identifier string. A new /proc file will be created with this @@ -34,6 +34,28 @@ The mask is anded with the byte sequence of the file. - 'interpreter' is the program that should be invoked with the binary as first argument (specify the full path) + - 'flags' is an optional field that controls several aspects of the invocation + of the interpreter. It is a string of capital letters, each controls a certain + aspect. The following flags are supported - + 'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite the + original argv[0] with the full path to the binary. When this flag is + included, binfmt_misc will add an argument to the argument vector for + this purpose, thus preserving the original argv[0]. + 'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path + of the binary to the interpreter as an argument. When this flag is + included, binfmt_misc will open the file for reading and pass its + descriptor as an argument, instead of the full path, thus allowing + the interpreter to execute non-readable binaries. This feature should + be used with care - the interpreter has to be trusted not to emit + the contents of the non-readable binary. + 'C' - credentials. Currently, the behavior of binfmt_misc is to calculate + the credentials and security token of the new process according to + the interpreter. When this flag is included, these attributes are + calculated according to the binary. It also implies the 'O' flag. + This feature should be used with care as the interpreter + will run with root permissions when a setuid binary owned by root + is run with binfmt_misc. + There are some restrictions: - the whole register string may not exceed 255 characters @@ -83,9 +105,9 @@ write a wrapper script for it. See Documentation/java.txt for an example. -Your interpreter should NOT look in the PATH for the filename; the -kernel passes it the full filename to use. Using the PATH can cause -unexpected behaviour and be a security hazard. +Your interpreter should NOT look in the PATH for the filename; the kernel +passes it the full filename (or the file descriptor) to use. Using $PATH can +cause unexpected behaviour and can be a security hazard. There is a web page about binfmt_misc at --- diff/Documentation/filesystems/proc.txt 2004-05-27 13:41:09.000000000 +0100 +++ source/Documentation/filesystems/proc.txt 2004-05-27 18:34:14.000000000 +0100 @@ -201,7 +201,7 @@ devices Available devices (block and character) dma Used DMS channels filesystems Supported filesystems - driver Various drivers grouped here, currently rtc (2.4) + driver Various drivers grouped here, currently rtc (2.4) and hpet (2.6) execdomains Execdomains, related to security (2.4) fb Frame Buffer devices (2.4) fs File system parameters, currently nfs/exports (2.4) --- diff/Documentation/kernel-parameters.txt 2004-05-19 22:10:50.000000000 +0100 +++ source/Documentation/kernel-parameters.txt 2004-05-27 18:34:14.000000000 +0100 @@ -896,8 +896,8 @@ psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports per second. psmouse.resetafter= - [HW,MOUSE] Try to reset Synaptics Touchpad after so many - bad packets (0 = never). + [HW,MOUSE] Try to reset the device after so many bad packets + (0 = never). psmouse.resolution= [HW,MOUSE] Set desired mouse resolution, in dpi. psmouse.smartscroll= --- diff/Documentation/laptop-mode.txt 2004-05-27 13:41:09.000000000 +0100 +++ source/Documentation/laptop-mode.txt 2004-05-27 18:34:14.000000000 +0100 @@ -279,7 +279,13 @@ fi } -KLEVEL="$(uname -r | cut -c1-3)" +KLEVEL=$( + uname -r | + ( + IFS="." read a b c + echo $a.$b + ) + ) case "$KLEVEL" in "2.4"|"2.6") true @@ -496,7 +502,7 @@ case $status in "on-line") - echo "Setting HD spindown to 2 hours" + echo "Setting HD spindown for AC mode." /sbin/laptop_mode stop /sbin/hdparm -S $ACAD_HD /dev/hda > /dev/null 2>&1 /sbin/hdparm -B 255 /dev/hda > /dev/null 2>&1 @@ -504,7 +510,7 @@ exit 0 ;; "off-line") - echo "Setting HD spindown to 20 seconds" + echo "Setting HD spindown for battery mode." /sbin/laptop_mode start /sbin/hdparm -S $BATT_HD /dev/hda > /dev/null 2>&1 /sbin/hdparm -B 1 /dev/hda > /dev/null 2>&1 --- diff/Documentation/networking/bridge.txt 2004-05-19 22:10:52.000000000 +0100 +++ source/Documentation/networking/bridge.txt 2004-05-27 18:34:14.000000000 +0100 @@ -1,11 +1,8 @@ -In order to use the ethernet bridging functionality you'll need the -userspace tools available at http://www.math.leidenuniv.nl/~buytenh/bridge. -The tarball available there contains extensive documentation, but if you -still have questions, don't hesitate to post to the mailing list (more info -at http://www.math.leidenuniv.nl/mailman/listinfo/bridge). You can also -mail me at buytenh@gnu.org. +In order to use the Ethernet bridging functionality, you'll need the +userspace tools. These programs and documentation are available +at http://bridge.sourceforge.net. The download page is +http://prdownloads.sourceforge.net/bridge. +If you still have questions, don't hesitate to post to the mailing list +(more info http://lists.osdl.org/mailman/listinfo/bridge). - -Lennert Buytenhek - --- diff/Documentation/power/swsusp.txt 2004-05-27 13:41:09.000000000 +0100 +++ source/Documentation/power/swsusp.txt 2004-05-27 18:34:14.000000000 +0100 @@ -123,14 +123,15 @@ replace ethernet card, resume. If you are fast your users will not even see broken connections. -Q: Maybe I'm missing something, but why doesn't the regular io paths -work? -A: (Basically) you want to replace all kernel data with kernel data saved -on disk. How do you do that using normal i/o paths? If you'll read -"new" data 4KB at a time, you'll crash... because you still need "old" -data to do the reading, and "new" data may fit on same physical spot -in memory. +Q: Maybe I'm missing something, but why don't the regular I/O paths work? + +A: We do use the regular I/O paths. However we cannot restore the data +to its original location as we load it. That would create an +inconsistent kernel state which would certainly result in an oops. +Instead, we load the image into unused memory and then atomically copy +it back to it original location. This implies, of course, a maximum +image size of half the amount of memory. There are two solutions to this: @@ -141,6 +142,10 @@ between 0-640KB. That way, I'd have to make sure that 0-640KB is free during suspending, but otherwise it would work... +suspend2 shares this fundamental limitation, but does not include user +data and disk caches into "used memory" by saving them in +advance. That means that the limitation goes away in practice. + Q: Does linux support ACPI S4? A: No. @@ -161,7 +166,7 @@ Q: My machine doesn't work with ACPI. How can I use swsusp than ? -A: Do reboot() syscall with right parameters. Warning: glibc gets in +A: Do a reboot() syscall with right parameters. Warning: glibc gets in its way, so check with strace: reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, 0xd000fce2) @@ -181,3 +186,16 @@ LINUX_REBOOT_CMD_SW_SUSPEND, 0); return 0; } + +Q: What is 'suspend2'? + +A: suspend2 is 'Software Suspend 2', a forked implementation of +suspend-to-disk which is available as separate patches for 2.4 and 2.6 +kernels from swsusp.sourceforge.net. It includes support for SMP, 4GB +highmem and preemption. It also has a extensible architecture that +allows for arbitrary transformations on the image (compression, +encryption) and arbitrary backends for writing the image (eg to swap +or an NFS share[Work In Progress]). Questions regarding suspend2 +should be sent to the mailing list available through the suspend2 +website, and not to the Linux Kernel Mailing List. We are working +toward merging suspend2 into the mainline kernel. --- diff/Documentation/power/tricks.txt 2004-05-19 22:10:52.000000000 +0100 +++ source/Documentation/power/tricks.txt 2004-05-27 18:34:14.000000000 +0100 @@ -7,6 +7,8 @@ * go with minimal config, turn off drivers like USB, AGP you don't really need +* turn off APIC and preempt + * use ext2. At least it has working fsck. [If something seemes to go wrong, force fsck when you have a chance] --- diff/Documentation/power/video.txt 2004-05-19 22:10:52.000000000 +0100 +++ source/Documentation/power/video.txt 2004-05-27 18:34:14.000000000 +0100 @@ -30,6 +30,10 @@ patched X, and plain text console (no vesafb or radeonfb), see http://www.doesi.gmxhome.de/linux/tm800s3/s3.html. (Acer TM 800) +* radeon systems, where X can soft-boot your video card. You'll need + patched X, and plain text console (no vesafb or radeonfb), see + http://www.doesi.gmxhome.de/linux/tm800s3/s3.html. (Acer TM 800) + Now, if you pass acpi_sleep=something, and it does not work with your bios, you'll get hard crash during resume. Be carefull. --- diff/Documentation/sound/alsa/ALSA-Configuration.txt 2004-05-19 22:10:52.000000000 +0100 +++ source/Documentation/sound/alsa/ALSA-Configuration.txt 2004-05-27 18:34:14.000000000 +0100 @@ -416,7 +416,8 @@ * Creative Card w/Digital out + Digital I/O 2 [0x0fc3/0x1f0f] * Creative Card w/Digital CD in + Digital I/O 2 [0x0fcf/0x1f0f] * Creative Card 5.1/w Digital out + LiveDrive [0x3fc3/0x1fff] - * Creative Card all ins and outs [0x3fff/0x1fff] + * Creative Card 5.1 (c) 2003 [0x3fc3/0x7cff] + * Creative Card all ins and outs [0x3fff/0x7fff] Module snd-ens1370 ------------------ @@ -609,6 +610,10 @@ * Hoontech SoundTrack DSP 24 Media 7.1 * Digigram VX442 + model - Use the given board model, one of the following: + delta1010, dio2496, delta66, delta44, audiophile, delta410, + delta1010lt, vx442, ewx2496, ews88mt, ews88mt_new, ews88d, + dmx6fire, dsp24, dsp24_71, ez8 omni - Omni I/O support for MidiMan M-Audio Delta44/66 cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transciever) in msec resolution, default value is 500 (0.5 sec) @@ -625,6 +630,9 @@ * AMP Ltd AUDIO2000 * TerraTec Aureon Sky-5.1, Space-7.1 + model - Use the given board model, one of the following: + revo71, amp2000, prodigy71, aureon51, aureon71 + Module supports up to 8 cards and autoprobe. Module snd-intel8x0 @@ -787,6 +795,8 @@ Module supports autoprobe and multiple chips (max 8). + The power-management is supported. + Note: on some notebooks the buffer address cannot be detected automatically, or causes hang-up during initialization. In such a case, specify the buffer top address explicity via @@ -796,9 +806,24 @@ Sony F270: buffer_top=0x272800 The driver supports only ac97 codec. It's possible to force to initialize/use ac97 although it's not detected. In such a - case, use force_ac97=1 option. + case, use force_ac97=1 option - but *NO* guarantee whether it + works! - The power-management is supported. + Note: The NM256 chip can be linked internally with non-AC97 + codecs. This driver supports only the AC97 codec, and won't work + with machines with other (most likely CS423x or OPL3SAx) chips, + even though the device is detected in lspci. In such a case, try + other drivers, e.g. snd-cs4232 or snd-opl3sa2. Some has ISA-PnP + but some doesn't have ISA PnP. You'll need to speicfy isapnp=0 + and proper hardware parameters in the case without ISA PnP. + + Note: This driver is really crappy. It's a porting from the + OSS driver, which is a result of black-magic reverse engineering. + The detection of codec will fail if the driver is loaded *after* + X-server as described above. You might be able to force to load + the module, but it may result in hang-up. Hence, make sure that + you load this module *before* X if you encounter this kind of + problem. Module snd-opl3sa2 ------------------ --- diff/Documentation/sound/alsa/CMIPCI.txt 2004-05-19 22:10:52.000000000 +0100 +++ source/Documentation/sound/alsa/CMIPCI.txt 2004-05-27 18:34:14.000000000 +0100 @@ -180,8 +180,8 @@ device automatically to the previous state. On the model 033, AC3 is implemented by the software conversion in -the driver. This prevents the mmap support. If you need mmap -support, pass the "soft_ac3=0" module option. This doesn't matter +the alsa-lib. If you need to bypass the software conversion of IEC958 +subframes, pass the "soft_ac3=0" module option. This doesn't matter on the newer models. --- diff/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl 2004-05-19 22:10:52.000000000 +0100 +++ source/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl 2004-05-27 18:34:14.000000000 +0100 @@ -511,7 +511,7 @@ } // (7) - pci_set_drvdata(pci, chip); + pci_set_drvdata(pci, card); dev++; return 0; } @@ -519,10 +519,7 @@ // destructor -- see "Destructor" sub-section static void __devexit snd_mychip_remove(struct pci_dev *pci) { - mychip_t *chip = snd_magic_cast(mychip_t, - pci_get_drvdata(pci), return); - if (chip) - snd_card_free(chip->card); + snd_card_free(pci_get_drvdata(pci)); pci_set_drvdata(pci, NULL); } ]]> @@ -691,21 +688,16 @@ - In the above, the chip record is stored. This pointer is + In the above, the card record is stored. This pointer is referred in the remove callback and power-management callbacks, too. - If the card doesn't support the suspend/resume, you can store - the card pointer instead of the chip pointer, so that - snd_card_free can be called directly - without cast in the remove callback. But anyway, be sure - which pointer is used. @@ -726,21 +718,15 @@ card); + snd_card_free(pci_get_drvdata(pci)); pci_set_drvdata(pci, NULL); } ]]> - The above code assumes that the chip is allocated - with snd_magic stuff and - has the field to hold the card pointer (see the next - section). + The above code assumes that the card pointer is set to the PCI + driver data. @@ -1355,16 +1341,7 @@ // initialization of the module static int __init alsa_card_mychip_init(void) { - int err; - - if ((err = pci_module_init(&driver)) < 0) { - #ifdef MODULE - printk(KERN_ERR "My chip soundcard not found " - "or device busy\n"); - #endif - return err; - } - return 0; + return pci_module_init(&driver); } // clean up the module @@ -1781,16 +1758,7 @@ - Basic jobs of suspend/resume are done in - suspend and - resume callbacks of - pci_driver struct. Unfortunately, the - API of these callbacks was changed at the middle time of Linux - 2.4.x, if you want to keep the support for older kernels, you - have to write two different callbacks. The example below is the - skeleton callbacks which just call the real suspend and resume - functions. + ALSA provides the common power-management layer. Each card driver + needs to have only low-level suspend and resume callbacks. @@ -5302,17 +5246,10 @@ - For keeping the readability of 2.6 source code, it's recommended to - separate the above ifdef condition as the patch file in alsa-driver - directory. - See alsa-driver/pci/ali5451.c for example. - - - The scheme of the real suspend job is as following. - Check whether the power-state is already D3hot. If yes, skip the job. + Retrieve the chip data from pm_private_data field. Call snd_pcm_suspend_all() to suspend the running PCM streams. Save the register values if necessary. Stop the hardware if necessary. @@ -5326,12 +5263,11 @@ card; // (1) - if (card->power_state == SNDRV_CTL_POWER_D3hot) - return; + mychip_t *chip = snd_magic_cast(mychip_t, card->pm_private_data, + return -ENXIO); // (2) snd_pcm_suspend_all(chip->pcm); // (3) @@ -5340,6 +5276,7 @@ snd_mychip_stop_hardware(chip); // (5) snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + return 0; } ]]> @@ -5350,8 +5287,7 @@ The scheme of the real resume job is as following. - Check whether the power-state is already D0. - If yes, skip the job. + Retrieve the chip data from pm_private_data field. Enable the pci device again by calling pci_enable_device(). Re-initialize the chip. @@ -5372,10 +5308,9 @@ card; // (1) - if (card->power_state == SNDRV_CTL_POWER_D0) - return; + mychip_t *chip = snd_magic_cast(mychip_t, card->pm_private_data, + return -ENXIO); // (2) pci_enable_device(chip->pci); // (3) @@ -5388,38 +5323,6 @@ snd_mychip_restart_chip(chip); // (7) snd_power_change_state(card, SNDRV_CTL_POWER_D0); - } -]]> - - - - - - In addition to the callbacks above, you should define a callback - for the changes via the ALSA control interface. It's defined - like below: - - - -power_state_private_data, return -ENXIO); - switch (power_state) { - case SNDRV_CTL_POWER_D0: - case SNDRV_CTL_POWER_D1: - case SNDRV_CTL_POWER_D2: - mychip_resume(chip); - break; - case SNDRV_CTL_POWER_D3hot: - case SNDRV_CTL_POWER_D3cold: - mychip_suspend(chip); - break; - default: - return -EINVAL; - } return 0; } ]]> @@ -5439,41 +5342,42 @@ { .... snd_card_t *card; + mychip_t *chip; .... - #ifdef CONFIG_PM - card->set_power_state = snd_mychip_set_power_state; - card->power_state_private_data = chip; - #endif + snd_card_set_pm_callback(card, snd_my_suspend, snd_my_resume, chip); .... } ]]> + + Here you don't have to put ifdef CONFIG_PM around, since it's already + checked in the header and expanded to empty if not needed. If you need a space for saving the registers, you'll need to - allocate the buffer for it here, too, since you cannot call - kmalloc() with - GFP_KERNEL flag or - vmalloc() in the suspend callback. + allocate the buffer for it here, too, since it would be fatal + if you cannot allocate a memory in the suspend phase. The allocated buffer should be released in the corresponding destructor. And next, set suspend/resume callbacks to the pci_driver, + This can be done by passing a macro SND_PCI_PM_CALLBACKS + in the pci_driver struct. This macro is expanded to the correct + (global) callbacks if CONFIG_PM is set. @@ -5521,7 +5425,8 @@ The module parameters must be declared with the standard - MODULE_PARM() and + module_param()(), + module_param_array()() and MODULE_PARM_DESC() macros. The ALSA provides an additional macro, MODULE_PARM_SYNTAX(), for describing its syntax. The strings will be written to @@ -5545,18 +5450,22 @@ + + Here boot_devs is passed but simply ignored since we don't care + the number of parsed parameters. @@ -5577,39 +5486,6 @@ - - For building the driver into kernel, you should define the - setup() function in addition, too. - ALSA provides get_id() function to retrieve - a string argument from the kernel boot parameters. - - - -= SNDRV_CARDS) - return 0; - (void)(get_option(&str,&enable[nr_dev]) == 2 && - get_option(&str,&index[nr_dev]) == 2 && - get_id(&str,&id[nr_dev]) == 2); - nr_dev++; - return 1; - } - - __setup("snd-mychip=", alsa_card_mychip_setup); - - #endif /* ifndef MODULE */ -]]> - - - @@ -5631,10 +5507,14 @@ Suppose that you'll create a new PCI driver for the card xyz. The card module name would be snd-xyz. The new driver is usually put into alsa-driver - tree. Then the driver is evaluated, audited and tested + tree, alsa-driver/pci directory in + the case of PCI cards. + Then the driver is evaluated, audited and tested by developers and users. After a certain time, the driver - will go to alsa-kernel tree and eventually integrated into - Linux 2.6 tree. + will go to alsa-kernel tree (to the corresponding directory, + such as alsa-kernel/pci) and eventually + integrated into Linux 2.6 tree (the directory would be + linux/sound/pci). @@ -5661,7 +5541,7 @@ @@ -5678,8 +5558,8 @@ - Add a new directory (xyz) to extra-subdir-y list in alsa-driver/pci/Makefile + Add a new directory (xyz) in + alsa-driver/pci/Makefile like below @@ -5744,7 +5625,7 @@ - Under the directory xyz, create a Makefile + Under the directory xyz, create a Makefile Sample Makefile for a driver xyz --- diff/Documentation/sound/alsa/Procfile.txt 2004-05-19 22:10:52.000000000 +0100 +++ source/Documentation/sound/alsa/Procfile.txt 2004-05-27 18:34:14.000000000 +0100 @@ -131,6 +131,12 @@ card*/codec97#0/ac97#?-?+regs Shows the AC97 register dump. Useful for debugging. + When CONFIG_SND_DEBUG is enabled, you can write to this file for + changing an AC97 register directly. Pass two hex numbers. + For example, + + # echo 02 9f1f > /proc/asound/card0/codec97#0/ac97#0-0+regs + Sequencer Information --------------------- --- diff/MAINTAINERS 2004-05-27 13:41:09.000000000 +0100 +++ source/MAINTAINERS 2004-05-27 18:34:14.000000000 +0100 @@ -90,6 +90,20 @@ L: linux-net@vger.kernel.org S: Maintained +3W-XXXX ATA-RAID CONTROLLER DRIVER +P: Adam Radford +M: linuxraid@amcc.com +L: linux-scsi@vger.kernel.org +W: http://www.amcc.com +S: Supported + +3W-9XXX SATA-RAID CONTROLLER DRIVER +P: Adam Radford +M: linuxraid@amcc.com +L: linux-scsi@vger.kernel.org +W: http://www.amcc.com +S: Supported + 53C700 AND 53C700-66 SCSI DRIVER P: James E.J. Bottomley M: James.Bottomley@HansenPartnership.com @@ -538,11 +552,6 @@ W: http://sourceforge.net/projects/cramfs/ S: Orphan -CREDITS FILE -P: John A. Martin -M: jam@acm.org -S: Maintained - CRIS PORT P: Bjorn Wesen M: bjornw@axis.com @@ -1204,6 +1213,12 @@ W: http://developer.osdl.org/rddunlap/kj-patches/ S: Maintained +KGDB FOR I386 PLATFORM +P: George Anzinger +M: george@mvista.com +L: linux-net@vger.kernel.org +S: Supported + KERNEL NFSD P: Neil Brown M: neilb@cse.unsw.edu.au --- diff/Makefile 2004-05-27 13:41:09.000000000 +0100 +++ source/Makefile 2004-05-27 18:34:14.000000000 +0100 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 7 -EXTRAVERSION =-rc1 +EXTRAVERSION =-rc1-mm1 NAME=Zonked Quokka # *DOCUMENTATION* @@ -461,6 +461,7 @@ ifdef CONFIG_DEBUG_INFO CFLAGS += -g +AFLAGS += -g endif # warn about C99 declaration after statement @@ -680,7 +681,7 @@ uts_len := 64 define filechk_version.h - if ((`echo -n "$(KERNELRELEASE)" | wc -c ` > $(uts_len))); then \ + if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \ echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \ exit 1; \ fi; \ @@ -1065,6 +1066,11 @@ endif #ifeq ($(config-targets),1) endif #ifeq ($(mixed-targets),1) +.PHONY: checkstack +checkstack: + $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \ + $(PERL) scripts/checkstack.pl $(ARCH) + # FIXME Should go into a make.lib or something # =========================================================================== --- diff/arch/alpha/kernel/init_task.c 2004-05-19 22:10:53.000000000 +0100 +++ source/arch/alpha/kernel/init_task.c 2004-05-27 18:34:14.000000000 +0100 @@ -4,6 +4,7 @@ #include #include #include +#include #include --- diff/arch/alpha/kernel/setup.c 2004-05-19 22:10:53.000000000 +0100 +++ source/arch/alpha/kernel/setup.c 2004-05-27 18:34:14.000000000 +0100 @@ -122,7 +122,6 @@ static void determine_cpu_caches (unsigned int); static char command_line[COMMAND_LINE_SIZE]; -char saved_command_line[COMMAND_LINE_SIZE]; /* * The format of "screen_info" is strange, and due to early --- diff/arch/arm/Kconfig 2004-05-27 13:41:09.000000000 +0100 +++ source/arch/arm/Kconfig 2004-05-27 18:34:14.000000000 +0100 @@ -84,9 +84,6 @@ config ARCH_CO285 bool "Co-EBSA285" -config ARCH_PXA - bool "PXA2xx-based" - config ARCH_EBSA110 bool "EBSA-110" help @@ -126,6 +123,9 @@ If you have any questions or comments about the Linux kernel port to this board, send e-mail to sjhill@cotw.com. +config ARCH_PXA + bool "PXA2xx-based" + config ARCH_RPC bool "RiscPC" help @@ -135,9 +135,6 @@ config ARCH_SA1100 bool "SA1100-based" -config ARCH_SHARK - bool "Shark" - config ARCH_S3C2410 bool "Samsung S3C2410" help @@ -145,8 +142,8 @@ BAST (http://www.simtec.co.uk/products/EB110ITX/), the IPAQ 1940 or the Samsung SMDK2410 development board (and derviatives). -config ARCH_OMAP - bool "TI OMAP" +config ARCH_SHARK + bool "Shark" config ARCH_LH7A40X bool "Sharp LH7A40X" @@ -156,6 +153,9 @@ core with a wide array of integrated devices for hand-held and low-power applications. +config ARCH_OMAP + bool "TI OMAP" + config ARCH_VERSATILE_PB bool "Versatile PB" help --- diff/arch/arm/common/dmabounce.c 2004-05-27 13:41:10.000000000 +0100 +++ source/arch/arm/common/dmabounce.c 2004-05-27 18:34:14.000000000 +0100 @@ -100,6 +100,7 @@ if (d->dev == dev) return d; } + return NULL; } --- diff/arch/arm/kernel/arch.c 2004-05-19 22:10:55.000000000 +0100 +++ source/arch/arm/kernel/arch.c 2004-05-27 18:34:14.000000000 +0100 @@ -10,7 +10,6 @@ #include #include #include -#include #include unsigned int vram_size; --- diff/arch/arm/kernel/init_task.c 2004-05-19 22:10:55.000000000 +0100 +++ source/arch/arm/kernel/init_task.c 2004-05-27 18:34:14.000000000 +0100 @@ -7,6 +7,7 @@ #include #include #include +#include #include #include --- diff/arch/arm/kernel/setup.c 2004-05-27 13:41:10.000000000 +0100 +++ source/arch/arm/kernel/setup.c 2004-05-27 18:34:14.000000000 +0100 @@ -95,7 +95,6 @@ char elf_platform[ELF_PLATFORM_SIZE]; EXPORT_SYMBOL(elf_platform); -char saved_command_line[COMMAND_LINE_SIZE]; unsigned long phys_initrd_start __initdata = 0; unsigned long phys_initrd_size __initdata = 0; --- diff/arch/arm/mach-adifcc/irq.c 2004-05-19 22:10:55.000000000 +0100 +++ source/arch/arm/mach-adifcc/irq.c 2004-05-27 18:34:14.000000000 +0100 @@ -19,8 +19,6 @@ #include #include -#include - static void xs80200_irq_mask (unsigned int irq) { long INTCTL; --- diff/arch/arm/mach-iop3xx/iop310-irq.c 2004-05-19 22:10:55.000000000 +0100 +++ source/arch/arm/mach-iop3xx/iop310-irq.c 2004-05-27 18:34:14.000000000 +0100 @@ -21,8 +21,6 @@ #include #include -#include - extern void xs80200_irq_mask(unsigned int); extern void xs80200_irq_unmask(unsigned int); extern void xs80200_init_irq(void); --- diff/arch/arm/mach-iop3xx/iop321-time.c 2004-05-19 22:10:55.000000000 +0100 +++ source/arch/arm/mach-iop3xx/iop321-time.c 2004-05-27 18:34:14.000000000 +0100 @@ -23,7 +23,6 @@ #include #include #include -#include #include static unsigned long iop321_gettimeoffset(void) --- diff/arch/arm/mach-iop3xx/iq80310-irq.c 2004-05-19 22:10:55.000000000 +0100 +++ source/arch/arm/mach-iop3xx/iq80310-irq.c 2004-05-27 18:34:14.000000000 +0100 @@ -22,8 +22,6 @@ #include #include -#include - extern void iop310_init_irq(void); extern void iop310_irq_demux(unsigned int, struct irqdesc *, struct pt_regs *); --- diff/arch/arm/mach-iop3xx/iq80310-time.c 2004-05-19 22:10:55.000000000 +0100 +++ source/arch/arm/mach-iop3xx/iq80310-time.c 2004-05-27 18:34:14.000000000 +0100 @@ -21,7 +21,6 @@ #include #include #include -#include #include static void iq80310_write_timer (u_long val) --- diff/arch/arm/mach-iop3xx/mm-321.c 2004-05-19 22:10:55.000000000 +0100 +++ source/arch/arm/mach-iop3xx/mm-321.c 2004-05-27 18:34:14.000000000 +0100 @@ -21,7 +21,6 @@ #include #include -#include /* --- diff/arch/arm/mach-iop3xx/mm.c 2004-05-19 22:10:55.000000000 +0100 +++ source/arch/arm/mach-iop3xx/mm.c 2004-05-27 18:34:14.000000000 +0100 @@ -23,7 +23,6 @@ #include #include -#include #ifdef CONFIG_IOP310_MU #include "message.h" --- diff/arch/arm/mach-iop3xx/xs80200-irq.c 2004-05-19 22:10:55.000000000 +0100 +++ source/arch/arm/mach-iop3xx/xs80200-irq.c 2004-05-27 18:34:14.000000000 +0100 @@ -17,8 +17,6 @@ #include #include -#include - static void xs80200_irq_mask (unsigned int irq) { unsigned long intctl; --- diff/arch/arm/mach-ixp4xx/common.c 2004-05-27 13:41:10.000000000 +0100 +++ source/arch/arm/mach-ixp4xx/common.c 2004-05-27 18:34:14.000000000 +0100 @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include --- diff/arch/arm/mach-omap/bus.c 2004-05-19 22:10:55.000000000 +0100 +++ source/arch/arm/mach-omap/bus.c 2004-05-27 18:34:14.000000000 +0100 @@ -39,7 +39,6 @@ #include #include -#include #include #include #include --- diff/arch/arm/mach-pxa/generic.c 2004-05-27 13:41:10.000000000 +0100 +++ source/arch/arm/mach-pxa/generic.c 2004-05-27 18:34:14.000000000 +0100 @@ -104,6 +104,7 @@ .id = 0, .dev = { .dma_mask = &pxamci_dmamask, + .coherent_dma_mask = 0xffffffff, }, .num_resources = ARRAY_SIZE(pxamci_resources), .resource = pxamci_resources, --- diff/arch/arm/mach-pxa/lubbock.c 2004-05-19 22:10:56.000000000 +0100 +++ source/arch/arm/mach-pxa/lubbock.c 2004-05-27 18:34:14.000000000 +0100 @@ -11,11 +11,12 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include #include #include -#include +#include #include #include @@ -29,11 +30,22 @@ #include #include +#include #include #include "generic.h" +void lubbock_set_misc_wr(unsigned int mask, unsigned int set) +{ + unsigned long flags; + + local_irq_save(flags); + LUB_MISC_WR = (LUB_MISC_WR & ~mask) | (set & mask); + local_irq_restore(flags); +} +EXPORT_SYMBOL(lubbock_set_misc_wr); + static unsigned long lubbock_irq_enabled; static void lubbock_mask_irq(unsigned int irq) @@ -148,9 +160,29 @@ &smc91x_device, }; +static struct pxafb_mach_info sharp_lm8v31 __initdata = { + .pixclock = 270000, + .xres = 640, + .yres = 480, + .bpp = 16, + .hsync_len = 1, + .left_margin = 3, + .right_margin = 3, + .vsync_len = 1, + .upper_margin = 0, + .lower_margin = 0, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .cmap_greyscale = 0, + .cmap_inverse = 0, + .cmap_static = 0, + .lccr0 = LCCR0_SDS, + .lccr3 = LCCR3_PCP | LCCR3_Acb(255), +}; + static void __init lubbock_init(void) { pxa_set_udc_info(&udc_info); + set_pxa_fb_info(&sharp_lm8v31); (void) platform_add_devices(devices, ARRAY_SIZE(devices)); } --- diff/arch/arm/mach-s3c2410/s3c2410.c 2004-05-19 22:10:56.000000000 +0100 +++ source/arch/arm/mach-s3c2410/s3c2410.c 2004-05-27 18:34:14.000000000 +0100 @@ -31,7 +31,6 @@ #include #include #include -#include #include #include --- diff/arch/arm26/kernel/init_task.c 2004-05-19 22:10:58.000000000 +0100 +++ source/arch/arm26/kernel/init_task.c 2004-05-27 18:34:14.000000000 +0100 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include --- diff/arch/arm26/kernel/setup.c 2004-05-19 22:10:58.000000000 +0100 +++ source/arch/arm26/kernel/setup.c 2004-05-27 18:34:14.000000000 +0100 @@ -76,7 +76,6 @@ unsigned char aux_device_present; char elf_platform[ELF_PLATFORM_SIZE]; -char saved_command_line[COMMAND_LINE_SIZE]; unsigned long phys_initrd_start __initdata = 0; unsigned long phys_initrd_size __initdata = 0; --- diff/arch/cris/kernel/process.c 2004-05-19 22:10:59.000000000 +0100 +++ source/arch/cris/kernel/process.c 2004-05-27 18:34:14.000000000 +0100 @@ -102,6 +102,7 @@ #include #include #include +#include //#define DEBUG --- diff/arch/cris/kernel/setup.c 2004-05-19 22:10:59.000000000 +0100 +++ source/arch/cris/kernel/setup.c 2004-05-27 18:34:14.000000000 +0100 @@ -28,10 +28,7 @@ extern int root_mountflags; extern char _etext, _edata, _end; -#define COMMAND_LINE_SIZE 256 - static char command_line[COMMAND_LINE_SIZE] = { 0, }; - char saved_command_line[COMMAND_LINE_SIZE]; extern const unsigned long text_start, edata; /* set by the linker script */ extern unsigned long dram_start, dram_end; --- diff/arch/h8300/kernel/h8300_ksyms.c 2004-05-27 13:41:10.000000000 +0100 +++ source/arch/h8300/kernel/h8300_ksyms.c 2004-05-27 18:34:14.000000000 +0100 @@ -40,6 +40,8 @@ EXPORT_SYMBOL(ip_fast_csum); EXPORT_SYMBOL(kernel_thread); +EXPORT_SYMBOL(enable_irq); +EXPORT_SYMBOL(disable_irq); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy); --- diff/arch/h8300/kernel/init_task.c 2004-05-19 22:10:59.000000000 +0100 +++ source/arch/h8300/kernel/init_task.c 2004-05-27 18:34:14.000000000 +0100 @@ -7,6 +7,7 @@ #include #include #include +#include #include #include --- diff/arch/h8300/kernel/module.c 2004-05-27 13:41:10.000000000 +0100 +++ source/arch/h8300/kernel/module.c 2004-05-27 18:34:14.000000000 +0100 @@ -67,7 +67,6 @@ Elf32_Sym *sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + ELF32_R_SYM(rela[i].r_info); uint32_t v = sym->st_value + rela[i].r_addend; - uint32_t dot = sechdrs[symindex].sh_addr + rela[i].r_offset; switch (ELF32_R_TYPE(rela[i].r_info)) { case R_H8_DIR24R8: @@ -75,14 +74,15 @@ *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v); break; case R_H8_DIR24A8: - *loc += v; + if (ELF32_R_SYM(rela[i].r_info)) + *loc += v; break; case R_H8_DIR32: case R_H8_DIR32A16: *loc += v; break; case R_H8_PCREL16: - v -= dot + 2; + v -= (unsigned long)loc + 2; if ((Elf32_Sword)v > 0x7fff || (Elf32_Sword)v < -(Elf32_Sword)0x8000) goto overflow; @@ -90,7 +90,7 @@ *(unsigned short *)loc = v; break; case R_H8_PCREL8: - v -= dot + 1; + v -= (unsigned long)loc + 1; if ((Elf32_Sword)v > 0x7f || (Elf32_Sword)v < -(Elf32_Sword)0x80) goto overflow; @@ -105,7 +105,7 @@ } return 0; overflow: - printk(KERN_ERR "module %s: relocation offset overflow: %p\n", + printk(KERN_ERR "module %s: relocation offset overflow: %08x\n", me->name, rela[i].r_offset); return -ENOEXEC; } --- diff/arch/h8300/kernel/setup.c 2004-05-27 13:41:11.000000000 +0100 +++ source/arch/h8300/kernel/setup.c 2004-05-27 18:34:14.000000000 +0100 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -54,8 +55,7 @@ unsigned long memory_start; unsigned long memory_end; -char command_line[512]; -char saved_command_line[512]; +char command_line[COMMAND_LINE_SIZE]; extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end; extern int _ramstart, _ramend; --- diff/arch/i386/Kconfig 2004-05-27 13:41:11.000000000 +0100 +++ source/arch/i386/Kconfig 2004-05-27 18:34:14.000000000 +0100 @@ -434,7 +434,8 @@ Choose N to continue using the legacy 8254 timer. config HPET_EMULATE_RTC - def_bool HPET_TIMER && RTC=y + bool "Provide RTC interrupt" + depends on HPET_TIMER && RTC=y config SMP bool "Symmetric multi-processing support" @@ -849,17 +850,7 @@ default y config REGPARM - bool "Use register arguments (EXPERIMENTAL)" - depends on EXPERIMENTAL - default n - help - Compile the kernel with -mregparm=3. This uses an different ABI - and passes the first three arguments of a function call in registers. - This will probably break binary only modules. - - This feature is only enabled for gcc-3.0 and later - earlier compilers - generate incorrect output with certain kernel constructs when - -mregparm=3 is used. + def_bool y endmenu @@ -1255,6 +1246,15 @@ This results in a large slowdown, but helps to find certain types of memory corruptions. +config SPINLINE + bool "Spinlock inlining" + depends on DEBUG_KERNEL + help + This will change spinlocks from out of line to inline, making them + account cost to the callers in readprofile, rather than the lock + itself (as ".text.lock.filename"). This can be helpful for finding + the callers of locks. + config DEBUG_HIGHMEM bool "Highmem debugging" depends on DEBUG_KERNEL && HIGHMEM @@ -1271,12 +1271,194 @@ Say Y here only if you plan to use gdb to debug the kernel. If you don't debug the kernel, you can say N. +config LOCKMETER + bool "Kernel lock metering" + depends on SMP + help + Say Y to enable kernel lock metering, which adds overhead to SMP locks, + but allows you to see various statistics using the lockstat command. + config DEBUG_SPINLOCK_SLEEP bool "Sleep-inside-spinlock checking" help If you say Y here, various routines which may sleep will become very noisy if they are called with a spinlock held. +config KGDB + bool "Include kgdb kernel debugger" + depends on DEBUG_KERNEL + help + If you say Y here, the system will be compiled with the debug + option (-g) and a debugging stub will be included in the + kernel. This stub communicates with gdb on another (host) + computer via a serial port. The host computer should have + access to the kernel binary file (vmlinux) and a serial port + that is connected to the target machine. Gdb can be made to + configure the serial port or you can use stty and setserial to + do this. See the 'target' command in gdb. This option also + configures in the ability to request a breakpoint early in the + boot process. To request the breakpoint just include 'kgdb' + as a boot option when booting the target machine. The system + will then break as soon as it looks at the boot options. This + option also installs a breakpoint in panic and sends any + kernel faults to the debugger. For more information see the + Documentation/i386/kgdb/kgdb.txt file. + +choice + depends on KGDB + prompt "Debug serial port BAUD" + default KGDB_115200BAUD + help + Gdb and the kernel stub need to agree on the baud rate to be + used. Some systems (x86 family at this writing) allow this to + be configured. + +config KGDB_9600BAUD + bool "9600" + +config KGDB_19200BAUD + bool "19200" + +config KGDB_38400BAUD + bool "38400" + +config KGDB_57600BAUD + bool "57600" + +config KGDB_115200BAUD + bool "115200" +endchoice + +config KGDB_PORT + hex "hex I/O port address of the debug serial port" + depends on KGDB + default 3f8 + help + Some systems (x86 family at this writing) allow the port + address to be configured. The number entered is assumed to be + hex, don't put 0x in front of it. The standard address are: + COM1 3f8 , irq 4 and COM2 2f8 irq 3. Setserial /dev/ttySx + will tell you what you have. It is good to test the serial + connection with a live system before trying to debug. + +config KGDB_IRQ + int "IRQ of the debug serial port" + depends on KGDB + default 4 + help + This is the irq for the debug port. If everything is working + correctly and the kernel has interrupts on a control C to the + port should cause a break into the kernel debug stub. + +config DEBUG_INFO + bool + depends on KGDB + default y + +config KGDB_MORE + bool "Add any additional compile options" + depends on KGDB + default n + help + Saying yes here turns on the ability to enter additional + compile options. + + +config KGDB_OPTIONS + depends on KGDB_MORE + string "Additional compile arguments" + default "-O1" + help + This option allows you enter additional compile options for + the whole kernel compile. Each platform will have a default + that seems right for it. For example on PPC "-ggdb -O1", and + for i386 "-O1". Note that by configuring KGDB "-g" is already + turned on. In addition, on i386 platforms + "-fomit-frame-pointer" is deleted from the standard compile + options. + +config NO_KGDB_CPUS + int "Number of CPUs" + depends on KGDB && SMP + default NR_CPUS + help + + This option sets the number of cpus for kgdb ONLY. It is used + to prune some internal structures so they look "nice" when + displayed with gdb. This is to overcome possibly larger + numbers that may have been entered above. Enter the real + number to get nice clean kgdb_info displays. + +config KGDB_TS + bool "Enable kgdb time stamp macros?" + depends on KGDB + default n + help + Kgdb event macros allow you to instrument your code with calls + to the kgdb event recording function. The event log may be + examined with gdb at a break point. Turning on this + capability also allows you to choose how many events to + keep. Kgdb always keeps the lastest events. + +choice + depends on KGDB_TS + prompt "Max number of time stamps to save?" + default KGDB_TS_128 + +config KGDB_TS_64 + bool "64" + +config KGDB_TS_128 + bool "128" + +config KGDB_TS_256 + bool "256" + +config KGDB_TS_512 + bool "512" + +config KGDB_TS_1024 + bool "1024" + +endchoice + +config STACK_OVERFLOW_TEST + bool "Turn on kernel stack overflow testing?" + depends on KGDB + default n + help + This option enables code in the front line interrupt handlers + to check for kernel stack overflow on interrupts and system + calls. This is part of the kgdb code on x86 systems. + +config KGDB_CONSOLE + bool "Enable serial console thru kgdb port" + depends on KGDB + default n + help + This option enables the command line "console=kgdb" option. + When the system is booted with this option in the command line + all kernel printk output is sent to gdb (as well as to other + consoles). For this to work gdb must be connected. For this + reason, this command line option will generate a breakpoint if + gdb has not yet connected. After the gdb continue command is + given all pent up console output will be printed by gdb on the + host machine. Neither this option, nor KGDB require the + serial driver to be configured. + +config KGDB_SYSRQ + bool "Turn on SysRq 'G' command to do a break?" + depends on KGDB + default y + help + This option includes an option in the SysRq code that allows + you to enter SysRq G which generates a breakpoint to the KGDB + stub. This will work if the keyboard is alive and can + interrupt the system. Because of constraints on when the + serial port interrupt can be enabled, this code may allow you + to interrupt the system before the serial port control C is + available. Just say yes here. + config FRAME_POINTER bool "Compile the kernel with frame pointers" help @@ -1294,6 +1476,19 @@ on the VM subsystem for higher order allocations. This option will also use IRQ stacks to compensate for the reduced stackspace. +config SCHEDSTATS + bool "Collect scheduler statistics" + depends on PROC_FS + default n + help + If you say Y here, additional code will be inserted into the + scheduler and related routines to collect statistics about + scheduler behavior and provide them in /proc/schedstat. These + stats may be useful for both tuning and debugging the scheduler + If you aren't debugging the scheduler or trying to tune a specific + application, you can say N to avoid the very slight overhead + this adds. + config X86_FIND_SMP_CONFIG bool depends on X86_LOCAL_APIC || X86_VOYAGER @@ -1332,12 +1527,6 @@ depends on X86_SMP || (X86_VOYAGER && SMP) default y -# std_resources is overridden for pc9800, but that's not -# a currently selectable arch choice -config X86_STD_RESOURCES - bool - default y - config PC bool depends on X86 && !EMBEDDED --- diff/arch/i386/Makefile 2004-05-27 13:41:11.000000000 +0100 +++ source/arch/i386/Makefile 2004-05-27 18:34:14.000000000 +0100 @@ -98,6 +98,9 @@ # default subarch .h files mflags-y += -Iinclude/asm-i386/mach-default +mflags-$(CONFIG_KGDB) += -gdwarf-2 +mflags-$(CONFIG_KGDB_MORE) += $(shell echo $(CONFIG_KGDB_OPTIONS) | sed -e 's/"//g') + head-y := arch/i386/kernel/head.o arch/i386/kernel/init_task.o libs-y += arch/i386/lib/ --- diff/arch/i386/boot/compressed/misc.c 2004-05-19 22:11:00.000000000 +0100 +++ source/arch/i386/boot/compressed/misc.c 2004-05-27 18:34:14.000000000 +0100 @@ -87,12 +87,11 @@ */ static unsigned char *real_mode; /* Pointer to real-mode data */ -#define EXT_MEM_K (*(unsigned short *)(real_mode + 0x2)) +#define RM_EXT_MEM_K (*(unsigned short *)(real_mode + 0x2)) #ifndef STANDARD_MEMORY_BIOS_CALL -#define ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0)) +#define RM_ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0)) #endif -#define SCREEN_INFO (*(struct screen_info *)(real_mode+0)) -#define EDID_INFO (*(struct edid_info *)(real_mode+0x440)) +#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0)) extern char input_data[]; extern int input_len; @@ -174,8 +173,8 @@ int x,y,pos; char c; - x = SCREEN_INFO.orig_x; - y = SCREEN_INFO.orig_y; + x = RM_SCREEN_INFO.orig_x; + y = RM_SCREEN_INFO.orig_y; while ( ( c = *s++ ) != '\0' ) { if ( c == '\n' ) { @@ -196,8 +195,8 @@ } } - SCREEN_INFO.orig_x = x; - SCREEN_INFO.orig_y = y; + RM_SCREEN_INFO.orig_x = x; + RM_SCREEN_INFO.orig_y = y; pos = (x + cols * y) * 2; /* Update cursor position */ outb_p(14, vidport); @@ -306,9 +305,9 @@ static void setup_normal_output_buffer(void) { #ifdef STANDARD_MEMORY_BIOS_CALL - if (EXT_MEM_K < 1024) error("Less than 2MB of memory"); + if (RM_EXT_MEM_K < 1024) error("Less than 2MB of memory"); #else - if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory"); + if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < 1024) error("Less than 2MB of memory"); #endif output_data = (char *)0x100000; /* Points to 1M */ free_mem_end_ptr = (long)real_mode; @@ -323,9 +322,11 @@ { high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE); #ifdef STANDARD_MEMORY_BIOS_CALL - if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory"); + if (RM_EXT_MEM_K < (3*1024)) error("Less than 4MB of memory"); #else - if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory"); + if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < + (3*1024)) + error("Less than 4MB of memory"); #endif mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START; low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX @@ -358,7 +359,7 @@ { real_mode = rmode; - if (SCREEN_INFO.orig_video_mode == 7) { + if (RM_SCREEN_INFO.orig_video_mode == 7) { vidmem = (char *) 0xb0000; vidport = 0x3b4; } else { @@ -366,8 +367,8 @@ vidport = 0x3d4; } - lines = SCREEN_INFO.orig_video_lines; - cols = SCREEN_INFO.orig_video_cols; + lines = RM_SCREEN_INFO.orig_video_lines; + cols = RM_SCREEN_INFO.orig_video_cols; if (free_mem_ptr < 0x100000) setup_normal_output_buffer(); else setup_output_buffer_if_we_run_high(mv); --- diff/arch/i386/kernel/Makefile 2004-05-19 22:11:00.000000000 +0100 +++ source/arch/i386/kernel/Makefile 2004-05-27 18:34:14.000000000 +0100 @@ -14,6 +14,7 @@ obj-$(CONFIG_ACPI_BOOT) += acpi/ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o obj-$(CONFIG_MCA) += mca.o +obj-$(CONFIG_KGDB) += kgdb_stub.o obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_MICROCODE) += microcode.o @@ -31,7 +32,6 @@ obj-$(CONFIG_HPET_TIMER) += time_hpet.o obj-$(CONFIG_EFI) += efi.o efi_stub.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -obj-$(CONFIG_X86_STD_RESOURCES) += std_resources.o EXTRA_AFLAGS := -traditional --- diff/arch/i386/kernel/acpi/boot.c 2004-05-27 13:41:11.000000000 +0100 +++ source/arch/i386/kernel/acpi/boot.c 2004-05-27 18:34:14.000000000 +0100 @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -437,6 +437,34 @@ return 0; } +#ifdef CONFIG_ACPI_PCI +unsigned int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low) +{ + static u16 irq_mask; + unsigned int irq; + extern void eisa_set_level_irq(unsigned int irq); + + /* + * Make sure all (legacy) PCI IRQs are set as level-triggered. + */ + if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) { + if ((gsi < 16) && !((1 << gsi) & irq_mask)) { + Dprintk(KERN_DEBUG PREFIX "Setting GSI %u as level-triggered\n", gsi); + irq_mask |= (1 << gsi); + eisa_set_level_irq(gsi); + } + } + +#ifdef CONFIG_X86_IO_APIC + if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) { + mp_register_gsi(gsi, edge_level, active_high_low); + } +#endif + acpi_gsi_to_irq(gsi, &irq); + return irq; +} +#endif /* CONFIG_ACPI_PCI */ + static unsigned long __init acpi_scan_rsdp ( unsigned long start, --- diff/arch/i386/kernel/apic.c 2004-05-19 22:11:00.000000000 +0100 +++ source/arch/i386/kernel/apic.c 2004-05-27 18:34:14.000000000 +0100 @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include --- diff/arch/i386/kernel/cpu/common.c 2004-05-27 13:41:11.000000000 +0100 +++ source/arch/i386/kernel/cpu/common.c 2004-05-27 18:34:14.000000000 +0100 @@ -201,6 +201,8 @@ { struct cpuinfo_x86 *c = &boot_cpu_data; + c->x86_cache_alignment = 32; + if (!have_cpuid_p()) return; @@ -213,8 +215,6 @@ get_cpu_vendor(c, 1); c->x86 = 4; - c->x86_cache_alignment = 32; - if (c->cpuid_level >= 0x00000001) { u32 junk, tfms, cap0, misc; cpuid(0x00000001, &tfms, &misc, &junk, &cap0); --- diff/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c 2004-05-27 13:41:11.000000000 +0100 +++ source/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c 2004-05-27 18:34:14.000000000 +0100 @@ -75,7 +75,6 @@ #include #include -#include #include #include #include --- diff/arch/i386/kernel/cpu/cpufreq/longhaul.c 2004-05-27 13:41:11.000000000 +0100 +++ source/arch/i386/kernel/cpu/cpufreq/longhaul.c 2004-05-27 18:34:14.000000000 +0100 @@ -18,7 +18,8 @@ */ #include -#include +#include +#include #include #include #include @@ -30,25 +31,25 @@ #include "longhaul.h" -#define DEBUG - -#ifdef DEBUG -#define dprintk(msg...) printk(msg) -#else -#define dprintk(msg...) do { } while(0) -#endif - #define PFX "longhaul: " static unsigned int numscales=16, numvscales; +static unsigned int fsb; static int minvid, maxvid; static int can_scale_voltage; static int vrmrev; - /* Module parameters */ static int dont_scale_voltage; -static unsigned int fsb; +static int debug; +static int debug; + +static void dprintk(const char *msg, ...) +{ + if (debug == 1) + printk(msg); +} + #define __hlt() __asm__ __volatile__("hlt": : :"memory") @@ -118,8 +119,7 @@ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - dprintk (KERN_INFO PFX "FSB:%d Mult:%d.%dx\n", fsb, - mult/10, mult%10); + dprintk (KERN_INFO PFX "FSB:%d Mult:%d.%dx\n", fsb, mult/10, mult%10); switch (longhaul_version) { case 1: @@ -167,16 +167,16 @@ longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; longhaul.bits.EnableSoftBusRatio = 1; - + longhaul.bits.RevisionKey = 0x0; - + wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); __hlt(); - + rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); longhaul.bits.EnableSoftBusRatio = 0; longhaul.bits.RevisionKey = 0xf; - wrmsrl (MSR_VIA_LONGHAUL, longhaul.val); + wrmsrl (MSR_VIA_LONGHAUL, longhaul.val); break; } @@ -276,26 +276,26 @@ break; } break; - + case 4: rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); - + //TODO: Nehemiah may have borken MaxMHzBR. // need to extrapolate from FSB. - + invalue2 = longhaul.bits.MinMHzBR; invalue = longhaul.bits.MaxMHzBR; - if (longhaul.bits.MaxMHzBR4) + if (longhaul.bits.MaxMHzBR4) invalue += 16; maxmult=multipliers[invalue]; - + maxmult=longhaul_get_cpu_mult(); - + printk(KERN_INFO PFX " invalue: %ld maxmult: %d \n", invalue, maxmult); printk(KERN_INFO PFX " invalue2: %ld \n", invalue2); - + minmult=50; - + switch (longhaul.bits.MaxMHzFSB) { case 0x0: fsb=133; break; @@ -306,8 +306,8 @@ case 0x3: fsb=66; break; } - - break; + + break; } dprintk (KERN_INFO PFX "MinMult=%d.%dx MaxMult=%d.%dx\n", @@ -418,13 +418,13 @@ unsigned int relation) { unsigned int table_index = 0; - unsigned int new_clock_ratio = 0; + unsigned int new_clock_ratio = 0; if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index)) return -EINVAL; new_clock_ratio = longhaul_table[table_index].index & 0xFF; - + longhaul_setstate(new_clock_ratio); return 0; @@ -500,7 +500,6 @@ break; } break; - default: cpuname = "Unknown"; @@ -514,11 +513,11 @@ if (ret != 0) return ret; - if ((longhaul_version==2) && (dont_scale_voltage==0)) + if ((longhaul_version==2) && (dont_scale_voltage==0)) longhaul_setup_voltagescaling(); policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = calc_speed (longhaul_get_cpu_mult(), fsb); ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table); @@ -542,14 +541,14 @@ }; static struct cpufreq_driver longhaul_driver = { - .verify = longhaul_verify, - .target = longhaul_target, - .get = longhaul_get, - .init = longhaul_cpu_init, - .exit = longhaul_cpu_exit, - .name = "longhaul", - .owner = THIS_MODULE, - .attr = longhaul_attr, + .verify = longhaul_verify, + .target = longhaul_target, + .get = longhaul_get, + .init = longhaul_cpu_init, + .exit = longhaul_cpu_exit, + .name = "longhaul", + .owner = THIS_MODULE, + .attr = longhaul_attr, }; static int __init longhaul_init (void) @@ -560,12 +559,8 @@ return -ENODEV; switch (c->x86_model) { - case 6 ... 8: + case 6 ... 9: return cpufreq_register_driver(&longhaul_driver); - case 9: - printk (KERN_INFO PFX "Nehemiah unsupported: Waiting on working silicon " - "from VIA before this is usable.\n"); - break; default: printk (KERN_INFO PFX "Unknown VIA CPU. Contact davej@codemonkey.org.uk\n"); } @@ -579,7 +574,11 @@ kfree(longhaul_table); } -MODULE_PARM (dont_scale_voltage, "i"); +module_param (dont_scale_voltage, int, 0644); +MODULE_PARM_DESC(dont_scale_voltage, "Don't scale voltage of processor"); + +module_param (debug, int, 0644); +MODULE_PARM_DESC(debug, "Dump debugging information."); MODULE_AUTHOR ("Dave Jones "); MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); --- diff/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c 2004-05-27 13:41:11.000000000 +0100 +++ source/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c 2004-05-27 18:34:14.000000000 +0100 @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -35,7 +34,7 @@ #include "speedstep-lib.h" -#define PFX "cpufreq: " +#define PFX "p4-clockmod: " /* * Duty Cycle (3bits), note DC_DISABLE is not specified in --- diff/arch/i386/kernel/cpu/cpufreq/powernow-k7.c 2004-05-27 13:41:11.000000000 +0100 +++ source/arch/i386/kernel/cpu/cpufreq/powernow-k7.c 2004-05-27 18:34:14.000000000 +0100 @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include #include @@ -86,7 +86,7 @@ /* divide by 10 to get FID. */ static int fid_codes[32] = { 110, 115, 120, 125, 50, 55, 60, 65, - 70, 75, 80, 85, 90, 95, 100, 105, + 70, 75, 80, 85, 90, 95, 100, 105, 30, 190, 40, 200, 130, 135, 140, 210, 150, 225, 160, 165, 170, 180, -1, -1, }; @@ -144,6 +144,11 @@ } cpuid(0x80000007, &eax, &ebx, &ecx, &edx); + + /* Check we can actually do something before we say anything.*/ + if (!(edx & (1 << 1 | 1 << 2))) + return 0; + printk (KERN_INFO PFX "PowerNOW! Technology present. Can scale: "); if (edx & 1 << 1) { @@ -159,11 +164,6 @@ can_scale_vid=1; } - if (!(edx & (1 << 1 | 1 << 2))) { - printk ("nothing.\n"); - return 0; - } - printk (".\n"); return 1; } --- diff/arch/i386/kernel/cpu/cpufreq/powernow-k8.c 2004-05-27 13:41:11.000000000 +0100 +++ source/arch/i386/kernel/cpu/cpufreq/powernow-k8.c 2004-05-27 18:34:14.000000000 +0100 @@ -553,7 +553,7 @@ printk(KERN_ERR PFX "no p states to transition\n"); return -ENODEV; } - + if (check_pst_table(data, pst, maxvid)) return -EINVAL; @@ -736,9 +736,9 @@ /* verify only 1 entry from the lo frequency table */ if ((fid < HI_FID_TABLE_BOTTOM) && (cntlofreq++)) { printk(KERN_ERR PFX "Too many lo freq table entries\n"); - goto err_out; + goto err_out_mem; } - + if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) { printk(KERN_INFO PFX "invalid freq entries %u kHz vs. %u kHz\n", powernow_table[i].frequency, @@ -757,12 +757,16 @@ print_basics(data); powernow_k8_acpi_pst_values(data, 0); return 0; + +err_out_mem: + kfree(powernow_table); + err_out: acpi_processor_unregister_performance(&data->acpi_data, data->cpu); /* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */ data->acpi_data.state_count = 0; - + return -ENODEV; } @@ -1047,7 +1051,7 @@ if (query_current_values_with_pending_wait(data)) goto out; - khz = find_khz_freq_from_fid(data->currfid); + khz = find_khz_freq_from_fid(data->currfid); out: preempt_enable_no_resched(); --- diff/arch/i386/kernel/dmi_scan.c 2004-05-19 22:11:00.000000000 +0100 +++ source/arch/i386/kernel/dmi_scan.c 2004-05-27 18:34:14.000000000 +0100 @@ -401,6 +401,23 @@ } /* + * HP Proliant 8500 systems can't use i8042 in mux mode, + * or they instantly reboot. + */ +#ifdef CONFIG_SERIO_I8042 +extern unsigned int i8042_nomux; +static __init int set_8042_nomux(struct dmi_blacklist *d) +{ + if (i8042_nomux == 0) + { + i8042_nomux = 1; + printk(KERN_INFO "Disabling i8042 mux mode\n"); + } + return 0; +} +#endif + +/* * This bios swaps the APM minute reporting bytes over (Many sony laptops * have this problem). */ @@ -924,6 +941,14 @@ MATCH(DMI_PRODUCT_NAME, "ProLiant ML350 G3"), NO_MATCH, NO_MATCH }}, +#ifdef CONFIG_SERIO_I8042 + { set_8042_nomux, "Compaq Proliant 8500", { + MATCH(DMI_SYS_VENDOR, "Compaq"), + MATCH(DMI_PRODUCT_NAME , "ProLiant"), + MATCH(DMI_PRODUCT_VERSION, "8500"), + NO_MATCH }}, +#endif + { force_acpi_ht, "Compaq Workstation W8000", { MATCH(DMI_SYS_VENDOR, "Compaq"), MATCH(DMI_PRODUCT_NAME, "Workstation W8000"), --- diff/arch/i386/kernel/efi.c 2004-05-19 22:11:00.000000000 +0100 +++ source/arch/i386/kernel/efi.c 2004-05-27 18:34:14.000000000 +0100 @@ -37,7 +37,6 @@ #include #include #include -#include #include #define EFI_DEBUG 0 --- diff/arch/i386/kernel/entry.S 2004-05-27 13:41:11.000000000 +0100 +++ source/arch/i386/kernel/entry.S 2004-05-27 18:34:14.000000000 +0100 @@ -48,6 +48,18 @@ #include #include #include "irq_vectors.h" + /* We do not recover from a stack overflow, but at least + * we know it happened and should be able to track it down. + */ +#ifdef CONFIG_STACK_OVERFLOW_TEST +#define STACK_OVERFLOW_TEST \ + testl $(THREAD_SIZE - 512),%esp; \ + jnz 10f; \ + call stack_overflow; \ +10: +#else +#define STACK_OVERFLOW_TEST +#endif #define nr_syscalls ((syscall_table_size)/4) @@ -94,7 +106,8 @@ pushl %ebx; \ movl $(__USER_DS), %edx; \ movl %edx, %ds; \ - movl %edx, %es; + movl %edx, %es; \ + STACK_OVERFLOW_TEST #define RESTORE_INT_REGS \ popl %ebx; \ @@ -294,6 +307,19 @@ testw $_TIF_ALLWORK_MASK, %cx # current->work jne syscall_exit_work restore_all: +#ifdef CONFIG_TRAP_BAD_SYSCALL_EXITS + movl EFLAGS(%esp), %eax # mix EFLAGS and CS + movb CS(%esp), %al + testl $(VM_MASK | 3), %eax + jz resume_kernelX # returning to kernel or vm86-space + + cmpl $0,TI_PRE_COUNT(%ebx) # non-zero preempt_count ? + jz resume_kernelX + + int $3 + +resume_kernelX: +#endif RESTORE_ALL # perform work that needs to be done immediately before resumption @@ -348,7 +374,7 @@ # perform syscall exit tracing ALIGN syscall_exit_work: - testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT), %cl + testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl jz work_pending sti # could let do_syscall_trace() call # schedule() instead --- diff/arch/i386/kernel/i386_ksyms.c 2004-05-19 22:11:00.000000000 +0100 +++ source/arch/i386/kernel/i386_ksyms.c 2004-05-27 18:34:14.000000000 +0100 @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include --- diff/arch/i386/kernel/i8259.c 2004-05-19 22:11:00.000000000 +0100 +++ source/arch/i386/kernel/i8259.c 2004-05-27 18:34:14.000000000 +0100 @@ -317,16 +317,11 @@ * be shot. */ -/* - * =PC9800NOTE= In NEC PC-9800, we use irq8 instead of irq13! - */ static irqreturn_t math_error_irq(int cpl, void *dev_id, struct pt_regs *regs) { extern void math_error(void *); -#ifndef CONFIG_X86_PC9800 outb(0,0xF0); -#endif if (ignore_fpu_irq || !boot_cpu_data.hard_math) return IRQ_NONE; math_error((void *)regs->eip); --- diff/arch/i386/kernel/init_task.c 2004-05-19 22:11:00.000000000 +0100 +++ source/arch/i386/kernel/init_task.c 2004-05-27 18:34:14.000000000 +0100 @@ -4,6 +4,7 @@ #include #include #include +#include #include #include --- diff/arch/i386/kernel/io_apic.c 2004-05-27 13:41:11.000000000 +0100 +++ source/arch/i386/kernel/io_apic.c 2004-05-27 18:34:14.000000000 +0100 @@ -41,8 +41,6 @@ #include "io_ports.h" -#undef APIC_LOCKUP_DEBUG - #define APIC_LOCKUP_DEBUG static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED; @@ -127,8 +125,7 @@ } } -/* mask = 1 */ -static void __mask_IO_APIC_irq (unsigned int irq) +static inline void __modify_IO_APIC_irq (unsigned int irq, unsigned long enable, unsigned long disable) { int pin; struct irq_pin_list *entry = irq_2_pin + irq; @@ -139,71 +136,39 @@ if (pin == -1) break; reg = io_apic_read(entry->apic, 0x10 + pin*2); - io_apic_modify(entry->apic, 0x10 + pin*2, reg |= 0x00010000); + reg &= ~disable; + reg |= enable; + io_apic_modify(entry->apic, 0x10 + pin*2, reg); if (!entry->next) break; entry = irq_2_pin + entry->next; } - io_apic_sync(entry->apic); } -/* mask = 0 */ -static void __unmask_IO_APIC_irq (unsigned int irq) +/* mask = 1 */ +static void __mask_IO_APIC_irq (unsigned int irq) { - int pin; struct irq_pin_list *entry = irq_2_pin + irq; + __modify_IO_APIC_irq(irq, 0x00010000, 0); + io_apic_sync(entry->apic); /* Is it needed? Or do others need it too? */ +} - for (;;) { - unsigned int reg; - pin = entry->pin; - if (pin == -1) - break; - reg = io_apic_read(entry->apic, 0x10 + pin*2); - io_apic_modify(entry->apic, 0x10 + pin*2, reg &= 0xfffeffff); - if (!entry->next) - break; - entry = irq_2_pin + entry->next; - } +/* mask = 0 */ +static void __unmask_IO_APIC_irq (unsigned int irq) +{ + __modify_IO_APIC_irq(irq, 0, 0x00010000); } /* mask = 1, trigger = 0 */ static void __mask_and_edge_IO_APIC_irq (unsigned int irq) { - int pin; - struct irq_pin_list *entry = irq_2_pin + irq; - - for (;;) { - unsigned int reg; - pin = entry->pin; - if (pin == -1) - break; - reg = io_apic_read(entry->apic, 0x10 + pin*2); - reg = (reg & 0xffff7fff) | 0x00010000; - io_apic_modify(entry->apic, 0x10 + pin*2, reg); - if (!entry->next) - break; - entry = irq_2_pin + entry->next; - } + __modify_IO_APIC_irq(irq, 0x00010000, 0x00008000); } /* mask = 0, trigger = 1 */ static void __unmask_and_level_IO_APIC_irq (unsigned int irq) { - int pin; - struct irq_pin_list *entry = irq_2_pin + irq; - - for (;;) { - unsigned int reg; - pin = entry->pin; - if (pin == -1) - break; - reg = io_apic_read(entry->apic, 0x10 + pin*2); - reg = (reg & 0xfffeffff) | 0x00008000; - io_apic_modify(entry->apic, 0x10 + pin*2, reg); - if (!entry->next) - break; - entry = irq_2_pin + entry->next; - } + __modify_IO_APIC_irq(irq, 0x00008000, 0x00010000); } static void mask_IO_APIC_irq (unsigned int irq) @@ -853,7 +818,7 @@ * we need to reprogram the ioredtbls to cater for the cpus which have come online * so mask in all cases should simply be TARGET_CPUS */ -void __init setup_ioapic_dest(cpumask_t mask) +void __init setup_ioapic_dest(void) { int pin, ioapic, irq, irq_entry; @@ -866,7 +831,7 @@ if (irq_entry == -1) continue; irq = pin_2_irq(irq_entry, ioapic, pin); - set_ioapic_affinity_irq(irq, mask); + set_ioapic_affinity_irq(irq, TARGET_CPUS); } } --- diff/arch/i386/kernel/irq.c 2004-05-19 22:11:00.000000000 +0100 +++ source/arch/i386/kernel/irq.c 2004-05-27 18:34:14.000000000 +0100 @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -570,6 +569,8 @@ irq_exit(); + kgdb_process_breakpoint(); + return 1; } @@ -1117,8 +1118,8 @@ #ifdef CONFIG_4KSTACKS -static char softirq_stack[NR_CPUS * THREAD_SIZE] __attribute__((__aligned__(THREAD_SIZE))); -static char hardirq_stack[NR_CPUS * THREAD_SIZE] __attribute__((__aligned__(THREAD_SIZE))); +static char softirq_stack[NR_CPUS * THREAD_SIZE] __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned"))); +static char hardirq_stack[NR_CPUS * THREAD_SIZE] __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned"))); /* * allocate per-cpu stacks for hardirq and for softirq processing --- diff/arch/i386/kernel/mpparse.c 2004-05-27 13:41:11.000000000 +0100 +++ source/arch/i386/kernel/mpparse.c 2004-05-27 18:34:14.000000000 +0100 @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -1025,96 +1024,56 @@ } } -extern FADT_DESCRIPTOR acpi_fadt; - -#ifdef CONFIG_ACPI_PCI - int (*platform_rename_gsi)(int ioapic, int gsi); -void __init mp_parse_prt (void) +void mp_register_gsi (u32 gsi, int edge_level, int active_high_low) { - struct list_head *node = NULL; - struct acpi_prt_entry *entry = NULL; int ioapic = -1; int ioapic_pin = 0; - int gsi = 0; int idx, bit = 0; - int edge_level = 0; - int active_high_low = 0; - /* - * Parsing through the PCI Interrupt Routing Table (PRT) and program - * routing for all entries. - */ - list_for_each(node, &acpi_prt.entries) { - entry = list_entry(node, struct acpi_prt_entry, node); +#ifdef CONFIG_ACPI_BUS + /* Don't set up the ACPI SCI because it's already set up */ + if (acpi_fadt.sci_int == gsi) + return; +#endif - /* Need to get gsi for dynamic entry */ - if (entry->link.handle) { - gsi = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low); - if (!gsi) - continue; - } - else { - /* Hardwired GSI. Assume PCI standard settings */ - gsi = entry->link.index; - edge_level = 1; - active_high_low = 1; - } + ioapic = mp_find_ioapic(gsi); + if (ioapic < 0) { + printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); + return; + } - /* Don't set up the ACPI SCI because it's already set up */ - if (acpi_fadt.sci_int == gsi) { - /* we still need to set entry's irq */ - acpi_gsi_to_irq(gsi, &entry->irq); - continue; - } - - ioapic = mp_find_ioapic(gsi); - if (ioapic < 0) - continue; - ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; - - if (platform_rename_gsi) - gsi = platform_rename_gsi(ioapic, gsi); - - /* - * Avoid pin reprogramming. PRTs typically include entries - * with redundant pin->gsi mappings (but unique PCI devices); - * we only only program the IOAPIC on the first. - */ - bit = ioapic_pin % 32; - idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32); - if (idx > 3) { - printk(KERN_ERR "Invalid reference to IOAPIC pin " - "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, - ioapic_pin); - continue; - } - if ((1<irq); - continue; - } + ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; - mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<irq); - } - printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d %s %s\n", - entry->id.segment, entry->id.bus, - entry->id.device, ('A' + entry->pin), - mp_ioapic_routing[ioapic].apic_id, ioapic_pin, - entry->irq, edge_level ? "level" : "edge", - active_high_low ? "low" : "high"); + /* + * Avoid pin reprogramming. PRTs typically include entries + * with redundant pin->gsi mappings (but unique PCI devices); + * we only program the IOAPIC on the first. + */ + bit = ioapic_pin % 32; + idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32); + if (idx > 3) { + printk(KERN_ERR "Invalid reference to IOAPIC pin " + "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, + ioapic_pin); + return; + } + if ((1< #include +#ifdef CONFIG_KGDB +#include +#ifdef CONFIG_SMP +unsigned int nmi_watchdog = NMI_IO_APIC; +#else +unsigned int nmi_watchdog = NMI_LOCAL_APIC; +#endif +#else unsigned int nmi_watchdog = NMI_NONE; +#endif static unsigned int nmi_hz = HZ; static unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ static unsigned int nmi_p4_cccr_val; @@ -458,6 +467,9 @@ for (i = 0; i < NR_CPUS; i++) alert_counter[i] = 0; } +#ifdef CONFIG_KGDB +int tune_watchdog = 5*HZ; +#endif void nmi_watchdog_tick (struct pt_regs * regs) { @@ -471,12 +483,24 @@ sum = irq_stat[cpu].apic_timer_irqs; +#ifdef CONFIG_KGDB + if (! in_kgdb(regs) && last_irq_sums[cpu] == sum ) { + +#else if (last_irq_sums[cpu] == sum) { +#endif /* * Ayiee, looks like this CPU is stuck ... * wait a few IRQs (5 seconds) before doing the oops ... */ alert_counter[cpu]++; +#ifdef CONFIG_KGDB + if (alert_counter[cpu] == tune_watchdog) { + kgdb_handle_exception(2, SIGPWR, 0, regs); + last_irq_sums[cpu] = sum; + alert_counter[cpu] = 0; + } +#endif if (alert_counter[cpu] == 5*nmi_hz) { spin_lock(&nmi_print_lock); /* --- diff/arch/i386/kernel/process.c 2004-05-27 13:41:12.000000000 +0100 +++ source/arch/i386/kernel/process.c 2004-05-27 18:34:14.000000000 +0100 @@ -202,6 +202,10 @@ if (!strncmp(str, "poll", 4)) { printk("using polling idle threads.\n"); pm_idle = poll_idle; +#ifdef CONFIG_SMP + if (smp_num_siblings > 1) + printk("WARNING: polling idle and HT enabled, performance may degrade.\n"); +#endif } else if (!strncmp(str, "halt", 4)) { printk("using halt in idle threads.\n"); pm_idle = default_idle; --- diff/arch/i386/kernel/ptrace.c 2004-05-27 13:41:12.000000000 +0100 +++ source/arch/i386/kernel/ptrace.c 2004-05-27 18:34:14.000000000 +0100 @@ -147,6 +147,7 @@ { long tmp; + clear_tsk_thread_flag(child, TIF_SINGLESTEP); tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; put_stack_long(child, EFL_OFFSET, tmp); } @@ -369,6 +370,7 @@ else { clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); } + clear_tsk_thread_flag(child, TIF_SINGLESTEP); child->exit_code = data; /* make sure the single step bit is not set. */ tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; @@ -390,6 +392,7 @@ if (child->state == TASK_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; + clear_tsk_thread_flag(child, TIF_SINGLESTEP); /* make sure the single step bit is not set. */ tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; put_stack_long(child, EFL_OFFSET, tmp); @@ -410,6 +413,7 @@ } tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG; put_stack_long(child, EFL_OFFSET, tmp); + set_tsk_thread_flag(child, TIF_SINGLESTEP); child->exit_code = data; /* give it a chance to run. */ wake_up_process(child); @@ -534,7 +538,8 @@ audit_syscall_exit(current, regs->eax); } - if (!test_thread_flag(TIF_SYSCALL_TRACE)) + if (!test_thread_flag(TIF_SYSCALL_TRACE) && + !test_thread_flag(TIF_SINGLESTEP)) return; if (!(current->ptrace & PT_PTRACED)) return; --- diff/arch/i386/kernel/setup.c 2004-05-27 13:41:12.000000000 +0100 +++ source/arch/i386/kernel/setup.c 2004-05-27 18:34:14.000000000 +0100 @@ -47,7 +47,7 @@ #include #include #include -#include +#include #include "setup_arch_pre.h" /* This value is set up by the early boot code to point to the value @@ -129,12 +129,206 @@ #define RAMDISK_LOAD_FLAG 0x4000 static char command_line[COMMAND_LINE_SIZE]; - char saved_command_line[COMMAND_LINE_SIZE]; unsigned char __initdata boot_params[PARAM_SIZE]; -static struct resource code_resource = { "Kernel code", 0x100000, 0 }; -static struct resource data_resource = { "Kernel data", 0, 0 }; +static struct resource data_resource = { + .name = "Kernel data", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; + +static struct resource code_resource = { + .name = "Kernel code", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; + +static struct resource system_rom_resource = { + .name = "System ROM", + .start = 0xf0000, + .end = 0xfffff, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}; + +static struct resource extension_rom_resource = { + .name = "Extension ROM", + .start = 0xe0000, + .end = 0xeffff, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}; + +static struct resource adapter_rom_resources[] = { { + .name = "Adapter ROM", + .start = 0xc8000, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}, { + .name = "Adapter ROM", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}, { + .name = "Adapter ROM", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}, { + .name = "Adapter ROM", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}, { + .name = "Adapter ROM", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}, { + .name = "Adapter ROM", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +} }; + +#define ADAPTER_ROM_RESOURCES \ + (sizeof adapter_rom_resources / sizeof adapter_rom_resources[0]) + +static struct resource video_rom_resource = { + .name = "Video ROM", + .start = 0xc0000, + .end = 0xc7fff, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}; + +static struct resource video_ram_resource = { + .name = "Video RAM area", + .start = 0xa0000, + .end = 0xbffff, + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; + +static struct resource standard_io_resources[] = { { + .name = "dma1", + .start = 0x0000, + .end = 0x001f, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "pic1", + .start = 0x0020, + .end = 0x0021, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "timer", + .start = 0x0040, + .end = 0x005f, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "keyboard", + .start = 0x0060, + .end = 0x006f, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "dma page reg", + .start = 0x0080, + .end = 0x008f, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "pic2", + .start = 0x00a0, + .end = 0x00a1, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "dma2", + .start = 0x00c0, + .end = 0x00df, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "fpu", + .start = 0x00f0, + .end = 0x00ff, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +} }; + +#define STANDARD_IO_RESOURCES \ + (sizeof standard_io_resources / sizeof standard_io_resources[0]) + +#define romsignature(x) (*(unsigned short *)(x) == 0xaa55) + +static int __init romchecksum(unsigned char *rom, unsigned long length) +{ + unsigned char *p, sum = 0; + + for (p = rom; p < rom + length; p++) + sum += *p; + return sum == 0; +} + +static void __init probe_roms(void) +{ + unsigned long start, length, upper; + unsigned char *rom; + int i; + + /* video rom */ + upper = adapter_rom_resources[0].start; + for (start = video_rom_resource.start; start < upper; start += 2048) { + rom = isa_bus_to_virt(start); + if (!romsignature(rom)) + continue; + + video_rom_resource.start = start; + + /* 0 < length <= 0x7f * 512, historically */ + length = rom[2] * 512; + + /* if checksum okay, trust length byte */ + if (length && romchecksum(rom, length)) + video_rom_resource.end = start + length - 1; + + request_resource(&iomem_resource, &video_rom_resource); + break; + } + + start = (video_rom_resource.end + 1 + 2047) & ~2047UL; + if (start < upper) + start = upper; + + /* system rom */ + request_resource(&iomem_resource, &system_rom_resource); + upper = system_rom_resource.start; + + /* check for extension rom (ignore length byte!) */ + rom = isa_bus_to_virt(extension_rom_resource.start); + if (romsignature(rom)) { + length = extension_rom_resource.end - extension_rom_resource.start + 1; + if (romchecksum(rom, length)) { + request_resource(&iomem_resource, &extension_rom_resource); + upper = extension_rom_resource.start; + } + } + + /* check for adapter roms on 2k boundaries */ + for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) { + rom = isa_bus_to_virt(start); + if (!romsignature(rom)) + continue; + + /* 0 < length <= 0x7f * 512, historically */ + length = rom[2] * 512; + + /* but accept any length that fits if checksum okay */ + if (!length || start + length > upper || !romchecksum(rom, length)) + continue; + + adapter_rom_resources[i].start = start; + adapter_rom_resources[i].end = start + length - 1; + request_resource(&iomem_resource, &adapter_rom_resources[i]); + + start = adapter_rom_resources[i++].end & ~2047UL; + } +} static void __init limit_regions(unsigned long long size) { @@ -948,6 +1142,7 @@ static void __init register_memory(unsigned long max_low_pfn) { unsigned long low_mem_size; + int i; if (efi_enabled) efi_initialize_iomem_resources(&code_resource, &data_resource); @@ -955,10 +1150,11 @@ legacy_init_iomem_resources(&code_resource, &data_resource); /* EFI systems may still have VGA */ - request_graphics_resource(); + request_resource(&iomem_resource, &video_ram_resource); /* request I/O space for devices used on all i[345]86 PCs */ - request_standard_io_resources(); + for (i = 0; i < STANDARD_IO_RESOURCES; i++) + request_resource(&ioport_resource, &standard_io_resources[i]); /* Tell the PCI layer not to allocate too close to the RAM area.. */ low_mem_size = ((max_low_pfn << PAGE_SHIFT) + 0xfffff) & ~0xfffff; --- diff/arch/i386/kernel/smp.c 2004-05-27 13:41:12.000000000 +0100 +++ source/arch/i386/kernel/smp.c 2004-05-27 18:34:15.000000000 +0100 @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -466,7 +465,17 @@ { on_each_cpu(do_flush_tlb_all, 0, 1, 1); } - +#ifdef CONFIG_KGDB +/* + * By using the NMI code instead of a vector we just sneak thru the + * word generator coming out with just what we want. AND it does + * not matter if clustered_apic_mode is set or not. + */ +void smp_send_nmi_allbutself(void) +{ + send_IPI_allbutself(APIC_DM_NMI); +} +#endif /* * this function sends a 'reschedule' IPI to another CPU. * it goes straight through and wastes no time serializing --- diff/arch/i386/kernel/smpboot.c 2004-05-27 13:41:12.000000000 +0100 +++ source/arch/i386/kernel/smpboot.c 2004-05-27 18:34:15.000000000 +0100 @@ -47,7 +47,6 @@ #include #include -#include #include #include #include @@ -1369,8 +1368,7 @@ void __init smp_cpus_done(unsigned int max_cpus) { #ifdef CONFIG_X86_IO_APIC - cpumask_t targets = CPU_MASK_ALL; - setup_ioapic_dest(targets); + setup_ioapic_dest(); #endif zap_low_mappings(); } --- diff/arch/i386/kernel/time_hpet.c 2004-05-19 22:11:00.000000000 +0100 +++ source/arch/i386/kernel/time_hpet.c 2004-05-27 18:34:15.000000000 +0100 @@ -21,6 +21,7 @@ #include #include +#include unsigned long hpet_period; /* fsecs / HPET clock */ unsigned long hpet_tick; /* hpet clks count per tick */ @@ -135,6 +136,51 @@ hpet_writel(cfg, HPET_CFG); use_hpet = 1; + +#ifdef CONFIG_HPET + { + struct hpet_data hd; + unsigned int ntimer; + + memset(&hd, 0, sizeof (hd)); + + ntimer = hpet_readl(HPET_ID); + ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT; + ntimer++; + + /* + * Register with driver. + * Timer0 and Timer1 is used by platform. + */ + hd.hd_address = hpet_virt_address; + hd.hd_nirqs = ntimer; + hd.hd_flags = HPET_DATA_PLATFORM; +#ifndef CONFIG_HPET_EMULATE_RTC + hd.hd_state = 0x1; +#else + hd.hd_state = 0x3; +#endif + hd.hd_irq[0] = HPET_LEGACY_8254; + hd.hd_irq[1] = HPET_LEGACY_RTC; + if (ntimer > 2) { + struct hpet *hpet; + struct hpet_timer *timer; + int i; + + hpet = (struct hpet *) hpet_virt_address; + + for (i = 2, timer = &hpet->hpet_timers[2]; i < ntimer; + timer++, i++) + hd.hd_irq[i] = (timer->hpet_config & + Tn_INT_ROUTE_CNF_MASK) >> + Tn_INT_ROUTE_CNF_SHIFT; + + } + + hpet_alloc(&hd); + } +#endif + #ifdef CONFIG_X86_LOCAL_APIC wait_timer_tick = wait_hpet_tick; #endif --- diff/arch/i386/kernel/traps.c 2004-05-27 13:41:12.000000000 +0100 +++ source/arch/i386/kernel/traps.c 2004-05-27 18:34:15.000000000 +0100 @@ -47,7 +47,6 @@ #include #include -#include #include #include @@ -103,8 +102,42 @@ return 1; } +#ifdef CONFIG_KGDB +extern void sysenter_entry(void); +#include +#include +void set_intr_gate(unsigned int n, void *addr); +static void set_intr_usr_gate(unsigned int n, void *addr); +/* + * Should be able to call this breakpoint() very early in + * bring up. Just hard code the call where needed. + * The breakpoint() code is here because set_?_gate() functions + * are local (static) to trap.c. They need be done only once, + * but it does not hurt to do them over. + */ +void breakpoint(void) +{ + set_intr_usr_gate(3,&int3); /* disable ints on trap */ + set_intr_gate(1,&debug); + set_intr_gate(14,&page_fault); + + BREAKPOINT; +} +#define CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after) \ + { \ + if (!user_mode(regs) ) \ + { \ + kgdb_handle_exception(trapnr, signr, error_code, regs); \ + after; \ + } else if ((trapnr == 3) && (regs->eflags &0x200)) local_irq_enable(); \ + } +#else +#define CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,after) +#endif + + #ifdef CONFIG_FRAME_POINTER -void print_context_stack(struct task_struct *task, unsigned long *stack, +static void print_context_stack(struct task_struct *task, unsigned long *stack, unsigned long ebp) { unsigned long addr; @@ -118,7 +151,7 @@ } } #else -void print_context_stack(struct task_struct *task, unsigned long *stack, +static void print_context_stack(struct task_struct *task, unsigned long *stack, unsigned long ebp) { unsigned long addr; @@ -126,8 +159,9 @@ while (!kstack_end(stack)) { addr = *stack++; if (kernel_text_address(addr)) { - printk(" [<%08lx>] ", addr); - print_symbol("%s\n", addr); + printk(" [<%08lx>]", addr); + print_symbol(" %s", addr); + printk("\n"); } } } @@ -217,7 +251,7 @@ ss = regs->xss & 0xffff; } print_modules(); - printk("CPU: %d\nEIP: %04x:[<%08lx>] %s\nEFLAGS: %08lx" + printk("CPU: %d\nEIP: %04x:[<%08lx>] %s VLI\nEFLAGS: %08lx" " (%s) \n", smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags, UTS_RELEASE); @@ -235,23 +269,25 @@ * time of the fault.. */ if (in_kernel) { + u8 *eip; printk("\nStack: "); show_stack(NULL, (unsigned long*)esp); printk("Code: "); - if(regs->eip < PAGE_OFFSET) - goto bad; - for(i=0;i<20;i++) - { + eip = (u8 *)regs->eip - 43; + for (i = 0; i < 64; i++, eip++) { unsigned char c; - if(__get_user(c, &((unsigned char*)regs->eip)[i])) { -bad: + + if (eip < (u8 *)PAGE_OFFSET || __get_user(c, eip)) { printk(" Bad EIP value."); break; } - printk("%02x ", c); + if (eip == (u8 *)regs->eip) + printk("<%02x> ", c); + else + printk("%02x ", c); } } printk("\n"); @@ -319,6 +355,15 @@ #endif if (nl) printk("\n"); +#ifdef CONFIG_KGDB + /* This is about the only place we want to go to kgdb even if in + * user mode. But we must go in via a trap so within kgdb we will + * always be in kernel mode. + */ + if (user_mode(regs)) + BREAKPOINT; +#endif + CHK_REMOTE_DEBUG(0,SIGTRAP,err,regs,) show_registers(regs); bust_spinlocks(0); spin_unlock_irq(&die_lock); @@ -388,6 +433,7 @@ #define DO_ERROR(trapnr, signr, str, name) \ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ { \ + CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,)\ do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \ } @@ -405,7 +451,9 @@ #define DO_VM86_ERROR(trapnr, signr, str, name) \ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ { \ + CHK_REMOTE_DEBUG(trapnr, signr, error_code,regs, return)\ do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \ + return; \ } #define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ @@ -452,8 +500,10 @@ return; gp_in_kernel: - if (!fixup_exception(regs)) + if (!fixup_exception(regs)){ + CHK_REMOTE_DEBUG(13,SIGSEGV,error_code,regs,) die("general protection fault", regs, error_code); + } } static void mem_parity_error(unsigned char reason, struct pt_regs * regs) @@ -615,8 +665,18 @@ * allowing programs to debug themselves without the ptrace() * interface. */ +#ifdef CONFIG_KGDB + /* + * I think this is the only "real" case of a TF in the kernel + * that really belongs to user space. Others are + * "Ours all ours!" + */ + if (((regs->xcs & 3) == 0) && ((void *)regs->eip == sysenter_entry)) + goto clear_TF_reenable; +#else if ((regs->xcs & 3) == 0) goto clear_TF_reenable; +#endif if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE) goto clear_TF; } @@ -628,6 +688,17 @@ info.si_errno = 0; info.si_code = TRAP_BRKPT; +#ifdef CONFIG_KGDB + /* + * If this is a kernel mode trap, we need to reset db7 to allow us + * to continue sanely ALSO skip the signal delivery + */ + if ((regs->xcs & 3) == 0) + goto clear_dr7; + + /* if not kernel, allow ints but only if they were on */ + if ( regs->eflags & 0x200) local_irq_enable(); +#endif /* If this is a kernel mode trap, save the user PC on entry to * the kernel, that's what the debugger can make sense of. */ @@ -642,6 +713,7 @@ __asm__("movl %0,%%db7" : /* no output */ : "r" (0)); + CHK_REMOTE_DEBUG(1,SIGTRAP,error_code,regs,) return; debug_vm86: @@ -890,6 +962,12 @@ { _set_gate(a,12,3,addr,__KERNEL_CS); } +#ifdef CONFIG_KGDB +void set_intr_usr_gate(unsigned int n, void *addr) +{ + _set_gate(idt_table+n,14,3,addr,__KERNEL_CS); +} +#endif static void __init set_task_gate(unsigned int n, unsigned int gdt_entry) { @@ -912,7 +990,11 @@ set_trap_gate(0,÷_error); set_intr_gate(1,&debug); set_intr_gate(2,&nmi); +#ifndef CONFIG_KGDB set_system_gate(3,&int3); /* int3-5 can be called from all */ +#else + set_intr_usr_gate(3,&int3); /* int3-5 can be called from all */ +#endif set_system_gate(4,&overflow); set_system_gate(5,&bounds); set_trap_gate(6,&invalid_op); --- diff/arch/i386/kernel/vm86.c 2004-05-19 22:11:00.000000000 +0100 +++ source/arch/i386/kernel/vm86.c 2004-05-27 18:34:15.000000000 +0100 @@ -44,7 +44,6 @@ #include #include -#include #include #include #include --- diff/arch/i386/lib/Makefile 2004-05-19 22:11:01.000000000 +0100 +++ source/arch/i386/lib/Makefile 2004-05-27 18:34:15.000000000 +0100 @@ -9,3 +9,4 @@ lib-$(CONFIG_X86_USE_3DNOW) += mmx.o lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o +lib-$(CONFIG_KGDB) += kgdb_serial.o --- diff/arch/i386/lib/dec_and_lock.c 2004-05-19 22:11:01.000000000 +0100 +++ source/arch/i386/lib/dec_and_lock.c 2004-05-27 18:34:15.000000000 +0100 @@ -10,6 +10,7 @@ #include #include +#ifndef ATOMIC_DEC_AND_LOCK int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) { int counter; @@ -38,3 +39,5 @@ spin_unlock(lock); return 0; } +#endif + --- diff/arch/i386/mach-visws/traps.c 2004-05-19 22:11:01.000000000 +0100 +++ source/arch/i386/mach-visws/traps.c 2004-05-27 18:34:15.000000000 +0100 @@ -8,7 +8,6 @@ #include #include -#include #include #include #include "cobalt.h" --- diff/arch/i386/mach-voyager/voyager_basic.c 2004-05-19 22:11:01.000000000 +0100 +++ source/arch/i386/mach-voyager/voyager_basic.c 2004-05-27 18:34:15.000000000 +0100 @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include --- diff/arch/i386/mach-voyager/voyager_smp.c 2004-05-27 13:41:12.000000000 +0100 +++ source/arch/i386/mach-voyager/voyager_smp.c 2004-05-27 18:34:15.000000000 +0100 @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include --- diff/arch/i386/mach-voyager/voyager_thread.c 2004-05-19 22:11:01.000000000 +0100 +++ source/arch/i386/mach-voyager/voyager_thread.c 2004-05-27 18:34:15.000000000 +0100 @@ -28,7 +28,6 @@ #include #include #include -#include #include #include --- diff/arch/i386/mm/extable.c 2004-05-19 22:11:02.000000000 +0100 +++ source/arch/i386/mm/extable.c 2004-05-27 18:34:15.000000000 +0100 @@ -5,6 +5,7 @@ #include #include #include + #include int fixup_exception(struct pt_regs *regs) @@ -34,3 +35,15 @@ return 0; } + +int check_exception(struct pt_regs *regs) +{ + const struct exception_table_entry *fixup; + + fixup = search_exception_tables(regs->eip); + if (fixup) { + return 1; + } + + return 0; +} --- diff/arch/i386/mm/fault.c 2004-05-19 22:11:02.000000000 +0100 +++ source/arch/i386/mm/fault.c 2004-05-27 18:34:15.000000000 +0100 @@ -24,7 +24,6 @@ #include #include -#include #include #include @@ -262,7 +261,26 @@ if (in_atomic() || !mm) goto bad_area_nosemaphore; - down_read(&mm->mmap_sem); + /* When running in the kernel we expect faults to occur only to + * addresses in user space. All other faults represent errors in the + * kernel and should generate an OOPS. Unfortunatly, in the case of an + * erroneous fault occuring in a code path which already holds mmap_sem + * we will deadlock attempting to validate the fault against the + * address space. Luckily the kernel only validly references user + * space from well defined areas of code, which are listed in the + * exceptions table. + * + * As the vast majority of faults will be valid we will only perform + * the source reference check when there is a possibilty of a deadlock. + * Attempt to lock the address space, if we cannot we then validate the + * source. If this is invalid we can skip the address space check, + * thus avoiding the deadlock. + */ + if (!down_read_trylock(&mm->mmap_sem)) { + if ((error_code & 4) == 0 && !check_exception(regs)) + goto bad_area_nosemaphore; + down_read(&mm->mmap_sem); + } vma = find_vma(mm, address); if (!vma) @@ -403,6 +421,12 @@ * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ +#ifdef CONFIG_KGDB + if (!user_mode(regs)){ + kgdb_handle_exception(14,SIGBUS, error_code, regs); + return; + } +#endif bust_spinlocks(1); --- diff/arch/i386/mm/hugetlbpage.c 2004-05-27 13:41:12.000000000 +0100 +++ source/arch/i386/mm/hugetlbpage.c 2004-05-27 18:34:15.000000000 +0100 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include --- diff/arch/i386/mm/init.c 2004-05-19 22:11:02.000000000 +0100 +++ source/arch/i386/mm/init.c 2004-05-27 18:34:15.000000000 +0100 @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -328,9 +327,30 @@ #endif } +#if defined(CONFIG_PM_DISK) || defined(CONFIG_SOFTWARE_SUSPEND) +/* + * Swap suspend & friends need this for resume because things like the intel-agp + * driver might have split up a kernel 4MB mapping. + */ +char __nosavedata swsusp_pg_dir[PAGE_SIZE] + __attribute__ ((aligned (PAGE_SIZE))); + +static inline void save_pg_dir(void) +{ + memcpy(swsusp_pg_dir, swapper_pg_dir, PAGE_SIZE); +} +#else +static inline void save_pg_dir(void) +{ +} +#endif + void zap_low_mappings (void) { int i; + + save_pg_dir(); + /* * Zap initial low-memory mappings. * --- diff/arch/i386/mm/ioremap.c 2004-05-19 22:11:02.000000000 +0100 +++ source/arch/i386/mm/ioremap.c 2004-05-27 18:34:15.000000000 +0100 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include --- diff/arch/i386/pci/acpi.c 2004-05-19 22:11:02.000000000 +0100 +++ source/arch/i386/pci/acpi.c 2004-05-27 18:34:15.000000000 +0100 @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include "pci.h" struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) @@ -15,18 +17,31 @@ static int __init pci_acpi_init(void) { + struct pci_dev *dev = NULL; + if (pcibios_scanned) return 0; - if (!acpi_noirq) { - if (!acpi_pci_irq_init()) { - printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); - pcibios_scanned++; - pcibios_enable_irq = acpi_pci_irq_enable; - } else - printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n"); + if (acpi_noirq) + return 0; - } + printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); + acpi_irq_penalty_init(); + pcibios_scanned++; + pcibios_enable_irq = acpi_pci_irq_enable; + + /* + * PCI IRQ routing is set up by pci_enable_device(), but we + * also do it here in case there are still broken drivers that + * don't use pci_enable_device(). + */ + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) + acpi_pci_irq_enable(dev); + +#ifdef CONFIG_X86_IO_APIC + if (acpi_ioapic) + print_IO_APIC(); +#endif return 0; } --- diff/arch/i386/power/pmdisk.S 2004-05-19 22:11:02.000000000 +0100 +++ source/arch/i386/power/pmdisk.S 2004-05-27 18:34:15.000000000 +0100 @@ -21,7 +21,7 @@ jmp .L1449 .p2align 4,,7 .L1450: - movl $swapper_pg_dir-__PAGE_OFFSET,%ecx + movl $swsusp_pg_dir-__PAGE_OFFSET,%ecx movl %ecx,%cr3 movl pm_pagedir_nosave,%ebx --- diff/arch/i386/power/swsusp.S 2004-05-19 22:11:02.000000000 +0100 +++ source/arch/i386/power/swsusp.S 2004-05-27 18:34:15.000000000 +0100 @@ -36,7 +36,7 @@ jmp .L1449 .p2align 4,,7 .L1450: - movl $swapper_pg_dir-__PAGE_OFFSET,%ecx + movl $swsusp_pg_dir-__PAGE_OFFSET,%ecx movl %ecx,%cr3 call do_magic_resume_1 --- diff/arch/ia64/Kconfig 2004-05-27 13:41:12.000000000 +0100 +++ source/arch/ia64/Kconfig 2004-05-27 18:34:15.000000000 +0100 @@ -201,6 +201,184 @@ or have huge holes in the physical address space for other reasons. See for more. +config KGDB + bool "Include kgdb kernel debugger" + depends on DEBUG_KERNEL + help + If you say Y here, the system will be compiled with the debug + option (-g) and a debugging stub will be included in the + kernel. This stub communicates with gdb on another (host) + computer via a serial port. The host computer should have + access to the kernel binary file (vmlinux) and a serial port + that is connected to the target machine. Gdb can be made to + configure the serial port or you can use stty and setserial to + do this. See the 'target' command in gdb. This option also + configures in the ability to request a breakpoint early in the + boot process. To request the breakpoint just include 'kgdb' + as a boot option when booting the target machine. The system + will then break as soon as it looks at the boot options. This + option also installs a breakpoint in panic and sends any + kernel faults to the debugger. For more information see the + Documentation/i386/kgdb/kgdb.txt file. + +config KGDB_EARLY + bool + depends on KGDB + default n + prompt "KGDB Early" + help + Kgdb debugging in kernel can start shortly before/after setup_arch routine exits. + +choice + depends on KGDB + prompt "Debug serial port BAUD" + default KGDB_115200BAUD + help + Gdb and the kernel stub need to agree on the baud rate to be + used. Some systems (x86 family at this writing) allow this to + be configured. + +config KGDB_9600BAUD + bool "9600" + +config KGDB_19200BAUD + bool "19200" + +config KGDB_38400BAUD + bool "38400" + +config KGDB_57600BAUD + bool "57600" + +config KGDB_115200BAUD + bool "115200" +endchoice + +config KGDB_IOMEM + hex "hex I/O port IOMEM address" + depends on KGDB + default 0xc0000000ff5e0000 + help + Some systems use IOMEM address for the port. This value is from + the rx2600 chassis console port. + +config KGDB_IOMEM_REG_SHIFT + hex "hex I/O port IOMEM reg shift" + depends on KGDB + default 0x0 + help + This is the memory shift for IOMEM. + +config KGDB_IRQ + int "IRQ of the debug serial port" + depends on KGDB + default 59 + help + This is the irq for the debug port. If everything is working + correctly and the kernel has interrupts on a control C to the + port should cause a break into the kernel debug stub. This value + is the rx2600 chassis's console port. + +config DEBUG_INFO + bool + depends on KGDB + default y + +config KGDB_MORE + bool "Add any additional compile options" + depends on KGDB + default n + help + Saying yes here turns on the ability to enter additional + compile options. + + +config KGDB_OPTIONS + depends on KGDB_MORE + string "Additional compile arguments" + default "-O1" + help + This option allows you enter additional compile options for + the whole kernel compile. Each platform will have a default + that seems right for it. For example on PPC "-ggdb -O1", and + for i386 "-O1". Note that by configuring KGDB "-g" is already + turned on. In addition, on i386 platforms + "-fomit-frame-pointer" is deleted from the standard compile + options. + +config NO_KGDB_CPUS + int "Number of CPUs" + depends on KGDB && SMP + default NR_CPUS + help + + This option sets the number of cpus for kgdb ONLY. It is used + to prune some internal structures so they look "nice" when + displayed with gdb. This is to overcome possibly larger + numbers that may have been entered above. Enter the real + number to get nice clean kgdb_info displays. + +config KGDB_TS + bool "Enable kgdb time stamp macros?" + depends on KGDB + default n + help + Kgdb event macros allow you to instrument your code with calls + to the kgdb event recording function. The event log may be + examined with gdb at a break point. Turning on this + capability also allows you to choose how many events to + keep. Kgdb always keeps the lastest events. + +choice + depends on KGDB_TS + prompt "Max number of time stamps to save?" + default KGDB_TS_128 + +config KGDB_TS_64 + bool "64" + +config KGDB_TS_128 + bool "128" + +config KGDB_TS_256 + bool "256" + +config KGDB_TS_512 + bool "512" + +config KGDB_TS_1024 + bool "1024" + +endchoice + +config KGDB_CONSOLE + bool "Enable serial console thru kgdb port" + depends on KGDB + default n + help + This option enables the command line "console=kgdb" option. + When the system is booted with this option in the command line + all kernel printk output is sent to gdb (as well as to other + consoles). For this to work gdb must be connected. For this + reason, this command line option will generate a breakpoint if + gdb has not yet connected. After the gdb continue command is + given all pent up console output will be printed by gdb on the + host machine. Neither this option, nor KGDB require the + serial driver to be configured. + +config KGDB_SYSRQ + bool "Turn on SysRq 'G' command to do a break?" + depends on KGDB + default y + help + This option includes an option in the SysRq code that allows + you to enter SysRq G which generates a breakpoint to the KGDB + stub. This will work if the keyboard is alive and can + interrupt the system. Because of constraints on when the + serial port interrupt can be enabled, this code may allow you + to interrupt the system before the serial port control C is + available. Just say yes here. + config IA64_CYCLONE bool "Support Cyclone(EXA) Time Source" help @@ -445,6 +623,19 @@ keys are documented in . Don't say Y unless you really know what this hack does. +config SCHEDSTATS + bool "Collect scheduler statistics" + depends on PROC_FS + default n + help + If you say Y here, additional code will be inserted into the + scheduler and related routines to collect statistics about + scheduler behavior and provide them in /proc/schedstat. These + stats may be useful for both tuning and debugging the scheduler + If you aren't debugging the scheduler or trying to tune a specific + application, you can say N to avoid the very slight overhead + this adds. + config DEBUG_SLAB bool "Debug memory allocations" depends on DEBUG_KERNEL @@ -494,6 +685,13 @@ Say Y here only if you plan to use gdb to debug the kernel. If you don't debug the kernel, you can say N. +config LOCKMETER + bool "Kernel lock metering" + depends on SMP + help + Say Y to enable kernel lock metering, which adds overhead to SMP locks, + but allows you to see various statistics using the lockstat command. + config SYSVIPC_COMPAT bool depends on COMPAT && SYSVIPC --- diff/arch/ia64/kernel/Makefile 2004-05-27 13:41:12.000000000 +0100 +++ source/arch/ia64/kernel/Makefile 2004-05-27 18:34:15.000000000 +0100 @@ -17,6 +17,7 @@ obj-$(CONFIG_SMP) += smp.o smpboot.o obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o obj-$(CONFIG_IA64_CYCLONE) += cyclone.o +obj-$(CONFIG_KGDB) += kgdb_stub.o # The gate DSO image is built using a special linker script. targets += gate.so gate-syms.o --- diff/arch/ia64/kernel/acpi.c 2004-05-27 13:41:12.000000000 +0100 +++ source/arch/ia64/kernel/acpi.c 2004-05-27 18:34:15.000000000 +0100 @@ -521,9 +521,14 @@ #endif /* CONFIG_ACPI_NUMA */ unsigned int -acpi_register_gsi (u32 gsi, int polarity, int trigger) +acpi_register_gsi (u32 gsi, int edge_level, int active_high_low) { - return acpi_register_irq(gsi, polarity, trigger); + if (has_8259 && gsi < 16) + return isa_irq_to_vector(gsi); + + return iosapic_register_intr(gsi, + (active_high_low == ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, + (edge_level == ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); } EXPORT_SYMBOL(acpi_register_gsi); @@ -548,7 +553,7 @@ if (fadt->iapc_boot_arch & BAF_LEGACY_DEVICES) acpi_legacy_devices = 1; - acpi_register_gsi(fadt->sci_int, ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE); + acpi_register_gsi(fadt->sci_int, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW); return 0; } @@ -662,16 +667,4 @@ return 0; } -int -acpi_register_irq (u32 gsi, u32 polarity, u32 trigger) -{ - if (has_8259 && gsi < 16) - return isa_irq_to_vector(gsi); - - return iosapic_register_intr(gsi, - (polarity == ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, - (trigger == ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); -} -EXPORT_SYMBOL(acpi_register_irq); - #endif /* CONFIG_ACPI_BOOT */ --- diff/arch/ia64/kernel/init_task.c 2004-05-19 22:11:03.000000000 +0100 +++ source/arch/ia64/kernel/init_task.c 2004-05-27 18:34:15.000000000 +0100 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include --- diff/arch/ia64/kernel/iosapic.c 2004-05-27 13:41:12.000000000 +0100 +++ source/arch/ia64/kernel/iosapic.c 2004-05-27 18:34:15.000000000 +0100 @@ -483,7 +483,7 @@ index = find_iosapic(gsi); if (index < 0) { - printk(KERN_WARNING "%s: No IOSAPIC for GSI 0x%x\n", __FUNCTION__, gsi); + printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n", __FUNCTION__, gsi); return; } @@ -512,6 +512,42 @@ } } +static unsigned int +get_target_cpu (void) +{ +#ifdef CONFIG_SMP + static int cpu = -1; + + /* + * If the platform supports redirection via XTP, let it + * distribute interrupts. + */ + if (smp_int_redirect & SMP_IRQ_REDIRECTION) + return hard_smp_processor_id(); + + /* + * Some interrupts (ACPI SCI, for instance) are registered + * before the BSP is marked as online. + */ + if (!cpu_online(smp_processor_id())) + return hard_smp_processor_id(); + + /* + * Otherwise, round-robin interrupt vectors across all the + * processors. (It'd be nice if we could be smarter in the + * case of NUMA.) + */ + do { + if (++cpu >= NR_CPUS) + cpu = 0; + } while (!cpu_online(cpu)); + + return cpu_physical_id(cpu); +#else + return hard_smp_processor_id(); +#endif +} + /* * ACPI can describe IOSAPIC interrupts via static tables and namespace * methods. This provides an interface to register those interrupts and @@ -522,21 +558,35 @@ unsigned long polarity, unsigned long trigger) { int vector; - unsigned int dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff; - - vector = gsi_to_vector(gsi); - if (vector < 0) - vector = assign_irq_vector(AUTO_ASSIGN); + unsigned int dest; + unsigned long flags; - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, - polarity, trigger); + /* + * If this GSI has already been registered (i.e., it's a + * shared interrupt, or we lost a race to register it), + * don't touch the RTE. + */ + spin_lock_irqsave(&iosapic_lock, flags); + { + vector = gsi_to_vector(gsi); + if (vector > 0) { + spin_unlock_irqrestore(&iosapic_lock, flags); + return vector; + } - printk(KERN_INFO "GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n", - gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), - (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector); + vector = assign_irq_vector(AUTO_ASSIGN); + dest = get_target_cpu(); + register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, + polarity, trigger); + } + spin_unlock_irqrestore(&iosapic_lock, flags); + + printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n", + gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), + (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), + cpu_logical_id(dest), dest, vector); - /* program the IOSAPIC routing table */ - set_rte(vector, dest, 0); + set_rte(vector, dest, 1); return vector; } @@ -549,8 +599,9 @@ int iosapic_vector, u16 eid, u16 id, unsigned long polarity, unsigned long trigger) { + static const char * const name[] = {"unknown", "PMI", "INIT", "CPEI"}; unsigned char delivery; - int vector; + int vector, mask = 0; unsigned int dest = ((id << 8) | eid) & 0xffff; switch (int_type) { @@ -570,21 +621,22 @@ case ACPI_INTERRUPT_CPEI: vector = IA64_CPE_VECTOR; delivery = IOSAPIC_LOWEST_PRIORITY; + mask = 1; break; default: - printk(KERN_ERR "iosapic_register_platform_irq(): invalid int type\n"); + printk(KERN_ERR "iosapic_register_platform_irq(): invalid int type 0x%x\n", int_type); return -1; } - register_intr(gsi, vector, delivery, polarity, - trigger); + register_intr(gsi, vector, delivery, polarity, trigger); - printk(KERN_INFO "PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n", - int_type, gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), - (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector); + printk(KERN_INFO "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n", + int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown", + int_type, gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"), + (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), + cpu_logical_id(dest), dest, vector); - /* program the IOSAPIC routing table */ - set_rte(vector, dest, 0); + set_rte(vector, dest, mask); return vector; } @@ -599,18 +651,18 @@ unsigned long trigger) { int vector; - unsigned int dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff; + unsigned int dest = hard_smp_processor_id(); vector = isa_irq_to_vector(isa_irq); register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); - DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n", - isa_irq, gsi, polarity == IOSAPIC_POL_HIGH ? "high" : "low", - trigger == IOSAPIC_EDGE ? "edge" : "level", dest, vector); + DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n", + isa_irq, gsi, trigger == IOSAPIC_EDGE ? "edge" : "level", + polarity == IOSAPIC_POL_HIGH ? "high" : "low", + cpu_logical_id(dest), dest, vector); - /* program the IOSAPIC routing table */ - set_rte(vector, dest, 0); + set_rte(vector, dest, 1); } void __init @@ -665,104 +717,3 @@ iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE); } } - -void -iosapic_enable_intr (unsigned int vector) -{ - unsigned int dest; - irq_desc_t *desc; - - /* - * In the case of a shared interrupt, do not re-route the vector, and - * especially do not mask a running interrupt (startup will not get - * called for a shared interrupt). - */ - desc = irq_descp(vector); - if (desc->action) - return; - -#ifdef CONFIG_SMP - /* - * For platforms that do not support interrupt redirect via the XTP interface, we - * can round-robin the PCI device interrupts to the processors - */ - if (!(smp_int_redirect & SMP_IRQ_REDIRECTION)) { - static int cpu_index = -1; - - do - if (++cpu_index >= NR_CPUS) - cpu_index = 0; - while (!cpu_online(cpu_index)); - - dest = cpu_physical_id(cpu_index) & 0xffff; - } else { - /* - * Direct the interrupt vector to the current cpu, platform redirection - * will distribute them. - */ - dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff; - } -#else - /* direct the interrupt vector to the running cpu id */ - dest = (ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff; -#endif - set_rte(vector, dest, 1); - - printk(KERN_INFO "IOSAPIC: vector %d -> CPU 0x%04x, enabled\n", - vector, dest); -} - -#ifdef CONFIG_ACPI_PCI - -void __init -iosapic_parse_prt (void) -{ - struct acpi_prt_entry *entry; - struct list_head *node; - unsigned int gsi; - int vector; - char pci_id[16]; - struct hw_interrupt_type *irq_type = &irq_type_iosapic_level; - irq_desc_t *idesc; - - list_for_each(node, &acpi_prt.entries) { - entry = list_entry(node, struct acpi_prt_entry, node); - - /* We're only interested in static (non-link) entries. */ - if (entry->link.handle) - continue; - - gsi = entry->link.index; - - vector = gsi_to_vector(gsi); - if (vector < 0) { - if (find_iosapic(gsi) < 0) - continue; - - /* allocate a vector for this interrupt line */ - if (pcat_compat && (gsi < 16)) - vector = isa_irq_to_vector(gsi); - else - /* new GSI; allocate a vector for it */ - vector = assign_irq_vector(AUTO_ASSIGN); - - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, - IOSAPIC_LEVEL); - } - entry->irq = vector; - snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]", - entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin); - - /* - * If vector was previously initialized to a different - * handler, re-initialize. - */ - idesc = irq_descp(vector); - if (idesc->handler != irq_type) - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, - IOSAPIC_LEVEL); - - } -} - -#endif /* CONFIG_ACPI */ --- diff/arch/ia64/kernel/irq.c 2004-05-27 13:41:12.000000000 +0100 +++ source/arch/ia64/kernel/irq.c 2004-05-27 18:34:15.000000000 +0100 @@ -534,6 +534,11 @@ desc->handler->end(irq); spin_unlock(&desc->lock); } + +#ifdef CONFIG_KGDB + kgdb_process_breakpoint(); +#endif + return 1; } --- diff/arch/ia64/kernel/ivt.S 2004-05-27 13:41:12.000000000 +0100 +++ source/arch/ia64/kernel/ivt.S 2004-05-27 18:34:15.000000000 +0100 @@ -68,6 +68,13 @@ # define DBG_FAULT(i) #endif +#ifdef CONFIG_KGDB +#define KGDB_ENABLE_PSR_DB mov r31=psr;; movl r30=IA64_PSR_DB;; or r31=r31,r30;; \ + mov psr.l=r31;; srlz.i;; +#else +#define KGDB_ENABLE_PSR_DB +#endif + #define MINSTATE_VIRT /* needed by minstate.h */ #include "minstate.h" @@ -473,6 +480,7 @@ movl r14=ia64_leave_kernel ;; SAVE_REST + KGDB_ENABLE_PSR_DB mov rp=r14 ;; adds out2=16,r12 // out2 = pointer to pt_regs @@ -733,6 +741,8 @@ ;; srlz.i // guarantee that interruption collection is on ;; + KGDB_ENABLE_PSR_DB + ;; (p15) ssm psr.i // restore psr.i ;; mov r3=NR_syscalls - 1 @@ -774,6 +784,7 @@ srlz.i // ensure everybody knows psr.ic is back on ;; SAVE_REST + KGDB_ENABLE_PSR_DB ;; alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group mov out0=cr.ivr // pass cr.ivr as first arg @@ -1001,6 +1012,7 @@ movl r15=ia64_leave_kernel ;; SAVE_REST + KGDB_ENABLE_PSR_DB mov rp=r15 ;; br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr @@ -1034,6 +1046,7 @@ adds r3=8,r2 // set up second base pointer ;; SAVE_REST + KGDB_ENABLE_PSR_DB movl r14=ia64_leave_kernel ;; mov rp=r14 @@ -1076,6 +1089,7 @@ adds r3=8,r2 // set up second base pointer for SAVE_REST ;; SAVE_REST + KGDB_ENABLE_PSR_DB movl r14=ia64_leave_kernel ;; mov rp=r14 --- diff/arch/ia64/kernel/machvec.c 2004-05-27 13:41:12.000000000 +0100 +++ source/arch/ia64/kernel/machvec.c 2004-05-27 18:34:15.000000000 +0100 @@ -62,6 +62,12 @@ EXPORT_SYMBOL(machvec_timer_interrupt); void +machvec_tlb_migrate_finish (struct mm_struct *mm) +{ +} +EXPORT_SYMBOL(machvec_tlb_migrate_finish); + +void machvec_dma_sync_single (struct device *hwdev, dma_addr_t dma_handle, size_t size, int dir) { mb(); --- diff/arch/ia64/kernel/process.c 2004-05-27 13:41:13.000000000 +0100 +++ source/arch/ia64/kernel/process.c 2004-05-27 18:34:15.000000000 +0100 @@ -407,6 +407,9 @@ */ child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); +#ifdef CONFIG_KGDB + child_ptregs->cr_ipsr |= IA64_PSR_DB; +#endif /* * NOTE: The calling convention considers all floating point @@ -639,6 +642,9 @@ 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; +#ifdef CONFIG_KGDB + regs.pt.cr_ipsr |= IA64_PSR_DB; +#endif 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; --- diff/arch/ia64/kernel/setup.c 2004-05-27 13:41:13.000000000 +0100 +++ source/arch/ia64/kernel/setup.c 2004-05-27 18:34:15.000000000 +0100 @@ -50,6 +50,7 @@ #include #include #include +#include #if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE) # error "struct cpuinfo_ia64 too big!" @@ -88,10 +89,6 @@ unsigned long ia64_max_iommu_merge_mask = ~0UL; EXPORT_SYMBOL(ia64_max_iommu_merge_mask); -#define COMMAND_LINE_SIZE 512 - -char saved_command_line[COMMAND_LINE_SIZE]; /* used in proc filesystem */ - /* * We use a special marker for the end of memory and it uses the extra (+1) slot */ @@ -359,11 +356,36 @@ conswitchp = &vga_con; # endif #endif +#ifndef CONFIG_IA64_HP_SIM +#ifdef CONFIG_KGDB + { + unsigned long total_ibr, total_dbr; + long status; + int dbr; + + status = ia64_pal_debug_info(&total_ibr, &total_dbr); + + if (!status) { + printk(KERN_INFO "kgdb has DBR = %d IBR = %d\n", + (int) total_dbr, (int) total_ibr); + + for (dbr = 0; dbr < total_dbr; dbr++) + ia64_set_dbr((dbr << 1) + 1, 0); + for (dbr = 0; dbr < total_ibr; dbr++) + ia64_set_ibr((dbr << 1) + 1, 0); + } + } +#endif +#endif + /* enable IA-64 Machine Check Abort Handling */ ia64_mca_init(); platform_setup(cmdline_p); +#ifdef CONFIG_KGDB_EARLY + kgdb_serial_init(); +#endif paging_init(); } --- diff/arch/ia64/kernel/smp.c 2004-05-27 13:41:13.000000000 +0100 +++ source/arch/ia64/kernel/smp.c 2004-05-27 18:34:15.000000000 +0100 @@ -47,6 +47,7 @@ #include #include #include +#include /* * Structure and data for smp_call_function(). This is designed to minimise static memory @@ -66,6 +67,9 @@ #define IPI_CALL_FUNC 0 #define IPI_CPU_STOP 1 +#ifdef CONFIG_KGDB +#define IPI_KGDB_INTERRUPT 2 +#endif /* This needs to be cacheline aligned because it is written to by *other* CPUs. */ static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned; @@ -156,6 +160,12 @@ stop_this_cpu(); break; +#ifdef CONFIG_KGDB + case IPI_KGDB_INTERRUPT: + (void) in_kgdb(regs, NULL); + break; +#endif + default: printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which); break; @@ -361,6 +371,14 @@ } EXPORT_SYMBOL(smp_call_function); +#ifdef CONFIG_KGDB +void +smp_send_nmi_allbutself(void) +{ + send_IPI_allbutself(IPI_KGDB_INTERRUPT); +} +#endif + /* * this function calls the 'stop' function on all other CPUs in the system. */ --- diff/arch/ia64/kernel/traps.c 2004-05-27 13:41:13.000000000 +0100 +++ source/arch/ia64/kernel/traps.c 2004-05-27 18:34:15.000000000 +0100 @@ -35,6 +35,19 @@ fpswa_interface = __va(ia64_boot_param->fpswa); } +#ifdef CONFIG_KGDB +extern int kgdb_handle_exception(int, int, int, struct pt_regs *); +#define CHK_REMOTE_DEBUG(trapnr, signr, error_code, regs, after) \ + { \ + if (!user_mode(regs)) { \ + kgdb_handle_exception(trapnr, signr, error_code, regs); \ + after; \ + } \ + } +#else +#define CHK_REMOTE_DEBUG(trapnr, signr, error_code, regs, after) +#endif + /* * Unlock any spinlocks which will prevent us from getting the message out (timerlist_lock * is acquired through the console unblank code) @@ -85,6 +98,8 @@ bust_spinlocks(1); } + CHK_REMOTE_DEBUG(-1, SIGTRAP, err, regs,) + if (++die.lock_owner_depth < 3) { printk("%s[%d]: %s %ld [%d]\n", current->comm, current->pid, str, err, ++die_counter); @@ -117,9 +132,13 @@ siginfo.si_flags = 0; /* clear __ISR_VALID */ siginfo.si_isr = 0; + + switch (break_num) { case 0: /* unknown error (used by GCC for __builtin_abort()) */ +#ifndef CONFIG_KGDB die_if_kernel("bugcheck!", regs, break_num); +#endif sig = SIGILL; code = ILL_ILLOPC; break; @@ -172,8 +191,10 @@ break; default: +#ifndef CONFIG_KGDB if (break_num < 0x40000 || break_num > 0x100000) die_if_kernel("Bad break", regs, break_num); +#endif if (break_num < 0x80000) { sig = SIGILL; code = __ILL_BREAK; @@ -181,6 +202,13 @@ sig = SIGTRAP; code = TRAP_BRKPT; } } +#ifdef CONFIG_KGDB + /* + * We don't want to trap simulator system calls. + */ + if (break_num != 0x80001) + CHK_REMOTE_DEBUG(11, sig, break_num, regs, return) +#endif siginfo.si_signo = sig; siginfo.si_errno = 0; siginfo.si_code = code; @@ -488,8 +516,9 @@ break; case 29: /* Debug */ - case 35: /* Taken Branch Trap */ case 36: /* Single Step Trap */ + CHK_REMOTE_DEBUG(vector, SIGTRAP, isr, regs, return) + case 35: /* Taken Branch Trap */ if (fsys_mode(current, regs)) { extern char __kernel_syscall_via_break[]; /* @@ -603,6 +632,7 @@ sprintf(buf, "Fault %lu", vector); break; } + CHK_REMOTE_DEBUG(vector, SIGTRAP, isr, regs,) die_if_kernel(buf, regs, error); force_sig(SIGILL, current); } --- diff/arch/ia64/kernel/unwind.c 2004-05-27 13:41:13.000000000 +0100 +++ source/arch/ia64/kernel/unwind.c 2004-05-27 18:34:15.000000000 +0100 @@ -75,10 +75,69 @@ # define STAT(x...) #endif + +#ifdef CONFIG_KGDB_EARLY +#define KGDB_EARLY_SIZE 100 +static struct unw_reg_state __initdata kgdb_reg_state[KGDB_EARLY_SIZE]; +static struct unw_labeled_state __initdata kgdb_labeled_state[KGDB_EARLY_SIZE]; +void __initdata *kgdb_reg_state_free, __initdata *kgdb_labeled_state_free; + +static void __init +kgdb_malloc_init(void) +{ + int i; + + kgdb_reg_state_free = kgdb_reg_state; + for (i = 1; i < KGDB_EARLY_SIZE; i++) { + *((unsigned long *) &kgdb_reg_state[i]) = (unsigned long) kgdb_reg_state_free; + kgdb_reg_state_free = &kgdb_reg_state[i]; + } + + kgdb_labeled_state_free = kgdb_labeled_state; + for (i = 1; i < KGDB_EARLY_SIZE; i++) { + *((unsigned long *) &kgdb_labeled_state[i]) = + (unsigned long) kgdb_labeled_state_free; + kgdb_labeled_state_free = &kgdb_labeled_state[i]; + } + +} + +static void * __init +kgdb_malloc(void **mem) +{ + void *p; + + p = *mem; + *mem = *((void **) p); + return p; +} + +static void __init +kgdb_free(void **mem, void *p) +{ + *((void **)p) = *mem; + *mem = p; +} + +#define alloc_reg_state() (!malloc_sizes[0].cs_cachep ? \ + kgdb_malloc(&kgdb_reg_state_free) : \ + kmalloc(sizeof(struct unw_reg_state), GFP_ATOMIC)) +#define free_reg_state(usr) (!malloc_sizes[0].cs_cachep ? \ + kgdb_free(&kgdb_reg_state_free, usr) : \ + kfree(usr)) +#define alloc_labeled_state() (!malloc_sizes[0].cs_cachep ? \ + kgdb_malloc(&kgdb_labeled_state_free) : \ + kmalloc(sizeof(struct unw_labeled_state), GFP_ATOMIC)) +#define free_labeled_state(usr) (!malloc_sizes[0].cs_cachep ? \ + kgdb_free(&kgdb_labeled_state_free, usr) : \ + kfree(usr)) + +#else #define alloc_reg_state() kmalloc(sizeof(struct unw_reg_state), GFP_ATOMIC) #define free_reg_state(usr) kfree(usr) #define alloc_labeled_state() kmalloc(sizeof(struct unw_labeled_state), GFP_ATOMIC) #define free_labeled_state(usr) kfree(usr) +#endif typedef unsigned long unw_word; typedef unsigned char unw_hash_index_t; @@ -2262,6 +2321,10 @@ init_unwind_table(&unw.kernel_table, "kernel", KERNEL_START, (unsigned long) __gp, __start_unwind, __end_unwind); + +#ifdef CONFIG_KGDB_EARLY + kgdb_malloc_init(); +#endif } /* --- diff/arch/ia64/lib/Makefile 2004-05-19 22:11:04.000000000 +0100 +++ source/arch/ia64/lib/Makefile 2004-05-27 18:34:15.000000000 +0100 @@ -16,6 +16,7 @@ lib-$(CONFIG_PERFMON) += carta_random.o lib-$(CONFIG_MD_RAID5) += xor.o lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o +lib-$(CONFIG_KGDB) += kgdb_serial.o AFLAGS___divdi3.o = AFLAGS___udivdi3.o = -DUNSIGNED --- diff/arch/ia64/lib/dec_and_lock.c 2004-05-19 22:11:04.000000000 +0100 +++ source/arch/ia64/lib/dec_and_lock.c 2004-05-27 18:34:15.000000000 +0100 @@ -13,6 +13,7 @@ #include #include +#ifndef CONFIG_LOCKMETER /* * Decrement REFCOUNT and if the count reaches zero, acquire the spinlock. Both of these * operations have to be done atomically, so that the count doesn't drop to zero without @@ -40,3 +41,4 @@ } EXPORT_SYMBOL(atomic_dec_and_lock); +#endif --- diff/arch/ia64/mm/fault.c 2004-05-19 22:11:04.000000000 +0100 +++ source/arch/ia64/mm/fault.c 2004-05-27 18:34:15.000000000 +0100 @@ -15,6 +15,7 @@ #include #include #include +#include extern void die (char *, struct pt_regs *, long); @@ -232,6 +233,11 @@ */ bust_spinlocks(1); +#ifdef CONFIG_KGDB + kgdb_handle_exception(5, SIGBUS, isr, regs); + return; +#endif + if (address < PAGE_SIZE) printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference (address %016lx)\n", address); else --- diff/arch/ia64/pci/pci.c 2004-05-19 22:11:04.000000000 +0100 +++ source/arch/ia64/pci/pci.c 2004-05-27 18:34:15.000000000 +0100 @@ -134,10 +134,18 @@ static int __init pci_acpi_init (void) { - if (!acpi_pci_irq_init()) - printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); - else - printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n"); + struct pci_dev *dev = NULL; + + printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); + + /* + * PCI IRQ routing is set up by pci_enable_device(), but we + * also do it here in case there are still broken drivers that + * don't use pci_enable_device(). + */ + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) + acpi_pci_irq_enable(dev); + return 0; } --- diff/arch/ia64/sn/kernel/sn2/sn2_smp.c 2004-05-19 22:11:05.000000000 +0100 +++ source/arch/ia64/sn/kernel/sn2/sn2_smp.c 2004-05-27 18:34:15.000000000 +0100 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,13 @@ } +void +sn_tlb_migrate_finish(struct mm_struct *mm) +{ + if (mm == current->mm) + flush_tlb_mm(mm); +} + /** * sn2_global_tlb_purge - globally purge translation cache of virtual address range @@ -114,6 +122,13 @@ return; } + if (atomic_read(&mm->mm_users) == 1) { + flush_tlb_mm(mm); + preempt_enable(); + return; + } + + nix = 0; for (cnode=find_first_bit(&nodes_flushed, NR_NODES); cnode < NR_NODES; cnode=find_next_bit(&nodes_flushed, NR_NODES, ++cnode)) --- diff/arch/m68k/kernel/process.c 2004-05-27 13:41:14.000000000 +0100 +++ source/arch/m68k/kernel/process.c 2004-05-27 18:34:15.000000000 +0100 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include --- diff/arch/m68k/kernel/setup.c 2004-05-27 13:41:14.000000000 +0100 +++ source/arch/m68k/kernel/setup.c 2004-05-27 18:34:15.000000000 +0100 @@ -62,7 +62,6 @@ static struct mem_info m68k_ramdisk; static char m68k_command_line[CL_SIZE]; -char saved_command_line[CL_SIZE]; char m68k_debug_device[6] = ""; --- diff/arch/m68k/q40/config.c 2004-05-27 13:41:15.000000000 +0100 +++ source/arch/m68k/q40/config.c 2004-05-27 18:34:15.000000000 +0100 @@ -64,7 +64,6 @@ extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/ ); -extern char *saved_command_line; extern char m68k_debug_device[]; static void q40_mem_console_write(struct console *co, const char *b, unsigned int count); --- diff/arch/m68knommu/kernel/init_task.c 2004-05-19 22:11:07.000000000 +0100 +++ source/arch/m68knommu/kernel/init_task.c 2004-05-27 18:34:15.000000000 +0100 @@ -7,6 +7,7 @@ #include #include #include +#include #include #include --- diff/arch/m68knommu/kernel/setup.c 2004-05-19 22:11:07.000000000 +0100 +++ source/arch/m68knommu/kernel/setup.c 2004-05-27 18:34:15.000000000 +0100 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -44,8 +45,7 @@ unsigned long memory_start; unsigned long memory_end; -char command_line[512]; -char saved_command_line[512]; +char command_line[COMMAND_LINE_SIZE]; /* setup some dummy routines */ static void dummy_waitbut(void) --- diff/arch/mips/kernel/init_task.c 2004-05-19 22:11:09.000000000 +0100 +++ source/arch/mips/kernel/init_task.c 2004-05-27 18:34:15.000000000 +0100 @@ -3,6 +3,7 @@ #include #include #include +#include #include #include --- diff/arch/mips/kernel/setup.c 2004-05-19 22:11:10.000000000 +0100 +++ source/arch/mips/kernel/setup.c 2004-05-27 18:34:15.000000000 +0100 @@ -71,7 +71,6 @@ struct boot_mem_map boot_mem_map; static char command_line[CL_SIZE]; - char saved_command_line[CL_SIZE]; char arcs_cmdline[CL_SIZE]=CONFIG_CMDLINE; /* --- diff/arch/parisc/kernel/init_task.c 2004-05-27 13:41:15.000000000 +0100 +++ source/arch/parisc/kernel/init_task.c 2004-05-27 18:34:15.000000000 +0100 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include --- diff/arch/parisc/kernel/setup.c 2004-05-27 13:41:15.000000000 +0100 +++ source/arch/parisc/kernel/setup.c 2004-05-27 18:34:15.000000000 +0100 @@ -45,8 +45,6 @@ #include #include -#define COMMAND_LINE_SIZE 1024 -char saved_command_line[COMMAND_LINE_SIZE]; char command_line[COMMAND_LINE_SIZE]; /* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */ --- diff/arch/ppc/Kconfig 2004-05-27 13:41:15.000000000 +0100 +++ source/arch/ppc/Kconfig 2004-05-27 18:34:15.000000000 +0100 @@ -1227,6 +1227,19 @@ debug the kernel. If you don't debug the kernel, you can say N. +config SCHEDSTATS + bool "Collect scheduler statistics" + depends on PROC_FS + default n + help + If you say Y here, additional code will be inserted into the + scheduler and related routines to collect statistics about + scheduler behavior and provide them in /proc/schedstat. These + stats may be useful for both tuning and debugging the scheduler + If you aren't debugging the scheduler or trying to tune a specific + application, you can say N to avoid the very slight overhead + this adds. + config BOOTX_TEXT bool "Support for early boot text console (BootX or OpenFirmware only)" depends PPC_OF --- diff/arch/ppc/boot/Makefile 2004-05-19 22:11:13.000000000 +0100 +++ source/arch/ppc/boot/Makefile 2004-05-27 18:34:15.000000000 +0100 @@ -17,11 +17,11 @@ bootdir-y := simple bootdir-$(CONFIG_PPC_OF) += openfirmware -subdir-y := lib/ common/ images/ -subdir-$(CONFIG_PPC_OF) += of1275/ +subdir-y := lib common images +subdir-$(CONFIG_PPC_OF) += of1275 # for cleaning -subdir- += simple/ openfirmware/ +subdir- += simple openfirmware host-progs := $(addprefix utils/, addnote mknote hack-coff mkprep mkbugboot mktree) --- diff/arch/ppc/boot/openfirmware/Makefile 2004-05-19 22:11:14.000000000 +0100 +++ source/arch/ppc/boot/openfirmware/Makefile 2004-05-27 18:34:15.000000000 +0100 @@ -22,9 +22,10 @@ images := $(boot)/images OBJCOPY_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment -COFF_LD_ARGS := -T $(boot)/ld.script -e _start -Ttext 0x00500000 -Bstatic -CHRP_LD_ARGS := -T $(boot)/ld.script -e _start -Ttext 0x00800000 -NEWWORLD_LD_ARGS:= -T $(boot)/ld.script -e _start -Ttext 0x01000000 +COFF_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00500000 \ + -Bstatic +CHRP_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00800000 +NEWWORLD_LD_ARGS:= -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x01000000 COMMONOBJS := start.o misc.o common.o COFFOBJS := coffcrt0.o $(COMMONOBJS) coffmain.o @@ -92,11 +93,11 @@ cmd_gencoffb = $(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) $< $(LIBS) && \ $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec) targets += coffboot -$(obj)/coffboot: $(obj)/image.o $(COFFOBJS) $(LIBS) $(boot)/ld.script FORCE +$(obj)/coffboot: $(obj)/image.o $(COFFOBJS) $(LIBS) $(srctree)/$(boot)/ld.script FORCE $(call if_changed,gencoffb) targets += coffboot.initrd $(obj)/coffboot.initrd: $(obj)/image.initrd.o $(COFFOBJS) $(LIBS) \ - $(boot)/ld.script FORCE + $(srctree)/$(boot)/ld.script FORCE $(call if_changed,gencoffb) @@ -118,20 +119,22 @@ -R .comment $(del-ramdisk-sec) $(images)/vmlinux.elf-pmac: $(obj)/image.o $(NEWWORLDOBJS) $(LIBS) \ - $(obj)/note $(boot)/ld.script + $(obj)/note $(srctree)/$(boot)/ld.script $(call cmd,gen-elf-pmac) $(images)/vmlinux.initrd.elf-pmac: $(obj)/image.initrd.o $(NEWWORLDOBJS) \ - $(LIBS) $(obj)/note $(boot)/ld.script + $(LIBS) $(obj)/note \ + $(srctree)/$(boot)/ld.script $(call cmd,gen-elf-pmac) quiet_cmd_gen-chrp = CHRP $@ cmd_gen-chrp = $(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) $< $(LIBS) && \ $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec) -$(images)/zImage.chrp: $(obj)/image.o $(CHRPOBJS) $(LIBS) $(boot)/ld.script +$(images)/zImage.chrp: $(obj)/image.o $(CHRPOBJS) $(LIBS) \ + $(srctree)/$(boot)/ld.script $(call cmd,gen-chrp) $(images)/zImage.initrd.chrp: $(obj)/image.initrd.o $(CHRPOBJS) $(LIBS) \ - $(boot)/ld.script + $(srctree)/$(boot)/ld.script $(call cmd,gen-chrp) quiet_cmd_addnote = ADDNOTE $@ --- diff/arch/ppc/boot/simple/Makefile 2004-05-27 13:41:15.000000000 +0100 +++ source/arch/ppc/boot/simple/Makefile 2004-05-27 18:34:15.000000000 +0100 @@ -41,7 +41,7 @@ # if present on 'classic' PPC. cacheflag-y := -DCLEAR_CACHES="" # This file will flush / disable the L2, and L3 if present. -clear_L2_L3 := $(srctree)/$(boot)/simple/clear.S +clear_L2_L3 := $(boot)/simple/clear.S # # See arch/ppc/kconfig and arch/ppc/platforms/Kconfig --- diff/arch/ppc/kernel/process.c 2004-05-27 13:41:15.000000000 +0100 +++ source/arch/ppc/kernel/process.c 2004-05-27 18:34:15.000000000 +0100 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include --- diff/arch/ppc/kernel/setup.c 2004-05-27 13:41:15.000000000 +0100 +++ source/arch/ppc/kernel/setup.c 2004-05-27 18:34:15.000000000 +0100 @@ -54,7 +54,6 @@ extern void power4_idle(void); extern boot_infos_t *boot_infos; -char saved_command_line[COMMAND_LINE_SIZE]; unsigned char aux_device_present; struct ide_machdep_calls ppc_ide_md; char *sysmap; --- diff/arch/ppc/platforms/lopec_setup.c 2004-05-19 22:11:16.000000000 +0100 +++ source/arch/ppc/platforms/lopec_setup.c 2004-05-27 18:34:15.000000000 +0100 @@ -33,7 +33,6 @@ #include #include -extern char saved_command_line[]; extern void lopec_find_bridges(void); /* --- diff/arch/ppc/platforms/pmac_setup.c 2004-05-27 13:41:16.000000000 +0100 +++ source/arch/ppc/platforms/pmac_setup.c 2004-05-27 18:34:15.000000000 +0100 @@ -103,8 +103,6 @@ static int current_root_goodness = -1; -extern char saved_command_line[]; - extern int pmac_newworld; #define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ --- diff/arch/ppc/platforms/pplus.c 2004-05-19 22:11:16.000000000 +0100 +++ source/arch/ppc/platforms/pplus.c 2004-05-27 18:34:15.000000000 +0100 @@ -48,8 +48,6 @@ TODC_ALLOC(); -extern char saved_command_line[]; - extern void pplus_setup_hose(void); extern void pplus_set_VIA_IDE_native(void); --- diff/arch/ppc/platforms/prep_setup.c 2004-05-19 22:11:16.000000000 +0100 +++ source/arch/ppc/platforms/prep_setup.c 2004-05-27 18:34:15.000000000 +0100 @@ -76,7 +76,6 @@ extern void ibm_prep_init(void); extern void prep_find_bridges(void); -extern char saved_command_line[]; int _prep_type; --- diff/arch/ppc64/Kconfig 2004-05-27 13:41:16.000000000 +0100 +++ source/arch/ppc64/Kconfig 2004-05-27 18:34:15.000000000 +0100 @@ -417,9 +417,29 @@ debugging info resulting in a larger kernel image. Say Y here only if you plan to use gdb to debug the kernel. If you don't debug the kernel, you can say N. + +config IRQSTACKS + bool "Use separate kernel stacks when processing interrupts" + help + If you say Y here the kernel will use separate kernel stacks + for handling hard and soft interrupts. This can help avoid + overflowing the process kernel stacks. endmenu +config SCHEDSTATS + bool "Collect scheduler statistics" + depends on PROC_FS + default n + help + If you say Y here, additional code will be inserted into the + scheduler and related routines to collect statistics about + scheduler behavior and provide them in /proc/schedstat. These + stats may be useful for both tuning and debugging the scheduler + If you aren't debugging the scheduler or trying to tune a specific + application, you can say N to avoid the very slight overhead + this adds. + config SPINLINE bool "Inline spinlock code at each call site" depends on SMP && !PPC_SPLPAR && !PPC_ISERIES --- diff/arch/ppc64/kernel/head.S 2004-05-27 13:41:16.000000000 +0100 +++ source/arch/ppc64/kernel/head.S 2004-05-27 18:34:15.000000000 +0100 @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef CONFIG_PPC_ISERIES #define DO_SOFT_DISABLE @@ -1281,6 +1282,10 @@ SAVE_4GPRS(16, r1) SAVE_8GPRS(24, r1) + /* Set the marker value "regshere" just before the reg values */ + SET_REG_TO_CONST(r22, 0x7265677368657265) + std r22,STACK_FRAME_OVERHEAD-16(r1) + /* * Clear the RESULT field */ @@ -2273,4 +2278,4 @@ */ .globl cmd_line cmd_line: - .space 512 /* COMMAND_LINE_SIZE */ + .space COMMAND_LINE_SIZE --- diff/arch/ppc64/kernel/init_task.c 2004-05-19 22:11:18.000000000 +0100 +++ source/arch/ppc64/kernel/init_task.c 2004-05-27 18:34:15.000000000 +0100 @@ -4,6 +4,7 @@ #include #include #include +#include #include static struct fs_struct init_fs = INIT_FS; --- diff/arch/ppc64/kernel/ioctl32.c 2004-05-19 22:11:18.000000000 +0100 +++ source/arch/ppc64/kernel/ioctl32.c 2004-05-27 18:34:15.000000000 +0100 @@ -29,307 +29,6 @@ #define CODE #include "compat_ioctl.c" -struct ncp_ioctl_request_32 { - unsigned int function; - unsigned int size; - compat_caddr_t data; -}; - -struct ncp_fs_info_v2_32 { - int version; - unsigned int mounted_uid; - unsigned int connection; - unsigned int buffer_size; - - unsigned int volume_number; - __u32 directory_id; - - __u32 dummy1; - __u32 dummy2; - __u32 dummy3; -}; - -struct ncp_objectname_ioctl_32 -{ - int auth_type; - unsigned int object_name_len; - compat_caddr_t object_name; /* an userspace data, in most cases user name */ -}; - -struct ncp_privatedata_ioctl_32 -{ - unsigned int len; - compat_caddr_t data; /* ~1000 for NDS */ -}; - -#define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct ncp_ioctl_request_32) - -#define NCP_IOC_GETMOUNTUID2_32 _IOW('n', 2, unsigned int) - -#define NCP_IOC_GET_FS_INFO_V2_32 _IOWR('n', 4, struct ncp_fs_info_v2_32) - -#define NCP_IOC_GETOBJECTNAME_32 _IOWR('n', 9, struct ncp_objectname_ioctl_32) -#define NCP_IOC_SETOBJECTNAME_32 _IOR('n', 9, struct ncp_objectname_ioctl_32) -#define NCP_IOC_GETPRIVATEDATA_32 _IOWR('n', 10, struct ncp_privatedata_ioctl_32) -#define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct ncp_privatedata_ioctl_32) - -static int do_ncp_ncprequest(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ncp_ioctl_request_32 n32; - struct ncp_ioctl_request n; - mm_segment_t old_fs; - int err; - - if (copy_from_user(&n32, (struct ncp_ioctl_request_32*)arg, - sizeof(n32))) - return -EFAULT; - - n.function = n32.function; - n.size = n32.size; - if (n.size > 65536) - return -EINVAL; - n.data = vmalloc(65536); /* 65536 must be same as NCP_PACKET_SIZE_INTERNAL in ncpfs */ - if (!n.data) - return -ENOMEM; - err = -EFAULT; - if (copy_from_user(n.data, (void *)A(n32.data), n.size)) - goto out; - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, NCP_IOC_NCPREQUEST, (unsigned long)&n); - set_fs (old_fs); - if(err <= 0) - goto out; - if (err > 65536) { - err = -EINVAL; - goto out; - } - if (copy_to_user((void *)A(n32.data), n.data, err)) { - err = -EFAULT; - goto out; - } - out: - vfree(n.data); - return err; -} - -static int do_ncp_getmountuid2(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - __kernel_uid_t kuid; - int err; - - cmd = NCP_IOC_GETMOUNTUID2; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&kuid); - set_fs(old_fs); - - if (!err) - err = put_user(kuid, (unsigned int*)arg); - - return err; -} - -static int do_ncp_getfsinfo2(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct ncp_fs_info_v2_32 n32; - struct ncp_fs_info_v2 n; - int err; - - if (copy_from_user(&n32, (struct ncp_fs_info_v2_32*)arg, sizeof(n32))) - return -EFAULT; - if (n32.version != NCP_GET_FS_INFO_VERSION_V2) - return -EINVAL; - n.version = NCP_GET_FS_INFO_VERSION_V2; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, NCP_IOC_GET_FS_INFO_V2, (unsigned long)&n); - set_fs(old_fs); - - if (!err) { - n32.version = n.version; - n32.mounted_uid = n.mounted_uid; - n32.connection = n.connection; - n32.buffer_size = n.buffer_size; - n32.volume_number = n.volume_number; - n32.directory_id = n.directory_id; - n32.dummy1 = n.dummy1; - n32.dummy2 = n.dummy2; - n32.dummy3 = n.dummy3; - err = copy_to_user((struct ncp_fs_info_v2_32*)arg, &n32, sizeof(n32)) ? -EFAULT : 0; - } - return err; -} - -static int do_ncp_getobjectname(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ncp_objectname_ioctl_32 n32; - struct ncp_objectname_ioctl n; - mm_segment_t old_fs; - int err; - size_t tl; - - if (copy_from_user(&n32, (struct ncp_objectname_ioctl_32*)arg, - sizeof(n32))) - return -EFAULT; - - n.object_name_len = tl = n32.object_name_len; - if (tl) { - n.object_name = kmalloc(tl, GFP_KERNEL); - if (!n.object_name) - return -ENOMEM; - } else { - n.object_name = NULL; - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, NCP_IOC_GETOBJECTNAME, (unsigned long)&n); - set_fs (old_fs); - if(err) - goto out; - - if (tl > n.object_name_len) - tl = n.object_name_len; - - err = -EFAULT; - if (tl && copy_to_user((void *)A(n32.object_name), n.object_name, tl)) - goto out; - - n32.auth_type = n.auth_type; - n32.object_name_len = n.object_name_len; - - if (copy_to_user((struct ncp_objectname_ioctl_32*)arg, &n32, sizeof(n32))) - goto out; - - err = 0; - out: - if (n.object_name) - kfree(n.object_name); - - return err; -} - -static int do_ncp_setobjectname(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ncp_objectname_ioctl_32 n32; - struct ncp_objectname_ioctl n; - mm_segment_t old_fs; - int err; - size_t tl; - - if (copy_from_user(&n32, (struct ncp_objectname_ioctl_32*)arg, - sizeof(n32))) - return -EFAULT; - - n.auth_type = n32.auth_type; - n.object_name_len = tl = n32.object_name_len; - if (tl) { - n.object_name = kmalloc(tl, GFP_KERNEL); - if (!n.object_name) - return -ENOMEM; - err = -EFAULT; - if (copy_from_user(n.object_name, (void *)A(n32.object_name), tl)) - goto out; - } else { - n.object_name = NULL; - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, NCP_IOC_SETOBJECTNAME, (unsigned long)&n); - set_fs (old_fs); - - out: - if (n.object_name) - kfree(n.object_name); - - return err; -} - -static int do_ncp_getprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ncp_privatedata_ioctl_32 n32; - struct ncp_privatedata_ioctl n; - mm_segment_t old_fs; - int err; - size_t tl; - - if (copy_from_user(&n32, (struct ncp_privatedata_ioctl_32*)arg, - sizeof(n32))) - return -EFAULT; - - n.len = tl = n32.len; - if (tl) { - n.data = kmalloc(tl, GFP_KERNEL); - if (!n.data) - return -ENOMEM; - } else { - n.data = NULL; - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, NCP_IOC_GETPRIVATEDATA, (unsigned long)&n); - set_fs (old_fs); - if(err) - goto out; - - if (tl > n.len) - tl = n.len; - - err = -EFAULT; - if (tl && copy_to_user((void *)A(n32.data), n.data, tl)) - goto out; - - n32.len = n.len; - - if (copy_to_user((struct ncp_privatedata_ioctl_32*)arg, &n32, sizeof(n32))) - goto out; - - err = 0; - out: - if (n.data) - kfree(n.data); - - return err; -} - -static int do_ncp_setprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ncp_privatedata_ioctl_32 n32; - struct ncp_privatedata_ioctl n; - mm_segment_t old_fs; - int err; - size_t tl; - - if (copy_from_user(&n32, (struct ncp_privatedata_ioctl_32*)arg, - sizeof(n32))) - return -EFAULT; - - n.len = tl = n32.len; - if (tl) { - n.data = kmalloc(tl, GFP_KERNEL); - if (!n.data) - return -ENOMEM; - err = -EFAULT; - if (copy_from_user(n.data, (void *)A(n32.data), tl)) - goto out; - } else { - n.data = NULL; - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, NCP_IOC_SETPRIVATEDATA, (unsigned long)&n); - set_fs (old_fs); - - out: - if (n.data) - kfree(n.data); - - return err; -} - - #define HANDLE_IOCTL(cmd,handler) { cmd, (ioctl_trans_handler_t)handler, 0 }, #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl) @@ -350,17 +49,6 @@ COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */ COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ -/* And these ioctls need translation */ - -/* NCPFS */ -HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest) -HANDLE_IOCTL(NCP_IOC_GETMOUNTUID2_32, do_ncp_getmountuid2) -HANDLE_IOCTL(NCP_IOC_GET_FS_INFO_V2_32, do_ncp_getfsinfo2) -HANDLE_IOCTL(NCP_IOC_GETOBJECTNAME_32, do_ncp_getobjectname) -HANDLE_IOCTL(NCP_IOC_SETOBJECTNAME_32, do_ncp_setobjectname) -HANDLE_IOCTL(NCP_IOC_GETPRIVATEDATA_32, do_ncp_getprivatedata) -HANDLE_IOCTL(NCP_IOC_SETPRIVATEDATA_32, do_ncp_setprivatedata) - IOCTL_TABLE_END int ioctl_table_size = ARRAY_SIZE(ioctl_start); --- diff/arch/ppc64/kernel/irq.c 2004-05-27 13:41:16.000000000 +0100 +++ source/arch/ppc64/kernel/irq.c 2004-05-27 18:34:15.000000000 +0100 @@ -370,8 +370,7 @@ return 0; } -static inline int handle_irq_event(int irq, struct pt_regs *regs, - struct irqaction *action) +int handle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action) { int status = 0; int retval = 0; @@ -482,6 +481,9 @@ int cpu = smp_processor_id(); irq_desc_t *desc = get_irq_desc(irq); irqreturn_t action_ret; +#ifdef CONFIG_IRQSTACKS + struct thread_info *curtp, *irqtp; +#endif kstat_cpu(cpu).irqs[irq]++; @@ -548,7 +550,22 @@ */ for (;;) { spin_unlock(&desc->lock); - action_ret = handle_irq_event(irq, regs, action); + +#ifdef CONFIG_IRQSTACKS + /* Switch to the irq stack to handle this */ + curtp = current_thread_info(); + irqtp = hardirq_ctx[smp_processor_id()]; + if (curtp != irqtp) { + irqtp->task = curtp->task; + irqtp->flags = 0; + action_ret = call_handle_irq_event(irq, regs, action, irqtp); + irqtp->task = NULL; + if (irqtp->flags) + set_bits(irqtp->flags, &curtp->flags); + } else +#endif + action_ret = handle_irq_event(irq, regs, action); + spin_lock(&desc->lock); if (!noirqdebug) note_interrupt(irq, desc, action_ret); @@ -690,6 +707,7 @@ once++; ppc_md.init_IRQ(); + irq_ctx_init(); } static struct proc_dir_entry * root_irq_dir; @@ -973,4 +991,51 @@ } -#endif +#endif /* CONFIG_PPC_ISERIES */ + +#ifdef CONFIG_IRQSTACKS +struct thread_info *softirq_ctx[NR_CPUS]; +struct thread_info *hardirq_ctx[NR_CPUS]; + +void irq_ctx_init(void) +{ + struct thread_info *tp; + int i; + + for (i = 0; i < NR_CPUS; i++) { + memset((void *)softirq_ctx[i], 0, THREAD_SIZE); + tp = softirq_ctx[i]; + tp->cpu = i; + tp->preempt_count = SOFTIRQ_OFFSET; + + memset((void *)hardirq_ctx[i], 0, THREAD_SIZE); + tp = hardirq_ctx[i]; + tp->cpu = i; + tp->preempt_count = HARDIRQ_OFFSET; + } +} + +void do_softirq(void) +{ + unsigned long flags; + struct thread_info *curtp, *irqtp; + + if (in_interrupt()) + return; + + local_irq_save(flags); + + if (local_softirq_pending()) { + curtp = current_thread_info(); + irqtp = softirq_ctx[smp_processor_id()]; + irqtp->task = curtp->task; + call_do_softirq(irqtp); + irqtp->task = NULL; + } + + local_irq_restore(flags); +} +EXPORT_SYMBOL(do_softirq); + +#endif /* CONFIG_IRQSTACKS */ + --- diff/arch/ppc64/kernel/misc.S 2004-05-27 13:41:16.000000000 +0100 +++ source/arch/ppc64/kernel/misc.S 2004-05-27 18:34:15.000000000 +0100 @@ -102,6 +102,30 @@ blr #endif /* CONFIG_PPC_ISERIES */ +#ifdef CONFIG_IRQSTACKS +_GLOBAL(call_do_softirq) + mflr r0 + std r0,16(r1) + stdu r1,THREAD_SIZE-112(r3) + mr r1,r3 + bl .__do_softirq + ld r1,0(r1) + ld r0,16(r1) + mtlr r0 + blr + +_GLOBAL(call_handle_irq_event) + mflr r0 + std r0,16(r1) + stdu r1,THREAD_SIZE-112(r6) + mr r1,r6 + bl .handle_irq_event + ld r1,0(r1) + ld r0,16(r1) + mtlr r0 + blr +#endif /* CONFIG_IRQSTACKS */ + /* * Flush instruction cache. */ --- diff/arch/ppc64/kernel/process.c 2004-05-27 13:41:16.000000000 +0100 +++ source/arch/ppc64/kernel/process.c 2004-05-27 18:34:15.000000000 +0100 @@ -457,16 +457,28 @@ static int kstack_depth_to_print = 64; -static inline int validate_sp(unsigned long sp, struct task_struct *p) +static int validate_sp(unsigned long sp, struct task_struct *p, + unsigned long nbytes) { unsigned long stack_page = (unsigned long)p->thread_info; - if (sp < stack_page + sizeof(struct thread_struct)) - return 0; - if (sp >= stack_page + THREAD_SIZE) - return 0; + if (sp >= stack_page + sizeof(struct thread_struct) + && sp <= stack_page + THREAD_SIZE - nbytes) + return 1; + +#ifdef CONFIG_IRQSTACKS + stack_page = (unsigned long) hardirq_ctx[task_cpu(p)]; + if (sp >= stack_page + sizeof(struct thread_struct) + && sp <= stack_page + THREAD_SIZE - nbytes) + return 1; + + stack_page = (unsigned long) softirq_ctx[task_cpu(p)]; + if (sp >= stack_page + sizeof(struct thread_struct) + && sp <= stack_page + THREAD_SIZE - nbytes) + return 1; +#endif - return 1; + return 0; } unsigned long get_wchan(struct task_struct *p) @@ -478,12 +490,12 @@ return 0; sp = p->thread.ksp; - if (!validate_sp(sp, p)) + if (!validate_sp(sp, p, 112)) return 0; do { sp = *(unsigned long *)sp; - if (!validate_sp(sp, p)) + if (!validate_sp(sp, p, 112)) return 0; if (count > 0) { ip = *(unsigned long *)(sp + 16); @@ -496,9 +508,10 @@ void show_stack(struct task_struct *p, unsigned long *_sp) { - unsigned long ip; + unsigned long ip, newsp, lr; int count = 0; unsigned long sp = (unsigned long)_sp; + int firstframe = 1; if (sp == 0) { if (p) { @@ -509,17 +522,40 @@ } } - if (!validate_sp(sp, p)) - return; - + lr = 0; printk("Call Trace:\n"); do { - sp = *(unsigned long *)sp; - if (!validate_sp(sp, p)) + if (!validate_sp(sp, p, 112)) return; - ip = *(unsigned long *)(sp + 16); - printk("[%016lx] ", ip); - print_symbol("%s\n", ip); + + _sp = (unsigned long *) sp; + newsp = _sp[0]; + ip = _sp[2]; + if (!firstframe || ip != lr) { + printk("[%016lx] [%016lx] ", sp, ip); + print_symbol("%s", ip); + if (firstframe) + printk(" (unreliable)"); + printk("\n"); + } + firstframe = 0; + + /* + * See if this is an exception frame. + * We look for the "regshere" marker in the current frame. + */ + if (validate_sp(sp, p, sizeof(struct pt_regs) + 400) + && _sp[12] == 0x7265677368657265) { + struct pt_regs *regs = (struct pt_regs *) + (sp + STACK_FRAME_OVERHEAD); + printk("--- Exception: %lx", regs->trap); + print_symbol(" at %s\n", regs->nip); + lr = regs->link; + print_symbol(" LR = %s\n", lr); + firstframe = 1; + } + + sp = newsp; } while (count++ < kstack_depth_to_print); } --- diff/arch/ppc64/kernel/prom.c 2004-05-19 22:11:18.000000000 +0100 +++ source/arch/ppc64/kernel/prom.c 2004-05-27 18:34:15.000000000 +0100 @@ -2189,11 +2189,13 @@ ints = imap - nintrc; reg = ints - naddrc; } + if (p == NULL) { #ifdef DEBUG_IRQ - if (p == NULL) printk("hmmm, int tree for %s doesn't have ctrler\n", np->full_name); #endif + return 0; + } *irq = ints; *ictrler = p; return nintrc; @@ -2204,7 +2206,7 @@ int measure_only) { unsigned int *ints; - int intlen, intrcells; + int intlen, intrcells, intrcount; int i, j, n; unsigned int *irq, virq; struct device_node *ic; @@ -2214,34 +2216,40 @@ return mem_start; intrcells = prom_n_intr_cells(np); intlen /= intrcells * sizeof(unsigned int); - np->n_intrs = intlen; np->intrs = (struct interrupt_info *) mem_start; mem_start += intlen * sizeof(struct interrupt_info); if (measure_only) return mem_start; - for (i = 0; i < intlen; ++i) { - np->intrs[i].line = 0; - np->intrs[i].sense = 1; + intrcount = 0; + for (i = 0; i < intlen; ++i, ints += intrcells) { n = map_interrupt(&irq, &ic, np, ints, intrcells); if (n <= 0) continue; - virq = virt_irq_create_mapping(irq[0]); - if (virq == NO_IRQ) { - printk(KERN_CRIT "Could not allocate interrupt " - "number for %s\n", np->full_name); - } else - np->intrs[i].line = irq_offset_up(virq); + + /* don't map IRQ numbers under a cascaded 8259 controller */ + if (ic && device_is_compatible(ic, "chrp,iic")) { + np->intrs[intrcount].line = irq[0]; + } else { + virq = virt_irq_create_mapping(irq[0]); + if (virq == NO_IRQ) { + printk(KERN_CRIT "Could not allocate interrupt" + " number for %s\n", np->full_name); + continue; + } + np->intrs[intrcount].line = irq_offset_up(virq); + } /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) { char *name = get_property(ic->parent, "name", NULL); if (name && !strcmp(name, "u3")) - np->intrs[i].line += 128; + np->intrs[intrcount].line += 128; } + np->intrs[intrcount].sense = 1; if (n > 1) - np->intrs[i].sense = irq[1]; + np->intrs[intrcount].sense = irq[1]; if (n > 2) { printk("hmmm, got %d intr cells for %s:", n, np->full_name); @@ -2249,8 +2257,9 @@ printk(" %d", irq[j]); printk("\n"); } - ints += intrcells; + ++intrcount; } + np->n_intrs = intrcount; return mem_start; } --- diff/arch/ppc64/kernel/rtas-proc.c 2004-05-19 22:11:19.000000000 +0100 +++ source/arch/ppc64/kernel/rtas-proc.c 2004-05-27 18:34:15.000000000 +0100 @@ -541,7 +541,7 @@ case SENSOR_BUSY: return "(busy)"; case SENSOR_NOT_EXIST: - return "(non existant)"; + return "(non existent)"; case SENSOR_DR_ENTITY: return "(dr entity removed)"; default: @@ -698,7 +698,7 @@ } break; default: - n += sprintf(buf+n, "Unkown sensor (type %d), ignoring it\n", + n += sprintf(buf+n, "Unknown sensor (type %d), ignoring it\n", s.token); unknown = 1; have_strings = 1; --- diff/arch/ppc64/kernel/setup.c 2004-05-27 13:41:16.000000000 +0100 +++ source/arch/ppc64/kernel/setup.c 2004-05-27 18:34:15.000000000 +0100 @@ -82,7 +82,6 @@ int powersave_nap; -char saved_command_line[COMMAND_LINE_SIZE]; unsigned char aux_device_present; void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5, @@ -572,6 +571,23 @@ extern void (*calibrate_delay)(void); +#ifdef CONFIG_IRQSTACKS +static void __init irqstack_early_init(void) +{ + int i; + + /* interrupt stacks must be under 256MB, we cannot afford to take SLB misses on them */ + for (i = 0; i < NR_CPUS; i++) { + softirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE, + THREAD_SIZE, 0x10000000)); + hardirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE, + THREAD_SIZE, 0x10000000)); + } +} +#else +#define irqstack_early_init() +#endif + /* * Called into from start_kernel, after lock_kernel has been called. * Initializes bootmem, which is unsed to manage page allocation until @@ -617,6 +633,8 @@ strlcpy(saved_command_line, cmd_line, sizeof(saved_command_line)); *cmdline_p = cmd_line; + irqstack_early_init(); + /* set up the bootmem stuff with available memory */ do_init_bootmem(); --- diff/arch/ppc64/kernel/viopath.c 2004-05-19 22:11:19.000000000 +0100 +++ source/arch/ppc64/kernel/viopath.c 2004-05-27 18:34:15.000000000 +0100 @@ -190,6 +190,8 @@ static int proc_viopath_show(struct seq_file *m, void *v) { char *buf; + u16 vlanMap; + int vlanIndex; dma_addr_t handle; HvLpEvent_Rc hvrc; DECLARE_MUTEX_LOCKED(Semaphore); @@ -216,12 +218,18 @@ down(&Semaphore); - dma_unmap_single(iSeries_vio_dev, handle, PAGE_SIZE, DMA_FROM_DEVICE); - kfree(buf); + vlanMap = HvLpConfig_getVirtualLanIndexMap(); + vlanIndex = 0; + while (vlanMap != 0){ + if (vlanMap & 0x8000) + vlanIndex++;; + vlanMap = vlanMap << 1; + } - buf[PAGE_SIZE] = '\0'; + buf[PAGE_SIZE-1] = '\0'; seq_printf(m, "%s", buf); + seq_printf(m, "AVAILABLE_VETH=%d\n", vlanIndex ); seq_printf(m, "SRLNBR=%c%c%c%c%c%c%c\n", e2a(xItExtVpdPanel.mfgID[2]), e2a(xItExtVpdPanel.mfgID[3]), @@ -231,6 +239,9 @@ e2a(xItExtVpdPanel.systemSerial[4]), e2a(xItExtVpdPanel.systemSerial[5])); + dma_unmap_single(iSeries_vio_dev, handle, PAGE_SIZE, DMA_FROM_DEVICE); + kfree(buf); + return 0; } --- diff/arch/ppc64/kernel/xics.c 2004-05-27 13:41:16.000000000 +0100 +++ source/arch/ppc64/kernel/xics.c 2004-05-27 18:34:15.000000000 +0100 @@ -620,7 +620,7 @@ cpumask_t tmp = CPU_MASK_NONE; irq = virt_irq_to_real(irq_offset_down(virq)); - if (irq == XICS_IPI) + if (irq == XICS_IPI || irq == NO_IRQ) return; status = rtas_call(ibm_get_xive, 1, 3, (void *)&xics_status, irq); --- diff/arch/ppc64/mm/fault.c 2004-05-19 22:11:19.000000000 +0100 +++ source/arch/ppc64/mm/fault.c 2004-05-27 18:34:15.000000000 +0100 @@ -75,6 +75,8 @@ return 0; } +int check_exception(struct pt_regs *regs); + /* * The error_code parameter is * - DSISR for a non-SLB data access fault, @@ -110,7 +112,29 @@ bad_page_fault(regs, address, SIGSEGV); return; } - down_read(&mm->mmap_sem); + + /* When running in the kernel we expect faults to occur only to + * addresses in user space. All other faults represent errors in the + * kernel and should generate an OOPS. Unfortunatly, in the case of an + * erroneous fault occuring in a code path which already holds mmap_sem + * we will deadlock attempting to validate the fault against the + * address space. Luckily the kernel only validly references user + * space from well defined areas of code, which are listed in the + * exceptions table. + * + * As the vast majority of faults will be valid we will only perform + * the source reference check when there is a possibilty of a deadlock. + * Attempt to lock the address space, if we cannot we then validate the + * source. If this is invalid we can skip the address space check, + * thus avoiding the deadlock. + */ + if (!down_read_trylock(&mm->mmap_sem)) { + if (!user_mode(regs) && !check_exception(regs)) + goto bad_area_nosemaphore; + + down_read(&mm->mmap_sem); + } + vma = find_vma(mm, address); if (!vma) goto bad_area; @@ -200,6 +224,7 @@ bad_area: up_read(&mm->mmap_sem); +bad_area_nosemaphore: /* User mode accesses cause a SIGSEGV */ if (user_mode(regs)) { info.si_signo = SIGSEGV; @@ -259,3 +284,15 @@ /* kernel has accessed a bad area */ die("Kernel access of bad area", regs, sig); } + +int check_exception(struct pt_regs *regs) +{ + const struct exception_table_entry *entry; + + /* Are we prepared to handle this fault? */ + if ((entry = search_exception_tables(regs->nip)) != NULL) { + return 1; + } + + return 0; +} --- diff/arch/ppc64/mm/init.c 2004-05-19 22:11:19.000000000 +0100 +++ source/arch/ppc64/mm/init.c 2004-05-27 18:34:15.000000000 +0100 @@ -407,7 +407,7 @@ area = im_get_area((unsigned long) addr, size, IM_REGION_EXISTS | IM_REGION_SUBSET); if (area == NULL) { - printk(KERN_ERR "%s() cannot unmap nonexistant range 0x%lx\n", + printk(KERN_ERR "%s() cannot unmap nonexistent range 0x%lx\n", __FUNCTION__, (unsigned long) addr); return 1; } --- diff/arch/ppc64/mm/numa.c 2004-05-19 22:11:19.000000000 +0100 +++ source/arch/ppc64/mm/numa.c 2004-05-27 18:34:15.000000000 +0100 @@ -19,7 +19,7 @@ #include #if 1 -#define dbg(args...) udbg_printf(args) +#define dbg(args...) printk(KERN_INFO args) #else #define dbg(args...) #endif @@ -56,16 +56,136 @@ } } +static struct device_node * __init find_cpu_node(unsigned int cpu) +{ + unsigned int hw_cpuid = get_hard_smp_processor_id(cpu); + struct device_node *cpu_node = NULL; + unsigned int *interrupt_server, *reg; + int len; + + while ((cpu_node = of_find_node_by_type(cpu_node, "cpu")) != NULL) { + /* Try interrupt server first */ + interrupt_server = (unsigned int *)get_property(cpu_node, + "ibm,ppc-interrupt-server#s", &len); + + if (interrupt_server && (len > 0)) { + while (len--) { + if (interrupt_server[len-1] == hw_cpuid) + return cpu_node; + } + } else { + reg = (unsigned int *)get_property(cpu_node, + "reg", &len); + if (reg && (len > 0) && (reg[0] == hw_cpuid)) + return cpu_node; + } + } + + return NULL; +} + +/* must hold reference to node during call */ +static int *of_get_associativity(struct device_node *dev) + { + unsigned int *result; + int len; + + result = (unsigned int *)get_property(dev, "ibm,associativity", &len); + + if (len <= 0) + return NULL; + + return result; +} + +static int of_node_numa_domain(struct device_node *device, int depth) +{ + int numa_domain; + unsigned int *tmp; + + tmp = of_get_associativity(device); + if (tmp && (tmp[0] >= depth)) { + numa_domain = tmp[depth]; + } else { + printk(KERN_ERR "WARNING: no NUMA information for " + "%s\n", device->full_name); + numa_domain = 0; + } + return numa_domain; +} + +/* + * In theory, the "ibm,associativity" property may contain multiple + * associativity lists because a resource may be multiply connected + * into the machine. This resource then has different associativity + * characteristics relative to its multiple connections. We ignore + * this for now. We also assume that all cpu and memory sets have + * their distances represented at a common level. This won't be + * true for heirarchical NUMA. + * + * In any case the ibm,associativity-reference-points should give + * the correct depth for a normal NUMA system. + * + * - Dave Hansen + */ +static int find_min_common_depth(void) +{ + int depth; + unsigned int *ref_points; + struct device_node *rtas_root; + unsigned int len; + + rtas_root = of_find_node_by_path("/rtas"); + + if (!rtas_root) { + printk(KERN_ERR "WARNING: %s() could not find rtas root\n", + __FUNCTION__); + return -1; + } + + /* + * this property is 2 32-bit integers, each representing a level of + * depth in the associativity nodes. The first is for an SMP + * configuration (should be all 0's) and the second is for a normal + * NUMA configuration. + */ + ref_points = (unsigned int *)get_property(rtas_root, + "ibm,associativity-reference-points", &len); + + if ((len >= 1) && ref_points) { + depth = ref_points[1]; + } else { + printk(KERN_ERR "WARNING: could not find NUMA " + "associativity reference point\n"); + depth = -1; + } + of_node_put(rtas_root); + + return depth; +} + +static unsigned long read_cell_ul(struct device_node *device, unsigned int **buf) +{ + int i; + unsigned long result = 0; + + i = prom_n_size_cells(device); + /* bug on i>2 ?? */ + while (i--) { + result = (result << 32) | **buf; + (*buf)++; + } + return result; +} + static int __init parse_numa_properties(void) { struct device_node *cpu = NULL; struct device_node *memory = NULL; - int *cpu_associativity; - int *memory_associativity; int depth; int max_domain = 0; long entries = lmb_end_of_DRAM() >> MEMORY_INCREMENT_SHIFT; - long i; + unsigned long i; if (strstr(saved_command_line, "numa=off")) { printk(KERN_WARNING "NUMA disabled by user\n"); @@ -78,112 +198,78 @@ for (i = 0; i < entries ; i++) numa_memory_lookup_table[i] = ARRAY_INITIALISER; - cpu = of_find_node_by_type(NULL, "cpu"); - if (!cpu) - goto err; - - memory = of_find_node_by_type(NULL, "memory"); - if (!memory) - goto err; - - cpu_associativity = (int *)get_property(cpu, "ibm,associativity", NULL); - if (!cpu_associativity) - goto err; - - memory_associativity = (int *)get_property(memory, "ibm,associativity", - NULL); - if (!memory_associativity) - goto err; - - /* find common depth */ - if (cpu_associativity[0] < memory_associativity[0]) - depth = cpu_associativity[0]; - else - depth = memory_associativity[0]; - - for (; cpu; cpu = of_find_node_by_type(cpu, "cpu")) { - int *tmp; - int cpu_nr, numa_domain; + depth = find_min_common_depth(); - tmp = (int *)get_property(cpu, "reg", NULL); - if (!tmp) - continue; - cpu_nr = *tmp; + printk(KERN_INFO "NUMA associativity depth for CPU/Memory: %d\n", depth); + if (depth < 0) + return depth; - tmp = (int *)get_property(cpu, "ibm,associativity", - NULL); - if (!tmp) - continue; - numa_domain = tmp[depth]; + for_each_cpu(i) { + int numa_domain; + + cpu = find_cpu_node(i); - /* FIXME */ - if (numa_domain == 0xffff) { - dbg("cpu %d has no numa doman\n", cpu_nr); + if (cpu) { + numa_domain = of_node_numa_domain(cpu, depth); + of_node_put(cpu); + + if (numa_domain >= MAX_NUMNODES) { + /* + * POWER4 LPAR uses 0xffff as invalid node, + * dont warn in this case. + */ + if (numa_domain != 0xffff) + printk(KERN_ERR "WARNING: cpu %ld " + "maps to invalid NUMA node %d\n", + i, numa_domain); + numa_domain = 0; + } + } else { + printk(KERN_ERR "WARNING: no NUMA information for " + "cpu %ld\n", i); numa_domain = 0; } - if (numa_domain >= MAX_NUMNODES) - BUG(); - node_set_online(numa_domain); if (max_domain < numa_domain) max_domain = numa_domain; - map_cpu_to_node(cpu_nr, numa_domain); - /* register the second thread on an SMT machine */ - if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) - map_cpu_to_node(cpu_nr ^ 0x1, numa_domain); + map_cpu_to_node(i, numa_domain); } - for (; memory; memory = of_find_node_by_type(memory, "memory")) { - unsigned int *tmp1, *tmp2; - unsigned long i; - unsigned long start = 0; - unsigned long size = 0; + memory = NULL; + while ((memory = of_find_node_by_type(memory, "memory")) != NULL) { + unsigned long start; + unsigned long size; int numa_domain; int ranges; + unsigned int *memcell_buf; + unsigned int len; - tmp1 = (int *)get_property(memory, "reg", NULL); - if (!tmp1) + memcell_buf = (unsigned int *)get_property(memory, "reg", &len); + if (!memcell_buf || len <= 0) continue; ranges = memory->n_addrs; new_range: - - i = prom_n_size_cells(memory); - while (i--) { - start = (start << 32) | *tmp1; - tmp1++; - } - - i = prom_n_size_cells(memory); - while (i--) { - size = (size << 32) | *tmp1; - tmp1++; - } + /* these are order-sensitive, and modify the buffer pointer */ + start = read_cell_ul(memory, &memcell_buf); + size = read_cell_ul(memory, &memcell_buf); start = _ALIGN_DOWN(start, MEMORY_INCREMENT); size = _ALIGN_UP(size, MEMORY_INCREMENT); - if ((start + size) > MAX_MEMORY) - BUG(); + numa_domain = of_node_numa_domain(memory, depth); - tmp2 = (int *)get_property(memory, "ibm,associativity", - NULL); - if (!tmp2) - continue; - numa_domain = tmp2[depth]; - - /* FIXME */ - if (numa_domain == 0xffff) { - dbg("memory has no numa doman\n"); + if (numa_domain >= MAX_NUMNODES) { + if (numa_domain != 0xffff) + printk(KERN_ERR "WARNING: memory at %lx maps " + "to invalid NUMA node %d\n", start, + numa_domain); numa_domain = 0; } - if (numa_domain >= MAX_NUMNODES) - BUG(); - node_set_online(numa_domain); if (max_domain < numa_domain) @@ -205,11 +291,13 @@ start, size); continue; } - node_data[numa_domain].node_spanned_pages += size / PAGE_SIZE; + node_data[numa_domain].node_spanned_pages += + size / PAGE_SIZE; } else { node_data[numa_domain].node_start_pfn = start / PAGE_SIZE; - node_data[numa_domain].node_spanned_pages = size / PAGE_SIZE; + node_data[numa_domain].node_spanned_pages = + size / PAGE_SIZE; } for (i = start ; i < (start+size); i += MEMORY_INCREMENT) @@ -227,10 +315,6 @@ numnodes = max_domain + 1; return 0; -err: - of_node_put(cpu); - of_node_put(memory); - return -1; } static void __init setup_nonnuma(void) --- diff/arch/ppc64/mm/tlb.c 2004-05-27 13:41:16.000000000 +0100 +++ source/arch/ppc64/mm/tlb.c 2004-05-27 18:34:15.000000000 +0100 @@ -41,6 +41,33 @@ DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); unsigned long pte_freelist_forced_free; +void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage) +{ + /* This is safe as we are holding page_table_lock */ + cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id()); + struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); + + if (atomic_read(&tlb->mm->mm_users) < 2 || + cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) { + pte_free(ptepage); + return; + } + + if (*batchp == NULL) { + *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC); + if (*batchp == NULL) { + pte_free_now(ptepage); + return; + } + (*batchp)->index = 0; + } + (*batchp)->pages[(*batchp)->index++] = ptepage; + if ((*batchp)->index == PTE_FREELIST_SIZE) { + pte_free_submit(*batchp); + *batchp = NULL; + } +} + /* * Update the MMU hash table to correspond with a change to * a Linux PTE. If wrprot is true, it is permissible to --- diff/arch/ppc64/xmon/xmon.c 2004-05-27 13:41:16.000000000 +0100 +++ source/arch/ppc64/xmon/xmon.c 2004-05-27 18:34:15.000000000 +0100 @@ -273,7 +273,7 @@ args.args[0] = SURVEILLANCE_TOKEN; args.args[1] = 0; args.args[2] = 0; - enter_rtas((void *) __pa(&args)); + enter_rtas(__pa(&args)); } #endif } @@ -1399,8 +1399,7 @@ /* Look for "regshere" marker to see if this is an exception frame. */ - if (newsp - sp == sizeof(struct pt_regs) + 400 - && mread(sp + 0x60, &marker, sizeof(unsigned long)) + if (mread(sp + 0x60, &marker, sizeof(unsigned long)) && marker == 0x7265677368657265) { if (mread(sp + 0x70, ®s, sizeof(regs)) != sizeof(regs)) { @@ -1417,12 +1416,6 @@ if (newsp == 0) break; - if (newsp < sp) { - printf("Stack chain goes %s: %.16lx\n", - (newsp < KERNELBASE? "into userspace": - "backwards"), newsp); - break; - } sp = newsp; } while (count++ < xmon_depth_to_print); --- diff/arch/s390/kernel/init_task.c 2004-05-19 22:11:20.000000000 +0100 +++ source/arch/s390/kernel/init_task.c 2004-05-27 18:34:15.000000000 +0100 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include --- diff/arch/s390/kernel/setup.c 2004-05-19 22:11:20.000000000 +0100 +++ source/arch/s390/kernel/setup.c 2004-05-27 18:34:15.000000000 +0100 @@ -74,7 +74,6 @@ #include static char command_line[COMMAND_LINE_SIZE] = { 0, }; - char saved_command_line[COMMAND_LINE_SIZE]; static struct resource code_resource = { "Kernel code", 0x100000, 0 }; static struct resource data_resource = { "Kernel data", 0, 0 }; --- diff/arch/sh/kernel/init_task.c 2004-05-19 22:11:22.000000000 +0100 +++ source/arch/sh/kernel/init_task.c 2004-05-27 18:34:15.000000000 +0100 @@ -2,6 +2,7 @@ #include #include #include +#include #include #include --- diff/arch/sh/kernel/setup.c 2004-05-19 22:11:22.000000000 +0100 +++ source/arch/sh/kernel/setup.c 2004-05-27 18:34:15.000000000 +0100 @@ -85,14 +85,12 @@ #define INITRD_SIZE (*(unsigned long *) (PARAM+0x014)) /* ... */ #define COMMAND_LINE ((char *) (PARAM+0x100)) -#define COMMAND_LINE_SIZE 256 #define RAMDISK_IMAGE_START_MASK 0x07FF #define RAMDISK_PROMPT_FLAG 0x8000 #define RAMDISK_LOAD_FLAG 0x4000 static char command_line[COMMAND_LINE_SIZE] = { 0, }; - char saved_command_line[COMMAND_LINE_SIZE]; struct resource standard_io_resources[] = { { "dma1", 0x00, 0x1f }, --- diff/arch/sparc/kernel/init_task.c 2004-05-19 22:11:22.000000000 +0100 +++ source/arch/sparc/kernel/init_task.c 2004-05-27 18:34:15.000000000 +0100 @@ -2,6 +2,7 @@ #include #include #include +#include #include #include --- diff/arch/sparc/kernel/setup.c 2004-05-19 22:11:23.000000000 +0100 +++ source/arch/sparc/kernel/setup.c 2004-05-27 18:34:15.000000000 +0100 @@ -244,8 +244,7 @@ extern int root_mountflags; -char saved_command_line[256]; -char reboot_command[256]; +char reboot_command[COMMAND_LINE_SIZE]; enum sparc_cpu sparc_cpu_model; struct tt_entry *sparc_ttable; --- diff/arch/sparc/kernel/sparc_ksyms.c 2004-05-19 22:11:23.000000000 +0100 +++ source/arch/sparc/kernel/sparc_ksyms.c 2004-05-27 18:34:15.000000000 +0100 @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -74,7 +75,6 @@ extern void *__memscan_generic(void *, int, size_t); extern int __memcmp(const void *, const void *, __kernel_size_t); extern int __strncmp(const char *, const char *, __kernel_size_t); -extern char saved_command_line[]; extern void bcopy (const char *, char *, int); extern int __ashrdi3(int, int); --- diff/arch/sparc64/Kconfig 2004-05-19 22:11:23.000000000 +0100 +++ source/arch/sparc64/Kconfig 2004-05-27 18:34:15.000000000 +0100 @@ -687,12 +687,19 @@ depends on DEBUG_KERNEL bool "Debug BOOTMEM initialization" +config LOCKMETER + bool "Kernel lock metering" + depends on SMP && !PREEMPT + help + Say Y to enable kernel lock metering, which adds overhead to SMP locks, + but allows you to see various statistics using the lockstat command. + # We have a custom atomic_dec_and_lock() implementation but it's not # compatible with spinlock debugging so we need to fall back on # the generic version in that case. config HAVE_DEC_LOCK bool - depends on SMP && !DEBUG_SPINLOCK + depends on SMP && !DEBUG_SPINLOCK && !LOCKMETER default y config MCOUNT --- diff/arch/sparc64/kernel/init_task.c 2004-05-19 22:11:24.000000000 +0100 +++ source/arch/sparc64/kernel/init_task.c 2004-05-27 18:34:15.000000000 +0100 @@ -2,6 +2,7 @@ #include #include #include +#include #include #include --- diff/arch/sparc64/kernel/ioctl32.c 2004-05-19 22:11:24.000000000 +0100 +++ source/arch/sparc64/kernel/ioctl32.c 2004-05-27 18:34:15.000000000 +0100 @@ -148,306 +148,6 @@ return ret; } -struct ncp_ioctl_request_32 { - unsigned int function; - unsigned int size; - compat_caddr_t data; -}; - -struct ncp_fs_info_v2_32 { - int version; - unsigned int mounted_uid; - unsigned int connection; - unsigned int buffer_size; - - unsigned int volume_number; - __u32 directory_id; - - __u32 dummy1; - __u32 dummy2; - __u32 dummy3; -}; - -struct ncp_objectname_ioctl_32 -{ - int auth_type; - unsigned int object_name_len; - compat_caddr_t object_name; /* an userspace data, in most cases user name */ -}; - -struct ncp_privatedata_ioctl_32 -{ - unsigned int len; - compat_caddr_t data; /* ~1000 for NDS */ -}; - -#define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct ncp_ioctl_request_32) - -#define NCP_IOC_GETMOUNTUID2_32 _IOW('n', 2, unsigned int) - -#define NCP_IOC_GET_FS_INFO_V2_32 _IOWR('n', 4, struct ncp_fs_info_v2_32) - -#define NCP_IOC_GETOBJECTNAME_32 _IOWR('n', 9, struct ncp_objectname_ioctl_32) -#define NCP_IOC_SETOBJECTNAME_32 _IOR('n', 9, struct ncp_objectname_ioctl_32) -#define NCP_IOC_GETPRIVATEDATA_32 _IOWR('n', 10, struct ncp_privatedata_ioctl_32) -#define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct ncp_privatedata_ioctl_32) - -static int do_ncp_ncprequest(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ncp_ioctl_request_32 n32; - struct ncp_ioctl_request n; - mm_segment_t old_fs; - int err; - - if (copy_from_user(&n32, (struct ncp_ioctl_request_32*)arg, - sizeof(n32))) - return -EFAULT; - - n.function = n32.function; - n.size = n32.size; - if (n.size > 65536) - return -EINVAL; - n.data = vmalloc(65536); /* 65536 must be same as NCP_PACKET_SIZE_INTERNAL in ncpfs */ - if (!n.data) - return -ENOMEM; - err = -EFAULT; - if (copy_from_user(n.data, A(n32.data), n.size)) - goto out; - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, NCP_IOC_NCPREQUEST, (unsigned long)&n); - set_fs (old_fs); - if(err <= 0) - goto out; - if (err > 65536) { - err = -EINVAL; - goto out; - } - if (copy_to_user(A(n32.data), n.data, err)) { - err = -EFAULT; - goto out; - } - out: - vfree(n.data); - return err; -} - -static int do_ncp_getmountuid2(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - __kernel_uid_t kuid; - int err; - - cmd = NCP_IOC_GETMOUNTUID2; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&kuid); - set_fs(old_fs); - - if (!err) - err = put_user(kuid, (unsigned int*)arg); - - return err; -} - -static int do_ncp_getfsinfo2(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct ncp_fs_info_v2_32 n32; - struct ncp_fs_info_v2 n; - int err; - - if (copy_from_user(&n32, (struct ncp_fs_info_v2_32*)arg, sizeof(n32))) - return -EFAULT; - if (n32.version != NCP_GET_FS_INFO_VERSION_V2) - return -EINVAL; - n.version = NCP_GET_FS_INFO_VERSION_V2; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, NCP_IOC_GET_FS_INFO_V2, (unsigned long)&n); - set_fs(old_fs); - - if (!err) { - n32.version = n.version; - n32.mounted_uid = n.mounted_uid; - n32.connection = n.connection; - n32.buffer_size = n.buffer_size; - n32.volume_number = n.volume_number; - n32.directory_id = n.directory_id; - n32.dummy1 = n.dummy1; - n32.dummy2 = n.dummy2; - n32.dummy3 = n.dummy3; - err = copy_to_user((struct ncp_fs_info_v2_32*)arg, &n32, sizeof(n32)) ? -EFAULT : 0; - } - return err; -} - -static int do_ncp_getobjectname(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ncp_objectname_ioctl_32 n32; - struct ncp_objectname_ioctl n; - mm_segment_t old_fs; - int err; - size_t tl; - - if (copy_from_user(&n32, (struct ncp_objectname_ioctl_32*)arg, - sizeof(n32))) - return -EFAULT; - - n.object_name_len = tl = n32.object_name_len; - if (tl) { - n.object_name = kmalloc(tl, GFP_KERNEL); - if (!n.object_name) - return -ENOMEM; - } else { - n.object_name = NULL; - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, NCP_IOC_GETOBJECTNAME, (unsigned long)&n); - set_fs (old_fs); - if(err) - goto out; - - if (tl > n.object_name_len) - tl = n.object_name_len; - - err = -EFAULT; - if (tl && copy_to_user(A(n32.object_name), n.object_name, tl)) - goto out; - - n32.auth_type = n.auth_type; - n32.object_name_len = n.object_name_len; - - if (copy_to_user((struct ncp_objectname_ioctl_32*)arg, &n32, sizeof(n32))) - goto out; - - err = 0; - out: - if (n.object_name) - kfree(n.object_name); - - return err; -} - -static int do_ncp_setobjectname(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ncp_objectname_ioctl_32 n32; - struct ncp_objectname_ioctl n; - mm_segment_t old_fs; - int err; - size_t tl; - - if (copy_from_user(&n32, (struct ncp_objectname_ioctl_32*)arg, - sizeof(n32))) - return -EFAULT; - - n.auth_type = n32.auth_type; - n.object_name_len = tl = n32.object_name_len; - if (tl) { - n.object_name = kmalloc(tl, GFP_KERNEL); - if (!n.object_name) - return -ENOMEM; - err = -EFAULT; - if (copy_from_user(n.object_name, A(n32.object_name), tl)) - goto out; - } else { - n.object_name = NULL; - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, NCP_IOC_SETOBJECTNAME, (unsigned long)&n); - set_fs (old_fs); - - out: - if (n.object_name) - kfree(n.object_name); - - return err; -} - -static int do_ncp_getprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ncp_privatedata_ioctl_32 n32; - struct ncp_privatedata_ioctl n; - mm_segment_t old_fs; - int err; - size_t tl; - - if (copy_from_user(&n32, (struct ncp_privatedata_ioctl_32*)arg, - sizeof(n32))) - return -EFAULT; - - n.len = tl = n32.len; - if (tl) { - n.data = kmalloc(tl, GFP_KERNEL); - if (!n.data) - return -ENOMEM; - } else { - n.data = NULL; - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, NCP_IOC_GETPRIVATEDATA, (unsigned long)&n); - set_fs (old_fs); - if(err) - goto out; - - if (tl > n.len) - tl = n.len; - - err = -EFAULT; - if (tl && copy_to_user(A(n32.data), n.data, tl)) - goto out; - - n32.len = n.len; - - if (copy_to_user((struct ncp_privatedata_ioctl_32*)arg, &n32, sizeof(n32))) - goto out; - - err = 0; - out: - if (n.data) - kfree(n.data); - - return err; -} - -static int do_ncp_setprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ncp_privatedata_ioctl_32 n32; - struct ncp_privatedata_ioctl n; - mm_segment_t old_fs; - int err; - size_t tl; - - if (copy_from_user(&n32, (struct ncp_privatedata_ioctl_32*)arg, - sizeof(n32))) - return -EFAULT; - - n.len = tl = n32.len; - if (tl) { - n.data = kmalloc(tl, GFP_KERNEL); - if (!n.data) - return -ENOMEM; - err = -EFAULT; - if (copy_from_user(n.data, A(n32.data), tl)) - goto out; - } else { - n.data = NULL; - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, NCP_IOC_SETPRIVATEDATA, (unsigned long)&n); - set_fs (old_fs); - - out: - if (n.data) - kfree(n.data); - - return err; -} - #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) /* This really belongs in include/linux/drm.h -DaveM */ #include "../../../drivers/char/drm/drm.h" @@ -1070,18 +770,6 @@ COMPATIBLE_IOCTL(AUDIO_GETDEV_SUNOS) COMPATIBLE_IOCTL(AUDIO_FLUSH) COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI) -/* NCP ioctls which do not need any translations */ -COMPATIBLE_IOCTL(NCP_IOC_CONN_LOGGED_IN) -COMPATIBLE_IOCTL(NCP_IOC_SIGN_INIT) -COMPATIBLE_IOCTL(NCP_IOC_SIGN_WANTED) -COMPATIBLE_IOCTL(NCP_IOC_SET_SIGN_WANTED) -COMPATIBLE_IOCTL(NCP_IOC_LOCKUNLOCK) -COMPATIBLE_IOCTL(NCP_IOC_GETROOT) -COMPATIBLE_IOCTL(NCP_IOC_SETROOT) -COMPATIBLE_IOCTL(NCP_IOC_GETCHARSETS) -COMPATIBLE_IOCTL(NCP_IOC_SETCHARSETS) -COMPATIBLE_IOCTL(NCP_IOC_GETDENTRYTTL) -COMPATIBLE_IOCTL(NCP_IOC_SETDENTRYTTL) #if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) COMPATIBLE_IOCTL(DRM_IOCTL_IRQ_BUSID) @@ -1107,14 +795,6 @@ COMPATIBLE_IOCTL(WIOCSTOP) COMPATIBLE_IOCTL(WIOCGSTAT) /* And these ioctls need translation */ -/* NCPFS */ -HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest) -HANDLE_IOCTL(NCP_IOC_GETMOUNTUID2_32, do_ncp_getmountuid2) -HANDLE_IOCTL(NCP_IOC_GET_FS_INFO_V2_32, do_ncp_getfsinfo2) -HANDLE_IOCTL(NCP_IOC_GETOBJECTNAME_32, do_ncp_getobjectname) -HANDLE_IOCTL(NCP_IOC_SETOBJECTNAME_32, do_ncp_setobjectname) -HANDLE_IOCTL(NCP_IOC_GETPRIVATEDATA_32, do_ncp_getprivatedata) -HANDLE_IOCTL(NCP_IOC_SETPRIVATEDATA_32, do_ncp_setprivatedata) /* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */ HANDLE_IOCTL(FBIOPUTCMAP32, fbiogetputcmap) HANDLE_IOCTL(FBIOGETCMAP32, fbiogetputcmap) --- diff/arch/sparc64/kernel/setup.c 2004-05-19 22:11:24.000000000 +0100 +++ source/arch/sparc64/kernel/setup.c 2004-05-27 18:34:15.000000000 +0100 @@ -451,8 +451,7 @@ extern int root_mountflags; -char saved_command_line[256]; -char reboot_command[256]; +char reboot_command[COMMAND_LINE_SIZE]; static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 }; --- diff/arch/sparc64/kernel/sparc64_ksyms.c 2004-05-19 22:11:24.000000000 +0100 +++ source/arch/sparc64/kernel/sparc64_ksyms.c 2004-05-27 18:34:15.000000000 +0100 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -76,7 +77,6 @@ extern int __strncmp(const char *, const char *, __kernel_size_t); extern __kernel_size_t __strlen(const char *); extern __kernel_size_t strlen(const char *); -extern char saved_command_line[]; extern void linux_sparc_syscall(void); extern void rtrap(void); extern void show_regs(struct pt_regs *); --- diff/arch/sparc64/lib/rwlock.S 2004-05-19 22:11:25.000000000 +0100 +++ source/arch/sparc64/lib/rwlock.S 2004-05-27 18:34:15.000000000 +0100 @@ -85,5 +85,20 @@ __write_trylock_fail: retl mov 0, %o0 + + .globl __read_trylock +__read_trylock: /* %o0 = lock_ptr */ + ldsw [%o0], %g5 + brlz,pn %g5, 100f + add %g5, 1, %g7 + cas [%o0], %g5, %g7 + cmp %g5, %g7 + bne,pn %icc, __read_trylock + membar #StoreLoad | #StoreStore + retl + mov 1, %o0 +100: retl + mov 0, %o0 + rwlock_impl_end: --- diff/arch/um/kernel/init_task.c 2004-05-19 22:11:27.000000000 +0100 +++ source/arch/um/kernel/init_task.c 2004-05-27 18:34:15.000000000 +0100 @@ -9,6 +9,7 @@ #include "linux/sched.h" #include "linux/init_task.h" #include "linux/version.h" +#include "linux/mqueue.h" #include "asm/uaccess.h" #include "asm/pgtable.h" #include "user_util.h" --- diff/arch/um/kernel/user_util.c 2004-05-19 22:11:27.000000000 +0100 +++ source/arch/um/kernel/user_util.c 2004-05-27 18:34:15.000000000 +0100 @@ -34,7 +34,6 @@ #define COMMAND_LINE_SIZE _POSIX_ARG_MAX /* Changed in linux_main and setup_arch, which run before SMP is started */ -char saved_command_line[COMMAND_LINE_SIZE] = { 0 }; char command_line[COMMAND_LINE_SIZE] = { 0 }; void add_arg(char *cmd_line, char *arg) --- diff/arch/v850/kernel/init_task.c 2004-05-19 22:11:28.000000000 +0100 +++ source/arch/v850/kernel/init_task.c 2004-05-27 18:34:15.000000000 +0100 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include --- diff/arch/v850/kernel/setup.c 2004-05-19 22:11:28.000000000 +0100 +++ source/arch/v850/kernel/setup.c 2004-05-27 18:34:15.000000000 +0100 @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -40,8 +41,7 @@ extern char _root_fs_image_end __attribute__ ((__weak__)); -char command_line[512]; -char saved_command_line[512]; +char command_line[COMMAND_LINE_SIZE]; /* Memory not used by the kernel. */ static unsigned long total_ram_pages; --- diff/arch/x86_64/Kconfig 2004-05-27 13:41:16.000000000 +0100 +++ source/arch/x86_64/Kconfig 2004-05-27 18:34:15.000000000 +0100 @@ -455,12 +455,26 @@ config DEBUG_INFO bool "Compile the kernel with debug info" depends on DEBUG_KERNEL + default n help If you say Y here the resulting kernel image will include debugging info resulting in a larger kernel image. Say Y here only if you plan to use gdb to debug the kernel. Please note that this option requires new binutils. If you don't debug the kernel, you can say N. + +config SCHEDSTATS + bool "Collect scheduler statistics" + depends on PROC_FS + default n + help + If you say Y here, additional code will be inserted into the + scheduler and related routines to collect statistics about + scheduler behavior and provide them in /proc/schedstat. These + stats may be useful for both tuning and debugging the scheduler + If you aren't debugging the scheduler or trying to tune a specific + application, you can say N to avoid the very slight overhead + this adds. config FRAME_POINTER bool "Compile the kernel with frame pointers" @@ -493,9 +507,8 @@ help Add a simple leak tracer to the IOMMU code. This is useful when you are debugging a buggy device driver that leaks IOMMU mappings. - -#config X86_REMOTE_DEBUG -# bool "kgdb debugging stub" + +source "arch/x86_64/Kconfig.kgdb" endmenu --- diff/arch/x86_64/kernel/Makefile 2004-05-27 13:41:16.000000000 +0100 +++ source/arch/x86_64/kernel/Makefile 2004-05-27 18:34:15.000000000 +0100 @@ -28,6 +28,7 @@ obj-$(CONFIG_SCHED_SMT) += domain.o obj-$(CONFIG_MODULES) += module.o +obj-$(CONFIG_KGDB) += kgdb_stub.o obj-y += topology.o --- diff/arch/x86_64/kernel/e820.c 2004-05-19 22:11:28.000000000 +0100 +++ source/arch/x86_64/kernel/e820.c 2004-05-27 18:34:15.000000000 +0100 @@ -34,7 +34,7 @@ */ unsigned long end_user_pfn = MAXMEM>>PAGE_SHIFT; -extern struct resource code_resource, data_resource, vram_resource; +extern struct resource code_resource, data_resource; /* Check for some hardcoded bad areas that early boot is not allowed to touch */ static inline int bad_addr(unsigned long *addrp, unsigned long size) --- diff/arch/x86_64/kernel/init_task.c 2004-05-19 22:11:28.000000000 +0100 +++ source/arch/x86_64/kernel/init_task.c 2004-05-27 18:34:15.000000000 +0100 @@ -4,6 +4,7 @@ #include #include #include +#include #include #include --- diff/arch/x86_64/kernel/irq.c 2004-05-19 22:11:28.000000000 +0100 +++ source/arch/x86_64/kernel/irq.c 2004-05-27 18:34:15.000000000 +0100 @@ -405,6 +405,9 @@ spin_unlock(&desc->lock); irq_exit(); + + kgdb_process_breakpoint(); + return 1; } --- diff/arch/x86_64/kernel/mpparse.c 2004-05-27 13:41:16.000000000 +0100 +++ source/arch/x86_64/kernel/mpparse.c 2004-05-27 18:34:15.000000000 +0100 @@ -884,91 +884,54 @@ return; } - -extern FADT_DESCRIPTOR acpi_fadt; - -#ifdef CONFIG_ACPI_PCI - -void __init mp_parse_prt (void) +void mp_register_gsi (u32 gsi, int edge_level, int active_high_low) { - struct list_head *node = NULL; - struct acpi_prt_entry *entry = NULL; int ioapic = -1; int ioapic_pin = 0; - int gsi = 0; int idx, bit = 0; - int edge_level = 0; - int active_high_low = 0; - /* - * Parsing through the PCI Interrupt Routing Table (PRT) and program - * routing for all static (IOAPIC-direct) entries. - */ - list_for_each(node, &acpi_prt.entries) { - entry = list_entry(node, struct acpi_prt_entry, node); + if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) + return; - /* Need to get gsi for dynamic entry */ - if (entry->link.handle) { - gsi = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, &edge_level, &active_high_low); - if (!gsi) - continue; - } else { - /* Hardwired GSI. Assume PCI standard settings */ - gsi = entry->link.index; - edge_level = 1; - active_high_low = 1; - } - - /* Don't set up the ACPI SCI because it's already set up */ - if (acpi_fadt.sci_int == gsi) { - /* we still need to set up the entry's irq */ - acpi_gsi_to_irq(gsi, &entry->irq); - continue; - } - - ioapic = mp_find_ioapic(gsi); - if (ioapic < 0) - continue; - ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start; - - /* - * Avoid pin reprogramming. PRTs typically include entries - * with redundant pin->gsi mappings (but unique PCI devices); - * we only only program the IOAPIC on the first. - */ - bit = ioapic_pin % 32; - idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32); - if (idx > 3) { - printk(KERN_ERR "Invalid reference to IOAPIC pin " - "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, - ioapic_pin); - continue; - } - if ((1<irq); - continue; - } - - mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<irq); - } - printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d\n", - entry->id.segment, entry->id.bus, - entry->id.device, ('A' + entry->pin), - mp_ioapic_routing[ioapic].apic_id, ioapic_pin, - entry->irq); +#ifdef CONFIG_ACPI_BUS + /* Don't set up the ACPI SCI because it's already set up */ + if (acpi_fadt.sci_int == gsi) + return; +#endif + + ioapic = mp_find_ioapic(gsi); + if (ioapic < 0) { + printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); + return; } - - print_IO_APIC(); - return; -} + ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_start; -#endif /*CONFIG_ACPI_PCI*/ + /* + * Avoid pin reprogramming. PRTs typically include entries + * with redundant pin->gsi mappings (but unique PCI devices); + * we only program the IOAPIC on the first. + */ + bit = ioapic_pin % 32; + idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32); + if (idx > 3) { + printk(KERN_ERR "Invalid reference to IOAPIC pin " + "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, + ioapic_pin); + return; + } + if ((1< upper || !checksum(rom, length)) + if (!length || start + length > upper || !romchecksum(rom, length)) continue; adapter_rom_resources[i].start = start; @@ -554,13 +555,13 @@ probe_roms(); e820_reserve_resources(); - request_resource(&iomem_resource, &vram_resource); + request_resource(&iomem_resource, &video_ram_resource); { unsigned i; /* request I/O space for devices used on all i[345]86 PCs */ for (i = 0; i < STANDARD_IO_RESOURCES; i++) - request_resource(&ioport_resource, standard_io_resources+i); + request_resource(&ioport_resource, &standard_io_resources[i]); } /* Will likely break when you have unassigned resources with more --- diff/arch/x86_64/kernel/smp.c 2004-05-27 13:41:16.000000000 +0100 +++ source/arch/x86_64/kernel/smp.c 2004-05-27 18:34:15.000000000 +0100 @@ -362,6 +362,18 @@ send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR); } +#ifdef CONFIG_KGDB +/* + * By using the NMI code instead of a vector we just sneak thru the + * word generator coming out with just what we want. AND it does + * not matter if clustered_apic_mode is set or not. + */ +void smp_send_nmi_allbutself(void) +{ + send_IPI_allbutself(APIC_DM_NMI); +} +#endif + /* * Structure and data for smp_call_function(). This is designed to minimise * static memory requirements. It also looks cleaner. --- diff/arch/x86_64/kernel/traps.c 2004-05-27 13:41:16.000000000 +0100 +++ source/arch/x86_64/kernel/traps.c 2004-05-27 18:34:15.000000000 +0100 @@ -45,6 +45,9 @@ #include #include +#ifdef CONFIG_KGDB +#include +#endif extern struct gate_struct idt_table[256]; --- diff/arch/x86_64/lib/Makefile 2004-05-19 22:11:29.000000000 +0100 +++ source/arch/x86_64/lib/Makefile 2004-05-27 18:34:15.000000000 +0100 @@ -10,3 +10,4 @@ lib-y += memcpy.o memmove.o memset.o copy_user.o lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o +lib-$(CONFIG_KGDB) += kgdb_serial.o --- diff/crypto/cipher.c 2004-05-19 22:11:29.000000000 +0100 +++ source/crypto/cipher.c 2004-05-27 18:34:15.000000000 +0100 @@ -68,19 +68,20 @@ for(;;) { u8 *src_p, *dst_p; + int in_place; scatterwalk_map(&walk_in, 0); scatterwalk_map(&walk_out, 1); src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src); dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst); + in_place = scatterwalk_samebuf(&walk_in, &walk_out, + src_p, dst_p); nbytes -= bsize; scatterwalk_copychunks(src_p, &walk_in, bsize, 0); - prfn(tfm, dst_p, src_p, crfn, enc, info, - scatterwalk_samebuf(&walk_in, &walk_out, - src_p, dst_p)); + prfn(tfm, dst_p, src_p, crfn, enc, info, in_place); scatterwalk_done(&walk_in, 0, nbytes); --- diff/crypto/scatterwalk.h 2004-05-19 22:11:29.000000000 +0100 +++ source/crypto/scatterwalk.h 2004-05-27 18:34:15.000000000 +0100 @@ -38,6 +38,7 @@ void *src_p, void *dst_p) { return walk_in->page == walk_out->page && + walk_in->offset == walk_out->offset && walk_in->data == src_p && walk_out->data == dst_p; } --- diff/drivers/acpi/Kconfig 2004-05-19 22:11:29.000000000 +0100 +++ source/drivers/acpi/Kconfig 2004-05-27 18:34:15.000000000 +0100 @@ -267,7 +267,7 @@ (TSC) timing source. So, if you see messages like 'Losing too many ticks!' in the - kernel logs, and/or you are using a this on a notebook which + kernel logs, and/or you are using this on a notebook which does not yet have an HPET, you should say "Y" here. endmenu --- diff/drivers/acpi/pci_irq.c 2004-05-19 22:11:29.000000000 +0100 +++ source/drivers/acpi/pci_irq.c 2004-05-27 18:34:15.000000000 +0100 @@ -35,12 +35,6 @@ #include #include #include -#ifdef CONFIG_X86_IO_APIC -#include -#endif -#ifdef CONFIG_IOSAPIC -# include -#endif #include #include @@ -50,10 +44,6 @@ struct acpi_prt_list acpi_prt; -#ifdef CONFIG_X86 -extern void eisa_set_level_irq(unsigned int irq); -#endif - /* -------------------------------------------------------------------------- PCI IRQ Routing Table (PRT) Support @@ -237,12 +227,18 @@ PCI Interrupt Routing Support -------------------------------------------------------------------------- */ -int -acpi_pci_irq_lookup (struct pci_bus *bus, int device, int pin) +static int +acpi_pci_irq_lookup ( + struct pci_bus *bus, + int device, + int pin, + int *edge_level, + int *active_high_low) { struct acpi_prt_entry *entry = NULL; int segment = pci_domain_nr(bus); int bus_nr = bus->number; + int irq; ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup"); @@ -255,28 +251,30 @@ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n")); return_VALUE(0); } - - if (!entry->irq && entry->link.handle) { - entry->irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, NULL, NULL); - if (!entry->irq) { + + if (entry->link.handle) { + irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, edge_level, active_high_low); + if (!irq) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); return_VALUE(0); } - } - else if (!entry->irq) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid static routing entry (IRQ 0)\n")); - return_VALUE(0); + } else { + irq = entry->link.index; + *edge_level = ACPI_LEVEL_SENSITIVE; + *active_high_low = ACPI_ACTIVE_LOW; } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", entry->irq)); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); - return_VALUE(entry->irq); + return_VALUE(irq); } static int acpi_pci_irq_derive ( struct pci_dev *dev, - int pin) + int pin, + int *edge_level, + int *active_high_low) { struct pci_dev *bridge = dev; int irq = 0; @@ -308,8 +306,8 @@ pin = bridge_pin; } - irq = acpi_pci_irq_lookup(bridge->bus, - PCI_SLOT(bridge->devfn), pin); + irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), + pin, edge_level, active_high_low); } if (!irq) { @@ -330,6 +328,8 @@ { int irq = 0; u8 pin = 0; + int edge_level = ACPI_LEVEL_SENSITIVE; + int active_high_low = ACPI_ACTIVE_LOW; ACPI_FUNCTION_TRACE("acpi_pci_irq_enable"); @@ -352,21 +352,22 @@ * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT * values override any BIOS-assigned IRQs set during boot. */ - irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin); + irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, &edge_level, &active_high_low); /* * If no PRT entry was found, we'll try to derive an IRQ from the * device's parent bridge. */ if (!irq) - irq = acpi_pci_irq_derive(dev, pin); + irq = acpi_pci_irq_derive(dev, pin, &edge_level, &active_high_low); /* * No IRQ known to the ACPI subsystem - maybe the BIOS / * driver reported one, then use it. Exit in any case. */ if (!irq) { - printk(KERN_WARNING PREFIX "No IRQ known for interrupt pin %c of device %s", ('A' + pin), pci_name(dev)); + printk(KERN_WARNING PREFIX "PCI interrupt %s[%c]: no GSI", + pci_name(dev), ('A' + pin)); /* Interrupt Line values above 0xF are forbidden */ if (dev->irq && (dev->irq <= 0xF)) { printk(" - using IRQ %d\n", dev->irq); @@ -378,62 +379,14 @@ } } - dev->irq = irq; + dev->irq = acpi_register_gsi(irq, edge_level, active_high_low); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device %s using IRQ %d\n", pci_name(dev), dev->irq)); - - /* - * Make sure all (legacy) PCI IRQs are set as level-triggered. - */ -#ifdef CONFIG_X86 - { - static u16 irq_mask; - if ((dev->irq < 16) && !((1 << dev->irq) & irq_mask)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Setting IRQ %d as level-triggered\n", dev->irq)); - irq_mask |= (1 << dev->irq); - eisa_set_level_irq(dev->irq); - } - } -#endif -#ifdef CONFIG_IOSAPIC - if (acpi_irq_model == ACPI_IRQ_MODEL_IOSAPIC) - iosapic_enable_intr(dev->irq); -#endif + printk(KERN_INFO PREFIX "PCI interrupt %s[%c] -> GSI %u " + "(%s, %s) -> IRQ %d\n", + pci_name(dev), 'A' + pin, irq, + (edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", + (active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high", + dev->irq); return_VALUE(dev->irq); } - - -int __init -acpi_pci_irq_init (void) -{ - struct pci_dev *dev = NULL; - - ACPI_FUNCTION_TRACE("acpi_pci_irq_init"); - - if (!acpi_prt.count) { - printk(KERN_WARNING PREFIX "ACPI tables contain no PCI IRQ " - "routing entries\n"); - return_VALUE(-ENODEV); - } - - /* Make sure all link devices have a valid IRQ. */ - if (acpi_pci_link_check()) { - return_VALUE(-ENODEV); - } - -#ifdef CONFIG_X86_IO_APIC - /* Program IOAPICs using data from PRT entries. */ - if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) - mp_parse_prt(); -#endif -#ifdef CONFIG_IOSAPIC - if (acpi_irq_model == ACPI_IRQ_MODEL_IOSAPIC) - iosapic_parse_prt(); -#endif - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) - acpi_pci_irq_enable(dev); - - return_VALUE(0); -} --- diff/drivers/acpi/pci_link.c 2004-05-27 13:41:16.000000000 +0100 +++ source/drivers/acpi/pci_link.c 2004-05-27 18:34:15.000000000 +0100 @@ -487,13 +487,13 @@ }; int -acpi_pci_link_check (void) +acpi_irq_penalty_init(void) { struct list_head *node = NULL; struct acpi_pci_link *link = NULL; int i = 0; - ACPI_FUNCTION_TRACE("acpi_pci_link_check"); + ACPI_FUNCTION_TRACE("acpi_irq_penalty_init"); /* * Update penalties to facilitate IRQ balancing. --- diff/drivers/acpi/tables.c 2004-05-27 13:41:16.000000000 +0100 +++ source/drivers/acpi/tables.c 2004-05-27 18:34:15.000000000 +0100 @@ -131,7 +131,7 @@ { struct acpi_table_ioapic *p = (struct acpi_table_ioapic*) header; - printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] global_irq_base[0x%x])\n", + printk(KERN_INFO PREFIX "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n", p->id, p->address, p->global_irq_base); } break; @@ -185,8 +185,8 @@ { struct acpi_table_iosapic *p = (struct acpi_table_iosapic*) header; - printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] global_irq_base[0x%x] address[%p])\n", - p->id, p->global_irq_base, (void *) (unsigned long) p->address); + printk(KERN_INFO PREFIX "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n", + p->id, (void *) (unsigned long) p->address, p->global_irq_base); } break; --- diff/drivers/atm/firestream.c 2004-05-19 22:11:30.000000000 +0100 +++ source/drivers/atm/firestream.c 2004-05-27 18:34:15.000000000 +0100 @@ -576,7 +576,7 @@ } -static inline u32 read_fs (struct fs_dev *dev, int offset) +static inline u32 read_fs (struct fs_dev *dev, int offset) { return readl (dev->base + offset); } @@ -1380,7 +1380,7 @@ if (alignment <= 0x10) { t = kmalloc (size, flags); - if ((unsigned int)t & (alignment-1)) { + if ((unsigned long)t & (alignment-1)) { printk ("Kmalloc doesn't align things correctly! %p\n", t); kfree (t); return aligned_kmalloc (size, flags, alignment * 4); @@ -1496,7 +1496,7 @@ ne->skb = skb; ne->fp = fp; - qe = (struct FS_BPENTRY *) (read_fs (dev, FP_EA(fp->offset))); + qe = (struct FS_BPENTRY *)(long)(read_fs (dev, FP_EA(fp->offset))); fs_dprintk (FS_DEBUG_QUEUE, "link at %p\n", qe); if (qe) { qe = bus_to_virt ((long) qe); --- diff/drivers/base/power/resume.c 2004-05-19 22:11:32.000000000 +0100 +++ source/drivers/base/power/resume.c 2004-05-27 18:34:15.000000000 +0100 @@ -35,7 +35,10 @@ struct list_head * entry = dpm_off.next; struct device * dev = to_device(entry); list_del_init(entry); - resume_device(dev); + + if (!dev->power.power_state) + resume_device(dev); + list_add_tail(entry,&dpm_active); } } --- diff/drivers/base/power/runtime.c 2004-05-19 22:11:32.000000000 +0100 +++ source/drivers/base/power/runtime.c 2004-05-27 18:34:15.000000000 +0100 @@ -14,7 +14,10 @@ { if (!dev->power.power_state) return; - resume_device(dev); + if (! resume_device(dev)) + dev->power.power_state = 0; + + return; } --- diff/drivers/base/power/suspend.c 2004-05-19 22:11:32.000000000 +0100 +++ source/drivers/base/power/suspend.c 2004-05-27 18:34:15.000000000 +0100 @@ -39,16 +39,9 @@ { int error = 0; - if (dev->bus && dev->bus->suspend) + if (dev->bus && dev->bus->suspend && !dev->power.power_state) error = dev->bus->suspend(dev,state); - if (!error) { - list_del(&dev->power.entry); - list_add(&dev->power.entry,&dpm_off); - } else if (error == -EAGAIN) { - list_del(&dev->power.entry); - list_add(&dev->power.entry,&dpm_off_irq); - } return error; } @@ -81,12 +74,16 @@ while(!list_empty(&dpm_active)) { struct list_head * entry = dpm_active.prev; struct device * dev = to_device(entry); - if ((error = suspend_device(dev,state))) { - if (error != -EAGAIN) - goto Error; - else - error = 0; - } + error = suspend_device(dev,state); + + if (!error) { + list_del(&dev->power.entry); + list_add(&dev->power.entry,&dpm_off); + } else if (error == -EAGAIN) { + list_del(&dev->power.entry); + list_add(&dev->power.entry,&dpm_off_irq); + } else + goto Error; } Done: up(&dpm_sem); --- diff/drivers/block/Kconfig 2004-05-27 13:41:16.000000000 +0100 +++ source/drivers/block/Kconfig 2004-05-27 18:34:15.000000000 +0100 @@ -6,7 +6,7 @@ config BLK_DEV_FD tristate "Normal floppy disk support" - depends on (!X86_PC9800 && !ARCH_S390 && !M68K && !IA64) || Q40 || (SUN3X && BROKEN) + depends on (!ARCH_S390 && !M68K && !IA64) || Q40 || (SUN3X && BROKEN) ---help--- If you want to use the floppy disk drive(s) of your PC under Linux, say Y. Information about this driver, especially important for IBM @@ -26,13 +26,6 @@ tristate "Atari floppy support" depends on ATARI -config BLK_DEV_FD98 - tristate "NEC PC-9800 floppy disk support" - depends on X86_PC9800 - ---help--- - If you want to use the floppy disk drive(s) of NEC PC-9801/PC-9821, - say Y. - config BLK_DEV_SWIM_IOP bool "Macintosh IIfx/Quadra 900/Quadra 950 floppy support (EXPERIMENTAL)" depends on MAC && EXPERIMENTAL && BROKEN --- diff/drivers/block/ll_rw_blk.c 2004-05-27 13:41:16.000000000 +0100 +++ source/drivers/block/ll_rw_blk.c 2004-05-27 18:34:15.000000000 +0100 @@ -106,22 +106,28 @@ q->nr_congestion_off = nr; } -/* - * A queue has just exitted congestion. Note this in the global counter of - * congested queues, and wake up anyone who was waiting for requests to be - * put back. - */ -static void clear_queue_congested(request_queue_t *q, int rw) +void clear_backing_dev_congested(struct backing_dev_info *bdi, int rw) { enum bdi_state bit; wait_queue_head_t *wqh = &congestion_wqh[rw]; bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested; - clear_bit(bit, &q->backing_dev_info.state); + clear_bit(bit, &bdi->state); smp_mb__after_clear_bit(); if (waitqueue_active(wqh)) wake_up(wqh); } +EXPORT_SYMBOL(clear_backing_dev_congested); + +/* + * A queue has just exitted congestion. Note this in the global counter of + * congested queues, and wake up anyone who was waiting for requests to be + * put back. + */ +static void clear_queue_congested(request_queue_t *q, int rw) +{ + clear_backing_dev_congested(&q->backing_dev_info, rw); +} /* * A queue has just entered congestion. Flag that in the queue's VM-visible @@ -263,6 +269,45 @@ EXPORT_SYMBOL(blk_queue_make_request); /** + * blk_queue_ordered - does this queue support ordered writes + * @q: the request queue + * @flag: see below + * + * Description: + * For journalled file systems, doing ordered writes on a commit + * block instead of explicitly doing wait_on_buffer (which is bad + * for performance) can be a big win. Block drivers supporting this + * feature should call this function and indicate so. + * + **/ +void blk_queue_ordered(request_queue_t *q, int flag) +{ + if (flag) + set_bit(QUEUE_FLAG_ORDERED, &q->queue_flags); + else + clear_bit(QUEUE_FLAG_ORDERED, &q->queue_flags); +} + +EXPORT_SYMBOL(blk_queue_ordered); + +/** + * blk_queue_issue_flush_fn - set function for issuing a flush + * @q: the request queue + * @iff: the function to be called issuing the flush + * + * Description: + * If a driver supports issuing a flush command, the support is notified + * to the block layer by defining it through this call. + * + **/ +void blk_queue_issue_flush_fn(request_queue_t *q, issue_flush_fn *iff) +{ + q->issue_flush_fn = iff; +} + +EXPORT_SYMBOL(blk_queue_issue_flush_fn); + +/** * blk_queue_bounce_limit - set bounce buffer limit for queue * @q: the request queue for the device * @dma_addr: bus address limit @@ -1151,6 +1196,7 @@ **/ void generic_unplug_device(request_queue_t *q) { + might_sleep(); spin_lock_irq(q->queue_lock); __generic_unplug_device(q); spin_unlock_irq(q->queue_lock); @@ -1872,10 +1918,11 @@ } rq->flags |= REQ_NOMERGE; - rq->waiting = &wait; + if (!rq->waiting) + rq->waiting = &wait; elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); generic_unplug_device(q); - wait_for_completion(&wait); + wait_for_completion(rq->waiting); rq->waiting = NULL; if (rq->errors) @@ -1886,6 +1933,72 @@ EXPORT_SYMBOL(blk_execute_rq); +/** + * blkdev_issue_flush - queue a flush + * @bdev: blockdev to issue flush for + * @error_sector: error sector + * + * Description: + * Issue a flush for the block device in question. Caller can supply + * room for storing the error offset in case of a flush error, if they + * wish to. Caller must run wait_for_completion() on its own. + */ +int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector) +{ + request_queue_t *q; + + if (bdev->bd_disk == NULL) + return -ENXIO; + + q = bdev_get_queue(bdev); + if (!q) + return -ENXIO; + if (!q->issue_flush_fn) + return -EOPNOTSUPP; + + return q->issue_flush_fn(q, bdev->bd_disk, error_sector); +} + +EXPORT_SYMBOL(blkdev_issue_flush); + +/** + * blkdev_scsi_issue_flush_fn - issue flush for SCSI devices + * @q: device queue + * @disk: gendisk + * @error_sector: error offset + * + * Description: + * Devices understanding the SCSI command set, can use this function as + * a helper for issuing a cache flush. Note: driver is required to store + * the error offset (in case of error flushing) in ->sector of struct + * request. + */ +int blkdev_scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + struct request *rq = blk_get_request(q, WRITE, __GFP_WAIT); + int ret; + + rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER; + rq->sector = 0; + memset(rq->cmd, 0, sizeof(rq->cmd)); + rq->cmd[0] = 0x35; + rq->cmd_len = 12; + rq->data = NULL; + rq->data_len = 0; + rq->timeout = 60 * HZ; + + ret = blk_execute_rq(q, disk, rq); + + if (ret && error_sector) + *error_sector = rq->sector; + + blk_put_request(rq); + return ret; +} + +EXPORT_SYMBOL(blkdev_scsi_issue_flush_fn); + void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) { int rw = rq_data_dir(rq); @@ -2139,7 +2252,7 @@ static int __make_request(request_queue_t *q, struct bio *bio) { struct request *req, *freereq = NULL; - int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, ra; + int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err; sector_t sector; sector = bio->bi_sector; @@ -2157,9 +2270,11 @@ spin_lock_prefetch(q->queue_lock); - barrier = test_bit(BIO_RW_BARRIER, &bio->bi_rw); - - ra = bio->bi_rw & (1 << BIO_RW_AHEAD); + barrier = bio_barrier(bio); + if (barrier && !(q->queue_flags & (1 << QUEUE_FLAG_ORDERED))) { + err = -EOPNOTSUPP; + goto end_io; + } again: spin_lock_irq(q->queue_lock); @@ -2239,7 +2354,8 @@ /* * READA bit set */ - if (ra) + err = -EWOULDBLOCK; + if (bio_rw_ahead(bio)) goto end_io; freereq = get_request_wait(q, rw); @@ -2250,10 +2366,9 @@ req->flags |= REQ_CMD; /* - * inherit FAILFAST from bio and don't stack up - * retries for read ahead + * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST) */ - if (ra || test_bit(BIO_RW_FAILFAST, &bio->bi_rw)) + if (bio_rw_ahead(bio) || bio_failfast(bio)) req->flags |= REQ_FAILFAST; /* @@ -2291,7 +2406,7 @@ return 0; end_io: - bio_endio(bio, nr_sectors << 9, -EWOULDBLOCK); + bio_endio(bio, nr_sectors << 9, err); return 0; } @@ -2591,10 +2706,17 @@ static int __end_that_request_first(struct request *req, int uptodate, int nr_bytes) { - int total_bytes, bio_nbytes, error = 0, next_idx = 0; + int total_bytes, bio_nbytes, error, next_idx = 0; struct bio *bio; /* + * extend uptodate bool to allow < 0 value to be direct io error + */ + error = 0; + if (end_io_error(uptodate)) + error = !uptodate ? -EIO : uptodate; + + /* * for a REQ_BLOCK_PC request, we want to carry any eventual * sense key with us all the way through */ @@ -2602,7 +2724,6 @@ req->errors = 0; if (!uptodate) { - error = -EIO; if (blk_fs_request(req) && !(req->flags & REQ_QUIET)) printk("end_request: I/O error, dev %s, sector %llu\n", req->rq_disk ? req->rq_disk->disk_name : "?", @@ -2685,7 +2806,7 @@ /** * end_that_request_first - end I/O on a request * @req: the request being processed - * @uptodate: 0 for I/O error + * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error * @nr_sectors: number of sectors to end I/O on * * Description: @@ -2706,7 +2827,7 @@ /** * end_that_request_chunk - end I/O on a request * @req: the request being processed - * @uptodate: 0 for I/O error + * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error * @nr_bytes: number of bytes to complete * * Description: @@ -2824,19 +2945,13 @@ panic("Failed to create kblockd\n"); request_cachep = kmem_cache_create("blkdev_requests", - sizeof(struct request), 0, 0, NULL, NULL); - if (!request_cachep) - panic("Can't create request pool slab cache\n"); + sizeof(struct request), 0, SLAB_PANIC, NULL, NULL); requestq_cachep = kmem_cache_create("blkdev_queue", - sizeof(request_queue_t), 0, 0, NULL, NULL); - if (!requestq_cachep) - panic("Can't create request queue slab cache\n"); + sizeof(request_queue_t), 0, SLAB_PANIC, NULL, NULL); iocontext_cachep = kmem_cache_create("blkdev_ioc", - sizeof(struct io_context), 0, 0, NULL, NULL); - if (!iocontext_cachep) - panic("Can't create io context slab cache\n"); + sizeof(struct io_context), 0, SLAB_PANIC, NULL, NULL); blk_max_low_pfn = max_low_pfn; blk_max_pfn = max_pfn; --- diff/drivers/block/rd.c 2004-05-27 13:41:17.000000000 +0100 +++ source/drivers/block/rd.c 2004-05-27 18:34:15.000000000 +0100 @@ -108,8 +108,21 @@ struct buffer_head *head = bh; do { - if (!buffer_uptodate(bh)) + if (!buffer_uptodate(bh)) { memset(bh->b_data, 0, bh->b_size); + /* + * akpm: I'm totally undecided about this. The + * buffer has just been magically brought "up to + * date", but nobody should want to be reading + * it anyway, because it hasn't been used for + * anything yet. It is still in a "not read + * from disk yet" state. + * + * But non-uptodate buffers against an uptodate + * page are against the rules. So do it anyway. + */ + set_buffer_uptodate(bh); + } } while ((bh = bh->b_this_page) != head); } else { memset(page_address(page), 0, PAGE_CACHE_SIZE); --- diff/drivers/block/viodasd.c 2004-05-27 13:41:17.000000000 +0100 +++ source/drivers/block/viodasd.c 2004-05-27 18:34:15.000000000 +0100 @@ -40,8 +40,11 @@ #include #include #include +#include +#include #include +#include #include #include #include @@ -519,13 +522,6 @@ "bad rc sending event to OS/400 %d\n", (int)hvrc); return; } - printk(VIOD_KERN_INFO "disk %d: %lu sectors (%lu MB) " - "CHS=%d/%d/%d sector size %d%s\n", - dev_no, (unsigned long)(d->size >> 9), - (unsigned long)(d->size >> 20), - (int)d->cylinders, (int)d->tracks, - (int)d->sectors, (int)d->bytes_per_sector, - d->read_only ? " (RO)" : ""); /* create the request queue for the disk */ spin_lock_init(&d->q_lock); q = blk_init_queue(do_viodasd_request, &d->q_lock); @@ -563,6 +559,14 @@ g->private_data = d; set_capacity(g, d->size >> 9); + printk(VIOD_KERN_INFO "disk %d: %lu sectors (%lu MB) " + "CHS=%d/%d/%d sector size %d%s\n", + dev_no, (unsigned long)(d->size >> 9), + (unsigned long)(d->size >> 20), + (int)d->cylinders, (int)d->tracks, + (int)d->sectors, (int)d->bytes_per_sector, + d->read_only ? " (RO)" : ""); + /* register us in the global list */ add_disk(g); } @@ -725,6 +729,26 @@ } /* + * Get the driver to reprobe for more disks. + */ +static ssize_t probe_disks(struct device_driver *drv, const char *buf, + size_t count) +{ + struct viodasd_device *d; + + for (d = viodasd_devices; d < &viodasd_devices[MAX_DISKNO]; d++) { + if (d->disk == NULL) + probe_disk(d); + } + return count; +} +static DRIVER_ATTR(probe, S_IWUSR, NULL, probe_disks) + +static struct vio_driver viodasd_driver = { + .name = "viodasd" +}; + +/* * Initialize the whole device driver. Handle module and non-module * versions */ @@ -767,6 +791,9 @@ for (i = 0; i < MAX_DISKNO; i++) probe_disk(&viodasd_devices[i]); + vio_register_driver(&viodasd_driver); /* FIX ME - error checking */ + driver_create_file(&viodasd_driver.driver, &driver_attr_probe); + return 0; } module_init(viodasd_init); @@ -776,6 +803,9 @@ int i; struct viodasd_device *d; + driver_remove_file(&viodasd_driver.driver, &driver_attr_probe); + vio_unregister_driver(&viodasd_driver); + for (i = 0; i < MAX_DISKNO; i++) { d = &viodasd_devices[i]; if (d->disk) { --- diff/drivers/bluetooth/bt3c_cs.c 2004-05-19 22:11:33.000000000 +0100 +++ source/drivers/bluetooth/bt3c_cs.c 2004-05-27 18:34:15.000000000 +0100 @@ -491,6 +491,9 @@ static struct device bt3c_device = { .bus_id = "pcmcia", + .kobj = { + .k_name = "bt3c" + } }; --- diff/drivers/bluetooth/hci_bcsp.c 2004-05-19 22:11:33.000000000 +0100 +++ source/drivers/bluetooth/hci_bcsp.c 2004-05-27 18:34:15.000000000 +0100 @@ -33,7 +33,6 @@ #include #include -#include #include #include #include --- diff/drivers/char/Kconfig 2004-05-27 13:41:17.000000000 +0100 +++ source/drivers/char/Kconfig 2004-05-27 18:34:16.000000000 +0100 @@ -586,17 +586,6 @@ console. This driver allows each pSeries partition to have a console which is accessed via the HMC. -config PC9800_OLDLP - tristate "NEC PC-9800 old-style printer port support" - depends on X86_PC9800 && !PARPORT - ---help--- - If you intend to attach a printer to the parallel port of NEC PC-9801 - /PC-9821 with OLD compatibility mode, Say Y. - -config PC9800_OLDLP_CONSOLE - bool "Support for console on line printer" - depends on PC9800_OLDLP - config QIC02_TAPE tristate "QIC-02 tape support" help @@ -740,7 +729,7 @@ config RTC tristate "Enhanced Real Time Clock Support" - depends on !PPC32 && !PARISC && !IA64 && !X86_PC9800 && !M68K + depends on !PPC32 && !PARISC && !IA64 && !M68K ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you @@ -793,15 +782,6 @@ bool "EFI Real Time Clock Services" depends on IA64 -config RTC98 - tristate "NEC PC-9800 Real Time Clock Support" - depends on X86_PC9800 - default y - ---help--- - If you say Y here and create a character special file /dev/rtc with - major number 10 and minor number 135 using mknod ("man mknod"), you - will get access to the real time clock (or hardware clock) built - config H8 bool "Tadpole ANA H8 Support (OBSOLETE)" depends on OBSOLETE && ALPHA_BOOK1 @@ -957,6 +937,33 @@ kernels. Applications should simply open the device (eg /dev/hda1) with the O_DIRECT flag. +config HPET + bool "HPET - High Precision Event Timer" if (X86 || IA64) + default n + depends on ACPI + help + If you say Y here, you will have a device named "/dev/hpet/XX" for + each timer supported by the HPET. The timers are + non-periodioc and/or periodic. + +config HPET_RTC_IRQ + bool "HPET Control RTC IRQ" if !HPET_EMULATE_RTC + default n + depends on HPET + help + If you say Y here, you will disable RTC_IRQ in drivers/char/rtc.c. It + is assumed the platform called hpet_alloc with the RTC IRQ values for + the HPET timers. + +config HPET_NOMMAP + bool "HPET - Control mmap capability." + default n + depends on HPET + help + If you say Y here, then the mmap interface for the HPET driver returns ENOSYS. + Some hardware implementations might not want all the memory in the page the + HPET control registers reside to be exposed. + config MAX_RAW_DEVS int "Maximum number of RAW devices to support (1-8192)" depends on RAW_DRIVER --- diff/drivers/char/Makefile 2004-05-27 13:41:17.000000000 +0100 +++ source/drivers/char/Makefile 2004-05-27 18:34:16.000000000 +0100 @@ -47,13 +47,13 @@ obj-$(CONFIG_PRINTER) += lp.o obj-$(CONFIG_TIPAR) += tipar.o -obj-$(CONFIG_PC9800_OLDLP) += lp_old98.o obj-$(CONFIG_DTLK) += dtlk.o obj-$(CONFIG_R3964) += n_r3964.o obj-$(CONFIG_APPLICOM) += applicom.o obj-$(CONFIG_SONYPI) += sonypi.o obj-$(CONFIG_RTC) += rtc.o +obj-$(CONFIG_HPET) += hpet.o obj-$(CONFIG_GEN_RTC) += genrtc.o obj-$(CONFIG_EFI_RTC) += efirtc.o ifeq ($(CONFIG_GENERIC_NVRAM),y) --- diff/drivers/char/agp/amd-k7-agp.c 2004-05-19 22:11:35.000000000 +0100 +++ source/drivers/char/agp/amd-k7-agp.c 2004-05-27 18:34:16.000000000 +0100 @@ -20,6 +20,8 @@ #define AMD_TLBFLUSH 0x0c /* In mmio region (32-bit register) */ #define AMD_CACHEENTRY 0x10 /* In mmio region (32-bit register) */ +static struct pci_device_id agp_amdk7_pci_table[]; + struct amd_page_map { unsigned long *real; unsigned long *remapped; @@ -41,7 +43,7 @@ SetPageReserved(virt_to_page(page_map->real)); global_cache_flush(); - page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), + page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), PAGE_SIZE); if (page_map->remapped == NULL) { ClearPageReserved(virt_to_page(page_map->real)); @@ -90,7 +92,7 @@ int retval = 0; int i; - tables = kmalloc((nr_tables + 1) * sizeof(struct amd_page_map *), + tables = kmalloc((nr_tables + 1) * sizeof(struct amd_page_map *), GFP_KERNEL); if (tables == NULL) return -ENOMEM; @@ -124,7 +126,7 @@ #define GET_PAGE_DIR_OFF(addr) (addr >> 22) #define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \ GET_PAGE_DIR_OFF(agp_bridge->gart_bus_addr)) -#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) +#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) #define GET_GATT(addr) (amd_irongate_private.gatt_pages[\ GET_PAGE_DIR_IDX(addr)]->remapped) @@ -174,7 +176,7 @@ static int amd_free_gatt_table(void) { struct amd_page_map page_dir; - + page_dir.real = (unsigned long *)agp_bridge->gatt_table_real; page_dir.remapped = (unsigned long *)agp_bridge->gatt_table; @@ -224,9 +226,9 @@ /* Write the Sync register */ pci_write_config_byte(agp_bridge->dev, AMD_MODECNTL, 0x80); - - /* Set indexing mode */ - pci_write_config_byte(agp_bridge->dev, AMD_MODECNTL2, 0x00); + + /* Set indexing mode */ + pci_write_config_byte(agp_bridge->dev, AMD_MODECNTL2, 0x00); /* Write the enable register */ enable_reg = INREG16(amd_irongate_private.registers, AMD_GARTENABLE); @@ -394,7 +396,6 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct agp_device_ids *devs = amd_agp_device_ids; struct agp_bridge_data *bridge; u8 cap_ptr; int j; @@ -403,19 +404,10 @@ if (!cap_ptr) return -ENODEV; - for (j = 0; devs[j].chipset_name; j++) { - if (pdev->device == devs[j].device_id) { - printk (KERN_INFO PFX "Detected AMD %s chipset\n", - devs[j].chipset_name); - goto found; - } - } - - printk(KERN_ERR PFX "Unsupported AMD chipset (device id: %04x)\n", - pdev->device); - return -ENODEV; + j = ent - agp_amdk7_pci_table; + printk(KERN_INFO PFX "Detected AMD %s chipset\n", + amd_agp_device_ids[j].chipset_name); -found: bridge = agp_alloc_bridge(); if (!bridge) return -ENOMEM; @@ -442,12 +434,29 @@ agp_put_bridge(bridge); } +/* must be the same order as name table above */ static struct pci_device_id agp_amdk7_pci_table[] = { { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_ANY_ID, + .device = PCI_DEVICE_ID_AMD_FE_GATE_7006, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_FE_GATE_700E, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_FE_GATE_700C, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, --- diff/drivers/char/agp/amd64-agp.c 2004-05-19 22:11:35.000000000 +0100 +++ source/drivers/char/agp/amd64-agp.c 2004-05-27 18:34:16.000000000 +0100 @@ -1,7 +1,7 @@ -/* +/* * Copyright 2001-2003 SuSE Labs. * Distributed under the GNU public license, v2. - * + * * This is a GART driver for the AMD Opteron/Athlon64 on-CPU northbridge. * It also includes support for the AMD 8151 AGP bridge, * although it doesn't actually do much, as all the real @@ -194,7 +194,7 @@ /* keep CPU's coherent. */ flush_amd64_tlb (hammer); - + return aper_base; } @@ -261,53 +261,53 @@ /* Some basic sanity checks for the aperture. */ static int __devinit aperture_valid(u64 aper, u32 size) -{ +{ u32 pfn, c; - if (aper == 0) { + if (aper == 0) { printk(KERN_ERR PFX "No aperture\n"); - return 0; + return 0; } if (size < 32*1024*1024) { printk(KERN_ERR PFX "Aperture too small (%d MB)\n", size>>20); return 0; } - if (aper + size > 0xffffffff) { - printk(KERN_ERR PFX "Aperture out of bounds\n"); + if (aper + size > 0xffffffff) { + printk(KERN_ERR PFX "Aperture out of bounds\n"); return 0; - } + } pfn = aper >> PAGE_SHIFT; - for (c = 0; c < size/PAGE_SIZE; c++) { + for (c = 0; c < size/PAGE_SIZE; c++) { if (!pfn_valid(pfn + c)) break; - if (!PageReserved(pfn_to_page(pfn + c))) { + if (!PageReserved(pfn_to_page(pfn + c))) { printk(KERN_ERR PFX "Aperture pointing to RAM\n"); return 0; } } /* Request the Aperture. This catches cases when someone else - already put a mapping in there - happens with some very broken BIOS + already put a mapping in there - happens with some very broken BIOS - Maybe better to use pci_assign_resource/pci_enable_device instead trusting - the bridges? */ + Maybe better to use pci_assign_resource/pci_enable_device instead + trusting the bridges? */ if (!aperture_resource && !(aperture_resource = request_mem_region(aper, size, "aperture"))) { - printk(KERN_ERR PFX "Aperture conflicts with PCI mapping.\n"); + printk(KERN_ERR PFX "Aperture conflicts with PCI mapping.\n"); return 0; } return 1; -} +} -/* +/* * W*s centric BIOS sometimes only set up the aperture in the AGP - * bridge, not the northbridge. On AMD64 this is handled early + * bridge, not the northbridge. On AMD64 this is handled early * in aperture.c, but when GART_IOMMU is not enabled or we run - * on a 32bit kernel this needs to be redone. + * on a 32bit kernel this needs to be redone. * Unfortunately it is impossible to fix the aperture here because it's too late * to allocate that much memory. But at least error out cleanly instead of * crashing. - */ -static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, + */ +static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, u16 cap) { u32 aper_low, aper_hi; @@ -316,38 +316,38 @@ u32 nb_order, nb_base; u16 apsize; - pci_read_config_dword(nb, 0x90, &nb_order); + pci_read_config_dword(nb, 0x90, &nb_order); nb_order = (nb_order >> 1) & 7; - pci_read_config_dword(nb, 0x94, &nb_base); - nb_aper = nb_base << 25; - if (aperture_valid(nb_aper, (32*1024*1024)<> 25); + return -1; + + pci_write_config_dword(nb, 0x90, order << 1); + pci_write_config_dword(nb, 0x94, aper >> 25); return 0; -} +} static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) { @@ -355,19 +355,19 @@ int i = 0; /* cache pci_devs of northbridges. */ - while ((loop_dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev)) + while ((loop_dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev)) != NULL) { - if (i == MAX_HAMMER_GARTS) { + if (i == MAX_HAMMER_GARTS) { printk(KERN_ERR PFX "Too many northbridges for AGP\n"); return -1; } - if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) { + if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) { printk(KERN_ERR PFX "No usable aperture found.\n"); -#ifdef __x86_64__ +#ifdef __x86_64__ /* should port this to i386 */ printk(KERN_ERR PFX "Consider rebooting with iommu=memaper=2 to get a good aperture.\n"); -#endif - return -1; +#endif + return -1; } hammers[i++] = loop_dev; } @@ -377,8 +377,7 @@ /* Handle AMD 8151 quirks */ static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge) - -{ +{ char *revstring; u8 rev_id; @@ -417,12 +416,12 @@ /* Handle shadow device of the Nvidia NForce3 */ /* CHECK-ME original 2.4 version set up some IORRs. Check if that is needed. */ -static int __devinit nforce3_agp_init(struct pci_dev *pdev) -{ +static int __devinit nforce3_agp_init(struct pci_dev *pdev) +{ u32 tmp, apbase, apbar, aplimit; - struct pci_dev *dev1; + struct pci_dev *dev1; int i; - unsigned size = amd64_fetch_size(); + unsigned size = amd64_fetch_size(); printk(KERN_INFO PFX "Setting up Nforce3 AGP.\n"); @@ -432,17 +431,17 @@ "nForce3 chipset, but could not find " "the secondary device.\n"); return -ENODEV; - } + } - for (i = 0; i < ARRAY_SIZE(nforce3_sizes); i++) + for (i = 0; i < ARRAY_SIZE(nforce3_sizes); i++) if (nforce3_sizes[i].size == size) - break; + break; if (i == ARRAY_SIZE(nforce3_sizes)) { - printk(KERN_INFO PFX "No NForce3 size found for %d\n", size); - return -ENODEV; + printk(KERN_INFO PFX "No NForce3 size found for %d\n", size); + return -ENODEV; } - + pci_read_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, &tmp); tmp &= ~(0xf); tmp |= nforce3_sizes[i].size_value; @@ -491,8 +490,7 @@ pdev->device == PCI_DEVICE_ID_AMD_8151_0) { amd8151_init(pdev, bridge); } else { - printk(KERN_INFO PFX "Detected AGP bridge %x\n", - pdev->devfn); + printk(KERN_INFO PFX "Detected AGP bridge %x\n", pdev->devfn); } bridge->driver = &amd_8151_driver; @@ -507,10 +505,10 @@ return -ENODEV; } - if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) { + if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) { int ret = nforce3_agp_init(pdev); - if (ret) { - agp_put_bridge(bridge); + if (ret) { + agp_put_bridge(bridge); return ret; } } @@ -523,8 +521,8 @@ { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); - release_mem_region(virt_to_phys(bridge->gatt_table_real), - amd64_aperture_sizes[bridge->aperture_size_idx].size); + release_mem_region(virt_to_phys(bridge->gatt_table_real), + amd64_aperture_sizes[bridge->aperture_size_idx].size); agp_remove_bridge(bridge); agp_put_bridge(bridge); } @@ -581,6 +579,15 @@ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, + /* SIS 755 */ + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_SI, + .device = PCI_DEVICE_ID_SI_755, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, { } }; @@ -600,15 +607,15 @@ int err = 0; if (agp_off) return -EINVAL; - if (pci_module_init(&agp_amd64_pci_driver) > 0) { + if (pci_module_init(&agp_amd64_pci_driver) > 0) { struct pci_dev *dev; - if (!agp_try_unsupported && !agp_try_unsupported_boot) { + if (!agp_try_unsupported && !agp_try_unsupported_boot) { printk(KERN_INFO PFX "No supported AGP bridge found.\n"); -#ifdef MODULE +#ifdef MODULE printk(KERN_INFO PFX "You can try agp_try_unsupported=1\n"); #else printk(KERN_INFO PFX "You can boot with agp=try_unsupported\n"); -#endif +#endif return -ENODEV; } @@ -622,12 +629,12 @@ while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev))) { if (!pci_find_capability(dev, PCI_CAP_ID_AGP)) continue; - /* Only one bridge supported right now */ + /* Only one bridge supported right now */ if (agp_amd64_probe(dev, NULL) == 0) { err = 0; break; - } - } + } + } } return err; } --- diff/drivers/char/agp/ati-agp.c 2004-05-19 22:11:35.000000000 +0100 +++ source/drivers/char/agp/ati-agp.c 2004-05-27 18:34:16.000000000 +0100 @@ -131,6 +131,7 @@ i--; } kfree (tables); + tables = NULL; retval = -ENOMEM; break; } --- diff/drivers/char/agp/intel-agp.c 2004-05-19 22:11:35.000000000 +0100 +++ source/drivers/char/agp/intel-agp.c 2004-05-27 18:34:16.000000000 +0100 @@ -1233,7 +1233,7 @@ name); return 0; } - + intel_i810_private.i810_dev = i810_dev; return 1; } @@ -1384,6 +1384,7 @@ default: printk(KERN_ERR PFX "Unsupported Intel chipset (device id: %04x)\n", pdev->device); + agp_put_bridge(bridge); return -ENODEV; }; @@ -1406,7 +1407,8 @@ if (!r->start && r->end) { if(pci_assign_resource(pdev, 0)) { printk(KERN_ERR PFX "could not assign resource 0\n"); - return (-ENODEV); + agp_put_bridge(bridge); + return -ENODEV; } } @@ -1417,7 +1419,8 @@ */ if (pci_enable_device(pdev)) { printk(KERN_ERR PFX "Unable to Enable PCI device\n"); - return (-ENODEV); + agp_put_bridge(bridge); + return -ENODEV; } /* Fill in the mode register */ @@ -1462,14 +1465,37 @@ } static struct pci_device_id agp_intel_pci_table[] = { - { - .class = (PCI_CLASS_BRIDGE_HOST << 8), - .class_mask = ~0, - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, +#define ID(x) \ + { \ + .class = (PCI_CLASS_BRIDGE_HOST << 8), \ + .class_mask = ~0, \ + .vendor = PCI_VENDOR_ID_INTEL, \ + .device = x, \ + .subvendor = PCI_ANY_ID, \ + .subdevice = PCI_ANY_ID, \ + } + ID(PCI_DEVICE_ID_INTEL_82443LX_0), + ID(PCI_DEVICE_ID_INTEL_82443BX_0), + ID(PCI_DEVICE_ID_INTEL_82443GX_0), + ID(PCI_DEVICE_ID_INTEL_82810_MC1), + ID(PCI_DEVICE_ID_INTEL_82810_MC3), + ID(PCI_DEVICE_ID_INTEL_82810E_MC), + ID(PCI_DEVICE_ID_INTEL_82815_MC), + ID(PCI_DEVICE_ID_INTEL_82820_HB), + ID(PCI_DEVICE_ID_INTEL_82820_UP_HB), + ID(PCI_DEVICE_ID_INTEL_82830_HB), + ID(PCI_DEVICE_ID_INTEL_82840_HB), + ID(PCI_DEVICE_ID_INTEL_82845_HB), + ID(PCI_DEVICE_ID_INTEL_82845G_HB), + ID(PCI_DEVICE_ID_INTEL_82850_HB), + ID(PCI_DEVICE_ID_INTEL_82855PM_HB), + ID(PCI_DEVICE_ID_INTEL_82855GM_HB), + ID(PCI_DEVICE_ID_INTEL_82860_HB), + ID(PCI_DEVICE_ID_INTEL_82865_HB), + ID(PCI_DEVICE_ID_INTEL_82875_HB), + ID(PCI_DEVICE_ID_INTEL_7505_0), + ID(PCI_DEVICE_ID_INTEL_7501_0), + ID(PCI_DEVICE_ID_INTEL_7205_0), { } }; --- diff/drivers/char/agp/intel-mch-agp.c 2004-05-19 22:11:35.000000000 +0100 +++ source/drivers/char/agp/intel-mch-agp.c 2004-05-27 18:34:16.000000000 +0100 @@ -491,10 +491,9 @@ char *name = "(unknown)"; u8 cap_ptr = 0; - if (!boot_cpu_has(X86_FEATURE_LM)) - return -ENODEV; - cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; bridge = agp_alloc_bridge(); if (!bridge) @@ -590,7 +589,15 @@ .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_ANY_ID, + .device = PCI_DEVICE_ID_INTEL_82865_HB, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82875_HB, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, --- diff/drivers/char/agp/nvidia-agp.c 2004-05-19 22:11:35.000000000 +0100 +++ source/drivers/char/agp/nvidia-agp.c 2004-05-27 18:34:16.000000000 +0100 @@ -380,7 +380,15 @@ .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_NVIDIA, - .device = PCI_ANY_ID, + .device = PCI_DEVICE_ID_NVIDIA_NFORCE, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NFORCE2, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, --- diff/drivers/char/agp/sis-agp.c 2004-05-19 22:11:35.000000000 +0100 +++ source/drivers/char/agp/sis-agp.c 2004-05-27 18:34:16.000000000 +0100 @@ -13,6 +13,8 @@ #define SIS_TLBCNTRL 0x97 #define SIS_TLBFLUSH 0x98 +static int __devinitdata agp_sis_force_delay = 0; +static int __devinitdata agp_sis_agp_spec = -1; static int sis_fetch_size(void) { @@ -67,7 +69,7 @@ (previous_size->size_value & ~(0x03))); } -static void sis_648_enable(u32 mode) +static void sis_delayed_enable(u32 mode) { struct pci_dev *device = NULL; u32 command; @@ -94,13 +96,12 @@ pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command); /* - * Weird: on 648(fx) and 746(fx) chipsets any rate change in the target + * Weird: on some sis chipsets any rate change in the target * command register triggers a 5ms screwup during which the master * cannot be configured */ - if (device->device == PCI_DEVICE_ID_SI_648 || - device->device == PCI_DEVICE_ID_SI_746) { - printk(KERN_INFO PFX "SiS chipset with AGP problems detected. Giving bridge time to recover.\n"); + if (device->device == agp_bridge->dev->device) { + printk(KERN_INFO PFX "SiS delay workaround: giving bridge time to recover.\n"); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout (1+(HZ*10)/1000); } @@ -223,28 +224,35 @@ }; +// chipsets that require the 'delay hack' +static int sis_broken_chipsets[] __devinitdata = { + PCI_DEVICE_ID_SI_648, + PCI_DEVICE_ID_SI_746, + 0 // terminator +}; + static void __devinit sis_get_driver(struct agp_bridge_data *bridge) { - if (bridge->dev->device == PCI_DEVICE_ID_SI_648) { - sis_driver.agp_enable=sis_648_enable; - if (agp_bridge->major_version == 3) { - sis_driver.aperture_sizes = agp3_generic_sizes; - sis_driver.size_type = U16_APER_SIZE; - sis_driver.num_aperture_sizes = AGP_GENERIC_SIZES_ENTRIES; - sis_driver.configure = agp3_generic_configure; - sis_driver.fetch_size = agp3_generic_fetch_size; - sis_driver.cleanup = agp3_generic_cleanup; - sis_driver.tlb_flush = agp3_generic_tlbflush; - } - } + int i; - if (bridge->dev->device == PCI_DEVICE_ID_SI_746) { - /* - * We don't know enough about the 746 to enable it properly. - * Though we do know that it needs the 'delay' hack to settle - * after changing modes. - */ - sis_driver.agp_enable=sis_648_enable; + for(i=0; sis_broken_chipsets[i]!=0; ++i) + if(bridge->dev->device==sis_broken_chipsets[i]) + break; + + if(sis_broken_chipsets[i] || agp_sis_force_delay) + sis_driver.agp_enable=sis_delayed_enable; + + // sis chipsets that indicate less than agp3.5 + // are not actually fully agp3 compliant + if ((agp_bridge->major_version == 3 && agp_bridge->minor_version >= 5 + && agp_sis_agp_spec!=0) || agp_sis_agp_spec==1) { + sis_driver.aperture_sizes = agp3_generic_sizes; + sis_driver.size_type = U16_APER_SIZE; + sis_driver.num_aperture_sizes = AGP_GENERIC_SIZES_ENTRIES; + sis_driver.configure = agp3_generic_configure; + sis_driver.fetch_size = agp3_generic_fetch_size; + sis_driver.cleanup = agp3_generic_cleanup; + sis_driver.tlb_flush = agp3_generic_tlbflush; } } @@ -335,4 +343,8 @@ module_init(agp_sis_init); module_exit(agp_sis_cleanup); +MODULE_PARM(agp_sis_force_delay,"i"); +MODULE_PARM_DESC(agp_sis_force_delay,"forces sis delay hack"); +MODULE_PARM(agp_sis_agp_spec,"i"); +MODULE_PARM_DESC(agp_sis_agp_spec,"0=force sis init, 1=force generic agp3 init, default: autodetect"); MODULE_LICENSE("GPL and additional rights"); --- diff/drivers/char/agp/via-agp.c 2004-05-19 22:11:35.000000000 +0100 +++ source/drivers/char/agp/via-agp.c 2004-05-27 18:34:16.000000000 +0100 @@ -9,6 +9,8 @@ #include #include "agp.h" +static struct pci_device_id agp_via_pci_table[]; + #define VIA_GARTCTRL 0x80 #define VIA_APSIZE 0x84 #define VIA_ATTBASE 0x88 @@ -378,20 +380,9 @@ if (!cap_ptr) return -ENODEV; - /* probe for known chipsets */ - for (j = 0; devs[j].chipset_name; j++) { - if (pdev->device == devs[j].device_id) { - printk (KERN_INFO PFX "Detected VIA %s chipset\n", - devs[j].chipset_name); - goto found; - } - } - - printk(KERN_ERR PFX "Unsupported VIA chipset (device id: %04x)\n", - pdev->device); - return -ENODEV; + j = ent - agp_via_pci_table; + printk (KERN_INFO PFX "Detected VIA %s chipset\n", devs[j].chipset_name); -found: bridge = agp_alloc_bridge(); if (!bridge) return -ENOMEM; @@ -432,15 +423,40 @@ agp_put_bridge(bridge); } +/* must be the same order as name table above */ static struct pci_device_id agp_via_pci_table[] = { - { - .class = (PCI_CLASS_BRIDGE_HOST << 8), - .class_mask = ~0, - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, +#define ID(x) \ + { \ + .class = (PCI_CLASS_BRIDGE_HOST << 8), \ + .class_mask = ~0, \ + .vendor = PCI_VENDOR_ID_VIA, \ + .device = x, \ + .subvendor = PCI_ANY_ID, \ + .subdevice = PCI_ANY_ID, \ + } + ID(PCI_DEVICE_ID_VIA_82C598_0), + ID(PCI_DEVICE_ID_VIA_8501_0), + ID(PCI_DEVICE_ID_VIA_8601_0), + ID(PCI_DEVICE_ID_VIA_82C691_0), + ID(PCI_DEVICE_ID_VIA_8371_0), + ID(PCI_DEVICE_ID_VIA_8633_0), + ID(PCI_DEVICE_ID_VIA_XN266), + ID(PCI_DEVICE_ID_VIA_8361), + ID(PCI_DEVICE_ID_VIA_8363_0), + ID(PCI_DEVICE_ID_VIA_8753_0), + ID(PCI_DEVICE_ID_VIA_8367_0), + ID(PCI_DEVICE_ID_VIA_8653_0), + ID(PCI_DEVICE_ID_VIA_XM266), + ID(PCI_DEVICE_ID_VIA_862X_0), + ID(PCI_DEVICE_ID_VIA_8377_0), + ID(PCI_DEVICE_ID_VIA_8605_0), + ID(PCI_DEVICE_ID_VIA_8703_51_0), + ID(PCI_DEVICE_ID_VIA_8754C_0), + ID(PCI_DEVICE_ID_VIA_8763_0), + ID(PCI_DEVICE_ID_VIA_8378_0), + ID(PCI_DEVICE_ID_VIA_PT880), + ID(PCI_DEVICE_ID_VIA_8783_0), + ID(PCI_DEVICE_ID_VIA_PX8X0_0), { } }; --- diff/drivers/char/keyboard.c 2004-05-19 22:11:34.000000000 +0100 +++ source/drivers/char/keyboard.c 2004-05-27 18:34:16.000000000 +0100 @@ -52,13 +52,12 @@ /* * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on. - * This seems a good reason to start with NumLock off. On PC9800 and HIL keyboards + * This seems a good reason to start with NumLock off. On HIL keyboards * of PARISC machines however there is no NumLock key and everyone expects the keypad * to be used for numbers. */ -#if defined(CONFIG_X86_PC9800) || \ - defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD)) +#if defined(CONFIG_PARISC) && (defined(CONFIG_KEYBOARD_HIL) || defined(CONFIG_KEYBOARD_HIL_OLD)) #define KBD_DEFLEDS (1 << VC_NUMLOCK) #else #define KBD_DEFLEDS 0 @@ -1066,6 +1065,9 @@ } if (sysrq_down && down && !rep) { handle_sysrq(kbd_sysrq_xlate[keycode], regs, tty); +#ifdef CONFIG_KGDB_SYSRQ + sysrq_down = 0; /* in case we miss the "up" event */ +#endif return; } #endif --- diff/drivers/char/mem.c 2004-05-27 13:41:17.000000000 +0100 +++ source/drivers/char/mem.c 2004-05-27 18:34:16.000000000 +0100 @@ -26,7 +26,6 @@ #include #include -#include #ifdef CONFIG_IA64 # include @@ -39,6 +38,7 @@ extern void tapechar_init(void); #endif +#ifdef pgprot_noncached /* * Architectures vary in how they handle caching for addresses * outside of main memory. @@ -77,7 +77,8 @@ return 0; #elif defined(CONFIG_IA64) /* - * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases. + * On ia64, we ignore O_SYNC because we cannot tolerate memory + * attribute aliases. */ return !(efi_mem_attributes(addr) & EFI_MEMORY_WB); #elif defined(CONFIG_PPC64) @@ -90,14 +91,15 @@ return !page_is_ram(addr); #else /* - * Accessing memory above the top the kernel knows about or through a file pointer - * that was marked O_SYNC will be done non-cached. + * Accessing memory above the top the kernel knows about or through a + * file pointer that was marked O_SYNC will be done non-cached. */ if (file->f_flags & O_SYNC) return 1; return addr >= __pa(high_memory); #endif } +#endif #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE static inline int valid_phys_addr_range(unsigned long addr, size_t *count) @@ -194,28 +196,24 @@ return do_write_mem(__va(p), p, buf, count, ppos); } -static int mmap_mem(struct file * file, struct vm_area_struct * vma) +static int mmap_mem(struct file *file, struct vm_area_struct *vma) { unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - int uncached; - uncached = uncached_access(file, offset); #ifdef pgprot_noncached - if (uncached) + if (uncached_access(file, offset)) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); #endif - /* Don't try to swap out physical pages.. */ - vma->vm_flags |= VM_RESERVED; - /* - * Don't dump addresses that are not real memory to a core file. + * Don't try to swap out physical pages.. + * And treat /dev/mem mappings as "IO" regions: they may not + * describe valid pageframes. */ - if (uncached) - vma->vm_flags |= VM_IO; + vma->vm_flags |= VM_RESERVED|VM_IO; - if (remap_page_range(vma, vma->vm_start, offset, vma->vm_end-vma->vm_start, - vma->vm_page_prot)) + if (remap_page_range(vma, vma->vm_start, offset, + vma->vm_end-vma->vm_start, vma->vm_page_prot)) return -EAGAIN; return 0; } --- diff/drivers/char/rtc.c 2004-05-19 22:11:34.000000000 +0100 +++ source/drivers/char/rtc.c 2004-05-27 18:34:16.000000000 +0100 @@ -97,6 +97,11 @@ static int rtc_irq = PCI_IRQ_NONE; #endif +#ifdef CONFIG_HPET_RTC_IRQ +#undef RTC_IRQ +#define RTC_IRQ 0 +#endif + #if RTC_IRQ static int rtc_has_irq = 1; #endif --- diff/drivers/char/sysrq.c 2004-05-27 13:41:17.000000000 +0100 +++ source/drivers/char/sysrq.c 2004-05-27 18:34:16.000000000 +0100 @@ -35,6 +35,25 @@ #include #include +#ifdef CONFIG_KGDB_SYSRQ + +#define GDB_OP &kgdb_op +static void kgdb_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty) +{ + printk("kgdb sysrq\n"); + breakpoint(); +} + +static struct sysrq_key_op kgdb_op = { + .handler = kgdb_sysrq, + .help_msg = "kGdb|Fgdb", + .action_msg = "Debug breakpoint\n", +}; + +#else +#define GDB_OP NULL +#endif + extern void reset_vc(unsigned int); @@ -238,8 +257,8 @@ /* c */ NULL, /* d */ NULL, /* e */ &sysrq_term_op, -/* f */ NULL, -/* g */ NULL, +/* f */ GDB_OP, +/* g */ GDB_OP, /* h */ NULL, /* i */ &sysrq_kill_op, /* j */ NULL, --- diff/drivers/char/tty_io.c 2004-05-27 13:41:17.000000000 +0100 +++ source/drivers/char/tty_io.c 2004-05-27 18:34:16.000000000 +0100 @@ -91,6 +91,7 @@ #include #include #include +#include #include #include @@ -128,6 +129,8 @@ #ifdef CONFIG_UNIX98_PTYS extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ extern int pty_limit; /* Config limit on Unix98 ptys */ +static DEFINE_IDR(allocated_ptys); +static DECLARE_MUTEX(allocated_ptys_lock); #endif extern void disable_early_printk(void); @@ -1295,6 +1298,14 @@ o_tty->ldisc = ldiscs[N_TTY]; } +#ifdef CONFIG_UNIX98_PTYS + if (filp->f_dentry->d_inode->i_rdev == MKDEV(TTYAUX_MAJOR,2)) { + down(&allocated_ptys_lock); + idr_remove(&allocated_ptys, idx); + up(&allocated_ptys_lock); + } +#endif + /* * The release_mem function takes care of the details of clearing * the slots and preserving the termios structure. @@ -1319,7 +1330,7 @@ struct tty_struct *tty; int noctty, retval; struct tty_driver *driver; - int index; + int index = -1; dev_t device = inode->i_rdev; unsigned short saved_flags = filp->f_flags; retry_open: @@ -1361,23 +1372,41 @@ #ifdef CONFIG_UNIX98_PTYS if (device == MKDEV(TTYAUX_MAJOR,2)) { + int idr_ret; + /* find a device that is not in use. */ - static int next_ptmx_dev = 0; - retval = -1; + down(&allocated_ptys_lock); + if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) { + up(&allocated_ptys_lock); + return -ENOMEM; + } + idr_ret = idr_get_new(&allocated_ptys, NULL, &index); + if (idr_ret < 0) { + up(&allocated_ptys_lock); + if (idr_ret == -EAGAIN) + return -ENOMEM; + return -EIO; + } + if (index >= pty_limit) { + idr_remove(&allocated_ptys, index); + up(&allocated_ptys_lock); + return -EIO; + } driver = ptm_driver; - while (driver->refcount < pty_limit) { - index = next_ptmx_dev; - next_ptmx_dev = (next_ptmx_dev+1) % driver->num; - if (!init_dev(driver, index, &tty)) - goto ptmx_found; /* ok! */ + retval = init_dev(driver, index, &tty); + if (retval) { + idr_remove(&allocated_ptys, index); + up(&allocated_ptys_lock); + return retval; } - return -EIO; /* no free ptys */ - ptmx_found: set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ if (devpts_pty_new(tty->link)) { /* BADNESS - need to destroy both ptm and pts! */ + idr_remove(&allocated_ptys, index); + up(&allocated_ptys_lock); return -ENOMEM; } + up(&allocated_ptys_lock); noctty = 1; } else #endif @@ -1415,6 +1444,14 @@ tty->name); #endif +#ifdef CONFIG_UNIX98_PTYS + if (index != -1) { + down(&allocated_ptys_lock); + idr_remove(&allocated_ptys, index); + up(&allocated_ptys_lock); + } +#endif + release_dev(filp); if (retval != -ERESTARTSYS) return retval; --- diff/drivers/char/watchdog/wdt.c 2004-05-19 22:11:39.000000000 +0100 +++ source/drivers/char/watchdog/wdt.c 2004-05-27 18:34:16.000000000 +0100 @@ -633,8 +633,8 @@ outmisc: #ifdef CONFIG_WDT_501 misc_deregister(&temp_miscdev); -#endif /* CONFIG_WDT_501 */ outrbt: +#endif /* CONFIG_WDT_501 */ unregister_reboot_notifier(&wdt_notifier); outirq: free_irq(irq, NULL); --- diff/drivers/firmware/smbios.c 2004-05-27 13:41:17.000000000 +0100 +++ source/drivers/firmware/smbios.c 2004-05-27 18:34:16.000000000 +0100 @@ -126,7 +126,7 @@ if(keep_going != 0) printk(KERN_INFO "Warning: SMBIOS table does not end with a" " structure type 127. This may indicate a" - " truncated table."); + " truncated table.\n"); if(sdev->smbios_table_real_length != max_length) printk(KERN_INFO "Warning: BIOS specified SMBIOS table length" --- diff/drivers/i2c/busses/Kconfig 2004-05-27 13:41:17.000000000 +0100 +++ source/drivers/i2c/busses/Kconfig 2004-05-27 18:34:16.000000000 +0100 @@ -118,8 +118,14 @@ will be called i2c-i810. config I2C_IBM_IIC - tristate "IBM IIC I2C" + tristate "IBM PPC 4xx on-chip I2C interface" depends on IBM_OCP && I2C + help + Say Y here if you want to use IIC peripheral found on + embedded IBM PPC 4xx based systems. + + This driver can also be built as a module. If so, the module + will be called i2c-ibm_iic. config I2C_IOP3XX tristate "Intel XScale IOP3xx on-chip I2C interface" --- diff/drivers/i2c/busses/i2c-ibm_iic.c 2004-05-19 22:11:39.000000000 +0100 +++ source/drivers/i2c/busses/i2c-ibm_iic.c 2004-05-27 18:34:16.000000000 +0100 @@ -3,7 +3,7 @@ * * Support for the IIC peripheral on IBM PPC 4xx * - * Copyright (c) 2003 Zultys Technologies. + * Copyright (c) 2003, 2004 Zultys Technologies. * Eugene Surovegin or * * Based on original work by @@ -45,7 +45,7 @@ #include "i2c-ibm_iic.h" -#define DRIVER_VERSION "2.0" +#define DRIVER_VERSION "2.01" MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION); MODULE_LICENSE("GPL"); @@ -69,14 +69,14 @@ #endif #if DBG_LEVEL > 0 -# define DBG(x...) printk(KERN_DEBUG "ibm-iic" ##x) +# define DBG(f,x...) printk(KERN_DEBUG "ibm-iic" f, ##x) #else -# define DBG(x...) ((void)0) +# define DBG(f,x...) ((void)0) #endif #if DBG_LEVEL > 1 -# define DBG2(x...) DBG( ##x ) +# define DBG2(f,x...) DBG(f, ##x) #else -# define DBG2(x...) ((void)0) +# define DBG2(f,x...) ((void)0) #endif #if DBG_LEVEL > 2 static void dump_iic_regs(const char* header, struct ibm_iic_private* dev) @@ -455,6 +455,16 @@ } for (i = 0; i < num; ++i){ if (unlikely(msgs[i].len <= 0)){ + if (num == 1 && !msgs[0].len){ + /* Special case for I2C_SMBUS_QUICK emulation. + * Although this logic is FAR FROM PERFECT, this + * is what previous driver version did. + * IBM IIC doesn't support 0-length transactions + * (except bit-banging through IICx_DIRECTCNTL). + */ + DBG("%d: zero-length msg kludge\n", dev->idx); + return 0; + } DBG("%d: invalid len %d in msg[%d]\n", dev->idx, msgs[i].len, i); return -EINVAL; @@ -549,19 +559,24 @@ struct ibm_iic_private* dev; struct i2c_adapter* adap; + struct ocp_func_iic_data* iic_data = ocp->def->additions; int ret; - bd_t* bd = (bd_t*)&__res; + if (!iic_data) + printk(KERN_WARNING"ibm-iic%d: missing additional data!\n", + ocp->def->index); + if (!(dev = kmalloc(sizeof(*dev), GFP_KERNEL))){ - printk(KERN_CRIT "ibm-iic: failed to allocate device data\n"); + printk(KERN_CRIT "ibm-iic%d: failed to allocate device data\n", + ocp->def->index); return -ENOMEM; } memset(dev, 0, sizeof(*dev)); - dev->idx = ocp->num; + dev->idx = ocp->def->index; ocp_set_drvdata(ocp, dev); - if (!(dev->vaddr = ioremap(ocp->paddr, sizeof(struct iic_regs)))){ + if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){ printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n", dev->idx); ret = -ENXIO; @@ -570,7 +585,7 @@ init_waitqueue_head(&dev->wq); - dev->irq = iic_force_poll ? -1 : ocp->irq; + dev->irq = iic_force_poll ? -1 : ocp->def->irq; if (dev->irq >= 0){ /* Disable interrupts until we finish intialization, assumes level-sensitive IRQ setup... @@ -589,13 +604,12 @@ dev->idx); /* Board specific settings */ - BUG_ON(dev->idx >= sizeof(bd->bi_iic_fast) / sizeof(bd->bi_iic_fast[0])); - dev->fast_mode = iic_force_fast ? 1 : bd->bi_iic_fast[dev->idx]; + dev->fast_mode = iic_force_fast ? 1 : (iic_data ? iic_data->fast_mode : 0); /* clckdiv is the same for *all* IIC interfaces, * but I'd rather make a copy than introduce another global. --ebs */ - dev->clckdiv = iic_clckdiv(bd->bi_opb_busfreq); + dev->clckdiv = iic_clckdiv(ocp_sys_info.opb_bus_freq); DBG("%d: clckdiv = %d\n", dev->idx, dev->clckdiv); /* Initialize IIC interface */ @@ -664,7 +678,7 @@ static struct ocp_device_id ibm_iic_ids[] __devinitdata = { - { .vendor = OCP_VENDOR_IBM, .device = OCP_FUNC_IIC }, + { .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_IIC }, { .vendor = OCP_VENDOR_INVALID } }; @@ -672,7 +686,7 @@ static struct ocp_driver ibm_iic_driver = { - .name = "ocp_iic", + .name = "iic", .id_table = ibm_iic_ids, .probe = iic_probe, .remove = __devexit_p(iic_remove), @@ -685,7 +699,7 @@ static int __init iic_init(void) { printk(KERN_INFO "IBM IIC driver v" DRIVER_VERSION "\n"); - return ocp_module_init(&ibm_iic_driver); + return ocp_register_driver(&ibm_iic_driver); } static void __exit iic_exit(void) --- diff/drivers/i2c/chips/eeprom.c 2004-05-19 22:11:40.000000000 +0100 +++ source/drivers/i2c/chips/eeprom.c 2004-05-27 18:34:16.000000000 +0100 @@ -203,11 +203,12 @@ new_client->driver = &eeprom_driver; new_client->flags = 0; + /* prevent 24RF08 corruption */ + i2c_smbus_write_quick(new_client, 0); + /* Now, we do the remaining detection. It is not there, unless you force the checksum to work out. */ if (checksum) { - /* prevent 24RF08 corruption */ - i2c_smbus_write_quick(new_client, 0); cs = 0; for (i = 0; i <= 0x3e; i++) cs += i2c_smbus_read_byte_data(new_client, i); --- diff/drivers/i2c/i2c-core.c 2004-05-19 22:11:39.000000000 +0100 +++ source/drivers/i2c/i2c-core.c 2004-05-27 18:34:16.000000000 +0100 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,7 @@ static LIST_HEAD(adapters); static LIST_HEAD(drivers); static DECLARE_MUTEX(core_lists); +static DEFINE_IDR(i2c_adapter_idr); int i2c_device_probe(struct device *dev) { @@ -113,13 +115,25 @@ */ int i2c_add_adapter(struct i2c_adapter *adap) { - static int nr = 0; + int id, res = 0; struct list_head *item; struct i2c_driver *driver; down(&core_lists); - adap->nr = nr++; + if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) { + res = -ENOMEM; + goto out_unlock; + } + + res = idr_get_new(&i2c_adapter_idr, NULL, &id); + if (res < 0) { + if (res == -EAGAIN) + res = -ENOMEM; + goto out_unlock; + } + + adap->nr = id & MAX_ID_MASK; init_MUTEX(&adap->bus_lock); init_MUTEX(&adap->clist_lock); list_add_tail(&adap->list,&adapters); @@ -151,10 +165,12 @@ /* We ignore the return code; if it fails, too bad */ driver->attach_adapter(adap); } - up(&core_lists); dev_dbg(&adap->dev, "registered as adapter #%d\n", adap->nr); - return 0; + +out_unlock: + up(&core_lists); + return res; } @@ -208,6 +224,9 @@ wait_for_completion(&adap->dev_released); wait_for_completion(&adap->class_dev_released); + /* free dynamically allocated bus id */ + idr_remove(&i2c_adapter_idr, adap->nr); + dev_dbg(&adap->dev, "adapter unregistered\n"); out_unlock: --- diff/drivers/ide/Kconfig 2004-05-27 13:41:17.000000000 +0100 +++ source/drivers/ide/Kconfig 2004-05-27 18:34:16.000000000 +0100 @@ -97,25 +97,7 @@ config BLK_DEV_HD_IDE bool "Use old disk-only driver on primary interface" - depends on ((X86 && X86_PC9800!=y) || SH_MPC1211) - ---help--- - There are two drivers for MFM/RLL/IDE disks. Most people use just - the new enhanced driver by itself. This option however installs the - old hard disk driver to control the primary IDE/disk interface in - the system, leaving the new enhanced IDE driver to take care of only - the 2nd/3rd/4th IDE interfaces. Doing this will prevent you from - having an IDE/ATAPI CD-ROM or tape drive connected to the primary - IDE interface. Choosing this option may be useful for older systems - which have MFM/RLL/ESDI controller+drives at the primary port - address (0x1f0), along with IDE drives at the secondary/3rd/4th port - addresses. - - Normally, just say N here; you will then use the new driver for all - 4 interfaces. - -config BLK_DEV_HD_IDE98 - bool "Use old disk-only driver on primary interface" - depends on X86 && X86_PC9800 + depends on (X86 || SH_MPC1211) ---help--- There are two drivers for MFM/RLL/IDE disks. Most people use just the new enhanced driver by itself. This option however installs the --- diff/drivers/ide/Makefile 2004-05-27 13:41:17.000000000 +0100 +++ source/drivers/ide/Makefile 2004-05-27 18:34:16.000000000 +0100 @@ -29,7 +29,6 @@ ide-core-$(CONFIG_IDE_ARM) += arm/ide_arm.o # built-in only drivers from legacy/ -ide-core-$(CONFIG_BLK_DEV_IDE_PC9800) += legacy/pc9800.o ide-core-$(CONFIG_BLK_DEV_BUDDHA) += legacy/buddha.o ide-core-$(CONFIG_BLK_DEV_FALCON_IDE) += legacy/falconide.o ide-core-$(CONFIG_BLK_DEV_GAYLE) += legacy/gayle.o --- diff/drivers/ide/ide-disk.c 2004-05-27 13:41:17.000000000 +0100 +++ source/drivers/ide/ide-disk.c 2004-05-27 18:34:16.000000000 +0100 @@ -1329,6 +1329,41 @@ #endif /* CONFIG_PROC_FS */ +static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + ide_drive_t *drive = q->queuedata; + struct request *rq; + int ret; + + if (!drive->wcache) + return 0; + + rq = blk_get_request(q, WRITE, __GFP_WAIT); + + memset(rq->cmd, 0, sizeof(rq->cmd)); + + if ((drive->id->cfs_enable_2 & 0x2400) == 0x2400) + rq->cmd[0] = WIN_FLUSH_CACHE_EXT; + else + rq->cmd[0] = WIN_FLUSH_CACHE; + + + rq->flags |= REQ_DRIVE_TASK | REQ_SOFTBARRIER; + rq->buffer = rq->cmd; + + ret = blk_execute_rq(q, disk, rq); + + /* + * if we failed and caller wants error offset, get it + */ + if (ret && error_sector) + *error_sector = ide_get_error_location(drive, rq->cmd); + + blk_put_request(rq); + return ret; +} + /* * This is tightly woven into the driver->do_special can not touch. * DON'T do it again until a total personality rewrite is committed. @@ -1357,16 +1392,10 @@ return 0; } -/* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */ -#define ide_id_has_flush_cache(id) ((id)->cfs_enable_2 & 0x3000) - -/* some Maxtor disks have bit 13 defined incorrectly so check bit 10 too */ -#define ide_id_has_flush_cache_ext(id) \ - (((id)->cfs_enable_2 & 0x2400) == 0x2400) - static int write_cache (ide_drive_t *drive, int arg) { ide_task_t args; + int err; if (!ide_id_has_flush_cache(drive->id)) return 1; @@ -1377,7 +1406,10 @@ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES; args.command_type = IDE_DRIVE_TASK_NO_DATA; args.handler = &task_no_data_intr; - (void) ide_raw_taskfile(drive, &args, NULL); + + err = ide_raw_taskfile(drive, &args, NULL); + if (err) + return err; drive->wcache = arg; return 0; @@ -1558,6 +1590,7 @@ { struct hd_driveid *id = drive->id; unsigned long long capacity; + int barrier; idedisk_add_settings(drive); @@ -1690,6 +1723,27 @@ write_cache(drive, 1); + /* + * decide if we can sanely support flushes and barriers on + * this drive. unfortunately not all drives advertise FLUSH_CACHE + * support even if they support it. So assume FLUSH_CACHE is there + * always. LBA48 drives are newer, so expect it to flag support + * properly. We can safely support FLUSH_CACHE on lba48, if capacity + * doesn't exceed lba28 + */ + barrier = 1; + if (drive->addressing == 1) { + barrier = ide_id_has_flush_cache(id); + if (capacity > (1ULL << 28) && !ide_id_has_flush_cache_ext(id)) + barrier = 0; + } + + printk("%s: cache flushes %ssupported\n", drive->name, barrier ? "" : "not "); + if (barrier) { + blk_queue_ordered(drive->queue, 1); + blk_queue_issue_flush_fn(drive->queue, idedisk_issue_flush); + } + #ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT if (drive->using_dma) __ide_dma_queued_on(drive); --- diff/drivers/ide/ide-io.c 2004-05-27 13:41:17.000000000 +0100 +++ source/drivers/ide/ide-io.c 2004-05-27 18:34:16.000000000 +0100 @@ -54,38 +54,73 @@ #include #include -/** - * ide_end_request - complete an IDE I/O - * @drive: IDE device for the I/O - * @uptodate: - * @nr_sectors: number of sectors completed - * - * This is our end_request wrapper function. We complete the I/O - * update random number input and dequeue the request, which if - * it was tagged may be out of order. +static void ide_fill_flush_cmd(ide_drive_t *drive, struct request *rq) +{ + char *buf = rq->cmd; + + /* + * reuse cdb space for ata command + */ + memset(buf, 0, sizeof(rq->cmd)); + + rq->flags |= REQ_DRIVE_TASK | REQ_STARTED; + rq->buffer = buf; + rq->buffer[0] = WIN_FLUSH_CACHE; + + if (ide_id_has_flush_cache_ext(drive->id)) + rq->buffer[0] = WIN_FLUSH_CACHE_EXT; +} + +/* + * preempt pending requests, and store this cache flush for immediate + * execution */ - -int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) +static struct request *ide_queue_flush_cmd(ide_drive_t *drive, + struct request *rq, int post) { - struct request *rq; - unsigned long flags; - int ret = 1; + struct request *flush_rq = &HWGROUP(drive)->wrq; - spin_lock_irqsave(&ide_lock, flags); - rq = HWGROUP(drive)->rq; + /* + * write cache disabled, just return barrier write immediately + */ + if (!drive->wcache) + return rq; - BUG_ON(!(rq->flags & REQ_STARTED)); + ide_init_drive_cmd(flush_rq); + ide_fill_flush_cmd(drive, flush_rq); - if (!nr_sectors) - nr_sectors = rq->hard_cur_sectors; + flush_rq->special = rq; + flush_rq->nr_sectors = rq->nr_sectors; + + if (!post) { + drive->doing_barrier = 1; + flush_rq->flags |= REQ_BAR_PREFLUSH; + blkdev_dequeue_request(rq); + } else + flush_rq->flags |= REQ_BAR_POSTFLUSH; + + __elv_add_request(drive->queue, flush_rq, ELEVATOR_INSERT_FRONT, 0); + HWGROUP(drive)->rq = NULL; + return flush_rq; +} + +static int __ide_end_request(ide_drive_t *drive, struct request *rq, + int uptodate, int nr_sectors) +{ + int ret = 1; + + BUG_ON(!(rq->flags & REQ_STARTED)); /* * if failfast is set on a request, override number of sectors and * complete the whole request right now */ - if (blk_noretry_request(rq) && !uptodate) + if (blk_noretry_request(rq) && end_io_error(uptodate)) nr_sectors = rq->hard_nr_sectors; + if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors) + rq->errors = -EIO; + /* * decide whether to reenable DMA -- 3 is a random magic for now, * if we DMA timeout more than 3 times, just stay in PIO @@ -97,14 +132,54 @@ if (!end_that_request_first(rq, uptodate, nr_sectors)) { add_disk_randomness(rq->rq_disk); - if (!blk_rq_tagged(rq)) - blkdev_dequeue_request(rq); - else + + if (blk_rq_tagged(rq)) blk_queue_end_tag(drive->queue, rq); - HWGROUP(drive)->rq = NULL; + + blkdev_dequeue_request(rq); end_that_request_last(rq); + HWGROUP(drive)->rq = NULL; ret = 0; } + + return ret; +} + +/** + * ide_end_request - complete an IDE I/O + * @drive: IDE device for the I/O + * @uptodate: + * @nr_sectors: number of sectors completed + * + * This is our end_request wrapper function. We complete the I/O + * update random number input and dequeue the request, which if + * it was tagged may be out of order. + */ + +int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) +{ + struct request *rq; + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&ide_lock, flags); + rq = HWGROUP(drive)->rq; + + if (!nr_sectors) + nr_sectors = rq->hard_cur_sectors; + + if (!blk_barrier_rq(rq)) + ret = __ide_end_request(drive, rq, uptodate, nr_sectors); + else { + struct request *flush_rq = &HWGROUP(drive)->wrq; + + flush_rq->nr_sectors -= nr_sectors; + if (!flush_rq->nr_sectors) { + ide_queue_flush_cmd(drive, rq, 1); + ret = 0; + } + } + spin_unlock_irqrestore(&ide_lock, flags); return ret; } @@ -140,6 +215,113 @@ spin_unlock_irqrestore(&ide_lock, flags); } +/* + * FIXME: probably move this somewhere else, name is bad too :) + */ +u64 ide_get_error_location(ide_drive_t *drive, char *args) +{ + u32 high, low; + u8 hcyl, lcyl, sect; + u64 sector; + + high = 0; + hcyl = args[5]; + lcyl = args[4]; + sect = args[3]; + + if (ide_id_has_flush_cache_ext(drive->id)) { + low = (hcyl << 16) | (lcyl << 8) | sect; + HWIF(drive)->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); + high = ide_read_24(drive); + } else { + u8 cur = HWIF(drive)->INB(IDE_SELECT_REG); + if (cur & 0x40) + low = (hcyl << 16) | (lcyl << 8) | sect; + else { + low = hcyl * drive->head * drive->sect; + low += lcyl * drive->sect; + low += sect - 1; + } + } + + sector = ((u64) high << 24) | low; + return sector; +} +EXPORT_SYMBOL(ide_get_error_location); + +static void ide_complete_barrier(ide_drive_t *drive, struct request *rq, + int error) +{ + struct request *real_rq = rq->special; + int good_sectors, bad_sectors; + sector_t sector; + + if (!error) { + if (blk_barrier_postflush(rq)) { + /* + * this completes the barrier write + */ + __ide_end_request(drive, real_rq, 1, real_rq->hard_nr_sectors); + drive->doing_barrier = 0; + } else { + /* + * just indicate that we did the pre flush + */ + real_rq->flags |= REQ_BAR_PREFLUSH; + elv_requeue_request(drive->queue, real_rq); + } + /* + * all is fine, return + */ + return; + } + + /* + * we need to end real_rq, but it's not on the queue currently. + * put it back on the queue, so we don't have to special case + * anything else for completing it + */ + if (!blk_barrier_postflush(rq)) + elv_requeue_request(drive->queue, real_rq); + + /* + * drive aborted flush command, assume FLUSH_CACHE_* doesn't + * work and disable barrier support + */ + if (error & ABRT_ERR) { + printk(KERN_ERR "%s: barrier support doesn't work\n", drive->name); + __ide_end_request(drive, real_rq, -EOPNOTSUPP, real_rq->hard_nr_sectors); + blk_queue_ordered(drive->queue, 0); + blk_queue_issue_flush_fn(drive->queue, NULL); + } else { + /* + * find out what part of the request failed + */ + good_sectors = 0; + if (blk_barrier_postflush(rq)) { + sector = ide_get_error_location(drive, rq->buffer); + + if ((sector >= real_rq->hard_sector) && + (sector < real_rq->hard_sector + real_rq->hard_nr_sectors)) + good_sectors = sector - real_rq->hard_sector; + } else + sector = real_rq->hard_sector; + + bad_sectors = real_rq->hard_nr_sectors - good_sectors; + if (good_sectors) + __ide_end_request(drive, real_rq, 1, good_sectors); + if (bad_sectors) + __ide_end_request(drive, real_rq, 0, bad_sectors); + + printk(KERN_ERR "%s: failed barrier write: " + "sector=%Lx(good=%d/bad=%d)\n", + drive->name, (unsigned long long)sector, + good_sectors, bad_sectors); + } + + drive->doing_barrier = 0; +} + /** * ide_end_drive_cmd - end an explicit drive command * @drive: command @@ -229,6 +411,10 @@ spin_lock_irqsave(&ide_lock, flags); blkdev_dequeue_request(rq); + + if (blk_barrier_preflush(rq) || blk_barrier_postflush(rq)) + ide_complete_barrier(drive, rq, err); + HWGROUP(drive)->rq = NULL; end_that_request_last(rq); spin_unlock_irqrestore(&ide_lock, flags); @@ -715,6 +901,22 @@ repeat: best = NULL; drive = hwgroup->drive; + + /* + * drive is doing pre-flush, ordered write, post-flush sequence. even + * though that is 3 requests, it must be seen as a single transaction. + * we must not preempt this drive until that is complete + */ + if (drive->doing_barrier) { + /* + * small race where queue could get replugged during + * the 3-request flush cycle, just yank the plug since + * we want it to finish asap + */ + blk_remove_plug(drive->queue); + return drive; + } + do { if ((!drive->sleep || time_after_eq(jiffies, drive->sleep)) && !elv_queue_empty(drive->queue)) { @@ -882,6 +1084,13 @@ } /* + * if rq is a barrier write, issue pre cache flush if not + * already done + */ + if (blk_barrier_rq(rq) && !blk_barrier_preflush(rq)) + rq = ide_queue_flush_cmd(drive, rq, 0); + + /* * Sanity: don't accept a request that isn't a PM request * if we are currently power managed. This is very important as * blk_stop_queue() doesn't prevent the elv_next_request() @@ -900,6 +1109,10 @@ break; } + /* + * we can only queue read-write requests, so let the drive + * queue drain before continuing with this command. + */ if (!rq->bio && ata_pending_commands(drive)) break; @@ -936,7 +1149,9 @@ */ void do_ide_request(request_queue_t *q) { - ide_do_request(q->queuedata, IDE_NO_IRQ); + ide_drive_t *drive = q->queuedata; + + ide_do_request(HWGROUP(drive), IDE_NO_IRQ); } /* @@ -1305,6 +1520,7 @@ { memset(rq, 0, sizeof(*rq)); rq->flags = REQ_DRIVE_CMD; + rq->ref_count = 1; } EXPORT_SYMBOL(ide_init_drive_cmd); --- diff/drivers/ide/ide-probe.c 2004-05-19 22:11:40.000000000 +0100 +++ source/drivers/ide/ide-probe.c 2004-05-27 18:34:16.000000000 +0100 @@ -914,11 +914,15 @@ if (!q) return 1; - q->queuedata = HWGROUP(drive); + q->queuedata = drive; blk_queue_segment_boundary(q, 0xffff); - if (!hwif->rqsize) - hwif->rqsize = hwif->no_lba48 ? 256 : 65536; + if (!hwif->rqsize) { + if (hwif->max_rqsize) + hwif->rqsize = hwif->max_rqsize(drive); + else + hwif->rqsize = hwif->no_lba48 ? 256 : 65536; + } if (hwif->rqsize < max_sectors) max_sectors = hwif->rqsize; blk_queue_max_sectors(q, max_sectors); --- diff/drivers/ide/ide-proc.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/ide/ide-proc.c 2004-05-27 18:34:16.000000000 +0100 @@ -352,7 +352,6 @@ case ide_cy82c693: name = "cy82c693"; break; case ide_4drives: name = "4drives"; break; case ide_pmac: name = "mac-io"; break; - case ide_pc9800: name = "pc9800"; break; default: name = "(unknown)"; break; } len = sprintf(page, "%s\n", name); --- diff/drivers/ide/pci/siimage.c 2004-05-19 22:11:41.000000000 +0100 +++ source/drivers/ide/pci/siimage.c 2004-05-27 18:34:16.000000000 +0100 @@ -203,13 +203,12 @@ else pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc); - if(is_sata(hwif)) - { - if(strstr(drive->id->model, "Maxtor")) + if (is_sata(hwif)) { + if (strstr(drive->id->model, "Maxtor 4D060H3")) return 3; return 4; } - + if ((scsc & 0x30) == 0x10) /* 133 */ mode = 4; else if ((scsc & 0x30) == 0x20) /* 2xPCI */ @@ -1046,25 +1045,34 @@ hwif->mmio = 2; } -static int is_dev_seagate_sata(ide_drive_t *drive) +/* TODO firmware versions should be added - eric */ +static const char * sil_blacklist [] = { + "ST320012AS", + "ST330013AS", + "ST340017AS", + "ST360015AS", + "ST380023AS", + "ST3120023AS", + "ST340014ASL", + "ST360014ASL", + "ST380011ASL", + "ST3120022ASL", + "ST3160021ASL", +}; + +static unsigned int siimage_sata_max_rqsize(ide_drive_t *drive) { const char *s = &drive->id->model[0]; - unsigned len; + unsigned int n; - if (!drive->present) - return 0; - - len = strnlen(s, sizeof(drive->id->model)); - - if ((len > 4) && (!memcmp(s, "ST", 2))) { - if ((!memcmp(s + len - 2, "AS", 2)) || - (!memcmp(s + len - 3, "ASL", 3))) { - printk(KERN_INFO "%s: applying pessimistic Seagate " - "errata fix\n", drive->name); - return 1; + for (n = 0; n < ARRAY_SIZE(sil_blacklist); n++) + if (!memcmp(sil_blacklist[n], s, strlen(sil_blacklist[n]))) { + printk(KERN_INFO "%s: applying Seagate errata fix\n", + drive->name); + return 15; } - } - return 0; + + return 128; } /** @@ -1087,9 +1095,10 @@ hwif->hwif_data = 0; - hwif->rqsize = 128; - if (is_sata(hwif) && is_dev_seagate_sata(&hwif->drives[0])) - hwif->rqsize = 15; + if (is_sata(hwif) && (class_rev <= 0x01)) + hwif->max_rqsize = siimage_sata_max_rqsize; + else + hwif->rqsize = 128; if (pci_get_drvdata(dev) == NULL) return; --- diff/drivers/ieee1394/hosts.c 2004-05-19 22:11:42.000000000 +0100 +++ source/drivers/ieee1394/hosts.c 2004-05-27 18:34:16.000000000 +0100 @@ -187,6 +187,9 @@ void hpsb_remove_host(struct hpsb_host *host) { host->is_shutdown = 1; + + del_timer_sync(&host->delayed_reset); + host->driver = &dummy_driver; highlevel_remove_host(host); --- diff/drivers/input/Kconfig 2004-05-19 22:11:42.000000000 +0100 +++ source/drivers/input/Kconfig 2004-05-27 18:34:16.000000000 +0100 @@ -41,9 +41,16 @@ module will be called mousedev. config INPUT_MOUSEDEV_PSAUX - bool "Provide legacy /dev/psaux device" if EMBEDDED + bool "Provide legacy /dev/psaux device" default y depends on INPUT_MOUSEDEV + ---help--- + Say Y here if you want your mouse also be accessible as char device + 10:1 - /dev/psaux. The data available through /dev/psaux is exactly + the same as the data from /dev/input/mice. + + If unsure, say Y. + config INPUT_MOUSEDEV_SCREEN_X int "Horizontal screen resolution" --- diff/drivers/input/evbug.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/evbug.c 2004-05-27 18:34:16.000000000 +0100 @@ -11,18 +11,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -35,7 +35,7 @@ #include MODULE_AUTHOR("Vojtech Pavlik "); -MODULE_DESCRIPTION("Input driver event debug module"); +MODULE_DESCRIPTION("Input driver event debug module"); MODULE_LICENSE("GPL"); static char evbug_name[] = "evbug"; @@ -67,7 +67,7 @@ static void evbug_disconnect(struct input_handle *handle) { printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n", handle->dev->phys); - + input_close_device(handle); kfree(handle); @@ -79,7 +79,7 @@ }; MODULE_DEVICE_TABLE(input, evbug_ids); - + static struct input_handler evbug_handler = { .event = evbug_event, .connect = evbug_connect, --- diff/drivers/input/evdev.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/evdev.c 2004-05-27 18:34:16.000000000 +0100 @@ -126,7 +126,7 @@ int i = iminor(inode) - EVDEV_MINOR_BASE; int accept_err; - if (i >= EVDEV_MINORS || !evdev_table[i]) + if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist) return -ENODEV; if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file))) @@ -175,7 +175,7 @@ return -EAGAIN; retval = wait_event_interruptible(list->evdev->wait, - list->head != list->tail && list->evdev->exist); + list->head != list->tail || (!list->evdev->exist)); if (retval) return retval; @@ -220,7 +220,7 @@ case EVIOCGID: return copy_to_user((void *) arg, &dev->id, sizeof(struct input_id)) ? -EFAULT : 0; - + case EVIOCGKEYCODE: if (get_user(t, ((int *) arg) + 0)) return -EFAULT; if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL; @@ -428,7 +428,7 @@ devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor); - class_simple_device_add(input_class, + class_simple_device_add(input_class, MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), dev->dev, "event%d", minor); --- diff/drivers/input/gameport/cs461x.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/gameport/cs461x.c 2004-05-27 18:34:16.000000000 +0100 @@ -1,8 +1,8 @@ /* - The all defines and part of code (such as cs461x_*) are - contributed from ALSA 0.5.8 sources. + The all defines and part of code (such as cs461x_*) are + contributed from ALSA 0.5.8 sources. See http://www.alsa-project.org/ for sources - + Tested on Linux 686 2.4.0-test9, ALSA 0.5.8a and CS4610 */ @@ -89,8 +89,8 @@ #define JSIO_BXOE 0x00000040 #define JSIO_BYOE 0x00000080 -/* - The card initialization code is obfuscated; the module cs461x +/* + The card initialization code is obfuscated; the module cs461x need to be loaded after ALSA modules initialized and something played on the CS 4610 chip (see sources for details of CS4610 initialization code from ALSA) @@ -112,7 +112,7 @@ #define BA1_DWORD_SIZE (13 * 1024 + 512) #define BA1_MEMORY_COUNT 3 -/* +/* Only one CS461x card is still suppoted; the code requires redesign to avoid this limitatuion. */ @@ -163,7 +163,7 @@ if(port){ gameport_unregister_port(port); kfree(port); - } + } if (ba0) iounmap(ba0); #ifdef CS461X_FULL_MAP if (ba1.name.data0) iounmap(ba1.name.data0); @@ -187,13 +187,13 @@ static int cs461x_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons) { unsigned js1, js2, jst; - + js1 = cs461x_peekBA0(BA0_JSC1); js2 = cs461x_peekBA0(BA0_JSC2); jst = cs461x_peekBA0(BA0_JSPT); - - *buttons = (~jst >> 4) & 0x0F; - + + *buttons = (~jst >> 4) & 0x0F; + axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF; axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF; axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF; @@ -228,7 +228,7 @@ { int rc; struct gameport* port; - + rc = pci_enable_device(pdev); if (rc) { printk(KERN_ERR "cs461x: Cannot enable PCI gameport (bus %d, devfn %d) error=%d\n", @@ -240,7 +240,7 @@ #ifdef CS461X_FULL_MAP ba1_addr = pci_resource_start(pdev, 1); #endif - if (ba0_addr == 0 || ba0_addr == ~0 + if (ba0_addr == 0 || ba0_addr == ~0 #ifdef CS461X_FULL_MAP || ba1_addr == 0 || ba1_addr == ~0 #endif @@ -281,7 +281,7 @@ memset(port, 0, sizeof(struct gameport)); pci_set_drvdata(pdev, port); - + port->open = cs461x_gameport_open; port->trigger = cs461x_gameport_trigger; port->read = cs461x_gameport_read; @@ -310,7 +310,7 @@ { cs461x_free(pdev); } - + static struct pci_driver cs461x_pci_driver = { .name = "CS461x Gameport", .id_table = cs461x_pci_tbl, --- diff/drivers/input/gameport/emu10k1-gp.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/gameport/emu10k1-gp.c 2004-05-27 18:34:16.000000000 +0100 @@ -11,18 +11,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -48,7 +48,7 @@ int size; char phys[32]; }; - + static struct pci_device_id emu_tbl[] = { { 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */ { 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */ @@ -61,7 +61,7 @@ { int ioport, iolen; struct emu *emu; - + if (pci_enable_device(pdev)) return -EBUSY; --- diff/drivers/input/gameport/fm801-gp.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/gameport/fm801-gp.c 2004-05-27 18:34:16.000000000 +0100 @@ -111,7 +111,7 @@ pci_set_drvdata(pci, gp); - outb(0x60, gp->gameport.io + 0x0d); /* enable joystick 1 and 2 */ + outb(0x60, gp->gameport.io + 0x0d); /* enable joystick 1 and 2 */ gameport_register_port(&gp->gameport); --- diff/drivers/input/gameport/gameport.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/gameport/gameport.c 2004-05-27 18:34:16.000000000 +0100 @@ -168,7 +168,7 @@ return -1; gameport->dev = dev; - + return 0; } --- diff/drivers/input/gameport/lightning.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/gameport/lightning.c 2004-05-27 18:34:16.000000000 +0100 @@ -11,18 +11,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -106,7 +106,7 @@ result = 0; -fail: outb(L4_SELECT_ANALOG, L4_PORT); +fail: outb(L4_SELECT_ANALOG, L4_PORT); return result; } @@ -126,7 +126,7 @@ static int l4_getcal(int port, int *cal) { int i, result = -1; - + outb(L4_SELECT_ANALOG, L4_PORT); outb(L4_SELECT_DIGITAL + (port >> 2), L4_PORT); @@ -208,7 +208,7 @@ return 0; } - + static int __init l4_init(void) { int cal[4] = {255,255,255,255}; @@ -266,7 +266,7 @@ if (rev > 0x28) /* on 2.9+ the setcal command works correctly */ l4_setcal(l4->port, cal); - + gameport_register_port(gameport); } --- diff/drivers/input/gameport/ns558.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/input/gameport/ns558.c 2004-05-27 18:34:16.000000000 +0100 @@ -12,18 +12,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -59,7 +59,7 @@ char phys[32]; char name[32]; }; - + static LIST_HEAD(ns558_list); /* @@ -116,7 +116,7 @@ i = 0; goto out; } -/* +/* * And now find the number of mirrors of the port. */ @@ -292,7 +292,7 @@ release_region(port->gameport.io & ~(port->size - 1), port->size); kfree(port); break; - + default: break; } --- diff/drivers/input/gameport/vortex.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/input/gameport/vortex.c 2004-05-27 18:34:16.000000000 +0100 @@ -83,7 +83,7 @@ axes[i] = readw(vortex->io + VORTEX_AXD + i * sizeof(u32)); if (axes[i] == 0x1fff) axes[i] = -1; } - + return 0; } @@ -122,7 +122,7 @@ vortex->gameport.driver = vortex; vortex->gameport.fuzz = 64; - + vortex->gameport.read = vortex_read; vortex->gameport.trigger = vortex_trigger; vortex->gameport.cooked_read = vortex_cooked_read; @@ -145,7 +145,7 @@ vortex->io = vortex->base + id->driver_data; gameport_register_port(&vortex->gameport); - + printk(KERN_INFO "gameport at pci%s speed %d kHz\n", pci_name(dev), vortex->gameport.speed); --- diff/drivers/input/input.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/input.c 2004-05-27 18:34:16.000000000 +0100 @@ -106,7 +106,7 @@ } break; - + case EV_ABS: if (code > ABS_MAX || !test_bit(code, dev->absbit)) @@ -144,27 +144,27 @@ if (code > MSC_MAX || !test_bit(code, dev->mscbit)) return; - if (dev->event) dev->event(dev, type, code, value); - + if (dev->event) dev->event(dev, type, code, value); + break; case EV_LED: - + if (code > LED_MAX || !test_bit(code, dev->ledbit) || !!test_bit(code, dev->led) == value) return; change_bit(code, dev->led); - if (dev->event) dev->event(dev, type, code, value); - + if (dev->event) dev->event(dev, type, code, value); + break; case EV_SND: - + if (code > SND_MAX || !test_bit(code, dev->sndbit)) return; - if (dev->event) dev->event(dev, type, code, value); - + if (dev->event) dev->event(dev, type, code, value); + break; case EV_REP: @@ -181,7 +181,7 @@ break; } - if (type != EV_SYN) + if (type != EV_SYN) dev->sync = 0; if (dev->grab) @@ -282,11 +282,11 @@ if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR) if (id->id.vendor != dev->id.vendor) continue; - + if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT) if (id->id.product != dev->id.product) continue; - + if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION) if (id->id.version != dev->id.version) continue; @@ -351,11 +351,11 @@ } if (in_interrupt()) { printk(KERN_ERR "input.c: calling hotplug from interrupt\n"); - return; + return; } if (!current->fs->root) { printk(KERN_WARNING "input.c: calling hotplug without valid filesystem\n"); - return; + return; } if (!(envp = (char **) kmalloc(20 * sizeof(char *), GFP_KERNEL))) { printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n"); @@ -381,17 +381,17 @@ envp[i++] = scratch; scratch += sprintf(scratch, "PRODUCT=%x/%x/%x/%x", - dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version) + 1; - + dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version) + 1; + if (dev->name) { envp[i++] = scratch; - scratch += sprintf(scratch, "NAME=%s", dev->name) + 1; + scratch += sprintf(scratch, "NAME=%s", dev->name) + 1; } if (dev->phys) { envp[i++] = scratch; - scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1; - } + scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1; + } SPRINTF_BIT_A(evbit, "EV=", EV_MAX); SPRINTF_BIT_A2(keybit, "KEY=", KEY_MAX, EV_KEY); @@ -506,7 +506,7 @@ input_table[handler->minor >> 5] = handler; list_add_tail(&handler->node, &input_handler_list); - + list_for_each_entry(dev, &input_dev_list, node) if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) if ((id = input_match_device(handler->id_table, dev))) --- diff/drivers/input/joydev.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joydev.c 2004-05-27 18:34:16.000000000 +0100 @@ -1,12 +1,12 @@ /* * Joystick device driver for the input driver suite. * - * Copyright (c) 1999-2002 Vojtech Pavlik - * Copyright (c) 1999 Colin Van Dyke + * Copyright (c) 1999-2002 Vojtech Pavlik + * Copyright (c) 1999 Colin Van Dyke * * 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 + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ @@ -34,7 +34,7 @@ MODULE_LICENSE("GPL"); #define JOYDEV_MINOR_BASE 0 -#define JOYDEV_MINORS 16 +#define JOYDEV_MINORS 16 #define JOYDEV_BUFFER_SIZE 64 #define MSECS(t) (1000 * ((t) / HZ) + 1000 * ((t) % HZ) / HZ) @@ -115,7 +115,7 @@ default: return; - } + } event.time = MSECS(jiffies); @@ -449,10 +449,10 @@ } joydev_table[minor] = joydev; - + devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), S_IFCHR|S_IRUGO|S_IWUSR, "input/js%d", minor); - class_simple_device_add(input_class, + class_simple_device_add(input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), dev->dev, "js%d", minor); @@ -466,7 +466,7 @@ joydev->exist = 0; if (joydev->open) - input_close_device(handle); + input_close_device(handle); else joydev_free(joydev); } --- diff/drivers/input/joystick/Kconfig 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/Kconfig 2004-05-27 18:34:16.000000000 +0100 @@ -22,7 +22,7 @@ supports many extensions, including joysticks with throttle control, with rudders, additional hats and buttons compatible with CH Flightstick Pro, ThrustMaster FCS, 6 and 8 button gamepads, or - Saitek Cyborg joysticks. + Saitek Cyborg joysticks. Please read the file which contains more information. @@ -35,7 +35,7 @@ depends on INPUT && INPUT_JOYSTICK && GAMEPORT help Say Y here if you have an FPGaming or MadCatz controller using the - A3D protocol over the PC gameport. + A3D protocol over the PC gameport. To compile this driver as a module, choose M here: the module will be called a3d. @@ -45,7 +45,7 @@ depends on INPUT && INPUT_JOYSTICK && GAMEPORT help Say Y here if you have a Logitech controller using the ADI - protocol over the PC gameport. + protocol over the PC gameport. To compile this driver as a module, choose M here: the module will be called adi. @@ -74,7 +74,7 @@ depends on INPUT && INPUT_JOYSTICK && GAMEPORT help Say Y here if you have a Gravis controller using the GrIP protocol - over the PC gameport. + over the PC gameport. To compile this driver as a module, choose M here: the module will be called grip. @@ -94,7 +94,7 @@ depends on INPUT && INPUT_JOYSTICK && GAMEPORT help Say Y here if you have a Guillemot joystick using a digital - protocol over the PC gameport. + protocol over the PC gameport. To compile this driver as a module, choose M here: the module will be called guillemot. @@ -124,7 +124,7 @@ depends on INPUT && INPUT_JOYSTICK && GAMEPORT help Say Y here if you have a ThrustMaster controller using the - DirectConnect (BSP) protocol over the PC gameport. + DirectConnect (BSP) protocol over the PC gameport. To compile this driver as a module, choose M here: the module will be called tmdc. @@ -137,7 +137,7 @@ select SERIO help Say Y here if you have a Logitech WingMan Warrior joystick connected - to your computer's serial port. + to your computer's serial port. To compile this driver as a module, choose M here: the module will be called warrior. @@ -253,7 +253,7 @@ help Say Y here if you want to dump data from your joystick into the system log for debugging purposes. Say N if you are making a production - configuration or aren't sure. + configuration or aren't sure. To compile this driver as a module, choose M here: the module will be called joydump. --- diff/drivers/input/joystick/a3d.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/a3d.c 2004-05-27 18:34:16.000000000 +0100 @@ -39,8 +39,8 @@ MODULE_DESCRIPTION("FP-Gaming Assasin 3D joystick driver"); MODULE_LICENSE("GPL"); -#define A3D_MAX_START 400 /* 400 us */ -#define A3D_MAX_STROBE 60 /* 40 us */ +#define A3D_MAX_START 400 /* 400 us */ +#define A3D_MAX_STROBE 60 /* 40 us */ #define A3D_DELAY_READ 3 /* 3 ms */ #define A3D_MAX_LENGTH 40 /* 40*3 bits */ #define A3D_REFRESH_TIME HZ/50 /* 20 ms */ @@ -125,7 +125,7 @@ input_report_rel(dev, REL_X, ((data[5] << 6) | (data[6] << 3) | data[ 7]) - ((data[5] & 4) << 7)); input_report_rel(dev, REL_Y, ((data[8] << 6) | (data[9] << 3) | data[10]) - ((data[8] & 4) << 7)); - + input_report_key(dev, BTN_RIGHT, data[2] & 1); input_report_key(dev, BTN_LEFT, data[3] & 2); input_report_key(dev, BTN_MIDDLE, data[3] & 4); @@ -201,7 +201,7 @@ int i; for (i = 0; i < 4; i++) axes[i] = (a3d->axes[i] < 254) ? a3d->axes[i] : -1; - *buttons = a3d->buttons; + *buttons = a3d->buttons; return 0; } @@ -216,7 +216,7 @@ if (mode != GAMEPORT_MODE_COOKED) return -1; if (!a3d->used++) - mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME); + mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME); return 0; } @@ -239,7 +239,7 @@ { struct a3d *a3d = dev->private; if (!a3d->used++) - mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME); + mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME); return 0; } @@ -340,7 +340,7 @@ a3d->adc.open = a3d_adc_open; a3d->adc.close = a3d_adc_close; a3d->adc.cooked_read = a3d_adc_cooked_read; - a3d->adc.fuzz = 1; + a3d->adc.fuzz = 1; a3d->adc.name = a3d_names[a3d->mode]; a3d->adc.phys = a3d->adcphys; --- diff/drivers/input/joystick/adi.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/input/joystick/adi.c 2004-05-27 18:34:16.000000000 +0100 @@ -11,18 +11,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -72,8 +72,8 @@ */ static char *adi_names[] = { "WingMan Extreme Digital", "ThunderPad Digital", "SideCar", "CyberMan 2", - "WingMan Interceptor", "WingMan Formula", "WingMan GamePad", - "WingMan Extreme Digital 3D", "WingMan GamePad Extreme", + "WingMan Interceptor", "WingMan Formula", "WingMan GamePad", + "WingMan Extreme Digital 3D", "WingMan GamePad Extreme", "WingMan GamePad USB", "Unknown Device %#x" }; static char adi_wmgpe_abs[] = { ABS_X, ABS_Y, ABS_HAT0X, ABS_HAT0Y }; @@ -178,7 +178,7 @@ /* * adi_move_bits() detects a possible 2-stream mode, and moves - * the bits accordingly. + * the bits accordingly. */ static void adi_move_bits(struct adi_port *port, int length) @@ -208,7 +208,7 @@ int i; if ((adi->idx += count) > adi->ret) return 0; for (i = 0; i < count; i++) - bits |= ((adi->data[adi->idx - i] >> 5) & 1) << i; + bits |= ((adi->data[adi->idx - i] >> 5) & 1) << i; return bits; } @@ -224,12 +224,12 @@ int i, t; if (adi->ret < adi->length || adi->id != (adi_get_bits(adi, 4) | (adi_get_bits(adi, 4) << 4))) - return -1; + return -1; - for (i = 0; i < adi->axes10; i++) + for (i = 0; i < adi->axes10; i++) input_report_abs(dev, *abs++, adi_get_bits(adi, 10)); - for (i = 0; i < adi->axes8; i++) + for (i = 0; i < adi->axes8; i++) input_report_abs(dev, *abs++, adi_get_bits(adi, 8)); for (i = 0; i < adi->buttons && i < 63; i++) { @@ -249,7 +249,7 @@ for (i = 63; i < adi->buttons; i++) input_report_key(dev, *key++, adi_get_bits(adi, 1)); - + input_sync(dev); return 0; @@ -294,7 +294,7 @@ { struct adi_port *port = dev->private; if (!port->used++) - mod_timer(&port->timer, jiffies + ADI_REFRESH_TIME); + mod_timer(&port->timer, jiffies + ADI_REFRESH_TIME); return 0; } @@ -334,7 +334,7 @@ return; if (adi->ret < (t = adi_get_bits(adi, 10))) { - printk(KERN_WARNING "adi: Short ID packet: reported: %d != read: %d\n", t, adi->ret); + printk(KERN_WARNING "adi: Short ID packet: reported: %d != read: %d\n", t, adi->ret); return; } @@ -498,7 +498,7 @@ adi_init_digital(gameport); adi_read_packet(port); - + if (port->adi[0].ret >= ADI_MIN_LEN_LENGTH) adi_move_bits(port, adi_get_bits(port->adi, 10)); --- diff/drivers/input/joystick/amijoy.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/amijoy.c 2004-05-27 18:34:16.000000000 +0100 @@ -46,7 +46,7 @@ MODULE_LICENSE("GPL"); static int amijoy[2] = { 0, 1 }; -static int amijoy_nargs; +static int amijoy_nargs; module_param_array_named(map, amijoy, uint, amijoy_nargs, 0); MODULE_PARM_DESC(map, "Map of attached joysticks in form of , (default is 0,1)"); --- diff/drivers/input/joystick/analog.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/input/joystick/analog.c 2004-05-27 18:34:16.000000000 +0100 @@ -11,18 +11,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -237,7 +237,7 @@ loopout = (ANALOG_LOOP_TIME * port->loop) / 1000; timeout = ANALOG_MAX_TIME * port->speed; - + local_irq_save(flags); gameport_trigger(gameport); GET_TIME(now); @@ -284,7 +284,7 @@ u = gameport_read(port->gameport); - if (!chf) { + if (!chf) { port->buttons = (~u >> 4) & 0xf; return 0; } @@ -333,7 +333,7 @@ } } - for (i = 0; i < 2; i++) + for (i = 0; i < 2; i++) if (port->analog[i].mask) analog_decode(port->analog + i, port->axes, port->initial, port->buttons); @@ -348,7 +348,7 @@ { struct analog_port *port = dev->private; if (!port->used++) - mod_timer(&port->timer, jiffies + ANALOG_REFRESH_TIME); + mod_timer(&port->timer, jiffies + ANALOG_REFRESH_TIME); return 0; } @@ -408,7 +408,7 @@ static void analog_name(struct analog *analog) { - sprintf(analog->name, "Analog %d-axis %d-button", + sprintf(analog->name, "Analog %d-axis %d-button", hweight8(analog->mask & ANALOG_AXES_STD), hweight8(analog->mask & ANALOG_BTNS_STD) + !!(analog->mask & ANALOG_BTNS_CHF) * 2 + hweight16(analog->mask & ANALOG_BTNS_GAMEPAD) + !!(analog->mask & ANALOG_HBTN_CHF) * 4); @@ -450,10 +450,10 @@ analog->dev.close = analog_close; analog->dev.private = port; analog->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - + for (i = j = 0; i < 4; i++) if (analog->mask & (1 << i)) { - + t = analog_axes[j]; x = port->axes[i]; y = (port->axes[0] + port->axes[1]) >> 1; @@ -481,8 +481,8 @@ j++; } - for (i = j = 0; i < 3; i++) - if (analog->mask & analog_exts[i]) + for (i = j = 0; i < 3; i++) + if (analog->mask & analog_exts[i]) for (x = 0; x < 2; x++) { t = analog_hats[j++]; set_bit(t, analog->dev.absbit); @@ -517,7 +517,7 @@ else printk(" [%s timer, %d %sHz clock, %d ns res]\n", TIME_NAME, port->speed > 10000 ? (port->speed + 800) / 1000 : port->speed, - port->speed > 10000 ? "M" : "k", + port->speed > 10000 ? "M" : "k", port->speed > 10000 ? (port->loop * 1000) / (port->speed / 1000) : (port->loop * 1000000) / port->speed); } @@ -580,11 +580,11 @@ gameport_calibrate(port->gameport, port->axes, max); } - - for (i = 0; i < 4; i++) + + for (i = 0; i < 4; i++) port->initial[i] = port->axes[i]; - return -!(analog[0].mask || analog[1].mask); + return -!(analog[0].mask || analog[1].mask); } static int analog_init_port(struct gameport *gameport, struct gameport_dev *dev, struct analog_port *port) @@ -606,7 +606,7 @@ msleep(ANALOG_MAX_TIME); port->mask = (gameport_read(gameport) ^ t) & t & 0xf; port->fuzz = (port->speed * ANALOG_FUZZ_MAGIC) / port->loop / 1000 + ANALOG_FUZZ_BITS; - + for (i = 0; i < ANALOG_INIT_RETRIES; i++) { if (!analog_cooked_read(port)) break; msleep(ANALOG_MAX_TIME); @@ -617,11 +617,11 @@ msleep(ANALOG_MAX_TIME); t = gameport_time(gameport, ANALOG_MAX_TIME * 1000); gameport_trigger(gameport); - while ((gameport_read(port->gameport) & port->mask) && (u < t)) u++; + while ((gameport_read(port->gameport) & port->mask) && (u < t)) u++; udelay(ANALOG_SAITEK_DELAY); t = gameport_time(gameport, ANALOG_SAITEK_TIME); gameport_trigger(gameport); - while ((gameport_read(port->gameport) & port->mask) && (v < t)) v++; + while ((gameport_read(port->gameport) & port->mask) && (v < t)) v++; if (v < (u >> 1)) { /* FIXME - more than one port */ analog_options[0] |= /* FIXME - more than one port */ @@ -721,7 +721,7 @@ if (!strcmp(analog_types[j].name, js[i])) { analog_options[i] = analog_types[j].value; break; - } + } if (analog_types[j].name) continue; analog_options[i] = simple_strtoul(js[i], &end, 0); --- diff/drivers/input/joystick/cobra.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/cobra.c 2004-05-27 18:34:16.000000000 +0100 @@ -72,7 +72,7 @@ r[i] = buf[i] = 0; t[i] = COBRA_MAX_STROBE; } - + local_irq_save(flags); u = gameport_read(gameport); @@ -140,14 +140,14 @@ } - mod_timer(&cobra->timer, jiffies + COBRA_REFRESH_TIME); + mod_timer(&cobra->timer, jiffies + COBRA_REFRESH_TIME); } static int cobra_open(struct input_dev *dev) { struct cobra *cobra = dev->private; if (!cobra->used++) - mod_timer(&cobra->timer, jiffies + COBRA_REFRESH_TIME); + mod_timer(&cobra->timer, jiffies + COBRA_REFRESH_TIME); return 0; } @@ -180,7 +180,7 @@ cobra->exists = cobra_read_packet(gameport, data); - for (i = 0; i < 2; i++) + for (i = 0; i < 2; i++) if ((cobra->exists >> i) & data[i] & 1) { printk(KERN_WARNING "cobra.c: Device %d on %s has the Ext bit set. ID is: %d" " Contact vojtech@ucw.cz\n", i, gameport->phys, (data[i] >> 2) & 7); @@ -205,7 +205,7 @@ cobra->dev[i].id.vendor = GAMEPORT_ID_VENDOR_CREATIVE; cobra->dev[i].id.product = 0x0008; cobra->dev[i].id.version = 0x0100; - + cobra->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); cobra->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y); --- diff/drivers/input/joystick/db9.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/db9.c 2004-05-27 18:34:16.000000000 +0100 @@ -14,14 +14,14 @@ /* * 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 + * 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 @@ -95,7 +95,7 @@ struct db9 { struct input_dev dev[DB9_MAX_DEVICES]; struct timer_list timer; - struct pardevice *pd; + struct pardevice *pd; int mode; int used; char phys[2][32]; @@ -188,7 +188,7 @@ } /* - * db9_saturn_read_packet() reads whole saturn packet at connector + * db9_saturn_read_packet() reads whole saturn packet at connector * and returns device identifier code. */ static unsigned char db9_saturn_read_packet(struct parport *port, unsigned char *data, int type, int powered) @@ -481,16 +481,16 @@ input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1)); input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1)); - parport_write_control(port, 0x0a); + parport_write_control(port, 0x0a); - for (i = 0; i < 7; i++) { + for (i = 0; i < 7; i++) { data = parport_read_data(port); - parport_write_control(port, 0x02); - parport_write_control(port, 0x0a); + parport_write_control(port, 0x02); + parport_write_control(port, 0x0a); input_report_key(dev, db9_cd32_btn[i], ~data & DB9_FIRE2); } - parport_write_control(port, 0x00); + parport_write_control(port, 0x00); break; } @@ -600,7 +600,7 @@ db9->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); for (j = 0; j < db9_buttons[db9->mode]; j++) - set_bit(db9_btn[db9->mode][j], db9->dev[i].keybit); + set_bit(db9_btn[db9->mode][j], db9->dev[i].keybit); for (j = 0; j < db9_num_axis[db9->mode]; j++) { set_bit(db9_abs[j], db9->dev[i].absbit); if (j < 2) { @@ -635,7 +635,7 @@ { int i, j; - for (i = 0; i < 3; i++) + for (i = 0; i < 3; i++) if (db9_base[i]) { for (j = 0; j < min(db9_max_pads[db9_base[i]->mode], DB9_MAX_DEVICES); j++) input_unregister_device(db9_base[i]->dev + j); --- diff/drivers/input/joystick/gamecon.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/gamecon.c 2004-05-27 18:34:16.000000000 +0100 @@ -15,14 +15,14 @@ /* * 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 + * 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 @@ -70,13 +70,13 @@ #define GC_NES4 3 #define GC_MULTI 4 #define GC_MULTI2 5 -#define GC_N64 6 +#define GC_N64 6 #define GC_PSX 7 #define GC_MAX 7 #define GC_REFRESH_TIME HZ/100 - + struct gc { struct pardevice *pd; struct input_dev dev[5]; @@ -104,7 +104,7 @@ #define GC_N64_DELAY 133 /* delay between transmit request, and response ready (us) */ #define GC_N64_REQUEST 0x1dd1111111ULL /* the request data command (encoded for 000000011) */ #define GC_N64_DWS 3 /* delay between write segments (required for sound playback because of ISA DMA) */ - /* GC_N64_DWS > 24 is known to fail */ + /* GC_N64_DWS > 24 is known to fail */ #define GC_N64_POWER_W 0xe2 /* power during write (transmit request) */ #define GC_N64_POWER_R 0xfd /* power during read */ #define GC_N64_OUT 0x1d /* output bits to the 4 pads */ @@ -113,8 +113,8 @@ /* than 123 us */ #define GC_N64_CLOCK 0x02 /* clock bits for read */ -/* - * gc_n64_read_packet() reads an N64 packet. +/* + * gc_n64_read_packet() reads an N64 packet. * Each pad uses one bit per byte. So all pads connected to this port are read in parallel. */ @@ -224,7 +224,7 @@ * http://www.dim.com/~mackys/psxmemcard/ps-eng2.txt * http://www.gamesx.com/controldata/psxcont/psxcont.htm * ftp://milano.usal.es/pablo/ - * + * */ #define GC_PSX_DELAY 25 /* 25 usec */ @@ -331,13 +331,13 @@ s = gc_status_bit[i]; if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) { - + signed char axes[2]; axes[0] = axes[1] = 0; for (j = 0; j < 8; j++) { - if (data[23 - j] & s) axes[0] |= 1 << j; - if (data[31 - j] & s) axes[1] |= 1 << j; + if (data[23 - j] & s) axes[0] |= 1 << j; + if (data[31 - j] & s) axes[1] |= 1 << j; } input_report_abs(dev + i, ABS_X, axes[0]); @@ -588,7 +588,7 @@ break; case GC_PSX: - + psx = gc_psx_read_packet(gc, data); switch(psx) { @@ -629,7 +629,7 @@ } sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i); - + gc->dev[i].name = gc_names[config[i + 1]]; gc->dev[i].phys = gc->phys[i]; gc->dev[i].id.bustype = BUS_PARPORT; @@ -646,7 +646,7 @@ return NULL; } - for (i = 0; i < 5; i++) + for (i = 0; i < 5; i++) if (gc->pads[0] & gc_status_bit[i]) { input_register_device(gc->dev + i); printk(KERN_INFO "input: %s on %s\n", gc->dev[i].name, gc->pd->port->name); @@ -675,7 +675,7 @@ if (gc_base[i]) { for (j = 0; j < 5; j++) if (gc_base[i]->pads[0] & gc_status_bit[j]) - input_unregister_device(gc_base[i]->dev + j); + input_unregister_device(gc_base[i]->dev + j); parport_unregister_device(gc_base[i]->pd); } } --- diff/drivers/input/joystick/gf2k.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/input/joystick/gf2k.c 2004-05-27 18:34:16.000000000 +0100 @@ -11,18 +11,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -223,7 +223,7 @@ { struct gf2k *gf2k = dev->private; if (!gf2k->used++) - mod_timer(&gf2k->timer, jiffies + GF2K_REFRESH); + mod_timer(&gf2k->timer, jiffies + GF2K_REFRESH); return 0; } @@ -324,7 +324,7 @@ for (i = 0; i < gf2k_axes[gf2k->id]; i++) { gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 : - gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32; + gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32; gf2k->dev.absmin[gf2k_abs[i]] = 32; gf2k->dev.absfuzz[gf2k_abs[i]] = 8; gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0; --- diff/drivers/input/joystick/grip.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/grip.c 2004-05-27 18:34:16.000000000 +0100 @@ -48,8 +48,8 @@ #define GRIP_STROBE_GPP 200 /* 200 us */ #define GRIP_LENGTH_XT 4 #define GRIP_STROBE_XT 64 /* 64 us */ -#define GRIP_MAX_CHUNKS_XT 10 -#define GRIP_MAX_BITS_XT 30 +#define GRIP_MAX_CHUNKS_XT 10 +#define GRIP_MAX_BITS_XT 30 #define GRIP_REFRESH_TIME HZ/50 /* 20 ms */ @@ -153,7 +153,7 @@ buf = (buf << 1) | (u >> 1); t = strobe; i++; - } else + } else if ((((u ^ v) & (v ^ w)) >> 1) & ~(u | v | w) & 1) { if (i == 20) { --- diff/drivers/input/joystick/grip_mp.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/grip_mp.c 2004-05-27 18:34:16.000000000 +0100 @@ -69,7 +69,7 @@ #define IO_MODE_FAST 0x0200 /* Used 3 data bits per gameport read */ #define IO_SLOT_CHANGE 0x0800 /* Multiport physical slot status changed */ #define IO_DONE 0x1000 /* Multiport is done sending packets */ -#define IO_RETRY 0x4000 /* Try again later to get packet */ +#define IO_RETRY 0x4000 /* Try again later to get packet */ #define IO_RESET 0x8000 /* Force multiport to resend all packets */ /* @@ -144,8 +144,8 @@ /* * Gets a 28-bit packet from the multiport. * - * After getting a packet successfully, commands encoded by sendcode may - * be sent to the multiport. + * After getting a packet successfully, commands encoded by sendcode may + * be sent to the multiport. * * The multiport clock value is reflected in gameport bit B4. * @@ -169,7 +169,7 @@ *packet = 0; raw_data = gameport_read(gameport); - if (raw_data & 1) + if (raw_data & 1) return IO_RETRY; for (i = 0; i < 64; i++) { @@ -183,11 +183,11 @@ if (raw_data & 0x31) return IO_RESET; - gameport_trigger(gameport); + gameport_trigger(gameport); if (!poll_until(0x10, 0, 308, gameport, &raw_data)) return IO_RESET; - } else + } else return IO_RETRY; /* Determine packet transfer mode and prepare for packet construction. */ @@ -195,7 +195,7 @@ if (raw_data & 0x20) { /* 3 data bits/read */ portvals |= raw_data >> 4; /* Compare B4-B7 before & after trigger */ - if (portvals != 0xb) + if (portvals != 0xb) return 0; data_mask = 7; bits_per_read = 3; @@ -221,7 +221,7 @@ return IO_RESET; } - if (raw_data) + if (raw_data) return IO_RESET; /* If 3 bits/read used, drop from 30 bits to 28. */ @@ -231,7 +231,7 @@ pkt = (pkt >> 2) | 0xf0000000; } - if (bit_parity(pkt) == 1) + if (bit_parity(pkt) == 1) return IO_RESET; /* Acknowledge packet receipt */ @@ -251,10 +251,10 @@ /* Return if we just wanted the packet or multiport wants to send more */ - *packet = pkt; + *packet = pkt; if ((sendflags == 0) || ((sendflags & IO_RETRY) && !(pkt & PACKET_MP_DONE))) return IO_GOT_PACKET; - + if (pkt & PACKET_MP_MORE) return IO_GOT_PACKET | IO_RETRY; @@ -277,7 +277,7 @@ if (!poll_until(0x30, 0, 193, gameport, &raw_data)) return IO_GOT_PACKET | IO_RESET; - if (raw_data & 1) + if (raw_data & 1) return IO_GOT_PACKET | IO_RESET; if (sendcode & 1) @@ -429,19 +429,19 @@ strange_code = joytype; } } - return flags; + return flags; } /* * Returns true if all multiport slot states appear valid. */ - + static int slots_valid(struct grip_mp *grip) { int flags, slot, invalid = 0, active = 0; flags = get_and_decode_packet(grip, 0); - if (!(flags & IO_GOT_PACKET)) + if (!(flags & IO_GOT_PACKET)) return 0; for (slot = 0; slot < 4; slot++) { @@ -463,7 +463,7 @@ * Returns whether the multiport was placed into digital mode and * able to communicate its state successfully. */ - + static int multiport_init(struct grip_mp *grip) { int dig_mode, initialized = 0, tries = 0; @@ -481,7 +481,7 @@ dbg("multiport_init(): unable to achieve digital mode.\n"); return 0; } - + /* Get packets, store multiport state, and check state's validity */ for (tries = 0; tries < 4096; tries++) { if ( slots_valid(grip) ) { @@ -520,9 +520,9 @@ } /* - * Get the multiport state. + * Get the multiport state. */ - + static void get_and_report_mp_state(struct grip_mp *grip) { int i, npkts, flags; @@ -538,7 +538,7 @@ break; } - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) if (grip->dirty[i]) report_slot(grip, i); } @@ -546,7 +546,7 @@ /* * Called when a joystick device file is opened */ - + static int grip_open(struct input_dev *dev) { struct grip_mp *grip = dev->private; @@ -607,7 +607,7 @@ /* * Repeatedly polls the multiport and generates events. */ - + static void grip_timer(unsigned long private) { struct grip_mp *grip = (void*) private; --- diff/drivers/input/joystick/guillemot.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/guillemot.c 2004-05-27 18:34:16.000000000 +0100 @@ -45,7 +45,7 @@ #define GUILLEMOT_MAX_LENGTH 17 /* 17 bytes */ #define GUILLEMOT_REFRESH_TIME HZ/50 /* 20 ms */ -static short guillemot_abs_pad[] = +static short guillemot_abs_pad[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, -1 }; static short guillemot_btn_pad[] = @@ -160,7 +160,7 @@ { struct guillemot *guillemot = dev->private; if (!guillemot->used++) - mod_timer(&guillemot->timer, jiffies + GUILLEMOT_REFRESH_TIME); + mod_timer(&guillemot->timer, jiffies + GUILLEMOT_REFRESH_TIME); return 0; } @@ -211,7 +211,7 @@ if (!guillemot_type[i].name) { printk(KERN_WARNING "guillemot.c: Unknown joystick on %s. [ %02x%02x:%04x, ver %d.%02d ]\n", gameport->phys, data[12], data[13], data[11], data[14], data[15]); - goto fail2; + goto fail2; } sprintf(guillemot->phys, "%s/input0", gameport->phys); @@ -237,7 +237,7 @@ guillemot->dev.absmax[t] = 255; } - if (guillemot->type->hat) + if (guillemot->type->hat) for (i = 0; i < 2; i++) { t = ABS_HAT0X + i; set_bit(t, guillemot->dev.absbit); --- diff/drivers/input/joystick/iforce/Kconfig 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/iforce/Kconfig 2004-05-27 18:34:16.000000000 +0100 @@ -17,7 +17,7 @@ depends on JOYSTICK_IFORCE && (JOYSTICK_IFORCE=m || USB=y) && USB help Say Y here if you have an I-Force joystick or steering wheel - connected to your USB port. + connected to your USB port. config JOYSTICK_IFORCE_232 bool "I-Force Serial joysticks and wheels" --- diff/drivers/input/joystick/iforce/Makefile 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/iforce/Makefile 2004-05-27 18:34:16.000000000 +0100 @@ -7,14 +7,14 @@ # Goal definition iforce-objs := iforce-ff.o iforce-main.o iforce-packets.o -obj-$(CONFIG_JOYSTICK_IFORCE) += iforce.o +obj-$(CONFIG_JOYSTICK_IFORCE) += iforce.o ifeq ($(CONFIG_JOYSTICK_IFORCE_232),y) - iforce-objs += iforce-serio.o + iforce-objs += iforce-serio.o endif ifeq ($(CONFIG_JOYSTICK_IFORCE_USB),y) - iforce-objs += iforce-usb.o + iforce-objs += iforce-usb.o endif EXTRA_CFLAGS = -Werror-implicit-function-declaration --- diff/drivers/input/joystick/iforce/iforce-ff.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/iforce/iforce-ff.c 2004-05-27 18:34:16.000000000 +0100 @@ -195,7 +195,7 @@ } /* - * Analyse the changes in an effect, and tell if we need to send an condition + * Analyse the changes in an effect, and tell if we need to send an condition * parameter packet */ static int need_condition_modifier(struct iforce* iforce, struct ff_effect* new) @@ -372,7 +372,7 @@ int core_err = 0; if (!is_update || need_period_modifier(iforce, effect)) { - param1_err = make_period_modifier(iforce, mod1_chunk, + param1_err = make_period_modifier(iforce, mod1_chunk, is_update, effect->u.periodic.magnitude, effect->u.periodic.offset, effect->u.periodic.period, effect->u.periodic.phase); --- diff/drivers/input/joystick/iforce/iforce-main.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/iforce/iforce-main.c 2004-05-27 18:34:16.000000000 +0100 @@ -166,7 +166,7 @@ else { /* We want to update an effect */ if (!CHECK_OWNERSHIP(effect->id, iforce)) return -EACCES; - + /* Parameter type cannot be updated */ if (effect->type != iforce->core_effects[effect->id].effect.type) return -EINVAL; @@ -273,7 +273,7 @@ if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) && current->pid == iforce->core_effects[i].owner) { - + /* Stop effect */ input_report_ff(dev, i, 0); --- diff/drivers/input/joystick/iforce/iforce-packets.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/iforce/iforce-packets.c 2004-05-27 18:34:16.000000000 +0100 @@ -56,7 +56,7 @@ int empty; int head, tail; unsigned long flags; - + /* * Update head and tail of xmit buffer */ @@ -108,7 +108,7 @@ break; #endif #ifdef CONFIG_JOYSTICK_IFORCE_USB - case IFORCE_USB: + case IFORCE_USB: if (iforce->usbdev && empty && !test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)) { --- diff/drivers/input/joystick/iforce/iforce-serio.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/iforce/iforce-serio.c 2004-05-27 18:34:16.000000000 +0100 @@ -62,7 +62,7 @@ cs ^= iforce->xmit.buf[iforce->xmit.tail]; XMIT_INC(iforce->xmit.tail, 1); } - + serio_write(iforce->serio, cs); if (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags)) --- diff/drivers/input/joystick/iforce/iforce.h 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/iforce/iforce.h 2004-05-27 18:34:16.000000000 +0100 @@ -141,7 +141,7 @@ struct circ_buf xmit; unsigned char xmit_data[XMIT_SIZE]; long xmit_flags[1]; - + /* Force Feedback */ wait_queue_head_t wait; struct resource device_memory; --- diff/drivers/input/joystick/interact.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/interact.c 2004-05-27 18:34:16.000000000 +0100 @@ -63,7 +63,7 @@ char phys[32]; }; -static short interact_abs_hhfx[] = +static short interact_abs_hhfx[] = { ABS_RX, ABS_RY, ABS_X, ABS_Y, ABS_HAT0X, ABS_HAT0Y, -1 }; static short interact_abs_pp8d[] = { ABS_X, ABS_Y, -1 }; @@ -166,7 +166,7 @@ case INTERACT_TYPE_PP8D: for (i = 0; i < 2; i++) - input_report_abs(dev, interact_abs_pp8d[i], + input_report_abs(dev, interact_abs_pp8d[i], ((data[0] >> ((i << 1) + 20)) & 1) - ((data[0] >> ((i << 1) + 21)) & 1)); for (i = 0; i < 8; i++) @@ -190,7 +190,7 @@ { struct interact *interact = dev->private; if (!interact->used++) - mod_timer(&interact->timer, jiffies + INTERACT_REFRESH_TIME); + mod_timer(&interact->timer, jiffies + INTERACT_REFRESH_TIME); return 0; } @@ -242,7 +242,7 @@ if (!interact_type[i].length) { printk(KERN_WARNING "interact.c: Unknown joystick on %s. [len %d d0 %08x d1 %08x i2 %08x]\n", gameport->phys, i, data[0], data[1], data[2]); - goto fail2; + goto fail2; } sprintf(interact->phys, "%s/input0", gameport->phys); --- diff/drivers/input/joystick/joydump.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/joydump.c 2004-05-27 18:34:16.000000000 +0100 @@ -12,18 +12,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -63,7 +63,7 @@ printk(KERN_INFO "joydump: | Raw mode not available - trying cooked. |\n"); if (gameport_open(gameport, dev, GAMEPORT_MODE_COOKED)) { - + printk(KERN_INFO "joydump: | Cooked not available either. Failing. |\n"); printk(KERN_INFO "joydump: `-------------------- END -------------------'\n"); return; --- diff/drivers/input/joystick/magellan.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/magellan.c 2004-05-27 18:34:16.000000000 +0100 @@ -11,18 +11,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -159,7 +159,7 @@ memset(magellan, 0, sizeof(struct magellan)); - magellan->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + magellan->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); for (i = 0; i < 9; i++) set_bit(magellan_buttons[i], magellan->dev.keybit); @@ -181,7 +181,7 @@ magellan->dev.id.vendor = SERIO_MAGELLAN; magellan->dev.id.product = 0x0001; magellan->dev.id.version = 0x0100; - + serio->private = magellan; if (serio_open(serio, dev)) { --- diff/drivers/input/joystick/sidewinder.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/sidewinder.c 2004-05-27 18:34:16.000000000 +0100 @@ -11,18 +11,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -176,19 +176,19 @@ buf[i] = v >> 5; /* Store it */ i++; /* Advance index */ bitout = strobe; /* Extend timeout for next bit */ - } + } if (kick && (~v & u & 0x01)) { /* Falling edge on axis 0 */ sched = kick; /* Schedule second trigger */ kick = 0; /* Don't schedule next time on falling edge */ pending = 1; /* Mark schedule */ - } + } if (pending && sched < 0 && (i > -SW_END)) { /* Second trigger time */ gameport_trigger(gameport); /* Trigger */ bitout = start; /* Long bit timeout */ pending = 0; /* Unmark schedule */ - timeout = 0; /* Switch from global to bit timeouts */ + timeout = 0; /* Switch from global to bit timeouts */ } } @@ -482,14 +482,14 @@ sw_read_packet(sw->gameport, buf, SW_LENGTH, i); /* Read ID packet, this initializes the stick */ sw->fail = SW_FAIL; - + return -1; } static void sw_timer(unsigned long private) { struct sw *sw = (void *) private; - + sw->reads++; if (sw_read(sw)) sw->bads++; mod_timer(&sw->timer, jiffies + SW_REFRESH); @@ -653,7 +653,7 @@ case 60: sw->number++; case 45: /* Ambiguous packet length */ - if (j <= 40) { /* ID length less or eq 40 -> FSP */ + if (j <= 40) { /* ID length less or eq 40 -> FSP */ case 43: sw->type = SW_ID_FSP; break; --- diff/drivers/input/joystick/spaceball.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/spaceball.c 2004-05-27 18:34:16.000000000 +0100 @@ -15,18 +15,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -59,8 +59,8 @@ static int spaceball_axes[] = { ABS_X, ABS_Z, ABS_Y, ABS_RX, ABS_RZ, ABS_RY }; static char *spaceball_names[] = { - "?", "SpaceTec SpaceBall 1003", "SpaceTec SpaceBall 2003", "SpaceTec SpaceBall 2003B", - "SpaceTec SpaceBall 2003C", "SpaceTec SpaceBall 3003", "SpaceTec SpaceBall SpaceController", + "?", "SpaceTec SpaceBall 1003", "SpaceTec SpaceBall 2003", "SpaceTec SpaceBall 2003B", + "SpaceTec SpaceBall 2003C", "SpaceTec SpaceBall 3003", "SpaceTec SpaceBall SpaceController", "SpaceTec SpaceBall 3003C", "SpaceTec SpaceBall 4000FLX", "SpaceTec SpaceBall 4000FLX Lefty" }; /* @@ -96,7 +96,7 @@ case 'D': /* Ball data */ if (spaceball->idx != 15) return; for (i = 0; i < 6; i++) - input_report_abs(dev, spaceball_axes[i], + input_report_abs(dev, spaceball_axes[i], (__s16)((data[2 * i + 3] << 8) | data[2 * i + 2])); break; @@ -216,7 +216,7 @@ return; memset(spaceball, 0, sizeof(struct spaceball)); - spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); switch (id) { case SPACEBALL_4000FLX: @@ -224,7 +224,7 @@ spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_9); spaceball->dev.keybit[LONG(BTN_A)] |= BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_MODE); default: - spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) + spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7) | BIT(BTN_8); case SPACEBALL_3003C: spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_1) | BIT(BTN_8); @@ -251,7 +251,7 @@ spaceball->dev.id.vendor = SERIO_SPACEBALL; spaceball->dev.id.product = id; spaceball->dev.id.version = 0x0100; - + serio->private = spaceball; if (serio_open(serio, dev)) { --- diff/drivers/input/joystick/spaceorb.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/spaceorb.c 2004-05-27 18:34:16.000000000 +0100 @@ -2,7 +2,7 @@ * $Id: spaceorb.c,v 1.15 2002/01/22 20:29:19 vojtech Exp $ * * Copyright (c) 1999-2001 Vojtech Pavlik - * + * * Based on the work of: * David Thompson */ @@ -14,18 +14,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -67,7 +67,7 @@ static unsigned char spaceorb_xor[] = "SpaceWare"; static unsigned char *spaceorb_errors[] = { "EEPROM storing 0 failed", "Receive queue overflow", "Transmit queue timeout", - "Bad packet", "Power brown-out", "EEPROM checksum error", "Hardware fault" }; + "Bad packet", "Power brown-out", "EEPROM checksum error", "Hardware fault" }; /* * spaceorb_process_packet() decodes packets the driver receives from the @@ -99,7 +99,7 @@ case 'D': /* Ball + button data */ if (spaceorb->idx != 12) return; - for (i = 0; i < 9; i++) spaceorb->data[i+2] ^= spaceorb_xor[i]; + for (i = 0; i < 9; i++) spaceorb->data[i+2] ^= spaceorb_xor[i]; axes[0] = ( data[2] << 3) | (data[ 3] >> 4); axes[1] = ((data[3] & 0x0f) << 6) | (data[ 4] >> 1); axes[2] = ((data[4] & 0x01) << 9) | (data[ 5] << 2) | (data[4] >> 5); @@ -174,7 +174,7 @@ return; memset(spaceorb, 0, sizeof(struct spaceorb)); - spaceorb->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + spaceorb->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); for (i = 0; i < 6; i++) set_bit(spaceorb_buttons[i], spaceorb->dev.keybit); @@ -198,7 +198,7 @@ spaceorb->dev.id.vendor = SERIO_SPACEORB; spaceorb->dev.id.product = 0x0001; spaceorb->dev.id.version = 0x0100; - + serio->private = spaceorb; if (serio_open(serio, dev)) { --- diff/drivers/input/joystick/stinger.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/stinger.c 2004-05-27 18:34:16.000000000 +0100 @@ -147,7 +147,7 @@ memset(stinger, 0, sizeof(struct stinger)); - stinger->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + stinger->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); stinger->dev.keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) | \ BIT(BTN_Y) | BIT(BTN_Z) | BIT(BTN_TL) | BIT(BTN_TR) | \ BIT(BTN_START) | BIT(BTN_SELECT); @@ -164,8 +164,8 @@ stinger->dev.id.version = 0x0100; for (i = 0; i < 2; i++) { - stinger->dev.absmax[ABS_X+i] = 64; - stinger->dev.absmin[ABS_X+i] = -64; + stinger->dev.absmax[ABS_X+i] = 64; + stinger->dev.absmin[ABS_X+i] = -64; stinger->dev.absflat[ABS_X+i] = 4; } --- diff/drivers/input/joystick/tmdc.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/tmdc.c 2004-05-27 18:34:16.000000000 +0100 @@ -4,7 +4,7 @@ * Copyright (c) 1998-2001 Vojtech Pavlik * * Based on the work of: - * Trystan Larey-Williams + * Trystan Larey-Williams */ /* @@ -14,18 +14,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -58,7 +58,7 @@ #define TMDC_BYTE_REV 11 #define TMDC_BYTE_DEF 12 -#define TMDC_ABS 7 +#define TMDC_ABS 7 #define TMDC_ABS_HAT 4 #define TMDC_BTN 16 @@ -104,7 +104,7 @@ unsigned char btno[2][4]; int used; int reads; - int bads; + int bads; unsigned char exists; }; @@ -127,7 +127,7 @@ local_irq_save(flags); gameport_trigger(gameport); - + w = gameport_read(gameport) >> 4; do { @@ -148,7 +148,7 @@ } data[k][i[k]] |= (~v & 1) << (j[k]++ - 1); /* Data bit */ } - t[k]--; + t[k]--; } } while (t[0] > 0 || t[1] > 0); @@ -175,7 +175,7 @@ bad = 1; else - for (j = 0; j < 2; j++) + for (j = 0; j < 2; j++) if (r & (1 << j) & tmdc->exists) { if (data[j][TMDC_BYTE_ID] != tmdc->mode[j]) { @@ -227,7 +227,7 @@ { struct tmdc *tmdc = dev->private; if (!tmdc->used++) - mod_timer(&tmdc->timer, jiffies + TMDC_REFRESH_TIME); + mod_timer(&tmdc->timer, jiffies + TMDC_REFRESH_TIME); return 0; } @@ -356,7 +356,7 @@ struct tmdc *tmdc = gameport->private; int i; for (i = 0; i < 2; i++) - if (tmdc->exists & (1 << i)) + if (tmdc->exists & (1 << i)) input_unregister_device(tmdc->dev + i); gameport_close(gameport); kfree(tmdc); --- diff/drivers/input/joystick/turbografx.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/turbografx.c 2004-05-27 18:34:16.000000000 +0100 @@ -14,18 +14,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -65,7 +65,7 @@ #define TGFX_TRIGGER 0x08 #define TGFX_UP 0x10 -#define TGFX_DOWN 0x20 +#define TGFX_DOWN 0x20 #define TGFX_LEFT 0x40 #define TGFX_RIGHT 0x80 @@ -126,7 +126,7 @@ if (!tgfx->used++) { parport_claim(tgfx->pd); parport_write_control(tgfx->pd->port, 0x04); - mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); + mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); } return 0; } @@ -173,7 +173,7 @@ memset(tgfx, 0, sizeof(struct tgfx)); tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); - + parport_put_port(pp); if (!tgfx->pd) { @@ -210,7 +210,7 @@ tgfx->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y); for (j = 0; j < config[i+1]; j++) - set_bit(tgfx_buttons[j], tgfx->dev[i].keybit); + set_bit(tgfx_buttons[j], tgfx->dev[i].keybit); tgfx->dev[i].absmin[ABS_X] = -1; tgfx->dev[i].absmax[ABS_X] = 1; tgfx->dev[i].absmin[ABS_Y] = -1; tgfx->dev[i].absmax[ABS_Y] = 1; @@ -225,7 +225,7 @@ kfree(tgfx); return NULL; } - + return tgfx; } @@ -245,7 +245,7 @@ { int i, j; - for (i = 0; i < 3; i++) + for (i = 0; i < 3; i++) if (tgfx_base[i]) { for (j = 0; j < 7; j++) if (tgfx_base[i]->sticks & (1 << j)) --- diff/drivers/input/joystick/twidjoy.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/twidjoy.c 2004-05-27 18:34:16.000000000 +0100 @@ -58,6 +58,9 @@ #include #include +MODULE_DESCRIPTION("Handykey Twiddler keyboard as a joystick driver"); +MODULE_LICENSE("GPL"); + /* * Constants. */ @@ -142,7 +145,7 @@ * packet processing routine. */ -static void twidjoy_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struc pt_regs *regs) +static irqreturn_t twidjoy_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs) { struct twidjoy *twidjoy = serio->private; @@ -153,7 +156,7 @@ if ((data & 0x80) == 0) twidjoy->idx = 0; /* this byte starts a new packet */ else if (twidjoy->idx == 0) - return; /* wrong MSB -- ignore this byte */ + return IRQ_HANDLED; /* wrong MSB -- ignore this byte */ if (twidjoy->idx < TWIDJOY_MAX_LENGTH) twidjoy->data[twidjoy->idx++] = data; @@ -163,7 +166,7 @@ twidjoy->idx = 0; } - return; + return IRQ_HANDLED; } /* @@ -208,7 +211,7 @@ twidjoy->dev.id.product = 0x0001; twidjoy->dev.id.version = 0x0100; - twidjoy->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + twidjoy->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); for (bp = twidjoy_buttons; bp->bitmask; bp++) { for (i = 0; i < bp->bitmask; i++) @@ -218,8 +221,8 @@ twidjoy->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); for (i = 0; i < 2; i++) { - twidjoy->dev.absmax[ABS_X+i] = 50; - twidjoy->dev.absmin[ABS_X+i] = -50; + twidjoy->dev.absmax[ABS_X+i] = 50; + twidjoy->dev.absmin[ABS_X+i] = -50; /* TODO: arndt 20010708: Are these values appropriate? */ twidjoy->dev.absfuzz[ABS_X+i] = 4; --- diff/drivers/input/joystick/warrior.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/joystick/warrior.c 2004-05-27 18:34:16.000000000 +0100 @@ -11,18 +11,18 @@ /* * This program is free warftware; 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -44,7 +44,7 @@ */ #define WARRIOR_MAX_LENGTH 16 -static char warrior_lengths[] = { 0, 4, 12, 3, 4, 4, 0, 0 }; +static char warrior_lengths[] = { 0, 4, 12, 3, 4, 4, 0, 0 }; static char *warrior_name = "Logitech WingMan Warrior"; /* @@ -114,7 +114,7 @@ warrior->data[warrior->idx++] = data; if (warrior->idx == warrior->len) { - if (warrior->idx) warrior_process_packet(warrior, regs); + if (warrior->idx) warrior_process_packet(warrior, regs); warrior->idx = 0; warrior->len = 0; } @@ -152,7 +152,7 @@ memset(warrior, 0, sizeof(struct warrior)); - warrior->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS); + warrior->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS); warrior->dev.keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2); warrior->dev.relbit[0] = BIT(REL_DIAL); warrior->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y); @@ -168,24 +168,24 @@ warrior->dev.id.version = 0x0100; for (i = 0; i < 2; i++) { - warrior->dev.absmax[ABS_X+i] = -64; - warrior->dev.absmin[ABS_X+i] = 64; - warrior->dev.absflat[ABS_X+i] = 8; + warrior->dev.absmax[ABS_X+i] = -64; + warrior->dev.absmin[ABS_X+i] = 64; + warrior->dev.absflat[ABS_X+i] = 8; } - warrior->dev.absmax[ABS_THROTTLE] = -112; - warrior->dev.absmin[ABS_THROTTLE] = 112; + warrior->dev.absmax[ABS_THROTTLE] = -112; + warrior->dev.absmin[ABS_THROTTLE] = 112; for (i = 0; i < 2; i++) { - warrior->dev.absmax[ABS_HAT0X+i] = -1; - warrior->dev.absmin[ABS_HAT0X+i] = 1; + warrior->dev.absmax[ABS_HAT0X+i] = -1; + warrior->dev.absmin[ABS_HAT0X+i] = 1; } warrior->dev.private = warrior; - + serio->private = warrior; - if (serio_open(serio, dev)) { + if (serio_open(serio, dev)) { kfree(warrior); return; } --- diff/drivers/input/keyboard/98kbd.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/keyboard/98kbd.c 2004-05-27 18:34:16.000000000 +0100 @@ -12,18 +12,18 @@ /* * 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 + * 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 - * + * */ #include @@ -43,7 +43,7 @@ #define KBD98_KEY 0x7f #define KBD98_RELEASE 0x80 -static unsigned char kbd98_keycode[256] = { +static unsigned char kbd98_keycode[256] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 43, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 41, 26, 28, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 27, 44, 45, 46, 47, 48, 49, 50, @@ -109,8 +109,8 @@ struct jis_kbd_conv jis[16]; }; -void kbd98_interrupt(struct serio *serio, unsigned char data, - unsigned int flags, struct pt_regs *regs) +irqreturn_t kbd98_interrupt(struct serio *serio, unsigned char data, + unsigned int flags, struct pt_regs *regs) { struct kbd98 *kbd98 = serio->private; unsigned char scancode, keycode; @@ -119,15 +119,15 @@ switch (data) { case KBD98_RET_ACK: kbd98->ack = 1; - return; + goto out; case KBD98_RET_NAK: kbd98->ack = -1; - return; + goto out; } if (kbd98->cmdcnt) { kbd98->cmdbuf[--kbd98->cmdcnt] = data; - return; + goto out; } scancode = data & KBD98_KEY; @@ -164,7 +164,7 @@ keycode = kbd98->jis[i].emul[kbd98->shift].keycode; if (keycode == KBD98_KEY_NULL) - return; + break; if (press) { kbd98->emul.scancode = scancode; @@ -187,27 +187,31 @@ } input_sync(&kbd98->dev); - return; + break; case KEY_CAPSLOCK: input_report_key(&kbd98->dev, keycode, 1); input_sync(&kbd98->dev); input_report_key(&kbd98->dev, keycode, 0); input_sync(&kbd98->dev); - return; + break; case KBD98_KEY_NULL: - return; + break; case 0: printk(KERN_WARNING "kbd98.c: Unknown key (scancode %#x) %s.\n", data & KBD98_KEY, data & KBD98_RELEASE ? "released" : "pressed"); - return; + break; default: input_report_key(&kbd98->dev, keycode, press); input_sync(&kbd98->dev); - } + break; + } + +out: + return IRQ_HANDLED; } /* @@ -243,7 +247,7 @@ int i; kbd98->cmdcnt = receive; - + if (command & 0xff) if (kbd98_sendbyte(kbd98, command & 0xff)) return (kbd98->cmdcnt = 0) - 1; @@ -258,7 +262,7 @@ for (i = 0; i < receive; i++) param[i] = kbd98->cmdbuf[(receive - 1) - i]; - if (kbd98->cmdcnt) + if (kbd98->cmdcnt) return (kbd98->cmdcnt = 0) - 1; return 0; @@ -318,7 +322,7 @@ memset(kbd98, 0, sizeof(struct kbd98)); kbd98->emul.scancode = KBD98_KEY_UNKNOWN; - + kbd98->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); kbd98->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_KANA); --- diff/drivers/input/keyboard/Kconfig 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/keyboard/Kconfig 2004-05-27 18:34:16.000000000 +0100 @@ -62,7 +62,7 @@ Say Y here if you want to use the old IBM PC/XT keyboard (or compatible) on your system. This is only possible with a parallel port keyboard adapter, you cannot connect it to the - keyboard port on a PC that runs Linux. + keyboard port on a PC that runs Linux. To compile this driver as a module, choose M here: the module will be called xtkbd. @@ -92,19 +92,7 @@ depends on AMIGA && INPUT && INPUT_KEYBOARD help Say Y here if you are running Linux on any AMIGA and have a keyboard - attached. + attached. To compile this driver as a module, choose M here: the module will be called amikbd. - -config KEYBOARD_98KBD - tristate "NEC PC-9800 Keyboard support" - depends on X86_PC9800 && INPUT && INPUT_KEYBOARD - select SERIO - help - Say Y here if you want to use the NEC PC-9801/PC-9821 keyboard (or - compatible) on your system. - - To compile this driver as a module, choose M here: the - module will be called 98kbd. - --- diff/drivers/input/keyboard/atkbd.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/keyboard/atkbd.c 2004-05-27 18:34:16.000000000 +0100 @@ -26,7 +26,6 @@ #include #include #include -#include MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("AT and PS/2 keyboard driver"); @@ -81,13 +80,13 @@ 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125, - 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127, + 217,100,255, 0, 97,165,172, 0,156, 0, 0, 0, 0, 0,187,125, + 173,114, 0,113, 0, 0,189,126,128, 0, 0,140, 0, 0, 0,127, 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142, 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0, 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112, - 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0, + 110,111,108,112,106,103,171,119, 0,118,109, 0, 99,104,119, 0, 0, 0, 0, 65, 99, }; @@ -173,22 +172,24 @@ unsigned char keycode[512]; struct input_dev dev; struct serio *serio; - struct timer_list timer; + char name[64]; char phys[32]; + unsigned short id; + unsigned char set; + unsigned int translated:1; + unsigned int extra:1; + unsigned int write:1; + unsigned char cmdbuf[4]; unsigned char cmdcnt; - unsigned char set; - unsigned char extra; - unsigned char release; - int lastkey; volatile signed char ack; unsigned char emul; - unsigned short id; - unsigned char write; - unsigned char translated; - unsigned char resend; - unsigned char bat_xl; + unsigned int resend:1; + unsigned int release:1; + unsigned int bat_xl:1; + unsigned int enabled:1; + unsigned int last; unsigned long time; }; @@ -243,11 +244,14 @@ goto out; } - if (atkbd->cmdcnt) { + if (atkbd->cmdcnt && atkbd->ack == 1) { atkbd->cmdbuf[--atkbd->cmdcnt] = code; goto out; } + if (!atkbd->enabled) + goto out; + if (atkbd->translated) { if (atkbd->emul || @@ -300,15 +304,20 @@ case ATKBD_KEY_NULL: break; case ATKBD_KEY_UNKNOWN: - printk(KERN_WARNING "atkbd.c: Unknown key %s (%s set %d, code %#x on %s).\n", - atkbd->release ? "released" : "pressed", - atkbd->translated ? "translated" : "raw", - atkbd->set, code, serio->phys); - if (atkbd->translated && atkbd->set == 2 && code == 0x7a) - printk(KERN_WARNING "atkbd.c: This is an XFree86 bug. It shouldn't access" - " hardware directly.\n"); - else - printk(KERN_WARNING "atkbd.c: Use 'setkeycodes %s%02x ' to make it known.\n", code & 0x80 ? "e0" : "", code & 0x7f); + if (data == ATKBD_RET_ACK || data == ATKBD_RET_NAK) { + printk(KERN_WARNING "atkbd.c: Spurious %s on %s. Some program, " + "like XFree86, might be trying access hardware directly.\n", + data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); + } else { + printk(KERN_WARNING "atkbd.c: Unknown key %s " + "(%s set %d, code %#x on %s).\n", + atkbd->release ? "released" : "pressed", + atkbd->translated ? "translated" : "raw", + atkbd->set, code, serio->phys); + printk(KERN_WARNING "atkbd.c: Use 'setkeycodes %s%02x ' " + "to make it known.\n", + code & 0x80 ? "e0" : "", code & 0x7f); + } break; case ATKBD_SCR_1: scroll = 1 - atkbd->release * 2; @@ -365,10 +374,12 @@ * replacement anyway, and they only make a mess in the protocol. */ -static int atkbd_sendbyte(struct atkbd *atkbd, unsigned char byte) +static int atkbd_sendbyte(struct atkbd *atkbd, unsigned char byte, int cmdcnt) { int timeout = 20000; /* 200 msec */ atkbd->ack = 0; + wmb(); /* First clear ACK, then write how many reply bytes we want... though maybe it would want real spinlock */ + atkbd->cmdcnt = cmdcnt; #ifdef ATKBD_DEBUG printk(KERN_DEBUG "atkbd.c: Sent: %02x\n", byte); @@ -393,8 +404,6 @@ int receive = (command >> 8) & 0xf; int i; - atkbd->cmdcnt = receive; - if (command == ATKBD_CMD_RESET_BAT) timeout = 2000000; /* 2 sec */ @@ -403,11 +412,11 @@ atkbd->cmdbuf[(receive - 1) - i] = param[i]; if (command & 0xff) - if (atkbd_sendbyte(atkbd, command & 0xff)) + if (atkbd_sendbyte(atkbd, command & 0xff, send ? 0 : receive)) return (atkbd->cmdcnt = 0) - 1; for (i = 0; i < send; i++) - if (atkbd_sendbyte(atkbd, param[i])) + if (atkbd_sendbyte(atkbd, param[i], (i != send - 1) ? 0 : receive)) return (atkbd->cmdcnt = 0) - 1; while (atkbd->cmdcnt && timeout--) { @@ -745,6 +754,8 @@ atkbd->id = 0xab00; } + atkbd->enabled = 1; + if (atkbd->extra) { atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) | BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC); sprintf(atkbd->name, "AT Set 2 Extra keyboard"); @@ -809,12 +820,12 @@ param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0) | (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0) | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0); - + if (atkbd_probe(atkbd)) return -1; if (atkbd->set != atkbd_set_3(atkbd)) return -1; - + atkbd_enable(atkbd); if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS)) --- diff/drivers/input/keyboard/maple_keyb.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/keyboard/maple_keyb.c 2004-05-27 18:34:16.000000000 +0100 @@ -139,7 +139,7 @@ kbd->dev.name = dev->product_name; kbd->dev.id.bustype = BUS_MAPLE; - + input_register_device(&kbd->dev); maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD); --- diff/drivers/input/keyboard/sunkbd.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/keyboard/sunkbd.c 2004-05-27 18:34:16.000000000 +0100 @@ -11,18 +11,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -148,7 +148,7 @@ case EV_LED: sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED); - sunkbd->serio->write(sunkbd->serio, + sunkbd->serio->write(sunkbd->serio, (!!test_bit(LED_CAPSL, dev->led) << 3) | (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_COMPOSE, dev->led) << 1) | !!test_bit(LED_NUML, dev->led)); return 0; @@ -160,7 +160,7 @@ case SND_CLICK: sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value); return 0; - + case SND_BELL: sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value); return 0; @@ -210,7 +210,7 @@ wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED); - sunkbd->serio->write(sunkbd->serio, + sunkbd->serio->write(sunkbd->serio, (!!test_bit(LED_CAPSL, sunkbd->dev.led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev.led) << 2) | (!!test_bit(LED_COMPOSE, sunkbd->dev.led) << 1) | !!test_bit(LED_NUML, sunkbd->dev.led)); sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev.snd)); @@ -231,7 +231,7 @@ if ((serio->type & SERIO_PROTO) && (serio->type & SERIO_PROTO) != SERIO_SUNKBD) return; - + if (!(sunkbd = kmalloc(sizeof(struct sunkbd), GFP_KERNEL))) return; --- diff/drivers/input/keyboard/xtkbd.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/keyboard/xtkbd.c 2004-05-27 18:34:16.000000000 +0100 @@ -11,18 +11,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -43,7 +43,7 @@ #define XTKBD_KEY 0x7f #define XTKBD_RELEASE 0x80 -static unsigned char xtkbd_keycode[256] = { +static unsigned char xtkbd_keycode[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, @@ -98,7 +98,7 @@ return; memset(xtkbd, 0, sizeof(struct xtkbd)); - + xtkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); xtkbd->serio = serio; --- diff/drivers/input/misc/98spkr.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/input/misc/98spkr.c 2004-05-27 18:34:16.000000000 +0100 @@ -42,11 +42,11 @@ case SND_BELL: if (value) value = 1000; case SND_TONE: break; default: return -1; - } + } if (value > 20 && value < 32767) count = PIT_TICK_RATE / value; - + spin_lock_irqsave(&i8253_beep_lock, flags); if (count) { --- diff/drivers/input/misc/Kconfig 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/input/misc/Kconfig 2004-05-27 18:34:16.000000000 +0100 @@ -40,10 +40,6 @@ tristate "M68k Beeper support" depends on M68K && INPUT && INPUT_MISC -config INPUT_98SPKR - tristate "PC-9800 Speaker support" - depends on X86_PC9800 && INPUT && INPUT_MISC - config INPUT_UINPUT tristate "User level driver support" depends on INPUT && INPUT_MISC --- diff/drivers/input/misc/pcspkr.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/input/misc/pcspkr.c 2004-05-27 18:34:16.000000000 +0100 @@ -41,11 +41,11 @@ case SND_BELL: if (value) value = 1000; case SND_TONE: break; default: return -1; - } + } if (value > 20 && value < 32767) count = PIT_TICK_RATE / value; - + spin_lock_irqsave(&i8253_beep_lock, flags); if (count) { --- diff/drivers/input/misc/sparcspkr.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/misc/sparcspkr.c 2004-05-27 18:34:16.000000000 +0100 @@ -53,11 +53,11 @@ case SND_BELL: if (value) value = 1000; case SND_TONE: break; default: return -1; - } + } if (value > 20 && value < 32767) count = 1193182 / value; - + spin_lock_irqsave(&beep_lock, flags); /* EBUS speaker only has on/off state, the frequency does not @@ -108,11 +108,11 @@ case SND_BELL: if (value) value = 1000; case SND_TONE: break; default: return -1; - } + } if (value > 20 && value < 32767) count = 1193182 / value; - + spin_lock_irqsave(&beep_lock, flags); if (count) { --- diff/drivers/input/misc/uinput.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/misc/uinput.c 2004-05-27 18:34:16.000000000 +0100 @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Aristeu Sergio Rozanski Filho - * + * * Changes/Revisions: * 0.1 20/06/2002 * - first public version @@ -68,7 +68,7 @@ static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) { return 0; -} +} static int uinput_create_device(struct uinput_device *udev) { @@ -123,7 +123,7 @@ memset(newinput, 0, sizeof(struct input_dev)); newdev->dev = newinput; - + file->private_data = newdev; return 0; @@ -137,16 +137,16 @@ { unsigned int cnt; int retval = 0; - + for (cnt = 0; cnt < ABS_MAX; cnt++) { - if (!test_bit(cnt, dev->absbit)) + if (!test_bit(cnt, dev->absbit)) continue; - + if (/*!dev->absmin[cnt] || !dev->absmax[cnt] || */ (dev->absmax[cnt] <= dev->absmin[cnt])) { - printk(KERN_DEBUG + printk(KERN_DEBUG "%s: invalid abs[%02x] min:%d max:%d\n", - UINPUT_NAME, cnt, + UINPUT_NAME, cnt, dev->absmin[cnt], dev->absmax[cnt]); retval = -EINVAL; break; @@ -154,7 +154,7 @@ if ((dev->absflat[cnt] < dev->absmin[cnt]) || (dev->absflat[cnt] > dev->absmax[cnt])) { - printk(KERN_DEBUG + printk(KERN_DEBUG "%s: absflat[%02x] out of range: %d " "(min:%d/max:%d)\n", UINPUT_NAME, cnt, dev->absflat[cnt], @@ -190,7 +190,7 @@ goto exit; } - if (NULL != dev->name) + if (NULL != dev->name) kfree(dev->name); size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1; @@ -229,7 +229,7 @@ static ssize_t uinput_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) { struct uinput_device *udev = file->private_data; - + if (test_bit(UIST_CREATED, &(udev->state))) { struct input_event ev; @@ -247,7 +247,7 @@ { struct uinput_device *udev = file->private_data; int retval = 0; - + if (!test_bit(UIST_CREATED, &(udev->state))) return -ENODEV; @@ -255,16 +255,16 @@ return -EAGAIN; retval = wait_event_interruptible(udev->waitq, - (udev->head != udev->tail) || + (udev->head != udev->tail) || !test_bit(UIST_CREATED, &(udev->state))); - + if (retval) return retval; if (!test_bit(UIST_CREATED, &(udev->state))) return -ENODEV; - while ((udev->head != udev->tail) && + while ((udev->head != udev->tail) && (retval + sizeof(struct input_event) <= count)) { if (copy_to_user(buffer + retval, &(udev->buff[udev->tail]), sizeof(struct input_event))) return -EFAULT; @@ -284,7 +284,7 @@ if (udev->head != udev->tail) return POLLIN | POLLRDNORM; - return 0; + return 0; } static int uinput_burn_device(struct uinput_device *udev) @@ -318,7 +318,7 @@ case UI_DEV_CREATE: retval = uinput_create_device(udev); break; - + case UI_DEV_DESTROY: retval = uinput_destroy_device(udev); break; @@ -330,7 +330,7 @@ } set_bit(arg, udev->dev->evbit); break; - + case UI_SET_KEYBIT: if (arg > KEY_MAX) { retval = -EINVAL; @@ -338,7 +338,7 @@ } set_bit(arg, udev->dev->keybit); break; - + case UI_SET_RELBIT: if (arg > REL_MAX) { retval = -EINVAL; @@ -346,7 +346,7 @@ } set_bit(arg, udev->dev->relbit); break; - + case UI_SET_ABSBIT: if (arg > ABS_MAX) { retval = -EINVAL; @@ -354,7 +354,7 @@ } set_bit(arg, udev->dev->absbit); break; - + case UI_SET_MSCBIT: if (arg > MSC_MAX) { retval = -EINVAL; @@ -362,7 +362,7 @@ } set_bit(arg, udev->dev->mscbit); break; - + case UI_SET_LEDBIT: if (arg > LED_MAX) { retval = -EINVAL; @@ -370,7 +370,7 @@ } set_bit(arg, udev->dev->ledbit); break; - + case UI_SET_SNDBIT: if (arg > SND_MAX) { retval = -EINVAL; @@ -378,7 +378,7 @@ } set_bit(arg, udev->dev->sndbit); break; - + case UI_SET_FFBIT: if (arg > FF_MAX) { retval = -EINVAL; @@ -386,7 +386,7 @@ } set_bit(arg, udev->dev->ffbit); break; - + default: retval = -EFAULT; } --- diff/drivers/input/mouse/Kconfig 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/mouse/Kconfig 2004-05-27 18:34:16.000000000 +0100 @@ -130,14 +130,3 @@ described in the source file). This driver should, in theory, also work with the digitizer DEC produced, but it isn't tested with that (I don't have the hardware yet). - -config MOUSE_PC9800 - tristate "NEC PC-9800 busmouse" - depends on X86_PC9800 && INPUT && INPUT_MOUSE && ISA - help - Say Y here if you have NEC PC-9801/PC-9821 computer and want its - native mouse supported. - - To compile this driver as a module, choose M here: the - module will be called 98busmouse. - --- diff/drivers/input/mouse/Makefile 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/mouse/Makefile 2004-05-27 18:34:16.000000000 +0100 @@ -10,7 +10,6 @@ obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o -obj-$(CONFIG_MOUSE_PC9800) += 98busmouse.o obj-$(CONFIG_MOUSE_PS2) += psmouse.o obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o --- diff/drivers/input/mouse/logips2pp.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/mouse/logips2pp.c 2004-05-27 18:34:16.000000000 +0100 @@ -14,6 +14,25 @@ #include "psmouse.h" #include "logips2pp.h" +/* Logitech mouse types */ +#define PS2PP_KIND_WHEEL 1 +#define PS2PP_KIND_MX 2 +#define PS2PP_KIND_TP3 3 + +/* Logitech mouse features */ +#define PS2PP_WHEEL 0x01 +#define PS2PP_HWHEEL 0x02 +#define PS2PP_SIDE_BTN 0x04 +#define PS2PP_EXTRA_BTN 0x08 +#define PS2PP_TASK_BTN 0x10 +#define PS2PP_NAV_BTN 0x20 + +struct ps2pp_info { + const int model; + unsigned const int kind; + unsigned const int features; +}; + /* * Process a PS2++ or PS2T++ packet. */ @@ -63,7 +82,6 @@ packet[0] &= 0x0f; packet[1] = 0; packet[2] = 0; - } } @@ -76,18 +94,9 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned char command) { - unsigned char d; - int i; - - if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) + if (psmouse_sliced_command(psmouse, command)) return -1; - for (i = 6; i >= 0; i -= 2) { - d = (command >> i) & 3; - if(psmouse_command(psmouse, &d, PSMOUSE_CMD_SETRES)) - return -1; - } - if (psmouse_command(psmouse, param, PSMOUSE_CMD_POLL)) return -1; @@ -99,7 +108,7 @@ * enabled if we do nothing to it. Of course I put this in because I want it * disabled :P * 1 - enabled (if previously disabled, also default) - * 0/2 - disabled + * 0/2 - disabled */ static void ps2pp_set_smartscroll(struct psmouse *psmouse) @@ -113,14 +122,11 @@ psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); - if (psmouse_smartscroll == 1) - param[0] = 1; - else - if (psmouse_smartscroll > 2) - return; - - /* else leave param[0] == 0 to disable */ - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); + if (psmouse_smartscroll < 2) { + /* 0 - disabled, 1 - enabled */ + param[0] = psmouse_smartscroll; + psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); + } } /* @@ -138,133 +144,167 @@ psmouse_command(psmouse, ¶m, PSMOUSE_CMD_SETRES); } +static struct ps2pp_info *get_model_info(unsigned char model) +{ + static struct ps2pp_info ps2pp_list[] = { + { 12, 0, PS2PP_SIDE_BTN}, + { 13, 0, 0 }, + { 40, 0, PS2PP_SIDE_BTN }, + { 41, 0, PS2PP_SIDE_BTN }, + { 42, 0, PS2PP_SIDE_BTN }, + { 43, 0, PS2PP_SIDE_BTN }, + { 50, 0, 0 }, + { 51, 0, 0 }, + { 52, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL }, + { 53, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, + { 61, PS2PP_KIND_MX, + PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | + PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, /* MX700 */ + { 73, 0, PS2PP_SIDE_BTN }, + { 75, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, + { 76, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, + { 80, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL }, + { 81, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, + { 83, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, + { 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL }, + { 96, 0, 0 }, + { 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL }, + { 100, PS2PP_KIND_MX, + PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | + PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, /* MX510 */ + { 112, PS2PP_KIND_MX, + PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | + PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, /* MX500 */ + { 114, PS2PP_KIND_MX, + PS2PP_WHEEL | PS2PP_SIDE_BTN | + PS2PP_TASK_BTN | PS2PP_EXTRA_BTN }, /* M310 */ + { } + }; + int i; + + for (i = 0; ps2pp_list[i].model; i++) + if (model == ps2pp_list[i].model) + return &ps2pp_list[i]; + return NULL; +} + /* - * Detect the exact model and features of a PS2++ or PS2T++ Logitech mouse or - * touchpad. + * Set up input device's properties based on the detected mouse model. */ -static int ps2pp_detect_model(struct psmouse *psmouse, unsigned char *param) +static void ps2pp_set_model_properties(struct psmouse *psmouse, struct ps2pp_info *model_info) { - int i; - static struct _logips2_list { - const int model; - unsigned const int features; - } logips2pp_list [] = { - { 12, PS2PP_4BTN}, - { 13, 0 }, - { 40, PS2PP_4BTN }, - { 41, PS2PP_4BTN }, - { 42, PS2PP_4BTN }, - { 43, PS2PP_4BTN }, - { 50, 0 }, - { 51, 0 }, - { 52, PS2PP_4BTN | PS2PP_WHEEL }, - { 53, PS2PP_WHEEL }, - { 61, PS2PP_WHEEL | PS2PP_MX }, /* MX700 */ - { 73, PS2PP_4BTN }, - { 75, PS2PP_WHEEL }, - { 76, PS2PP_WHEEL }, - { 80, PS2PP_4BTN | PS2PP_WHEEL }, - { 81, PS2PP_WHEEL }, - { 83, PS2PP_WHEEL }, - { 88, PS2PP_WHEEL }, - { 96, 0 }, - { 97, 0 }, - { 100 , PS2PP_WHEEL | PS2PP_MX }, /* MX510 */ - { 112 , PS2PP_WHEEL | PS2PP_MX }, /* MX500 */ - { 114 , PS2PP_WHEEL | PS2PP_MX | PS2PP_MX310 }, /* MX310 */ - { } - }; + if (model_info->features & PS2PP_SIDE_BTN) + set_bit(BTN_SIDE, psmouse->dev.keybit); - psmouse->vendor = "Logitech"; - psmouse->model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78); + if (model_info->features & PS2PP_EXTRA_BTN) + set_bit(BTN_EXTRA, psmouse->dev.keybit); - if (param[1] < 3) - clear_bit(BTN_MIDDLE, psmouse->dev.keybit); - if (param[1] < 2) - clear_bit(BTN_RIGHT, psmouse->dev.keybit); - - psmouse->type = PSMOUSE_PS2; - - for (i = 0; logips2pp_list[i].model; i++){ - if (logips2pp_list[i].model == psmouse->model){ - psmouse->type = PSMOUSE_PS2PP; - if (logips2pp_list[i].features & PS2PP_4BTN) - set_bit(BTN_SIDE, psmouse->dev.keybit); - - if (logips2pp_list[i].features & PS2PP_WHEEL){ - set_bit(REL_WHEEL, psmouse->dev.relbit); - psmouse->name = "Wheel Mouse"; - } - if (logips2pp_list[i].features & PS2PP_MX) { - set_bit(BTN_SIDE, psmouse->dev.keybit); - set_bit(BTN_EXTRA, psmouse->dev.keybit); - set_bit(BTN_TASK, psmouse->dev.keybit); - if (!(logips2pp_list[i].features & PS2PP_MX310)){ - set_bit(BTN_BACK, psmouse->dev.keybit); - set_bit(BTN_FORWARD, psmouse->dev.keybit); - } - psmouse->name = "MX Mouse"; - } + if (model_info->features & PS2PP_TASK_BTN) + set_bit(BTN_TASK, psmouse->dev.keybit); + + if (model_info->features & PS2PP_NAV_BTN) { + set_bit(BTN_FORWARD, psmouse->dev.keybit); + set_bit(BTN_BACK, psmouse->dev.keybit); + } + + if (model_info->features & PS2PP_WHEEL) + set_bit(REL_WHEEL, psmouse->dev.relbit); + + if (model_info->features & PS2PP_HWHEEL) + set_bit(REL_HWHEEL, psmouse->dev.relbit); + + switch (model_info->kind) { + case PS2PP_KIND_WHEEL: + psmouse->name = "Wheel Mouse"; + break; + + case PS2PP_KIND_MX: + psmouse->name = "MX Mouse"; + break; + + case PS2PP_KIND_TP3: + psmouse->name = "TouchPad 3"; break; - } } +} + + /* - * Do Logitech PS2++ / PS2T++ magic init. + * Logitech magic init. Detect whether the mouse is a Logitech one + * and its exact model and try turning on extended protocol for ones + * that support it. */ - if (psmouse->type == PSMOUSE_PS2PP) { - if (psmouse->model == 97) { /* TouchPad 3 */ +int ps2pp_init(struct psmouse *psmouse, int set_properties) +{ + unsigned char param[4]; + unsigned char protocol = PSMOUSE_PS2; + unsigned char model, buttons; + struct ps2pp_info *model_info; - set_bit(REL_WHEEL, psmouse->dev.relbit); - set_bit(REL_HWHEEL, psmouse->dev.relbit); + param[0] = 0; + psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); + psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); + psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); + psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); + param[1] = 0; + psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO); + + if (param[1] != 0) { + model = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78); + buttons = param[1]; + model_info = get_model_info(model); + +/* + * Do Logitech PS2++ / PS2T++ magic init. + */ + if (model == 97) { /* Touch Pad 3 */ - param[0] = 0x11; param[1] = 0x04; param[2] = 0x68; /* Unprotect RAM */ + /* Unprotect RAM */ + param[0] = 0x11; param[1] = 0x04; param[2] = 0x68; psmouse_command(psmouse, param, 0x30d1); - param[0] = 0x11; param[1] = 0x05; param[2] = 0x0b; /* Enable features */ + /* Enable features */ + param[0] = 0x11; param[1] = 0x05; param[2] = 0x0b; psmouse_command(psmouse, param, 0x30d1); - param[0] = 0x11; param[1] = 0x09; param[2] = 0xc3; /* Enable PS2++ */ + /* Enable PS2++ */ + param[0] = 0x11; param[1] = 0x09; param[2] = 0xc3; psmouse_command(psmouse, param, 0x30d1); param[0] = 0; if (!psmouse_command(psmouse, param, 0x13d1) && - param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) { - psmouse->name = "TouchPad 3"; - return PSMOUSE_PS2TPP; + param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) { + protocol = PSMOUSE_PS2TPP; } - } else { + } else if (get_model_info(model) != NULL) { param[0] = param[1] = param[2] = 0; ps2pp_cmd(psmouse, param, 0x39); /* Magic knock */ ps2pp_cmd(psmouse, param, 0xDB); - if ((param[0] & 0x78) == 0x48 && (param[1] & 0xf3) == 0xc2 && - (param[2] & 3) == ((param[1] >> 2) & 3)) { - ps2pp_set_smartscroll(psmouse); - return PSMOUSE_PS2PP; + if ((param[0] & 0x78) == 0x48 && + (param[1] & 0xf3) == 0xc2 && + (param[2] & 0x03) == ((param[1] >> 2) & 3)) { + ps2pp_set_smartscroll(psmouse); + protocol = PSMOUSE_PS2PP; } } - } - return 0; -} - -/* - * Logitech magic init. - */ -int ps2pp_detect(struct psmouse *psmouse) -{ - unsigned char param[4]; + if (set_properties) { + psmouse->vendor = "Logitech"; + psmouse->model = model; + + if (buttons < 3) + clear_bit(BTN_MIDDLE, psmouse->dev.keybit); + if (buttons < 2) + clear_bit(BTN_RIGHT, psmouse->dev.keybit); - param[0] = 0; - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); - psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); - psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); - psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11); - param[1] = 0; - psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO); + if (model_info) + ps2pp_set_model_properties(psmouse, model_info); + } + } - return param[1] != 0 ? ps2pp_detect_model(psmouse, param) : 0; + return protocol; } --- diff/drivers/input/mouse/logips2pp.h 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/mouse/logips2pp.h 2004-05-27 18:34:16.000000000 +0100 @@ -11,13 +11,8 @@ #ifndef _LOGIPS2PP_H #define _LOGIPS2PP_H -#define PS2PP_4BTN 0x01 -#define PS2PP_WHEEL 0x02 -#define PS2PP_MX 0x04 -#define PS2PP_MX310 0x08 - -struct psmouse; void ps2pp_process_packet(struct psmouse *psmouse); void ps2pp_set_800dpi(struct psmouse *psmouse); -int ps2pp_detect(struct psmouse *psmouse); +int ps2pp_init(struct psmouse *psmouse, int set_properties); + #endif --- diff/drivers/input/mouse/psmouse-base.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/mouse/psmouse-base.c 2004-05-27 18:34:16.000000000 +0100 @@ -43,9 +43,9 @@ module_param_named(smartscroll, psmouse_smartscroll, bool, 0); MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); -unsigned int psmouse_resetafter; +static unsigned int psmouse_resetafter; module_param_named(resetafter, psmouse_resetafter, uint, 0); -MODULE_PARM_DESC(resetafter, "Reset Synaptics Touchpad after so many bad packets (0 = never)."); +MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); __obsolete_setup("psmouse_noext"); __obsolete_setup("psmouse_resolution="); @@ -56,15 +56,22 @@ static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2"}; /* - * psmouse_process_packet() analyzes the PS/2 mouse packet contents and - * reports relevant events to the input module. + * psmouse_process_byte() analyzes the PS/2 data stream and reports + * relevant events to the input module once full packet has arrived. */ -static void psmouse_process_packet(struct psmouse *psmouse, struct pt_regs *regs) +static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_regs *regs) { struct input_dev *dev = &psmouse->dev; unsigned char *packet = psmouse->packet; + if (psmouse->pktcnt < 3 + (psmouse->type >= PSMOUSE_GENPS)) + return PSMOUSE_GOOD_DATA; + +/* + * Full packet accumulated, process it + */ + input_regs(dev, regs); /* @@ -112,6 +119,8 @@ input_report_rel(dev, REL_Y, packet[2] ? (int) ((packet[0] << 3) & 0x100) - (int) packet[2] : 0); input_sync(dev); + + return PSMOUSE_FULL_PACKET; } /* @@ -123,6 +132,7 @@ unsigned char data, unsigned int flags, struct pt_regs *regs) { struct psmouse *psmouse = serio->private; + psmouse_ret_t rc; if (psmouse->state == PSMOUSE_IGNORE) goto out; @@ -180,7 +190,7 @@ if (psmouse->pktcnt == 2) { if (psmouse->packet[1] == PSMOUSE_RET_ID) { psmouse->state = PSMOUSE_IGNORE; - serio_rescan(serio); + serio_reconnect(serio); goto out; } if (psmouse->type == PSMOUSE_SYNAPTICS) { @@ -193,19 +203,32 @@ } } - if (psmouse->type == PSMOUSE_SYNAPTICS) { - /* - * The synaptics driver has its own resync logic, - * so it needs to receive all bytes one at a time. - */ - synaptics_process_byte(psmouse, regs); - goto out; - } + rc = psmouse->protocol_handler(psmouse, regs); - if (psmouse->pktcnt == 3 + (psmouse->type >= PSMOUSE_GENPS)) { - psmouse_process_packet(psmouse, regs); - psmouse->pktcnt = 0; - goto out; + switch (rc) { + case PSMOUSE_BAD_DATA: + printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", + psmouse->name, psmouse->phys, psmouse->pktcnt); + psmouse->pktcnt = 0; + + if (++psmouse->out_of_sync == psmouse_resetafter) { + psmouse->state = PSMOUSE_IGNORE; + printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); + serio_reconnect(psmouse->serio); + } + break; + + case PSMOUSE_FULL_PACKET: + psmouse->pktcnt = 0; + if (psmouse->out_of_sync) { + psmouse->out_of_sync = 0; + printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", + psmouse->name, psmouse->phys); + } + break; + + case PSMOUSE_GOOD_DATA: + break; } out: return IRQ_HANDLED; @@ -289,6 +312,30 @@ /* + * psmouse_sliced_command() sends an extended PS/2 command to the mouse + * using sliced syntax, understood by advanced devices, such as Logitech + * or Synaptics touchpads. The command is encoded as: + * 0xE6 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu + * is the command. + */ +int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command) +{ + int i; + + if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) + return -1; + + for (i = 6; i >= 0; i -= 2) { + unsigned char d = (command >> i) & 3; + if (psmouse_command(psmouse, &d, PSMOUSE_CMD_SETRES)) + return -1; + } + + return 0; +} + + +/* * psmouse_reset() resets the mouse into power-on state. */ int psmouse_reset(struct psmouse *psmouse) @@ -363,31 +410,31 @@ * the mouse may have. */ -static int psmouse_extensions(struct psmouse *psmouse) +static int psmouse_extensions(struct psmouse *psmouse, + unsigned int max_proto, int set_properties) { int synaptics_hardware = 0; - psmouse->vendor = "Generic"; - psmouse->name = "Mouse"; - psmouse->model = 0; - /* * Try Synaptics TouchPad */ - if (psmouse_max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse)) { + if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse)) { synaptics_hardware = 1; - psmouse->vendor = "Synaptics"; - psmouse->name = "TouchPad"; - if (psmouse_max_proto > PSMOUSE_IMEX) { - if (synaptics_init(psmouse) == 0) + if (set_properties) { + psmouse->vendor = "Synaptics"; + psmouse->name = "TouchPad"; + } + + if (max_proto > PSMOUSE_IMEX) { + if (!set_properties || synaptics_init(psmouse) == 0) return PSMOUSE_SYNAPTICS; /* * Some Synaptics touchpads can emulate extended protocols (like IMPS/2). * Unfortunately Logitech/Genius probes confuse some firmware versions so * we'll have to skip them. */ - psmouse_max_proto = PSMOUSE_IMEX; + max_proto = PSMOUSE_IMEX; } /* * Make sure that touchpad is in relative mode, gestures (taps) are enabled @@ -395,35 +442,46 @@ synaptics_reset(psmouse); } - if (psmouse_max_proto > PSMOUSE_IMEX && genius_detect(psmouse)) { - set_bit(BTN_EXTRA, psmouse->dev.keybit); - set_bit(BTN_SIDE, psmouse->dev.keybit); - set_bit(REL_WHEEL, psmouse->dev.relbit); + if (max_proto > PSMOUSE_IMEX && genius_detect(psmouse)) { + + if (set_properties) { + set_bit(BTN_EXTRA, psmouse->dev.keybit); + set_bit(BTN_SIDE, psmouse->dev.keybit); + set_bit(REL_WHEEL, psmouse->dev.relbit); + psmouse->vendor = "Genius"; + psmouse->name = "Wheel Mouse"; + } - psmouse->vendor = "Genius"; - psmouse->name = "Wheel Mouse"; return PSMOUSE_GENPS; } - if (psmouse_max_proto > PSMOUSE_IMEX) { - int type = ps2pp_detect(psmouse); - if (type) + if (max_proto > PSMOUSE_IMEX) { + int type = ps2pp_init(psmouse, set_properties); + if (type > PSMOUSE_PS2) return type; } - if (psmouse_max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse)) { - set_bit(REL_WHEEL, psmouse->dev.relbit); + if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse)) { - if (psmouse_max_proto >= PSMOUSE_IMEX && - im_explorer_detect(psmouse)) { + if (set_properties) { + set_bit(REL_WHEEL, psmouse->dev.relbit); set_bit(BTN_SIDE, psmouse->dev.keybit); set_bit(BTN_EXTRA, psmouse->dev.keybit); + if (!psmouse->name) + psmouse->name = "Explorer Mouse"; + } + + return PSMOUSE_IMEX; + } + + if (max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse)) { - psmouse->name = "Explorer Mouse"; - return PSMOUSE_IMEX; + if (set_properties) { + set_bit(REL_WHEEL, psmouse->dev.relbit); + if (!psmouse->name) + psmouse->name = "Wheel Mouse"; } - psmouse->name = "Wheel Mouse"; return PSMOUSE_IMPS; } @@ -473,12 +531,7 @@ if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_RESET_DIS)) printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", psmouse->serio->phys); -/* - * And here we try to determine if it has any extensions over the - * basic PS/2 3-button mouse. - */ - - return psmouse->type = psmouse_extensions(psmouse); + return 0; } /* @@ -616,7 +669,6 @@ psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); - psmouse->state = PSMOUSE_CMD_MODE; psmouse->serio = serio; psmouse->dev.private = psmouse; @@ -628,13 +680,21 @@ return; } - if (psmouse_probe(psmouse) <= 0) { + if (psmouse_probe(psmouse) < 0) { serio_close(serio); kfree(psmouse); serio->private = NULL; return; } + psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); + if (!psmouse->vendor) + psmouse->vendor = "Generic"; + if (!psmouse->name) + psmouse->name = "Mouse"; + if (!psmouse->protocol_handler) + psmouse->protocol_handler = psmouse_process_byte; + sprintf(psmouse->devname, "%s %s %s", psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name); sprintf(psmouse->phys, "%s/input0", @@ -668,27 +728,24 @@ { struct psmouse *psmouse = serio->private; struct serio_dev *dev = serio->dev; - int old_type; if (!dev || !psmouse) { printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n"); return -1; } - old_type = psmouse->type; - psmouse->state = PSMOUSE_CMD_MODE; - psmouse->type = psmouse->acking = psmouse->cmdcnt = psmouse->pktcnt = 0; + psmouse->acking = psmouse->cmdcnt = psmouse->pktcnt = psmouse->out_of_sync = 0; if (psmouse->reconnect) { if (psmouse->reconnect(psmouse)) return -1; - } else if (psmouse_probe(psmouse) != old_type) + } else if (psmouse_probe(psmouse) < 0 || + psmouse->type != psmouse_extensions(psmouse, psmouse_max_proto, 0)) return -1; /* ok, the device type (and capabilities) match the old one, * we can continue using it, complete intialization */ - psmouse->type = old_type; psmouse_initialize(psmouse); if (psmouse->ptport) { --- diff/drivers/input/mouse/psmouse.h 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/mouse/psmouse.h 2004-05-27 18:34:16.000000000 +0100 @@ -22,6 +22,13 @@ #define PSMOUSE_ACTIVATED 1 #define PSMOUSE_IGNORE 2 +/* psmouse protocol handler return codes */ +typedef enum { + PSMOUSE_BAD_DATA, + PSMOUSE_GOOD_DATA, + PSMOUSE_FULL_PACKET +} psmouse_ret_t; + struct psmouse; struct psmouse_ptport { @@ -45,6 +52,7 @@ unsigned char type; unsigned char model; unsigned long last; + unsigned long out_of_sync; unsigned char state; char acking; volatile char ack; @@ -52,6 +60,7 @@ char devname[64]; char phys[32]; + psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); int (*reconnect)(struct psmouse *psmouse); void (*disconnect)(struct psmouse *psmouse); }; @@ -65,10 +74,10 @@ #define PSMOUSE_SYNAPTICS 7 int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command); +int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); int psmouse_reset(struct psmouse *psmouse); extern int psmouse_smartscroll; extern unsigned int psmouse_rate; -extern unsigned int psmouse_resetafter; #endif /* _PSMOUSE_H */ --- diff/drivers/input/mouse/synaptics.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/mouse/synaptics.c 2004-05-27 18:34:16.000000000 +0100 @@ -44,33 +44,11 @@ ****************************************************************************/ /* - * Use the Synaptics extended ps/2 syntax to write a special command byte. - * special command: 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu - * is the command. A 0xF3 or 0xE9 must follow (see synaptics_send_cmd - * and synaptics_mode_cmd) - */ -static int synaptics_special_cmd(struct psmouse *psmouse, unsigned char command) -{ - int i; - - if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) - return -1; - - for (i = 6; i >= 0; i -= 2) { - unsigned char d = (command >> i) & 3; - if (psmouse_command(psmouse, &d, PSMOUSE_CMD_SETRES)) - return -1; - } - - return 0; -} - -/* * Send a command to the synpatics touchpad by special commands */ static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param) { - if (synaptics_special_cmd(psmouse, c)) + if (psmouse_sliced_command(psmouse, c)) return -1; if (psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO)) return -1; @@ -84,7 +62,7 @@ { unsigned char param[1]; - if (synaptics_special_cmd(psmouse, mode)) + if (psmouse_sliced_command(psmouse, mode)) return -1; param[0] = SYN_PS_SET_MODE2; if (psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE)) @@ -118,17 +96,31 @@ if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap)) return -1; - priv->capabilities = (cap[0]<<16) | (cap[1]<<8) | cap[2]; + priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2]; priv->ext_cap = 0; if (!SYN_CAP_VALID(priv->capabilities)) return -1; - if (SYN_EXT_CAP_REQUESTS(priv->capabilities)) { + /* + * Unless capExtended is set the rest of the flags should be ignored + */ + if (!SYN_CAP_EXTENDED(priv->capabilities)) + priv->capabilities = 0; + + if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) { if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) { printk(KERN_ERR "Synaptics claims to have extended capabilities," " but I'm not able to read them."); - } else - priv->ext_cap = (cap[0]<<16) | (cap[1]<<8) | cap[2]; + } else { + priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2]; + + /* + * if nExtBtn is greater than 8 it should be considered + * invalid and treated as 0 + */ + if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 8) + priv->ext_cap &= 0xff0fff; + } } return 0; } @@ -167,11 +159,12 @@ if (SYN_CAP_EXTENDED(priv->capabilities)) { printk(KERN_INFO " Touchpad has extended capability bits\n"); - if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && - SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) <= 8) + if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) printk(KERN_INFO " -> %d multi-buttons, i.e. besides standard buttons\n", (int)(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))); - else if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) + if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) + printk(KERN_INFO " -> middle button\n"); + if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) printk(KERN_INFO " -> four buttons\n"); if (SYN_CAP_MULTIFINGER(priv->capabilities)) printk(KERN_INFO " -> multifinger detection\n"); @@ -219,21 +212,12 @@ /***************************************************************************** * Synaptics pass-through PS/2 port support ****************************************************************************/ -static int synaptics_pt_open(struct serio *port) -{ - return 0; -} - -static void synaptics_pt_close(struct serio *port) -{ -} - static int synaptics_pt_write(struct serio *port, unsigned char c) { struct psmouse *parent = port->driver; char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */ - if (synaptics_special_cmd(parent, c)) + if (psmouse_sliced_command(parent, c)) return -1; if (psmouse_command(parent, &rate_param, PSMOUSE_CMD_SETRATE)) return -1; @@ -289,166 +273,12 @@ port->serio.name = "Synaptics pass-through"; port->serio.phys = "synaptics-pt/serio0"; port->serio.write = synaptics_pt_write; - port->serio.open = synaptics_pt_open; - port->serio.close = synaptics_pt_close; port->serio.driver = psmouse; port->activate = synaptics_pt_activate; } /***************************************************************************** - * Driver initialization/cleanup functions - ****************************************************************************/ - -static inline void set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat) -{ - dev->absmin[axis] = min; - dev->absmax[axis] = max; - dev->absfuzz[axis] = fuzz; - dev->absflat[axis] = flat; - - set_bit(axis, dev->absbit); -} - -static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) -{ - set_bit(EV_ABS, dev->evbit); - set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0); - set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0); - set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); - set_bit(ABS_TOOL_WIDTH, dev->absbit); - - set_bit(EV_KEY, dev->evbit); - set_bit(BTN_TOUCH, dev->keybit); - set_bit(BTN_TOOL_FINGER, dev->keybit); - set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); - set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); - - set_bit(BTN_LEFT, dev->keybit); - set_bit(BTN_RIGHT, dev->keybit); - set_bit(BTN_FORWARD, dev->keybit); - set_bit(BTN_BACK, dev->keybit); - if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) { - switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { - default: - /* - * if nExtBtn is greater than 8 it should be considered - * invalid and treated as 0 - */ - break; - case 8: - set_bit(BTN_7, dev->keybit); - set_bit(BTN_6, dev->keybit); - case 6: - set_bit(BTN_5, dev->keybit); - set_bit(BTN_4, dev->keybit); - case 4: - set_bit(BTN_3, dev->keybit); - set_bit(BTN_2, dev->keybit); - case 2: - set_bit(BTN_1, dev->keybit); - set_bit(BTN_0, dev->keybit); - break; - } - } - - clear_bit(EV_REL, dev->evbit); - clear_bit(REL_X, dev->relbit); - clear_bit(REL_Y, dev->relbit); -} - -void synaptics_reset(struct psmouse *psmouse) -{ - /* reset touchpad back to relative mode, gestures enabled */ - synaptics_mode_cmd(psmouse, 0); -} - -static void synaptics_disconnect(struct psmouse *psmouse) -{ - synaptics_reset(psmouse); - kfree(psmouse->private); -} - -static int synaptics_reconnect(struct psmouse *psmouse) -{ - struct synaptics_data *priv = psmouse->private; - struct synaptics_data old_priv = *priv; - - if (!synaptics_detect(psmouse)) - return -1; - - if (synaptics_query_hardware(psmouse)) { - printk(KERN_ERR "Unable to query Synaptics hardware.\n"); - return -1; - } - - if (old_priv.identity != priv->identity || - old_priv.model_id != priv->model_id || - old_priv.capabilities != priv->capabilities || - old_priv.ext_cap != priv->ext_cap) - return -1; - - if (synaptics_set_mode(psmouse, 0)) { - printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); - return -1; - } - - return 0; -} - -int synaptics_detect(struct psmouse *psmouse) -{ - unsigned char param[4]; - - param[0] = 0; - - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); - psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); - psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO); - - return param[1] == 0x47; -} - -int synaptics_init(struct psmouse *psmouse) -{ - struct synaptics_data *priv; - - psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL); - if (!priv) - return -1; - memset(priv, 0, sizeof(struct synaptics_data)); - - if (synaptics_query_hardware(psmouse)) { - printk(KERN_ERR "Unable to query Synaptics hardware.\n"); - goto init_fail; - } - - if (synaptics_set_mode(psmouse, 0)) { - printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); - goto init_fail; - } - - priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; - - if (SYN_CAP_EXTENDED(priv->capabilities) && SYN_CAP_PASS_THROUGH(priv->capabilities)) - synaptics_pt_create(psmouse); - - print_ident(priv); - set_input_params(&psmouse->dev, priv); - - psmouse->disconnect = synaptics_disconnect; - psmouse->reconnect = synaptics_reconnect; - - return 0; - - init_fail: - kfree(priv); - return -1; -} - -/***************************************************************************** * Functions to interpret the absolute mode packets ****************************************************************************/ @@ -471,17 +301,17 @@ hw->left = (buf[0] & 0x01) ? 1 : 0; hw->right = (buf[0] & 0x02) ? 1 : 0; - if (SYN_CAP_EXTENDED(priv->capabilities) && - (SYN_CAP_FOUR_BUTTON(priv->capabilities))) { - hw->up = ((buf[3] & 0x01)) ? 1 : 0; - if (hw->left) - hw->up = !hw->up; - hw->down = ((buf[3] & 0x02)) ? 1 : 0; - if (hw->right) - hw->down = !hw->down; + + if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) + hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; + + if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) { + hw->up = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; + hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; } + if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && - ((buf[3] & 2) ? !hw->right : hw->right)) { + ((buf[0] ^ buf[3]) & 0x02)) { switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { default: /* @@ -490,17 +320,17 @@ */ break; case 8: - hw->b7 = ((buf[5] & 0x08)) ? 1 : 0; - hw->b6 = ((buf[4] & 0x08)) ? 1 : 0; + hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0; + hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0; case 6: - hw->b5 = ((buf[5] & 0x04)) ? 1 : 0; - hw->b4 = ((buf[4] & 0x04)) ? 1 : 0; + hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0; + hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0; case 4: - hw->b3 = ((buf[5] & 0x02)) ? 1 : 0; - hw->b2 = ((buf[4] & 0x02)) ? 1 : 0; + hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0; + hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0; case 2: - hw->b1 = ((buf[5] & 0x01)) ? 1 : 0; - hw->b0 = ((buf[4] & 0x01)) ? 1 : 0; + hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0; + hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0; } } } else { @@ -525,6 +355,7 @@ struct synaptics_hw_state hw; int num_fingers; int finger_width; + int i; synaptics_parse_hw_state(psmouse->packet, priv, &hw); @@ -570,32 +401,20 @@ input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); - input_report_key(dev, BTN_LEFT, hw.left); - input_report_key(dev, BTN_RIGHT, hw.right); - input_report_key(dev, BTN_FORWARD, hw.up); - input_report_key(dev, BTN_BACK, hw.down); - if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) - switch(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { - default: - /* - * if nExtBtn is greater than 8 it should be considered - * invalid and treated as 0 - */ - break; - case 8: - input_report_key(dev, BTN_7, hw.b7); - input_report_key(dev, BTN_6, hw.b6); - case 6: - input_report_key(dev, BTN_5, hw.b5); - input_report_key(dev, BTN_4, hw.b4); - case 4: - input_report_key(dev, BTN_3, hw.b3); - input_report_key(dev, BTN_2, hw.b2); - case 2: - input_report_key(dev, BTN_1, hw.b1); - input_report_key(dev, BTN_0, hw.b0); - break; - } + input_report_key(dev, BTN_LEFT, hw.left); + input_report_key(dev, BTN_RIGHT, hw.right); + + if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) + input_report_key(dev, BTN_MIDDLE, hw.middle); + + if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) { + input_report_key(dev, BTN_FORWARD, hw.up); + input_report_key(dev, BTN_BACK, hw.down); + } + + for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) + input_report_key(dev, BTN_0 + i, hw.ext_buttons & (1 << i)); + input_sync(dev); } @@ -607,6 +426,9 @@ static unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 }; static unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 }; + if (idx < 0 || idx > 4) + return 0; + switch (pkt_type) { case SYN_NEWABS: case SYN_NEWABS_RELAXED: @@ -637,7 +459,7 @@ return SYN_NEWABS_STRICT; } -void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs) +static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs) { struct input_dev *dev = &psmouse->dev; struct synaptics_data *priv = psmouse->private; @@ -645,11 +467,6 @@ input_regs(dev, regs); if (psmouse->pktcnt >= 6) { /* Full packet received */ - if (priv->out_of_sync) { - priv->out_of_sync = 0; - printk(KERN_NOTICE "Synaptics driver resynced.\n"); - } - if (unlikely(priv->pkt_type == SYN_NEWABS)) priv->pkt_type = synaptics_detect_pkt_type(psmouse); @@ -657,16 +474,142 @@ synaptics_pass_pt_packet(&psmouse->ptport->serio, psmouse->packet); else synaptics_process_packet(psmouse); - psmouse->pktcnt = 0; - } else if (psmouse->pktcnt && - !synaptics_validate_byte(psmouse->packet, psmouse->pktcnt - 1, priv->pkt_type)) { - printk(KERN_WARNING "Synaptics driver lost sync at byte %d\n", psmouse->pktcnt); - psmouse->pktcnt = 0; - if (++priv->out_of_sync == psmouse_resetafter) { - psmouse->state = PSMOUSE_IGNORE; - printk(KERN_NOTICE "synaptics: issuing reconnect request\n"); - serio_reconnect(psmouse->serio); - } + return PSMOUSE_FULL_PACKET; + } + + return synaptics_validate_byte(psmouse->packet, psmouse->pktcnt - 1, priv->pkt_type) ? + PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; +} + +/***************************************************************************** + * Driver initialization/cleanup functions + ****************************************************************************/ +static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) +{ + int i; + + set_bit(EV_ABS, dev->evbit); + input_set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0); + input_set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0); + input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); + set_bit(ABS_TOOL_WIDTH, dev->absbit); + + set_bit(EV_KEY, dev->evbit); + set_bit(BTN_TOUCH, dev->keybit); + set_bit(BTN_TOOL_FINGER, dev->keybit); + set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); + set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); + + set_bit(BTN_LEFT, dev->keybit); + set_bit(BTN_RIGHT, dev->keybit); + + if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) + set_bit(BTN_MIDDLE, dev->keybit); + + if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) { + set_bit(BTN_FORWARD, dev->keybit); + set_bit(BTN_BACK, dev->keybit); + } + + for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) + set_bit(BTN_0 + i, dev->keybit); + + clear_bit(EV_REL, dev->evbit); + clear_bit(REL_X, dev->relbit); + clear_bit(REL_Y, dev->relbit); +} + +void synaptics_reset(struct psmouse *psmouse) +{ + /* reset touchpad back to relative mode, gestures enabled */ + synaptics_mode_cmd(psmouse, 0); +} + +static void synaptics_disconnect(struct psmouse *psmouse) +{ + synaptics_reset(psmouse); + kfree(psmouse->private); +} + +static int synaptics_reconnect(struct psmouse *psmouse) +{ + struct synaptics_data *priv = psmouse->private; + struct synaptics_data old_priv = *priv; + + if (!synaptics_detect(psmouse)) + return -1; + + if (synaptics_query_hardware(psmouse)) { + printk(KERN_ERR "Unable to query Synaptics hardware.\n"); + return -1; + } + + if (old_priv.identity != priv->identity || + old_priv.model_id != priv->model_id || + old_priv.capabilities != priv->capabilities || + old_priv.ext_cap != priv->ext_cap) + return -1; + + if (synaptics_set_mode(psmouse, 0)) { + printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); + return -1; + } + + return 0; +} + +int synaptics_detect(struct psmouse *psmouse) +{ + unsigned char param[4]; + + param[0] = 0; + + psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); + psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); + psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); + psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); + psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO); + + return param[1] == 0x47; +} + +int synaptics_init(struct psmouse *psmouse) +{ + struct synaptics_data *priv; + + psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL); + if (!priv) + return -1; + memset(priv, 0, sizeof(struct synaptics_data)); + + if (synaptics_query_hardware(psmouse)) { + printk(KERN_ERR "Unable to query Synaptics hardware.\n"); + goto init_fail; + } + + if (synaptics_set_mode(psmouse, 0)) { + printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); + goto init_fail; } + + priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; + + if (SYN_CAP_PASS_THROUGH(priv->capabilities)) + synaptics_pt_create(psmouse); + + print_ident(priv); + set_input_params(&psmouse->dev, priv); + + psmouse->protocol_handler = synaptics_process_byte; + psmouse->disconnect = synaptics_disconnect; + psmouse->reconnect = synaptics_reconnect; + + return 0; + + init_fail: + kfree(priv); + return -1; } + + --- diff/drivers/input/mouse/synaptics.h 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/mouse/synaptics.h 2004-05-27 18:34:16.000000000 +0100 @@ -9,7 +9,6 @@ #ifndef _SYNAPTICS_H #define _SYNAPTICS_H -extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs); extern int synaptics_detect(struct psmouse *psmouse); extern int synaptics_init(struct psmouse *psmouse); extern void synaptics_reset(struct psmouse *psmouse); @@ -44,13 +43,14 @@ /* synaptics capability bits */ #define SYN_CAP_EXTENDED(c) ((c) & (1 << 23)) +#define SYN_CAP_MIDDLE_BUTTON(c) ((c) & (1 << 18)) #define SYN_CAP_PASS_THROUGH(c) ((c) & (1 << 7)) #define SYN_CAP_SLEEP(c) ((c) & (1 << 4)) #define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3)) #define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1)) #define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0)) #define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47) -#define SYN_EXT_CAP_REQUESTS(c) ((((c) & 0x700000) >> 20) == 1) +#define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) /* synaptics modes query bits */ @@ -86,18 +86,12 @@ int y; int z; int w; - int left; - int right; - int up; - int down; - int b0; - int b1; - int b2; - int b3; - int b4; - int b5; - int b6; - int b7; + unsigned int left:1; + unsigned int right:1; + unsigned int middle:1; + unsigned int up:1; + unsigned int down:1; + unsigned char ext_buttons; }; struct synaptics_data { @@ -108,7 +102,6 @@ unsigned long int identity; /* Identification */ /* Data for normal processing */ - unsigned int out_of_sync; /* # of packets out of sync */ int old_w; /* Previous w value */ unsigned char pkt_type; /* packet type - old, new, etc */ }; --- diff/drivers/input/mousedev.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/mousedev.c 2004-05-27 18:34:16.000000000 +0100 @@ -2,6 +2,7 @@ * Input driver to ExplorerPS/2 device driver module. * * Copyright (c) 1999-2002 Vojtech Pavlik + * Copyright (c) 2004 Dmitry Torokhov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published by @@ -47,15 +48,24 @@ module_param(yres, uint, 0); MODULE_PARM_DESC(yres, "Vertical screen resolution"); +struct mousedev_motion { + int dx, dy, dz; +}; + struct mousedev { int exist; int open; int minor; - int misc; char name[16]; wait_queue_head_t wait; struct list_head list; struct input_handle handle; + + struct mousedev_motion packet; + unsigned long buttons; + unsigned int pkt_count; + int old_x[4], old_y[4]; + unsigned int touch; }; struct mousedev_list { @@ -63,13 +73,10 @@ struct mousedev *mousedev; struct list_head node; int dx, dy, dz; - int old_x[4], old_y[4]; unsigned long buttons; signed char ps2[6]; unsigned char ready, buffer, bufsiz; unsigned char mode, imexseq, impsseq; - unsigned int pkt_count; - unsigned char touch; }; #define MOUSEDEV_SEQ_LEN 6 @@ -82,135 +89,157 @@ static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; static struct mousedev mousedev_mix; -#define fx(i) (list->old_x[(list->pkt_count - (i)) & 03]) -#define fy(i) (list->old_y[(list->pkt_count - (i)) & 03]) +#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03]) +#define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03]) -static void mousedev_abs_event(struct input_handle *handle, struct mousedev_list *list, unsigned int code, int value) +static void mousedev_touchpad_event(struct mousedev *mousedev, unsigned int code, int value) { - int size; - int touchpad; + if (mousedev->touch) { + switch (code) { + case ABS_X: + fx(0) = value; + if (mousedev->pkt_count >= 2) + mousedev->packet.dx = ((fx(0) - fx(1)) / 2 + (fx(1) - fx(2)) / 2) / 8; + break; - /* Ignore joysticks */ - if (test_bit(BTN_TRIGGER, handle->dev->keybit)) - return; + case ABS_Y: + fy(0) = value; + if (mousedev->pkt_count >= 2) + mousedev->packet.dy = -((fy(0) - fy(1)) / 2 + (fy(1) - fy(2)) / 2) / 8; + break; + } + } +} - touchpad = test_bit(BTN_TOOL_FINGER, handle->dev->keybit); +static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value) +{ + int size; switch (code) { case ABS_X: - if (touchpad) { - if (list->touch) { - fx(0) = value; - if (list->pkt_count >= 2) - list->dx = ((fx(0) - fx(1)) / 2 + (fx(1) - fx(2)) / 2) / 8; - } - } else { - size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X]; - if (size == 0) size = xres; - list->dx += (value * xres - list->old_x[0]) / size; - list->old_x[0] += list->dx * size; - } + size = dev->absmax[ABS_X] - dev->absmin[ABS_X]; + if (size == 0) size = xres; + mousedev->packet.dx = (value * xres - mousedev->old_x[0]) / size; + mousedev->old_x[0] = mousedev->packet.dx * size; break; + case ABS_Y: - if (touchpad) { - if (list->touch) { - fy(0) = value; - if (list->pkt_count >= 2) - list->dy = -((fy(0) - fy(1)) / 2 + (fy(1) - fy(2)) / 2) / 8; - } - } else { - size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y]; - if (size == 0) size = yres; - list->dy -= (value * yres - list->old_y[0]) / size; - list->old_y[0] -= list->dy * size; - } + size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y]; + if (size == 0) size = yres; + mousedev->packet.dy = (value * yres - mousedev->old_y[0]) / size; + mousedev->old_y[0] = mousedev->packet.dy * size; break; } } -static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) +static void mousedev_rel_event(struct mousedev *mousedev, unsigned int code, int value) +{ + switch (code) { + case REL_X: mousedev->packet.dx += value; break; + case REL_Y: mousedev->packet.dy -= value; break; + case REL_WHEEL: mousedev->packet.dz -= value; break; + } +} + +static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int value) +{ + int index; + + switch (code) { + case BTN_TOUCH: + case BTN_0: + case BTN_FORWARD: + case BTN_LEFT: index = 0; break; + case BTN_STYLUS: + case BTN_1: + case BTN_RIGHT: index = 1; break; + case BTN_2: + case BTN_STYLUS2: + case BTN_MIDDLE: index = 2; break; + case BTN_3: + case BTN_BACK: + case BTN_SIDE: index = 3; break; + case BTN_4: + case BTN_EXTRA: index = 4; break; + default: return; + } + + if (value) { + set_bit(index, &mousedev->buttons); + set_bit(index, &mousedev_mix.buttons); + } else { + clear_bit(index, &mousedev->buttons); + clear_bit(index, &mousedev_mix.buttons); + } +} + +static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_motion *packet) { - struct mousedev *mousedevs[3] = { handle->private, &mousedev_mix, NULL }; - struct mousedev **mousedev = mousedevs; struct mousedev_list *list; - int index, wake; - while (*mousedev) { + list_for_each_entry(list, &mousedev->list, node) { + list->dx += packet->dx; + list->dy += packet->dy; + list->dz += packet->dz; + list->buttons = mousedev->buttons; + list->ready = 1; + kill_fasync(&list->fasync, SIGIO, POLL_IN); + } + + wake_up_interruptible(&mousedev->wait); +} + +static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) +{ + struct mousedev *mousedev = handle->private; + + switch (type) { + case EV_ABS: + /* Ignore joysticks */ + if (test_bit(BTN_TRIGGER, handle->dev->keybit)) + return; + + if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) + mousedev_touchpad_event(mousedev, code, value); + else + mousedev_abs_event(handle->dev, mousedev, code, value); - wake = 0; + break; - list_for_each_entry(list, &(*mousedev)->list, node) - switch (type) { - case EV_ABS: - mousedev_abs_event(handle, list, code, value); - break; - - case EV_REL: - switch (code) { - case REL_X: list->dx += value; break; - case REL_Y: list->dy -= value; break; - case REL_WHEEL: if (list->mode) list->dz -= value; break; - } - break; - - case EV_KEY: - if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) { - /* Handle touchpad data */ - list->touch = value; - if (!list->touch) - list->pkt_count = 0; - break; - } - - switch (code) { - case BTN_TOUCH: - case BTN_0: - case BTN_FORWARD: - case BTN_LEFT: index = 0; break; - case BTN_4: - case BTN_EXTRA: if (list->mode == 2) { index = 4; break; } - case BTN_STYLUS: - case BTN_1: - case BTN_RIGHT: index = 1; break; - case BTN_3: - case BTN_BACK: - case BTN_SIDE: if (list->mode == 2) { index = 3; break; } - case BTN_2: - case BTN_STYLUS2: - case BTN_MIDDLE: index = 2; break; - default: return; - } - switch (value) { - case 0: clear_bit(index, &list->buttons); break; - case 1: set_bit(index, &list->buttons); break; - case 2: return; - } - break; - - case EV_SYN: - switch (code) { - case SYN_REPORT: - if (list->touch) { - list->pkt_count++; - /* Input system eats duplicate events, - * but we need all of them to do correct - * averaging so apply present one forward - */ - fx(0) = fx(1); - fy(0) = fy(1); - } - - list->ready = 1; - kill_fasync(&list->fasync, SIGIO, POLL_IN); - wake = 1; - break; - } + case EV_REL: + mousedev_rel_event(mousedev, code, value); + break; + + case EV_KEY: + if (value != 2) { + if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) { + /* Handle touchpad data */ + mousedev->touch = value; + if (!mousedev->touch) + mousedev->pkt_count = 0; + } + else + mousedev_key_event(mousedev, code, value); } + break; - if (wake) - wake_up_interruptible(&((*mousedev)->wait)); + case EV_SYN: + if (code == SYN_REPORT) { + if (mousedev->touch) { + mousedev->pkt_count++; + /* Input system eats duplicate events, but we need all of them + * to do correct averaging so apply present one forward + */ + fx(0) = fx(1); + fy(0) = fy(1); + } + + mousedev_notify_readers(mousedev, &mousedev->packet); + mousedev_notify_readers(&mousedev_mix, &mousedev->packet); - mousedev++; + memset(&mousedev->packet, 0, sizeof(struct mousedev_motion)); + } + break; } } @@ -267,7 +296,7 @@ mousedev_free(list->mousedev); } } - + kfree(list); return 0; } @@ -301,11 +330,11 @@ if (list->mousedev->minor == MOUSEDEV_MIX) { list_for_each_entry(handle, &mousedev_handler.h_list, h_node) { mousedev = handle->private; - if (!mousedev->open && mousedev->exist) + if (!mousedev->open && mousedev->exist) input_open_device(handle); } - } else - if (!mousedev_mix.open && list->mousedev->exist) + } else + if (!mousedev_mix.open && list->mousedev->exist) input_open_device(&list->mousedev->handle); } @@ -326,8 +355,10 @@ list->dz -= list->ps2[off + 3]; list->ps2[off + 3] = (list->ps2[off + 3] & 0x0f) | ((list->buttons & 0x18) << 1); list->bufsiz++; + } else { + list->ps2[off] |= ((list->buttons & 0x10) >> 3) | ((list->buttons & 0x08) >> 1); } - + if (list->mode == 1) { list->ps2[off + 3] = (list->dz > 127 ? 127 : (list->dz < -127 ? -127 : list->dz)); list->dz -= list->ps2[off + 3]; @@ -391,9 +422,9 @@ list->impsseq = 0; list->imexseq = 0; list->mode = 0; - list->ps2[0] = 0xaa; - list->ps2[1] = 0x00; - list->bufsiz = 2; + list->ps2[1] = 0xaa; + list->ps2[2] = 0x00; + list->bufsiz = 3; break; } @@ -403,7 +434,7 @@ kill_fasync(&list->fasync, SIGIO, POLL_IN); wake_up_interruptible(&list->mousedev->wait); - + return count; } @@ -431,7 +462,7 @@ if (copy_to_user(buffer, list->ps2 + list->bufsiz - list->buffer - count, count)) return -EFAULT; - return count; + return count; } /* No kernel lock - fine */ @@ -487,7 +518,7 @@ devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor); - class_simple_device_add(input_class, + class_simple_device_add(input_class, MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), dev->dev, "mouse%d", minor); @@ -538,7 +569,7 @@ }; MODULE_DEVICE_TABLE(input, mousedev_ids); - + static struct input_handler mousedev_handler = { .event = mousedev_event, .connect = mousedev_connect, @@ -553,6 +584,7 @@ static struct miscdevice psaux_mouse = { PSMOUSE_MINOR, "psaux", &mousedev_fops }; +static int psaux_registered; #endif static int __init mousedev_init(void) @@ -572,7 +604,7 @@ NULL, "mice"); #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX - if (!(mousedev_mix.misc = !misc_register(&psaux_mouse))) + if (!(psaux_registered = !misc_register(&psaux_mouse))) printk(KERN_WARNING "mice: could not misc_register the device\n"); #endif @@ -584,7 +616,7 @@ static void __exit mousedev_exit(void) { #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX - if (mousedev_mix.misc) + if (psaux_registered) misc_deregister(&psaux_mouse); #endif devfs_remove("input/mice"); --- diff/drivers/input/power.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/power.c 2004-05-27 18:34:16.000000000 +0100 @@ -1,7 +1,7 @@ /* * $Id: power.c,v 1.10 2001/09/25 09:17:15 vojtech Exp $ * - * Copyright (c) 2001 "Crazy" James Simmons + * Copyright (c) 2001 "Crazy" James Simmons * * Input driver Power Management. * @@ -51,7 +51,7 @@ static DECLARE_WORK(suspend_button_task, suspend_button_task_handler, NULL); -static void power_event(struct input_handle *handle, unsigned int type, +static void power_event(struct input_handle *handle, unsigned int type, unsigned int code, int down) { struct input_dev *dev = handle->dev; @@ -73,7 +73,7 @@ case KEY_POWER: /* Hum power down the machine. */ break; - default: + default: return; } } else { @@ -83,9 +83,9 @@ /* This is risky. See pm.h for details. */ if (dev->state != PM_RESUME) dev->state = PM_RESUME; - else - dev->state = PM_SUSPEND; - pm_send(dev->pm_dev, dev->state, dev); + else + dev->state = PM_SUSPEND; + pm_send(dev->pm_dev, dev->state, dev); break; case KEY_POWER: /* Turn the input device off completely ? */ @@ -97,14 +97,14 @@ return; } -static struct input_handle *power_connect(struct input_handler *handler, - struct input_dev *dev, +static struct input_handle *power_connect(struct input_handler *handler, + struct input_dev *dev, struct input_device_id *id) { struct input_handle *handle; if (!test_bit(EV_KEY, dev->evbit) || !test_bit(EV_PWR, dev->evbit)) - return NULL; + return NULL; if (!test_bit(KEY_SUSPEND, dev->keybit) || (!test_bit(KEY_POWER, dev->keybit))) return NULL; @@ -133,21 +133,21 @@ .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, .evbit = { BIT(EV_KEY) }, .keybit = { [LONG(KEY_SUSPEND)] = BIT(KEY_SUSPEND) } - }, + }, { .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, .evbit = { BIT(EV_KEY) }, .keybit = { [LONG(KEY_POWER)] = BIT(KEY_POWER) } - }, + }, { .flags = INPUT_DEVICE_ID_MATCH_EVBIT, .evbit = { BIT(EV_PWR) }, - }, + }, { }, /* Terminating entry */ }; MODULE_DEVICE_TABLE(input, power_ids); - + static struct input_handler power_handler = { .event = power_event, .connect = power_connect, @@ -172,3 +172,4 @@ MODULE_AUTHOR("James Simmons "); MODULE_DESCRIPTION("Input Power Management driver"); +MODULE_LICENSE("GPL"); --- diff/drivers/input/serio/98kbd-io.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/serio/98kbd-io.c 2004-05-27 18:34:16.000000000 +0100 @@ -42,8 +42,8 @@ * Register numbers. */ -#define KBD98_COMMAND_REG 0x43 -#define KBD98_STATUS_REG 0x43 +#define KBD98_COMMAND_REG 0x43 +#define KBD98_STATUS_REG 0x43 #define KBD98_DATA_REG 0x41 spinlock_t kbd98io_lock = SPIN_LOCK_UNLOCKED; @@ -51,7 +51,7 @@ static struct serio kbd98_port; extern struct pt_regs *kbd_pt_regs; -static void kbd98io_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t kbd98io_interrupt(int irq, void *dev_id, struct pt_regs *regs); /* * kbd98_flush() flushes all data that may be in the keyboard buffers @@ -143,7 +143,7 @@ * to the upper layers. */ -static void kbd98io_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t kbd98io_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned long flags; unsigned char data; @@ -154,6 +154,7 @@ spin_unlock_irqrestore(&kbd98io_lock, flags); serio_interrupt(&kbd98_port, data, 0, regs); + return IRQ_HANDLED; } int __init kbd98io_init(void) --- diff/drivers/input/serio/Kconfig 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/serio/Kconfig 2004-05-27 18:34:16.000000000 +0100 @@ -97,16 +97,6 @@ tristate "Intel SA1111 keyboard controller" depends on SA1111 && SERIO -config SERIO_98KBD - tristate "NEC PC-9800 keyboard controller" - depends on X86_PC9800 && SERIO - help - Say Y here if you have the NEC PC-9801/PC-9821 and want to use its - standard keyboard connected to its keyboard controller. - - To compile this driver as a module, choose M here: the - module will be called 98kbd-io. - config SERIO_GSCPS2 tristate "HP GSC PS/2 keyboard and PS/2 mouse controller" depends on GSC && SERIO --- diff/drivers/input/serio/ct82c710.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/serio/ct82c710.c 2004-05-27 18:34:16.000000000 +0100 @@ -11,18 +11,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic --- diff/drivers/input/serio/gscps2.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/serio/gscps2.c 2004-05-27 18:34:16.000000000 +0100 @@ -16,7 +16,7 @@ * 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. - * + * * TODO: * - Dino testing (did HP ever shipped a machine on which this port * was usable/enabled ?) @@ -44,7 +44,7 @@ #define PFX "gscps2.c: " -/* +/* * Driver constants */ @@ -222,7 +222,7 @@ /** * gscps2_interrupt() - Interruption service routine * - * This function reads received PS/2 bytes and processes them on + * This function reads received PS/2 bytes and processes them on * all interfaces. * The problematic part here is, that the keyboard and mouse PS/2 port * share the same interrupt and it's not possible to send data if any @@ -240,9 +240,9 @@ unsigned long flags; spin_lock_irqsave(&ps2port->lock, flags); - while ( (ps2port->buffer[ps2port->append].str = + while ( (ps2port->buffer[ps2port->append].str = gscps2_readb_status(ps2port->addr)) & GSC_STAT_RBNE ) { - ps2port->buffer[ps2port->append].data = + ps2port->buffer[ps2port->append].data = gscps2_readb_input(ps2port->addr); ps2port->append = ((ps2port->append+1) & BUFFER_SIZE); } @@ -349,7 +349,7 @@ if (!dev->irq) return -ENODEV; - + /* Offset for DINO PS/2. Works with LASI even */ if (dev->id.sversion == 0x96) hpa += GSC_DINO_OFFSET; @@ -368,7 +368,7 @@ gscps2_reset(ps2port); ps2port->id = readb(ps2port->addr+GSC_ID) & 0x0f; snprintf(ps2port->name, sizeof(ps2port->name)-1, "%s %s", - gscps2_serio_port.name, + gscps2_serio_port.name, (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse" ); memcpy(&ps2port->port, &gscps2_serio_port, sizeof(gscps2_serio_port)); @@ -401,9 +401,9 @@ ps2port->port.phys); serio_register_port(&ps2port->port); - + return 0; - + fail: free_irq(dev->irq, ps2port); @@ -430,7 +430,7 @@ list_del(&ps2port->node); iounmap(ps2port->addr); #if 0 - release_mem_region(dev->hpa, GSC_STATUS + 4); + release_mem_region(dev->hpa, GSC_STATUS + 4); #endif dev_set_drvdata(&dev->dev, NULL); kfree(ps2port); @@ -441,7 +441,7 @@ static struct parisc_device_id gscps2_device_tbl[] = { { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 }, /* LASI PS/2 */ #ifdef DINO_TESTED - { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00096 }, /* DINO PS/2 */ + { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00096 }, /* DINO PS/2 */ #endif { 0, } /* 0 terminated list */ }; --- diff/drivers/input/serio/i8042.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/serio/i8042.c 2004-05-27 18:34:16.000000000 +0100 @@ -32,7 +32,7 @@ module_param_named(noaux, i8042_noaux, bool, 0); MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); -static unsigned int i8042_nomux; +unsigned int i8042_nomux; module_param_named(nomux, i8042_nomux, bool, 0); MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing conrtoller is present."); @@ -150,7 +150,7 @@ */ static int i8042_command(unsigned char *param, int command) -{ +{ unsigned long flags; int retval = 0, i = 0; @@ -161,7 +161,7 @@ dbg("%02x -> i8042 (command)", command & 0xff); i8042_write_command(command & 0xff); } - + if (!retval) for (i = 0; i < ((command >> 12) & 0xf); i++) { if ((retval = i8042_wait_write())) break; @@ -172,7 +172,7 @@ if (!retval) for (i = 0; i < ((command >> 8) & 0xf); i++) { if ((retval = i8042_wait_read())) break; - if (i8042_read_status() & I8042_STR_AUXDATA) + if (i8042_read_status() & I8042_STR_AUXDATA) param[i] = ~i8042_read_data(); else param[i] = i8042_read_data(); @@ -415,17 +415,17 @@ } else dfl = 0; dbg("%02x <- i8042 (interrupt, aux%d, %d%s%s)", - data, (str >> 6), irq, + data, (str >> 6), irq, dfl & SERIO_PARITY ? ", bad parity" : "", dfl & SERIO_TIMEOUT ? ", timeout" : ""); serio_interrupt(i8042_mux_port + ((str >> 6) & 3), data, dfl, regs); - + goto irq_ret; } dbg("%02x <- i8042 (interrupt, %s, %d%s%s)", - data, (str & I8042_STR_AUXDATA) ? "aux" : "kbd", irq, + data, (str & I8042_STR_AUXDATA) ? "aux" : "kbd", irq, dfl & SERIO_PARITY ? ", bad parity" : "", dfl & SERIO_TIMEOUT ? ", timeout" : ""); @@ -474,8 +474,17 @@ if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0xa9) return -1; param = 0xa4; - if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == 0x5b) + if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == 0x5b) { + +/* + * Do another loop test with the 0x5a value. Doing anything else upsets + * Profusion/ServerWorks OSB4 chipsets. + */ + + param = 0x5a; + i8042_command(¶m, I8042_CMD_AUX_LOOP); return -1; + } if (mux_version) *mux_version = ~param; @@ -530,10 +539,10 @@ if (i8042_enable_mux_mode(values, &mux_version)) return -1; - + /* Workaround for broken chips which seem to support MUX, but in reality don't. */ - /* They all report version 12.10 */ - if (mux_version == 0xCA) + /* They all report version 10.12 */ + if (mux_version == 0xAC) return -1; printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", @@ -598,7 +607,7 @@ /* * Bit assignment test - filters out PS/2 i8042's in AT mode */ - + if (i8042_command(¶m, I8042_CMD_AUX_DISABLE)) return -1; if (i8042_command(¶m, I8042_CMD_CTL_RCTR) || (~param & I8042_CTR_AUXDIS)) { @@ -609,7 +618,7 @@ if (i8042_command(¶m, I8042_CMD_AUX_ENABLE)) return -1; if (i8042_command(¶m, I8042_CMD_CTL_RCTR) || (param & I8042_CTR_AUXDIS)) - return -1; + return -1; /* * Disable the interface. @@ -639,7 +648,7 @@ if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { printk(KERN_WARNING "i8042.c: Can't write CTR while registering.\n"); values->exists = 0; - return -1; + return -1; } printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n", @@ -868,7 +877,7 @@ static int i8042_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { - if (code==SYS_DOWN || code==SYS_HALT) + if (code == SYS_DOWN || code == SYS_HALT) i8042_controller_cleanup(); return NOTIFY_DONE; } @@ -997,20 +1006,20 @@ sysdev_class_unregister(&kbc_sysclass); } - del_timer_sync(&i8042_timer); - i8042_controller_cleanup(); - + if (i8042_kbd_values.exists) serio_unregister_port(&i8042_kbd_port); if (i8042_aux_values.exists) serio_unregister_port(&i8042_aux_port); - + for (i = 0; i < 4; i++) if (i8042_mux_values[i].exists) serio_unregister_port(i8042_mux_port + i); + del_timer_sync(&i8042_timer); + i8042_platform_exit(); } --- diff/drivers/input/serio/parkbd.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/serio/parkbd.c 2004-05-27 18:34:16.000000000 +0100 @@ -11,18 +11,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -86,20 +86,9 @@ return 0; } -static int parkbd_open(struct serio *port) -{ - return 0; -} - -static void parkbd_close(struct serio *port) -{ -} - static struct serio parkbd_port = { .write = parkbd_write, - .open = parkbd_open, - .close = parkbd_close, .name = parkbd_name, .phys = parkbd_phys, }; @@ -115,7 +104,7 @@ parkbd_writing = 0; parkbd_writelines(3); return; - } + } parkbd_writelines(((parkbd_buffer >> parkbd_counter++) & 1) | 2); @@ -131,7 +120,7 @@ if ((parkbd_counter == parkbd_mode + 10) || time_after(jiffies, parkbd_last + HZ/100)) { parkbd_counter = 0; parkbd_buffer = 0; - } + } parkbd_buffer |= (parkbd_readlines() >> 1) << parkbd_counter++; --- diff/drivers/input/serio/q40kbd.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/serio/q40kbd.c 2004-05-27 18:34:16.000000000 +0100 @@ -4,7 +4,7 @@ * Copyright (c) 2000-2001 Vojtech Pavlik * * Based on the work of: - * Richard Zidlicky + * Richard Zidlicky */ /* @@ -47,23 +47,12 @@ MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver"); MODULE_LICENSE("GPL"); - -static int q40kbd_open(struct serio *port) -{ - return 0; -} -static void q40kbd_close(struct serio *port) -{ -} - static struct serio q40kbd_port = { .type = SERIO_8042, .name = "Q40 kbd port", .phys = "Q40", .write = NULL, - .open = q40kbd_open, - .close = q40kbd_close, }; static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, --- diff/drivers/input/serio/rpckbd.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/serio/rpckbd.c 2004-05-27 18:34:16.000000000 +0100 @@ -98,7 +98,7 @@ static void rpckbd_close(struct serio *port) { free_irq(IRQ_KEYBOARDRX, port); - free_irq(IRQ_KEYBOARDTX, port); + free_irq(IRQ_KEYBOARDTX, port); } static struct serio rpckbd_port = --- diff/drivers/input/serio/sa1111ps2.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/serio/sa1111ps2.c 2004-05-27 18:34:16.000000000 +0100 @@ -45,7 +45,6 @@ { struct ps2if *ps2if = dev_id; unsigned int scancode, flag, status; - int handled = IRQ_NONE; status = sa1111_readl(ps2if->base + SA1111_PS2STAT); while (status & PS2STAT_RXF) { @@ -63,11 +62,9 @@ serio_interrupt(&ps2if->io, scancode, flag, regs); status = sa1111_readl(ps2if->base + SA1111_PS2STAT); - - handled = IRQ_HANDLED; } - return handled; + return IRQ_HANDLED; } /* --- diff/drivers/input/serio/serio.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/serio/serio.c 2004-05-27 18:34:16.000000000 +0100 @@ -11,18 +11,18 @@ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic @@ -108,7 +108,7 @@ struct serio_event *event; list_for_each_safe(node, next, &serio_event_list) { - event = container_of(node, struct serio_event, node); + event = container_of(node, struct serio_event, node); down(&serio_sem); if (event->serio == NULL) @@ -152,7 +152,7 @@ do { serio_handle_events(); - wait_event_interruptible(serio_wait, !list_empty(&serio_event_list)); + wait_event_interruptible(serio_wait, !list_empty(&serio_event_list)); if (current->flags & PF_FREEZE) refrigerator(PF_FREEZE); } while (!signal_pending(current)); @@ -195,9 +195,6 @@ ret = serio->dev->interrupt(serio, data, flags, regs); } else { if (!flags) { - if ((serio->type == SERIO_8042 || - serio->type == SERIO_8042_XL) && (data != 0xaa)) - return ret; serio_rescan(serio); ret = IRQ_HANDLED; } @@ -293,7 +290,7 @@ int serio_open(struct serio *serio, struct serio_dev *dev) { serio->dev = dev; - if (serio->open(serio)) { + if (serio->open && serio->open(serio)) { serio->dev = NULL; return -1; } @@ -303,7 +300,8 @@ /* called from serio_dev->connect/disconnect methods under serio_sem */ void serio_close(struct serio *serio) { - serio->close(serio); + if (serio->close) + serio->close(serio); serio->dev = NULL; } --- diff/drivers/input/serio/serport.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/serio/serport.c 2004-05-27 18:34:16.000000000 +0100 @@ -48,11 +48,6 @@ return -(serport->tty->driver->write(serport->tty, 0, &data, 1) != 1); } -static int serport_serio_open(struct serio *serio) -{ - return 0; -} - static void serport_serio_close(struct serio *serio) { struct serport *serport = serio->driver; @@ -87,7 +82,6 @@ serport->serio.type = SERIO_RS232; serport->serio.write = serport_serio_write; - serport->serio.open = serport_serio_open; serport->serio.close = serport_serio_close; serport->serio.driver = serport; @@ -135,7 +129,7 @@ } /* - * serport_ldisc_read() just waits indefinitely if everything goes well. + * serport_ldisc_read() just waits indefinitely if everything goes well. * However, when the serio driver closes the serio port, it finishes, * returning 0 characters. */ @@ -165,7 +159,7 @@ static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg) { struct serport *serport = (struct serport*) tty->disc_data; - + if (cmd == SPIOCSTYPE) return get_user(serport->serio.type, (unsigned long *) arg); --- diff/drivers/input/touchscreen/gunze.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/touchscreen/gunze.c 2004-05-27 18:34:16.000000000 +0100 @@ -124,12 +124,10 @@ memset(gunze, 0, sizeof(struct gunze)); init_input_dev(&gunze->dev); - gunze->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - gunze->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); + gunze->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); gunze->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - - gunze->dev.absmin[ABS_X] = 96; gunze->dev.absmin[ABS_Y] = 72; - gunze->dev.absmax[ABS_X] = 4000; gunze->dev.absmax[ABS_Y] = 3000; + input_set_abs_params(&gunze->dev, ABS_X, 96, 4000, 0, 0); + input_set_abs_params(&gunze->dev, ABS_Y, 72, 3000, 0, 0); gunze->serio = serio; serio->private = gunze; --- diff/drivers/input/touchscreen/h3600_ts_input.c 2004-05-19 22:11:44.000000000 +0100 +++ source/drivers/input/touchscreen/h3600_ts_input.c 2004-05-27 18:34:16.000000000 +0100 @@ -1,11 +1,11 @@ /* * $Id: h3600_ts_input.c,v 1.4 2002/01/23 06:39:37 jsimmons Exp $ * - * Copyright (c) 2001 "Crazy" James Simmons jsimmons@transvirtual.com + * Copyright (c) 2001 "Crazy" James Simmons jsimmons@transvirtual.com * - * Sponsored by Transvirtual Technology. - * - * Derived from the code in h3600_ts.[ch] by Charles Flynn + * Sponsored by Transvirtual Technology. + * + * Derived from the code in h3600_ts.[ch] by Charles Flynn */ /* @@ -45,6 +45,10 @@ #include #include +MODULE_AUTHOR("James Simmons "); +MODULE_DESCRIPTION("H3600 touchscreen driver"); +MODULE_LICENSE("GPL"); + /* * Definitions & global arrays. */ @@ -75,7 +79,7 @@ #define MAX_ID 14 #define H3600_MAX_LENGTH 16 -#define H3600_KEY 0xf +#define H3600_KEY 0xf #define H3600_SCANCODE_RECORD 1 /* 1 -> record button */ #define H3600_SCANCODE_CALENDAR 2 /* 2 -> calendar */ @@ -103,7 +107,7 @@ char phys[32]; }; -static void action_button_handler(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs *regs) { int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1; struct input_dev *dev = (struct input_dev *) dev_id; @@ -111,21 +115,25 @@ input_regs(dev, regs); input_report_key(dev, KEY_ENTER, down); input_sync(dev); + + return IRQ_HANDLED; } -static void npower_button_handler(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs *regs) { int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; struct input_dev *dev = (struct input_dev *) dev_id; - /* - * This interrupt is only called when we release the key. So we have + /* + * This interrupt is only called when we release the key. So we have * to fake a key press. - */ + */ input_regs(dev, regs); input_report_key(dev, KEY_SUSPEND, 1); - input_report_key(dev, KEY_SUSPEND, down); + input_report_key(dev, KEY_SUSPEND, down); input_sync(dev); + + return IRQ_HANDLED; } #ifdef CONFIG_PM @@ -141,21 +149,21 @@ * h3600_flite_power: enables or disables power to frontlight, using last bright */ unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr) { - unsigned char brightness = ((pwr==FLITE_PWR_OFF) ? 0:flite_brightness); + unsigned char brightness = (pwr == FLITE_PWR_OFF) ? 0 : flite_brightness; struct h3600_dev *ts = dev->private; - /* Must be in this order */ + /* Must be in this order */ ts->serio->write(ts->serio, 1); ts->serio->write(ts->serio, pwr); - ts->serio->write(ts->serio, brightness); + ts->serio->write(ts->serio, brightness); return 0; } static int suspended = 0; -static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req, +static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) { - struct input_dev *dev = (struct input_dev *) data; + struct input_dev *dev = (struct input_dev *) data; switch (req) { case PM_SUSPEND: /* enter D1-D3 */ @@ -183,7 +191,7 @@ /* * This function translates the native event packets to linux input event * packets. Some packets coming from serial are not touchscreen related. In - * this case we send them off to be processed elsewhere. + * this case we send them off to be processed elsewhere. */ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) { @@ -206,7 +214,7 @@ Note: This is true for non interrupt generated key events. */ case KEYBD_ID: - down = (ts->buf[0] & 0x80) ? 0 : 1; + down = (ts->buf[0] & 0x80) ? 0 : 1; switch (ts->buf[0] & 0x7f) { case H3600_SCANCODE_RECORD: @@ -218,7 +226,7 @@ case H3600_SCANCODE_CONTACTS: key = KEY_PROG2; break; - case H3600_SCANCODE_Q: + case H3600_SCANCODE_Q: key = KEY_Q; break; case H3600_SCANCODE_START: @@ -237,9 +245,9 @@ key = KEY_DOWN; break; default: - key = 0; - } - if (key) + key = 0; + } + if (key) input_report_key(dev, key, down); break; /* @@ -251,13 +259,13 @@ * byte 0 1 2 3 */ case TOUCHS_ID: - if (!touched) { + if (!touched) { input_report_key(dev, BTN_TOUCH, 1); touched = 1; - } + } if (ts->len) { - unsigned short x, y; + unsigned short x, y; x = ts->buf[0]; x <<= 8; x += ts->buf[1]; y = ts->buf[2]; y <<= 8; y += ts->buf[3]; @@ -267,7 +275,7 @@ } else { input_report_key(dev, BTN_TOUCH, 0); touched = 0; - } + } break; default: /* Send a non input event elsewhere */ @@ -280,7 +288,7 @@ /* * h3600ts_event() handles events from the input module. */ -static int h3600ts_event(struct input_dev *dev, unsigned int type, +static int h3600ts_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { struct h3600_dev *ts = dev->private; @@ -290,7 +298,7 @@ // ts->serio->write(ts->serio, SOME_CMD); return 0; } - } + } return -1; } @@ -317,19 +325,19 @@ #define STATE_DATA 2 /* state where we decode data */ #define STATE_EOF 3 /* state where we decode checksum or EOF */ -static void h3600ts_interrupt(struct serio *serio, unsigned char data, - unsigned int flags) +static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data, + unsigned int flags, struct pt_regs *regs) { struct h3600_dev *ts = serio->private; /* - * We have a new frame coming in. + * We have a new frame coming in. */ switch (state) { case STATE_SOF: if (data == CHAR_SOF) - state = STATE_ID; - return; + state = STATE_ID; + break; case STATE_ID: ts->event = (data & 0xf0) >> 4; ts->len = (data & 0xf); @@ -339,23 +347,25 @@ break; } ts->chksum = data; - state=(ts->len > 0 ) ? STATE_DATA : STATE_EOF; + state = (ts->len > 0) ? STATE_DATA : STATE_EOF; break; case STATE_DATA: ts->chksum += data; ts->buf[ts->idx]= data; - if(++ts->idx == ts->len) + if(++ts->idx == ts->len) state = STATE_EOF; break; case STATE_EOF: state = STATE_SOF; - if (data == CHAR_EOF || data == ts->chksum ) - h3600ts_process_packet(ts); + if (data == CHAR_EOF || data == ts->chksum) + h3600ts_process_packet(ts, regs); break; default: printk("Error3\n"); break; } + + return IRQ_HANDLED; } /* @@ -378,11 +388,11 @@ init_input_dev(&ts->dev); /* Device specific stuff */ - set_GPIO_IRQ_edge( GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES ); - set_GPIO_IRQ_edge( GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE ); + set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES); + set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE); if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, - SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, + SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, "h3600_action", &ts->dev)) { printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); kfree(ts); @@ -390,24 +400,19 @@ } if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, - SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, + SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, "h3600_suspend", &ts->dev)) { free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev); printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n"); kfree(ts); return; } + /* Now we have things going we setup our input device */ ts->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_LED) | BIT(EV_PWR); - ts->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); - ts->dev.ledbit[0] = BIT(LED_SLEEP); - - ts->dev.absmin[ABS_X] = 60; ts->dev.absmin[ABS_Y] = 35; - ts->dev.absmax[ABS_X] = 985; ts->dev.absmax[ABS_Y] = 1024; - ts->dev.absfuzz[ABS_X] = 0; ts->dev.absfuzz[ABS_Y] = 0; - - ts->serio = serio; - serio->private = ts; + ts->dev.ledbit[0] = BIT(LED_SLEEP); + input_set_abs_params(&ts->dev, ABS_X, 60, 985, 0, 0); + input_set_abs_params(&ts->dev, ABS_Y, 35, 1024, 0, 0); set_bit(KEY_RECORD, ts->dev.keybit); set_bit(KEY_Q, ts->dev.keybit); @@ -422,6 +427,9 @@ ts->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH); ts->dev.keybit[LONG(KEY_SUSPEND)] |= BIT(KEY_SUSPEND); + ts->serio = serio; + serio->private = ts; + sprintf(ts->phys, "%s/input0", serio->phys); ts->dev.event = h3600ts_event; @@ -442,7 +450,7 @@ //h3600_flite_control(1, 25); /* default brightness */ #ifdef CONFIG_PM - ts->dev.pm_dev = pm_register(PM_ILLUMINATION_DEV, PM_SYS_LIGHT, + ts->dev.pm_dev = pm_register(PM_ILLUMINATION_DEV, PM_SYS_LIGHT, h3600ts_pm_callback); printk("registered pm callback\n"); #endif @@ -458,7 +466,7 @@ static void h3600ts_disconnect(struct serio *serio) { struct h3600_dev *ts = serio->private; - + free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev); free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, &ts->dev); input_unregister_device(&ts->dev); --- diff/drivers/input/tsdev.c 2004-05-19 22:11:43.000000000 +0100 +++ source/drivers/input/tsdev.c 2004-05-27 18:34:16.000000000 +0100 @@ -3,9 +3,17 @@ * * Copyright (c) 2001 "Crazy" james Simmons * - * Input driver to Touchscreen device driver module. + * Compaq touchscreen protocol driver. The protocol emulated by this driver + * is obsolete; for new programs use the tslib library which can read directly + * from evdev and perform dejittering, variance filtering and calibration - + * all in user space, not at kernel level. The meaning of this driver is + * to allow usage of newer input drivers with old applications that use the + * old /dev/h3600_ts and /dev/h3600_tsraw devices. * - * Sponsored by Transvirtual Technology + * 09-Apr-2004: Andrew Zabolotny + * Fixed to actually work, not just output random numbers. + * Added support for both h3600_ts and h3600_tsraw protocol + * emulation. */ /* @@ -24,11 +32,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to . + * e-mail - mail your message to . */ #define TSDEV_MINOR_BASE 128 #define TSDEV_MINORS 32 +/* First 16 devices are h3600_ts compatible; second 16 are h3600_tsraw */ +#define TSDEV_MINOR_MASK 15 #define TSDEV_BUFFER_SIZE 64 #include @@ -52,48 +62,84 @@ #define CONFIG_INPUT_TSDEV_SCREEN_Y 320 #endif +/* This driver emulates both protocols of the old h3600_ts and h3600_tsraw + * devices. The first one must output X/Y data in 'cooked' format, e.g. + * filtered, dejittered and calibrated. Second device just outputs raw + * data received from the hardware. + * + * This driver doesn't support filtering and dejittering; it supports only + * calibration. Filtering and dejittering must be done in the low-level + * driver, if needed, because it may gain additional benefits from knowing + * the low-level details, the nature of noise and so on. + * + * The driver precomputes a calibration matrix given the initial xres and + * yres values (quite innacurate for most touchscreens) that will result + * in a more or less expected range of output values. The driver supports + * the TS_SET_CAL ioctl, which will replace the calibration matrix with a + * new one, supposedly generated from the values taken from the raw device. + */ + MODULE_AUTHOR("James Simmons "); MODULE_DESCRIPTION("Input driver to touchscreen converter"); MODULE_LICENSE("GPL"); static int xres = CONFIG_INPUT_TSDEV_SCREEN_X; module_param(xres, uint, 0); -MODULE_PARM_DESC(xres, "Horizontal screen resolution"); +MODULE_PARM_DESC(xres, "Horizontal screen resolution (can be negative for X-mirror)"); static int yres = CONFIG_INPUT_TSDEV_SCREEN_Y; module_param(yres, uint, 0); -MODULE_PARM_DESC(yres, "Vertical screen resolution"); +MODULE_PARM_DESC(yres, "Vertical screen resolution (can be negative for Y-mirror)"); + +/* From Compaq's Touch Screen Specification version 0.2 (draft) */ +struct ts_event { + short pressure; + short x; + short y; + short millisecs; +}; + +struct ts_calibration { + int xscale; + int xtrans; + int yscale; + int ytrans; + int xyswap; +}; struct tsdev { int exist; int open; int minor; - char name[16]; + char name[8]; wait_queue_head_t wait; struct list_head list; struct input_handle handle; + int x, y, pressure; + struct ts_calibration cal; }; -/* From Compaq's Touch Screen Specification version 0.2 (draft) */ -typedef struct { - short pressure; - short x; - short y; - short millisecs; -} TS_EVENT; - struct tsdev_list { struct fasync_struct *fasync; struct list_head node; struct tsdev *tsdev; int head, tail; - int oldx, oldy, pendown; - TS_EVENT event[TSDEV_BUFFER_SIZE]; + struct ts_event event[TSDEV_BUFFER_SIZE]; + int raw; }; +/* The following ioctl codes are defined ONLY for backward compatibility. + * Don't use tsdev for new developement; use the tslib library instead. + * Touchscreen calibration is a fully userspace task. + */ +/* Use 'f' as magic number */ +#define IOC_H3600_TS_MAGIC 'f' +#define TS_GET_CAL _IOR(IOC_H3600_TS_MAGIC, 10, struct ts_calibration) +#define TS_SET_CAL _IOW(IOC_H3600_TS_MAGIC, 11, struct ts_calibration) + static struct input_handler tsdev_handler; -static struct tsdev *tsdev_table[TSDEV_MINORS]; +static struct tsdev *tsdev_table[TSDEV_MINORS/2]; static int tsdev_fasync(int fd, struct file *file, int on) { @@ -109,13 +155,16 @@ int i = iminor(inode) - TSDEV_MINOR_BASE; struct tsdev_list *list; - if (i >= TSDEV_MINORS || !tsdev_table[i]) + if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK]) return -ENODEV; if (!(list = kmalloc(sizeof(struct tsdev_list), GFP_KERNEL))) return -ENOMEM; memset(list, 0, sizeof(struct tsdev_list)); + list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0; + + i &= TSDEV_MINOR_MASK; list->tsdev = tsdev_table[i]; list_add_tail(&list->node, &tsdev_table[i]->list); file->private_data = list; @@ -169,11 +218,13 @@ if (!list->tsdev->exist) return -ENODEV; - while (list->head != list->tail && retval + sizeof(TS_EVENT) <= count) { - if (copy_to_user (buffer + retval, list->event + list->tail, sizeof(TS_EVENT))) + while (list->head != list->tail && + retval + sizeof (struct ts_event) <= count) { + if (copy_to_user (buffer + retval, list->event + list->tail, + sizeof (struct ts_event))) return -EFAULT; list->tail = (list->tail + 1) & (TSDEV_BUFFER_SIZE - 1); - retval += sizeof(TS_EVENT); + retval += sizeof (struct ts_event); } return retval; @@ -193,22 +244,27 @@ static int tsdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { -/* struct tsdev_list *list = file->private_data; - struct tsdev *evdev = list->tsdev; - struct input_dev *dev = tsdev->handle.dev; - int retval; - + struct tsdev *tsdev = list->tsdev; + int retval = 0; + switch (cmd) { - case HHEHE: - return 0; - case hjff: - return 0; - default: - return 0; + case TS_GET_CAL: + if (copy_to_user ((void *)arg, &tsdev->cal, + sizeof (struct ts_calibration))) + retval = -EFAULT; + break; + case TS_SET_CAL: + if (copy_from_user (&tsdev->cal, (void *)arg, + sizeof (struct ts_calibration))) + retval = -EFAULT; + break; + default: + retval = -EINVAL; + break; } -*/ - return -EINVAL; + + return retval; } struct file_operations tsdev_fops = { @@ -227,82 +283,85 @@ struct tsdev *tsdev = handle->private; struct tsdev_list *list; struct timeval time; - int size; - list_for_each_entry(list, &tsdev->list, node) { - switch (type) { - case EV_ABS: - switch (code) { - case ABS_X: - if (!list->pendown) - return; - size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X]; - if (size > 0) - list->oldx = ((value - handle->dev->absmin[ABS_X]) * xres / size); - else - list->oldx = ((value - handle->dev->absmin[ABS_X])); - break; - case ABS_Y: - if (!list->pendown) - return; - size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y]; - if (size > 0) - list->oldy = ((value - handle->dev->absmin[ABS_Y]) * yres / size); - else - list->oldy = ((value - handle->dev->absmin[ABS_Y])); - break; - case ABS_PRESSURE: - list->pendown = ((value > handle->dev-> absmin[ABS_PRESSURE])) ? - value - handle->dev->absmin[ABS_PRESSURE] : 0; - break; - } + switch (type) { + case EV_ABS: + switch (code) { + case ABS_X: + tsdev->x = value; + break; + case ABS_Y: + tsdev->y = value; + break; + case ABS_PRESSURE: + if (value > handle->dev->absmax[ABS_PRESSURE]) + value = handle->dev->absmax[ABS_PRESSURE]; + value -= handle->dev->absmin[ABS_PRESSURE]; + if (value < 0) + value = 0; + tsdev->pressure = value; + break; + } + break; + + case EV_REL: + switch (code) { + case REL_X: + tsdev->x += value; + if (tsdev->x < 0) + tsdev->x = 0; + else if (tsdev->x > xres) + tsdev->x = xres; + break; + case REL_Y: + tsdev->y += value; + if (tsdev->y < 0) + tsdev->y = 0; + else if (tsdev->y > yres) + tsdev->y = yres; break; + } + break; - case EV_REL: - switch (code) { - case REL_X: - if (!list->pendown) - return; - list->oldx += value; - if (list->oldx < 0) - list->oldx = 0; - else if (list->oldx > xres) - list->oldx = xres; + case EV_KEY: + if (code == BTN_TOUCH || code == BTN_MOUSE) { + switch (value) { + case 0: + tsdev->pressure = 0; break; - case REL_Y: - if (!list->pendown) - return; - list->oldy += value; - if (list->oldy < 0) - list->oldy = 0; - else if (list->oldy > xres) - list->oldy = xres; + case 1: + if (!tsdev->pressure) + tsdev->pressure = 1; break; } - break; - - case EV_KEY: - if (code == BTN_TOUCH || code == BTN_MOUSE) { - switch (value) { - case 0: - list->pendown = 0; - break; - case 1: - if (!list->pendown) - list->pendown = 1; - break; - case 2: - return; - } - } else - return; - break; } + break; + } + + if (type != EV_SYN || code != SYN_REPORT) + return; + + list_for_each_entry(list, &tsdev->list, node) { + int x, y, tmp; + do_gettimeofday(&time); list->event[list->head].millisecs = time.tv_usec / 100; - list->event[list->head].pressure = list->pendown; - list->event[list->head].x = list->oldx; - list->event[list->head].y = list->oldy; + list->event[list->head].pressure = tsdev->pressure; + + x = tsdev->x; + y = tsdev->y; + + /* Calibration */ + if (!list->raw) { + x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans; + y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans; + if (tsdev->cal.xyswap) { + tmp = x; x = y; y = tmp; + } + } + + list->event[list->head].x = x; + list->event[list->head].y = y; list->head = (list->head + 1) & (TSDEV_BUFFER_SIZE - 1); kill_fasync(&list->fasync, SIGIO, POLL_IN); } @@ -314,11 +373,11 @@ struct input_device_id *id) { struct tsdev *tsdev; - int minor; + int minor, delta; - for (minor = 0; minor < TSDEV_MINORS && tsdev_table[minor]; + for (minor = 0; minor < TSDEV_MINORS/2 && tsdev_table[minor]; minor++); - if (minor == TSDEV_MINORS) { + if (minor >= TSDEV_MINORS/2) { printk(KERN_ERR "tsdev: You have way too many touchscreens\n"); return NULL; @@ -340,10 +399,25 @@ tsdev->handle.handler = handler; tsdev->handle.private = tsdev; + /* Precompute the rough calibration matrix */ + delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1; + if (delta == 0) + delta = 1; + tsdev->cal.xscale = (xres << 8) / delta; + tsdev->cal.xtrans = - ((dev->absmin [ABS_X] * tsdev->cal.xscale) >> 8); + + delta = dev->absmax [ABS_Y] - dev->absmin [ABS_Y] + 1; + if (delta == 0) + delta = 1; + tsdev->cal.yscale = (yres << 8) / delta; + tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8); + tsdev_table[minor] = tsdev; - + devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor); + devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor + TSDEV_MINORS/2), + S_IFCHR|S_IRUGO|S_IWUSR, "input/tsraw%d", minor); class_simple_device_add(input_class, MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), dev->dev, "ts%d", minor); @@ -362,6 +436,7 @@ wake_up_interruptible(&tsdev->wait); } else tsdev_free(tsdev); + devfs_remove("input/tsraw%d", tsdev->minor); } static struct input_device_id tsdev_ids[] = { @@ -379,6 +454,12 @@ .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, },/* A tablet like device, at least touch detection, two absolute axes */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT(EV_ABS) }, + .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) }, + },/* A tablet like device with several gradations of pressure */ + {},/* Terminating entry */ }; --- diff/drivers/md/dm-ioctl.c 2004-05-19 22:11:47.000000000 +0100 +++ source/drivers/md/dm-ioctl.c 2004-05-27 18:34:16.000000000 +0100 @@ -46,7 +46,7 @@ static struct list_head _name_buckets[NUM_BUCKETS]; static struct list_head _uuid_buckets[NUM_BUCKETS]; -void dm_hash_remove_all(void); +static void dm_hash_remove_all(void); /* * Guards access to both hash tables. @@ -61,7 +61,7 @@ INIT_LIST_HEAD(buckets + i); } -int dm_hash_init(void) +static int dm_hash_init(void) { init_buckets(_name_buckets); init_buckets(_uuid_buckets); @@ -69,7 +69,7 @@ return 0; } -void dm_hash_exit(void) +static void dm_hash_exit(void) { dm_hash_remove_all(); devfs_remove(DM_DIR); @@ -195,7 +195,7 @@ * The kdev_t and uuid of a device can never change once it is * initially inserted. */ -int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md) +static int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md) { struct hash_cell *cell; @@ -234,7 +234,7 @@ return -EBUSY; } -void __hash_remove(struct hash_cell *hc) +static void __hash_remove(struct hash_cell *hc) { /* remove from the dev hash */ list_del(&hc->uuid_list); @@ -246,7 +246,7 @@ free_cell(hc); } -void dm_hash_remove_all(void) +static void dm_hash_remove_all(void) { int i; struct hash_cell *hc; @@ -262,7 +262,7 @@ up_write(&_hash_lock); } -int dm_hash_rename(const char *old, const char *new) +static int dm_hash_rename(const char *old, const char *new) { char *new_name, *old_name; struct hash_cell *hc; @@ -377,7 +377,7 @@ for (i = 0; i < NUM_BUCKETS; i++) { list_for_each_entry (hc, _name_buckets + i, name_list) { needed += sizeof(struct dm_name_list); - needed += strlen(hc->name); + needed += strlen(hc->name) + 1; needed += ALIGN_MASK; } } @@ -850,7 +850,6 @@ int r; struct mapped_device *md; struct dm_table *table; - DECLARE_WAITQUEUE(wq, current); md = find_device(param); if (!md) @@ -859,12 +858,10 @@ /* * Wait for a notification event */ - set_current_state(TASK_INTERRUPTIBLE); - if (!dm_add_wait_queue(md, &wq, param->event_nr)) { - schedule(); - dm_remove_wait_queue(md, &wq); + if (dm_wait_event(md, param->event_nr)) { + r = -ERESTARTSYS; + goto out; } - set_current_state(TASK_RUNNING); /* * The userland program is going to want to know what --- diff/drivers/md/dm-table.c 2004-05-19 22:11:47.000000000 +0100 +++ source/drivers/md/dm-table.c 2004-05-27 18:34:16.000000000 +0100 @@ -181,8 +181,8 @@ /* * Allocate both the target array and offset array at once. */ - n_highs = (sector_t *) dm_vcalloc(sizeof(struct dm_target) + - sizeof(sector_t), num); + n_highs = (sector_t *) dm_vcalloc(num, sizeof(struct dm_target) + + sizeof(sector_t)); if (!n_highs) return -ENOMEM; @@ -900,6 +900,28 @@ } } +int dm_table_flush_all(struct dm_table *t) +{ + struct list_head *d, *devices = dm_table_get_devices(t); + int ret = 0; + + for (d = devices->next; d != devices; d = d->next) { + struct dm_dev *dd = list_entry(d, struct dm_dev, list); + request_queue_t *q = bdev_get_queue(dd->bdev); + int err; + + if (!q->issue_flush_fn) + err = -EOPNOTSUPP; + else + err = q->issue_flush_fn(q, dd->bdev->bd_disk, NULL); + + if (!ret) + ret = err; + } + + return ret; +} + EXPORT_SYMBOL(dm_vcalloc); EXPORT_SYMBOL(dm_get_device); EXPORT_SYMBOL(dm_put_device); @@ -908,3 +930,4 @@ EXPORT_SYMBOL(dm_table_put); EXPORT_SYMBOL(dm_table_get); EXPORT_SYMBOL(dm_table_unplug_all); +EXPORT_SYMBOL(dm_table_flush_all); --- diff/drivers/md/dm-target.c 2004-05-19 22:11:47.000000000 +0100 +++ source/drivers/md/dm-target.c 2004-05-27 18:34:16.000000000 +0100 @@ -7,6 +7,7 @@ #include "dm.h" #include +#include #include #include #include @@ -181,7 +182,7 @@ .map = io_err_map, }; -int dm_target_init(void) +int __init dm_target_init(void) { return dm_register_target(&error_target); } --- diff/drivers/md/dm.c 2004-05-19 22:11:47.000000000 +0100 +++ source/drivers/md/dm.c 2004-05-27 18:34:16.000000000 +0100 @@ -80,7 +80,7 @@ /* * Event handling. */ - uint32_t event_nr; + atomic_t event_nr; wait_queue_head_t eventq; /* @@ -93,7 +93,7 @@ static kmem_cache_t *_io_cache; static kmem_cache_t *_tio_cache; -static __init int local_init(void) +static int __init local_init(void) { int r; @@ -369,6 +369,7 @@ struct dm_io *io = tio->io; free_tio(tio->io->md, tio); dec_pending(io, -EIO); + bio_put(clone); } } @@ -585,6 +586,21 @@ return 0; } +static int dm_flush_all(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + struct mapped_device *md = q->queuedata; + struct dm_table *map = dm_get_table(md); + int ret = -ENXIO; + + if (map) { + ret = dm_table_flush_all(md->map); + dm_table_put(map); + } + + return ret; +} + static void dm_unplug_all(request_queue_t *q) { struct mapped_device *md = q->queuedata; @@ -662,6 +678,8 @@ return r; } +static struct block_device_operations dm_blk_dops; + /* * Allocate and initialise a blank device with a given minor. */ @@ -684,6 +702,7 @@ init_rwsem(&md->lock); rwlock_init(&md->map_lock); atomic_set(&md->holders, 1); + atomic_set(&md->event_nr, 0); md->queue = blk_alloc_queue(GFP_KERNEL); if (!md->queue) @@ -694,6 +713,7 @@ md->queue->backing_dev_info.congested_data = md; blk_queue_make_request(md->queue, dm_request); md->queue->unplug_fn = dm_unplug_all; + md->queue->issue_flush_fn = dm_flush_all; md->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab, mempool_free_slab, _io_cache); @@ -753,10 +773,8 @@ { struct mapped_device *md = (struct mapped_device *) context; - down_write(&md->lock); - md->event_nr++; + atomic_inc(&md->event_nr);; wake_up(&md->eventq); - up_write(&md->lock); } static void __set_size(struct gendisk *disk, sector_t size) @@ -1054,35 +1072,13 @@ *---------------------------------------------------------------*/ uint32_t dm_get_event_nr(struct mapped_device *md) { - uint32_t r; - - down_read(&md->lock); - r = md->event_nr; - up_read(&md->lock); - - return r; + return atomic_read(&md->event_nr); } -int dm_add_wait_queue(struct mapped_device *md, wait_queue_t *wq, - uint32_t event_nr) +int dm_wait_event(struct mapped_device *md, int event_nr) { - down_write(&md->lock); - if (event_nr != md->event_nr) { - up_write(&md->lock); - return 1; - } - - add_wait_queue(&md->eventq, wq); - up_write(&md->lock); - - return 0; -} - -void dm_remove_wait_queue(struct mapped_device *md, wait_queue_t *wq) -{ - down_write(&md->lock); - remove_wait_queue(&md->eventq, wq); - up_write(&md->lock); + return wait_event_interruptible(md->eventq, + (event_nr != atomic_read(&md->event_nr))); } /* @@ -1099,7 +1095,7 @@ return test_bit(DMF_SUSPENDED, &md->flags); } -struct block_device_operations dm_blk_dops = { +static struct block_device_operations dm_blk_dops = { .open = dm_blk_open, .release = dm_blk_close, .owner = THIS_MODULE --- diff/drivers/md/dm.h 2004-05-19 22:11:47.000000000 +0100 +++ source/drivers/md/dm.h 2004-05-27 18:34:16.000000000 +0100 @@ -31,8 +31,6 @@ #define SECTOR_SHIFT 9 -extern struct block_device_operations dm_blk_dops; - /* * List of devices that a metadevice uses and should open/close. */ @@ -81,9 +79,7 @@ * Event functions. */ uint32_t dm_get_event_nr(struct mapped_device *md); -int dm_add_wait_queue(struct mapped_device *md, wait_queue_t *wq, - uint32_t event_nr); -void dm_remove_wait_queue(struct mapped_device *md, wait_queue_t *wq); +int dm_wait_event(struct mapped_device *md, int event_nr); /* * Info functions. @@ -117,6 +113,7 @@ void dm_table_resume_targets(struct dm_table *t); int dm_table_any_congested(struct dm_table *t, int bdi_bits); void dm_table_unplug_all(struct dm_table *t); +int dm_table_flush_all(struct dm_table *t); /*----------------------------------------------------------------- * A registry of target types. --- diff/drivers/md/linear.c 2004-05-19 22:11:47.000000000 +0100 +++ source/drivers/md/linear.c 2004-05-27 18:34:16.000000000 +0100 @@ -47,7 +47,6 @@ return hash->dev0; } - /** * linear_mergeable_bvec -- tell bio layer if a two requests can be merged * @q: request queue @@ -93,6 +92,27 @@ } } +static int linear_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + linear_conf_t *conf = mddev_to_conf(mddev); + int i, ret = 0; + + for (i=0; i < mddev->raid_disks; i++) { + struct block_device *bdev = conf->disks[i].rdev->bdev; + request_queue_t *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) { + ret = -EOPNOTSUPP; + break; + } + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector); + if (ret) + break; + } + return ret; +} static int linear_run (mddev_t *mddev) { @@ -200,6 +220,7 @@ blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec); mddev->queue->unplug_fn = linear_unplug; + mddev->queue->issue_flush_fn = linear_issue_flush; return 0; out: --- diff/drivers/md/md.c 2004-05-19 22:11:47.000000000 +0100 +++ source/drivers/md/md.c 2004-05-27 18:34:16.000000000 +0100 @@ -154,6 +154,39 @@ tmp = tmp->next;}) \ ) +int md_flush_mddev(mddev_t *mddev, sector_t *error_sector) +{ + struct list_head *tmp; + mdk_rdev_t *rdev; + int ret = 0; + + /* + * this list iteration is done without any locking in md?! + */ + ITERATE_RDEV(mddev, rdev, tmp) { + request_queue_t *r_queue = bdev_get_queue(rdev->bdev); + int err; + + if (!r_queue->unplug_fn) + err = -EOPNOTSUPP; + else + err = r_queue->issue_flush_fn(r_queue, rdev->bdev->bd_disk, error_sector); + + if (!ret) + ret = err; + } + + return ret; +} + +static int md_flush_all(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + + return md_flush_mddev(mddev, error_sector); +} + static int md_fail_request (request_queue_t *q, struct bio *bio) { bio_io_error(bio, bio->bi_size); @@ -1645,6 +1678,7 @@ */ mddev->queue->queuedata = mddev; mddev->queue->make_request_fn = mddev->pers->make_request; + mddev->queue->issue_flush_fn = md_flush_all; mddev->changed = 1; return 0; --- diff/drivers/md/multipath.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/md/multipath.c 2004-05-27 18:34:17.000000000 +0100 @@ -236,6 +236,31 @@ seq_printf (seq, "]"); } +static int multipath_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + multipath_conf_t *conf = mddev_to_conf(mddev); + int i, ret = 0; + + for (i=0; iraid_disks; i++) { + mdk_rdev_t *rdev = conf->multipaths[i].rdev; + if (rdev && !rdev->faulty) { + struct block_device *bdev = rdev->bdev; + request_queue_t *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) { + ret = -EOPNOTSUPP; + break; + } + + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector); + if (ret) + break; + } + } + return ret; +} /* * Careful, this can execute in IRQ contexts as well! @@ -451,6 +476,8 @@ mddev->queue->unplug_fn = multipath_unplug; + mddev->queue->issue_flush_fn = multipath_issue_flush; + conf->working_disks = 0; ITERATE_RDEV(mddev,rdev,tmp) { disk_idx = rdev->raid_disk; --- diff/drivers/md/raid0.c 2004-05-19 22:11:47.000000000 +0100 +++ source/drivers/md/raid0.c 2004-05-27 18:34:17.000000000 +0100 @@ -40,6 +40,31 @@ } } +static int raid0_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + raid0_conf_t *conf = mddev_to_conf(mddev); + mdk_rdev_t **devlist = conf->strip_zone[0].dev; + int i, ret = 0; + + for (i=0; iraid_disks; i++) { + struct block_device *bdev = devlist[i]->bdev; + request_queue_t *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) { + ret = -EOPNOTSUPP; + break; + } + + ret =r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector); + if (ret) + break; + } + return ret; +} + + static int create_strip_zones (mddev_t *mddev) { int i, c, j; @@ -219,6 +244,8 @@ mddev->queue->unplug_fn = raid0_unplug; + mddev->queue->issue_flush_fn = raid0_issue_flush; + printk("raid0: done.\n"); return 0; abort: --- diff/drivers/md/raid1.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/md/raid1.c 2004-05-27 18:34:17.000000000 +0100 @@ -479,6 +479,32 @@ unplug_slaves(q->queuedata); } +static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + conf_t *conf = mddev_to_conf(mddev); + unsigned long flags; + int i, ret = 0; + + spin_lock_irqsave(&conf->device_lock, flags); + for (i=0; iraid_disks; i++) { + mdk_rdev_t *rdev = conf->mirrors[i].rdev; + if (rdev && !rdev->faulty) { + struct block_device *bdev = rdev->bdev; + request_queue_t *r_queue = bdev_get_queue(bdev); + + if (r_queue->issue_flush_fn) { + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector); + if (ret) + break; + } + } + } + spin_unlock_irqrestore(&conf->device_lock, flags); + return ret; +} + /* * Throttle resync depth, so that we can both get proper overlapping of * requests, but are still able to handle normal requests quickly. @@ -1147,6 +1173,7 @@ } mddev->queue->unplug_fn = raid1_unplug; + mddev->queue->issue_flush_fn = raid1_issue_flush; ITERATE_RDEV(mddev, rdev, tmp) { disk_idx = rdev->raid_disk; --- diff/drivers/md/raid5.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/md/raid5.c 2004-05-27 18:34:17.000000000 +0100 @@ -1339,6 +1339,39 @@ unplug_slaves(mddev); } +static int raid5_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + raid5_conf_t *conf = mddev_to_conf(mddev); + int i, ret = 0; + + for (i=0; iraid_disks; i++) { + mdk_rdev_t *rdev = conf->disks[i].rdev; + if (rdev && !rdev->faulty) { + struct block_device *bdev = rdev->bdev; + request_queue_t *r_queue; + + if (!bdev) + continue; + + r_queue = bdev_get_queue(bdev); + if (!r_queue) + continue; + + if (!r_queue->issue_flush_fn) { + ret = -EOPNOTSUPP; + break; + } + + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector); + if (ret) + break; + } + } + return ret; +} + static inline void raid5_plug_device(raid5_conf_t *conf) { spin_lock_irq(&conf->device_lock); @@ -1545,6 +1578,7 @@ atomic_set(&conf->preread_active_stripes, 0); mddev->queue->unplug_fn = raid5_unplug_device; + mddev->queue->issue_flush_fn = raid5_issue_flush; PRINTK("raid5: run(%s) called.\n", mdname(mddev)); --- diff/drivers/md/raid6main.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/md/raid6main.c 2004-05-27 18:34:17.000000000 +0100 @@ -1501,6 +1501,39 @@ unplug_slaves(mddev); } +static int raid6_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + raid6_conf_t *conf = mddev_to_conf(mddev); + int i, ret = 0; + + for (i=0; iraid_disks; i++) { + mdk_rdev_t *rdev = conf->disks[i].rdev; + if (rdev && !rdev->faulty) { + struct block_device *bdev = rdev->bdev; + request_queue_t *r_queue; + + if (!bdev) + continue; + + r_queue = bdev_get_queue(bdev); + if (!r_queue) + continue; + + if (!r_queue->issue_flush_fn) { + ret = -EOPNOTSUPP; + break; + } + + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector); + if (ret) + break; + } + } + return ret; +} + static inline void raid6_plug_device(raid6_conf_t *conf) { spin_lock_irq(&conf->device_lock); @@ -1708,6 +1741,7 @@ atomic_set(&conf->preread_active_stripes, 0); mddev->queue->unplug_fn = raid6_unplug_device; + mddev->queue->issue_flush_fn = raid6_issue_flush; PRINTK("raid6: run(%s) called.\n", mdname(mddev)); --- diff/drivers/media/video/ir-kbd-gpio.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/media/video/ir-kbd-gpio.c 2004-05-27 18:34:17.000000000 +0100 @@ -64,7 +64,7 @@ [ 13 ] = KEY_STOP, // freeze [ 29 ] = KEY_RECORD, // capture [ 3 ] = KEY_PLAY, // unmarked - [ 24 ] = KEY_RED, // unmarked + [ 23 ] = KEY_RED, // unmarked [ 7 ] = KEY_GREEN, // unmarked #if 0 --- diff/drivers/media/video/mxb.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/media/video/mxb.c 2004-05-27 18:34:17.000000000 +0100 @@ -24,42 +24,15 @@ #define DEBUG_VARIABLE debug #include -#include /* for saa7111a */ +#include +#include #include "mxb.h" #include "tea6415c.h" #include "tea6420.h" #include "tda9840.h" -#include -#define I2C_SAA7111A 0x24 - -/* All unused bytes are reserverd. */ -#define SAA711X_CHIP_VERSION 0x00 -#define SAA711X_ANALOG_INPUT_CONTROL_1 0x02 -#define SAA711X_ANALOG_INPUT_CONTROL_2 0x03 -#define SAA711X_ANALOG_INPUT_CONTROL_3 0x04 -#define SAA711X_ANALOG_INPUT_CONTROL_4 0x05 -#define SAA711X_HORIZONTAL_SYNC_START 0x06 -#define SAA711X_HORIZONTAL_SYNC_STOP 0x07 -#define SAA711X_SYNC_CONTROL 0x08 -#define SAA711X_LUMINANCE_CONTROL 0x09 -#define SAA711X_LUMINANCE_BRIGHTNESS 0x0A -#define SAA711X_LUMINANCE_CONTRAST 0x0B -#define SAA711X_CHROMA_SATURATION 0x0C -#define SAA711X_CHROMA_HUE_CONTROL 0x0D -#define SAA711X_CHROMA_CONTROL 0x0E -#define SAA711X_FORMAT_DELAY_CONTROL 0x10 -#define SAA711X_OUTPUT_CONTROL_1 0x11 -#define SAA711X_OUTPUT_CONTROL_2 0x12 -#define SAA711X_OUTPUT_CONTROL_3 0x13 -#define SAA711X_V_GATE_1_START 0x15 -#define SAA711X_V_GATE_1_STOP 0x16 -#define SAA711X_V_GATE_1_MSB 0x17 -#define SAA711X_TEXT_SLICER_STATUS 0x1A -#define SAA711X_DECODED_BYTES_OF_TS_1 0x1B -#define SAA711X_DECODED_BYTES_OF_TS_2 0x1C -#define SAA711X_STATUS_BYTE 0x1F +#define I2C_SAA7111 0x24 #define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) @@ -175,42 +148,33 @@ static struct saa7146_extension extension; -static int mxb_vbi_bypass(struct saa7146_dev* dev) -{ - struct mxb* mxb = (struct mxb*)dev->ext_priv; - s32 byte = 0x0; - int result = 0; - - DEB_EE(("dev:%p\n",dev)); - - /* switch bypass in saa7111a, this should be done in the - saa7111a driver of course... */ - if ( -1 == (result = i2c_smbus_read_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_3))) { - DEB_D(("could not read from saa7111a.\n")); - return -EFAULT; - } - byte = result; - byte &= 0xf0; - byte |= 0x0a; - - if ( 0 != (result = i2c_smbus_write_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_3, byte))) { - DEB_D(("could not write to saa7111a.\n")); - return -EFAULT; - } - return 0; -} - static int mxb_probe(struct saa7146_dev* dev) { struct mxb* mxb = 0; struct i2c_client *client; struct list_head *item; + int result; - request_module("tuner"); - request_module("tea6420"); - request_module("tea6415c"); - request_module("tda9840"); - request_module("saa7111"); + if ((result = request_module("saa7111")) < 0) { + printk("mxb: saa7111 i2c module not available.\n"); + return -ENODEV; + } + if ((result = request_module("tuner")) < 0) { + printk("mxb: tuner i2c module not available.\n"); + return -ENODEV; + } + if ((result = request_module("tea6420")) < 0) { + printk("mxb: tea6420 i2c module not available.\n"); + return -ENODEV; + } + if ((result = request_module("tea6415c")) < 0) { + printk("mxb: tea6415c i2c module not available.\n"); + return -ENODEV; + } + if ((result = request_module("tda9840")) < 0) { + printk("mxb: tda9840 i2c module not available.\n"); + return -ENODEV; + } mxb = (struct mxb*)kmalloc(sizeof(struct mxb), GFP_KERNEL); if( NULL == mxb ) { @@ -219,10 +183,6 @@ } memset(mxb, 0x0, sizeof(struct mxb)); - /* FIXME: enable i2c-port pins, video-port-pins - video port pins should be enabled here ?! */ - saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); - saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, I2C_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480); if(i2c_add_adapter(&mxb->i2c_adapter) < 0) { DEB_S(("cannot register i2c-device. skipping.\n")); @@ -241,7 +201,7 @@ mxb->tea6415c = client; if( I2C_TDA9840 == client->addr ) mxb->tda9840 = client; - if( I2C_SAA7111A == client->addr ) + if( I2C_SAA7111 == client->addr ) mxb->saa7111a = client; if( 0x60 == client->addr ) mxb->tuner = client; @@ -251,8 +211,7 @@ if( 0 == mxb->tea6420_1 || 0 == mxb->tea6420_2 || 0 == mxb->tea6415c || 0 == mxb->tda9840 || 0 == mxb->saa7111a || 0 == mxb->tuner ) { - printk("mxb: did not find all i2c devices. are you sure you\n"); - printk("mxb: insmod'ed tea6420, tea6415c, saa7111, tea6415c and tuner?\n"); + printk("mxb: did not find all i2c devices. aborting\n"); i2c_del_adapter(&mxb->i2c_adapter); kfree(mxb); return -ENODEV; @@ -322,37 +281,35 @@ {-1, { 0} } }; -static unsigned char mxb_saa7111_init[25] = { - 0x00, - - 0x00, /* 00 - ID byte */ - 0x00, /* 01 - reserved */ +static const unsigned char mxb_saa7111_init[] = { + 0x00, 0x00, /* 00 - ID byte */ + 0x01, 0x00, /* 01 - reserved */ /*front end */ - 0xd8, /* 02 - FUSE=x, GUDL=x, MODE=x */ - 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */ - 0x00, /* 04 - GAI1=256 */ - 0x00, /* 05 - GAI2=256 */ + 0x02, 0xd8, /* 02 - FUSE=x, GUDL=x, MODE=x */ + 0x03, 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */ + 0x04, 0x00, /* 04 - GAI1=256 */ + 0x05, 0x00, /* 05 - GAI2=256 */ /* decoder */ - 0xf0, /* 06 - HSB at xx(50Hz) / xx(60Hz) pixels after end of last line */ - 0x30, /* 07 - HSS at xx(50Hz) / xx(60Hz) pixels after end of last line */ - 0xa8, /* 08 - AUFD=x, FSEL=x, EXFIL=x, VTRC=x, HPLL=x, VNOI=x */ - 0x02, /* 09 - BYPS=x, PREF=x, BPSS=x, VBLB=x, UPTCV=x, APER=x */ - 0x80, /* 0a - BRIG=128 */ - 0x47, /* 0b - CONT=1.109 */ - 0x40, /* 0c - SATN=1.0 */ - 0x00, /* 0d - HUE=0 */ - 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */ - 0x00, /* 0f - reserved */ - 0xd0, /* 10 - OFTS=x, HDEL=x, VRLN=x, YDEL=x */ - 0x8c, /* 11 - GPSW=x, CM99=x, FECO=x, COMPO=x, OEYC=1, OEHV=1, VIPB=0, COLO=0 */ - 0x80, /* 12 - xx output control 2 */ - 0x30, /* 13 - xx output control 3 */ - 0x00, /* 14 - reserved */ - 0x15, /* 15 - VBI */ - 0x04, /* 16 - VBI */ - 0x00, /* 17 - VBI */ + 0x06, 0xf0, /* 06 - HSB at xx(50Hz) / xx(60Hz) pixels after end of last line */ + 0x07, 0x30, /* 07 - HSS at xx(50Hz) / xx(60Hz) pixels after end of last line */ + 0x08, 0xa8, /* 08 - AUFD=x, FSEL=x, EXFIL=x, VTRC=x, HPLL=x, VNOI=x */ + 0x09, 0x02, /* 09 - BYPS=x, PREF=x, BPSS=x, VBLB=x, UPTCV=x, APER=x */ + 0x0a, 0x80, /* 0a - BRIG=128 */ + 0x0b, 0x47, /* 0b - CONT=1.109 */ + 0x0c, 0x40, /* 0c - SATN=1.0 */ + 0x0d, 0x00, /* 0d - HUE=0 */ + 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */ + 0x0f, 0x00, /* 0f - reserved */ + 0x10, 0xd0, /* 10 - OFTS=x, HDEL=x, VRLN=x, YDEL=x */ + 0x11, 0x8c, /* 11 - GPSW=x, CM99=x, FECO=x, COMPO=x, OEYC=1, OEHV=1, VIPB=0, COLO=0 */ + 0x12, 0x80, /* 12 - xx output control 2 */ + 0x13, 0x30, /* 13 - xx output control 3 */ + 0x14, 0x00, /* 14 - reserved */ + 0x15, 0x15, /* 15 - VBI */ + 0x16, 0x04, /* 16 - VBI */ + 0x17, 0x00, /* 17 - VBI */ }; /* bring hardware to a sane state. this has to be done, just in case someone @@ -362,25 +319,29 @@ static int mxb_init_done(struct saa7146_dev* dev) { struct mxb* mxb = (struct mxb*)dev->ext_priv; - + struct video_decoder_init init; struct i2c_msg msg; int i = 0, err = 0; struct tea6415c_multiplex vm; + /* select video mode in saa7111a */ + i = VIDEO_MODE_PAL; + /* fixme: currently pointless: gets overwritten by configuration below */ + mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_NORM, &i); + /* write configuration to saa7111a */ - i = i2c_master_send(mxb->saa7111a, mxb_saa7111_init, sizeof(mxb_saa7111_init)); - if (i < 0) { - printk("failed to initialize saa7111a. this should never happen.\n"); - } + init.data = mxb_saa7111_init; + init.len = sizeof(mxb_saa7111_init); + mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_INIT, &init); /* select tuner-output on saa7111a */ i = 0; mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i); -// i = VIDEO_MODE_PAL; -// mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_NORM, &i); - mxb_vbi_bypass(dev); + /* enable vbi bypass */ + i = 1; + mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_VBI_BYPASS, &i); /* select a tuner type */ i = 5; @@ -538,36 +499,6 @@ return 0; } -/* hack: this should go into saa711x */ -static int saa7111_set_gpio(struct saa7146_dev *dev, int bl) -{ - struct mxb* mxb = (struct mxb*)dev->ext_priv; - s32 byte = 0x0; - int result = 0; - - DEB_EE(("dev:%p\n",dev)); - - /* get the old register contents */ - if ( -1 == (byte = i2c_smbus_read_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_1))) { - DEB_D(("could not read from saa711x\n")); - return -EFAULT; - } - - if( 0 == bl ) { - byte &= 0x7f; - } else { - byte |= 0x80; - } - - /* write register contents back */ - if ( 0 != (result = i2c_smbus_write_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_1, byte))) { - DEB_D(("could not write to saa711x\n")); - return -EFAULT; - } - - return 0; -} - static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { struct saa7146_dev *dev = fh->dev; @@ -988,18 +919,22 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std) { + struct mxb* mxb = (struct mxb*)dev->ext_priv; + int zero = 0; + int one = 1; + if(V4L2_STD_PAL_I == std->id ) { DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n")); /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* unset the 7111 gpio register -- I don't know what this does exactly */ - saa7111_set_gpio(dev,0); + mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &zero); } else { DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n")); /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* set the 7111 gpio register -- I don't know what this does exactly */ - saa7111_set_gpio(dev,1); + mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_GPIO, &one); } return 0; } --- diff/drivers/mtd/chips/sharp.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/mtd/chips/sharp.c 2004-05-27 18:34:17.000000000 +0100 @@ -30,6 +30,7 @@ #include #include #include +#include #define CMD_RESET 0xffffffff #define CMD_READ_ID 0x90909090 --- diff/drivers/mtd/maps/uclinux.c 2004-05-19 22:11:52.000000000 +0100 +++ source/drivers/mtd/maps/uclinux.c 2004-05-27 18:34:17.000000000 +0100 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include --- diff/drivers/net/3c509.c 2004-05-19 22:11:53.000000000 +0100 +++ source/drivers/net/3c509.c 2004-05-27 18:34:17.000000000 +0100 @@ -56,10 +56,6 @@ v1.19b 08Nov2002 Marc Zyngier - Introduce driver model for EISA cards. */ -/* - FIXES for PC-9800: - Shu Iwanaga: 3c569B(PC-9801 C-bus) support -*/ #define DRV_NAME "3c509" #define DRV_VERSION "1.19b" @@ -265,7 +261,7 @@ }; #endif /* CONFIG_MCA */ -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) static struct isapnp_device_id el3_isapnp_adapters[] __initdata = { { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090), @@ -362,7 +358,7 @@ if (lp->pmdev) pm_unregister(lp->pmdev); #endif -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) if (lp->type == EL3_PNP) pnp_device_detach(to_pnp_dev(lp->dev)); #endif @@ -381,7 +377,7 @@ u16 phys_addr[3]; static int current_tag; int err = -ENODEV; -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) static int pnp_cards; struct pnp_dev *idev = NULL; @@ -436,9 +432,6 @@ no_pnp: #endif /* __ISAPNP__ */ -#ifdef CONFIG_X86_PC9800 - id_port = 0x71d0; -#else /* Select an open I/O location at 0x1*0 to do contention select. */ for ( ; id_port < 0x200; id_port += 0x10) { if (!request_region(id_port, 1, "3c509")) @@ -456,7 +449,7 @@ printk(" WARNING: No I/O port available for 3c509 activation.\n"); return -ENODEV; } -#endif /* CONFIG_X86_PC9800 */ + /* Next check for all ISA bus boards by sending the ID sequence to the ID_PORT. We find cards past the first by setting the 'current_tag' on cards as they are found. Cards with their tag set will not @@ -487,7 +480,7 @@ phys_addr[i] = htons(id_read_eeprom(i)); } -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) if (nopnp == 0) { /* The ISA PnP 3c509 cards respond to the ID sequence. This check is needed in order not to register them twice. */ @@ -512,19 +505,9 @@ { unsigned int iobase = id_read_eeprom(8); if_port = iobase >> 14; -#ifdef CONFIG_X86_PC9800 - ioaddr = 0x40d0 + ((iobase & 0x1f) << 8); -#else ioaddr = 0x200 + ((iobase & 0x1f) << 4); -#endif } irq = id_read_eeprom(9) >> 12; -#ifdef CONFIG_X86_PC9800 - if (irq == 7) - irq = 6; - else if (irq == 15) - irq = 13; -#endif dev = alloc_etherdev(sizeof (struct el3_private)); if (!dev) @@ -555,11 +538,7 @@ outb(0xd0 + ++current_tag, id_port); /* Activate the adaptor at the EEPROM location. */ -#ifdef CONFIG_X86_PC9800 - outb((ioaddr >> 8) | 0xe0, id_port); -#else outb((ioaddr >> 4) | 0xe0, id_port); -#endif EL3WINDOW(0); if (inw(ioaddr) != 0x6d50) @@ -568,7 +547,7 @@ /* Free the interrupt so that some other card can use it. */ outw(0x0f00, ioaddr + WN0_IRQ); -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) found: /* PNP jumps here... */ #endif /* __ISAPNP__ */ @@ -577,7 +556,7 @@ dev->irq = irq; dev->if_port = if_port; lp = netdev_priv(dev); -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) lp->dev = &idev->dev; #endif err = el3_common_init(dev); @@ -601,7 +580,7 @@ return 0; out1: -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) if (idev) pnp_device_detach(idev); #endif @@ -1461,12 +1440,6 @@ outw(0x0001, ioaddr + 4); /* Set the IRQ line. */ -#ifdef CONFIG_X86_PC9800 - if (dev->irq == 6) - dev->irq = 7; - else if (dev->irq == 13) - dev->irq = 15; -#endif outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ); /* Set the station address in window 2 each time opened. */ @@ -1629,7 +1602,7 @@ MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); MODULE_PARM_DESC(xcvr,"transceiver(s) (0=internal, 1=external)"); MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt"); -#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) +#if defined(__ISAPNP__) MODULE_PARM(nopnp, "i"); MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)"); MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters); --- diff/drivers/net/82596.c 2004-05-19 22:11:53.000000000 +0100 +++ source/drivers/net/82596.c 2004-05-27 18:34:17.000000000 +0100 @@ -58,7 +58,6 @@ #include #include #include -#include static char version[] __initdata = "82596.c $Revision: 1.5 $\n"; --- diff/drivers/net/8390.h 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/net/8390.h 2004-05-27 18:34:17.000000000 +0100 @@ -143,7 +143,7 @@ #define inb_p(_p) inb(_p) #define outb_p(_v,_p) outb(_v,_p) -#elif defined(CONFIG_NET_CBUS) || defined(CONFIG_NE_H8300) +#elif defined(CONFIG_NET_CBUS) || defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE) #define EI_SHIFT(x) (ei_local->reg_offset[x]) #else #define EI_SHIFT(x) (x) --- diff/drivers/net/Kconfig 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/net/Kconfig 2004-05-27 18:34:17.000000000 +0100 @@ -922,7 +922,7 @@ config NET_ISA bool "Other ISA cards" - depends on NET_ETHERNET && ISA && !X86_PC9800 + depends on NET_ETHERNET && ISA ---help--- If your network (Ethernet) card hasn't been mentioned yet and its bus system (that's the way the cards talks to the other components @@ -1105,56 +1105,6 @@ the Ethernet-HOWTO, available from . -config NET_CBUS - bool "NEC PC-9800 C-bus cards" - depends on NET_ETHERNET && ISA && X86_PC9800 - ---help--- - If your network (Ethernet) card hasn't been mentioned yet and its - bus system (that's the way the cards talks to the other components - of your computer) is NEC PC-9800 C-Bus, say Y. - -config NE2K_CBUS - tristate "Most NE2000-based Ethernet support" - depends on NET_CBUS - select CRC32 - -config NE2K_CBUS_EGY98 - bool "Melco EGY-98 support" - depends on NE2K_CBUS - -config NE2K_CBUS_LGY98 - bool "Melco LGY-98 support" - depends on NE2K_CBUS - -config NE2K_CBUS_ICM - bool "ICM IF-27xxET support" - depends on NE2K_CBUS - -config NE2K_CBUS_IOLA98 - bool "I-O DATA LA-98 support" - depends on NE2K_CBUS - -config NE2K_CBUS_CNET98EL - bool "Contec C-NET(98)E/L support" - depends on NE2K_CBUS - -config NE2K_CBUS_CNET98EL_IO_BASE - hex "C-NET(98)E/L I/O base address (0xaaed or 0x55ed)" - depends on NE2K_CBUS_CNET98EL - default "0xaaed" - -config NE2K_CBUS_ATLA98 - bool "Allied Telesis LA-98 Support" - depends on NE2K_CBUS - -config NE2K_CBUS_BDN - bool "ELECOM Laneed LD-BDN[123]A Support" - depends on NE2K_CBUS - -config NE2K_CBUS_NEC108 - bool "NEC PC-9801-108 Support" - depends on NE2K_CBUS - config SKMC tristate "SKnet MCA support" depends on NET_ETHERNET && MCA && BROKEN @@ -1829,7 +1779,7 @@ controller on the Motorola ColdFire 5272 processor. config NE_H8300 - bool "NE2000 compatible support for H8/300" + tristate "NE2000 compatible support for H8/300" depends on H8300 && NET_ETHERNET help Say Y here if you want to use the NE2000 compatible @@ -1987,6 +1937,11 @@ To compile this driver as a module, choose M here: the module will be called r8169. This is recommended. +config R8169_NAPI + bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)" + depends on R8169 && EXPERIMENTAL + + config SK98LIN tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support" depends on PCI --- diff/drivers/net/Makefile 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/net/Makefile 2004-05-27 18:34:17.000000000 +0100 @@ -78,7 +78,6 @@ obj-$(CONFIG_WD80x3) += wd.o 8390.o obj-$(CONFIG_EL2) += 3c503.o 8390.o obj-$(CONFIG_NE2000) += ne.o 8390.o -obj-$(CONFIG_NE2K_CBUS) += ne2k_cbus.o 8390.o obj-$(CONFIG_NE2_MCA) += ne2.o 8390.o obj-$(CONFIG_HPLAN) += hp.o 8390.o obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390.o @@ -187,4 +186,6 @@ obj-$(CONFIG_HAMRADIO) += hamradio/ obj-$(CONFIG_IRDA) += irda/ +# Must come after all NICs that might use them obj-$(CONFIG_NETCONSOLE) += netconsole.o +obj-$(CONFIG_KGDB) += kgdb_eth.o --- diff/drivers/net/Space.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/net/Space.c 2004-05-27 18:34:17.000000000 +0100 @@ -191,8 +191,8 @@ #ifdef CONFIG_E2100 /* Cabletron E21xx series. */ {e2100_probe, 0}, #endif -#if defined(CONFIG_NE2000) || defined(CONFIG_NE2K_CBUS) || \ - defined(CONFIG_NE_H8300) /* ISA & PC-9800 CBUS (use ne2k-pci for PCI cards) */ +#if defined(CONFIG_NE2000) || \ + defined(CONFIG_NE_H8300) /* ISA (use ne2k-pci for PCI cards) */ {ne_probe, 0}, #endif #ifdef CONFIG_LANCE /* ISA/VLB (use pcnet32 for PCI cards) */ --- diff/drivers/net/acenic.c 2004-05-19 22:11:53.000000000 +0100 +++ source/drivers/net/acenic.c 2004-05-27 18:34:17.000000000 +0100 @@ -131,7 +131,6 @@ #define PCI_DEVICE_ID_SGI_ACENIC 0x0009 #endif -#if LINUX_VERSION_CODE >= 0x20400 static struct pci_device_id acenic_pci_tbl[] = { { PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, @@ -156,37 +155,6 @@ { } }; MODULE_DEVICE_TABLE(pci, acenic_pci_tbl); -#endif - - -#ifndef MODULE_LICENSE -#define MODULE_LICENSE(a) -#endif - -#ifndef wmb -#define wmb() mb() -#endif - -#ifndef __exit -#define __exit -#endif - -#ifndef __devinit -#define __devinit __init -#endif - -#ifndef SMP_CACHE_BYTES -#define SMP_CACHE_BYTES L1_CACHE_BYTES -#endif - -#ifndef SET_MODULE_OWNER -#define SET_MODULE_OWNER(dev) do{} while(0) -#define ACE_MOD_INC_USE_COUNT MOD_INC_USE_COUNT -#define ACE_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT -#else -#define ACE_MOD_INC_USE_COUNT do{} while(0) -#define ACE_MOD_DEC_USE_COUNT do{} while(0) -#endif #ifndef SET_NETDEV_DEV #define SET_NETDEV_DEV(net, pdev) do{} while(0) @@ -198,151 +166,8 @@ #define ace_sync_irq(irq) synchronize_irq() #endif -#if LINUX_VERSION_CODE < 0x2051e -#define local_irq_save(flags) do{__save_flags(flags) ; \ - __cli();} while(0) -#define local_irq_restore(flags) __restore_flags(flags) -#endif - -#if (LINUX_VERSION_CODE < 0x02030d) -#define pci_resource_start(dev, bar) dev->base_address[bar] -#elif (LINUX_VERSION_CODE < 0x02032c) -#define pci_resource_start(dev, bar) dev->resource[bar].start -#endif - -#if (LINUX_VERSION_CODE < 0x02030e) -#define net_device device -#endif - - -#if (LINUX_VERSION_CODE < 0x02032a) -typedef u32 dma_addr_t; - -static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) -{ - void *virt_ptr; - - virt_ptr = kmalloc(size, GFP_KERNEL); - if (!virt_ptr) - return NULL; - *dma_handle = virt_to_bus(virt_ptr); - return virt_ptr; -} - -#define pci_free_consistent(cookie, size, ptr, dma_ptr) kfree(ptr) -#define pci_map_page(cookie, page, off, size, dir) \ - virt_to_bus(page_address(page)+(off)) -#define pci_unmap_page(cookie, address, size, dir) -#define pci_set_dma_mask(dev, mask) \ - (((u64)(mask) & 0xffffffff00000000) == 0 ? 0 : -EIO) -#define pci_dma_supported(dev, mask) \ - (((u64)(mask) & 0xffffffff00000000) == 0 ? 1 : 0) - -#elif (LINUX_VERSION_CODE < 0x02040d) - -/* - * 2.4.13 introduced pci_map_page()/pci_unmap_page() - for 2.4.12 and prior, - * fall back on pci_map_single()/pci_unnmap_single(). - * - * We are guaranteed that the page is mapped at this point since - * pci_map_page() is only used upon valid struct skb's. - */ -static inline dma_addr_t -pci_map_page(struct pci_dev *cookie, struct page *page, unsigned long off, - size_t size, int dir) -{ - void *page_virt; - - page_virt = page_address(page); - if (!page_virt) - BUG(); - return pci_map_single(cookie, (page_virt + off), size, dir); -} -#define pci_unmap_page(cookie, dma_addr, size, dir) \ - pci_unmap_single(cookie, dma_addr, size, dir) -#endif - -#if (LINUX_VERSION_CODE < 0x020412) -#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) -#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) -#define pci_unmap_addr(PTR, ADDR_NAME) 0 -#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do{} while(0) -#define pci_unmap_len(PTR, LEN_NAME) 0 -#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do{} while(0) -#endif - - -#if (LINUX_VERSION_CODE < 0x02032b) -/* - * SoftNet - * - * For pre-softnet kernels we need to tell the upper layer not to - * re-enter start_xmit() while we are in there. However softnet - * guarantees not to enter while we are in there so there is no need - * to do the netif_stop_queue() dance unless the transmit queue really - * gets stuck. This should also improve performance according to tests - * done by Aman Singla. - */ -#define dev_kfree_skb_irq(a) dev_kfree_skb(a) -#define netif_wake_queue(dev) clear_bit(0, &dev->tbusy) -#define netif_stop_queue(dev) set_bit(0, &dev->tbusy) -#define late_stop_netif_stop_queue(dev) do{} while(0) -#define early_stop_netif_stop_queue(dev) test_and_set_bit(0,&dev->tbusy) -#define early_stop_netif_wake_queue(dev) netif_wake_queue(dev) - -static inline void netif_start_queue(struct net_device *dev) -{ - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; -} - -#define ace_mark_net_bh() mark_bh(NET_BH) -#define netif_queue_stopped(dev) dev->tbusy -#define netif_running(dev) dev->start -#define ace_if_down(dev) do{dev->start = 0;} while(0) - -#define tasklet_struct tq_struct -static inline void tasklet_schedule(struct tasklet_struct *tasklet) -{ - queue_task(tasklet, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -static inline void tasklet_init(struct tasklet_struct *tasklet, - void (*func)(unsigned long), - unsigned long data) -{ - tasklet->next = NULL; - tasklet->sync = 0; - tasklet->routine = (void (*)(void *))func; - tasklet->data = (void *)data; -} -#define tasklet_kill(tasklet) do{} while(0) -#else -#define late_stop_netif_stop_queue(dev) netif_stop_queue(dev) -#define early_stop_netif_stop_queue(dev) 0 -#define early_stop_netif_wake_queue(dev) do{} while(0) -#define ace_mark_net_bh() do{} while(0) -#define ace_if_down(dev) do{} while(0) -#endif - -#if (LINUX_VERSION_CODE >= 0x02031b) -#define NEW_NETINIT -#define ACE_PROBE_ARG void -#else -#define ACE_PROBE_ARG struct net_device *dev -#endif - -#ifndef min_t -#define min_t(type,a,b) (((a)<(b))?(a):(b)) -#endif - -#ifndef ARCH_HAS_PREFETCHW -#ifndef prefetchw -#define prefetchw(x) do{} while(0) -#endif +#ifndef offset_in_page +#define offset_in_page(ptr) ((unsigned long)(ptr) & ~PAGE_MASK) #endif #define ACE_MAX_MOD_PARMS 8 @@ -595,407 +420,323 @@ static int tx_ratio[ACE_MAX_MOD_PARMS]; static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1}; +MODULE_AUTHOR("Jes Sorensen "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); +MODULE_PARM(link, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(trace, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(tx_coal_tick, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(tx_ratio, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM_DESC(link, "AceNIC/3C985/NetGear link state"); +MODULE_PARM_DESC(trace, "AceNIC/3C985/NetGear firmware trace level"); +MODULE_PARM_DESC(tx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first tx descriptor arrives"); +MODULE_PARM_DESC(max_tx_desc, "AceNIC/3C985/GA620 max number of transmit descriptors to wait"); +MODULE_PARM_DESC(rx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first rx descriptor arrives"); +MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descriptors to wait"); +MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)"); + + static char version[] __initdata = "acenic.c: v0.92 08/05/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n" " http://home.cern.ch/~jes/gige/acenic.html\n"; -static struct net_device *root_dev; - -static int probed __initdata = 0; - - -int __devinit acenic_probe (ACE_PROBE_ARG) +static int __devinit acenic_probe_one(struct pci_dev *pdev, + const struct pci_device_id *id) { -#ifdef NEW_NETINIT struct net_device *dev; -#endif struct ace_private *ap; - struct pci_dev *pdev = NULL; - int boards_found = 0; - int version_disp; - - if (probed) - return -ENODEV; - probed++; - - version_disp = 0; - - while ((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET<<8, pdev))) { - - if (!((pdev->vendor == PCI_VENDOR_ID_ALTEON) && - ((pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE) || - (pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC_COPPER)))&& - !((pdev->vendor == PCI_VENDOR_ID_3COM) && - (pdev->device == PCI_DEVICE_ID_3COM_3C985)) && - !((pdev->vendor == PCI_VENDOR_ID_NETGEAR) && - ((pdev->device == PCI_DEVICE_ID_NETGEAR_GA620) || - (pdev->device == PCI_DEVICE_ID_NETGEAR_GA620T))) && - /* - * Farallon used the DEC vendor ID on their cards by - * mistake for a while - */ - !((pdev->vendor == PCI_VENDOR_ID_DEC) && - (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX)) && - !((pdev->vendor == PCI_VENDOR_ID_ALTEON) && - (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T)) && - !((pdev->vendor == PCI_VENDOR_ID_SGI) && - (pdev->device == PCI_DEVICE_ID_SGI_ACENIC))) - continue; - - dev = alloc_etherdev(sizeof(struct ace_private)); - if (dev == NULL) { - printk(KERN_ERR "acenic: Unable to allocate " - "net_device structure!\n"); - break; - } + static int boards_found; - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); + dev = alloc_etherdev(sizeof(struct ace_private)); + if (dev == NULL) { + printk(KERN_ERR "acenic: Unable to allocate " + "net_device structure!\n"); + return -ENOMEM; + } - ap = dev->priv; - ap->pdev = pdev; + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &pdev->dev); - dev->open = &ace_open; - dev->hard_start_xmit = &ace_start_xmit; - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; + ap = dev->priv; + ap->pdev = pdev; + + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; #if ACENIC_DO_VLAN - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->vlan_rx_register = ace_vlan_rx_register; - dev->vlan_rx_kill_vid = ace_vlan_rx_kill_vid; -#endif - if (1) { - static void ace_watchdog(struct net_device *dev); - dev->tx_timeout = &ace_watchdog; - dev->watchdog_timeo = 5*HZ; - } - dev->stop = &ace_close; - dev->get_stats = &ace_get_stats; - dev->set_multicast_list = &ace_set_multicast_list; - dev->do_ioctl = &ace_ioctl; - dev->set_mac_address = &ace_set_mac_addr; - dev->change_mtu = &ace_change_mtu; + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->vlan_rx_register = ace_vlan_rx_register; + dev->vlan_rx_kill_vid = ace_vlan_rx_kill_vid; +#endif + if (1) { + static void ace_watchdog(struct net_device *dev); + dev->tx_timeout = &ace_watchdog; + dev->watchdog_timeo = 5*HZ; + } - /* display version info if adapter is found */ - if (!version_disp) - { - /* set display flag to TRUE so that */ - /* we only display this string ONCE */ - version_disp = 1; - printk(version); - } + dev->open = &ace_open; + dev->stop = &ace_close; + dev->hard_start_xmit = &ace_start_xmit; + dev->get_stats = &ace_get_stats; + dev->set_multicast_list = &ace_set_multicast_list; + dev->do_ioctl = &ace_ioctl; + dev->set_mac_address = &ace_set_mac_addr; + dev->change_mtu = &ace_change_mtu; - if (pci_enable_device(pdev)) { - free_netdev(dev); - continue; - } + /* we only display this string ONCE */ + if (!boards_found) + printk(version); - /* - * Enable master mode before we start playing with the - * pci_command word since pci_set_master() will modify - * it. - */ - pci_set_master(pdev); + if (pci_enable_device(pdev)) + goto fail_free_netdev; - pci_read_config_word(pdev, PCI_COMMAND, &ap->pci_command); + /* + * Enable master mode before we start playing with the + * pci_command word since pci_set_master() will modify + * it. + */ + pci_set_master(pdev); - /* OpenFirmware on Mac's does not set this - DOH.. */ - if (!(ap->pci_command & PCI_COMMAND_MEMORY)) { - printk(KERN_INFO "%s: Enabling PCI Memory Mapped " - "access - was not enabled by BIOS/Firmware\n", - dev->name); - ap->pci_command = ap->pci_command | PCI_COMMAND_MEMORY; - pci_write_config_word(ap->pdev, PCI_COMMAND, - ap->pci_command); - wmb(); - } + pci_read_config_word(pdev, PCI_COMMAND, &ap->pci_command); - pci_read_config_byte(pdev, PCI_LATENCY_TIMER, - &ap->pci_latency); - if (ap->pci_latency <= 0x40) { - ap->pci_latency = 0x40; - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, - ap->pci_latency); - } + /* OpenFirmware on Mac's does not set this - DOH.. */ + if (!(ap->pci_command & PCI_COMMAND_MEMORY)) { + printk(KERN_INFO "%s: Enabling PCI Memory Mapped " + "access - was not enabled by BIOS/Firmware\n", + dev->name); + ap->pci_command = ap->pci_command | PCI_COMMAND_MEMORY; + pci_write_config_word(ap->pdev, PCI_COMMAND, + ap->pci_command); + wmb(); + } - /* - * Remap the regs into kernel space - this is abuse of - * dev->base_addr since it was means for I/O port - * addresses but who gives a damn. - */ - dev->base_addr = pci_resource_start(pdev, 0); - ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000); - if (!ap->regs) { - printk(KERN_ERR "%s: Unable to map I/O register, " - "AceNIC %i will be disabled.\n", - dev->name, boards_found); - break; - } + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &ap->pci_latency); + if (ap->pci_latency <= 0x40) { + ap->pci_latency = 0x40; + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, ap->pci_latency); + } - switch(pdev->vendor) { - case PCI_VENDOR_ID_ALTEON: - if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) { - strncpy(ap->name, "Farallon PN9100-T " - "Gigabit Ethernet", sizeof (ap->name)); - printk(KERN_INFO "%s: Farallon PN9100-T ", - dev->name); - } else { - strncpy(ap->name, "AceNIC Gigabit Ethernet", - sizeof (ap->name)); - printk(KERN_INFO "%s: Alteon AceNIC ", - dev->name); - } - break; - case PCI_VENDOR_ID_3COM: - strncpy(ap->name, "3Com 3C985 Gigabit Ethernet", - sizeof (ap->name)); - printk(KERN_INFO "%s: 3Com 3C985 ", dev->name); - break; - case PCI_VENDOR_ID_NETGEAR: - strncpy(ap->name, "NetGear GA620 Gigabit Ethernet", - sizeof (ap->name)); - printk(KERN_INFO "%s: NetGear GA620 ", dev->name); - break; - case PCI_VENDOR_ID_DEC: - if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX) { - strncpy(ap->name, "Farallon PN9000-SX " - "Gigabit Ethernet", sizeof (ap->name)); - printk(KERN_INFO "%s: Farallon PN9000-SX ", - dev->name); - break; - } - case PCI_VENDOR_ID_SGI: - strncpy(ap->name, "SGI AceNIC Gigabit Ethernet", + /* + * Remap the regs into kernel space - this is abuse of + * dev->base_addr since it was means for I/O port + * addresses but who gives a damn. + */ + dev->base_addr = pci_resource_start(pdev, 0); + ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000); + if (!ap->regs) { + printk(KERN_ERR "%s: Unable to map I/O register, " + "AceNIC %i will be disabled.\n", + dev->name, boards_found); + goto fail_free_netdev; + } + + switch(pdev->vendor) { + case PCI_VENDOR_ID_ALTEON: + if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) { + strncpy(ap->name, "Farallon PN9100-T " + "Gigabit Ethernet", sizeof (ap->name)); + printk(KERN_INFO "%s: Farallon PN9100-T ", + dev->name); + } else { + strncpy(ap->name, "AceNIC Gigabit Ethernet", sizeof (ap->name)); - printk(KERN_INFO "%s: SGI AceNIC ", dev->name); - break; - default: - strncpy(ap->name, "Unknown AceNIC based Gigabit " - "Ethernet", sizeof (ap->name)); - printk(KERN_INFO "%s: Unknown AceNIC ", dev->name); + printk(KERN_INFO "%s: Alteon AceNIC ", + dev->name); + } + break; + case PCI_VENDOR_ID_3COM: + strncpy(ap->name, "3Com 3C985 Gigabit Ethernet", + sizeof (ap->name)); + printk(KERN_INFO "%s: 3Com 3C985 ", dev->name); + break; + case PCI_VENDOR_ID_NETGEAR: + strncpy(ap->name, "NetGear GA620 Gigabit Ethernet", + sizeof (ap->name)); + printk(KERN_INFO "%s: NetGear GA620 ", dev->name); + break; + case PCI_VENDOR_ID_DEC: + if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX) { + strncpy(ap->name, "Farallon PN9000-SX " + "Gigabit Ethernet", sizeof (ap->name)); + printk(KERN_INFO "%s: Farallon PN9000-SX ", + dev->name); break; } - ap->name [sizeof (ap->name) - 1] = '\0'; - printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr); + case PCI_VENDOR_ID_SGI: + strncpy(ap->name, "SGI AceNIC Gigabit Ethernet", + sizeof (ap->name)); + printk(KERN_INFO "%s: SGI AceNIC ", dev->name); + break; + default: + strncpy(ap->name, "Unknown AceNIC based Gigabit " + "Ethernet", sizeof (ap->name)); + printk(KERN_INFO "%s: Unknown AceNIC ", dev->name); + break; + } + + ap->name [sizeof (ap->name) - 1] = '\0'; + printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr); #ifdef __sparc__ - printk("irq %s\n", __irq_itoa(pdev->irq)); + printk("irq %s\n", __irq_itoa(pdev->irq)); #else - printk("irq %i\n", pdev->irq); + printk("irq %i\n", pdev->irq); #endif #ifdef CONFIG_ACENIC_OMIT_TIGON_I - if ((readl(&ap->regs->HostCtrl) >> 28) == 4) { - printk(KERN_ERR "%s: Driver compiled without Tigon I" - " support - NIC disabled\n", dev->name); - ace_init_cleanup(dev); - free_netdev(dev); - continue; - } + if ((readl(&ap->regs->HostCtrl) >> 28) == 4) { + printk(KERN_ERR "%s: Driver compiled without Tigon I" + " support - NIC disabled\n", dev->name); + goto fail_uninit; + } #endif - if (ace_allocate_descriptors(dev)) { - /* - * ace_allocate_descriptors() calls - * ace_init_cleanup() on error. - */ - free_netdev(dev); - continue; - } + if (ace_allocate_descriptors(dev)) + goto fail_free_netdev; #ifdef MODULE - if (boards_found >= ACE_MAX_MOD_PARMS) - ap->board_idx = BOARD_IDX_OVERFLOW; - else - ap->board_idx = boards_found; + if (boards_found >= ACE_MAX_MOD_PARMS) + ap->board_idx = BOARD_IDX_OVERFLOW; + else + ap->board_idx = boards_found; #else - ap->board_idx = BOARD_IDX_STATIC; + ap->board_idx = BOARD_IDX_STATIC; #endif - if (ace_init(dev)) { - /* - * ace_init() calls ace_init_cleanup() on error. - */ - free_netdev(dev); - continue; - } + if (ace_init(dev)) + goto fail_free_netdev; - if (register_netdev(dev)) { - printk(KERN_ERR "acenic: device registration failed\n"); - ace_init_cleanup(dev); - free_netdev(dev); - continue; - } - - if (ap->pci_using_dac) - dev->features |= NETIF_F_HIGHDMA; - - boards_found++; + if (register_netdev(dev)) { + printk(KERN_ERR "acenic: device registration failed\n"); + goto fail_uninit; } - /* - * If we're at this point we're going through ace_probe() for - * the first time. Return success (0) if we've initialized 1 - * or more boards. Otherwise, return failure (-ENODEV). - */ - - if (boards_found > 0) - return 0; - else - return -ENODEV; -} + if (ap->pci_using_dac) + dev->features |= NETIF_F_HIGHDMA; + pci_set_drvdata(pdev, dev); -#ifdef MODULE -MODULE_AUTHOR("Jes Sorensen "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); -MODULE_PARM(link, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(trace, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(tx_coal_tick, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM(tx_ratio, "1-" __MODULE_STRING(8) "i"); -MODULE_PARM_DESC(link, "AceNIC/3C985/NetGear link state"); -MODULE_PARM_DESC(trace, "AceNIC/3C985/NetGear firmware trace level"); -MODULE_PARM_DESC(tx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first tx descriptor arrives"); -MODULE_PARM_DESC(max_tx_desc, "AceNIC/3C985/GA620 max number of transmit descriptors to wait"); -MODULE_PARM_DESC(rx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first rx descriptor arrives"); -MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descriptors to wait"); -MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)"); -#endif + boards_found++; + return 0; + fail_uninit: + ace_init_cleanup(dev); + fail_free_netdev: + free_netdev(dev); + return -ENODEV; +} -static void __exit ace_module_cleanup(void) +static void __devexit acenic_remove_one(struct pci_dev *pdev) { - struct ace_private *ap; - struct ace_regs *regs; - struct net_device *next; + struct net_device *dev = pci_get_drvdata(pdev); + struct ace_private *ap = dev->priv; + struct ace_regs *regs = ap->regs; short i; - while (root_dev) { - ap = root_dev->priv; - next = ap->next; - unregister_netdev(root_dev); + unregister_netdev(dev); - regs = ap->regs; - - writel(readl(®s->CpuCtrl) | CPU_HALT, ®s->CpuCtrl); - if (ap->version >= 2) - writel(readl(®s->CpuBCtrl) | CPU_HALT, - ®s->CpuBCtrl); - /* - * This clears any pending interrupts - */ - writel(1, ®s->Mb0Lo); - readl(®s->CpuCtrl); /* flush */ + writel(readl(®s->CpuCtrl) | CPU_HALT, ®s->CpuCtrl); + if (ap->version >= 2) + writel(readl(®s->CpuBCtrl) | CPU_HALT, ®s->CpuBCtrl); + + /* + * This clears any pending interrupts + */ + writel(1, ®s->Mb0Lo); + readl(®s->CpuCtrl); /* flush */ - /* - * Make sure no other CPUs are processing interrupts - * on the card before the buffers are being released. - * Otherwise one might experience some `interesting' - * effects. - * - * Then release the RX buffers - jumbo buffers were - * already released in ace_close(). - */ - ace_sync_irq(root_dev->irq); + /* + * Make sure no other CPUs are processing interrupts + * on the card before the buffers are being released. + * Otherwise one might experience some `interesting' + * effects. + * + * Then release the RX buffers - jumbo buffers were + * already released in ace_close(). + */ + ace_sync_irq(dev->irq); - for (i = 0; i < RX_STD_RING_ENTRIES; i++) { - struct sk_buff *skb = ap->skb->rx_std_skbuff[i].skb; + for (i = 0; i < RX_STD_RING_ENTRIES; i++) { + struct sk_buff *skb = ap->skb->rx_std_skbuff[i].skb; - if (skb) { - struct ring_info *ringp; - dma_addr_t mapping; + if (skb) { + struct ring_info *ringp; + dma_addr_t mapping; - ringp = &ap->skb->rx_std_skbuff[i]; - mapping = pci_unmap_addr(ringp, mapping); - pci_unmap_page(ap->pdev, mapping, - ACE_STD_BUFSIZE - (2 + 16), - PCI_DMA_FROMDEVICE); + ringp = &ap->skb->rx_std_skbuff[i]; + mapping = pci_unmap_addr(ringp, mapping); + pci_unmap_page(ap->pdev, mapping, + ACE_STD_BUFSIZE - (2 + 16), + PCI_DMA_FROMDEVICE); - ap->rx_std_ring[i].size = 0; - ap->skb->rx_std_skbuff[i].skb = NULL; - dev_kfree_skb(skb); - } - } - if (ap->version >= 2) { - for (i = 0; i < RX_MINI_RING_ENTRIES; i++) { - struct sk_buff *skb = ap->skb->rx_mini_skbuff[i].skb; - - if (skb) { - struct ring_info *ringp; - dma_addr_t mapping; - - ringp = &ap->skb->rx_mini_skbuff[i]; - mapping = pci_unmap_addr(ringp,mapping); - pci_unmap_page(ap->pdev, mapping, - ACE_MINI_BUFSIZE - (2 + 16), - PCI_DMA_FROMDEVICE); - - ap->rx_mini_ring[i].size = 0; - ap->skb->rx_mini_skbuff[i].skb = NULL; - dev_kfree_skb(skb); - } - } + ap->rx_std_ring[i].size = 0; + ap->skb->rx_std_skbuff[i].skb = NULL; + dev_kfree_skb(skb); } - for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) { - struct sk_buff *skb = ap->skb->rx_jumbo_skbuff[i].skb; + } + + if (ap->version >= 2) { + for (i = 0; i < RX_MINI_RING_ENTRIES; i++) { + struct sk_buff *skb = ap->skb->rx_mini_skbuff[i].skb; + if (skb) { struct ring_info *ringp; dma_addr_t mapping; - ringp = &ap->skb->rx_jumbo_skbuff[i]; - mapping = pci_unmap_addr(ringp, mapping); + ringp = &ap->skb->rx_mini_skbuff[i]; + mapping = pci_unmap_addr(ringp,mapping); pci_unmap_page(ap->pdev, mapping, - ACE_JUMBO_BUFSIZE - (2 + 16), + ACE_MINI_BUFSIZE - (2 + 16), PCI_DMA_FROMDEVICE); - ap->rx_jumbo_ring[i].size = 0; - ap->skb->rx_jumbo_skbuff[i].skb = NULL; + ap->rx_mini_ring[i].size = 0; + ap->skb->rx_mini_skbuff[i].skb = NULL; dev_kfree_skb(skb); } } - - ace_init_cleanup(root_dev); - free_netdev(root_dev); - root_dev = next; } -} + for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) { + struct sk_buff *skb = ap->skb->rx_jumbo_skbuff[i].skb; + if (skb) { + struct ring_info *ringp; + dma_addr_t mapping; -int __init ace_module_init(void) -{ - int status; + ringp = &ap->skb->rx_jumbo_skbuff[i]; + mapping = pci_unmap_addr(ringp, mapping); + pci_unmap_page(ap->pdev, mapping, + ACE_JUMBO_BUFSIZE - (2 + 16), + PCI_DMA_FROMDEVICE); - root_dev = NULL; + ap->rx_jumbo_ring[i].size = 0; + ap->skb->rx_jumbo_skbuff[i].skb = NULL; + dev_kfree_skb(skb); + } + } -#ifdef NEW_NETINIT - status = acenic_probe(); -#else - status = acenic_probe(NULL); -#endif - return status; + ace_init_cleanup(dev); + free_netdev(dev); } +static struct pci_driver acenic_pci_driver = { + .name = "acenic", + .id_table = acenic_pci_tbl, + .probe = acenic_probe_one, + .remove = __devexit_p(acenic_remove_one), +}; -#if (LINUX_VERSION_CODE < 0x02032a) -#ifdef MODULE -int init_module(void) +static int __init acenic_init(void) { - return ace_module_init(); + return pci_module_init(&acenic_pci_driver); } - -void cleanup_module(void) +static void __exit acenic_exit(void) { - ace_module_cleanup(); + pci_unregister_driver(&acenic_pci_driver); } -#endif -#else -module_init(ace_module_init); -module_exit(ace_module_cleanup); -#endif +module_init(acenic_init); +module_exit(acenic_exit); static void ace_free_descriptors(struct net_device *dev) { @@ -1462,13 +1203,6 @@ } else dev->irq = pdev->irq; - /* - * Register the device here to be able to catch allocated - * interrupt handlers in case the firmware doesn't come up. - */ - ap->next = root_dev; - root_dev = dev; - #ifdef INDEX_DEBUG spin_lock_init(&ap->debug_lock); ap->last_tx = ACE_TX_RING_ENTRIES(ap) - 1; @@ -2642,8 +2376,6 @@ netif_start_queue(dev); - ACE_MOD_INC_USE_COUNT; - /* * Setup the bottom half rx ring refill handler */ @@ -2660,8 +2392,6 @@ unsigned long flags; short i; - ace_if_down(dev); - /* * Without (or before) releasing irq and stopping hardware, this * is an absolute non-sense, by the way. It will be reset instantly @@ -2733,7 +2463,6 @@ ace_unmask_irq(dev); local_irq_restore(flags); - ACE_MOD_DEC_USE_COUNT; return 0; } @@ -2790,12 +2519,6 @@ struct tx_desc *desc; u32 idx, flagsize; - /* - * This only happens with pre-softnet, ie. 2.2.x kernels. - */ - if (early_stop_netif_stop_queue(dev)) - return 1; - restart: idx = ap->tx_prd; --- diff/drivers/net/at1700.c 2004-05-19 22:11:53.000000000 +0100 +++ source/drivers/net/at1700.c 2004-05-27 18:34:17.000000000 +0100 @@ -80,17 +80,10 @@ * ISA */ -#ifndef CONFIG_X86_PC9800 static unsigned at1700_probe_list[] __initdata = { 0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0 }; -#else /* CONFIG_X86_PC9800 */ -static unsigned at1700_probe_list[] __initdata = { - 0x1d6, 0x1d8, 0x1da, 0x1d4, 0xd4, 0xd2, 0xd8, 0xd0, 0 -}; - -#endif /* CONFIG_X86_PC9800 */ /* * MCA */ @@ -133,7 +126,6 @@ /* Offsets from the base address. */ -#ifndef CONFIG_X86_PC9800 #define STATUS 0 #define TX_STATUS 0 #define RX_STATUS 1 @@ -161,34 +153,6 @@ #define RESET 31 /* Write to reset some parts of the chip. */ #define AT1700_IO_EXTENT 32 #define PORT_OFFSET(o) (o) -#else /* CONFIG_X86_PC9800 */ -#define STATUS (0x0000) -#define TX_STATUS (0x0000) -#define RX_STATUS (0x0001) -#define TX_INTR (0x0200)/* Bit-mapped interrupt enable registers. */ -#define RX_INTR (0x0201) -#define TX_MODE (0x0400) -#define RX_MODE (0x0401) -#define CONFIG_0 (0x0600)/* Misc. configuration settings. */ -#define CONFIG_1 (0x0601) -/* Run-time register bank 2 definitions. */ -#define DATAPORT (0x0800)/* Word-wide DMA or programmed-I/O dataport. */ -#define TX_START (0x0a00) -#define COL16CNTL (0x0a01)/* Controll Reg for 16 collisions */ -#define MODE13 (0x0c01) -#define RX_CTRL (0x0e00) -/* Configuration registers only on the '865A/B chips. */ -#define EEPROM_Ctrl (0x1000) -#define EEPROM_Data (0x1200) -#define CARDSTATUS 16 /* FMV-18x Card Status */ -#define CARDSTATUS1 17 /* FMV-18x Card Status */ -#define IOCONFIG (0x1400)/* Either read the jumper, or move the I/O. */ -#define IOCONFIG1 (0x1600) -#define SAPROM 20 /* The station address PROM, if no EEPROM. */ -#define MODE24 (0x1800)/* The station address PROM, if no EEPROM. */ -#define RESET (0x1e01)/* Write to reset some parts of the chip. */ -#define PORT_OFFSET(o) ({ int _o_ = (o); (_o_ & ~1) * 0x100 + (_o_ & 1); }) -#endif /* CONFIG_X86_PC9800 */ #define TX_TIMEOUT 10 @@ -230,11 +194,7 @@ (detachable devices only). */ -#ifndef CONFIG_X86_PC9800 static int io = 0x260; -#else -static int io = 0xd0; -#endif static int irq; @@ -246,15 +206,7 @@ mca_mark_as_unused(lp->mca_slot); #endif free_irq(dev->irq, NULL); -#ifndef CONFIG_X86_PC9800 release_region(dev->base_addr, AT1700_IO_EXTENT); -#else - { - int i; - for (i = 0; i < 0x2000; i += 0x200) - release_region(dev->base_addr + i, 2); - } -#endif } struct net_device * __init at1700_probe(int unit) @@ -321,20 +273,8 @@ int slot, ret = -ENODEV; struct net_local *lp = netdev_priv(dev); -#ifndef CONFIG_X86_PC9800 if (!request_region(ioaddr, AT1700_IO_EXTENT, dev->name)) return -EBUSY; -#else - for (i = 0; i < 0x2000; i += 0x0200) { - if (!request_region(ioaddr + i, 2, dev->name)) { - while (i > 0) { - i -= 0x0200; - release_region(ioaddr + i, 2); - } - return -EBUSY; - } - } -#endif /* Resetting the chip doesn't reset the ISA interface, so don't bother. That means we have to be careful with the register values we probe @@ -425,15 +365,8 @@ outb(0, ioaddr + RESET); if (is_at1700) { -#ifndef CONFIG_X86_PC9800 irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04) | (read_eeprom(ioaddr, 0)>>14)]; -#else - { - char re1000plus_irqmap[4] = {3, 5, 6, 12}; - irq = re1000plus_irqmap[inb(ioaddr + IOCONFIG1) >> 6]; - } -#endif } else { /* Check PnP mode for FMV-183/184/183A/184A. */ /* This PnP routine is very poor. IO and IRQ should be known. */ @@ -517,11 +450,7 @@ /* Switch to bank 2 */ /* Lock our I/O address, and set manual processing mode for 16 collisions. */ outb(0x08, ioaddr + CONFIG_1); -#ifndef CONFIG_X86_PC9800 outb(dev->if_port, ioaddr + MODE13); -#else - outb(0, ioaddr + MODE13); -#endif outb(0x00, ioaddr + COL16CNTL); if (net_debug) @@ -552,12 +481,7 @@ return 0; err_out: -#ifndef CONFIG_X86_PC9800 release_region(ioaddr, AT1700_IO_EXTENT); -#else - for (i = 0; i < 0x2000; i += 0x0200) - release_region(ioaddr + i, 2); -#endif return ret; } @@ -568,13 +492,6 @@ #define EE_DATA_WRITE 0x80 /* EEPROM chip data in, in reg. 17. */ #define EE_DATA_READ 0x80 /* EEPROM chip data out, in reg. 17. */ -/* Delay between EEPROM clock transitions. */ -#ifndef CONFIG_X86_PC9800 -#define eeprom_delay() do { } while (0) -#else -#define eeprom_delay() __asm__ ("out%B0 %%al,%0" :: "N"(0x5f)) -#endif - /* The EEPROM commands include the alway-set leading bit. */ #define EE_WRITE_CMD (5 << 6) #define EE_READ_CMD (6 << 6) @@ -593,22 +510,17 @@ short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; outb(EE_CS, ee_addr); outb(dataval, ee_daddr); - eeprom_delay(); outb(EE_CS | EE_SHIFT_CLK, ee_addr); /* EEPROM clock tick. */ - eeprom_delay(); } outb(EE_DATA_WRITE, ee_daddr); for (i = 16; i > 0; i--) { outb(EE_CS, ee_addr); - eeprom_delay(); outb(EE_CS | EE_SHIFT_CLK, ee_addr); - eeprom_delay(); retval = (retval << 1) | ((inb(ee_daddr) & EE_DATA_READ) ? 1 : 0); } /* Terminate the EEPROM access. */ outb(EE_CS, ee_addr); - eeprom_delay(); outb(EE_SHIFT_CLK, ee_addr); outb(0, ee_addr); return retval; --- diff/drivers/net/e1000/e1000_ethtool.c 2004-05-19 22:11:57.000000000 +0100 +++ source/drivers/net/e1000/e1000_ethtool.c 2004-05-27 18:34:17.000000000 +0100 @@ -53,7 +53,7 @@ #define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \ offsetof(struct e1000_adapter, m) -static struct e1000_stats e1000_gstrings_stats[] = { +static const struct e1000_stats e1000_gstrings_stats[] = { { "rx_packets", E1000_STAT(net_stats.rx_packets) }, { "tx_packets", E1000_STAT(net_stats.tx_packets) }, { "rx_bytes", E1000_STAT(net_stats.rx_bytes) }, @@ -100,9 +100,10 @@ }; #define E1000_TEST_LEN sizeof(e1000_gstrings_test) / ETH_GSTRING_LEN -static void -e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) +static int +e1000_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; if(hw->media_type == e1000_media_type_copper) { @@ -169,11 +170,13 @@ } ecmd->autoneg = (hw->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); + return 0; } static int -e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) +e1000_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; if(ecmd->autoneg == AUTONEG_ENABLE) { @@ -195,10 +198,11 @@ return 0; } -static int -e1000_ethtool_gpause(struct e1000_adapter *adapter, +static void +e1000_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *epause) { + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; epause->autoneg = @@ -212,14 +216,13 @@ epause->rx_pause = 1; epause->tx_pause = 1; } - - return 0; } static int -e1000_ethtool_spause(struct e1000_adapter *adapter, +e1000_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *epause) { + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; adapter->fc_autoneg = epause->autoneg; @@ -248,28 +251,95 @@ return 0; } +static u32 +e1000_get_rx_csum(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + return adapter->rx_csum; +} + +static int +e1000_set_rx_csum(struct net_device *netdev, u32 data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + adapter->rx_csum = data; + if(netif_running(netdev)) { + e1000_down(adapter); + e1000_up(adapter); + } else + e1000_reset(adapter); + return 0; +} + +static u32 +e1000_get_tx_csum(struct net_device *netdev) +{ + return (netdev->features & NETIF_F_HW_CSUM) != 0; +} + +static int +e1000_set_tx_csum(struct net_device *netdev, u32 data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + if(adapter->hw.mac_type < e1000_82543) + return data ? -EINVAL : 0; + + if (data) + netdev->features |= NETIF_F_HW_CSUM; + else + netdev->features &= ~NETIF_F_HW_CSUM; + return 0; +} + +static int +e1000_set_tso(struct net_device *netdev, u32 data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + if (adapter->hw.mac_type < e1000_82544 || + adapter->hw.mac_type == e1000_82547) + return data ? -EINVAL : 0; + + if (data) + netdev->features |= NETIF_F_TSO; + else + netdev->features &= ~NETIF_F_TSO; + return 0; +} + + static void -e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter, - struct ethtool_drvinfo *drvinfo) +e1000_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *drvinfo) { + struct e1000_adapter *adapter = netdev_priv(dev); + strncpy(drvinfo->driver, e1000_driver_name, 32); strncpy(drvinfo->version, e1000_driver_version, 32); strncpy(drvinfo->fw_version, "N/A", 32); strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); - drvinfo->n_stats = E1000_STATS_LEN; - drvinfo->testinfo_len = E1000_TEST_LEN; +} + +static int +e1000_get_regs_len(struct net_device *dev) +{ #define E1000_REGS_LEN 32 - drvinfo->regdump_len = E1000_REGS_LEN * sizeof(uint32_t); - drvinfo->eedump_len = adapter->hw.eeprom.word_size * 2; + return E1000_REGS_LEN * sizeof(uint32_t); } static void -e1000_ethtool_gregs(struct e1000_adapter *adapter, - struct ethtool_regs *regs, uint32_t *regs_buff) +e1000_get_regs(struct net_device *dev, + struct ethtool_regs *regs, void *p) { + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; + u32 *regs_buff = p; uint16_t phy_data; + memset(p, 0, E1000_REGS_LEN * sizeof(uint32_t)); + regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; regs_buff[0] = E1000_READ_REG(hw, CTRL); @@ -342,30 +412,36 @@ e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); regs_buff[24] = (uint32_t)phy_data; /* phy local receiver status */ regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ +} - return; +static int +e1000_get_eeprom_len(struct net_device *dev) +{ + struct e1000_adapter *adapter = netdev_priv(dev); + + return adapter->hw.eeprom.word_size * 2; } static int -e1000_ethtool_geeprom(struct e1000_adapter *adapter, - struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff) +e1000_get_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *bytes) { + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; + uint16_t *eeprom_buff = (uint16_t *) bytes; int first_word, last_word; int ret_val = 0; uint16_t i; - if(eeprom->len == 0) { - ret_val = -EINVAL; - goto geeprom_error; - } + if(eeprom->len == 0) + return -EINVAL; eeprom->magic = hw->vendor_id | (hw->device_id << 16); - if(eeprom->offset > eeprom->offset + eeprom->len) { - ret_val = -EINVAL; - goto geeprom_error; - } + if(eeprom->offset > eeprom->offset + eeprom->len) + return -EINVAL; + + memset(bytes, 0, adapter->hw.eeprom.word_size*2); if((eeprom->offset + eeprom->len) > (hw->eeprom.word_size * 2)) eeprom->len = ((hw->eeprom.word_size * 2) - eeprom->offset); @@ -388,14 +464,14 @@ for (i = 0; i < last_word - first_word + 1; i++) le16_to_cpus(&eeprom_buff[i]); -geeprom_error: return ret_val; } static int -e1000_ethtool_seeprom(struct e1000_adapter *adapter, - struct ethtool_eeprom *eeprom, void *user_data) +e1000_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) { + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; uint16_t *eeprom_buff; void *ptr; @@ -439,11 +515,7 @@ for (i = 0; i < last_word - first_word + 1; i++) le16_to_cpus(&eeprom_buff[i]); - if((ret_val != 0) || copy_from_user(ptr, user_data, eeprom->len)) { - ret_val = -EFAULT; - goto seeprom_error; - } - + memcpy(ptr, bytes, eeprom->len); for (i = 0; i < last_word - first_word + 1; i++) eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); @@ -454,15 +526,15 @@ if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG) e1000_update_eeprom_checksum(hw); -seeprom_error: kfree(eeprom_buff); return ret_val; } -static int -e1000_ethtool_gring(struct e1000_adapter *adapter, +static void +e1000_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { + struct e1000_adapter *adapter = netdev_priv(netdev); e1000_mac_type mac_type = adapter->hw.mac_type; struct e1000_desc_ring *txdr = &adapter->tx_ring; struct e1000_desc_ring *rxdr = &adapter->rx_ring; @@ -477,13 +549,12 @@ ring->tx_pending = txdr->count; ring->rx_mini_pending = 0; ring->rx_jumbo_pending = 0; - - return 0; } + static int -e1000_ethtool_sring(struct e1000_adapter *adapter, - struct ethtool_ringparam *ring) +e1000_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { + struct e1000_adapter *adapter = netdev_priv(netdev); int err; e1000_mac_type mac_type = adapter->hw.mac_type; struct e1000_desc_ring *txdr = &adapter->tx_ring; @@ -806,8 +877,6 @@ kfree(txdr->buffer_info); if(rxdr->buffer_info) kfree(rxdr->buffer_info); - - return; } static int @@ -939,8 +1008,6 @@ e1000_write_phy_reg(&adapter->hw, 30, 0x8FFC); e1000_write_phy_reg(&adapter->hw, 29, 0x001A); e1000_write_phy_reg(&adapter->hw, 30, 0x8FF0); - - return; } static void @@ -1257,11 +1324,19 @@ return *data; } + static int -e1000_ethtool_test(struct e1000_adapter *adapter, - struct ethtool_test *eth_test, uint64_t *data) +e1000_diag_test_count(struct net_device *dev) { - boolean_t if_running = netif_running(adapter->netdev); + return E1000_TEST_LEN; +} + +static void +e1000_diag_test(struct net_device *netdev, + struct ethtool_test *eth_test, u64 *data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + boolean_t if_running = netif_running(netdev); if(eth_test->flags == ETH_TEST_FL_OFFLINE) { /* Offline tests */ @@ -1305,12 +1380,12 @@ data[2] = 0; data[3] = 0; } - return 0; } static void -e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) +e1000_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; switch(adapter->hw.device_id) { @@ -1348,10 +1423,10 @@ return; } } - static int -e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) +e1000_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; switch(adapter->hw.device_id) { @@ -1408,8 +1483,13 @@ } static int -e1000_ethtool_led_blink(struct e1000_adapter *adapter, struct ethtool_value *id) +e1000_phys_id(struct net_device *netdev, u32 data) { + struct e1000_adapter *adapter = netdev_priv(netdev); + + if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) + data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); + if(!adapter->blink_timer.function) { init_timer(&adapter->blink_timer); adapter->blink_timer.function = e1000_led_blink_callback; @@ -1420,11 +1500,7 @@ mod_timer(&adapter->blink_timer, jiffies); set_current_state(TASK_INTERRUPTIBLE); - if(id->data) - schedule_timeout(id->data * HZ); - else - schedule_timeout(MAX_SCHEDULE_TIMEOUT); - + schedule_timeout(data * HZ); del_timer_sync(&adapter->blink_timer); e1000_led_off(&adapter->hw); clear_bit(E1000_LED_ON, &adapter->led_status); @@ -1433,345 +1509,89 @@ return 0; } -int -e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) +static int +e1000_nway_reset(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev->priv; - void *addr = ifr->ifr_data; - uint32_t cmd; - - if(get_user(cmd, (uint32_t *) addr)) - return -EFAULT; - - switch(cmd) { - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = {ETHTOOL_GSET}; - e1000_ethtool_gset(adapter, &ecmd); - if(copy_to_user(addr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - case ETHTOOL_SSET: { - struct ethtool_cmd ecmd; - if(copy_from_user(&ecmd, addr, sizeof(ecmd))) - return -EFAULT; - return e1000_ethtool_sset(adapter, &ecmd); - } - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo drvinfo = {ETHTOOL_GDRVINFO}; - e1000_ethtool_gdrvinfo(adapter, &drvinfo); - if(copy_to_user(addr, &drvinfo, sizeof(drvinfo))) - return -EFAULT; - return 0; - } - case ETHTOOL_GSTRINGS: { - struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS }; - char *strings = NULL; - int err = 0; - - if(copy_from_user(&gstrings, addr, sizeof(gstrings))) - return -EFAULT; - switch(gstrings.string_set) { - case ETH_SS_TEST: - gstrings.len = E1000_TEST_LEN; - strings = kmalloc(E1000_TEST_LEN * ETH_GSTRING_LEN, - GFP_KERNEL); - if(!strings) - return -ENOMEM; - memcpy(strings, e1000_gstrings_test, E1000_TEST_LEN * - ETH_GSTRING_LEN); - break; - case ETH_SS_STATS: { - int i; - gstrings.len = E1000_STATS_LEN; - strings = kmalloc(E1000_STATS_LEN * ETH_GSTRING_LEN, - GFP_KERNEL); - if(!strings) - return -ENOMEM; - for(i=0; i < E1000_STATS_LEN; i++) { - memcpy(&strings[i * ETH_GSTRING_LEN], - e1000_gstrings_stats[i].stat_string, - ETH_GSTRING_LEN); - } - break; - } - default: - return -EOPNOTSUPP; - } - if(copy_to_user(addr, &gstrings, sizeof(gstrings))) - err = -EFAULT; - addr += offsetof(struct ethtool_gstrings, data); - if(!err && copy_to_user(addr, strings, - gstrings.len * ETH_GSTRING_LEN)) - err = -EFAULT; - - kfree(strings); - return err; - } - case ETHTOOL_GREGS: { - struct ethtool_regs regs = {ETHTOOL_GREGS}; - uint32_t regs_buff[E1000_REGS_LEN]; - - if(copy_from_user(®s, addr, sizeof(regs))) - return -EFAULT; - memset(regs_buff, 0, sizeof(regs_buff)); - if (regs.len > E1000_REGS_LEN) - regs.len = E1000_REGS_LEN; - e1000_ethtool_gregs(adapter, ®s, regs_buff); - if(copy_to_user(addr, ®s, sizeof(regs))) - return -EFAULT; - - addr += offsetof(struct ethtool_regs, data); - if(copy_to_user(addr, regs_buff, regs.len)) - return -EFAULT; - - return 0; - } - case ETHTOOL_NWAY_RST: { - if(netif_running(netdev)) { - e1000_down(adapter); - e1000_up(adapter); - } - return 0; - } - case ETHTOOL_PHYS_ID: { - struct ethtool_value id; - if(copy_from_user(&id, addr, sizeof(id))) - return -EFAULT; - return e1000_ethtool_led_blink(adapter, &id); - } - case ETHTOOL_GLINK: { - struct ethtool_value link = {ETHTOOL_GLINK}; - link.data = netif_carrier_ok(netdev); - if(copy_to_user(addr, &link, sizeof(link))) - return -EFAULT; - return 0; - } - case ETHTOOL_GWOL: { - struct ethtool_wolinfo wol = {ETHTOOL_GWOL}; - e1000_ethtool_gwol(adapter, &wol); - if(copy_to_user(addr, &wol, sizeof(wol)) != 0) - return -EFAULT; - return 0; - } - case ETHTOOL_SWOL: { - struct ethtool_wolinfo wol; - if(copy_from_user(&wol, addr, sizeof(wol)) != 0) - return -EFAULT; - return e1000_ethtool_swol(adapter, &wol); - } - case ETHTOOL_GEEPROM: { - struct ethtool_eeprom eeprom = {ETHTOOL_GEEPROM}; - struct e1000_hw *hw = &adapter->hw; - uint16_t *eeprom_buff; - void *ptr; - int err = 0; - - if(copy_from_user(&eeprom, addr, sizeof(eeprom))) - return -EFAULT; - - eeprom_buff = kmalloc(hw->eeprom.word_size * 2, GFP_KERNEL); - - if(!eeprom_buff) - return -ENOMEM; - - if((err = e1000_ethtool_geeprom(adapter, &eeprom, - eeprom_buff))) - goto err_geeprom_ioctl; - - if(copy_to_user(addr, &eeprom, sizeof(eeprom))) { - err = -EFAULT; - goto err_geeprom_ioctl; - } - - addr += offsetof(struct ethtool_eeprom, data); - ptr = ((void *)eeprom_buff) + (eeprom.offset & 1); - - if(copy_to_user(addr, ptr, eeprom.len)) - err = -EFAULT; - -err_geeprom_ioctl: - kfree(eeprom_buff); - return err; - } - case ETHTOOL_SEEPROM: { - struct ethtool_eeprom eeprom; - - if(copy_from_user(&eeprom, addr, sizeof(eeprom))) - return -EFAULT; - - addr += offsetof(struct ethtool_eeprom, data); - return e1000_ethtool_seeprom(adapter, &eeprom, addr); - } - case ETHTOOL_GRINGPARAM: { - struct ethtool_ringparam ering = {ETHTOOL_GRINGPARAM}; - e1000_ethtool_gring(adapter, &ering); - if(copy_to_user(addr, &ering, sizeof(ering))) - return -EFAULT; - return 0; - } - case ETHTOOL_SRINGPARAM: { - struct ethtool_ringparam ering; - if(copy_from_user(&ering, addr, sizeof(ering))) - return -EFAULT; - return e1000_ethtool_sring(adapter, &ering); - } - case ETHTOOL_GPAUSEPARAM: { - struct ethtool_pauseparam epause = {ETHTOOL_GPAUSEPARAM}; - e1000_ethtool_gpause(adapter, &epause); - if(copy_to_user(addr, &epause, sizeof(epause))) - return -EFAULT; - return 0; - } - case ETHTOOL_SPAUSEPARAM: { - struct ethtool_pauseparam epause; - if(copy_from_user(&epause, addr, sizeof(epause))) - return -EFAULT; - return e1000_ethtool_spause(adapter, &epause); - } - case ETHTOOL_GSTATS: { - struct { - struct ethtool_stats eth_stats; - uint64_t data[E1000_STATS_LEN]; - } stats = { {ETHTOOL_GSTATS, E1000_STATS_LEN} }; - int i; - - e1000_update_stats(adapter); - for(i = 0; i < E1000_STATS_LEN; i++) - stats.data[i] = (e1000_gstrings_stats[i].sizeof_stat == - sizeof(uint64_t)) ? - *(uint64_t *)((char *)adapter + - e1000_gstrings_stats[i].stat_offset) : - *(uint32_t *)((char *)adapter + - e1000_gstrings_stats[i].stat_offset); - if(copy_to_user(addr, &stats, sizeof(stats))) - return -EFAULT; - return 0; - } - case ETHTOOL_TEST: { - struct { - struct ethtool_test eth_test; - uint64_t data[E1000_TEST_LEN]; - } test = { {ETHTOOL_TEST} }; - int err; - - if(copy_from_user(&test.eth_test, addr, sizeof(test.eth_test))) - return -EFAULT; - - test.eth_test.len = E1000_TEST_LEN; - - if((err = e1000_ethtool_test(adapter, &test.eth_test, - test.data))) - return err; - - if(copy_to_user(addr, &test, sizeof(test)) != 0) - return -EFAULT; - return 0; - } - case ETHTOOL_GRXCSUM: { - struct ethtool_value edata = { ETHTOOL_GRXCSUM }; - - edata.data = adapter->rx_csum; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_SRXCSUM: { - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - adapter->rx_csum = edata.data; - if(netif_running(netdev)) { - e1000_down(adapter); - e1000_up(adapter); - } else - e1000_reset(adapter); - return 0; - } - case ETHTOOL_GTXCSUM: { - struct ethtool_value edata = { ETHTOOL_GTXCSUM }; + struct e1000_adapter *adapter = netdev_priv(netdev); - edata.data = - (netdev->features & NETIF_F_HW_CSUM) != 0; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; + if(netif_running(netdev)) { + e1000_down(adapter); + e1000_up(adapter); } - case ETHTOOL_STXCSUM: { - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - - if(adapter->hw.mac_type < e1000_82543) { - if (edata.data != 0) - return -EINVAL; - return 0; - } + return 0; +} - if (edata.data) - netdev->features |= NETIF_F_HW_CSUM; - else - netdev->features &= ~NETIF_F_HW_CSUM; +static int +e1000_get_stats_count(struct net_device *dev) +{ + return E1000_STATS_LEN; +} - return 0; - } - case ETHTOOL_GSG: { - struct ethtool_value edata = { ETHTOOL_GSG }; +static void +e1000_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 *data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + int i; - edata.data = - (netdev->features & NETIF_F_SG) != 0; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; + e1000_update_stats(adapter); + for(i = 0; i < E1000_STATS_LEN; i++) { + char *p = (char *) adapter + e1000_gstrings_stats[i].stat_offset; + data[i] = (e1000_gstrings_stats[i].sizeof_stat == sizeof(uint64_t)) + ? *(uint64_t *)p : *(uint32_t *)p; } - case ETHTOOL_SSG: { - struct ethtool_value edata; - - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; - - if (edata.data) - netdev->features |= NETIF_F_SG; - else - netdev->features &= ~NETIF_F_SG; +} - return 0; - } -#ifdef NETIF_F_TSO - case ETHTOOL_GTSO: { - struct ethtool_value edata = { ETHTOOL_GTSO }; - - edata.data = (netdev->features & NETIF_F_TSO) != 0; - if (copy_to_user(addr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - case ETHTOOL_STSO: { - struct ethtool_value edata; +static void +e1000_get_strings(struct net_device *netdev, u32 string_set, u8 *data) +{ + int i; - if (copy_from_user(&edata, addr, sizeof(edata))) - return -EFAULT; + switch(string_set) { + case ETH_SS_TEST: + memcpy(data, e1000_gstrings_test, E1000_TEST_LEN * ETH_GSTRING_LEN); + break; - if ((adapter->hw.mac_type < e1000_82544) || - (adapter->hw.mac_type == e1000_82547)) { - if (edata.data != 0) - return -EINVAL; - return 0; + case ETH_SS_STATS: + for(i=0; i < E1000_STATS_LEN; i++) { + memcpy(data + i * ETH_GSTRING_LEN, + e1000_gstrings_stats[i].stat_string, + ETH_GSTRING_LEN); } - - if (edata.data) - netdev->features |= NETIF_F_TSO; - else - netdev->features &= ~NETIF_F_TSO; - - return 0; - } -#endif - default: - return -EOPNOTSUPP; + break; } } +struct ethtool_ops e1000_ethtool_ops = { + .get_settings = e1000_get_settings, + .set_settings = e1000_set_settings, + .get_drvinfo = e1000_get_drvinfo, + .get_regs_len = e1000_get_regs_len, + .get_regs = e1000_get_regs, + .get_wol = e1000_get_wol, + .set_wol = e1000_set_wol, + .nway_reset = e1000_nway_reset, + .get_link = ethtool_op_get_link, + .get_eeprom_len = e1000_get_eeprom_len, + .get_eeprom = e1000_get_eeprom, + .set_eeprom = e1000_set_eeprom, + .get_ringparam = e1000_get_ringparam, + .set_ringparam = e1000_set_ringparam, + .get_pauseparam = e1000_get_pauseparam, + .set_pauseparam = e1000_set_pauseparam, + .get_rx_csum = e1000_get_rx_csum, + .set_rx_csum = e1000_set_rx_csum, + .get_tx_csum = e1000_get_tx_csum, + .set_tx_csum = e1000_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = e1000_set_tso, + .self_test_count = e1000_diag_test_count, + .self_test = e1000_diag_test, + .get_strings = e1000_get_strings, + .phys_id = e1000_phys_id, + .get_stats_count = e1000_get_stats_count, + .get_ethtool_stats = e1000_get_ethtool_stats, +}; --- diff/drivers/net/e1000/e1000_main.c 2004-05-19 22:11:57.000000000 +0100 +++ source/drivers/net/e1000/e1000_main.c 2004-05-27 18:34:17.000000000 +0100 @@ -167,9 +167,9 @@ static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter); #endif static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter); -static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); -static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, - int cmd); + +static int e1000_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); +extern struct ethtool_ops e1000_ethtool_ops; static void e1000_enter_82542_rst(struct e1000_adapter *adapter); static void e1000_leave_82542_rst(struct e1000_adapter *adapter); static inline void e1000_rx_checksum(struct e1000_adapter *adapter, @@ -206,7 +206,6 @@ /* Exported from other modules */ extern void e1000_check_options(struct e1000_adapter *adapter); -extern int e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr); static struct pci_driver e1000_driver = { .name = e1000_driver_name, @@ -445,7 +444,8 @@ netdev->set_multicast_list = &e1000_set_multi; netdev->set_mac_address = &e1000_set_mac; netdev->change_mtu = &e1000_change_mtu; - netdev->do_ioctl = &e1000_ioctl; + netdev->do_ioctl = &e1000_do_ioctl; + SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops); netdev->tx_timeout = &e1000_tx_timeout; netdev->watchdog_timeo = 5 * HZ; #ifdef CONFIG_E1000_NAPI @@ -2498,37 +2498,16 @@ adapter->smartspeed = 0; } -/** - * e1000_ioctl - - * @netdev: - * @ifreq: - * @cmd: - **/ - -static int -e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - return e1000_mii_ioctl(netdev, ifr, cmd); - case SIOCETHTOOL: - return e1000_ethtool_ioctl(netdev, ifr); - default: - return -EOPNOTSUPP; - } -} /** - * e1000_mii_ioctl - + * e1000_do_ioctl - * @netdev: * @ifreq: * @cmd: **/ static int -e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +e1000_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { struct e1000_adapter *adapter = netdev->priv; struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; --- diff/drivers/net/epic100.c 2004-05-19 22:11:53.000000000 +0100 +++ source/drivers/net/epic100.c 2004-05-27 18:34:17.000000000 +0100 @@ -77,8 +77,6 @@ These may be modified when a driver module is loaded.*/ static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work = 32; /* Used to pass the full-duplex flag, etc. */ #define MAX_UNITS 8 /* More are supported, limit only on options */ @@ -96,9 +94,9 @@ Making the Tx ring too large decreases the effectiveness of channel bonding and packet priority. There are no ill effects from too-large receive rings. */ -#define TX_RING_SIZE 16 -#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */ -#define RX_RING_SIZE 32 +#define TX_RING_SIZE 256 +#define TX_QUEUE_LEN 240 /* Limit ring entries actually used. */ +#define RX_RING_SIZE 256 #define TX_TOTAL_SIZE TX_RING_SIZE*sizeof(struct epic_tx_desc) #define RX_TOTAL_SIZE RX_RING_SIZE*sizeof(struct epic_rx_desc) @@ -155,12 +153,10 @@ MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); -MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM_DESC(debug, "EPIC/100 debug level (0-5)"); -MODULE_PARM_DESC(max_interrupt_work, "EPIC/100 maximum events handled per interrupt"); MODULE_PARM_DESC(options, "EPIC/100: Bits 0-3: media type, bit 4: full duplex"); MODULE_PARM_DESC(rx_copybreak, "EPIC/100 copy breakpoint for copy-only-tiny-frames"); MODULE_PARM_DESC(full_duplex, "EPIC/100 full duplex setting(s) (1)"); @@ -292,6 +288,12 @@ StopTxDMA=0x20, StopRxDMA=0x40, RestartTx=0x80, }; +#define EpicRemoved 0xffffffff /* Chip failed or removed (CardBus) */ + +#define EpicNapiEvent (TxEmpty | TxDone | \ + RxDone | RxStarted | RxEarlyWarn | RxOverflow | RxFull) +#define EpicNormalEvent (0x0000ffff & ~EpicNapiEvent) + static u16 media2miictl[16] = { 0, 0x0C00, 0x0C00, 0x2000, 0x0100, 0x2100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -330,9 +332,12 @@ /* Ring pointers. */ spinlock_t lock; /* Group with Tx control cache line. */ + spinlock_t napi_lock; + unsigned int reschedule_in_poll; unsigned int cur_tx, dirty_tx; unsigned int cur_rx, dirty_rx; + u32 irq_mask; unsigned int rx_buf_sz; /* Based on MTU+slack. */ struct pci_dev *pci_dev; /* PCI bus location. */ @@ -359,7 +364,8 @@ static void epic_tx_timeout(struct net_device *dev); static void epic_init_ring(struct net_device *dev); static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev); -static int epic_rx(struct net_device *dev); +static int epic_rx(struct net_device *dev, int budget); +static int epic_poll(struct net_device *dev, int *budget); static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static struct ethtool_ops netdev_ethtool_ops; @@ -378,7 +384,7 @@ int irq; struct net_device *dev; struct epic_private *ep; - int i, option = 0, duplex = 0; + int i, ret, option = 0, duplex = 0; void *ring_space; dma_addr_t ring_dma; @@ -392,29 +398,33 @@ card_idx++; - i = pci_enable_device(pdev); - if (i) - return i; + ret = pci_enable_device(pdev); + if (ret) + goto out; irq = pdev->irq; if (pci_resource_len(pdev, 0) < pci_id_tbl[chip_idx].io_size) { printk (KERN_ERR "card %d: no PCI region space\n", card_idx); - return -ENODEV; + ret = -ENODEV; + goto err_out_disable; } pci_set_master(pdev); + ret = pci_request_regions(pdev, DRV_NAME); + if (ret < 0) + goto err_out_disable; + + ret = -ENOMEM; + dev = alloc_etherdev(sizeof (*ep)); if (!dev) { printk (KERN_ERR "card %d: no memory for eth device\n", card_idx); - return -ENOMEM; + goto err_out_free_res; } SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - if (pci_request_regions(pdev, DRV_NAME)) - goto err_out_free_netdev; - #ifdef USE_IO_OPS ioaddr = pci_resource_start (pdev, 0); #else @@ -422,7 +432,7 @@ ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1)); if (!ioaddr) { printk (KERN_ERR DRV_NAME " %d: ioremap failed\n", card_idx); - goto err_out_free_res; + goto err_out_free_netdev; } #endif @@ -459,7 +469,9 @@ dev->base_addr = ioaddr; dev->irq = irq; - spin_lock_init (&ep->lock); + spin_lock_init(&ep->lock); + spin_lock_init(&ep->napi_lock); + ep->reschedule_in_poll = 0; /* Bring the chip out of low-power mode. */ outl(0x4200, ioaddr + GENCTL); @@ -489,6 +501,9 @@ ep->pci_dev = pdev; ep->chip_id = chip_idx; ep->chip_flags = pci_id_tbl[chip_idx].drv_flags; + ep->irq_mask = + (ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) + | CntFull | TxUnderrun | EpicNapiEvent; /* Find the connected MII xcvrs. Doing this in open() would allow detecting external xcvrs later, but @@ -543,10 +558,12 @@ dev->ethtool_ops = &netdev_ethtool_ops; dev->watchdog_timeo = TX_TIMEOUT; dev->tx_timeout = &epic_tx_timeout; + dev->poll = epic_poll; + dev->weight = 64; - i = register_netdev(dev); - if (i) - goto err_out_unmap_tx; + ret = register_netdev(dev); + if (ret < 0) + goto err_out_unmap_rx; printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq); @@ -554,19 +571,24 @@ printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x.\n", dev->dev_addr[i]); - return 0; +out: + return ret; +err_out_unmap_rx: + pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma); err_out_unmap_tx: pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma); err_out_iounmap: #ifndef USE_IO_OPS iounmap(ioaddr); -err_out_free_res: -#endif - pci_release_regions(pdev); err_out_free_netdev: +#endif free_netdev(dev); - return -ENODEV; +err_out_free_res: + pci_release_regions(pdev); +err_out_disable: + pci_disable_device(pdev); + goto out; } /* Serial EEPROM section. */ @@ -592,6 +614,38 @@ #define EE_READ256_CMD (6 << 8) #define EE_ERASE_CMD (7 << 6) +static void epic_disable_int(struct net_device *dev, struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + + outl(0x00000000, ioaddr + INTMASK); +} + +static inline void __epic_pci_commit(long ioaddr) +{ +#ifndef USE_IO_OPS + inl(ioaddr + INTMASK); +#endif +} + +static inline void epic_napi_irq_off(struct net_device *dev, + struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + + outl(ep->irq_mask & ~EpicNapiEvent, ioaddr + INTMASK); + __epic_pci_commit(ioaddr); +} + +static inline void epic_napi_irq_on(struct net_device *dev, + struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + + /* No need to commit possible posted write */ + outl(ep->irq_mask | EpicNapiEvent, ioaddr + INTMASK); +} + static int __devinit read_eeprom(long ioaddr, int location) { int i; @@ -752,9 +806,8 @@ /* Enable interrupts by setting the interrupt mask. */ outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) - | CntFull | TxUnderrun | TxDone | TxEmpty - | RxError | RxOverflow | RxFull | RxHeader | RxDone, - ioaddr + INTMASK); + | CntFull | TxUnderrun + | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK); if (debug > 1) printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x " @@ -795,7 +848,7 @@ } /* Remove the packets on the Rx queue. */ - epic_rx(dev); + epic_rx(dev, RX_RING_SIZE); } static void epic_restart(struct net_device *dev) @@ -841,9 +894,9 @@ /* Enable interrupts by setting the interrupt mask. */ outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) - | CntFull | TxUnderrun | TxDone | TxEmpty - | RxError | RxOverflow | RxFull | RxHeader | RxDone, - ioaddr + INTMASK); + | CntFull | TxUnderrun + | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK); + printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x" " interrupt %4.4x.\n", dev->name, (int)inl(ioaddr + COMMAND), (int)inl(ioaddr + GENCTL), @@ -929,7 +982,6 @@ int i; ep->tx_full = 0; - ep->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; ep->dirty_tx = ep->cur_tx = 0; ep->cur_rx = ep->dirty_rx = 0; ep->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); @@ -1029,6 +1081,76 @@ return 0; } +static void epic_tx_error(struct net_device *dev, struct epic_private *ep, + int status) +{ + struct net_device_stats *stats = &ep->stats; + +#ifndef final_version + /* There was an major error, log it. */ + if (debug > 1) + printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", + dev->name, status); +#endif + stats->tx_errors++; + if (status & 0x1050) + stats->tx_aborted_errors++; + if (status & 0x0008) + stats->tx_carrier_errors++; + if (status & 0x0040) + stats->tx_window_errors++; + if (status & 0x0010) + stats->tx_fifo_errors++; +} + +static void epic_tx(struct net_device *dev, struct epic_private *ep) +{ + unsigned int dirty_tx, cur_tx; + + /* + * Note: if this lock becomes a problem we can narrow the locked + * region at the cost of occasionally grabbing the lock more times. + */ + cur_tx = ep->cur_tx; + for (dirty_tx = ep->dirty_tx; cur_tx - dirty_tx > 0; dirty_tx++) { + struct sk_buff *skb; + int entry = dirty_tx % TX_RING_SIZE; + int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus); + + if (txstatus & DescOwn) + break; /* It still hasn't been Txed */ + + if (likely(txstatus & 0x0001)) { + ep->stats.collisions += (txstatus >> 8) & 15; + ep->stats.tx_packets++; + ep->stats.tx_bytes += ep->tx_skbuff[entry]->len; + } else + epic_tx_error(dev, ep, txstatus); + + /* Free the original skb. */ + skb = ep->tx_skbuff[entry]; + pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, + skb->len, PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb); + ep->tx_skbuff[entry] = 0; + } + +#ifndef final_version + if (cur_tx - dirty_tx > TX_RING_SIZE) { + printk(KERN_WARNING + "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", + dev->name, dirty_tx, cur_tx, ep->tx_full); + dirty_tx += TX_RING_SIZE; + } +#endif + ep->dirty_tx = dirty_tx; + if (ep->tx_full && cur_tx - dirty_tx < TX_QUEUE_LEN - 4) { + /* The ring is no longer full, allow new TX entries. */ + ep->tx_full = 0; + netif_wake_queue(dev); + } +} + /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs) @@ -1036,135 +1158,71 @@ struct net_device *dev = dev_instance; struct epic_private *ep = dev->priv; long ioaddr = dev->base_addr; - int status, boguscnt = max_interrupt_work; unsigned int handled = 0; + int status; - do { - status = inl(ioaddr + INTSTAT); - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(status & 0x00007fff, ioaddr + INTSTAT); - - if (debug > 4) - printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new " - "intstat=%#8.8x.\n", - dev->name, status, (int)inl(ioaddr + INTSTAT)); - - if ((status & IntrSummary) == 0) - break; - handled = 1; + status = inl(ioaddr + INTSTAT); + /* Acknowledge all of the current interrupt sources ASAP. */ + outl(status & EpicNormalEvent, ioaddr + INTSTAT); - if (status & (RxDone | RxStarted | RxEarlyWarn | RxOverflow)) - epic_rx(dev); + if (debug > 4) { + printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new " + "intstat=%#8.8x.\n", dev->name, status, + (int)inl(ioaddr + INTSTAT)); + } - if (status & (TxEmpty | TxDone)) { - unsigned int dirty_tx, cur_tx; + if ((status & IntrSummary) == 0) + goto out; - /* Note: if this lock becomes a problem we can narrow the locked - region at the cost of occasionally grabbing the lock more - times. */ - spin_lock(&ep->lock); - cur_tx = ep->cur_tx; - dirty_tx = ep->dirty_tx; - for (; cur_tx - dirty_tx > 0; dirty_tx++) { - struct sk_buff *skb; - int entry = dirty_tx % TX_RING_SIZE; - int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus); + handled = 1; - if (txstatus & DescOwn) - break; /* It still hasn't been Txed */ + if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) { + spin_lock(&ep->napi_lock); + if (netif_rx_schedule_prep(dev)) { + epic_napi_irq_off(dev, ep); + __netif_rx_schedule(dev); + } else + ep->reschedule_in_poll++; + spin_unlock(&ep->napi_lock); + } + status &= ~EpicNapiEvent; - if ( ! (txstatus & 0x0001)) { - /* There was an major error, log it. */ -#ifndef final_version - if (debug > 1) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); -#endif - ep->stats.tx_errors++; - if (txstatus & 0x1050) ep->stats.tx_aborted_errors++; - if (txstatus & 0x0008) ep->stats.tx_carrier_errors++; - if (txstatus & 0x0040) ep->stats.tx_window_errors++; - if (txstatus & 0x0010) ep->stats.tx_fifo_errors++; - } else { - ep->stats.collisions += (txstatus >> 8) & 15; - ep->stats.tx_packets++; - ep->stats.tx_bytes += ep->tx_skbuff[entry]->len; - } - - /* Free the original skb. */ - skb = ep->tx_skbuff[entry]; - pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(skb); - ep->tx_skbuff[entry] = 0; - } + /* Check uncommon events all at once. */ + if (status & (CntFull | TxUnderrun | PCIBusErr170 | PCIBusErr175)) { + if (status == EpicRemoved) + goto out; -#ifndef final_version - if (cur_tx - dirty_tx > TX_RING_SIZE) { - printk(KERN_WARNING "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dev->name, dirty_tx, cur_tx, ep->tx_full); - dirty_tx += TX_RING_SIZE; - } -#endif - ep->dirty_tx = dirty_tx; - if (ep->tx_full - && cur_tx - dirty_tx < TX_QUEUE_LEN - 4) { - /* The ring is no longer full, allow new TX entries. */ - ep->tx_full = 0; - spin_unlock(&ep->lock); - netif_wake_queue(dev); - } else - spin_unlock(&ep->lock); - } + /* Always update the error counts to avoid overhead later. */ + ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); + ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); + ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT); - /* Check uncommon events all at once. */ - if (status & (CntFull | TxUnderrun | RxOverflow | RxFull | - PCIBusErr170 | PCIBusErr175)) { - if (status == 0xffffffff) /* Chip failed or removed (CardBus). */ - break; - /* Always update the error counts to avoid overhead later. */ - ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); - ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); - ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT); - - if (status & TxUnderrun) { /* Tx FIFO underflow. */ - ep->stats.tx_fifo_errors++; - outl(ep->tx_threshold += 128, ioaddr + TxThresh); - /* Restart the transmit process. */ - outl(RestartTx, ioaddr + COMMAND); - } - if (status & RxOverflow) { /* Missed a Rx frame. */ - ep->stats.rx_errors++; - } - if (status & (RxOverflow | RxFull)) - outw(RxQueued, ioaddr + COMMAND); - if (status & PCIBusErr170) { - printk(KERN_ERR "%s: PCI Bus Error! EPIC status %4.4x.\n", - dev->name, status); - epic_pause(dev); - epic_restart(dev); - } - /* Clear all error sources. */ - outl(status & 0x7f18, ioaddr + INTSTAT); + if (status & TxUnderrun) { /* Tx FIFO underflow. */ + ep->stats.tx_fifo_errors++; + outl(ep->tx_threshold += 128, ioaddr + TxThresh); + /* Restart the transmit process. */ + outl(RestartTx, ioaddr + COMMAND); } - if (--boguscnt < 0) { - printk(KERN_ERR "%s: Too much work at interrupt, " - "IntrStatus=0x%8.8x.\n", - dev->name, status); - /* Clear all interrupt sources. */ - outl(0x0001ffff, ioaddr + INTSTAT); - break; + if (status & PCIBusErr170) { + printk(KERN_ERR "%s: PCI Bus Error! status %4.4x.\n", + dev->name, status); + epic_pause(dev); + epic_restart(dev); } - } while (1); + /* Clear all error sources. */ + outl(status & 0x7f18, ioaddr + INTSTAT); + } - if (debug > 3) - printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, status); +out: + if (debug > 3) { + printk(KERN_DEBUG "%s: exit interrupt, intr_status=%#4.4x.\n", + dev->name, status); + } return IRQ_RETVAL(handled); } -static int epic_rx(struct net_device *dev) +static int epic_rx(struct net_device *dev, int budget) { struct epic_private *ep = dev->priv; int entry = ep->cur_rx % RX_RING_SIZE; @@ -1174,6 +1232,10 @@ if (debug > 4) printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry, ep->rx_ring[entry].rxstatus); + + if (rx_work_limit > budget) + rx_work_limit = budget; + /* If we own the next entry, it's a new packet. Send it up. */ while ((ep->rx_ring[entry].rxstatus & cpu_to_le32(DescOwn)) == 0) { int status = le32_to_cpu(ep->rx_ring[entry].rxstatus); @@ -1215,13 +1277,8 @@ ep->rx_ring[entry].bufaddr, ep->rx_buf_sz, PCI_DMA_FROMDEVICE); -#if 1 /* HAS_IP_COPYSUM */ eth_copy_and_sum(skb, ep->rx_skbuff[entry]->tail, pkt_len, 0); skb_put(skb, pkt_len); -#else - memcpy(skb_put(skb, pkt_len), ep->rx_skbuff[entry]->tail, - pkt_len); -#endif pci_dma_sync_single_for_device(ep->pci_dev, ep->rx_ring[entry].bufaddr, ep->rx_buf_sz, @@ -1234,7 +1291,7 @@ ep->rx_skbuff[entry] = NULL; } skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); + netif_receive_skb(skb); dev->last_rx = jiffies; ep->stats.rx_packets++; ep->stats.rx_bytes += pkt_len; @@ -1262,6 +1319,65 @@ return work_done; } +static void epic_rx_err(struct net_device *dev, struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + int status; + + status = inl(ioaddr + INTSTAT); + + if (status == EpicRemoved) + return; + if (status & RxOverflow) /* Missed a Rx frame. */ + ep->stats.rx_errors++; + if (status & (RxOverflow | RxFull)) + outw(RxQueued, ioaddr + COMMAND); +} + +static int epic_poll(struct net_device *dev, int *budget) +{ + struct epic_private *ep = dev->priv; + int work_done, orig_budget; + long ioaddr = dev->base_addr; + + orig_budget = (*budget > dev->quota) ? dev->quota : *budget; + +rx_action: + + epic_tx(dev, ep); + + work_done = epic_rx(dev, *budget); + + epic_rx_err(dev, ep); + + *budget -= work_done; + dev->quota -= work_done; + + if (netif_running(dev) && (work_done < orig_budget)) { + unsigned long flags; + int more; + + /* A bit baroque but it avoids a (space hungry) spin_unlock */ + + spin_lock_irqsave(&ep->napi_lock, flags); + + more = ep->reschedule_in_poll; + if (!more) { + __netif_rx_complete(dev); + outl(EpicNapiEvent, ioaddr + INTSTAT); + epic_napi_irq_on(dev, ep); + } else + ep->reschedule_in_poll--; + + spin_unlock_irqrestore(&ep->napi_lock, flags); + + if (more) + goto rx_action; + } + + return (work_done >= orig_budget); +} + static int epic_close(struct net_device *dev) { long ioaddr = dev->base_addr; @@ -1276,9 +1392,13 @@ dev->name, (int)inl(ioaddr + INTSTAT)); del_timer_sync(&ep->timer); - epic_pause(dev); + + epic_disable_int(dev, ep); + free_irq(dev->irq, dev); + epic_pause(dev); + /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { skb = ep->rx_skbuff[i]; @@ -1476,6 +1596,7 @@ #endif pci_release_regions(pdev); free_netdev(dev); + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); /* pci_power_off(pdev, -1); */ } --- diff/drivers/net/fealnx.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/net/fealnx.c 2004-05-27 18:34:17.000000000 +0100 @@ -858,12 +858,17 @@ { struct netdev_private *np = dev->priv; long ioaddr = dev->base_addr; + int i; writel(0x00000001, ioaddr + BCR); /* Reset */ if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) return -EAGAIN; + for (i = 0; i < 3; i++) + writew(((unsigned short*)dev->dev_addr)[i], + ioaddr + PAR0 + i*2); + init_ring(dev); writel(np->rx_ring_dma, ioaddr + RXLBA); --- diff/drivers/net/lasi_82596.c 2004-05-19 22:11:55.000000000 +0100 +++ source/drivers/net/lasi_82596.c 2004-05-27 18:34:17.000000000 +0100 @@ -87,7 +87,6 @@ #include #include #include -#include #include #include #include --- diff/drivers/net/macsonic.c 2004-05-19 22:11:55.000000000 +0100 +++ source/drivers/net/macsonic.c 2004-05-27 18:34:17.000000000 +0100 @@ -53,7 +53,6 @@ #include #include #include -#include #define SREGS_PAD(n) u16 n; --- diff/drivers/net/natsemi.c 2004-05-19 22:11:55.000000000 +0100 +++ source/drivers/net/natsemi.c 2004-05-27 18:34:17.000000000 +0100 @@ -1798,14 +1798,9 @@ np->rx_dma[entry], buflen, PCI_DMA_FROMDEVICE); -#if HAS_IP_COPYSUM eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0); skb_put(skb, pkt_len); -#else - memcpy(skb_put(skb, pkt_len), - np->rx_skbuff[entry]->tail, pkt_len); -#endif pci_dma_sync_single_for_device(np->pci_dev, np->rx_dma[entry], buflen, --- diff/drivers/net/ne-h8300.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/net/ne-h8300.c 2004-05-27 18:34:17.000000000 +0100 @@ -260,8 +260,8 @@ bus_width &= 1 << ((ioaddr >> 21) & 7); ei_status.word16 = (bus_width == 0); /* temporary setting */ for(i = 0; i < 16 /*sizeof(SA_prom)*/; i++) { - SA_prom[i] = inb(ioaddr + NE_DATAPORT); - inb(ioaddr + NE_DATAPORT); /* dummy read */ + SA_prom[i] = inb_p(ioaddr + NE_DATAPORT); + inb_p(ioaddr + NE_DATAPORT); /* dummy read */ } start_page = NESM_START_PG; @@ -590,7 +590,7 @@ #ifdef MODULE -#define MAX_NE_CARDS 4 /* Max number of NE cards per module */ +#define MAX_NE_CARDS 1 /* Max number of NE cards per module */ static struct net_device *dev_ne[MAX_NE_CARDS]; static int io[MAX_NE_CARDS]; static int irq[MAX_NE_CARDS]; @@ -599,7 +599,7 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); -MODULE_PARM_DESC(io, "I/O base address(es),required"); +MODULE_PARM_DESC(io, "I/O base address(es)"); MODULE_PARM_DESC(irq, "IRQ number(s)"); MODULE_DESCRIPTION("H8/300 NE2000 Ethernet driver"); MODULE_LICENSE("GPL"); @@ -612,26 +612,35 @@ int init_module(void) { int this_dev, found = 0; + int err; for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { struct net_device *dev = alloc_ei_netdev(); if (!dev) break; - dev->irq = irq[this_dev]; - dev->mem_end = bad[this_dev]; - dev->base_addr = io[this_dev]; - if (do_ne_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_ne[found++] = dev; - continue; + if (io[this_dev]) { + dev->irq = irq[this_dev]; + dev->mem_end = bad[this_dev]; + dev->base_addr = io[this_dev]; + } else { + dev->base_addr = h8300_ne_base[this_dev]; + dev->irq = h8300_ne_irq[this_dev]; + } + err = init_reg_offset(dev, dev->base_addr); + if (!err) { + if (do_ne_probe(dev) == 0) { + if (register_netdev(dev) == 0) { + dev_ne[found++] = dev; + continue; + } + cleanup_card(dev); } - cleanup_card(dev); } free_netdev(dev); if (found) break; if (io[this_dev] != 0) - printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]); + printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", dev->base_addr); else printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n"); return -ENXIO; --- diff/drivers/net/r8169.c 2004-05-27 13:41:18.000000000 +0100 +++ source/drivers/net/r8169.c 2004-05-27 18:34:17.000000000 +0100 @@ -7,7 +7,7 @@ Feb 4 2002 - created initially by ShuChen . May 20 2002 - Add link status force-mode and TBI mode support. ========================================================================= - 1. The media can be forced in 5 modes. + 1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes. Command: 'insmod r8169 media = SET_MEDIA' Ex: 'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex. @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -64,6 +65,14 @@ #define dprintk(fmt, args...) do {} while (0) #endif /* RTL8169_DEBUG */ +#ifdef CONFIG_R8169_NAPI +#define rtl8169_rx_skb netif_receive_skb +#define rtl8169_rx_quota(count, quota) min(count, quota) +#else +#define rtl8169_rx_skb netif_rx +#define rtl8169_rx_quota(count, quota) count +#endif + /* media options */ #define MAX_UNITS 8 static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; @@ -90,15 +99,16 @@ #define RxPacketMaxSize 0x0800 /* Maximum size supported is 16K-1 */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ +#define R8169_NAPI_WEIGHT 64 #define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 64 /* Number of Rx descriptor registers */ +#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ #define RX_BUF_SIZE 1536 /* Rx Buffer size */ #define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) #define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) #define RTL_MIN_IO_SIZE 0x80 #define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (HZ) +#define RTL8169_PHY_TIMEOUT (10*HZ) /* write/read MMIO register */ #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) @@ -194,7 +204,7 @@ SWInt = 0x0100, TxDescUnavail = 0x80, RxFIFOOver = 0x40, - RxUnderrun = 0x20, + LinkChg = 0x20, RxOverflow = 0x10, TxErr = 0x08, TxOK = 0x04, @@ -233,6 +243,14 @@ TxInterFrameGapShift = 24, TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ + /* TBICSR p.28 */ + TBIReset = 0x80000000, + TBILoopback = 0x40000000, + TBINwEnable = 0x20000000, + TBINwRestart = 0x10000000, + TBILinkOk = 0x02000000, + TBINwComplete = 0x01000000, + /* CPlusCmd p.31 */ RxVlan = (1 << 6), RxChkSum = (1 << 5), @@ -306,10 +324,10 @@ }; struct rtl8169_private { - void *mmio_addr; /* memory map physical address */ + void *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; /* Index of PCI device */ struct net_device_stats stats; /* statistics of net device */ - spinlock_t lock; /* spin lock flag */ + spinlock_t lock; /* spin lock flag */ int chipset; int mac_version; int phy_version; @@ -317,15 +335,25 @@ u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ u32 dirty_rx; u32 dirty_tx; - struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */ - struct RxDesc *RxDescArray; /* Index of 256-alignment Rx Descriptor buffer */ + struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ + struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ dma_addr_t TxPhyAddr; dma_addr_t RxPhyAddr; struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Index of Transmit data buffer */ + struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Tx data buffers */ struct timer_list timer; - unsigned long phy_link_down_cnt; + unsigned int phy_tried_renegotiate; /* renegotiation hack */ u16 cp_cmd; + u16 intr_mask; + int phy_auto_nego_reg; + int phy_1000_ctrl_reg; + + int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); + void (*get_settings)(struct net_device *, struct ethtool_cmd *); + void (*phy_reset_enable)(void *); + unsigned int (*phy_reset_pending)(void *); + unsigned int (*link_ok)(void *); + void (*andy_s_phy_renegotiation_hack)(struct rtl8169_private *); }; MODULE_AUTHOR("Realtek"); @@ -344,9 +372,14 @@ static void rtl8169_set_rx_mode(struct net_device *dev); static void rtl8169_tx_timeout(struct net_device *dev); static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev); +#ifdef CONFIG_R8169_NAPI +static int rtl8169_poll(struct net_device *dev, int *budget); +#endif static const u16 rtl8169_intr_mask = - RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; + LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; +static const u16 rtl8169_napi_event = + RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr; static const unsigned int rtl8169_rx_config = (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); @@ -364,11 +397,9 @@ for (i = 2000; i > 0; i--) { // Check if the RTL8169 has completed writing to the specified MII register - if (!(RTL_R32(PHYAR) & 0x80000000)) { + if (!(RTL_R32(PHYAR) & 0x80000000)) break; - } else { - udelay(100); - } + udelay(100); } } @@ -390,18 +421,277 @@ return value; } +static unsigned int rtl8169_tbi_reset_pending(void *ioaddr) +{ + return RTL_R32(TBICSR) & TBIReset; +} + +static unsigned int rtl8169_xmii_reset_pending(void *ioaddr) +{ + return mdio_read(ioaddr, 0) & 0x8000; +} + +static unsigned int rtl8169_tbi_link_ok(void *ioaddr) +{ + return RTL_R32(TBICSR) & TBILinkOk; +} + +static unsigned int rtl8169_xmii_link_ok(void *ioaddr) +{ + return RTL_R8(PHYstatus) & LinkStatus; +} + +static void rtl8169_tbi_reset_enable(void *ioaddr) +{ + RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); +} + +static void rtl8169_xmii_reset_enable(void *ioaddr) +{ + unsigned int val; + + val = (mdio_read(ioaddr, PHY_CTRL_REG) | 0x8000) & 0xffff; + mdio_write(ioaddr, PHY_CTRL_REG, val); +} + +static void rtl8169_xmii_renegotiation_hack(struct rtl8169_private *tp) +{ + void *ioaddr = tp->mmio_addr; + + if (!tp->phy_tried_renegotiate && !(RTL_R8(PHYstatus) & _1000bpsF)) { + mdio_write(ioaddr, PHY_CTRL_REG, + BMCR_ANRESTART | BMCR_ANENABLE); + tp->phy_tried_renegotiate++; + } +} + +static void rtl8169_check_link_status(struct net_device *dev, + struct rtl8169_private *tp, void *ioaddr) +{ + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + if (tp->link_ok(ioaddr)) { + netif_carrier_on(dev); + printk(KERN_INFO PFX "%s: link up\n", dev->name); + } else { + netif_carrier_off(dev); + mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); + } + spin_unlock_irqrestore(&tp->lock, flags); +} + +static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex) +{ + struct { + u16 speed; + u8 duplex; + u8 autoneg; + u8 media; + } link_settings[] = { + { SPEED_10, DUPLEX_HALF, AUTONEG_DISABLE, _10_Half }, + { SPEED_10, DUPLEX_FULL, AUTONEG_DISABLE, _10_Full }, + { SPEED_100, DUPLEX_HALF, AUTONEG_DISABLE, _100_Half }, + { SPEED_100, DUPLEX_FULL, AUTONEG_DISABLE, _100_Full }, + { SPEED_1000, DUPLEX_FULL, AUTONEG_DISABLE, _1000_Full }, + /* Make TBI happy */ + { SPEED_1000, DUPLEX_FULL, AUTONEG_ENABLE, 0xff } + }, *p; + unsigned char option; + + option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff; + + if ((option != 0xff) && !idx) + printk(KERN_WARNING PFX "media option is deprecated.\n"); + + for (p = link_settings; p->media != 0xff; p++) { + if (p->media == option) + break; + } + *autoneg = p->autoneg; + *speed = p->speed; + *duplex = p->duplex; +} + static void rtl8169_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); strcpy(info->driver, RTL8169_DRIVER_NAME); strcpy(info->version, RTL8169_VERSION ); strcpy(info->bus_info, pci_name(tp->pci_dev)); } +static int rtl8169_set_speed_tbi(struct net_device *dev, + u8 autoneg, u16 speed, u8 duplex) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + int ret = 0; + u32 reg; + + reg = RTL_R32(TBICSR); + if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && + (duplex == DUPLEX_FULL)) { + RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); + } else if (autoneg == AUTONEG_ENABLE) + RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); + else { + printk(KERN_WARNING PFX + "%s: incorrect speed setting refused in TBI mode\n", + dev->name); + ret = -EOPNOTSUPP; + } + + return ret; +} + +static int rtl8169_set_speed_xmii(struct net_device *dev, + u8 autoneg, u16 speed, u8 duplex) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + int auto_nego, giga_ctrl; + + auto_nego = mdio_read(ioaddr, PHY_AUTO_NEGO_REG); + auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_10_Full | + PHY_Cap_100_Half | PHY_Cap_100_Full); + giga_ctrl = mdio_read(ioaddr, PHY_1000_CTRL_REG); + giga_ctrl &= ~(PHY_Cap_1000_Full | PHY_Cap_Null); + + if (autoneg == AUTONEG_ENABLE) { + auto_nego |= (PHY_Cap_10_Half | PHY_Cap_10_Full | + PHY_Cap_100_Half | PHY_Cap_100_Full); + giga_ctrl |= PHY_Cap_1000_Full; + } else { + if (speed == SPEED_10) + auto_nego |= PHY_Cap_10_Half | PHY_Cap_10_Full; + else if (speed == SPEED_100) + auto_nego |= PHY_Cap_100_Half | PHY_Cap_100_Full; + else if (speed == SPEED_1000) + giga_ctrl |= PHY_Cap_1000_Full; + + if (duplex == DUPLEX_HALF) + auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full); + } + + tp->phy_auto_nego_reg = auto_nego; + tp->phy_1000_ctrl_reg = giga_ctrl; + + mdio_write(ioaddr, PHY_AUTO_NEGO_REG, auto_nego); + mdio_write(ioaddr, PHY_1000_CTRL_REG, giga_ctrl); + mdio_write(ioaddr, PHY_CTRL_REG, PHY_Enable_Auto_Nego | + PHY_Restart_Auto_Nego); + return 0; +} + +static int rtl8169_set_speed(struct net_device *dev, + u8 autoneg, u16 speed, u8 duplex) +{ + struct rtl8169_private *tp = netdev_priv(dev); + int ret; + + ret = tp->set_speed(dev, autoneg, speed, duplex); + + if (netif_running(dev) && (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full)) + mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); + + return ret; +} + +static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8169_private *tp = netdev_priv(dev); + unsigned long flags; + int ret; + + spin_lock_irqsave(&tp->lock, flags); + ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex); + spin_unlock_irqrestore(&tp->lock, flags); + + return ret; +} + +static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + u32 status; + + cmd->supported = + SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; + cmd->port = PORT_FIBRE; + cmd->transceiver = XCVR_INTERNAL; + + status = RTL_R32(TBICSR); + cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; + cmd->autoneg = !!(status & TBINwEnable); + + cmd->speed = SPEED_1000; + cmd->duplex = DUPLEX_FULL; /* Always set */ +} + +static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + u8 status; + + cmd->supported = SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP; + + cmd->autoneg = 1; + cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg; + + if (tp->phy_auto_nego_reg & PHY_Cap_10_Half) + cmd->advertising |= ADVERTISED_10baseT_Half; + if (tp->phy_auto_nego_reg & PHY_Cap_10_Full) + cmd->advertising |= ADVERTISED_10baseT_Full; + if (tp->phy_auto_nego_reg & PHY_Cap_100_Half) + cmd->advertising |= ADVERTISED_100baseT_Half; + if (tp->phy_auto_nego_reg & PHY_Cap_100_Full) + cmd->advertising |= ADVERTISED_100baseT_Full; + if (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full) + cmd->advertising |= ADVERTISED_1000baseT_Full; + + status = RTL_R8(PHYstatus); + + if (status & _1000bpsF) + cmd->speed = SPEED_1000; + else if (status & _100bps) + cmd->speed = SPEED_100; + else if (status & _10bps) + cmd->speed = SPEED_10; + + cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ? + DUPLEX_FULL : DUPLEX_HALF; +} + +static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct rtl8169_private *tp = netdev_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&tp->lock, flags); + + tp->get_settings(dev, cmd); + + spin_unlock_irqrestore(&tp->lock, flags); + return 0; +} + + static struct ethtool_ops rtl8169_ethtool_ops = { .get_drvinfo = rtl8169_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_settings = rtl8169_get_settings, + .set_settings = rtl8169_set_settings, }; static void rtl8169_write_gmii_reg_bit(void *ioaddr, int reg, int bitnum, @@ -500,7 +790,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; struct { u16 regs[5]; /* Beware of bit-sign propagation */ @@ -566,61 +856,51 @@ mdio_write(ioaddr, 31, 0x0000); //w 31 2 0 0 } -static void rtl8169_hw_phy_reset(struct net_device *dev) -{ - struct rtl8169_private *tp = dev->priv; - void *ioaddr = tp->mmio_addr; - int i, val; - - printk(KERN_WARNING PFX "%s: Reset RTL8169s PHY\n", dev->name); - - val = (mdio_read(ioaddr, 0) | 0x8000) & 0xffff; - mdio_write(ioaddr, 0, val); - - for (i = 50; i >= 0; i--) { - if (!(mdio_read(ioaddr, 0) & 0x8000)) - break; - udelay(100); /* Gross */ - } - - if (i < 0) { - printk(KERN_WARNING PFX "%s: no PHY Reset ack. Giving up.\n", - dev->name); - } -} - static void rtl8169_phy_timer(unsigned long __opaque) { struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; void *ioaddr = tp->mmio_addr; + unsigned long timeout = RTL8169_PHY_TIMEOUT; assert(tp->mac_version > RTL_GIGA_MAC_VER_B); assert(tp->phy_version < RTL_GIGA_PHY_VER_G); - if (RTL_R8(PHYstatus) & LinkStatus) - tp->phy_link_down_cnt = 0; - else { - tp->phy_link_down_cnt++; - if (tp->phy_link_down_cnt >= 12) { - int reg; - - // If link on 1000, perform phy reset. - reg = mdio_read(ioaddr, PHY_1000_CTRL_REG); - if (reg & PHY_Cap_1000_Full) - rtl8169_hw_phy_reset(dev); + if (!(tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full)) + return; - tp->phy_link_down_cnt = 0; - } + spin_lock_irq(&tp->lock); + + if (tp->phy_reset_pending(ioaddr)) { + /* + * A busy loop could burn quite a few cycles on nowadays CPU. + * Let's delay the execution of the timer for a few ticks. + */ + timeout = HZ/10; + goto out_mod_timer; } - mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); + if (tp->link_ok(ioaddr)) { + /* Nothing personal here. Simple documentation purpose :o) */ + if (tp->andy_s_phy_renegotiation_hack) + tp->andy_s_phy_renegotiation_hack(tp); + goto out_unlock; + } + + printk(KERN_WARNING PFX "%s: PHY reset until link up\n", dev->name); + + tp->phy_reset_enable(ioaddr); + +out_mod_timer: + mod_timer(timer, jiffies + timeout); +out_unlock: + spin_unlock_irq(&tp->lock); } static inline void rtl8169_delete_timer(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) || @@ -628,21 +908,17 @@ return; del_timer_sync(timer); - - tp->phy_link_down_cnt = 0; } static inline void rtl8169_request_timer(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) || (tp->phy_version >= RTL_GIGA_PHY_VER_G)) return; - tp->phy_link_down_cnt = 0; - init_timer(timer); timer->expires = jiffies + RTL8169_PHY_TIMEOUT; timer->data = (unsigned long)(dev); @@ -681,7 +957,7 @@ // enable device (incl. PCI PM wakeup and hotplug setup) rc = pci_enable_device(pdev); if (rc) { - printk(KERN_ERR PFX "%s: unable to enable device\n", pdev->slot_name); + printk(KERN_ERR PFX "%s: enable failure\n", pdev->slot_name); goto err_out; } @@ -693,7 +969,8 @@ pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; } else { - printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n"); + printk(KERN_ERR PFX + "Cannot find PowerManagement capability, aborting.\n"); goto err_out_free_res; } @@ -718,7 +995,8 @@ rc = pci_request_regions(pdev, dev->name); if (rc) { - printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name); + printk(KERN_ERR PFX "%s: could not request regions.\n", + pdev->slot_name); goto err_out_disable; } @@ -800,8 +1078,9 @@ void *ioaddr = NULL; static int board_idx = -1; static int printed_version = 0; + u8 autoneg, duplex; + u16 speed; int i, rc; - int option = -1, Cap10_100 = 0, Cap1000 = 0; assert(pdev != NULL); assert(ent != NULL); @@ -822,6 +1101,25 @@ assert(dev != NULL); assert(tp != NULL); + if (RTL_R8(PHYstatus) & TBI_Enable) { + tp->set_speed = rtl8169_set_speed_tbi; + tp->get_settings = rtl8169_gset_tbi; + tp->phy_reset_enable = rtl8169_tbi_reset_enable; + tp->phy_reset_pending = rtl8169_tbi_reset_pending; + tp->link_ok = rtl8169_tbi_link_ok; + + tp->phy_1000_ctrl_reg = PHY_Cap_1000_Full; /* Implied by TBI */ + } else { + tp->set_speed = rtl8169_set_speed_xmii; + tp->get_settings = rtl8169_gset_xmii; + tp->phy_reset_enable = rtl8169_xmii_reset_enable; + tp->phy_reset_pending = rtl8169_xmii_reset_pending; + tp->link_ok = rtl8169_xmii_link_ok; + + tp->andy_s_phy_renegotiation_hack = + rtl8169_xmii_renegotiation_hack; + } + // Get MAC address. FIXME: read EEPROM for (i = 0; i < MAC_ADDR_LEN; i++) dev->dev_addr[i] = RTL_R8(MAC0 + i); @@ -836,9 +1134,12 @@ dev->watchdog_timeo = RTL8169_TX_TIMEOUT; dev->irq = pdev->irq; dev->base_addr = (unsigned long) ioaddr; -// dev->do_ioctl = mii_ioctl; - - tp = dev->priv; // private data // +#ifdef CONFIG_R8169_NAPI + dev->poll = rtl8169_poll; + dev->weight = R8169_NAPI_WEIGHT; + printk(KERN_INFO PFX "NAPI enabled\n"); +#endif + tp->intr_mask = 0xffff; tp->pci_dev = pdev; tp->mmio_addr = ioaddr; @@ -885,95 +1186,12 @@ mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0 } - // if TBI is not endbled - if (!(RTL_R8(PHYstatus) & TBI_Enable)) { - int val = mdio_read(ioaddr, PHY_AUTO_NEGO_REG); - - option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx]; - // Force RTL8169 in 10/100/1000 Full/Half mode. - if (option > 0) { - printk(KERN_INFO "%s: Force-mode Enabled.\n", - dev->name); - Cap10_100 = 0, Cap1000 = 0; - switch (option) { - case _10_Half: - Cap10_100 = PHY_Cap_10_Half_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _10_Full: - Cap10_100 = PHY_Cap_10_Full_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _100_Half: - Cap10_100 = PHY_Cap_100_Half_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _100_Full: - Cap10_100 = PHY_Cap_100_Full_Or_Less; - Cap1000 = PHY_Cap_Null; - break; - case _1000_Full: - Cap10_100 = PHY_Cap_100_Full_Or_Less; - Cap1000 = PHY_Cap_1000_Full; - break; - default: - break; - } - mdio_write(ioaddr, PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0x1F)); //leave PHY_AUTO_NEGO_REG bit4:0 unchanged - mdio_write(ioaddr, PHY_1000_CTRL_REG, Cap1000); - } else { - printk(KERN_INFO "%s: Auto-negotiation Enabled.\n", - dev->name); + rtl8169_link_option(board_idx, &autoneg, &speed, &duplex); - // enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged - mdio_write(ioaddr, PHY_AUTO_NEGO_REG, - PHY_Cap_100_Full_Or_Less | (val & 0x1f)); - - // enable 1000 Full Mode - mdio_write(ioaddr, PHY_1000_CTRL_REG, - PHY_Cap_1000_Full); + rtl8169_set_speed(dev, autoneg, speed, duplex); - } - - // Enable auto-negotiation and restart auto-nigotiation - mdio_write(ioaddr, PHY_CTRL_REG, - PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego); - udelay(100); - - // wait for auto-negotiation process - for (i = 10000; i > 0; i--) { - //check if auto-negotiation complete - if (mdio_read(ioaddr, PHY_STAT_REG) & - PHY_Auto_Neco_Comp) { - udelay(100); - option = RTL_R8(PHYstatus); - if (option & _1000bpsF) { - printk(KERN_INFO - "%s: 1000Mbps Full-duplex operation.\n", - dev->name); - } else { - printk(KERN_INFO - "%s: %sMbps %s-duplex operation.\n", - dev->name, - (option & _100bps) ? "100" : - "10", - (option & FullDup) ? "Full" : - "Half"); - } - break; - } else { - udelay(100); - } - } // end for-loop to wait for auto-negotiation process - - } else { - udelay(100); - printk(KERN_INFO - "%s: 1000Mbps Full-duplex operation, TBI Link %s!\n", - dev->name, - (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed"); - - } + if (RTL_R8(PHYstatus) & TBI_Enable) + printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); return 0; } @@ -982,7 +1200,7 @@ rtl8169_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); assert(dev != NULL); assert(tp != NULL); @@ -1001,7 +1219,7 @@ static int rtl8169_suspend(struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; @@ -1042,7 +1260,7 @@ static int rtl8169_open(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct pci_dev *pdev = tp->pci_dev; int retval; @@ -1074,6 +1292,8 @@ rtl8169_hw_start(dev); rtl8169_request_timer(dev); + + rtl8169_check_link_status(dev, tp, tp->mmio_addr); out: return retval; @@ -1091,7 +1311,7 @@ static void rtl8169_hw_start(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; u32 i; @@ -1102,8 +1322,7 @@ for (i = 1000; i > 0; i--) { if ((RTL_R8(ChipCmd) & CmdReset) == 0) break; - else - udelay(10); + udelay(10); } RTL_W8(Cfg9346, Cfg9346_Unlock); @@ -1114,8 +1333,8 @@ RTL_W16(RxMaxSize, RxPacketMaxSize); // Set Rx Config register - i = rtl8169_rx_config | (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset]. - RxConfigMask); + i = rtl8169_rx_config | + (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); RTL_W32(RxConfig, i); /* Set DMA burst size and Interframe Gap Time */ @@ -1126,7 +1345,8 @@ RTL_W16(CPlusCmd, tp->cp_cmd); if (tp->mac_version == RTL_GIGA_MAC_VER_D) { - dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14 MUST be 1\n"); + dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0. " + "Bit-3 and bit-14 MUST be 1\n"); tp->cp_cmd |= (1 << 14) | PCIMulRW; RTL_W16(CPlusCmd, tp->cp_cmd); } @@ -1151,7 +1371,6 @@ RTL_W16(IntrMask, rtl8169_intr_mask); netif_start_queue(dev); - } static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) @@ -1248,7 +1467,7 @@ static int rtl8169_init_ring(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); tp->cur_rx = tp->dirty_rx = 0; tp->cur_tx = tp->dirty_tx = 0; @@ -1302,10 +1521,11 @@ static void rtl8169_tx_timeout(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; u8 tmp8; + printk(KERN_INFO "%s: TX Timeout\n", dev->name); /* disable Tx, if not already */ tmp8 = RTL_R8(ChipCmd); if (tmp8 & CmdTxEnb) @@ -1328,9 +1548,9 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; - int entry = tp->cur_tx % NUM_TX_DESC; + unsigned int entry = tp->cur_tx % NUM_TX_DESC; u32 len = skb->len; if (unlikely(skb->len < ETH_ZLEN)) { @@ -1382,7 +1602,7 @@ rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp, void *ioaddr) { - unsigned long dirty_tx, tx_left; + unsigned int dirty_tx, tx_left; assert(dev != NULL); assert(tp != NULL); @@ -1392,7 +1612,7 @@ tx_left = tp->cur_tx - dirty_tx; while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; + unsigned int entry = dirty_tx % NUM_TX_DESC; struct sk_buff *skb = tp->Tx_skbuff[entry]; u32 status; @@ -1442,11 +1662,11 @@ return ret; } -static void +static int rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, void *ioaddr) { - unsigned long cur_rx, rx_left; + unsigned int cur_rx, rx_left, count; int delta; assert(dev != NULL); @@ -1455,9 +1675,10 @@ cur_rx = tp->cur_rx; rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; + rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota); while (rx_left > 0) { - int entry = cur_rx % NUM_RX_DESC; + unsigned int entry = cur_rx % NUM_RX_DESC; u32 status; rmb(); @@ -1494,7 +1715,7 @@ skb_put(skb, pkt_size); skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); + rtl8169_rx_skb(skb); dev->last_rx = jiffies; tp->stats.rx_bytes += pkt_size; @@ -1505,13 +1726,15 @@ rx_left--; } + count = cur_rx - tp->cur_rx; tp->cur_rx = cur_rx; delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (delta > 0) - tp->dirty_rx += delta; - else if (delta < 0) + if (delta < 0) { printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); + delta = 0; + } + tp->dirty_rx += delta; /* * FIXME: until there is periodic timer to try and refill the ring, @@ -1522,6 +1745,8 @@ */ if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); + + return count; } /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ @@ -1529,7 +1754,7 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); int boguscnt = max_interrupt_work; void *ioaddr = tp->mmio_addr; int status = 0; @@ -1543,18 +1768,31 @@ break; handled = 1; -/* - if (status & RxUnderrun) - link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; -*/ + + status &= tp->intr_mask; RTL_W16(IntrStatus, (status & RxFIFOOver) ? (status | RxOverflow) : status); if (!(status & rtl8169_intr_mask)) break; + if (status & LinkChg) + rtl8169_check_link_status(dev, tp, ioaddr); + +#ifdef CONFIG_R8169_NAPI + RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event); + tp->intr_mask = ~rtl8169_napi_event; + + if (likely(netif_rx_schedule_prep(dev))) + __netif_rx_schedule(dev); + else { + printk(KERN_INFO "%s: interrupt %x taken in poll\n", + dev->name, status); + } + break; +#else // Rx interrupt - if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) { + if (status & (RxOK | RxOverflow | RxFIFOOver)) { rtl8169_rx_interrupt(dev, tp, ioaddr); } // Tx interrupt @@ -1563,6 +1801,7 @@ rtl8169_tx_interrupt(dev, tp, ioaddr); spin_unlock(&tp->lock); } +#endif boguscnt--; } while (boguscnt > 0); @@ -1576,10 +1815,40 @@ return IRQ_RETVAL(handled); } +#ifdef CONFIG_R8169_NAPI +static int rtl8169_poll(struct net_device *dev, int *budget) +{ + unsigned int work_done, work_to_do = min(*budget, dev->quota); + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + + work_done = rtl8169_rx_interrupt(dev, tp, ioaddr); + rtl8169_tx_interrupt(dev, tp, ioaddr); + + *budget -= work_done; + dev->quota -= work_done; + + if ((work_done < work_to_do) || !netif_running(dev)) { + netif_rx_complete(dev); + tp->intr_mask = 0xffff; + /* + * 20040426: the barrier is not strictly required but the + * behavior of the irq handler could be less predictable + * without it. Btw, the lack of flush for the posted pci + * write is safe - FR + */ + smp_wmb(); + RTL_W16(IntrMask, rtl8169_intr_mask); + } + + return (work_done >= work_to_do); +} +#endif + static int rtl8169_close(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct pci_dev *pdev = tp->pci_dev; void *ioaddr = tp->mmio_addr; @@ -1621,7 +1890,7 @@ static void rtl8169_set_rx_mode(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; u32 mc_filter[2]; /* Multicast hash filter */ @@ -1655,10 +1924,8 @@ spin_lock_irqsave(&tp->lock, flags); - tmp = - rtl8169_rx_config | rx_mode | (RTL_R32(RxConfig) & - rtl_chip_info[tp->chipset]. - RxConfigMask); + tmp = rtl8169_rx_config | rx_mode | + (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); RTL_W32(RxConfig, tmp); RTL_W32(MAR0 + 0, mc_filter[0]); @@ -1675,7 +1942,7 @@ */ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; --- diff/drivers/net/s2io.h 2004-05-19 22:11:55.000000000 +0100 +++ source/drivers/net/s2io.h 2004-05-27 18:34:17.000000000 +0100 @@ -748,27 +748,6 @@ #define SMALL_RXD_CNT 40 * (MAX_RXDS_PER_BLOCK+1) #define LARGE_RXD_CNT 100 * (MAX_RXDS_PER_BLOCK+1) -/* OS related system calls */ -#ifndef readq -static inline u64 readq(void *addr) -{ - u64 ret = 0; - ret = readl(addr + 4); - ret <<= 32; - ret |= readl(addr); - - return ret; -} -#endif - -#ifndef writeq -static inline void writeq(u64 val, void *addr) -{ - writel((u32) (val), addr); - writel((u32) (val >> 32), (addr + 4)); -} -#endif - /* Interrupt related values of Xena */ #define ENABLE_INTRS 1 --- diff/drivers/net/sis900.c 2004-05-19 22:11:56.000000000 +0100 +++ source/drivers/net/sis900.c 2004-05-27 18:34:17.000000000 +0100 @@ -18,6 +18,7 @@ preliminary Rev. 1.0 Jan. 18, 1998 http://www.sis.com.tw/support/databook.htm + Jan. 7 2004 Grischa Jacobs - Skip mii's with MII_STAT_FAULT set Rev 1.08.07 Nov. 2 2003 Daniele Venzano add suspend/resume support Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support Rev 1.08.05 Jun. 6 2002 Mufasa Yang bug fix for read_eeprom & Tx descriptor over-boundary @@ -116,6 +117,7 @@ #define HOME 0x0001 #define LAN 0x0002 #define MIX 0x0003 +#define UNKNOWN 0x0 } mii_chip_table[] = { { "SiS 900 Internal MII PHY", 0x001d, 0x8000, LAN }, { "SiS 7014 Physical Layer Solution", 0x0016, 0xf830, LAN }, @@ -260,9 +262,13 @@ u8 reg; int i; - if ((isa_bridge = pci_find_device(0x1039, 0x0008, isa_bridge)) == NULL) { - printk("%s: Can not find ISA bridge\n", net_dev->name); - return 0; + isa_bridge = pci_find_device(PCI_VENDOR_ID_SI, 0x0008, isa_bridge); + if (!isa_bridge) { + isa_bridge = pci_find_device(PCI_VENDOR_ID_SI, 0x0018, isa_bridge); + if (!isa_bridge) { + printk("%s: Can not find ISA bridge\n", net_dev->name); + return 0; + } } pci_read_config_byte(isa_bridge, 0x48, ®); pci_write_config_byte(isa_bridge, 0x48, reg | 0x40); @@ -541,6 +547,10 @@ /* the mii is not accessible, try next one */ continue; + if (mii_status & MII_STAT_FAULT) + /* ignore mii with the fault bit set */ + continue; + if ((mii_phy = kmalloc(sizeof(struct mii_phy), GFP_KERNEL)) == NULL) { printk(KERN_INFO "Cannot allocate mem for struct mii_phy\n"); mii_phy = sis_priv->first_mii; @@ -573,9 +583,11 @@ break; } - if( !mii_chip_table[i].phy_id1 ) + if( !mii_chip_table[i].phy_id1 ) { printk(KERN_INFO "%s: Unknown PHY transceiver found at address %d.\n", - net_dev->name, phy_addr); + net_dev->name, phy_addr); + mii_phy->phy_types = UNKNOWN; + } } if (sis_priv->mii == NULL) { @@ -640,15 +652,15 @@ static u16 sis900_default_phy(struct net_device * net_dev) { struct sis900_private * sis_priv = net_dev->priv; - struct mii_phy *phy = NULL, *phy_home = NULL, *default_phy = NULL; + struct mii_phy *phy = NULL, *phy_home = NULL, *default_phy = NULL, *phy_lan = NULL; u16 status; for( phy=sis_priv->first_mii; phy; phy=phy->next ){ status = mdio_read(net_dev, phy->phy_addr, MII_STATUS); status = mdio_read(net_dev, phy->phy_addr, MII_STATUS); - /* Link ON & Not select deafalut PHY */ - if ( (status & MII_STAT_LINK) && !(default_phy) ) + /* Link ON & Not select default PHY & not ghost PHY */ + if ( (status & MII_STAT_LINK) && !default_phy && (phy->phy_types != UNKNOWN) ) default_phy = phy; else{ status = mdio_read(net_dev, phy->phy_addr, MII_CONTROL); @@ -656,12 +668,16 @@ status | MII_CNTL_AUTO | MII_CNTL_ISOLATE); if( phy->phy_types == HOME ) phy_home = phy; + else if (phy->phy_types == LAN) + phy_lan = phy; } } - if( (!default_phy) && phy_home ) + if( !default_phy && phy_home ) default_phy = phy_home; - else if(!default_phy) + else if( !default_phy && phy_lan ) + default_phy = phy_lan; + else if ( !default_phy ) default_phy = sis_priv->first_mii; if( sis_priv->mii != default_phy ){ @@ -2195,6 +2211,7 @@ return 0; netif_stop_queue(net_dev); + netif_device_detach(net_dev); /* Stop the chip's Tx and Rx Status Machine */ outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr); --- diff/drivers/net/sis900.h 2004-05-19 22:11:56.000000000 +0100 +++ source/drivers/net/sis900.h 2004-05-27 18:34:17.000000000 +0100 @@ -77,7 +77,7 @@ IE = 0x00000001 }; -/* maximum dma burst fro transmission and receive*/ +/* maximum dma burst for transmission and receive */ #define MAX_DMA_RANGE 7 /* actually 0 means MAXIMUM !! */ #define TxMXDMA_shift 20 #define RxMXDMA_shift 20 @@ -86,7 +86,7 @@ DMA_BURST_512 = 0, DMA_BURST_64 = 5 }; -/* transmit FIFO threshholds */ +/* transmit FIFO thresholds */ #define TX_FILL_THRESH 16 /* 1/4 FIFO size */ #define TxFILLT_shift 8 #define TxDRNT_shift 0 @@ -140,7 +140,7 @@ EEREQ = 0x00000400, EEDONE = 0x00000200, EEGNT = 0x00000100 }; -/* Manamgement Data I/O (mdio) frame */ +/* Management Data I/O (mdio) frame */ #define MIIread 0x6000 #define MIIwrite 0x5002 #define MIIpmdShift 7 --- diff/drivers/net/sk98lin/skvpd.c 2004-05-19 22:11:58.000000000 +0100 +++ source/drivers/net/sk98lin/skvpd.c 2004-05-27 18:34:17.000000000 +0100 @@ -468,6 +468,17 @@ pAC->vpd.vpd_size = vpd_size; + /* Asus K8V Se Deluxe bugfix. Correct VPD content */ + /* MBo April 2004 */ + if (((unsigned char)pAC->vpd.vpd_buf[0x3f] == 0x38) && + ((unsigned char)pAC->vpd.vpd_buf[0x40] == 0x3c) && + ((unsigned char)pAC->vpd.vpd_buf[0x41] == 0x45)) { + printk("sk98lin: Asus mainboard with buggy VPD? " + "Correcting data.\n"); + pAC->vpd.vpd_buf[0x40] = 0x38; + } + + /* find the end tag of the RO area */ if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) { SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, --- diff/drivers/net/sun3lance.c 2004-05-19 22:11:56.000000000 +0100 +++ source/drivers/net/sun3lance.c 2004-05-27 18:34:17.000000000 +0100 @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include --- diff/drivers/net/tg3.c 2004-05-27 13:41:19.000000000 +0100 +++ source/drivers/net/tg3.c 2004-05-27 18:34:17.000000000 +0100 @@ -56,8 +56,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.4" -#define DRV_MODULE_RELDATE "May 14, 2004" +#define DRV_MODULE_VERSION "3.5" +#define DRV_MODULE_RELDATE "May 25, 2004" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -128,7 +128,8 @@ /* minimum number of free TX descriptors required to wake up TX process */ #define TG3_TX_WAKEUP_THRESH (TG3_TX_RING_SIZE / 4) -#define TG3_NUM_STATS 25 /* number of ETHTOOL_GSTATS u64's */ +/* number of ETHTOOL_GSTATS u64's */ +#define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64)) static char version[] __devinitdata = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; @@ -216,10 +217,13 @@ struct { char string[ETH_GSTRING_LEN]; } ethtool_stats_keys[TG3_NUM_STATS] = { + { "rx_octets" }, { "rx_fragments" }, { "rx_ucast_packets" }, + { "rx_mcast_packets" }, { "rx_bcast_packets" }, { "rx_fcs_errors" }, + { "rx_align_errors" }, { "rx_xon_pause_rcvd" }, { "rx_xoff_pause_rcvd" }, { "rx_mac_ctrl_rcvd" }, @@ -229,6 +233,19 @@ { "rx_undersize_packets" }, { "rx_in_length_errors" }, { "rx_out_length_errors" }, + { "rx_64_or_less_octet_packets" }, + { "rx_65_to_127_octet_packets" }, + { "rx_128_to_255_octet_packets" }, + { "rx_256_to_511_octet_packets" }, + { "rx_512_to_1023_octet_packets" }, + { "rx_1024_to_1522_octet_packets" }, + { "rx_1523_to_2047_octet_packets" }, + { "rx_2048_to_4095_octet_packets" }, + { "rx_4096_to_8191_octet_packets" }, + { "rx_8192_to_9022_octet_packets" }, + + { "tx_octets" }, + { "tx_collisions" }, { "tx_xon_sent" }, { "tx_xoff_sent" }, @@ -239,9 +256,43 @@ { "tx_deferred" }, { "tx_excessive_collisions" }, { "tx_late_collisions" }, + { "tx_collide_2times" }, + { "tx_collide_3times" }, + { "tx_collide_4times" }, + { "tx_collide_5times" }, + { "tx_collide_6times" }, + { "tx_collide_7times" }, + { "tx_collide_8times" }, + { "tx_collide_9times" }, + { "tx_collide_10times" }, + { "tx_collide_11times" }, + { "tx_collide_12times" }, + { "tx_collide_13times" }, + { "tx_collide_14times" }, + { "tx_collide_15times" }, { "tx_ucast_packets" }, { "tx_mcast_packets" }, - { "tx_bcast_packets" } + { "tx_bcast_packets" }, + { "tx_carrier_sense_errors" }, + { "tx_discards" }, + { "tx_errors" }, + + { "dma_writeq_full" }, + { "dma_write_prioq_full" }, + { "rxbds_empty" }, + { "rx_discards" }, + { "rx_errors" }, + { "rx_threshold_hit" }, + + { "dma_readq_full" }, + { "dma_read_prioq_full" }, + { "tx_comp_queue_full" }, + + { "ring_set_send_prod_index" }, + { "ring_status_update" }, + { "nic_irqs" }, + { "nic_avoided_irqs" }, + { "nic_tx_threshold_hit" } }; static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) @@ -1053,6 +1104,8 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv) { u32 new_tg3_flags = 0; + u32 old_rx_mode = tp->rx_mode; + u32 old_tx_mode = tp->tx_mode; if (local_adv & ADVERTISE_PAUSE_CAP) { if (local_adv & ADVERTISE_PAUSE_ASYM) { @@ -1083,10 +1136,18 @@ else tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE; + if (old_rx_mode != tp->rx_mode) { + tw32_f(MAC_RX_MODE, tp->rx_mode); + } + if (new_tg3_flags & TG3_FLAG_TX_PAUSE) tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE; else tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE; + + if (old_tx_mode != tp->tx_mode) { + tw32_f(MAC_TX_MODE, tp->tx_mode); + } } static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex) @@ -2472,7 +2533,7 @@ static int tg3_poll(struct net_device *netdev, int *budget) { - struct tg3 *tp = netdev->priv; + struct tg3 *tp = netdev_priv(netdev); struct tg3_hw_status *sblk = tp->hw_status; unsigned long flags; int done; @@ -2554,7 +2615,7 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); struct tg3_hw_status *sblk = tp->hw_status; unsigned long flags; unsigned int handled = 1; @@ -2634,7 +2695,7 @@ static void tg3_tx_timeout(struct net_device *dev) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); printk(KERN_ERR PFX "%s: transmit timed out, resetting\n", dev->name); @@ -2750,7 +2811,7 @@ static int tg3_start_xmit_4gbug(struct sk_buff *skb, struct net_device *dev) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); dma_addr_t mapping; unsigned int i; u32 len, entry, base_flags, mss; @@ -2954,7 +3015,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); dma_addr_t mapping; u32 len, entry, base_flags, mss; unsigned long flags; @@ -3124,7 +3185,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp)) return -EINVAL; @@ -4741,7 +4802,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); struct sockaddr *addr = p; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); @@ -5533,7 +5594,7 @@ static int tg3_open(struct net_device *dev) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); int err; spin_lock_irq(&tp->lock); @@ -5836,7 +5897,7 @@ static int tg3_close(struct net_device *dev) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); netif_stop_queue(dev); @@ -5921,10 +5982,13 @@ if (!hw_stats) return old_estats; + ESTAT_ADD(rx_octets); ESTAT_ADD(rx_fragments); ESTAT_ADD(rx_ucast_packets); + ESTAT_ADD(rx_mcast_packets); ESTAT_ADD(rx_bcast_packets); ESTAT_ADD(rx_fcs_errors); + ESTAT_ADD(rx_align_errors); ESTAT_ADD(rx_xon_pause_rcvd); ESTAT_ADD(rx_xoff_pause_rcvd); ESTAT_ADD(rx_mac_ctrl_rcvd); @@ -5934,7 +5998,19 @@ ESTAT_ADD(rx_undersize_packets); ESTAT_ADD(rx_in_length_errors); ESTAT_ADD(rx_out_length_errors); + ESTAT_ADD(rx_64_or_less_octet_packets); + ESTAT_ADD(rx_65_to_127_octet_packets); + ESTAT_ADD(rx_128_to_255_octet_packets); + ESTAT_ADD(rx_256_to_511_octet_packets); + ESTAT_ADD(rx_512_to_1023_octet_packets); + ESTAT_ADD(rx_1024_to_1522_octet_packets); + ESTAT_ADD(rx_1523_to_2047_octet_packets); + ESTAT_ADD(rx_2048_to_4095_octet_packets); + ESTAT_ADD(rx_4096_to_8191_octet_packets); + ESTAT_ADD(rx_8192_to_9022_octet_packets); + ESTAT_ADD(tx_octets); + ESTAT_ADD(tx_collisions); ESTAT_ADD(tx_xon_sent); ESTAT_ADD(tx_xoff_sent); ESTAT_ADD(tx_flow_control); @@ -5944,16 +6020,50 @@ ESTAT_ADD(tx_deferred); ESTAT_ADD(tx_excessive_collisions); ESTAT_ADD(tx_late_collisions); + ESTAT_ADD(tx_collide_2times); + ESTAT_ADD(tx_collide_3times); + ESTAT_ADD(tx_collide_4times); + ESTAT_ADD(tx_collide_5times); + ESTAT_ADD(tx_collide_6times); + ESTAT_ADD(tx_collide_7times); + ESTAT_ADD(tx_collide_8times); + ESTAT_ADD(tx_collide_9times); + ESTAT_ADD(tx_collide_10times); + ESTAT_ADD(tx_collide_11times); + ESTAT_ADD(tx_collide_12times); + ESTAT_ADD(tx_collide_13times); + ESTAT_ADD(tx_collide_14times); + ESTAT_ADD(tx_collide_15times); ESTAT_ADD(tx_ucast_packets); ESTAT_ADD(tx_mcast_packets); ESTAT_ADD(tx_bcast_packets); + ESTAT_ADD(tx_carrier_sense_errors); + ESTAT_ADD(tx_discards); + ESTAT_ADD(tx_errors); + + ESTAT_ADD(dma_writeq_full); + ESTAT_ADD(dma_write_prioq_full); + ESTAT_ADD(rxbds_empty); + ESTAT_ADD(rx_discards); + ESTAT_ADD(rx_errors); + ESTAT_ADD(rx_threshold_hit); + + ESTAT_ADD(dma_readq_full); + ESTAT_ADD(dma_read_prioq_full); + ESTAT_ADD(tx_comp_queue_full); + + ESTAT_ADD(ring_set_send_prod_index); + ESTAT_ADD(ring_status_update); + ESTAT_ADD(nic_irqs); + ESTAT_ADD(nic_avoided_irqs); + ESTAT_ADD(nic_tx_threshold_hit); return estats; } static struct net_device_stats *tg3_get_stats(struct net_device *dev) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); struct net_device_stats *stats = &tp->net_stats; struct net_device_stats *old_stats = &tp->net_stats_prev; struct tg3_hw_stats *hw_stats = tp->hw_stats; @@ -5977,7 +6087,8 @@ get_stat64(&hw_stats->tx_octets); stats->rx_errors = old_stats->rx_errors + - get_stat64(&hw_stats->rx_errors); + get_stat64(&hw_stats->rx_errors) + + get_stat64(&hw_stats->rx_discards); stats->tx_errors = old_stats->tx_errors + get_stat64(&hw_stats->tx_errors) + get_stat64(&hw_stats->tx_mac_errors) + @@ -6044,7 +6155,7 @@ static void __tg3_set_rx_mode(struct net_device *dev) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); u32 rx_mode; rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC | @@ -6108,7 +6219,7 @@ static void tg3_set_rx_mode(struct net_device *dev) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); spin_lock_irq(&tp->lock); __tg3_set_rx_mode(dev); @@ -6126,7 +6237,7 @@ struct ethtool_regs *regs, void *_p) { u32 *p = _p; - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); u8 *orig_p = _p; int i; @@ -6257,7 +6368,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || tp->link_config.phy_is_low_power) @@ -6292,7 +6403,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || tp->link_config.phy_is_low_power) @@ -6331,7 +6442,7 @@ static void tg3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); strcpy(info->driver, DRV_MODULE_NAME); strcpy(info->version, DRV_MODULE_VERSION); @@ -6340,7 +6451,7 @@ static void tg3_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); wol->supported = WAKE_MAGIC; wol->wolopts = 0; @@ -6351,7 +6462,7 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; @@ -6372,20 +6483,20 @@ static u32 tg3_get_msglevel(struct net_device *dev) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); return tp->msg_enable; } static void tg3_set_msglevel(struct net_device *dev, u32 value) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); tp->msg_enable = value; } #if TG3_TSO_SUPPORT != 0 static int tg3_set_tso(struct net_device *dev, u32 value) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { if (value) @@ -6398,7 +6509,7 @@ static int tg3_nway_reset(struct net_device *dev) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); u32 bmcr; int r; @@ -6417,7 +6528,7 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); ering->rx_max_pending = TG3_RX_RING_SIZE - 1; ering->rx_mini_max_pending = 0; @@ -6431,7 +6542,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) || (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) || @@ -6462,7 +6573,7 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0; epause->rx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_RX) != 0; @@ -6471,7 +6582,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); tg3_netif_stop(tp); spin_lock_irq(&tp->lock); @@ -6499,13 +6610,13 @@ static u32 tg3_get_rx_csum(struct net_device *dev) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); return (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0; } static int tg3_set_rx_csum(struct net_device *dev, u32 data) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) { if (data != 0) @@ -6525,7 +6636,7 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) { if (data != 0) @@ -6562,13 +6673,13 @@ struct ethtool_stats *estats, u64 *tmp_stats) { struct tg3 *tp = dev->priv; - memcpy(tmp_stats, &tp->estats, sizeof(tp->estats)); + memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats)); } static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); int err; switch(cmd) { @@ -6608,7 +6719,7 @@ #if TG3_VLAN_TAG_USED static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); spin_lock_irq(&tp->lock); spin_lock(&tp->tx_lock); @@ -6624,7 +6735,7 @@ static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); spin_lock_irq(&tp->lock); spin_lock(&tp->tx_lock); @@ -8047,7 +8158,7 @@ dev->vlan_rx_kill_vid = tg3_vlan_rx_kill_vid; #endif - tp = dev->priv; + tp = netdev_priv(dev); tp->pdev = pdev; tp->dev = dev; tp->pm_cap = pm_cap; @@ -8268,8 +8379,10 @@ struct net_device *dev = pci_get_drvdata(pdev); if (dev) { + struct tg3 *tp = netdev_priv(dev); + unregister_netdev(dev); - iounmap((void *) ((struct tg3 *)(dev->priv))->regs); + iounmap((void *)tp->regs); free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); @@ -8280,7 +8393,7 @@ static int tg3_suspend(struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata(pdev); - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); int err; if (!netif_running(dev)) @@ -8327,7 +8440,7 @@ static int tg3_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct tg3 *tp = dev->priv; + struct tg3 *tp = netdev_priv(dev); int err; if (!netif_running(dev)) --- diff/drivers/net/tg3.h 2004-05-27 13:41:19.000000000 +0100 +++ source/drivers/net/tg3.h 2004-05-27 18:34:17.000000000 +0100 @@ -1845,10 +1845,13 @@ struct tg3_ethtool_stats { /* Statistics maintained by Receive MAC. */ + u64 rx_octets; u64 rx_fragments; u64 rx_ucast_packets; + u64 rx_mcast_packets; u64 rx_bcast_packets; u64 rx_fcs_errors; + u64 rx_align_errors; u64 rx_xon_pause_rcvd; u64 rx_xoff_pause_rcvd; u64 rx_mac_ctrl_rcvd; @@ -1858,8 +1861,20 @@ u64 rx_undersize_packets; u64 rx_in_length_errors; u64 rx_out_length_errors; + u64 rx_64_or_less_octet_packets; + u64 rx_65_to_127_octet_packets; + u64 rx_128_to_255_octet_packets; + u64 rx_256_to_511_octet_packets; + u64 rx_512_to_1023_octet_packets; + u64 rx_1024_to_1522_octet_packets; + u64 rx_1523_to_2047_octet_packets; + u64 rx_2048_to_4095_octet_packets; + u64 rx_4096_to_8191_octet_packets; + u64 rx_8192_to_9022_octet_packets; /* Statistics maintained by Transmit MAC. */ + u64 tx_octets; + u64 tx_collisions; u64 tx_xon_sent; u64 tx_xoff_sent; u64 tx_flow_control; @@ -1869,9 +1884,46 @@ u64 tx_deferred; u64 tx_excessive_collisions; u64 tx_late_collisions; + u64 tx_collide_2times; + u64 tx_collide_3times; + u64 tx_collide_4times; + u64 tx_collide_5times; + u64 tx_collide_6times; + u64 tx_collide_7times; + u64 tx_collide_8times; + u64 tx_collide_9times; + u64 tx_collide_10times; + u64 tx_collide_11times; + u64 tx_collide_12times; + u64 tx_collide_13times; + u64 tx_collide_14times; + u64 tx_collide_15times; u64 tx_ucast_packets; u64 tx_mcast_packets; u64 tx_bcast_packets; + u64 tx_carrier_sense_errors; + u64 tx_discards; + u64 tx_errors; + + /* Statistics maintained by Receive List Placement. */ + u64 dma_writeq_full; + u64 dma_write_prioq_full; + u64 rxbds_empty; + u64 rx_discards; + u64 rx_errors; + u64 rx_threshold_hit; + + /* Statistics maintained by Send Data Initiator. */ + u64 dma_readq_full; + u64 dma_read_prioq_full; + u64 tx_comp_queue_full; + + /* Statistics maintained by Host Coalescing. */ + u64 ring_set_send_prod_index; + u64 ring_status_update; + u64 nic_irqs; + u64 nic_avoided_irqs; + u64 nic_tx_threshold_hit; }; struct tg3 { --- diff/drivers/net/tokenring/olympic.c 2004-05-19 22:11:59.000000000 +0100 +++ source/drivers/net/tokenring/olympic.c 2004-05-27 18:34:17.000000000 +0100 @@ -1806,7 +1806,7 @@ static void __exit olympic_pci_cleanup(void) { - return pci_unregister_driver(&olympic_driver) ; + pci_unregister_driver(&olympic_driver) ; } --- diff/drivers/net/tulip/interrupt.c 2004-05-19 22:11:59.000000000 +0100 +++ source/drivers/net/tulip/interrupt.c 2004-05-27 18:34:17.000000000 +0100 @@ -133,6 +133,10 @@ tp->rx_ring[entry].status); do { + if (inl(dev->base_addr + CSR5) == 0xffffffff) { + printk(KERN_DEBUG " In tulip_poll(), hardware disappeared.\n"); + break; + } /* Acknowledge current RX interrupt sources. */ outl((RxIntr | RxNoBuf), dev->base_addr + CSR5); --- diff/drivers/net/tulip/tulip_core.c 2004-05-19 22:11:59.000000000 +0100 +++ source/drivers/net/tulip/tulip_core.c 2004-05-27 18:34:17.000000000 +0100 @@ -1513,7 +1513,7 @@ } } /* Lite-On boards have the address byte-swapped. */ - if ((dev->dev_addr[0] == 0xA0 || dev->dev_addr[0] == 0xC0) + if ((dev->dev_addr[0] == 0xA0 || dev->dev_addr[0] == 0xC0 || dev->dev_addr[0] == 0x02) && dev->dev_addr[1] == 0x00) for (i = 0; i < 6; i+=2) { char tmp = dev->dev_addr[i]; --- diff/drivers/net/tulip/winbond-840.c 2004-05-19 22:12:00.000000000 +0100 +++ source/drivers/net/tulip/winbond-840.c 2004-05-27 18:34:17.000000000 +0100 @@ -1292,14 +1292,8 @@ pci_dma_sync_single_for_cpu(np->pci_dev,np->rx_addr[entry], np->rx_skbuff[entry]->len, PCI_DMA_FROMDEVICE); - /* Call copy + cksum if available. */ -#if HAS_IP_COPYSUM eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0); skb_put(skb, pkt_len); -#else - memcpy(skb_put(skb, pkt_len), np->rx_skbuff[entry]->tail, - pkt_len); -#endif pci_dma_sync_single_for_device(np->pci_dev,np->rx_addr[entry], np->rx_skbuff[entry]->len, PCI_DMA_FROMDEVICE); --- diff/drivers/net/via-rhine.c 2004-05-19 22:11:56.000000000 +0100 +++ source/drivers/net/via-rhine.c 2004-05-27 18:34:17.000000000 +0100 @@ -74,8 +74,8 @@ LK1.1.11: - David Woodhouse: Set dev->base_addr before the first time we call - wait_for_reset(). It's a lot happier that way. - Free np->tx_bufs only if we actually allocated it. + wait_for_reset(). It's a lot happier that way. + Free np->tx_bufs only if we actually allocated it. LK1.1.12: - Martin Eriksson: Allow Memory-Mapped IO to be enabled. @@ -85,7 +85,7 @@ - Replace some MII-related magic numbers with constants LK1.1.14 (Ivan G.): - - fixes comments for Rhine-III + - fixes comments for Rhine-III - removes W_MAX_TIMEOUT (unused) - adds HasDavicomPhy for Rhine-I (basis: linuxfet driver; my card is R-I and has Davicom chip, flag is referenced in kernel driver) @@ -96,10 +96,10 @@ - transmit frame queue message is off by one - fixed - adds IntrNormalSummary to "Something Wicked" exclusion list so normal interrupts will not trigger the message (src: Donald Becker) - (Roger Luethi) - - show confused chip where to continue after Tx error - - location of collision counter is chip specific - - allow selecting backoff algorithm (module parameter) + (Roger Luethi) + - show confused chip where to continue after Tx error + - location of collision counter is chip specific + - allow selecting backoff algorithm (module parameter) LK1.1.15 (jgarzik): - Use new MII lib helper generic_mii_ioctl @@ -128,14 +128,14 @@ */ #define DRV_NAME "via-rhine" -#define DRV_VERSION "1.1.19-2.5" -#define DRV_RELDATE "July-12-2003" +#define DRV_VERSION "1.1.20-2.6" +#define DRV_RELDATE "May-23-2004" /* A few user-configurable values. These may be modified when a driver module is loaded. */ -static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ +static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ static int max_interrupt_work = 20; /* Set the copy breakpoint for the copy-only-tiny-frames scheme. @@ -155,12 +155,12 @@ Use option values 0x10 and 0x100 for forcing half duplex fixed speed. Use option values 0x20 and 0x200 for forcing full duplex operation. */ -#define MAX_UNITS 8 /* More are supported, limit only on options */ +#define MAX_UNITS 8 /* More are supported, limit only on options */ static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; /* Maximum number of multicast addresses to filter (vs. rx-all-multicast). - The Rhine has a 64 element 8390-like hash table. */ + The Rhine has a 64 element 8390-like hash table. */ static const int multicast_filter_limit = 32; @@ -172,16 +172,16 @@ bonding and packet priority. There are no ill effects from too-large receive rings. */ #define TX_RING_SIZE 16 -#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */ +#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */ #define RX_RING_SIZE 16 /* Operational parameters that usually are not changed. */ /* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (2*HZ) +#define TX_TIMEOUT (2*HZ) -#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ +#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ #if !defined(__OPTIMIZE__) || !defined(__KERNEL__) #warning You must compile this file with the correct options! @@ -206,7 +206,7 @@ #include #include #include -#include /* Processor type for cache alignment. */ +#include /* Processor type for cache alignment. */ #include #include #include @@ -214,18 +214,16 @@ /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = -KERN_INFO DRV_NAME ".c:v1.10-LK" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n" -KERN_INFO " http://www.scyld.com/network/via-rhine.html\n"; +KERN_INFO DRV_NAME ".c:v1.10-LK" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n"; static char shortname[] = DRV_NAME; -/* This driver was written to use PCI memory space, however most versions - of the Rhine only work correctly with I/O space accesses. */ +/* This driver was written to use PCI memory space. Some early versions + of the Rhine may only work correctly with I/O space accesses. */ #ifdef CONFIG_VIA_RHINE_MMIO -#define USE_MEM +#define USE_MMIO #else -#define USE_IO #undef readb #undef readw #undef readl @@ -258,7 +256,7 @@ MODULE_PARM_DESC(full_duplex, "VIA Rhine full duplex setting(s) (1)"); /* - Theory of Operation + Theory of Operation I. Board Compatibility @@ -281,7 +279,7 @@ This driver uses two statically allocated fixed-size descriptor lists formed into rings by a branch from the final descriptor to the beginning of -the list. The ring sizes are set at compile time by RX/TX_RING_SIZE. +the list. The ring sizes are set at compile time by RX/TX_RING_SIZE. IIIb/c. Transmit/Receive Structure @@ -292,29 +290,29 @@ The driver allocates full frame size skbuffs for the Rx ring buffers at open() time and passes the skb->data field to the chip as receive data -buffers. When an incoming frame is less than RX_COPYBREAK bytes long, +buffers. When an incoming frame is less than RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is copied to the new skbuff. When the incoming frame is larger, the skbuff is passed directly up the -protocol stack. Buffers consumed this way are replaced by newly allocated -skbuffs in the last phase of via_rhine_rx(). +protocol stack. Buffers consumed this way are replaced by newly allocated +skbuffs in the last phase of rhine_rx(). The RX_COPYBREAK value is chosen to trade-off the memory wasted by using a full-sized skbuff for small frames vs. the copying costs of larger -frames. New boards are typically used in generously configured machines +frames. New boards are typically used in generously configured machines and the underfilled buffers have negligible impact compared to the benefit of a single allocation size, so the default value of zero results in never -copying packets. When copying is done, the cost is usually mitigated by using -a combined copy/checksum routine. Copying also preloads the cache, which is +copying packets. When copying is done, the cost is usually mitigated by using +a combined copy/checksum routine. Copying also preloads the cache, which is most useful with small frames. Since the VIA chips are only able to transfer data to buffers on 32 bit boundaries, the IP header at offset 14 in an ethernet frame isn't -longword aligned for further processing. Copying these unaligned buffers +longword aligned for further processing. Copying these unaligned buffers has the beneficial effect of 16-byte aligning the IP header. IIId. Synchronization -The driver runs as two independent, single-threaded flows of control. One +The driver runs as two independent, single-threaded flows of control. One is the send-packet routine, which enforces single-threaded use by the dev->priv->lock spinlock. The other thread is the interrupt handler, which is single threaded by the hardware and interrupt handling software. @@ -324,7 +322,7 @@ is not available it stops the transmit queue by calling netif_stop_queue. The interrupt handler has exclusive control over the Rx ring and records stats -from the Tx ring. After reaping the stats, it marks the Tx queue entry as +from the Tx ring. After reaping the stats, it marks the Tx queue entry as empty by incrementing the dirty_tx mark. If at least half of the entries in the Rx ring are available the transmit queue is woken up if it was stopped. @@ -350,7 +348,7 @@ */ -/* This table drives the PCI probe routines. It's mostly boilerplate in all +/* This table drives the PCI probe routines. It's mostly boilerplate in all of the drivers, and will likely be provided by some future kernel. Note the matching code -- the first table entry matchs all 56** cards but second only the 1234 card. @@ -361,14 +359,14 @@ PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, }; -enum via_rhine_chips { +enum rhine_chips { VT86C100A = 0, VT6102, VT6105, VT6105M }; -struct via_rhine_chip_info { +struct rhine_chip_info { const char *name; u16 pci_flags; int io_size; @@ -378,9 +376,10 @@ enum chip_capability_flags { CanHaveMII=1, HasESIPhy=2, HasDavicomPhy=4, - ReqTxAlign=0x10, HasWOL=0x20, }; + ReqTxAlign=0x10, HasWOL=0x20, +}; -#ifdef USE_MEM +#ifdef USE_MMIO #define RHINE_IOTYPE (PCI_USES_MEM | PCI_USES_MASTER | PCI_ADDR1) #else #define RHINE_IOTYPE (PCI_USES_IO | PCI_USES_MASTER | PCI_ADDR0) @@ -388,8 +387,8 @@ /* Beware of PCI posted writes */ #define IOSYNC do { readb(dev->base_addr + StationAddr); } while (0) -/* directly indexed by enum via_rhine_chips, above */ -static struct via_rhine_chip_info via_rhine_chip_info[] __devinitdata = +/* directly indexed by enum rhine_chips, above */ +static struct rhine_chip_info rhine_chip_info[] __devinitdata = { { "VIA VT86C100A Rhine", RHINE_IOTYPE, 128, CanHaveMII | ReqTxAlign | HasDavicomPhy }, @@ -401,15 +400,15 @@ CanHaveMII | HasWOL }, }; -static struct pci_device_id via_rhine_pci_tbl[] = +static struct pci_device_id rhine_pci_tbl[] = { {0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT86C100A}, {0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6102}, {0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6105}, /* 6105{,L,LOM} */ {0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT6105M}, - {0,} /* terminate list */ + {0,} /* terminate list */ }; -MODULE_DEVICE_TABLE(pci, via_rhine_pci_tbl); +MODULE_DEVICE_TABLE(pci, rhine_pci_tbl); /* Offsets to the device registers. */ @@ -432,7 +431,7 @@ BackCaptureEffect=0x04, BackRandom=0x08 }; -#ifdef USE_MEM +#ifdef USE_MMIO /* Registers we check that mmio and reg are the same. */ int mmio_verify_registers[] = { RxConfig, TxConfig, IntrEnable, ConfigA, ConfigB, ConfigC, ConfigD, @@ -469,7 +468,7 @@ }; /* Initial value for tx_desc.desc_length, Buffer size goes to bits 0-10 */ -#define TXDESC 0x00e08000 +#define TXDESC 0x00e08000 enum rx_status_bits { RxOK=0x8000, RxWholePkt=0x0300, RxErr=0x008F @@ -489,7 +488,7 @@ }; #define MAX_MII_CNT 4 -struct netdev_private { +struct rhine_private { /* Descriptor rings */ struct rx_desc *rx_ring; struct tx_desc *tx_ring; @@ -517,48 +516,48 @@ /* Frequently used values: keep some adjacent for cache effect. */ int chip_id, drv_flags; struct rx_desc *rx_head_desc; - unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ + unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ unsigned int cur_tx, dirty_tx; - unsigned int rx_buf_sz; /* Based on MTU+slack. */ - u16 chip_cmd; /* Current setting for ChipCmd */ + unsigned int rx_buf_sz; /* Based on MTU+slack. */ + u16 chip_cmd; /* Current setting for ChipCmd */ /* These values are keep track of the transceiver/media in use. */ - unsigned int default_port:4; /* Last dev->if_port value. */ + unsigned int default_port:4; /* Last dev->if_port value. */ u8 tx_thresh, rx_thresh; /* MII transceiver section. */ - unsigned char phys[MAX_MII_CNT]; /* MII device addresses. */ - unsigned int mii_cnt; /* number of MIIs found, but only the first one is used */ - u16 mii_status; /* last read MII status */ + unsigned char phys[MAX_MII_CNT]; /* MII device addresses. */ + unsigned int mii_cnt; /* number of MIIs found, but only the first one is used */ + u16 mii_status; /* last read MII status */ struct mii_if_info mii_if; }; static int mdio_read(struct net_device *dev, int phy_id, int location); static void mdio_write(struct net_device *dev, int phy_id, int location, int value); -static int via_rhine_open(struct net_device *dev); -static void via_rhine_check_duplex(struct net_device *dev); -static void via_rhine_timer(unsigned long data); -static void via_rhine_tx_timeout(struct net_device *dev); -static int via_rhine_start_tx(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t via_rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -static void via_rhine_tx(struct net_device *dev); -static void via_rhine_rx(struct net_device *dev); -static void via_rhine_error(struct net_device *dev, int intr_status); -static void via_rhine_set_rx_mode(struct net_device *dev); -static struct net_device_stats *via_rhine_get_stats(struct net_device *dev); +static int rhine_open(struct net_device *dev); +static void rhine_check_duplex(struct net_device *dev); +static void rhine_timer(unsigned long data); +static void rhine_tx_timeout(struct net_device *dev); +static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev); +static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +static void rhine_tx(struct net_device *dev); +static void rhine_rx(struct net_device *dev); +static void rhine_error(struct net_device *dev, int intr_status); +static void rhine_set_rx_mode(struct net_device *dev); +static struct net_device_stats *rhine_get_stats(struct net_device *dev); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static struct ethtool_ops netdev_ethtool_ops; -static int via_rhine_close(struct net_device *dev); +static int rhine_close(struct net_device *dev); static inline u32 get_intr_status(struct net_device *dev) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); u32 intr_status; intr_status = readw(ioaddr + IntrStatus); /* On Rhine-II, Bit 3 indicates Tx descriptor write-back race. */ - if (np->chip_id == VT6102) + if (rp->chip_id == VT6102) intr_status |= readb(ioaddr + IntrStatus2) << 16; return intr_status; } @@ -590,7 +589,7 @@ boguscnt ? "succeeded" : "failed"); } -#ifdef USE_MEM +#ifdef USE_MMIO static void __devinit enable_mmio(long ioaddr, int chip_id) { int n; @@ -616,19 +615,19 @@ } #ifdef CONFIG_NET_POLL_CONTROLLER -static void via_rhine_poll(struct net_device *dev) +static void rhine_poll(struct net_device *dev) { disable_irq(dev->irq); - via_rhine_interrupt(dev->irq, (void *)dev, NULL); + rhine_interrupt(dev->irq, (void *)dev, NULL); enable_irq(dev->irq); } #endif -static int __devinit via_rhine_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit rhine_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct net_device *dev; - struct netdev_private *np; + struct rhine_private *rp; int i, option; int chip_id = (int) ent->driver_data; static int card_idx = -1; @@ -636,7 +635,7 @@ long memaddr; int io_size; int pci_flags; -#ifdef USE_MEM +#ifdef USE_MMIO long ioaddr0; #endif @@ -649,34 +648,36 @@ card_idx++; option = card_idx < MAX_UNITS ? options[card_idx] : 0; - io_size = via_rhine_chip_info[chip_id].io_size; - pci_flags = via_rhine_chip_info[chip_id].pci_flags; + io_size = rhine_chip_info[chip_id].io_size; + pci_flags = rhine_chip_info[chip_id].pci_flags; - if (pci_enable_device (pdev)) + if (pci_enable_device(pdev)) goto err_out; /* this should always be supported */ if (pci_set_dma_mask(pdev, 0xffffffff)) { - printk(KERN_ERR "32-bit PCI DMA addresses not supported by the card!?\n"); + printk(KERN_ERR "32-bit PCI DMA addresses not supported by " + "the card!?\n"); goto err_out; } /* sanity check */ - if ((pci_resource_len (pdev, 0) < io_size) || - (pci_resource_len (pdev, 1) < io_size)) { - printk (KERN_ERR "Insufficient PCI resources, aborting\n"); + if ((pci_resource_len(pdev, 0) < io_size) || + (pci_resource_len(pdev, 1) < io_size)) { + printk(KERN_ERR "Insufficient PCI resources, aborting\n"); goto err_out; } - ioaddr = pci_resource_start (pdev, 0); - memaddr = pci_resource_start (pdev, 1); + ioaddr = pci_resource_start(pdev, 0); + memaddr = pci_resource_start(pdev, 1); if (pci_flags & PCI_USES_MASTER) - pci_set_master (pdev); + pci_set_master(pdev); - dev = alloc_etherdev(sizeof(*np)); + dev = alloc_etherdev(sizeof(*rp)); if (dev == NULL) { - printk (KERN_ERR "init_ethernet failed for card #%d\n", card_idx); + printk(KERN_ERR "init_ethernet failed for card #%d\n", + card_idx); goto err_out; } SET_MODULE_OWNER(dev); @@ -685,14 +686,14 @@ if (pci_request_regions(pdev, shortname)) goto err_out_free_netdev; -#ifdef USE_MEM +#ifdef USE_MMIO ioaddr0 = ioaddr; enable_mmio(ioaddr0, chip_id); - ioaddr = (long) ioremap (memaddr, io_size); + ioaddr = (long) ioremap(memaddr, io_size); if (!ioaddr) { - printk (KERN_ERR "ioremap failed for device %s, region 0x%X @ 0x%lX\n", - pci_name(pdev), io_size, memaddr); + printk(KERN_ERR "ioremap failed for device %s, region 0x%X " + "@ 0x%lX\n", pci_name(pdev), io_size, memaddr); goto err_out_free_res; } @@ -703,15 +704,15 @@ unsigned char a = inb(ioaddr0+reg); unsigned char b = readb(ioaddr+reg); if (a != b) { - printk (KERN_ERR "MMIO do not match PIO [%02x] (%02x != %02x)\n", - reg, a, b); + printk(KERN_ERR "MMIO do not match PIO [%02x] " + "(%02x != %02x)\n", reg, a, b); goto err_out_unmap; } } -#endif +#endif /* USE_MMIO */ /* D-Link provided reset code (with comment additions) */ - if (via_rhine_chip_info[chip_id].drv_flags & HasWOL) { + if (rhine_chip_info[chip_id].drv_flags & HasWOL) { unsigned char byOrgValue; /* clear sticky bit before reset & read ethernet address */ @@ -735,14 +736,14 @@ wait_for_reset(dev, chip_id, shortname); /* Reload the station address from the EEPROM. */ -#ifdef USE_IO - reload_eeprom(ioaddr); -#else +#ifdef USE_MMIO reload_eeprom(ioaddr0); /* Reloading from eeprom overwrites cfgA-D, so we must re-enable MMIO. If reload_eeprom() was done first this could be avoided, but it is not known if that still works with the "win98-reboot" problem. */ enable_mmio(ioaddr0, chip_id); +#else + reload_eeprom(ioaddr); #endif for (i = 0; i < 6; i++) @@ -756,7 +757,7 @@ if (chip_id == VT6102) { /* * for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA - * turned on. it makes MAC receive magic packet + * turned on. it makes MAC receive magic packet * automatically. So, we turn it off. (D-Link) */ writeb(readb(ioaddr + ConfigA) & 0xFE, ioaddr + ConfigA); @@ -765,38 +766,38 @@ /* Select backoff algorithm */ if (backoff) writeb(readb(ioaddr + ConfigD) & (0xF0 | backoff), - ioaddr + ConfigD); + ioaddr + ConfigD); dev->irq = pdev->irq; - np = dev->priv; - spin_lock_init (&np->lock); - np->chip_id = chip_id; - np->drv_flags = via_rhine_chip_info[chip_id].drv_flags; - np->pdev = pdev; - np->mii_if.dev = dev; - np->mii_if.mdio_read = mdio_read; - np->mii_if.mdio_write = mdio_write; - np->mii_if.phy_id_mask = 0x1f; - np->mii_if.reg_num_mask = 0x1f; + rp = netdev_priv(dev); + spin_lock_init(&rp->lock); + rp->chip_id = chip_id; + rp->drv_flags = rhine_chip_info[chip_id].drv_flags; + rp->pdev = pdev; + rp->mii_if.dev = dev; + rp->mii_if.mdio_read = mdio_read; + rp->mii_if.mdio_write = mdio_write; + rp->mii_if.phy_id_mask = 0x1f; + rp->mii_if.reg_num_mask = 0x1f; if (dev->mem_start) option = dev->mem_start; /* The chip-specific entries in the device structure. */ - dev->open = via_rhine_open; - dev->hard_start_xmit = via_rhine_start_tx; - dev->stop = via_rhine_close; - dev->get_stats = via_rhine_get_stats; - dev->set_multicast_list = via_rhine_set_rx_mode; + dev->open = rhine_open; + dev->hard_start_xmit = rhine_start_tx; + dev->stop = rhine_close; + dev->get_stats = rhine_get_stats; + dev->set_multicast_list = rhine_set_rx_mode; dev->do_ioctl = netdev_ioctl; dev->ethtool_ops = &netdev_ethtool_ops; - dev->tx_timeout = via_rhine_tx_timeout; + dev->tx_timeout = rhine_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; #ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = via_rhine_poll; + dev->poll_controller = rhine_poll; #endif - if (np->drv_flags & ReqTxAlign) + if (rp->drv_flags & ReqTxAlign) dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM; /* dev->name not defined before register_netdev()! */ @@ -807,40 +808,41 @@ /* The lower four bits are the media type. */ if (option > 0) { if (option & 0x220) - np->mii_if.full_duplex = 1; - np->default_port = option & 15; + rp->mii_if.full_duplex = 1; + rp->default_port = option & 15; } - if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) - np->mii_if.full_duplex = 1; + if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) + rp->mii_if.full_duplex = 1; - if (np->mii_if.full_duplex) { - printk(KERN_INFO "%s: Set to forced full duplex, autonegotiation" - " disabled.\n", dev->name); - np->mii_if.force_media = 1; + if (rp->mii_if.full_duplex) { + printk(KERN_INFO "%s: Set to forced full duplex, " + "autonegotiation disabled.\n", dev->name); + rp->mii_if.force_media = 1; } printk(KERN_INFO "%s: %s at 0x%lx, ", - dev->name, via_rhine_chip_info[chip_id].name, - (pci_flags & PCI_USES_IO) ? ioaddr : memaddr); + dev->name, rhine_chip_info[chip_id].name, + (pci_flags & PCI_USES_IO) ? ioaddr : memaddr); for (i = 0; i < 5; i++) - printk("%2.2x:", dev->dev_addr[i]); + printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], pdev->irq); pci_set_drvdata(pdev, dev); - if (np->drv_flags & CanHaveMII) { + if (rp->drv_flags & CanHaveMII) { int phy, phy_idx = 0; - np->phys[0] = 1; /* Standard for this chip. */ + rp->phys[0] = 1; /* Standard for this chip. */ for (phy = 1; phy < 32 && phy_idx < MAX_MII_CNT; phy++) { int mii_status = mdio_read(dev, phy, 1); - if (mii_status != 0xffff && mii_status != 0x0000) { - np->phys[phy_idx++] = phy; - np->mii_if.advertising = mdio_read(dev, phy, 4); - printk(KERN_INFO "%s: MII PHY found at address %d, status " - "0x%4.4x advertising %4.4x Link %4.4x.\n", - dev->name, phy, mii_status, np->mii_if.advertising, - mdio_read(dev, phy, 5)); + if (mii_status != 0xffff && mii_status != 0x0000) { + rp->phys[phy_idx++] = phy; + rp->mii_if.advertising = mdio_read(dev, phy, 4); + printk(KERN_INFO "%s: MII PHY found at address " + "%d, status 0x%4.4x advertising %4.4x " + "Link %4.4x.\n", dev->name, phy, + mii_status, rp->mii_if.advertising, + mdio_read(dev, phy, 5)); /* set IFF_RUNNING */ if (mii_status & BMSR_LSTATUS) @@ -851,49 +853,50 @@ break; } } - np->mii_cnt = phy_idx; - np->mii_if.phy_id = np->phys[0]; + rp->mii_cnt = phy_idx; + rp->mii_if.phy_id = rp->phys[0]; } /* Allow forcing the media type. */ if (option > 0) { if (option & 0x220) - np->mii_if.full_duplex = 1; - np->default_port = option & 0x3ff; - if (np->default_port & 0x330) { + rp->mii_if.full_duplex = 1; + rp->default_port = option & 0x3ff; + if (option & 0x330) { /* FIXME: shouldn't someone check this variable? */ - /* np->medialock = 1; */ - printk(KERN_INFO " Forcing %dMbs %s-duplex operation.\n", - (option & 0x300 ? 100 : 10), - (option & 0x220 ? "full" : "half")); - if (np->mii_cnt) - mdio_write(dev, np->phys[0], MII_BMCR, - ((option & 0x300) ? 0x2000 : 0) | /* 100mbps? */ - ((option & 0x220) ? 0x0100 : 0)); /* Full duplex? */ + /* rp->medialock = 1; */ + printk(KERN_INFO " Forcing %dMbs %s-duplex " + "operation.\n", + (option & 0x300 ? 100 : 10), + (option & 0x220 ? "full" : "half")); + if (rp->mii_cnt) + mdio_write(dev, rp->phys[0], MII_BMCR, + ((option & 0x300) ? 0x2000 : 0) | /* 100mbps? */ + ((option & 0x220) ? 0x0100 : 0)); /* Full duplex? */ } } return 0; err_out_unmap: -#ifdef USE_MEM +#ifdef USE_MMIO iounmap((void *)ioaddr); err_out_free_res: #endif pci_release_regions(pdev); err_out_free_netdev: - free_netdev (dev); + free_netdev(dev); err_out: return -ENODEV; } static int alloc_ring(struct net_device* dev) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); void *ring; dma_addr_t ring_dma; - ring = pci_alloc_consistent(np->pdev, + ring = pci_alloc_consistent(rp->pdev, RX_RING_SIZE * sizeof(struct rx_desc) + TX_RING_SIZE * sizeof(struct tx_desc), &ring_dma); @@ -901,11 +904,12 @@ printk(KERN_ERR "Could not allocate DMA memory.\n"); return -ENOMEM; } - if (np->drv_flags & ReqTxAlign) { - np->tx_bufs = pci_alloc_consistent(np->pdev, PKT_BUF_SZ * TX_RING_SIZE, - &np->tx_bufs_dma); - if (np->tx_bufs == NULL) { - pci_free_consistent(np->pdev, + if (rp->drv_flags & ReqTxAlign) { + rp->tx_bufs = pci_alloc_consistent(rp->pdev, + PKT_BUF_SZ * TX_RING_SIZE, + &rp->tx_bufs_dma); + if (rp->tx_bufs == NULL) { + pci_free_consistent(rp->pdev, RX_RING_SIZE * sizeof(struct rx_desc) + TX_RING_SIZE * sizeof(struct tx_desc), ring, ring_dma); @@ -913,137 +917,138 @@ } } - np->rx_ring = ring; - np->tx_ring = ring + RX_RING_SIZE * sizeof(struct rx_desc); - np->rx_ring_dma = ring_dma; - np->tx_ring_dma = ring_dma + RX_RING_SIZE * sizeof(struct rx_desc); + rp->rx_ring = ring; + rp->tx_ring = ring + RX_RING_SIZE * sizeof(struct rx_desc); + rp->rx_ring_dma = ring_dma; + rp->tx_ring_dma = ring_dma + RX_RING_SIZE * sizeof(struct rx_desc); return 0; } void free_ring(struct net_device* dev) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); - pci_free_consistent(np->pdev, + pci_free_consistent(rp->pdev, RX_RING_SIZE * sizeof(struct rx_desc) + TX_RING_SIZE * sizeof(struct tx_desc), - np->rx_ring, np->rx_ring_dma); - np->tx_ring = NULL; + rp->rx_ring, rp->rx_ring_dma); + rp->tx_ring = NULL; - if (np->tx_bufs) - pci_free_consistent(np->pdev, PKT_BUF_SZ * TX_RING_SIZE, - np->tx_bufs, np->tx_bufs_dma); + if (rp->tx_bufs) + pci_free_consistent(rp->pdev, PKT_BUF_SZ * TX_RING_SIZE, + rp->tx_bufs, rp->tx_bufs_dma); - np->tx_bufs = NULL; + rp->tx_bufs = NULL; } static void alloc_rbufs(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); dma_addr_t next; int i; - np->dirty_rx = np->cur_rx = 0; + rp->dirty_rx = rp->cur_rx = 0; - np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); - np->rx_head_desc = &np->rx_ring[0]; - next = np->rx_ring_dma; + rp->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); + rp->rx_head_desc = &rp->rx_ring[0]; + next = rp->rx_ring_dma; /* Init the ring entries */ for (i = 0; i < RX_RING_SIZE; i++) { - np->rx_ring[i].rx_status = 0; - np->rx_ring[i].desc_length = cpu_to_le32(np->rx_buf_sz); + rp->rx_ring[i].rx_status = 0; + rp->rx_ring[i].desc_length = cpu_to_le32(rp->rx_buf_sz); next += sizeof(struct rx_desc); - np->rx_ring[i].next_desc = cpu_to_le32(next); - np->rx_skbuff[i] = 0; + rp->rx_ring[i].next_desc = cpu_to_le32(next); + rp->rx_skbuff[i] = 0; } /* Mark the last entry as wrapping the ring. */ - np->rx_ring[i-1].next_desc = cpu_to_le32(np->rx_ring_dma); + rp->rx_ring[i-1].next_desc = cpu_to_le32(rp->rx_ring_dma); /* Fill in the Rx buffers. Handle allocation failure gracefully. */ for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz); - np->rx_skbuff[i] = skb; + struct sk_buff *skb = dev_alloc_skb(rp->rx_buf_sz); + rp->rx_skbuff[i] = skb; if (skb == NULL) break; skb->dev = dev; /* Mark as being used by this device. */ - np->rx_skbuff_dma[i] = - pci_map_single(np->pdev, skb->tail, np->rx_buf_sz, - PCI_DMA_FROMDEVICE); + rp->rx_skbuff_dma[i] = + pci_map_single(rp->pdev, skb->tail, rp->rx_buf_sz, + PCI_DMA_FROMDEVICE); - np->rx_ring[i].addr = cpu_to_le32(np->rx_skbuff_dma[i]); - np->rx_ring[i].rx_status = cpu_to_le32(DescOwn); + rp->rx_ring[i].addr = cpu_to_le32(rp->rx_skbuff_dma[i]); + rp->rx_ring[i].rx_status = cpu_to_le32(DescOwn); } - np->dirty_rx = (unsigned int)(i - RX_RING_SIZE); + rp->dirty_rx = (unsigned int)(i - RX_RING_SIZE); } static void free_rbufs(struct net_device* dev) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); int i; /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { - np->rx_ring[i].rx_status = 0; - np->rx_ring[i].addr = cpu_to_le32(0xBADF00D0); /* An invalid address. */ - if (np->rx_skbuff[i]) { - pci_unmap_single(np->pdev, - np->rx_skbuff_dma[i], - np->rx_buf_sz, PCI_DMA_FROMDEVICE); - dev_kfree_skb(np->rx_skbuff[i]); + rp->rx_ring[i].rx_status = 0; + rp->rx_ring[i].addr = cpu_to_le32(0xBADF00D0); /* An invalid address. */ + if (rp->rx_skbuff[i]) { + pci_unmap_single(rp->pdev, + rp->rx_skbuff_dma[i], + rp->rx_buf_sz, PCI_DMA_FROMDEVICE); + dev_kfree_skb(rp->rx_skbuff[i]); } - np->rx_skbuff[i] = 0; + rp->rx_skbuff[i] = 0; } } static void alloc_tbufs(struct net_device* dev) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); dma_addr_t next; int i; - np->dirty_tx = np->cur_tx = 0; - next = np->tx_ring_dma; + rp->dirty_tx = rp->cur_tx = 0; + next = rp->tx_ring_dma; for (i = 0; i < TX_RING_SIZE; i++) { - np->tx_skbuff[i] = 0; - np->tx_ring[i].tx_status = 0; - np->tx_ring[i].desc_length = cpu_to_le32(TXDESC); + rp->tx_skbuff[i] = 0; + rp->tx_ring[i].tx_status = 0; + rp->tx_ring[i].desc_length = cpu_to_le32(TXDESC); next += sizeof(struct tx_desc); - np->tx_ring[i].next_desc = cpu_to_le32(next); - np->tx_buf[i] = &np->tx_bufs[i * PKT_BUF_SZ]; + rp->tx_ring[i].next_desc = cpu_to_le32(next); + rp->tx_buf[i] = &rp->tx_bufs[i * PKT_BUF_SZ]; } - np->tx_ring[i-1].next_desc = cpu_to_le32(np->tx_ring_dma); + rp->tx_ring[i-1].next_desc = cpu_to_le32(rp->tx_ring_dma); } static void free_tbufs(struct net_device* dev) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); int i; for (i = 0; i < TX_RING_SIZE; i++) { - np->tx_ring[i].tx_status = 0; - np->tx_ring[i].desc_length = cpu_to_le32(TXDESC); - np->tx_ring[i].addr = cpu_to_le32(0xBADF00D0); /* An invalid address. */ - if (np->tx_skbuff[i]) { - if (np->tx_skbuff_dma[i]) { - pci_unmap_single(np->pdev, - np->tx_skbuff_dma[i], - np->tx_skbuff[i]->len, PCI_DMA_TODEVICE); + rp->tx_ring[i].tx_status = 0; + rp->tx_ring[i].desc_length = cpu_to_le32(TXDESC); + rp->tx_ring[i].addr = cpu_to_le32(0xBADF00D0); /* An invalid address. */ + if (rp->tx_skbuff[i]) { + if (rp->tx_skbuff_dma[i]) { + pci_unmap_single(rp->pdev, + rp->tx_skbuff_dma[i], + rp->tx_skbuff[i]->len, + PCI_DMA_TODEVICE); } - dev_kfree_skb(np->tx_skbuff[i]); + dev_kfree_skb(rp->tx_skbuff[i]); } - np->tx_skbuff[i] = 0; - np->tx_buf[i] = 0; + rp->tx_skbuff[i] = 0; + rp->tx_buf[i] = 0; } } static void init_registers(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); long ioaddr = dev->base_addr; int i; @@ -1054,38 +1059,39 @@ writew(0x0006, ioaddr + PCIBusConfig); /* Tune configuration??? */ /* Configure initial FIFO thresholds. */ writeb(0x20, ioaddr + TxConfig); - np->tx_thresh = 0x20; - np->rx_thresh = 0x60; /* Written in via_rhine_set_rx_mode(). */ - np->mii_if.full_duplex = 0; + rp->tx_thresh = 0x20; + rp->rx_thresh = 0x60; /* Written in rhine_set_rx_mode(). */ + rp->mii_if.full_duplex = 0; if (dev->if_port == 0) - dev->if_port = np->default_port; + dev->if_port = rp->default_port; - writel(np->rx_ring_dma, ioaddr + RxRingPtr); - writel(np->tx_ring_dma, ioaddr + TxRingPtr); + writel(rp->rx_ring_dma, ioaddr + RxRingPtr); + writel(rp->tx_ring_dma, ioaddr + TxRingPtr); - via_rhine_set_rx_mode(dev); + rhine_set_rx_mode(dev); /* Enable interrupts by setting the interrupt mask. */ writew(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow | - IntrRxDropped | IntrRxNoBuf | IntrTxAborted | - IntrTxDone | IntrTxError | IntrTxUnderrun | - IntrPCIErr | IntrStatsMax | IntrLinkChange, - ioaddr + IntrEnable); - - np->chip_cmd = CmdStart|CmdTxOn|CmdRxOn|CmdNoTxPoll; - if (np->mii_if.force_media) - np->chip_cmd |= CmdFDuplex; - writew(np->chip_cmd, ioaddr + ChipCmd); + IntrRxDropped | IntrRxNoBuf | IntrTxAborted | + IntrTxDone | IntrTxError | IntrTxUnderrun | + IntrPCIErr | IntrStatsMax | IntrLinkChange, + ioaddr + IntrEnable); + + rp->chip_cmd = CmdStart|CmdTxOn|CmdRxOn|CmdNoTxPoll; + if (rp->mii_if.force_media) + rp->chip_cmd |= CmdFDuplex; + writew(rp->chip_cmd, ioaddr + ChipCmd); - via_rhine_check_duplex(dev); + rhine_check_duplex(dev); - /* The LED outputs of various MII xcvrs should be configured. */ + /* The LED outputs of various MII xcvrs should be configured. */ /* For NS or Mison phys, turn on bit 1 in register 0x17 */ /* For ESI phys, turn on bit 7 in register 0x17. */ - mdio_write(dev, np->phys[0], 0x17, mdio_read(dev, np->phys[0], 0x17) | - (np->drv_flags & HasESIPhy) ? 0x0080 : 0x0001); + mdio_write(dev, rp->phys[0], 0x17, mdio_read(dev, rp->phys[0], 0x17) | + (rp->drv_flags & HasESIPhy) ? 0x0080 : 0x0001); } + /* Read and write over the MII Management Data I/O (MDIO) interface. */ static int mdio_read(struct net_device *dev, int phy_id, int regnum) @@ -1099,7 +1105,7 @@ writeb(0x00, ioaddr + MIICmd); writeb(phy_id, ioaddr + MIIPhyAddr); writeb(regnum, ioaddr + MIIRegAddr); - writeb(0x40, ioaddr + MIICmd); /* Trigger read */ + writeb(0x40, ioaddr + MIICmd); /* Trigger read */ boguscnt = 1024; while ((readb(ioaddr + MIICmd) & 0x40) && --boguscnt > 0) ; @@ -1108,20 +1114,20 @@ static void mdio_write(struct net_device *dev, int phy_id, int regnum, int value) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); long ioaddr = dev->base_addr; int boguscnt = 1024; - if (phy_id == np->phys[0]) { + if (phy_id == rp->phys[0]) { switch (regnum) { - case MII_BMCR: /* Is user forcing speed/duplex? */ - if (value & 0x9000) /* Autonegotiation. */ - np->mii_if.force_media = 0; + case MII_BMCR: /* Is user forcing speed/duplex? */ + if (value & 0x9000) /* Autonegotiation. */ + rp->mii_if.force_media = 0; else - np->mii_if.full_duplex = (value & 0x0100) ? 1 : 0; + rp->mii_if.full_duplex = (value & 0x0100) ? 1 : 0; break; case MII_ADVERTISE: - np->mii_if.advertising = value; + rp->mii_if.advertising = value; break; } } @@ -1133,128 +1139,130 @@ writeb(phy_id, ioaddr + MIIPhyAddr); writeb(regnum, ioaddr + MIIRegAddr); writew(value, ioaddr + MIIData); - writeb(0x20, ioaddr + MIICmd); /* Trigger write. */ + writeb(0x20, ioaddr + MIICmd); /* Trigger write. */ } -static int via_rhine_open(struct net_device *dev) +static int rhine_open(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); long ioaddr = dev->base_addr; int i; /* Reset the chip. */ writew(CmdReset, ioaddr + ChipCmd); - i = request_irq(np->pdev->irq, &via_rhine_interrupt, SA_SHIRQ, dev->name, dev); + i = request_irq(rp->pdev->irq, &rhine_interrupt, SA_SHIRQ, dev->name, + dev); if (i) return i; if (debug > 1) - printk(KERN_DEBUG "%s: via_rhine_open() irq %d.\n", - dev->name, np->pdev->irq); + printk(KERN_DEBUG "%s: rhine_open() irq %d.\n", + dev->name, rp->pdev->irq); i = alloc_ring(dev); if (i) return i; alloc_rbufs(dev); alloc_tbufs(dev); - wait_for_reset(dev, np->chip_id, dev->name); + wait_for_reset(dev, rp->chip_id, dev->name); init_registers(dev); if (debug > 2) - printk(KERN_DEBUG "%s: Done via_rhine_open(), status %4.4x " - "MII status: %4.4x.\n", - dev->name, readw(ioaddr + ChipCmd), - mdio_read(dev, np->phys[0], MII_BMSR)); + printk(KERN_DEBUG "%s: Done rhine_open(), status %4.4x " + "MII status: %4.4x.\n", + dev->name, readw(ioaddr + ChipCmd), + mdio_read(dev, rp->phys[0], MII_BMSR)); netif_start_queue(dev); /* Set the timer to check for link beat. */ - init_timer(&np->timer); - np->timer.expires = jiffies + 2 * HZ/100; - np->timer.data = (unsigned long)dev; - np->timer.function = &via_rhine_timer; /* timer handler */ - add_timer(&np->timer); + init_timer(&rp->timer); + rp->timer.expires = jiffies + 2 * HZ/100; + rp->timer.data = (unsigned long)dev; + rp->timer.function = &rhine_timer; /* timer handler */ + add_timer(&rp->timer); return 0; } -static void via_rhine_check_duplex(struct net_device *dev) +static void rhine_check_duplex(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); long ioaddr = dev->base_addr; - int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA); - int negotiated = mii_lpa & np->mii_if.advertising; + int mii_lpa = mdio_read(dev, rp->phys[0], MII_LPA); + int negotiated = mii_lpa & rp->mii_if.advertising; int duplex; - if (np->mii_if.force_media || mii_lpa == 0xffff) + if (rp->mii_if.force_media || mii_lpa == 0xffff) return; duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040; - if (np->mii_if.full_duplex != duplex) { - np->mii_if.full_duplex = duplex; + if (rp->mii_if.full_duplex != duplex) { + rp->mii_if.full_duplex = duplex; if (debug) - printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link" - " partner capability of %4.4x.\n", dev->name, - duplex ? "full" : "half", np->phys[0], mii_lpa); + printk(KERN_INFO "%s: Setting %s-duplex based on " + "MII #%d link partner capability of %4.4x.\n", + dev->name, duplex ? "full" : "half", + rp->phys[0], mii_lpa); if (duplex) - np->chip_cmd |= CmdFDuplex; + rp->chip_cmd |= CmdFDuplex; else - np->chip_cmd &= ~CmdFDuplex; - writew(np->chip_cmd, ioaddr + ChipCmd); + rp->chip_cmd &= ~CmdFDuplex; + writew(rp->chip_cmd, ioaddr + ChipCmd); } } -static void via_rhine_timer(unsigned long data) +static void rhine_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); long ioaddr = dev->base_addr; int next_tick = 10*HZ; int mii_status; if (debug > 3) { printk(KERN_DEBUG "%s: VIA Rhine monitor tick, status %4.4x.\n", - dev->name, readw(ioaddr + IntrStatus)); + dev->name, readw(ioaddr + IntrStatus)); } - spin_lock_irq (&np->lock); + spin_lock_irq (&rp->lock); - via_rhine_check_duplex(dev); + rhine_check_duplex(dev); /* make IFF_RUNNING follow the MII status bit "Link established" */ - mii_status = mdio_read(dev, np->phys[0], MII_BMSR); - if ( (mii_status & BMSR_LSTATUS) != (np->mii_status & BMSR_LSTATUS) ) { + mii_status = mdio_read(dev, rp->phys[0], MII_BMSR); + if ((mii_status & BMSR_LSTATUS) != (rp->mii_status & BMSR_LSTATUS)) { if (mii_status & BMSR_LSTATUS) netif_carrier_on(dev); else netif_carrier_off(dev); } - np->mii_status = mii_status; + rp->mii_status = mii_status; - spin_unlock_irq (&np->lock); + spin_unlock_irq(&rp->lock); - np->timer.expires = jiffies + next_tick; - add_timer(&np->timer); + rp->timer.expires = jiffies + next_tick; + add_timer(&rp->timer); } -static void via_rhine_tx_timeout (struct net_device *dev) +static void rhine_tx_timeout(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); long ioaddr = dev->base_addr; - printk (KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status " - "%4.4x, resetting...\n", - dev->name, readw (ioaddr + IntrStatus), - mdio_read (dev, np->phys[0], MII_BMSR)); + printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status " + "%4.4x, resetting...\n", + dev->name, readw(ioaddr + IntrStatus), + mdio_read(dev, rp->phys[0], MII_BMSR)); dev->if_port = 0; /* protect against concurrent rx interrupts */ - disable_irq(np->pdev->irq); + disable_irq(rp->pdev->irq); - spin_lock(&np->lock); + spin_lock(&rp->lock); /* Reset the chip. */ writew(CmdReset, ioaddr + ChipCmd); @@ -1266,20 +1274,20 @@ alloc_rbufs(dev); /* Reinitialize the hardware. */ - wait_for_reset(dev, np->chip_id, dev->name); + wait_for_reset(dev, rp->chip_id, dev->name); init_registers(dev); - spin_unlock(&np->lock); - enable_irq(np->pdev->irq); + spin_unlock(&rp->lock); + enable_irq(rp->pdev->irq); dev->trans_start = jiffies; - np->stats.tx_errors++; + rp->stats.tx_errors++; netif_wake_queue(dev); } -static int via_rhine_start_tx(struct sk_buff *skb, struct net_device *dev) +static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); unsigned entry; u32 intr_status; @@ -1287,7 +1295,7 @@ with the "ownership" bits last. */ /* Calculate the next Tx descriptor entry. */ - entry = np->cur_tx % TX_RING_SIZE; + entry = rp->cur_tx % TX_RING_SIZE; if (skb->len < ETH_ZLEN) { skb = skb_padto(skb, ETH_ZLEN); @@ -1295,39 +1303,40 @@ return 0; } - np->tx_skbuff[entry] = skb; + rp->tx_skbuff[entry] = skb; - if ((np->drv_flags & ReqTxAlign) && - (((long)skb->data & 3) || skb_shinfo(skb)->nr_frags != 0 || skb->ip_summed == CHECKSUM_HW) - ) { + if ((rp->drv_flags & ReqTxAlign) && + (((long)skb->data & 3) || skb_shinfo(skb)->nr_frags != 0 || skb->ip_summed == CHECKSUM_HW)) { /* Must use alignment buffer. */ if (skb->len > PKT_BUF_SZ) { /* packet too long, drop it */ dev_kfree_skb(skb); - np->tx_skbuff[entry] = NULL; - np->stats.tx_dropped++; + rp->tx_skbuff[entry] = NULL; + rp->stats.tx_dropped++; return 0; } - skb_copy_and_csum_dev(skb, np->tx_buf[entry]); - np->tx_skbuff_dma[entry] = 0; - np->tx_ring[entry].addr = cpu_to_le32(np->tx_bufs_dma + - (np->tx_buf[entry] - np->tx_bufs)); + skb_copy_and_csum_dev(skb, rp->tx_buf[entry]); + rp->tx_skbuff_dma[entry] = 0; + rp->tx_ring[entry].addr = cpu_to_le32(rp->tx_bufs_dma + + (rp->tx_buf[entry] - + rp->tx_bufs)); } else { - np->tx_skbuff_dma[entry] = - pci_map_single(np->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); - np->tx_ring[entry].addr = cpu_to_le32(np->tx_skbuff_dma[entry]); + rp->tx_skbuff_dma[entry] = + pci_map_single(rp->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + rp->tx_ring[entry].addr = cpu_to_le32(rp->tx_skbuff_dma[entry]); } - np->tx_ring[entry].desc_length = + rp->tx_ring[entry].desc_length = cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); /* lock eth irq */ - spin_lock_irq (&np->lock); + spin_lock_irq(&rp->lock); wmb(); - np->tx_ring[entry].tx_status = cpu_to_le32(DescOwn); + rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn); wmb(); - np->cur_tx++; + rp->cur_tx++; /* Non-x86 Todo: explicitly flush cache lines here. */ @@ -1337,27 +1346,27 @@ */ intr_status = get_intr_status(dev); if ((intr_status & IntrTxErrSummary) == 0) { - writew(CmdTxDemand | np->chip_cmd, dev->base_addr + ChipCmd); + writew(CmdTxDemand | rp->chip_cmd, dev->base_addr + ChipCmd); } IOSYNC; - if (np->cur_tx == np->dirty_tx + TX_QUEUE_LEN) + if (rp->cur_tx == rp->dirty_tx + TX_QUEUE_LEN) netif_stop_queue(dev); dev->trans_start = jiffies; - spin_unlock_irq (&np->lock); + spin_unlock_irq(&rp->lock); if (debug > 4) { printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n", - dev->name, np->cur_tx-1, entry); + dev->name, rp->cur_tx-1, entry); } return 0; } /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ -static irqreturn_t via_rhine_interrupt(int irq, void *dev_instance, struct pt_regs *rgs) +static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *rgs) { struct net_device *dev = dev_instance; long ioaddr; @@ -1378,11 +1387,11 @@ if (debug > 4) printk(KERN_DEBUG "%s: Interrupt, status %8.8x.\n", - dev->name, intr_status); + dev->name, intr_status); if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped | - IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) - via_rhine_rx(dev); + IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) + rhine_rx(dev); if (intr_status & (IntrTxErrSummary | IntrTxDone)) { if (intr_status & IntrTxErrSummary) { @@ -1391,140 +1400,147 @@ while ((readw(ioaddr+ChipCmd) & CmdTxOn) && --cnt) udelay(5); if (debug > 2 && !cnt) - printk(KERN_WARNING "%s: via_rhine_interrupt() " - "Tx engine still on.\n", - dev->name); + printk(KERN_WARNING "%s: " + "rhine_interrupt() Tx engine" + "still on.\n", dev->name); } - via_rhine_tx(dev); + rhine_tx(dev); } /* Abnormal error summary/uncommon events handlers. */ if (intr_status & (IntrPCIErr | IntrLinkChange | IntrStatsMax | IntrTxError | IntrTxAborted | IntrTxUnderrun | IntrTxDescRace)) - via_rhine_error(dev, intr_status); + rhine_error(dev, intr_status); if (--boguscnt < 0) { printk(KERN_WARNING "%s: Too much work at interrupt, " - "status=%#8.8x.\n", - dev->name, intr_status); + "status=%#8.8x.\n", + dev->name, intr_status); break; } } if (debug > 3) printk(KERN_DEBUG "%s: exiting interrupt, status=%8.8x.\n", - dev->name, readw(ioaddr + IntrStatus)); + dev->name, readw(ioaddr + IntrStatus)); return IRQ_RETVAL(handled); } /* This routine is logically part of the interrupt handler, but isolated for clarity. */ -static void via_rhine_tx(struct net_device *dev) +static void rhine_tx(struct net_device *dev) { - struct netdev_private *np = dev->priv; - int txstatus = 0, entry = np->dirty_tx % TX_RING_SIZE; + struct rhine_private *rp = netdev_priv(dev); + int txstatus = 0, entry = rp->dirty_tx % TX_RING_SIZE; - spin_lock (&np->lock); + spin_lock(&rp->lock); /* find and cleanup dirty tx descriptors */ - while (np->dirty_tx != np->cur_tx) { - txstatus = le32_to_cpu(np->tx_ring[entry].tx_status); + while (rp->dirty_tx != rp->cur_tx) { + txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status); if (debug > 6) printk(KERN_DEBUG " Tx scavenge %d status %8.8x.\n", - entry, txstatus); + entry, txstatus); if (txstatus & DescOwn) break; if (txstatus & 0x8000) { if (debug > 1) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); - np->stats.tx_errors++; - if (txstatus & 0x0400) np->stats.tx_carrier_errors++; - if (txstatus & 0x0200) np->stats.tx_window_errors++; - if (txstatus & 0x0100) np->stats.tx_aborted_errors++; - if (txstatus & 0x0080) np->stats.tx_heartbeat_errors++; - if (((np->chip_id == VT86C100A) && txstatus & 0x0002) || - (txstatus & 0x0800) || (txstatus & 0x1000)) { - np->stats.tx_fifo_errors++; - np->tx_ring[entry].tx_status = cpu_to_le32(DescOwn); + printk(KERN_DEBUG "%s: Transmit error, " + "Tx status %8.8x.\n", + dev->name, txstatus); + rp->stats.tx_errors++; + if (txstatus & 0x0400) rp->stats.tx_carrier_errors++; + if (txstatus & 0x0200) rp->stats.tx_window_errors++; + if (txstatus & 0x0100) rp->stats.tx_aborted_errors++; + if (txstatus & 0x0080) rp->stats.tx_heartbeat_errors++; + if (((rp->chip_id == VT86C100A) && txstatus & 0x0002) || + (txstatus & 0x0800) || (txstatus & 0x1000)) { + rp->stats.tx_fifo_errors++; + rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn); break; /* Keep the skb - we try again */ } /* Transmitter restarted in 'abnormal' handler. */ } else { - if (np->chip_id == VT86C100A) - np->stats.collisions += (txstatus >> 3) & 0x0F; + if (rp->chip_id == VT86C100A) + rp->stats.collisions += (txstatus >> 3) & 0x0F; else - np->stats.collisions += txstatus & 0x0F; + rp->stats.collisions += txstatus & 0x0F; if (debug > 6) printk(KERN_DEBUG "collisions: %1.1x:%1.1x\n", - (txstatus >> 3) & 0xF, - txstatus & 0xF); - np->stats.tx_bytes += np->tx_skbuff[entry]->len; - np->stats.tx_packets++; + (txstatus >> 3) & 0xF, + txstatus & 0xF); + rp->stats.tx_bytes += rp->tx_skbuff[entry]->len; + rp->stats.tx_packets++; } /* Free the original skb. */ - if (np->tx_skbuff_dma[entry]) { - pci_unmap_single(np->pdev, - np->tx_skbuff_dma[entry], - np->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); + if (rp->tx_skbuff_dma[entry]) { + pci_unmap_single(rp->pdev, + rp->tx_skbuff_dma[entry], + rp->tx_skbuff[entry]->len, + PCI_DMA_TODEVICE); } - dev_kfree_skb_irq(np->tx_skbuff[entry]); - np->tx_skbuff[entry] = NULL; - entry = (++np->dirty_tx) % TX_RING_SIZE; + dev_kfree_skb_irq(rp->tx_skbuff[entry]); + rp->tx_skbuff[entry] = NULL; + entry = (++rp->dirty_tx) % TX_RING_SIZE; } - if ((np->cur_tx - np->dirty_tx) < TX_QUEUE_LEN - 4) - netif_wake_queue (dev); + if ((rp->cur_tx - rp->dirty_tx) < TX_QUEUE_LEN - 4) + netif_wake_queue(dev); - spin_unlock (&np->lock); + spin_unlock(&rp->lock); } /* This routine is logically part of the interrupt handler, but isolated for clarity and better register allocation. */ -static void via_rhine_rx(struct net_device *dev) +static void rhine_rx(struct net_device *dev) { - struct netdev_private *np = dev->priv; - int entry = np->cur_rx % RX_RING_SIZE; - int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx; + struct rhine_private *rp = netdev_priv(dev); + int entry = rp->cur_rx % RX_RING_SIZE; + int boguscnt = rp->dirty_rx + RX_RING_SIZE - rp->cur_rx; if (debug > 4) { - printk(KERN_DEBUG "%s: via_rhine_rx(), entry %d status %8.8x.\n", - dev->name, entry, le32_to_cpu(np->rx_head_desc->rx_status)); + printk(KERN_DEBUG "%s: rhine_rx(), entry %d status %8.8x.\n", + dev->name, entry, + le32_to_cpu(rp->rx_head_desc->rx_status)); } /* If EOP is set on the next entry, it's a new packet. Send it up. */ - while ( ! (np->rx_head_desc->rx_status & cpu_to_le32(DescOwn))) { - struct rx_desc *desc = np->rx_head_desc; + while (!(rp->rx_head_desc->rx_status & cpu_to_le32(DescOwn))) { + struct rx_desc *desc = rp->rx_head_desc; u32 desc_status = le32_to_cpu(desc->rx_status); int data_size = desc_status >> 16; if (debug > 4) - printk(KERN_DEBUG " via_rhine_rx() status is %8.8x.\n", - desc_status); + printk(KERN_DEBUG " rhine_rx() status is %8.8x.\n", + desc_status); if (--boguscnt < 0) break; - if ( (desc_status & (RxWholePkt | RxErr)) != RxWholePkt) { - if ((desc_status & RxWholePkt) != RxWholePkt) { - printk(KERN_WARNING "%s: Oversized Ethernet frame spanned " - "multiple buffers, entry %#x length %d status %8.8x!\n", - dev->name, entry, data_size, desc_status); - printk(KERN_WARNING "%s: Oversized Ethernet frame %p vs %p.\n", - dev->name, np->rx_head_desc, &np->rx_ring[entry]); - np->stats.rx_length_errors++; + if ((desc_status & (RxWholePkt | RxErr)) != RxWholePkt) { + if ((desc_status & RxWholePkt) != RxWholePkt) { + printk(KERN_WARNING "%s: Oversized Ethernet " + "frame spanned multiple buffers, entry " + "%#x length %d status %8.8x!\n", + dev->name, entry, data_size, + desc_status); + printk(KERN_WARNING "%s: Oversized Ethernet " + "frame %p vs %p.\n", dev->name, + rp->rx_head_desc, &rp->rx_ring[entry]); + rp->stats.rx_length_errors++; } else if (desc_status & RxErr) { /* There was a error. */ if (debug > 2) - printk(KERN_DEBUG " via_rhine_rx() Rx error was %8.8x.\n", - desc_status); - np->stats.rx_errors++; - if (desc_status & 0x0030) np->stats.rx_length_errors++; - if (desc_status & 0x0048) np->stats.rx_fifo_errors++; - if (desc_status & 0x0004) np->stats.rx_frame_errors++; + printk(KERN_DEBUG " rhine_rx() Rx " + "error was %8.8x.\n", + desc_status); + rp->stats.rx_errors++; + if (desc_status & 0x0030) rp->stats.rx_length_errors++; + if (desc_status & 0x0048) rp->stats.rx_fifo_errors++; + if (desc_status & 0x0004) rp->stats.rx_frame_errors++; if (desc_status & 0x0002) { /* this can also be updated outside the interrupt handler */ - spin_lock (&np->lock); - np->stats.rx_crc_errors++; - spin_unlock (&np->lock); + spin_lock(&rp->lock); + rp->stats.rx_crc_errors++; + spin_unlock(&rp->lock); } } } else { @@ -1532,76 +1548,89 @@ /* Length should omit the CRC */ int pkt_len = data_size - 4; - /* Check if the packet is long enough to accept without copying - to a minimally-sized skbuff. */ + /* Check if the packet is long enough to accept without + copying to a minimally-sized skbuff. */ if (pkt_len < rx_copybreak && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { skb->dev = dev; skb_reserve(skb, 2); /* 16 byte align the IP header */ - pci_dma_sync_single_for_cpu(np->pdev, np->rx_skbuff_dma[entry], - np->rx_buf_sz, PCI_DMA_FROMDEVICE); - - /* *_IP_COPYSUM isn't defined anywhere and eth_copy_and_sum - is memcpy for all archs so this is kind of pointless right - now ... or? */ -#if HAS_IP_COPYSUM /* Call copy + cksum if available. */ - eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0); + pci_dma_sync_single_for_cpu(rp->pdev, + rp->rx_skbuff_dma[entry], + rp->rx_buf_sz, + PCI_DMA_FROMDEVICE); + + /* *_IP_COPYSUM isn't defined anywhere and + eth_copy_and_sum is memcpy for all archs so + this is kind of pointless right now + ... or? */ +#if HAS_IP_COPYSUM /* Call copy + cksum if available. */ + eth_copy_and_sum(skb, + rp->rx_skbuff[entry]->tail, + pkt_len, 0); skb_put(skb, pkt_len); #else - memcpy(skb_put(skb, pkt_len), np->rx_skbuff[entry]->tail, - pkt_len); + memcpy(skb_put(skb, pkt_len), + rp->rx_skbuff[entry]->tail, pkt_len); #endif - pci_dma_sync_single_for_device(np->pdev, np->rx_skbuff_dma[entry], - np->rx_buf_sz, PCI_DMA_FROMDEVICE); + pci_dma_sync_single_for_device(rp->pdev, + rp->rx_skbuff_dma[entry], + rp->rx_buf_sz, + PCI_DMA_FROMDEVICE); } else { - skb = np->rx_skbuff[entry]; + skb = rp->rx_skbuff[entry]; if (skb == NULL) { - printk(KERN_ERR "%s: Inconsistent Rx descriptor chain.\n", - dev->name); + printk(KERN_ERR "%s: Inconsistent Rx " + "descriptor chain.\n", + dev->name); break; } - np->rx_skbuff[entry] = NULL; + rp->rx_skbuff[entry] = NULL; skb_put(skb, pkt_len); - pci_unmap_single(np->pdev, np->rx_skbuff_dma[entry], - np->rx_buf_sz, PCI_DMA_FROMDEVICE); + pci_unmap_single(rp->pdev, + rp->rx_skbuff_dma[entry], + rp->rx_buf_sz, + PCI_DMA_FROMDEVICE); } skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; - np->stats.rx_bytes += pkt_len; - np->stats.rx_packets++; + rp->stats.rx_bytes += pkt_len; + rp->stats.rx_packets++; } - entry = (++np->cur_rx) % RX_RING_SIZE; - np->rx_head_desc = &np->rx_ring[entry]; + entry = (++rp->cur_rx) % RX_RING_SIZE; + rp->rx_head_desc = &rp->rx_ring[entry]; } /* Refill the Rx ring buffers. */ - for (; np->cur_rx - np->dirty_rx > 0; np->dirty_rx++) { + for (; rp->cur_rx - rp->dirty_rx > 0; rp->dirty_rx++) { struct sk_buff *skb; - entry = np->dirty_rx % RX_RING_SIZE; - if (np->rx_skbuff[entry] == NULL) { - skb = dev_alloc_skb(np->rx_buf_sz); - np->rx_skbuff[entry] = skb; + entry = rp->dirty_rx % RX_RING_SIZE; + if (rp->rx_skbuff[entry] == NULL) { + skb = dev_alloc_skb(rp->rx_buf_sz); + rp->rx_skbuff[entry] = skb; if (skb == NULL) - break; /* Better luck next round. */ - skb->dev = dev; /* Mark as being used by this device. */ - np->rx_skbuff_dma[entry] = - pci_map_single(np->pdev, skb->tail, np->rx_buf_sz, - PCI_DMA_FROMDEVICE); - np->rx_ring[entry].addr = cpu_to_le32(np->rx_skbuff_dma[entry]); + break; /* Better luck next round. */ + skb->dev = dev; /* Mark as being used by this device. */ + rp->rx_skbuff_dma[entry] = + pci_map_single(rp->pdev, skb->tail, + rp->rx_buf_sz, + PCI_DMA_FROMDEVICE); + rp->rx_ring[entry].addr = cpu_to_le32(rp->rx_skbuff_dma[entry]); } - np->rx_ring[entry].rx_status = cpu_to_le32(DescOwn); + rp->rx_ring[entry].rx_status = cpu_to_le32(DescOwn); } /* Pre-emptively restart Rx engine. */ writew(readw(dev->base_addr + ChipCmd) | CmdRxOn | CmdRxDemand, - dev->base_addr + ChipCmd); + dev->base_addr + ChipCmd); } -/* Clears the "tally counters" for CRC errors and missed frames(?). - It has been reported that some chips need a write of 0 to clear - these, for others the counters are set to 1 when written to and - instead cleared when read. So we clear them both ways ... */ +/* + * Clears the "tally counters" for CRC errors and missed frames(?). + * It has been reported that some chips need a write of 0 to clear + * these, for others the counters are set to 1 when written to and + * instead cleared when read. So we clear them both ways ... + */ static inline void clear_tally_counters(const long ioaddr) { writel(0, ioaddr + RxMissed); @@ -1609,10 +1638,10 @@ readw(ioaddr + RxMissed); } -static void via_rhine_restart_tx(struct net_device *dev) { - struct netdev_private *np = dev->priv; +static void rhine_restart_tx(struct net_device *dev) { + struct rhine_private *rp = netdev_priv(dev); long ioaddr = dev->base_addr; - int entry = np->dirty_tx % TX_RING_SIZE; + int entry = rp->dirty_tx % TX_RING_SIZE; u32 intr_status; /* @@ -1624,120 +1653,123 @@ if ((intr_status & IntrTxErrSummary) == 0) { /* We know better than the chip where it should continue. */ - writel(np->tx_ring_dma + entry * sizeof(struct tx_desc), - ioaddr + TxRingPtr); + writel(rp->tx_ring_dma + entry * sizeof(struct tx_desc), + ioaddr + TxRingPtr); - writew(CmdTxDemand | np->chip_cmd, ioaddr + ChipCmd); + writew(CmdTxDemand | rp->chip_cmd, ioaddr + ChipCmd); IOSYNC; } else { /* This should never happen */ if (debug > 1) - printk(KERN_WARNING "%s: via_rhine_restart_tx() " - "Another error occured %8.8x.\n", - dev->name, intr_status); + printk(KERN_WARNING "%s: rhine_restart_tx() " + "Another error occured %8.8x.\n", + dev->name, intr_status); } } -static void via_rhine_error(struct net_device *dev, int intr_status) +static void rhine_error(struct net_device *dev, int intr_status) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); long ioaddr = dev->base_addr; - spin_lock (&np->lock); + spin_lock(&rp->lock); if (intr_status & (IntrLinkChange)) { if (readb(ioaddr + MIIStatus) & 0x02) { /* Link failed, restart autonegotiation. */ - if (np->drv_flags & HasDavicomPhy) - mdio_write(dev, np->phys[0], MII_BMCR, 0x3300); + if (rp->drv_flags & HasDavicomPhy) + mdio_write(dev, rp->phys[0], MII_BMCR, 0x3300); } else - via_rhine_check_duplex(dev); + rhine_check_duplex(dev); if (debug) - printk(KERN_ERR "%s: MII status changed: Autonegotiation " - "advertising %4.4x partner %4.4x.\n", dev->name, - mdio_read(dev, np->phys[0], MII_ADVERTISE), - mdio_read(dev, np->phys[0], MII_LPA)); + printk(KERN_ERR "%s: MII status changed: " + "Autonegotiation advertising %4.4x partner " + "%4.4x.\n", dev->name, + mdio_read(dev, rp->phys[0], MII_ADVERTISE), + mdio_read(dev, rp->phys[0], MII_LPA)); } if (intr_status & IntrStatsMax) { - np->stats.rx_crc_errors += readw(ioaddr + RxCRCErrs); - np->stats.rx_missed_errors += readw(ioaddr + RxMissed); + rp->stats.rx_crc_errors += readw(ioaddr + RxCRCErrs); + rp->stats.rx_missed_errors += readw(ioaddr + RxMissed); clear_tally_counters(ioaddr); } if (intr_status & IntrTxAborted) { if (debug > 1) printk(KERN_INFO "%s: Abort %8.8x, frame dropped.\n", - dev->name, intr_status); + dev->name, intr_status); } if (intr_status & IntrTxUnderrun) { - if (np->tx_thresh < 0xE0) - writeb(np->tx_thresh += 0x20, ioaddr + TxConfig); + if (rp->tx_thresh < 0xE0) + writeb(rp->tx_thresh += 0x20, ioaddr + TxConfig); if (debug > 1) printk(KERN_INFO "%s: Transmitter underrun, Tx " - "threshold now %2.2x.\n", - dev->name, np->tx_thresh); + "threshold now %2.2x.\n", + dev->name, rp->tx_thresh); } if (intr_status & IntrTxDescRace) { if (debug > 2) printk(KERN_INFO "%s: Tx descriptor write-back race.\n", - dev->name); + dev->name); } - if ((intr_status & IntrTxError) && ~( IntrTxAborted | IntrTxUnderrun | - IntrTxDescRace )) { - if (np->tx_thresh < 0xE0) { - writeb(np->tx_thresh += 0x20, ioaddr + TxConfig); + if ((intr_status & IntrTxError) && + (intr_status & (IntrTxAborted | + IntrTxUnderrun | IntrTxDescRace)) == 0) { + if (rp->tx_thresh < 0xE0) { + writeb(rp->tx_thresh += 0x20, ioaddr + TxConfig); } if (debug > 1) printk(KERN_INFO "%s: Unspecified error. Tx " - "threshold now %2.2x.\n", - dev->name, np->tx_thresh); + "threshold now %2.2x.\n", + dev->name, rp->tx_thresh); } - if (intr_status & ( IntrTxAborted | IntrTxUnderrun | IntrTxDescRace | - IntrTxError )) - via_rhine_restart_tx(dev); - - if (intr_status & ~( IntrLinkChange | IntrStatsMax | IntrTxUnderrun | - IntrTxError | IntrTxAborted | IntrNormalSummary | - IntrTxDescRace )) { + if (intr_status & (IntrTxAborted | IntrTxUnderrun | IntrTxDescRace | + IntrTxError)) + rhine_restart_tx(dev); + + if (intr_status & ~(IntrLinkChange | IntrStatsMax | IntrTxUnderrun | + IntrTxError | IntrTxAborted | IntrNormalSummary | + IntrTxDescRace)) { if (debug > 1) - printk(KERN_ERR "%s: Something Wicked happened! %8.8x.\n", - dev->name, intr_status); + printk(KERN_ERR "%s: Something Wicked happened! " + "%8.8x.\n", dev->name, intr_status); } - spin_unlock (&np->lock); + spin_unlock(&rp->lock); } -static struct net_device_stats *via_rhine_get_stats(struct net_device *dev) +static struct net_device_stats *rhine_get_stats(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); long ioaddr = dev->base_addr; unsigned long flags; - spin_lock_irqsave(&np->lock, flags); - np->stats.rx_crc_errors += readw(ioaddr + RxCRCErrs); - np->stats.rx_missed_errors += readw(ioaddr + RxMissed); + spin_lock_irqsave(&rp->lock, flags); + rp->stats.rx_crc_errors += readw(ioaddr + RxCRCErrs); + rp->stats.rx_missed_errors += readw(ioaddr + RxMissed); clear_tally_counters(ioaddr); - spin_unlock_irqrestore(&np->lock, flags); + spin_unlock_irqrestore(&rp->lock, flags); - return &np->stats; + return &rp->stats; } -static void via_rhine_set_rx_mode(struct net_device *dev) +static void rhine_set_rx_mode(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); long ioaddr = dev->base_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - u8 rx_mode; /* Note: 0x02=accept runt, 0x01=accept errs */ + u32 mc_filter[2]; /* Multicast hash filter */ + u8 rx_mode; /* Note: 0x02=accept runt, 0x01=accept errs */ - if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ + if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ /* Unconditionally log net taps. */ - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name); + printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", + dev->name); rx_mode = 0x1C; writel(0xffffffff, ioaddr + MulticastFilter0); writel(0xffffffff, ioaddr + MulticastFilter1); } else if ((dev->mc_count > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { + || (dev->flags & IFF_ALLMULTI)) { /* Too many to match, or accept all multicasts. */ writel(0xffffffff, ioaddr + MulticastFilter0); writel(0xffffffff, ioaddr + MulticastFilter1); @@ -1747,7 +1779,7 @@ int i; memset(mc_filter, 0, sizeof(mc_filter)); for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { + i++, mclist = mclist->next) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31)); @@ -1756,66 +1788,66 @@ writel(mc_filter[1], ioaddr + MulticastFilter1); rx_mode = 0x0C; } - writeb(np->rx_thresh | rx_mode, ioaddr + RxConfig); + writeb(rp->rx_thresh | rx_mode, ioaddr + RxConfig); } -static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info) +static void netdev_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); - strcpy (info->driver, DRV_NAME); - strcpy (info->version, DRV_VERSION); - strcpy (info->bus_info, pci_name(np->pdev)); + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(rp->pdev)); } static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); int rc; - if (!(np->drv_flags & CanHaveMII)) + if (!(rp->drv_flags & CanHaveMII)) return -EINVAL; - spin_lock_irq(&np->lock); - rc = mii_ethtool_gset(&np->mii_if, cmd); - spin_unlock_irq(&np->lock); + spin_lock_irq(&rp->lock); + rc = mii_ethtool_gset(&rp->mii_if, cmd); + spin_unlock_irq(&rp->lock); return rc; } static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); int rc; - if (!(np->drv_flags & CanHaveMII)) + if (!(rp->drv_flags & CanHaveMII)) return -EINVAL; - spin_lock_irq(&np->lock); - rc = mii_ethtool_sset(&np->mii_if, cmd); - spin_unlock_irq(&np->lock); + spin_lock_irq(&rp->lock); + rc = mii_ethtool_sset(&rp->mii_if, cmd); + spin_unlock_irq(&rp->lock); return rc; } static int netdev_nway_reset(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); - if (!(np->drv_flags & CanHaveMII)) + if (!(rp->drv_flags & CanHaveMII)) return -EINVAL; - return mii_nway_restart(&np->mii_if); + return mii_nway_restart(&rp->mii_if); } static u32 netdev_get_link(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); - if (!(np->drv_flags & CanHaveMII)) + if (!(rp->drv_flags & CanHaveMII)) return 0; /* -EINVAL */ - return mii_link_ok(&np->mii_if); + return mii_link_ok(&rp->mii_if); } static u32 netdev_get_msglevel(struct net_device *dev) @@ -1842,37 +1874,38 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data; int rc; if (!netif_running(dev)) return -EINVAL; - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii_if, data, cmd, NULL); - spin_unlock_irq(&np->lock); + spin_lock_irq(&rp->lock); + rc = generic_mii_ioctl(&rp->mii_if, data, cmd, NULL); + spin_unlock_irq(&rp->lock); return rc; } -static int via_rhine_close(struct net_device *dev) +static int rhine_close(struct net_device *dev) { long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct rhine_private *rp = netdev_priv(dev); - del_timer_sync(&np->timer); + del_timer_sync(&rp->timer); - spin_lock_irq(&np->lock); + spin_lock_irq(&rp->lock); netif_stop_queue(dev); if (debug > 1) - printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n", - dev->name, readw(ioaddr + ChipCmd)); + printk(KERN_DEBUG "%s: Shutting down ethercard, " + "status was %4.4x.\n", + dev->name, readw(ioaddr + ChipCmd)); /* Switch to loopback mode to avoid hardware races. */ - writeb(np->tx_thresh | 0x02, ioaddr + TxConfig); + writeb(rp->tx_thresh | 0x02, ioaddr + TxConfig); /* Disable interrupts by clearing the interrupt mask. */ writew(0x0000, ioaddr + IntrEnable); @@ -1880,9 +1913,9 @@ /* Stop the chip's Tx and Rx processes. */ writew(CmdStop, ioaddr + ChipCmd); - spin_unlock_irq(&np->lock); + spin_unlock_irq(&rp->lock); - free_irq(np->pdev->irq, dev); + free_irq(rp->pdev->irq, dev); free_rbufs(dev); free_tbufs(dev); free_ring(dev); @@ -1891,7 +1924,7 @@ } -static void __devexit via_rhine_remove_one (struct pci_dev *pdev) +static void __devexit rhine_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); @@ -1899,7 +1932,7 @@ pci_release_regions(pdev); -#ifdef USE_MEM +#ifdef USE_MMIO iounmap((char *)(dev->base_addr)); #endif @@ -1909,39 +1942,29 @@ } -static struct pci_driver via_rhine_driver = { +static struct pci_driver rhine_driver = { .name = "via-rhine", - .id_table = via_rhine_pci_tbl, - .probe = via_rhine_init_one, - .remove = __devexit_p(via_rhine_remove_one), + .id_table = rhine_pci_tbl, + .probe = rhine_init_one, + .remove = __devexit_p(rhine_remove_one), }; -static int __init via_rhine_init (void) +static int __init rhine_init(void) { /* when a module, this is printed whether or not devices are found in probe */ #ifdef MODULE printk(version); #endif - return pci_module_init (&via_rhine_driver); + return pci_module_init(&rhine_driver); } -static void __exit via_rhine_cleanup (void) +static void __exit rhine_cleanup(void) { - pci_unregister_driver (&via_rhine_driver); + pci_unregister_driver(&rhine_driver); } -module_init(via_rhine_init); -module_exit(via_rhine_cleanup); - - -/* - * Local variables: - * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c via-rhine.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" - * c-indent-level: 4 - * c-basic-offset: 4 - * tab-width: 4 - * End: - */ +module_init(rhine_init); +module_exit(rhine_cleanup); --- diff/drivers/net/wireless/prism54/isl_38xx.c 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/net/wireless/prism54/isl_38xx.c 2004-05-27 18:34:17.000000000 +0100 @@ -1,4 +1,4 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/isl_38xx.c,v 1.22 2004/02/28 03:06:07 mcgrof Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/isl_38xx.c,v 1.26 2004/03/20 16:58:36 mcgrof Exp $ * * Copyright (C) 2002 Intersil Americas Inc. * Copyright (C) 2003-2004 Luis R. Rodriguez _ @@ -25,17 +25,11 @@ #include #include -#include "isl_38xx.h" -#include - #include #include -#include -#if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE) -#error No Firmware Loading configured in the kernel ! -#endif - +#include "prismcompat.h" +#include "isl_38xx.h" #include "islpci_dev.h" #include "islpci_mgt.h" --- diff/drivers/net/wireless/prism54/isl_38xx.h 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/net/wireless/prism54/isl_38xx.h 2004-05-27 18:34:17.000000000 +0100 @@ -1,4 +1,4 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/isl_38xx.h,v 1.22 2004/02/28 03:06:07 mcgrof Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/isl_38xx.h,v 1.25 2004/03/20 16:58:36 mcgrof Exp $ * * Copyright (C) 2002 Intersil Americas Inc. * @@ -22,14 +22,6 @@ #include #include - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,75)) -#include -# define _REQ_FW_DEV_T struct device * -#else -# define _REQ_FW_DEV_T char * -#endif - #include #define ISL38XX_CB_RX_QSIZE 8 --- diff/drivers/net/wireless/prism54/isl_ioctl.c 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/net/wireless/prism54/isl_ioctl.c 2004-05-27 18:34:17.000000000 +0100 @@ -1,7 +1,7 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/isl_ioctl.c,v 1.140 2004/02/28 03:06:07 mcgrof Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/isl_ioctl.c,v 1.154 2004/05/20 06:24:11 ajfa Exp $ * * Copyright (C) 2002 Intersil Americas Inc. - * (C) 2003 Aurelien Alleaume + * (C) 2003,2004 Aurelien Alleaume * (C) 2003 Herbert Valerio Riedel * (C) 2003 Luis R. Rodriguez * @@ -25,10 +25,10 @@ #include #include #include -#include #include +#include "prismcompat.h" #include "isl_ioctl.h" #include "islpci_mgt.h" #include "isl_oid.h" /* additional types and defs for isl38xx fw */ @@ -87,9 +87,9 @@ /* For now, just catch early the Repeater and Secondary modes here */ if (iw_mode == IW_MODE_REPEAT || iw_mode == IW_MODE_SECOND) { - printk(KERN_DEBUG "%s(): Sorry, Repeater mode and Secondary mode " - "are not yet supported by this driver.\n", - __FUNCTION__); + printk(KERN_DEBUG + "%s(): Sorry, Repeater mode and Secondary mode " + "are not yet supported by this driver.\n", __FUNCTION__); return -EINVAL; } @@ -143,8 +143,8 @@ { u32 t; struct obj_buffer psm_buffer = { - .size = cpu_to_le32(PSM_BUFFER_SIZE), - .addr = cpu_to_le32(priv->device_psm_buffer) + .size = PSM_BUFFER_SIZE, + .addr = priv->device_psm_buffer }; mgt_set(priv, DOT11_OID_CHANNEL, &init_channel); @@ -166,21 +166,13 @@ * for it save old values */ if (init_mode > IW_MODE_MONITOR || init_mode < IW_MODE_AUTO) { printk(KERN_DEBUG "%s(): You passed a non-valid init_mode. " - "Using default mode\n", __FUNCTION__); + "Using default mode\n", __FUNCTION__); init_mode = CARD_DEFAULT_IW_MODE; } /* This sets all of the mode-dependent values */ prism54_mib_mode_helper(priv, init_mode); } -void -prism54_mib_init_work(islpci_private *priv) -{ - down_write(&priv->mib_sem); - mgt_commit(priv); - up_write(&priv->mib_sem); -} - /* this will be executed outside of atomic context thanks to * schedule_work(), thus we can as well use sleeping semaphore * locking */ @@ -195,16 +187,9 @@ if (down_interruptible(&priv->stats_sem)) return; -/* missing stats are : - * iwstatistics.qual.updated - * iwstatistics.discard.nwid - * iwstatistics.discard.fragment - * iwstatistics.discard.misc - * iwstatistics.miss.beacon */ - /* Noise floor. * I'm not sure if the unit is dBm. - * Note : If we are not connected, this value seems to be irrevelant. */ + * Note : If we are not connected, this value seems to be irrelevant. */ mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r); priv->local_iwstatistics.qual.noise = r.u; @@ -216,8 +201,7 @@ data = r.ptr; /* copy this MAC to the bss */ - for (j = 0; j < 6; j++) - bss.address[j] = data[j]; + memcpy(bss.address, data, 6); kfree(data); /* now ask for the corresponding bss */ @@ -285,7 +269,7 @@ /* Commit in Monitor mode is not necessary, also setting essid * in Monitor mode does not make sense and isn't allowed for this * device's firmware */ - if(priv->iw_mode != IW_MODE_MONITOR) + if (priv->iw_mode != IW_MODE_MONITOR) return mgt_set_request(priv, DOT11_OID_SSID, 0, NULL); return 0; } @@ -327,34 +311,15 @@ { islpci_private *priv = netdev_priv(ndev); int rvalue; - u32 c = 0; + u32 c; - /* prepare the structure for the set object */ if (fwrq->m < 1000) - /* structure value contains a channel indication */ + /* we have a channel number */ c = fwrq->m; - else { - /* structure contains a frequency indication and fwrq->e = 1 */ - int f = fwrq->m / 100000; - - if (fwrq->e != 1) - return -EINVAL; - if ((f >= 2412) && (f <= 2484)) { - while ((c < 14) && (f != frequency_list_bg[c])) - c++; - if (c >= 14) - return -EINVAL; - } else if ((f >= (int) 5170) && (f <= (int) 5320)) { - while ((c < 12) && (f != frequency_list_a[c])) - c++; - if (c >= 12) - return -EINVAL; - } else - return -EINVAL; - c++; - } + else + c = (fwrq->e == 1) ? channel_of_freq(fwrq->m / 100000) : 0; - rvalue = mgt_set_request(priv, DOT11_OID_CHANNEL, 0, &c); + rvalue = c ? mgt_set_request(priv, DOT11_OID_CHANNEL, 0, &c) : -EINVAL; /* Call commit handler */ return (rvalue ? rvalue : -EINPROGRESS); @@ -410,7 +375,7 @@ mgt_commit(priv); priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) - ? ARPHRD_IEEE80211 : ARPHRD_ETHER; + ? priv->monitor_type : ARPHRD_ETHER; up_write(&priv->mib_sem); return 0; @@ -445,7 +410,6 @@ /* by default the card sets this to 20. */ sens = vwrq->disabled ? 20 : vwrq->value; - /* set the ed threshold. */ return mgt_set_request(priv, DOT11_OID_EDTHRESHOLD, 0, &sens); } @@ -524,31 +488,22 @@ return 0; /* Request the device for the supported frequencies - * not really revelant since some devices will report the 5 GHz band + * not really relevant since some devices will report the 5 GHz band * frequencies even if they don't support them. */ rvalue = mgt_get_request(priv, DOT11_OID_SUPPORTEDFREQUENCIES, 0, NULL, &r); freq = r.ptr; - range->num_channels = le16_to_cpu(freq->nr); - range->num_frequency = le16_to_cpu(freq->nr); + range->num_channels = freq->nr; + range->num_frequency = freq->nr; - /* Frequencies are not listed in the right order. The reordering is probably - * firmware dependant and thus should work for everyone. - */ - m = min(IW_MAX_FREQUENCIES, (int) le16_to_cpu(freq->nr)); - for (i = 0; i < m - 12; i++) { - range->freq[i].m = le16_to_cpu(freq->mhz[12 + i]); - range->freq[i].e = 6; - range->freq[i].i = i + 1; - } - for (i = m - 12; i < m; i++) { - range->freq[i].m = le16_to_cpu(freq->mhz[i - m + 12]); + m = min(IW_MAX_FREQUENCIES, (int) freq->nr); + for (i = 0; i < m; i++) { + range->freq[i].m = freq->mhz[i]; range->freq[i].e = 6; - range->freq[i].i = i + 23; + range->freq[i].i = channel_of_freq(freq->mhz[i]); } - kfree(freq); rvalue |= mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r); @@ -563,9 +518,7 @@ i++; data++; } - range->num_bitrates = i; - kfree(r.ptr); return rvalue; @@ -604,7 +557,6 @@ int rvalue; rvalue = mgt_get_request(priv, DOT11_OID_BSSID, 0, NULL, &r); - memcpy(awrq->sa_data, r.ptr, 6); awrq->sa_family = ARPHRD_ETHER; kfree(r.ptr); @@ -655,7 +607,7 @@ #define CAP_CRYPT 0x10 /* Mode */ - cap = le16_to_cpu(bss->capinfo); + cap = bss->capinfo; iwe.u.mode = 0; if (cap & CAP_ESS) iwe.u.mode = IW_MODE_MASTER; @@ -677,8 +629,8 @@ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, NULL); /* Add frequency. (short) bss->channel is the frequency in MHz */ - iwe.u.freq.m = bss->channel; - iwe.u.freq.e = 6; + iwe.u.freq.m = channel_of_freq(bss->channel); + iwe.u.freq.e = 0; iwe.cmd = SIOCGIWFREQ; current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); @@ -714,7 +666,6 @@ kfree(buf); } } - return current_ev; } @@ -741,13 +692,13 @@ /* Ask the device for a list of known bss. We can report at most * IW_MAX_AP=64 to the range struct. But the device won't repport anything - * if you change the value of MAXBSS=24. Anyway 24 AP It is probably enough. + * if you change the value of IWMAX_BSS=24. */ rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); bsslist = r.ptr; /* ok now, scan the list and translate its info */ - for (i = 0; i < min(IW_MAX_AP, (int) le32_to_cpu(bsslist->nr)); i++) + for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++) current_ev = prism54_translate_bss(ndev, current_ev, extra + IW_SCAN_MAX_DATA, &(bsslist->bsslist[i]), @@ -776,7 +727,7 @@ memcpy(essid.octets, extra, dwrq->length); } else essid.length = 0; - + if (priv->iw_mode != IW_MODE_MONITOR) return mgt_set_request(priv, DOT11_OID_SSID, 0, &essid); @@ -862,38 +813,39 @@ char *data; int ret, i; union oid_res_t r; - + if (vwrq->value == -1) { /* auto mode. No limit. */ profile = 1; return mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile); } - - if((ret = mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r))) + + if ((ret = + mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r))) return ret; - + rate = (u32) (vwrq->value / 500000); data = r.ptr; i = 0; - - while(data[i]) { - if(rate && (data[i] == rate)) { + + while (data[i]) { + if (rate && (data[i] == rate)) { break; } - if(vwrq->value == i) { + if (vwrq->value == i) { break; } data[i] |= 0x80; i++; } - - if(!data[i]) { + + if (!data[i]) { return -EINVAL; } - + data[i] |= 0x80; data[i + 1] = 0; - + /* Now, check if we want a fixed or auto value */ if (vwrq->fixed) { data[0] = data[i]; @@ -908,14 +860,14 @@ i++; } printk("0\n"); -*/ +*/ profile = -1; ret = mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile); ret |= mgt_set_request(priv, DOT11_OID_EXTENDEDRATES, 0, data); ret |= mgt_set_request(priv, DOT11_OID_RATES, 0, data); - + kfree(r.ptr); - + return ret; } @@ -931,17 +883,17 @@ union oid_res_t r; /* Get the current bit rate */ - if((rvalue = mgt_get_request(priv, GEN_OID_LINKSTATE, 0, NULL, &r))) + if ((rvalue = mgt_get_request(priv, GEN_OID_LINKSTATE, 0, NULL, &r))) return rvalue; vwrq->value = r.u * 500000; /* request the device for the enabled rates */ - if((rvalue = mgt_get_request(priv, DOT11_OID_RATES, 0, NULL, &r))) + if ((rvalue = mgt_get_request(priv, DOT11_OID_RATES, 0, NULL, &r))) return rvalue; data = r.ptr; vwrq->fixed = (data[0] != 0) && (data[1] == 0); kfree(r.ptr); - + return 0; } @@ -997,8 +949,6 @@ * small frame <=> smaller than the rts threshold * This is not really the behavior expected by the wireless tool but it seems * to be a common behavior in other drivers. - * - * It seems that playing with this tends to hang the card -> DISABLED */ static int @@ -1030,18 +980,16 @@ lifetime = vwrq->value / 1024; /* now set what is requested */ - - if (slimit != 0) + if (slimit) rvalue = mgt_set_request(priv, DOT11_OID_SHORTRETRIES, 0, &slimit); - if (llimit != 0) + if (llimit) rvalue |= mgt_set_request(priv, DOT11_OID_LONGRETRIES, 0, &llimit); - if (lifetime != 0) + if (lifetime) rvalue |= mgt_set_request(priv, DOT11_OID_MAXTXLIFETIME, 0, &lifetime); - return rvalue; } @@ -1137,8 +1085,7 @@ } } } - - /* now read the flags */ + /* now read the flags */ if (dwrq->flags & IW_ENCODE_DISABLED) { /* Encoding disabled, * authen = DOT11_AUTH_OS; @@ -1225,7 +1172,7 @@ rvalue = mgt_get_request(priv, OID_INL_OUTPUTPOWER, 0, NULL, &r); /* intersil firmware operates in 0.25 dBm (1/4 dBm) */ - vwrq->value = (s32)r.u / 4; + vwrq->value = (s32) r.u / 4; vwrq->fixed = 1; /* radio is not turned of * btw: how is possible to turn off only the radio @@ -1271,28 +1218,36 @@ } static int -prism54_set_beacon(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) +prism54_get_oid(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) { - int rvalue = mgt_set_request((islpci_private *) netdev_priv(ndev), - DOT11_OID_BEACONPERIOD, 0, uwrq); + union oid_res_t r; + int rvalue; + enum oid_num_t n = dwrq->flags; - return (rvalue ? rvalue : -EINPROGRESS); + rvalue = mgt_get_request((islpci_private *) ndev->priv, n, 0, NULL, &r); + dwrq->length = mgt_response_to_str(n, &r, extra); + if ((isl_oid[n].flags & OID_FLAG_TYPE) != OID_TYPE_U32) + kfree(r.ptr); + return rvalue; } static int -prism54_get_beacon(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) +prism54_set_u32(struct net_device *ndev, struct iw_request_info *info, + __u32 * uwrq, char *extra) { - union oid_res_t r; - int rvalue; + u32 oid = uwrq[0], u = uwrq[1]; - rvalue = - mgt_get_request((islpci_private *) netdev_priv(ndev), - DOT11_OID_BEACONPERIOD, 0, NULL, &r); - *uwrq = r.u; + return mgt_set_request((islpci_private *) ndev->priv, oid, 0, &u); +} - return rvalue; +static int +prism54_set_raw(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + u32 oid = dwrq->flags; + + return mgt_set_request((islpci_private *) ndev->priv, oid, 0, extra); } void @@ -1511,8 +1466,9 @@ return -ENOMEM; /* Tell the card to kick every client */ - mlme->id = cpu_to_le16(0); - rvalue = mgt_set_request(netdev_priv(ndev), DOT11_OID_DISASSOCIATE, 0, mlme); + mlme->id = 0; + rvalue = + mgt_set_request(netdev_priv(ndev), DOT11_OID_DISASSOCIATE, 0, mlme); kfree(mlme); return rvalue; @@ -1535,8 +1491,9 @@ /* Tell the card to only kick the corresponding bastard */ memcpy(mlme->address, addr->sa_data, ETH_ALEN); - mlme->id = cpu_to_le16(-1); - rvalue = mgt_set_request(netdev_priv(ndev), DOT11_OID_DISASSOCIATE, 0, mlme); + mlme->id = -1; + rvalue = + mgt_set_request(netdev_priv(ndev), DOT11_OID_DISASSOCIATE, 0, mlme); kfree(mlme); @@ -1551,12 +1508,12 @@ { const u8 *a = mlme->address; int n = snprintf(dest, IW_CUSTOM_MAX, - "%s %s %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X %s", + "%s %s %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X %s (%2.2X)", str, - ((priv->iw_mode == IW_MODE_MASTER) ? "to" : "from"), + ((priv->iw_mode == IW_MODE_MASTER) ? "from" : "to"), a[0], a[1], a[2], a[3], a[4], a[5], (error ? (mlme->code ? " : REJECTED " : " : ACCEPTED ") - : "")); + : ""), mlme->code); BUG_ON(n > IW_CUSTOM_MAX); *length = n; } @@ -1598,14 +1555,15 @@ { islpci_private *priv = netdev_priv(ndev); - if (le32_to_cpu(bitrate)) { + if (bitrate) { if (priv->iw_mode == IW_MODE_INFRA) { union iwreq_data uwrq; prism54_get_wap(ndev, NULL, (struct sockaddr *) &uwrq, NULL); wireless_send_event(ndev, SIOCGIWAP, &uwrq, NULL); } else - send_simple_event(netdev_priv(ndev), "Link established"); + send_simple_event(netdev_priv(ndev), + "Link established"); } else send_simple_event(netdev_priv(ndev), "Link lost"); } @@ -1765,15 +1723,14 @@ static void handle_request(islpci_private *priv, struct obj_mlme *mlme, enum oid_num_t oid) { - if (((le16_to_cpu(mlme->state) == DOT11_STATE_AUTHING) || - (le16_to_cpu(mlme->state) == DOT11_STATE_ASSOCING)) + if (((mlme->state == DOT11_STATE_AUTHING) || + (mlme->state == DOT11_STATE_ASSOCING)) && mgt_mlme_answer(priv)) { /* Someone is requesting auth and we must respond. Just send back * the trap with error code set accordingly. */ - mlme->code = cpu_to_le16(prism54_mac_accept(&priv->acl, - mlme-> - address) ? 0 : 1); + mlme->code = prism54_mac_accept(&priv->acl, + mlme->address) ? 0 : 1; mgt_set_request(priv, oid, 0, mlme); } } @@ -1797,6 +1754,13 @@ * suited. We use the more flexible custom event facility. */ + /* I fear prism54_process_bss_data won't work with big endian data */ + if ((oid == DOT11_OID_BEACON) || (oid == DOT11_OID_PROBE)) + prism54_process_bss_data(priv, oid, mlme->address, + payload, len); + + mgt_le_to_cpu(isl_oid[oid].flags & OID_FLAG_TYPE, (void *) mlme); + switch (oid) { case GEN_OID_LINKSTATE: @@ -1831,8 +1795,6 @@ break; case DOT11_OID_BEACON: - prism54_process_bss_data(priv, oid, mlme->address, - payload, len); send_formatted_event(priv, "Received a beacon from an unkown AP", mlme, 0); @@ -1840,15 +1802,11 @@ case DOT11_OID_PROBE: /* we received a probe from a client. */ - prism54_process_bss_data(priv, oid, mlme->address, - payload, len); send_formatted_event(priv, "Received a probe from client", mlme, 0); break; - /* Note : the following should never happen since we don't run the card in - * extended mode. - * Note : "mlme" is actually a "struct obj_mlmeex *" here, but this + /* Note : "mlme" is actually a "struct obj_mlmeex *" here, but this * is backward compatible layout-wise with "struct obj_mlme". */ @@ -1893,7 +1851,8 @@ struct net_device *ndev = frame->ndev; enum oid_num_t n = mgt_oidtonum(frame->header->oid); - prism54_process_trap_helper(netdev_priv(ndev), n, frame->data); + if (n != OID_NUM_LAST) + prism54_process_trap_helper(netdev_priv(ndev), n, frame->data); islpci_mgt_release(frame); } @@ -1915,13 +1874,6 @@ } int -prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) -{ - /* should we really support this old stuff ? */ - return -EOPNOTSUPP; -} - -int prism54_set_wpa(struct net_device *ndev, struct iw_request_info *info, __u32 * uwrq, char *extra) { @@ -1951,65 +1903,33 @@ } int -prism54_set_maxframeburst(struct net_device *ndev, struct iw_request_info *info, - __u32 *uwrq, char *extra) +prism54_set_prismhdr(struct net_device *ndev, struct iw_request_info *info, + __u32 * uwrq, char *extra) { islpci_private *priv = netdev_priv(ndev); - u32 max_burst; - - max_burst = (*uwrq) ? *uwrq : CARD_DEFAULT_MAXFRAMEBURST; - mgt_set_request(priv, DOT11_OID_MAXFRAMEBURST, 0, &max_burst); - - return -EINPROGRESS; /* Call commit handler */ -} + priv->monitor_type = + (*uwrq ? ARPHRD_IEEE80211_PRISM : ARPHRD_IEEE80211); + if (priv->iw_mode == IW_MODE_MONITOR) + priv->ndev->type = priv->monitor_type; -int -prism54_get_maxframeburst(struct net_device *ndev, struct iw_request_info *info, - __u32 *uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - union oid_res_t r; - int rvalue; - - rvalue = mgt_get_request(priv, DOT11_OID_MAXFRAMEBURST, 0, NULL, &r); - *uwrq = r.u; - - return rvalue; + return 0; } int -prism54_set_profile(struct net_device *ndev, struct iw_request_info *info, - __u32 *uwrq, char *extra) +prism54_get_prismhdr(struct net_device *ndev, struct iw_request_info *info, + __u32 * uwrq, char *extra) { islpci_private *priv = netdev_priv(ndev); - u32 profile; - - profile = (*uwrq) ? *uwrq : CARD_DEFAULT_PROFILE; - mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile); - - return -EINPROGRESS; /* Call commit handler */ + *uwrq = (priv->monitor_type == ARPHRD_IEEE80211_PRISM); + return 0; } int -prism54_get_profile(struct net_device *ndev, struct iw_request_info *info, - __u32 *uwrq, char *extra) +prism54_debug_oid(struct net_device *ndev, struct iw_request_info *info, + __u32 * uwrq, char *extra) { islpci_private *priv = netdev_priv(ndev); - union oid_res_t r; - int rvalue; - - rvalue = mgt_get_request(priv, DOT11_OID_PROFILES, 0, NULL, &r); - *uwrq = r.u; - return rvalue; -} - -int -prism54_oid(struct net_device *ndev, struct iw_request_info *info, - __u32 *uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - priv->priv_oid = *uwrq; printk("%s: oid 0x%08X\n", ndev->name, *uwrq); @@ -2017,22 +1937,26 @@ } int -prism54_get_oid(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *data, char *extra) +prism54_debug_get_oid(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *data, char *extra) { islpci_private *priv = netdev_priv(ndev); struct islpci_mgmtframe *response = NULL; int ret = -EIO, response_op = PIMFOR_OP_ERROR; - + printk("%s: get_oid 0x%08X\n", ndev->name, priv->priv_oid); data->length = 0; - + if (islpci_get_state(priv) >= PRV_STATE_INIT) { - ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, priv->priv_oid, extra, 256, &response); + ret = + islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, + priv->priv_oid, extra, 256, + &response); response_op = response->header->operation; printk("%s: ret: %i\n", ndev->name, ret); printk("%s: response_op: %i\n", ndev->name, response_op); - if (ret || !response || response->header->operation == PIMFOR_OP_ERROR) { + if (ret || !response + || response->header->operation == PIMFOR_OP_ERROR) { if (response) { islpci_mgt_release(response); } @@ -2046,35 +1970,65 @@ printk("%s: len: %i\n", ndev->name, data->length); } } - + return ret; } int -prism54_set_oid(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *data, char *extra) +prism54_debug_set_oid(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *data, char *extra) { islpci_private *priv = netdev_priv(ndev); struct islpci_mgmtframe *response = NULL; int ret = 0, response_op = PIMFOR_OP_ERROR; - - printk("%s: set_oid 0x%08X\tlen: %d\n", ndev->name, priv->priv_oid, data->length); - + + printk("%s: set_oid 0x%08X\tlen: %d\n", ndev->name, priv->priv_oid, + data->length); + if (islpci_get_state(priv) >= PRV_STATE_INIT) { - ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, priv->priv_oid, extra, data->length, &response); + ret = + islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, + priv->priv_oid, extra, data->length, + &response); printk("%s: ret: %i\n", ndev->name, ret); if (!ret) { response_op = response->header->operation; - printk("%s: response_op: %i\n", ndev->name, response_op); + printk("%s: response_op: %i\n", ndev->name, + response_op); islpci_mgt_release(response); } if (ret || response_op == PIMFOR_OP_ERROR) { printk("%s: EIO\n", ndev->name); - ret = -EIO; + ret = -EIO; } } - - return ret; + + return (ret ? ret : -EINPROGRESS); +} + +static int +prism54_set_spy(struct net_device *ndev, + struct iw_request_info *info, + union iwreq_data *uwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + u32 u, oid = OID_INL_CONFIG; + + down_write(&priv->mib_sem); + mgt_get(priv, OID_INL_CONFIG, &u); + + if ((uwrq->data.length == 0) && (priv->spy_data.spy_number > 0)) + /* disable spy */ + u &= ~INL_CONFIG_RXANNEX; + else if ((uwrq->data.length > 0) && (priv->spy_data.spy_number == 0)) + /* enable spy */ + u |= INL_CONFIG_RXANNEX; + + mgt_set(priv, OID_INL_CONFIG, &u); + mgt_commit_list(priv, &oid, 1); + up_write(&priv->mib_sem); + + return iw_handler_set_spy(ndev, info, uwrq, extra); } static const iw_handler prism54_handler[] = { @@ -2094,7 +2048,7 @@ (iw_handler) NULL, /* SIOCGIWPRIV */ (iw_handler) NULL, /* SIOCSIWSTATS */ (iw_handler) NULL, /* SIOCGIWSTATS */ - iw_handler_set_spy, /* SIOCSIWSPY */ + prism54_set_spy, /* SIOCSIWSPY */ iw_handler_get_spy, /* SIOCGIWSPY */ iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ @@ -2129,33 +2083,50 @@ /* The low order bit identify a SET (0) or a GET (1) ioctl. */ #define PRISM54_RESET SIOCIWFIRSTPRIV -#define PRISM54_GET_BEACON SIOCIWFIRSTPRIV+1 -#define PRISM54_SET_BEACON SIOCIWFIRSTPRIV+2 -#define PRISM54_GET_POLICY SIOCIWFIRSTPRIV+3 -#define PRISM54_SET_POLICY SIOCIWFIRSTPRIV+4 -#define PRISM54_GET_MAC SIOCIWFIRSTPRIV+5 -#define PRISM54_ADD_MAC SIOCIWFIRSTPRIV+6 +#define PRISM54_GET_POLICY SIOCIWFIRSTPRIV+1 +#define PRISM54_SET_POLICY SIOCIWFIRSTPRIV+2 +#define PRISM54_GET_MAC SIOCIWFIRSTPRIV+3 +#define PRISM54_ADD_MAC SIOCIWFIRSTPRIV+4 + +#define PRISM54_DEL_MAC SIOCIWFIRSTPRIV+6 + +#define PRISM54_KICK_MAC SIOCIWFIRSTPRIV+8 -#define PRISM54_DEL_MAC SIOCIWFIRSTPRIV+8 +#define PRISM54_KICK_ALL SIOCIWFIRSTPRIV+10 -#define PRISM54_KICK_MAC SIOCIWFIRSTPRIV+10 +#define PRISM54_GET_WPA SIOCIWFIRSTPRIV+11 +#define PRISM54_SET_WPA SIOCIWFIRSTPRIV+12 -#define PRISM54_KICK_ALL SIOCIWFIRSTPRIV+12 +#define PRISM54_DBG_OID SIOCIWFIRSTPRIV+14 +#define PRISM54_DBG_GET_OID SIOCIWFIRSTPRIV+15 +#define PRISM54_DBG_SET_OID SIOCIWFIRSTPRIV+16 -#define PRISM54_GET_WPA SIOCIWFIRSTPRIV+13 -#define PRISM54_SET_WPA SIOCIWFIRSTPRIV+14 +#define PRISM54_GET_OID SIOCIWFIRSTPRIV+17 +#define PRISM54_SET_OID_U32 SIOCIWFIRSTPRIV+18 +#define PRISM54_SET_OID_STR SIOCIWFIRSTPRIV+20 +#define PRISM54_SET_OID_ADDR SIOCIWFIRSTPRIV+22 -#define PRISM54_OID SIOCIWFIRSTPRIV+16 -#define PRISM54_GET_OID SIOCIWFIRSTPRIV+17 -#define PRISM54_SET_OID SIOCIWFIRSTPRIV+18 +#define PRISM54_GET_PRISMHDR SIOCIWFIRSTPRIV+23 +#define PRISM54_SET_PRISMHDR SIOCIWFIRSTPRIV+24 + +#define IWPRIV_SET_U32(n,x) { n, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x } +#define IWPRIV_SET_SSID(n,x) { n, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x } +#define IWPRIV_SET_ADDR(n,x) { n, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x } +#define IWPRIV_GET(n,x) { n, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, "g_"x } + +#define IWPRIV_U32(n,x) IWPRIV_SET_U32(n,x), IWPRIV_GET(n,x) +#define IWPRIV_SSID(n,x) IWPRIV_SET_SSID(n,x), IWPRIV_GET(n,x) +#define IWPRIV_ADDR(n,x) IWPRIV_SET_ADDR(n,x), IWPRIV_GET(n,x) + +/* Note : limited to 128 private ioctls (wireless tools 26) */ static const struct iw_priv_args prism54_private_args[] = { /*{ cmd, set_args, get_args, name } */ {PRISM54_RESET, 0, 0, "reset"}, - {PRISM54_GET_BEACON, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getBeaconPeriod"}, - {PRISM54_SET_BEACON, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, - "setBeaconPeriod"}, + {PRISM54_GET_PRISMHDR, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_prismhdr"}, + {PRISM54_SET_PRISMHDR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "set_prismhdr"}, {PRISM54_GET_POLICY, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getPolicy"}, {PRISM54_SET_POLICY, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, @@ -2172,15 +2143,77 @@ "get_wpa"}, {PRISM54_SET_WPA, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_wpa"}, - {PRISM54_OID, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "oid"}, - {PRISM54_GET_OID, 0, IW_PRIV_TYPE_BYTE | 256, "get_oid"}, - {PRISM54_SET_OID, IW_PRIV_TYPE_BYTE | 256, 0, "set_oid"}, + {PRISM54_DBG_OID, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "dbg_oid"}, + {PRISM54_DBG_GET_OID, 0, IW_PRIV_TYPE_BYTE | 256, "dbg_get_oid"}, + {PRISM54_DBG_SET_OID, IW_PRIV_TYPE_BYTE | 256, 0, "dbg_set_oid"}, + /* --- sub-ioctls handlers --- */ + {PRISM54_GET_OID, + 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, ""}, + {PRISM54_SET_OID_U32, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, ""}, + {PRISM54_SET_OID_STR, + IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, ""}, + {PRISM54_SET_OID_ADDR, + IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, ""}, + /* --- sub-ioctls definitions --- */ + IWPRIV_ADDR(GEN_OID_MACADDRESS, "addr"), + IWPRIV_GET(GEN_OID_LINKSTATE, "linkstate"), + IWPRIV_U32(DOT11_OID_BSSTYPE, "bsstype"), + IWPRIV_ADDR(DOT11_OID_BSSID, "bssid"), + IWPRIV_U32(DOT11_OID_STATE, "state"), + IWPRIV_U32(DOT11_OID_AID, "aid"), + + IWPRIV_SSID(DOT11_OID_SSIDOVERRIDE, "ssidoverride"), + + IWPRIV_U32(DOT11_OID_MEDIUMLIMIT, "medlimit"), + IWPRIV_U32(DOT11_OID_BEACONPERIOD, "beacon"), + IWPRIV_U32(DOT11_OID_DTIMPERIOD, "dtimperiod"), + + IWPRIV_U32(DOT11_OID_AUTHENABLE, "authenable"), + IWPRIV_U32(DOT11_OID_PRIVACYINVOKED, "privinvok"), + IWPRIV_U32(DOT11_OID_EXUNENCRYPTED, "exunencrypt"), + + IWPRIV_U32(DOT11_OID_REKEYTHRESHOLD, "rekeythresh"), + + IWPRIV_U32(DOT11_OID_MAXTXLIFETIME, "maxtxlife"), + IWPRIV_U32(DOT11_OID_MAXRXLIFETIME, "maxrxlife"), + IWPRIV_U32(DOT11_OID_ALOFT_FIXEDRATE, "fixedrate"), + IWPRIV_U32(DOT11_OID_MAXFRAMEBURST, "frameburst"), + IWPRIV_U32(DOT11_OID_PSM, "psm"), + + IWPRIV_U32(DOT11_OID_BRIDGELOCAL, "bridge"), + IWPRIV_U32(DOT11_OID_CLIENTS, "clients"), + IWPRIV_U32(DOT11_OID_CLIENTSASSOCIATED, "clientassoc"), + IWPRIV_U32(DOT11_OID_DOT1XENABLE, "dot1xenable"), + IWPRIV_U32(DOT11_OID_ANTENNARX, "rxant"), + IWPRIV_U32(DOT11_OID_ANTENNATX, "txant"), + IWPRIV_U32(DOT11_OID_ANTENNADIVERSITY, "antdivers"), + IWPRIV_U32(DOT11_OID_EDTHRESHOLD, "edthresh"), + IWPRIV_U32(DOT11_OID_PREAMBLESETTINGS, "preamble"), + IWPRIV_GET(DOT11_OID_RATES, "rates"), + IWPRIV_U32(DOT11_OID_OUTPUTPOWER, ".11outpower"), + IWPRIV_GET(DOT11_OID_SUPPORTEDRATES, "supprates"), + IWPRIV_GET(DOT11_OID_SUPPORTEDFREQUENCIES, "suppfreq"), + + IWPRIV_U32(DOT11_OID_NOISEFLOOR, "noisefloor"), + IWPRIV_GET(DOT11_OID_FREQUENCYACTIVITY, "freqactivity"), + IWPRIV_U32(DOT11_OID_NONERPPROTECTION, "nonerpprotec"), + IWPRIV_U32(DOT11_OID_PROFILES, "profile"), + IWPRIV_GET(DOT11_OID_EXTENDEDRATES, "extrates"), + IWPRIV_U32(DOT11_OID_MLMEAUTOLEVEL, "mlmelevel"), + + IWPRIV_GET(DOT11_OID_BSSS, "bsss"), + IWPRIV_GET(DOT11_OID_BSSLIST, "bsslist"), + IWPRIV_U32(OID_INL_MODE, "mode"), + IWPRIV_U32(OID_INL_CONFIG, "config"), + IWPRIV_U32(OID_INL_DOT11D_CONFORMANCE, ".11dconform"), + IWPRIV_GET(OID_INL_PHYCAPABILITIES, "phycapa"), + IWPRIV_U32(OID_INL_OUTPUTPOWER, "outpower"), }; static const iw_handler prism54_private_handler[] = { (iw_handler) prism54_reset, - (iw_handler) prism54_get_beacon, - (iw_handler) prism54_set_beacon, (iw_handler) prism54_get_policy, (iw_handler) prism54_set_policy, (iw_handler) prism54_get_mac, @@ -2194,9 +2227,17 @@ (iw_handler) prism54_get_wpa, (iw_handler) prism54_set_wpa, (iw_handler) NULL, - (iw_handler) prism54_oid, + (iw_handler) prism54_debug_oid, + (iw_handler) prism54_debug_get_oid, + (iw_handler) prism54_debug_set_oid, (iw_handler) prism54_get_oid, - (iw_handler) prism54_set_oid, + (iw_handler) prism54_set_u32, + (iw_handler) NULL, + (iw_handler) prism54_set_raw, + (iw_handler) NULL, + (iw_handler) prism54_set_raw, + (iw_handler) prism54_get_prismhdr, + (iw_handler) prism54_set_prismhdr, }; const struct iw_handler_def prism54_handler_def = { @@ -2207,5 +2248,14 @@ .standard = (iw_handler *) prism54_handler, .private = (iw_handler *) prism54_private_handler, .private_args = (struct iw_priv_args *) prism54_private_args, + .spy_offset = offsetof(islpci_private, spy_data), }; +/* For ioctls that don't work with the new API */ + +int +prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) +{ + + return -EOPNOTSUPP; +} --- diff/drivers/net/wireless/prism54/isl_ioctl.h 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/net/wireless/prism54/isl_ioctl.h 2004-05-27 18:34:17.000000000 +0100 @@ -1,4 +1,4 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/isl_ioctl.h,v 1.30 2004/01/30 16:24:00 ajfa Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/isl_ioctl.h,v 1.32 2004/04/17 08:46:04 ajfa Exp $ * * Copyright (C) 2002 Intersil Americas Inc. * (C) 2003 Aurelien Alleaume @@ -30,7 +30,6 @@ #define SUPPORTED_WIRELESS_EXT 16 void prism54_mib_init(islpci_private *); -void prism54_mib_init_work(islpci_private *); struct iw_statistics *prism54_get_wireless_stats(struct net_device *); void prism54_update_stats(islpci_private *); --- diff/drivers/net/wireless/prism54/isl_oid.h 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/net/wireless/prism54/isl_oid.h 2004-05-27 18:34:17.000000000 +0100 @@ -1,8 +1,9 @@ /* - * $Id: isl_oid.h,v 1.3 2004/03/09 09:05:27 mcgrof Exp $ + * $Id: isl_oid.h,v 1.6 2004/03/19 20:54:33 ajfa Exp $ * * Copyright (C) 2003 Herbert Valerio Riedel * Copyright (C) 2004 Luis R. Rodriguez + * Copyright (C) 2004 Aurelien Alleaume * * 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 @@ -457,16 +458,29 @@ OID_NUM_LAST }; -/* We could add more flags. eg: in which mode are they allowed, ro, rw, ...*/ -#define OID_FLAG_CACHED 0x01 -#define OID_FLAG_U32 0x02 -#define OID_FLAG_MLMEEX 0x04 /* this type is special because of a variable - size field when sending. Not yet implemented (not used in driver). */ +#define OID_FLAG_CACHED 0x80 +#define OID_FLAG_TYPE 0x7f + +#define OID_TYPE_U32 0x01 +#define OID_TYPE_SSID 0x02 +#define OID_TYPE_KEY 0x03 +#define OID_TYPE_BUFFER 0x04 +#define OID_TYPE_BSS 0x05 +#define OID_TYPE_BSSLIST 0x06 +#define OID_TYPE_FREQUENCIES 0x07 +#define OID_TYPE_MLME 0x08 +#define OID_TYPE_MLMEEX 0x09 +#define OID_TYPE_ADDR 0x0A +#define OID_TYPE_RAW 0x0B + +/* OID_TYPE_MLMEEX is special because of a variable size field when sending. + * Not yet implemented (not used in driver anyway). + */ struct oid_t { enum oid_num_t oid; short range; /* to define a range of oid */ - short size; /* size of the associated data */ + short size; /* max size of the associated data */ char flags; }; @@ -478,6 +492,7 @@ #define IWMAX_BITRATES 20 #define IWMAX_BSS 24 #define IWMAX_FREQ 30 +#define PRIV_STR_SIZE 1024 #endif /* !defined(_ISL_OID_H) */ /* EOF */ --- diff/drivers/net/wireless/prism54/islpci_dev.c 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/net/wireless/prism54/islpci_dev.c 2004-05-27 18:34:17.000000000 +0100 @@ -1,4 +1,4 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.c,v 1.68 2004/02/28 03:06:07 mcgrof Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.c,v 1.78 2004/04/27 17:22:35 ajfa Exp $ * * Copyright (C) 2002 Intersil Americas Inc. * Copyright (C) 2003 Herbert Valerio Riedel @@ -30,6 +30,7 @@ #include +#include "prismcompat.h" #include "isl_38xx.h" #include "isl_ioctl.h" #include "islpci_dev.h" @@ -37,12 +38,6 @@ #include "islpci_eth.h" #include "oid_mgt.h" -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) -#define prism54_synchronize_irq(irq) synchronize_irq() -#else -#define prism54_synchronize_irq(irq) synchronize_irq(irq) -#endif - #define ISL3877_IMAGE_FILE "isl3877" #define ISL3890_IMAGE_FILE "isl3890" @@ -74,7 +69,9 @@ if (reg & ISL38XX_CTRL_STAT_SLEEPMODE) /* device is in sleep mode, IRQ was generated by someone else */ { - printk(KERN_DEBUG "Assuming someone else called the IRQ\n"); +#if VERBOSE > SHOW_ERROR_MESSAGES + DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n"); +#endif return IRQ_NONE; } @@ -325,11 +322,7 @@ printk(KERN_DEBUG "%s: uploading firmware...\n", priv->ndev->name); rc = isl38xx_upload_firmware(priv->firmware, -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,75)) - &priv->pdev->dev, -#else - pci_name(priv->pdev), -#endif + PRISM_FW_PDEV, priv->device_base, priv->device_host_address); if (rc) { @@ -357,15 +350,8 @@ int result = -ETIME; int count; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - /* This is 2.6 specific, nicer, shorter, but not in 2.4 yet */ - DEFINE_WAIT(wait); - prepare_to_wait(&priv->reset_done, &wait, TASK_UNINTERRUPTIBLE); -#else - DECLARE_WAITQUEUE(wait, current); - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&priv->reset_done, &wait); -#endif + PRISM_DEFWAITQ(wait); + PRISM_PREPWAITQ(priv->reset_done, wait); /* now the last step is to reset the interface */ isl38xx_interface_reset(priv->device_base, priv->device_host_address); @@ -390,13 +376,7 @@ } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - /* 2.6 specific too */ - finish_wait(&priv->reset_done, &wait); -#else - remove_wait_queue(&priv->reset_done, &wait); - set_current_state(TASK_RUNNING); -#endif + PRISM_ENDWAITQ(priv->reset_done, wait); if(result) return result; @@ -410,7 +390,9 @@ * the IRQ line until we know for sure the reset went through */ isl38xx_enable_common_interrupts(priv->device_base); - prism54_mib_init_work(priv); + down_write(&priv->mib_sem); + mgt_commit(priv); + up_write(&priv->mib_sem); islpci_set_state(priv, PRV_STATE_READY); @@ -448,9 +430,9 @@ /* reset the mgmt receive queue */ for (counter = 0; counter < ISL38XX_CB_MGMT_QSIZE; counter++) { isl38xx_fragment *frag = &cb->rx_data_mgmt[counter]; - frag->size = MGMT_FRAME_SIZE; + frag->size = cpu_to_le16(MGMT_FRAME_SIZE); frag->flags = 0; - frag->address = priv->mgmt_rx[counter].pci_addr; + frag->address = cpu_to_le32(priv->mgmt_rx[counter].pci_addr); } for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) { @@ -580,6 +562,7 @@ skb = NULL; goto out_free; } + skb_reserve(skb, (4 - (long) skb->data) & 0x03); /* add the new allocated sk_buff to the buffer array */ priv->data_low_rx[counter] = skb; @@ -715,9 +698,9 @@ priv = netdev_priv(ndev); priv->ndev = ndev; priv->pdev = pdev; - + priv->monitor_type = ARPHRD_IEEE80211; priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ? - ARPHRD_IEEE80211: ARPHRD_ETHER; + priv->monitor_type : ARPHRD_ETHER; /* save the start and end address of the PCI memory area */ ndev->mem_start = (unsigned long) priv->device_base; @@ -743,9 +726,11 @@ /* initialize workqueue's */ INIT_WORK(&priv->stats_work, (void (*)(void *)) prism54_update_stats, priv); - priv->stats_timestamp = 0; + INIT_WORK(&priv->reset_task, islpci_do_reset_and_wake, priv); + priv->reset_task_pending = 0; + /* allocate various memory areas */ if (islpci_alloc_memory(priv)) goto do_free_netdev; --- diff/drivers/net/wireless/prism54/islpci_dev.h 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/net/wireless/prism54/islpci_dev.h 2004-05-27 18:34:17.000000000 +0100 @@ -1,8 +1,9 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.h,v 1.53 2004/02/28 03:06:07 mcgrof Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_dev.h,v 1.59 2004/03/20 16:58:36 mcgrof Exp $ * * Copyright (C) 2002 Intersil Americas Inc. * Copyright (C) 2003 Herbert Valerio Riedel * Copyright (C) 2003 Luis R. Rodriguez + * Copyright (C) 2003 Aurelien Alleaume * * 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 @@ -25,22 +26,9 @@ #include #include #include +#include #include -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) -# include -#else -# include -# define work_struct tq_struct -# define INIT_WORK INIT_TQUEUE -# define schedule_work schedule_task -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23) -#define free_netdev(x) kfree(x) -#define pci_name(x) x->slot_name -#endif - #include "isl_38xx.h" #include "isl_oid.h" #include "islpci_mgt.h" @@ -110,6 +98,10 @@ struct iw_statistics local_iwstatistics; struct iw_statistics iwstatistics; + struct iw_spy_data spy_data; /* iwspy support */ + + int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */ + struct islpci_acl acl; /* PCI bus allocation & configuration members */ @@ -181,12 +173,15 @@ islpci_state_t state; int state_off; /* enumeration of off-state, if 0 then * we're not in any off-state */ - + /* WPA stuff */ int wpa; /* WPA mode enabled */ struct list_head bss_wpa_list; int num_bss_wpa; struct semaphore wpa_sem; + + struct work_struct reset_task; + int reset_task_pending; } islpci_private; static inline islpci_state_t @@ -201,12 +196,6 @@ #define ISLPCI_TX_TIMEOUT (2*HZ) -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,75)) -# define irqreturn_t void -# define IRQ_HANDLED -# define IRQ_NONE -#endif - irqreturn_t islpci_interrupt(int, void *, struct pt_regs *); int prism54_post_setup(islpci_private *, int); --- diff/drivers/net/wireless/prism54/islpci_eth.c 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/net/wireless/prism54/islpci_eth.c 2004-05-27 18:34:17.000000000 +0100 @@ -1,7 +1,7 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.c,v 1.27 2004/01/30 16:24:00 ajfa Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.c,v 1.37 2004/05/20 06:24:12 ajfa Exp $ * * Copyright (C) 2002 Intersil Americas Inc. - * + * Copyright (C) 2004 Aurelien Alleaume * 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 @@ -24,10 +24,13 @@ #include #include #include +#include +#include "prismcompat.h" #include "isl_38xx.h" #include "islpci_eth.h" #include "islpci_mgt.h" +#include "oid_mgt.h" /****************************************************************************** Network Interface functions @@ -102,7 +105,7 @@ /* check whether the destination queue has enough fragments for the frame */ curr_frag = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ]); - if (curr_frag - priv->free_data_tx >= ISL38XX_CB_TX_QSIZE) { + if (unlikely(curr_frag - priv->free_data_tx >= ISL38XX_CB_TX_QSIZE)) { printk(KERN_ERR "%s: transmit device queue full when awake\n", ndev->name); netif_stop_queue(ndev); @@ -118,7 +121,7 @@ /* Check alignment and WDS frame formatting. The start of the packet should * be aligned on a 4-byte boundary. If WDS is enabled add another 6 bytes * and add WDS address information */ - if (((long) skb->data & 0x03) | init_wds) { + if (unlikely(((long) skb->data & 0x03) | init_wds)) { /* get the number of bytes to add and re-allign */ offset = (4 - (long) skb->data) & 0x03; offset += init_wds ? 6 : 0; @@ -189,7 +192,7 @@ pci_map_address = pci_map_single(priv->pdev, (void *) skb->data, skb->len, PCI_DMA_TODEVICE); - if (pci_map_address == 0) { + if (unlikely(pci_map_address == 0)) { printk(KERN_WARNING "%s: cannot map buffer to PCI\n", ndev->name); @@ -205,7 +208,7 @@ priv->data_low_tx[index] = skb; /* set the proper fragment start address and size information */ fragment->size = cpu_to_le16(frame_size); - fragment->flags = cpu_to_le16(0); /* set to 1 if more fragments */ + fragment->flags = cpu_to_le16(0); /* set to 1 if more fragments */ fragment->address = cpu_to_le32(pci_map_address); curr_frag++; @@ -215,7 +218,7 @@ cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ] = cpu_to_le32(curr_frag); if (curr_frag - priv->free_data_tx + ISL38XX_MIN_QTHRESHOLD - > ISL38XX_CB_TX_QSIZE) { + > ISL38XX_CB_TX_QSIZE) { /* stop sends from upper layers */ netif_stop_queue(ndev); @@ -236,7 +239,7 @@ return 0; - drop_free: + drop_free: /* free the skbuf structure before aborting */ dev_kfree_skb(skb); skb = NULL; @@ -246,6 +249,69 @@ return err; } +static inline int +islpci_monitor_rx(islpci_private *priv, struct sk_buff **skb) +{ + /* The card reports full 802.11 packets but with a 20 bytes + * header and without the FCS. But there a is a bit that + * indicates if the packet is corrupted :-) */ + struct rfmon_header *hdr = (struct rfmon_header *) (*skb)->data; + if (hdr->flags & 0x01) + /* This one is bad. Drop it ! */ + return -1; + if (priv->ndev->type == ARPHRD_IEEE80211_PRISM) { + struct avs_80211_1_header *avs; + /* extract the relevant data from the header */ + u32 clock = le32_to_cpu(hdr->clock); + u8 rate = hdr->rate; + u16 freq = le16_to_cpu(hdr->freq); + u8 rssi = hdr->rssi; + + skb_pull(*skb, sizeof (struct rfmon_header)); + + if (skb_headroom(*skb) < sizeof (struct avs_80211_1_header)) { + struct sk_buff *newskb = skb_copy_expand(*skb, + sizeof (struct + avs_80211_1_header), + 0, GFP_ATOMIC); + if (newskb) { + dev_kfree_skb_irq(*skb); + *skb = newskb; + } else + return -1; + /* This behavior is not very subtile... */ + } + + /* make room for the new header and fill it. */ + avs = + (struct avs_80211_1_header *) skb_push(*skb, + sizeof (struct + avs_80211_1_header)); + + avs->version = cpu_to_be32(P80211CAPTURE_VERSION); + avs->length = cpu_to_be32(sizeof (struct avs_80211_1_header)); + avs->mactime = cpu_to_be64(le64_to_cpu(clock)); + avs->hosttime = cpu_to_be64(jiffies); + avs->phytype = cpu_to_be32(6); /*OFDM: 6 for (g), 8 for (a) */ + avs->channel = cpu_to_be32(channel_of_freq(freq)); + avs->datarate = cpu_to_be32(rate * 5); + avs->antenna = cpu_to_be32(0); /*unknown */ + avs->priority = cpu_to_be32(0); /*unknown */ + avs->ssi_type = cpu_to_be32(3); /*2: dBm, 3: raw RSSI */ + avs->ssi_signal = cpu_to_be32(rssi & 0x7f); + avs->ssi_noise = cpu_to_be32(priv->local_iwstatistics.qual.noise); /*better than 'undefined', I assume */ + avs->preamble = cpu_to_be32(0); /*unknown */ + avs->encoding = cpu_to_be32(0); /*unknown */ + } else + skb_pull(*skb, sizeof (struct rfmon_header)); + + (*skb)->protocol = htons(ETH_P_802_2); + (*skb)->mac.raw = (*skb)->data; + (*skb)->pkt_type = PACKET_OTHERHOST; + + return 0; +} + int islpci_eth_receive(islpci_private *priv) { @@ -266,7 +332,8 @@ index = priv->free_data_rx % ISL38XX_CB_RX_QSIZE; size = le16_to_cpu(control_block->rx_data_low[index].size); skb = priv->data_low_rx[index]; - offset = ((unsigned long) le32_to_cpu(control_block->rx_data_low[index].address) - + offset = ((unsigned long) + le32_to_cpu(control_block->rx_data_low[index].address) - (unsigned long) skb->data) & 3; #if VERBOSE > SHOW_ERROR_MESSAGES @@ -314,29 +381,32 @@ /* do some additional sk_buff and network layer parameters */ skb->dev = ndev; - /* take care of monitor mode */ - if (priv->iw_mode == IW_MODE_MONITOR) { - /* The card reports full 802.11 packets but with a 20 bytes - * header and without the FCS. But there a is a bit that - * indicates if the packet is corrupted :-) */ - /* int i; */ - if (skb->data[8] & 0x01){ - /* This one is bad. Drop it !*/ - discard = 1; - /* printk("BAD\n");*/ + /* take care of monitor mode and spy monitoring. */ + if (unlikely(priv->iw_mode == IW_MODE_MONITOR)) + discard = islpci_monitor_rx(priv, &skb); + else { + if (unlikely(skb->data[2 * ETH_ALEN] == 0)) { + /* The packet has a rx_annex. Read it for spy monitoring, Then + * remove it, while keeping the 2 leading MAC addr. + */ + struct iw_quality wstats; + struct rx_annex_header *annex = + (struct rx_annex_header *) skb->data; + wstats.level = annex->rfmon.rssi; + /* The noise value can be a bit outdated if nobody's + * reading wireless stats... */ + wstats.noise = priv->local_iwstatistics.qual.noise; + wstats.qual = wstats.level - wstats.noise; + wstats.updated = 0x07; + /* Update spy records */ + wireless_spy_update(ndev, annex->addr2, &wstats); + + memcpy(skb->data + sizeof (struct rfmon_header), + skb->data, 2 * ETH_ALEN); + skb_pull(skb, sizeof (struct rfmon_header)); } - /* - for(i=0;i<50;i++) - printk("%2.2X:",skb->data[i]); - printk("\n"); - */ - skb_pull(skb, 20); - skb->protocol = htons(ETH_P_802_2); - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_OTHERHOST; - } else skb->protocol = eth_type_trans(skb, ndev); - + } skb->ip_summed = CHECKSUM_NONE; priv->statistics.rx_packets++; priv->statistics.rx_bytes += size; @@ -348,11 +418,10 @@ skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4], skb->data[5]); #endif - if (discard) { - dev_kfree_skb(skb); + if (unlikely(discard)) { + dev_kfree_skb_irq(skb); skb = NULL; - } - else + } else netif_rx(skb); /* increment the read index for the rx data low queue */ @@ -365,11 +434,13 @@ index - priv->free_data_rx < ISL38XX_CB_RX_QSIZE) { /* allocate an sk_buff for received data frames storage * include any required allignment operations */ - if (skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2), skb == NULL) { + skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2); + if (unlikely(skb == NULL)) { /* error allocating an sk_buff structure elements */ DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb \n"); break; } + skb_reserve(skb, (4 - (long) skb->data) & 0x03); /* store the new skb structure pointer */ index = index % ISL38XX_CB_RX_QSIZE; priv->data_low_rx[index] = skb; @@ -385,13 +456,13 @@ pci_map_single(priv->pdev, (void *) skb->data, MAX_FRAGMENT_SIZE_RX + 2, PCI_DMA_FROMDEVICE); - if (priv->pci_map_rx_address[index] == (dma_addr_t) NULL) { + if (unlikely(priv->pci_map_rx_address[index] == (dma_addr_t) NULL)) { /* error mapping the buffer to device accessable memory address */ DEBUG(SHOW_ERROR_MESSAGES, "Error mapping DMA address\n"); /* free the skbuf structure before aborting */ - dev_kfree_skb((struct sk_buff *) skb); + dev_kfree_skb_irq((struct sk_buff *) skb); skb = NULL; break; } @@ -403,7 +474,7 @@ wmb(); /* increment the driver read pointer */ - add_le32p((u32 *) & control_block-> + add_le32p((u32 *) &control_block-> driver_curr_frag[ISL38XX_CB_RX_DATA_LQ], 1); } @@ -414,6 +485,15 @@ } void +islpci_do_reset_and_wake(void *data) +{ + islpci_private *priv = (islpci_private *) data; + islpci_reset(priv, 1); + netif_wake_queue(priv->ndev); + priv->reset_task_pending = 0; +} + +void islpci_eth_tx_timeout(struct net_device *ndev) { islpci_private *priv = netdev_priv(ndev); @@ -422,13 +502,11 @@ /* increment the transmit error counter */ statistics->tx_errors++; -#if 0 - /* don't do this here! we are not allowed to sleep since we are in interrupt context */ - if (islpci_reset(priv)) - printk(KERN_ERR "%s: error on TX timeout card reset!\n", - ndev->name); -#endif + if (!priv->reset_task_pending) { + priv->reset_task_pending = 1; + netif_stop_queue(ndev); + schedule_work(&priv->reset_task); + } - /* netif_wake_queue(ndev); */ return; } --- diff/drivers/net/wireless/prism54/islpci_eth.h 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/net/wireless/prism54/islpci_eth.h 2004-05-27 18:34:17.000000000 +0100 @@ -1,4 +1,4 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.h,v 1.5 2004/01/12 22:16:32 jmaurer Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_eth.h,v 1.7 2004/03/19 20:54:33 ajfa Exp $ * * Copyright (C) 2002 Intersil Americas Inc. * @@ -23,9 +23,51 @@ #include "isl_38xx.h" #include "islpci_dev.h" +struct rfmon_header { + u16 unk0; /* = 0x0000 */ + u16 length; /* = 0x1400 */ + u32 clock; /* 1MHz clock */ + u8 flags; + u8 unk1; + u8 rate; + u8 unk2; + u16 freq; + u16 unk3; + u8 rssi; + u8 padding[3]; +} __attribute__ ((packed)); + +struct rx_annex_header { + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + struct rfmon_header rfmon; +} __attribute__ ((packed)); + +/* wlan-ng (and hopefully others) AVS header, version one. Fields in + * network byte order. */ +#define P80211CAPTURE_VERSION 0x80211001 + +struct avs_80211_1_header { + uint32_t version; + uint32_t length; + uint64_t mactime; + uint64_t hosttime; + uint32_t phytype; + uint32_t channel; + uint32_t datarate; + uint32_t antenna; + uint32_t priority; + uint32_t ssi_type; + int32_t ssi_signal; + int32_t ssi_noise; + uint32_t preamble; + uint32_t encoding; +}; + void islpci_eth_cleanup_transmit(islpci_private *, isl38xx_control_block *); int islpci_eth_transmit(struct sk_buff *, struct net_device *); int islpci_eth_receive(islpci_private *); void islpci_eth_tx_timeout(struct net_device *); +void islpci_do_reset_and_wake(void *data); #endif /* _ISL_GEN_H */ --- diff/drivers/net/wireless/prism54/islpci_hotplug.c 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/net/wireless/prism54/islpci_hotplug.c 2004-05-27 18:34:17.000000000 +0100 @@ -1,4 +1,4 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_hotplug.c,v 1.56 2004/02/26 23:33:02 mcgrof Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_hotplug.c,v 1.60 2004/05/13 13:19:47 msw Exp $ * * Copyright (C) 2002 Intersil Americas Inc. * Copyright (C) 2003 Herbert Valerio Riedel @@ -24,12 +24,13 @@ #include #include /* For __init, __exit */ +#include "prismcompat.h" #include "islpci_dev.h" #include "islpci_mgt.h" /* for pc_debug */ #include "isl_oid.h" #define DRV_NAME "prism54" -#define DRV_VERSION "1.1" +#define DRV_VERSION "1.2" MODULE_AUTHOR("[Intersil] R.Bastings and W.Termorshuizen, The prism54.org Development Team "); MODULE_DESCRIPTION("The Prism54 802.11 Wireless LAN adapter"); --- diff/drivers/net/wireless/prism54/islpci_mgt.c 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/net/wireless/prism54/islpci_mgt.c 2004-05-27 18:34:17.000000000 +0100 @@ -1,4 +1,4 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_mgt.c,v 1.40 2004/02/01 10:57:23 mcgrof Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_mgt.c,v 1.46 2004/04/19 18:33:45 ajfa Exp $ * * Copyright (C) 2002 Intersil Americas Inc. * Copyright 2004 Jens Maurer @@ -22,12 +22,12 @@ #include #include #include -#include #include #include #include +#include "prismcompat.h" #include "isl_38xx.h" #include "islpci_mgt.h" #include "isl_oid.h" /* additional types and defs for isl38xx fw */ @@ -63,7 +63,6 @@ Queue handling for management frames ******************************************************************************/ - /* * Helper function to create a PIMFOR management frame header. */ @@ -86,8 +85,8 @@ { pimfor_header_t *h = data; - while ((void *) h < data + len) { - if(h->flags & PIMFOR_FLAG_LITTLE_ENDIAN) { + while ((void *) h < data + len) { + if (h->flags & PIMFOR_FLAG_LITTLE_ENDIAN) { le32_to_cpus(&h->oid); le32_to_cpus(&h->length); } else { @@ -108,8 +107,8 @@ islpci_mgmt_rx_fill(struct net_device *ndev) { islpci_private *priv = netdev_priv(ndev); - isl38xx_control_block *cb = /* volatile not needed */ - (isl38xx_control_block *) priv->control_block; + isl38xx_control_block *cb = /* volatile not needed */ + (isl38xx_control_block *) priv->control_block; u32 curr = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ]); #if VERBOSE > SHOW_ERROR_MESSAGES @@ -124,7 +123,8 @@ if (buf->mem == NULL) { buf->mem = kmalloc(MGMT_FRAME_SIZE, GFP_ATOMIC); if (!buf->mem) { - printk(KERN_WARNING "Error allocating management frame.\n"); + printk(KERN_WARNING + "Error allocating management frame.\n"); return -ENOMEM; } buf->size = MGMT_FRAME_SIZE; @@ -133,24 +133,24 @@ buf->pci_addr = pci_map_single(priv->pdev, buf->mem, MGMT_FRAME_SIZE, PCI_DMA_FROMDEVICE); - if(!buf->pci_addr) { - printk(KERN_WARNING "Failed to make memory DMA'able\n."); + if (!buf->pci_addr) { + printk(KERN_WARNING + "Failed to make memory DMA'able\n."); return -ENOMEM; } } - /* be safe: always reset control block information */ + /* be safe: always reset control block information */ frag->size = cpu_to_le16(MGMT_FRAME_SIZE); frag->flags = 0; frag->address = cpu_to_le32(buf->pci_addr); curr++; - /* The fragment address in the control block must have - * been written before announcing the frame buffer to - * device */ + /* The fragment address in the control block must have + * been written before announcing the frame buffer to + * device */ wmb(); - cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] = - cpu_to_le32(curr); + cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] = cpu_to_le32(curr); } return 0; } @@ -168,7 +168,7 @@ { islpci_private *priv = netdev_priv(ndev); isl38xx_control_block *cb = - (isl38xx_control_block *) priv->control_block; + (isl38xx_control_block *) priv->control_block; void *p; int err = -EINVAL; unsigned long flags; @@ -242,25 +242,25 @@ priv->mgmt_tx[index] = buf; frag = &cb->tx_data_mgmt[index]; frag->size = cpu_to_le16(frag_len); - frag->flags = 0; /* for any other than the last fragment, set to 1 */ + frag->flags = 0; /* for any other than the last fragment, set to 1 */ frag->address = cpu_to_le32(buf.pci_addr); /* The fragment address in the control block must have * been written before announcing the frame buffer to * device */ wmb(); - cb->driver_curr_frag[ISL38XX_CB_TX_MGMTQ] = cpu_to_le32(curr_frag+1); + cb->driver_curr_frag[ISL38XX_CB_TX_MGMTQ] = cpu_to_le32(curr_frag + 1); spin_unlock_irqrestore(&priv->slock, flags); /* trigger the device */ islpci_trigger(priv); return 0; - error_unlock: + error_unlock: spin_unlock_irqrestore(&priv->slock, flags); - error_free: + error_free: kfree(buf.mem); - error: + error: return err; } @@ -274,50 +274,49 @@ { islpci_private *priv = netdev_priv(ndev); isl38xx_control_block *cb = - (isl38xx_control_block *) priv->control_block; + (isl38xx_control_block *) priv->control_block; u32 curr_frag; #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_receive \n"); #endif - - /* Only once per interrupt, determine fragment range to - * process. This avoids an endless loop (i.e. lockup) if - * frames come in faster than we can process them. */ + /* Only once per interrupt, determine fragment range to + * process. This avoids an endless loop (i.e. lockup) if + * frames come in faster than we can process them. */ curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_RX_MGMTQ]); barrier(); - for ( ; priv->index_mgmt_rx < curr_frag; priv->index_mgmt_rx++) { + for (; priv->index_mgmt_rx < curr_frag; priv->index_mgmt_rx++) { pimfor_header_t *header; u32 index = priv->index_mgmt_rx % ISL38XX_CB_MGMT_QSIZE; struct islpci_membuf *buf = &priv->mgmt_rx[index]; u16 frag_len; int size; struct islpci_mgmtframe *frame; - - /* I have no idea (and no documentation) if flags != 0 - * is possible. Drop the frame, reuse the buffer. */ - if(le16_to_cpu(cb->rx_data_mgmt[index].flags) != 0) { - printk(KERN_WARNING "%s: unknown flags 0x%04x\n", - ndev->name, - le16_to_cpu(cb->rx_data_mgmt[index].flags)); - continue; - } + + /* I have no idea (and no documentation) if flags != 0 + * is possible. Drop the frame, reuse the buffer. */ + if (le16_to_cpu(cb->rx_data_mgmt[index].flags) != 0) { + printk(KERN_WARNING "%s: unknown flags 0x%04x\n", + ndev->name, + le16_to_cpu(cb->rx_data_mgmt[index].flags)); + continue; + } /* The device only returns the size of the header(s) here. */ frag_len = le16_to_cpu(cb->rx_data_mgmt[index].size); /* - * We appear to have no way to tell the device the - * size of a receive buffer. Thus, if this check - * triggers, we likely have kernel heap corruption. */ - if (frag_len > MGMT_FRAME_SIZE) { - printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\ -n", - ndev->name, frag_len, frag_len); - frag_len = MGMT_FRAME_SIZE; - } + * We appear to have no way to tell the device the + * size of a receive buffer. Thus, if this check + * triggers, we likely have kernel heap corruption. */ + if (frag_len > MGMT_FRAME_SIZE) { + printk(KERN_WARNING + "%s: Bogus packet size of %d (%#x).\n", + ndev->name, frag_len, frag_len); + frag_len = MGMT_FRAME_SIZE; + } /* Ensure the results of device DMA are visible to the CPU. */ pci_dma_sync_single(priv->pdev, buf->pci_addr, @@ -339,30 +338,32 @@ #if VERBOSE > SHOW_ERROR_MESSAGES DEBUG(SHOW_PIMFOR_FRAMES, "PIMFOR: op %i, oid 0x%08x, device %i, flags 0x%x length 0x%x \n", - header->operation, header->oid, header->device_id, + header->operation, header->oid, header->device_id, header->flags, header->length); /* display the buffer contents for debugging */ display_buffer((char *) header, PIMFOR_HEADER_SIZE); - display_buffer((char *) header + PIMFOR_HEADER_SIZE, header->length); + display_buffer((char *) header + PIMFOR_HEADER_SIZE, + header->length); #endif /* nobody sends these */ if (header->flags & PIMFOR_FLAG_APPLIC_ORIGIN) { - printk(KERN_DEBUG "%s: errant PIMFOR application frame\n", + printk(KERN_DEBUG + "%s: errant PIMFOR application frame\n", ndev->name); continue; } /* Determine frame size, skipping OID_INL_TUNNEL headers. */ size = PIMFOR_HEADER_SIZE + header->length; - frame = kmalloc(sizeof(struct islpci_mgmtframe) + size, + frame = kmalloc(sizeof (struct islpci_mgmtframe) + size, GFP_ATOMIC); if (!frame) { - printk(KERN_WARNING "%s: Out of memory, cannot handle oid 0x%08x\n", - + printk(KERN_WARNING + "%s: Out of memory, cannot handle oid 0x%08x\n", ndev->name, header->oid); - continue; + continue; } frame->ndev = ndev; memcpy(&frame->buf, header, size); @@ -382,7 +383,7 @@ header->oid, header->device_id, header->flags, header->length); #endif - + /* Create work to handle trap out of interrupt * context. */ INIT_WORK(&frame->ws, prism54_process_trap, frame); @@ -392,14 +393,13 @@ /* Signal the one waiting process that a response * has been received. */ if ((frame = xchg(&priv->mgmt_received, frame)) != NULL) { - printk(KERN_WARNING "%s: mgmt response not collected\n", + printk(KERN_WARNING + "%s: mgmt response not collected\n", ndev->name); kfree(frame); } - #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, - "Wake up Mgmt Queue\n"); + DEBUG(SHOW_TRACING, "Wake up Mgmt Queue\n"); #endif wake_up(&priv->mgmt_wqueue); } @@ -416,22 +416,22 @@ islpci_mgt_cleanup_transmit(struct net_device *ndev) { islpci_private *priv = netdev_priv(ndev); - isl38xx_control_block *cb = /* volatile not needed */ - (isl38xx_control_block *) priv->control_block; + isl38xx_control_block *cb = /* volatile not needed */ + (isl38xx_control_block *) priv->control_block; u32 curr_frag; #if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_cleanup_transmit\n"); + DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_cleanup_transmit\n"); #endif /* Only once per cleanup, determine fragment range to * process. This avoids an endless loop (i.e. lockup) if * the device became confused, incrementing device_curr_frag * rapidly. */ - curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_TX_MGMTQ]); + curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_TX_MGMTQ]); barrier(); - for ( ; priv->index_mgmt_tx < curr_frag; priv->index_mgmt_tx++) { + for (; priv->index_mgmt_tx < curr_frag; priv->index_mgmt_tx++) { int index = priv->index_mgmt_tx % ISL38XX_CB_MGMT_QSIZE; struct islpci_membuf *buf = &priv->mgmt_tx[index]; pci_unmap_single(priv->pdev, buf->pci_addr, buf->size, @@ -456,23 +456,14 @@ const long wait_cycle_jiffies = (ISL38XX_WAIT_CYCLE * 10 * HZ) / 1000; long timeout_left = ISL38XX_MAX_WAIT_CYCLES * wait_cycle_jiffies; int err; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - DEFINE_WAIT(wait); -#else - DECLARE_WAITQUEUE(wait, current); -#endif + PRISM_DEFWAITQ(wait); if (down_interruptible(&priv->mgmt_sem)) return -ERESTARTSYS; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - prepare_to_wait(&priv->mgmt_wqueue, &wait, TASK_UNINTERRUPTIBLE); -#else - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&priv->mgmt_wqueue, &wait); -#endif + PRISM_PREPWAITQ(priv->mgmt_wqueue, wait); err = islpci_mgt_transmit(ndev, operation, oid, senddata, sendlen); - if(err) + if (err) goto out; err = -ETIMEDOUT; @@ -483,13 +474,24 @@ timeleft = schedule_timeout(wait_cycle_jiffies); frame = xchg(&priv->mgmt_received, NULL); if (frame) { - *recvframe = frame; - err = 0; - goto out; - } - if(timeleft == 0) { - printk(KERN_DEBUG "%s: timeout waiting for mgmt response %lu, trigging device\n", - ndev->name, timeout_left); + if (frame->header->oid == oid) { + *recvframe = frame; + err = 0; + goto out; + } else { + printk(KERN_DEBUG + "%s: expecting oid 0x%x, received 0x%x.\n", + ndev->name, (unsigned int) oid, + frame->header->oid); + kfree(frame); + frame = NULL; + } + } + if (timeleft == 0) { + printk(KERN_DEBUG + "%s: timeout waiting for mgmt response %lu, " + "triggering device\n", + ndev->name, timeout_left); islpci_trigger(priv); } timeout_left += timeleft - wait_cycle_jiffies; @@ -497,15 +499,9 @@ printk(KERN_WARNING "%s: timeout waiting for mgmt response\n", ndev->name); - /* TODO: we should reset the device here */ - out: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - finish_wait(&priv->mgmt_wqueue, &wait); -#else - remove_wait_queue(&priv->mgmt_wqueue, &wait); - set_current_state(TASK_RUNNING); -#endif + /* TODO: we should reset the device here */ + out: + PRISM_ENDWAITQ(priv->mgmt_wqueue, wait); up(&priv->mgmt_sem); return err; } - --- diff/drivers/net/wireless/prism54/islpci_mgt.h 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/net/wireless/prism54/islpci_mgt.h 2004-05-27 18:34:17.000000000 +0100 @@ -1,4 +1,4 @@ -/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_mgt.h,v 1.22 2004/01/30 16:24:00 ajfa Exp $ +/* $Header: /var/lib/cvs/prism54-ng/ksrc/islpci_mgt.h,v 1.26 2004/04/26 10:09:58 msw Exp $ * * Copyright (C) 2002 Intersil Americas Inc. * Copyright (C) 2003 Luis R. Rodriguez @@ -24,15 +24,6 @@ #include #include -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) -# include -#else -# include -# define work_struct tq_struct -# define INIT_WORK INIT_TQUEUE -# define schedule_work schedule_task -#endif - /* * Function definitions */ @@ -43,7 +34,7 @@ #define TRACE(devname) K_DEBUG(SHOW_TRACING, VERBOSE, "%s: -> " __FUNCTION__ "()\n", devname) extern int pc_debug; -static const int init_wds = 0; /* help compiler optimize away dead code */ +#define init_wds 0 /* help compiler optimize away dead code */ /* General driver definitions */ --- diff/drivers/net/wireless/prism54/oid_mgt.c 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/net/wireless/prism54/oid_mgt.c 2004-05-27 18:34:17.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 Aurelien Alleaume + * Copyright (C) 2003,2004 Aurelien Alleaume * * 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 @@ -16,6 +16,7 @@ * */ +#include "prismcompat.h" #include "islpci_dev.h" #include "islpci_mgt.h" #include "isl_oid.h" @@ -31,182 +32,206 @@ 5240, 5260, 5280, 5300, 5320 }; -#define OID_U32(x) {x, 0, sizeof(u32), OID_FLAG_U32} -#define OID_U32_C(x) {x, 0, sizeof(u32), OID_FLAG_U32 | OID_FLAG_CACHED} -#define OID_STRUCT(x,s) {x, 0, sizeof(s), 0} -#define OID_STRUCT_C(x,s) {x, 0, sizeof(s), OID_FLAG_CACHED} -#define OID_STRUCT_MLME(x){x, 0, sizeof(struct obj_mlme), 0} -#define OID_STRUCT_MLMEEX(x){x, 0, sizeof(struct obj_mlmeex), OID_FLAG_MLMEEX} +int +channel_of_freq(int f) +{ + int c = 0; + + if ((f >= 2412) && (f <= 2484)) { + while ((c < 14) && (f != frequency_list_bg[c])) + c++; + return (c >= 14) ? 0 : ++c; + } else if ((f >= (int) 5170) && (f <= (int) 5320)) { + while ((c < 12) && (f != frequency_list_a[c])) + c++; + return (c >= 12) ? 0 : (c + 37); + } else + return 0; +} + +#define OID_STRUCT(name,oid,s,t) [name] = {oid, 0, sizeof(s), t} +#define OID_STRUCT_C(name,oid,s,t) OID_STRUCT(name,oid,s,t | OID_FLAG_CACHED) +#define OID_U32(name,oid) OID_STRUCT(name,oid,u32,OID_TYPE_U32) +#define OID_U32_C(name,oid) OID_STRUCT_C(name,oid,u32,OID_TYPE_U32) +#define OID_STRUCT_MLME(name,oid) OID_STRUCT(name,oid,struct obj_mlme,OID_TYPE_MLME) +#define OID_STRUCT_MLMEEX(name,oid) OID_STRUCT(name,oid,struct obj_mlmeex,OID_TYPE_MLMEEX) -#define OID_UNKNOWN(x) {x, 0, 0, 0} +#define OID_UNKNOWN(name,oid) OID_STRUCT(name,oid,0,0) struct oid_t isl_oid[] = { - [GEN_OID_MACADDRESS] = OID_STRUCT(0x00000000, u8[6]), - [GEN_OID_LINKSTATE] = OID_U32(0x00000001), - [GEN_OID_WATCHDOG] = OID_UNKNOWN(0x00000002), - [GEN_OID_MIBOP] = OID_UNKNOWN(0x00000003), - [GEN_OID_OPTIONS] = OID_UNKNOWN(0x00000004), - [GEN_OID_LEDCONFIG] = OID_UNKNOWN(0x00000005), + OID_STRUCT(GEN_OID_MACADDRESS, 0x00000000, u8[6], OID_TYPE_ADDR), + OID_U32(GEN_OID_LINKSTATE, 0x00000001), + OID_UNKNOWN(GEN_OID_WATCHDOG, 0x00000002), + OID_UNKNOWN(GEN_OID_MIBOP, 0x00000003), + OID_UNKNOWN(GEN_OID_OPTIONS, 0x00000004), + OID_UNKNOWN(GEN_OID_LEDCONFIG, 0x00000005), /* 802.11 */ - [DOT11_OID_BSSTYPE] = OID_U32_C(0x10000000), - [DOT11_OID_BSSID] = OID_STRUCT_C(0x10000001, u8[6]), - [DOT11_OID_SSID] = OID_STRUCT_C(0x10000002, struct obj_ssid), - [DOT11_OID_STATE] = OID_U32(0x10000003), - [DOT11_OID_AID] = OID_U32(0x10000004), - [DOT11_OID_COUNTRYSTRING] = OID_STRUCT(0x10000005, u8[4]), - [DOT11_OID_SSIDOVERRIDE] = OID_STRUCT_C(0x10000006, struct obj_ssid), - - [DOT11_OID_MEDIUMLIMIT] = OID_U32(0x11000000), - [DOT11_OID_BEACONPERIOD] = OID_U32_C(0x11000001), - [DOT11_OID_DTIMPERIOD] = OID_U32(0x11000002), - [DOT11_OID_ATIMWINDOW] = OID_U32(0x11000003), - [DOT11_OID_LISTENINTERVAL] = OID_U32(0x11000004), - [DOT11_OID_CFPPERIOD] = OID_U32(0x11000005), - [DOT11_OID_CFPDURATION] = OID_U32(0x11000006), - - [DOT11_OID_AUTHENABLE] = OID_U32_C(0x12000000), - [DOT11_OID_PRIVACYINVOKED] = OID_U32_C(0x12000001), - [DOT11_OID_EXUNENCRYPTED] = OID_U32_C(0x12000002), - [DOT11_OID_DEFKEYID] = OID_U32_C(0x12000003), - [DOT11_OID_DEFKEYX] = {0x12000004, 3, sizeof (struct obj_key), OID_FLAG_CACHED}, /* DOT11_OID_DEFKEY1,...DOT11_OID_DEFKEY4 */ - [DOT11_OID_STAKEY] = OID_UNKNOWN(0x12000008), - [DOT11_OID_REKEYTHRESHOLD] = OID_U32(0x12000009), - [DOT11_OID_STASC] = OID_UNKNOWN(0x1200000a), - - [DOT11_OID_PRIVTXREJECTED] = OID_U32(0x1a000000), - [DOT11_OID_PRIVRXPLAIN] = OID_U32(0x1a000001), - [DOT11_OID_PRIVRXFAILED] = OID_U32(0x1a000002), - [DOT11_OID_PRIVRXNOKEY] = OID_U32(0x1a000003), - - [DOT11_OID_RTSTHRESH] = OID_U32_C(0x13000000), - [DOT11_OID_FRAGTHRESH] = OID_U32_C(0x13000001), - [DOT11_OID_SHORTRETRIES] = OID_U32_C(0x13000002), - [DOT11_OID_LONGRETRIES] = OID_U32_C(0x13000003), - [DOT11_OID_MAXTXLIFETIME] = OID_U32_C(0x13000004), - [DOT11_OID_MAXRXLIFETIME] = OID_U32(0x13000005), - [DOT11_OID_AUTHRESPTIMEOUT] = OID_U32(0x13000006), - [DOT11_OID_ASSOCRESPTIMEOUT] = OID_U32(0x13000007), - - [DOT11_OID_ALOFT_TABLE] = OID_UNKNOWN(0x1d000000), - [DOT11_OID_ALOFT_CTRL_TABLE] = OID_UNKNOWN(0x1d000001), - [DOT11_OID_ALOFT_RETREAT] = OID_UNKNOWN(0x1d000002), - [DOT11_OID_ALOFT_PROGRESS] = OID_UNKNOWN(0x1d000003), - [DOT11_OID_ALOFT_FIXEDRATE] = OID_U32(0x1d000004), - [DOT11_OID_ALOFT_RSSIGRAPH] = OID_UNKNOWN(0x1d000005), - [DOT11_OID_ALOFT_CONFIG] = OID_UNKNOWN(0x1d000006), + OID_U32_C(DOT11_OID_BSSTYPE, 0x10000000), + OID_STRUCT_C(DOT11_OID_BSSID, 0x10000001, u8[6], OID_TYPE_SSID), + OID_STRUCT_C(DOT11_OID_SSID, 0x10000002, struct obj_ssid, + OID_TYPE_SSID), + OID_U32(DOT11_OID_STATE, 0x10000003), + OID_U32(DOT11_OID_AID, 0x10000004), + OID_STRUCT(DOT11_OID_COUNTRYSTRING, 0x10000005, u8[4], OID_TYPE_RAW), + OID_STRUCT_C(DOT11_OID_SSIDOVERRIDE, 0x10000006, struct obj_ssid, + OID_TYPE_SSID), + + OID_U32(DOT11_OID_MEDIUMLIMIT, 0x11000000), + OID_U32_C(DOT11_OID_BEACONPERIOD, 0x11000001), + OID_U32(DOT11_OID_DTIMPERIOD, 0x11000002), + OID_U32(DOT11_OID_ATIMWINDOW, 0x11000003), + OID_U32(DOT11_OID_LISTENINTERVAL, 0x11000004), + OID_U32(DOT11_OID_CFPPERIOD, 0x11000005), + OID_U32(DOT11_OID_CFPDURATION, 0x11000006), + + OID_U32_C(DOT11_OID_AUTHENABLE, 0x12000000), + OID_U32_C(DOT11_OID_PRIVACYINVOKED, 0x12000001), + OID_U32_C(DOT11_OID_EXUNENCRYPTED, 0x12000002), + OID_U32_C(DOT11_OID_DEFKEYID, 0x12000003), + [DOT11_OID_DEFKEYX] = {0x12000004, 3, sizeof (struct obj_key), + OID_FLAG_CACHED | OID_TYPE_KEY}, /* DOT11_OID_DEFKEY1,...DOT11_OID_DEFKEY4 */ + OID_UNKNOWN(DOT11_OID_STAKEY, 0x12000008), + OID_U32(DOT11_OID_REKEYTHRESHOLD, 0x12000009), + OID_UNKNOWN(DOT11_OID_STASC, 0x1200000a), + + OID_U32(DOT11_OID_PRIVTXREJECTED, 0x1a000000), + OID_U32(DOT11_OID_PRIVRXPLAIN, 0x1a000001), + OID_U32(DOT11_OID_PRIVRXFAILED, 0x1a000002), + OID_U32(DOT11_OID_PRIVRXNOKEY, 0x1a000003), + + OID_U32_C(DOT11_OID_RTSTHRESH, 0x13000000), + OID_U32_C(DOT11_OID_FRAGTHRESH, 0x13000001), + OID_U32_C(DOT11_OID_SHORTRETRIES, 0x13000002), + OID_U32_C(DOT11_OID_LONGRETRIES, 0x13000003), + OID_U32_C(DOT11_OID_MAXTXLIFETIME, 0x13000004), + OID_U32(DOT11_OID_MAXRXLIFETIME, 0x13000005), + OID_U32(DOT11_OID_AUTHRESPTIMEOUT, 0x13000006), + OID_U32(DOT11_OID_ASSOCRESPTIMEOUT, 0x13000007), + + OID_UNKNOWN(DOT11_OID_ALOFT_TABLE, 0x1d000000), + OID_UNKNOWN(DOT11_OID_ALOFT_CTRL_TABLE, 0x1d000001), + OID_UNKNOWN(DOT11_OID_ALOFT_RETREAT, 0x1d000002), + OID_UNKNOWN(DOT11_OID_ALOFT_PROGRESS, 0x1d000003), + OID_U32(DOT11_OID_ALOFT_FIXEDRATE, 0x1d000004), + OID_UNKNOWN(DOT11_OID_ALOFT_RSSIGRAPH, 0x1d000005), + OID_UNKNOWN(DOT11_OID_ALOFT_CONFIG, 0x1d000006), [DOT11_OID_VDCFX] = {0x1b000000, 7, 0, 0}, - [DOT11_OID_MAXFRAMEBURST] = OID_U32(0x1b000008), /* in microseconds */ + OID_U32(DOT11_OID_MAXFRAMEBURST, 0x1b000008), - [DOT11_OID_PSM] = OID_U32(0x14000000), - [DOT11_OID_CAMTIMEOUT] = OID_U32(0x14000001), - [DOT11_OID_RECEIVEDTIMS] = OID_U32(0x14000002), - [DOT11_OID_ROAMPREFERENCE] = OID_U32(0x14000003), - - [DOT11_OID_BRIDGELOCAL] = OID_U32(0x15000000), - [DOT11_OID_CLIENTS] = OID_U32(0x15000001), - [DOT11_OID_CLIENTSASSOCIATED] = OID_U32(0x15000002), + OID_U32(DOT11_OID_PSM, 0x14000000), + OID_U32(DOT11_OID_CAMTIMEOUT, 0x14000001), + OID_U32(DOT11_OID_RECEIVEDTIMS, 0x14000002), + OID_U32(DOT11_OID_ROAMPREFERENCE, 0x14000003), + + OID_U32(DOT11_OID_BRIDGELOCAL, 0x15000000), + OID_U32(DOT11_OID_CLIENTS, 0x15000001), + OID_U32(DOT11_OID_CLIENTSASSOCIATED, 0x15000002), [DOT11_OID_CLIENTX] = {0x15000003, 2006, 0, 0}, /* DOT11_OID_CLIENTX,...DOT11_OID_CLIENT2007 */ - [DOT11_OID_CLIENTFIND] = OID_STRUCT(0x150007DB, u8[6]), - [DOT11_OID_WDSLINKADD] = OID_STRUCT(0x150007DC, u8[6]), - [DOT11_OID_WDSLINKREMOVE] = OID_STRUCT(0x150007DD, u8[6]), - [DOT11_OID_EAPAUTHSTA] = OID_STRUCT(0x150007DE, u8[6]), - [DOT11_OID_EAPUNAUTHSTA] = OID_STRUCT(0x150007DF, u8[6]), - [DOT11_OID_DOT1XENABLE] = OID_U32_C(0x150007E0), - [DOT11_OID_MICFAILURE] = OID_UNKNOWN(0x150007E1), - [DOT11_OID_REKEYINDICATE] = OID_UNKNOWN(0x150007E2), - - [DOT11_OID_MPDUTXSUCCESSFUL] = OID_U32(0x16000000), - [DOT11_OID_MPDUTXONERETRY] = OID_U32(0x16000001), - [DOT11_OID_MPDUTXMULTIPLERETRIES] = OID_U32(0x16000002), - [DOT11_OID_MPDUTXFAILED] = OID_U32(0x16000003), - [DOT11_OID_MPDURXSUCCESSFUL] = OID_U32(0x16000004), - [DOT11_OID_MPDURXDUPS] = OID_U32(0x16000005), - [DOT11_OID_RTSSUCCESSFUL] = OID_U32(0x16000006), - [DOT11_OID_RTSFAILED] = OID_U32(0x16000007), - [DOT11_OID_ACKFAILED] = OID_U32(0x16000008), - [DOT11_OID_FRAMERECEIVES] = OID_U32(0x16000009), - [DOT11_OID_FRAMEERRORS] = OID_U32(0x1600000A), - [DOT11_OID_FRAMEABORTS] = OID_U32(0x1600000B), - [DOT11_OID_FRAMEABORTSPHY] = OID_U32(0x1600000C), - - [DOT11_OID_SLOTTIME] = OID_U32(0x17000000), - [DOT11_OID_CWMIN] = OID_U32(0x17000001), - [DOT11_OID_CWMAX] = OID_U32(0x17000002), - [DOT11_OID_ACKWINDOW] = OID_U32(0x17000003), - [DOT11_OID_ANTENNARX] = OID_U32(0x17000004), - [DOT11_OID_ANTENNATX] = OID_U32(0x17000005), - [DOT11_OID_ANTENNADIVERSITY] = OID_U32(0x17000006), - [DOT11_OID_CHANNEL] = OID_U32_C(0x17000007), - [DOT11_OID_EDTHRESHOLD] = OID_U32_C(0x17000008), - [DOT11_OID_PREAMBLESETTINGS] = OID_U32(0x17000009), - [DOT11_OID_RATES] = OID_STRUCT(0x1700000A, u8[IWMAX_BITRATES + 1]), - [DOT11_OID_CCAMODESUPPORTED] = OID_U32(0x1700000B), - [DOT11_OID_CCAMODE] = OID_U32(0x1700000C), - [DOT11_OID_RSSIVECTOR] = OID_U32(0x1700000D), - [DOT11_OID_OUTPUTPOWERTABLE] = OID_U32(0x1700000E), - [DOT11_OID_OUTPUTPOWER] = OID_U32_C(0x1700000F), - [DOT11_OID_SUPPORTEDRATES] = - OID_STRUCT(0x17000010, u8[IWMAX_BITRATES + 1]), - [DOT11_OID_FREQUENCY] = OID_U32_C(0x17000011), - [DOT11_OID_SUPPORTEDFREQUENCIES] = {0x17000012, 0, sizeof (struct - obj_frequencies) - + sizeof (u16) * IWMAX_FREQ, 0}, - - [DOT11_OID_NOISEFLOOR] = OID_U32(0x17000013), - [DOT11_OID_FREQUENCYACTIVITY] = - OID_STRUCT(0x17000014, u8[IWMAX_FREQ + 1]), - [DOT11_OID_IQCALIBRATIONTABLE] = OID_UNKNOWN(0x17000015), - [DOT11_OID_NONERPPROTECTION] = OID_U32(0x17000016), - [DOT11_OID_SLOTSETTINGS] = OID_U32(0x17000017), - [DOT11_OID_NONERPTIMEOUT] = OID_U32(0x17000018), - [DOT11_OID_PROFILES] = OID_U32(0x17000019), - [DOT11_OID_EXTENDEDRATES] = - OID_STRUCT(0x17000020, u8[IWMAX_BITRATES + 1]), - - [DOT11_OID_DEAUTHENTICATE] = OID_STRUCT_MLME(0x18000000), - [DOT11_OID_AUTHENTICATE] = OID_STRUCT_MLME(0x18000001), - [DOT11_OID_DISASSOCIATE] = OID_STRUCT_MLME(0x18000002), - [DOT11_OID_ASSOCIATE] = OID_STRUCT_MLME(0x18000003), - [DOT11_OID_SCAN] = OID_UNKNOWN(0x18000004), - [DOT11_OID_BEACON] = OID_STRUCT_MLMEEX(0x18000005), - [DOT11_OID_PROBE] = OID_STRUCT_MLMEEX(0x18000006), - [DOT11_OID_DEAUTHENTICATEEX] = OID_STRUCT_MLMEEX(0x18000007), - [DOT11_OID_AUTHENTICATEEX] = OID_STRUCT_MLMEEX(0x18000008), - [DOT11_OID_DISASSOCIATEEX] = OID_STRUCT_MLMEEX(0x18000009), - [DOT11_OID_ASSOCIATEEX] = OID_STRUCT_MLMEEX(0x1800000A), - [DOT11_OID_REASSOCIATE] = OID_STRUCT_MLMEEX(0x1800000B), - [DOT11_OID_REASSOCIATEEX] = OID_STRUCT_MLMEEX(0x1800000C), - - [DOT11_OID_NONERPSTATUS] = OID_U32(0x1E000000), - - [DOT11_OID_STATIMEOUT] = OID_U32(0x19000000), - [DOT11_OID_MLMEAUTOLEVEL] = OID_U32_C(0x19000001), - [DOT11_OID_BSSTIMEOUT] = OID_U32(0x19000002), - [DOT11_OID_ATTACHMENT] = OID_UNKNOWN(0x19000003), - [DOT11_OID_PSMBUFFER] = OID_STRUCT_C(0x19000004, struct obj_buffer), - - [DOT11_OID_BSSS] = OID_U32(0x1C000000), - [DOT11_OID_BSSX] = {0x1C000001, 63, sizeof (struct obj_bss), 0}, /*DOT11_OID_BSS1,...,DOT11_OID_BSS64 */ - [DOT11_OID_BSSFIND] = OID_STRUCT(0x1C000042, struct obj_bss), + OID_STRUCT(DOT11_OID_CLIENTFIND, 0x150007DB, u8[6], OID_TYPE_ADDR), + OID_STRUCT(DOT11_OID_WDSLINKADD, 0x150007DC, u8[6], OID_TYPE_ADDR), + OID_STRUCT(DOT11_OID_WDSLINKREMOVE, 0x150007DD, u8[6], OID_TYPE_ADDR), + OID_STRUCT(DOT11_OID_EAPAUTHSTA, 0x150007DE, u8[6], OID_TYPE_ADDR), + OID_STRUCT(DOT11_OID_EAPUNAUTHSTA, 0x150007DF, u8[6], OID_TYPE_ADDR), + OID_U32_C(DOT11_OID_DOT1XENABLE, 0x150007E0), + OID_UNKNOWN(DOT11_OID_MICFAILURE, 0x150007E1), + OID_UNKNOWN(DOT11_OID_REKEYINDICATE, 0x150007E2), + + OID_U32(DOT11_OID_MPDUTXSUCCESSFUL, 0x16000000), + OID_U32(DOT11_OID_MPDUTXONERETRY, 0x16000001), + OID_U32(DOT11_OID_MPDUTXMULTIPLERETRIES, 0x16000002), + OID_U32(DOT11_OID_MPDUTXFAILED, 0x16000003), + OID_U32(DOT11_OID_MPDURXSUCCESSFUL, 0x16000004), + OID_U32(DOT11_OID_MPDURXDUPS, 0x16000005), + OID_U32(DOT11_OID_RTSSUCCESSFUL, 0x16000006), + OID_U32(DOT11_OID_RTSFAILED, 0x16000007), + OID_U32(DOT11_OID_ACKFAILED, 0x16000008), + OID_U32(DOT11_OID_FRAMERECEIVES, 0x16000009), + OID_U32(DOT11_OID_FRAMEERRORS, 0x1600000A), + OID_U32(DOT11_OID_FRAMEABORTS, 0x1600000B), + OID_U32(DOT11_OID_FRAMEABORTSPHY, 0x1600000C), + + OID_U32(DOT11_OID_SLOTTIME, 0x17000000), + OID_U32(DOT11_OID_CWMIN, 0x17000001), + OID_U32(DOT11_OID_CWMAX, 0x17000002), + OID_U32(DOT11_OID_ACKWINDOW, 0x17000003), + OID_U32(DOT11_OID_ANTENNARX, 0x17000004), + OID_U32(DOT11_OID_ANTENNATX, 0x17000005), + OID_U32(DOT11_OID_ANTENNADIVERSITY, 0x17000006), + OID_U32_C(DOT11_OID_CHANNEL, 0x17000007), + OID_U32_C(DOT11_OID_EDTHRESHOLD, 0x17000008), + OID_U32(DOT11_OID_PREAMBLESETTINGS, 0x17000009), + OID_STRUCT(DOT11_OID_RATES, 0x1700000A, u8[IWMAX_BITRATES + 1], + OID_TYPE_RAW), + OID_U32(DOT11_OID_CCAMODESUPPORTED, 0x1700000B), + OID_U32(DOT11_OID_CCAMODE, 0x1700000C), + OID_UNKNOWN(DOT11_OID_RSSIVECTOR, 0x1700000D), + OID_UNKNOWN(DOT11_OID_OUTPUTPOWERTABLE, 0x1700000E), + OID_U32(DOT11_OID_OUTPUTPOWER, 0x1700000F), + OID_STRUCT(DOT11_OID_SUPPORTEDRATES, 0x17000010, + u8[IWMAX_BITRATES + 1], OID_TYPE_RAW), + OID_U32_C(DOT11_OID_FREQUENCY, 0x17000011), + [DOT11_OID_SUPPORTEDFREQUENCIES] = + {0x17000012, 0, sizeof (struct obj_frequencies) + + sizeof (u16) * IWMAX_FREQ, OID_TYPE_FREQUENCIES}, + + OID_U32(DOT11_OID_NOISEFLOOR, 0x17000013), + OID_STRUCT(DOT11_OID_FREQUENCYACTIVITY, 0x17000014, u8[IWMAX_FREQ + 1], + OID_TYPE_RAW), + OID_UNKNOWN(DOT11_OID_IQCALIBRATIONTABLE, 0x17000015), + OID_U32(DOT11_OID_NONERPPROTECTION, 0x17000016), + OID_U32(DOT11_OID_SLOTSETTINGS, 0x17000017), + OID_U32(DOT11_OID_NONERPTIMEOUT, 0x17000018), + OID_U32(DOT11_OID_PROFILES, 0x17000019), + OID_STRUCT(DOT11_OID_EXTENDEDRATES, 0x17000020, + u8[IWMAX_BITRATES + 1], OID_TYPE_RAW), + + OID_STRUCT_MLME(DOT11_OID_DEAUTHENTICATE, 0x18000000), + OID_STRUCT_MLME(DOT11_OID_AUTHENTICATE, 0x18000001), + OID_STRUCT_MLME(DOT11_OID_DISASSOCIATE, 0x18000002), + OID_STRUCT_MLME(DOT11_OID_ASSOCIATE, 0x18000003), + OID_UNKNOWN(DOT11_OID_SCAN, 0x18000004), + OID_STRUCT_MLMEEX(DOT11_OID_BEACON, 0x18000005), + OID_STRUCT_MLMEEX(DOT11_OID_PROBE, 0x18000006), + OID_STRUCT_MLMEEX(DOT11_OID_DEAUTHENTICATEEX, 0x18000007), + OID_STRUCT_MLMEEX(DOT11_OID_AUTHENTICATEEX, 0x18000008), + OID_STRUCT_MLMEEX(DOT11_OID_DISASSOCIATEEX, 0x18000009), + OID_STRUCT_MLMEEX(DOT11_OID_ASSOCIATEEX, 0x1800000A), + OID_STRUCT_MLMEEX(DOT11_OID_REASSOCIATE, 0x1800000B), + OID_STRUCT_MLMEEX(DOT11_OID_REASSOCIATEEX, 0x1800000C), + + OID_U32(DOT11_OID_NONERPSTATUS, 0x1E000000), + + OID_U32(DOT11_OID_STATIMEOUT, 0x19000000), + OID_U32_C(DOT11_OID_MLMEAUTOLEVEL, 0x19000001), + OID_U32(DOT11_OID_BSSTIMEOUT, 0x19000002), + OID_UNKNOWN(DOT11_OID_ATTACHMENT, 0x19000003), + OID_STRUCT_C(DOT11_OID_PSMBUFFER, 0x19000004, struct obj_buffer, + OID_TYPE_BUFFER), + + OID_U32(DOT11_OID_BSSS, 0x1C000000), + [DOT11_OID_BSSX] = {0x1C000001, 63, sizeof (struct obj_bss), + OID_TYPE_BSS}, /*DOT11_OID_BSS1,...,DOT11_OID_BSS64 */ + OID_STRUCT(DOT11_OID_BSSFIND, 0x1C000042, struct obj_bss, OID_TYPE_BSS), [DOT11_OID_BSSLIST] = {0x1C000043, 0, sizeof (struct obj_bsslist) + - sizeof (struct obj_bss[IWMAX_BSS]), 0}, + sizeof (struct obj_bss[IWMAX_BSS]), + OID_TYPE_BSSLIST}, - [OID_INL_TUNNEL] = OID_UNKNOWN(0xFF020000), - [OID_INL_MEMADDR] = OID_UNKNOWN(0xFF020001), - [OID_INL_MEMORY] = OID_UNKNOWN(0xFF020002), - [OID_INL_MODE] = OID_U32_C(0xFF020003), - [OID_INL_COMPONENT_NR] = OID_UNKNOWN(0xFF020004), - [OID_INL_VERSION] = OID_UNKNOWN(0xFF020005), - [OID_INL_INTERFACE_ID] = OID_UNKNOWN(0xFF020006), - [OID_INL_COMPONENT_ID] = OID_UNKNOWN(0xFF020007), - [OID_INL_CONFIG] = OID_U32_C(0xFF020008), - [OID_INL_DOT11D_CONFORMANCE] = OID_U32_C(0xFF02000C), - [OID_INL_PHYCAPABILITIES] = OID_U32(0xFF02000D), - [OID_INL_OUTPUTPOWER] = OID_U32_C(0xFF02000F), + OID_UNKNOWN(OID_INL_TUNNEL, 0xFF020000), + OID_UNKNOWN(OID_INL_MEMADDR, 0xFF020001), + OID_UNKNOWN(OID_INL_MEMORY, 0xFF020002), + OID_U32_C(OID_INL_MODE, 0xFF020003), + OID_UNKNOWN(OID_INL_COMPONENT_NR, 0xFF020004), + OID_UNKNOWN(OID_INL_VERSION, 0xFF020005), + OID_UNKNOWN(OID_INL_INTERFACE_ID, 0xFF020006), + OID_UNKNOWN(OID_INL_COMPONENT_ID, 0xFF020007), + OID_U32_C(OID_INL_CONFIG, 0xFF020008), + OID_U32_C(OID_INL_DOT11D_CONFORMANCE, 0xFF02000C), + OID_U32(OID_INL_PHYCAPABILITIES, 0xFF02000D), + OID_U32_C(OID_INL_OUTPUTPOWER, 0xFF02000F), }; @@ -257,6 +282,134 @@ priv->mib = NULL; } +void +mgt_le_to_cpu(int type, void *data) +{ + switch (type) { + case OID_TYPE_U32: + *(u32 *) data = le32_to_cpu(*(u32 *) data); + break; + case OID_TYPE_BUFFER:{ + struct obj_buffer *buff = data; + buff->size = le32_to_cpu(buff->size); + buff->addr = le32_to_cpu(buff->addr); + break; + } + case OID_TYPE_BSS:{ + struct obj_bss *bss = data; + bss->age = le16_to_cpu(bss->age); + bss->channel = le16_to_cpu(bss->channel); + bss->capinfo = le16_to_cpu(bss->capinfo); + bss->rates = le16_to_cpu(bss->rates); + bss->basic_rates = le16_to_cpu(bss->basic_rates); + break; + } + case OID_TYPE_BSSLIST:{ + struct obj_bsslist *list = data; + int i; + list->nr = le32_to_cpu(list->nr); + for (i = 0; i < list->nr; i++) + mgt_le_to_cpu(OID_TYPE_BSS, &list->bsslist[i]); + break; + } + case OID_TYPE_FREQUENCIES:{ + struct obj_frequencies *freq = data; + int i; + freq->nr = le16_to_cpu(freq->nr); + for (i = 0; i < freq->nr; i++) + freq->mhz[i] = le16_to_cpu(freq->mhz[i]); + break; + } + case OID_TYPE_MLME:{ + struct obj_mlme *mlme = data; + mlme->id = le16_to_cpu(mlme->id); + mlme->state = le16_to_cpu(mlme->state); + mlme->code = le16_to_cpu(mlme->code); + break; + } + case OID_TYPE_MLMEEX:{ + struct obj_mlmeex *mlme = data; + mlme->id = le16_to_cpu(mlme->id); + mlme->state = le16_to_cpu(mlme->state); + mlme->code = le16_to_cpu(mlme->code); + mlme->size = le16_to_cpu(mlme->size); + break; + } + case OID_TYPE_SSID: + case OID_TYPE_KEY: + case OID_TYPE_ADDR: + case OID_TYPE_RAW: + break; + default: + BUG(); + } +} + +static void +mgt_cpu_to_le(int type, void *data) +{ + switch (type) { + case OID_TYPE_U32: + *(u32 *) data = cpu_to_le32(*(u32 *) data); + break; + case OID_TYPE_BUFFER:{ + struct obj_buffer *buff = data; + buff->size = cpu_to_le32(buff->size); + buff->addr = cpu_to_le32(buff->addr); + break; + } + case OID_TYPE_BSS:{ + struct obj_bss *bss = data; + bss->age = cpu_to_le16(bss->age); + bss->channel = cpu_to_le16(bss->channel); + bss->capinfo = cpu_to_le16(bss->capinfo); + bss->rates = cpu_to_le16(bss->rates); + bss->basic_rates = cpu_to_le16(bss->basic_rates); + break; + } + case OID_TYPE_BSSLIST:{ + struct obj_bsslist *list = data; + int i; + list->nr = cpu_to_le32(list->nr); + for (i = 0; i < list->nr; i++) + mgt_cpu_to_le(OID_TYPE_BSS, &list->bsslist[i]); + break; + } + case OID_TYPE_FREQUENCIES:{ + struct obj_frequencies *freq = data; + int i; + freq->nr = cpu_to_le16(freq->nr); + for (i = 0; i < freq->nr; i++) + freq->mhz[i] = cpu_to_le16(freq->mhz[i]); + break; + } + case OID_TYPE_MLME:{ + struct obj_mlme *mlme = data; + mlme->id = cpu_to_le16(mlme->id); + mlme->state = cpu_to_le16(mlme->state); + mlme->code = cpu_to_le16(mlme->code); + break; + } + case OID_TYPE_MLMEEX:{ + struct obj_mlmeex *mlme = data; + mlme->id = cpu_to_le16(mlme->id); + mlme->state = cpu_to_le16(mlme->state); + mlme->code = cpu_to_le16(mlme->code); + mlme->size = cpu_to_le16(mlme->size); + break; + } + case OID_TYPE_SSID: + case OID_TYPE_KEY: + case OID_TYPE_ADDR: + case OID_TYPE_RAW: + break; + default: + BUG(); + } +} + +/* Note : data is modified during this function */ + int mgt_set_request(islpci_private *priv, enum oid_num_t n, int extra, void *data) { @@ -265,7 +418,7 @@ int response_op = PIMFOR_OP_ERROR; int dlen; void *cache, *_data = data; - u32 oid, u; + u32 oid; BUG_ON(OID_NUM_LAST <= n); BUG_ON(extra > isl_oid[n].range); @@ -279,13 +432,11 @@ cache += (cache ? extra * dlen : 0); oid = isl_oid[n].oid + extra; - if (data == NULL) + if (_data == NULL) /* we are requested to re-set a cached value */ _data = cache; - if ((isl_oid[n].flags & OID_FLAG_U32) && data) { - u = cpu_to_le32(*(u32 *) data); - _data = &u; - } + else + mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, _data); /* If we are going to write to the cache, we don't want anyone to read * it -> acquire write lock. * Else we could acquire a read lock to be sure we don't bother the @@ -295,7 +446,7 @@ if (cache) down_write(&priv->mib_sem); - if (islpci_get_state(priv) >= PRV_STATE_INIT) { + if (islpci_get_state(priv) >= PRV_STATE_READY) { ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid, _data, dlen, &response); if (!ret) { @@ -303,7 +454,7 @@ islpci_mgt_release(response); } if (ret || response_op == PIMFOR_OP_ERROR) - ret = -EIO; + ret = -EIO; } else if (!cache) ret = -EIO; @@ -313,6 +464,10 @@ up_write(&priv->mib_sem); } + /* re-set given data to what it was */ + if (data) + mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, data); + return ret; } @@ -324,9 +479,9 @@ int ret = -EIO; int reslen = 0; struct islpci_mgmtframe *response = NULL; - + int dlen; - void *cache, *_res=NULL; + void *cache, *_res = NULL; u32 oid; BUG_ON(OID_NUM_LAST <= n); @@ -345,11 +500,11 @@ if (cache) down_read(&priv->mib_sem); - if (islpci_get_state(priv) >= PRV_STATE_INIT) { + if (islpci_get_state(priv) >= PRV_STATE_READY) { ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, oid, data, dlen, &response); if (ret || !response || - response->header->operation == PIMFOR_OP_ERROR) { + response->header->operation == PIMFOR_OP_ERROR) { if (response) islpci_mgt_release(response); ret = -EIO; @@ -362,20 +517,19 @@ _res = cache; ret = 0; } - if (isl_oid[n].flags & OID_FLAG_U32) { - if (ret) - res->u = 0; - else - res->u = le32_to_cpu(*(u32 *) _res); - } else { + if ((isl_oid[n].flags & OID_FLAG_TYPE) == OID_TYPE_U32) + res->u = ret ? 0 : le32_to_cpu(*(u32 *) _res); + else { res->ptr = kmalloc(reslen, GFP_KERNEL); BUG_ON(res->ptr == NULL); if (ret) memset(res->ptr, 0, reslen); - else + else { memcpy(res->ptr, _res, reslen); + mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, + res->ptr); + } } - if (cache) up_read(&priv->mib_sem); @@ -385,9 +539,9 @@ if (reslen > isl_oid[n].size) printk(KERN_DEBUG "mgt_get_request(0x%x): received data length was bigger " - "than expected (%d > %d). Memory is probably corrupted... ", + "than expected (%d > %d). Memory is probably corrupted...", oid, reslen, isl_oid[n].size); - + return ret; } @@ -404,14 +558,14 @@ int j = 0; u32 oid = t->oid; BUG_ON(data == NULL); - while (j <= t->range){ + while (j <= t->range) { response = NULL; ret |= islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, - oid, data, t->size, + oid, data, t->size, &response); if (response) { ret |= (response->header->operation == - PIMFOR_OP_ERROR); + PIMFOR_OP_ERROR); islpci_mgt_release(response); } j++; @@ -431,13 +585,21 @@ BUG_ON(priv->mib[n] == NULL); memcpy(priv->mib[n], data, isl_oid[n].size); - if (isl_oid[n].flags & OID_FLAG_U32) - *(u32 *) priv->mib[n] = cpu_to_le32(*(u32 *) priv->mib[n]); + mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, priv->mib[n]); } -/* Commits the cache. If something goes wrong, it restarts the device. Lock - * outside - */ +void +mgt_get(islpci_private *priv, enum oid_num_t n, void *res) +{ + BUG_ON(OID_NUM_LAST <= n); + BUG_ON(priv->mib[n] == NULL); + BUG_ON(res == NULL); + + memcpy(res, priv->mib[n], isl_oid[n].size); + mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, res); +} + +/* Commits the cache. Lock outside. */ static enum oid_num_t commit_part1[] = { OID_INL_CONFIG, @@ -460,12 +622,32 @@ OID_INL_OUTPUTPOWER, }; +/* update the MAC addr. */ +static int +mgt_update_addr(islpci_private *priv) +{ + struct islpci_mgmtframe *res; + int ret; + + ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, + isl_oid[GEN_OID_MACADDRESS].oid, NULL, + isl_oid[GEN_OID_MACADDRESS].size, &res); + + if ((ret == 0) && res && (res->header->operation != PIMFOR_OP_ERROR)) + memcpy(priv->ndev->dev_addr, res->data, 6); + else + ret = -EIO; + if (res) + islpci_mgt_release(res); + + return ret; +} + void mgt_commit(islpci_private *priv) { int rvalue; u32 u; - union oid_res_t r; if (islpci_get_state(priv) < PRV_STATE_INIT) return; @@ -481,21 +663,14 @@ u = OID_INL_MODE; rvalue |= mgt_commit_list(priv, &u, 1); + rvalue |= mgt_update_addr(priv); if (rvalue) { /* some request have failed. The device might be in an incoherent state. We should reset it ! */ printk(KERN_DEBUG "%s: mgt_commit has failed. Restart the " - "device \n", priv->ndev->name); + "device \n", priv->ndev->name); } - - /* update the MAC addr. As it's not cached, no lock will be acquired by - * the mgt_get_request - */ - mgt_get_request(priv, GEN_OID_MACADDRESS, 0, NULL, &r); - memcpy(priv->ndev->dev_addr, r.ptr, 6); - kfree(r.ptr); - } /* This will tell you if you are allowed to answer a mlme(ex) request .*/ @@ -522,11 +697,116 @@ { int i; - for (i = 0; i < OID_NUM_LAST - 1; i++) + for (i = 0; i < OID_NUM_LAST; i++) if (isl_oid[i].oid == oid) return i; printk(KERN_DEBUG "looking for an unknown oid 0x%x", oid); + return OID_NUM_LAST; +} + +int +mgt_response_to_str(enum oid_num_t n, union oid_res_t *r, char *str) +{ + switch (isl_oid[n].flags & OID_FLAG_TYPE) { + case OID_TYPE_U32: + return snprintf(str, PRIV_STR_SIZE, "%u\n", r->u); + break; + case OID_TYPE_BUFFER:{ + struct obj_buffer *buff = r->ptr; + return snprintf(str, PRIV_STR_SIZE, + "size=%u\naddr=0x%X\n", buff->size, + buff->addr); + } + break; + case OID_TYPE_BSS:{ + struct obj_bss *bss = r->ptr; + return snprintf(str, PRIV_STR_SIZE, + "age=%u\nchannel=%u\n" + "capinfo=0x%X\nrates=0x%X\n" + "basic_rates=0x%X\n", bss->age, + bss->channel, bss->capinfo, + bss->rates, bss->basic_rates); + } + break; + case OID_TYPE_BSSLIST:{ + struct obj_bsslist *list = r->ptr; + int i, k; + k = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", list->nr); + for (i = 0; i < list->nr; i++) + k += snprintf(str + k, PRIV_STR_SIZE - k, + "bss[%u] : \nage=%u\nchannel=%u\n" + "capinfo=0x%X\nrates=0x%X\n" + "basic_rates=0x%X\n", + i, list->bsslist[i].age, + list->bsslist[i].channel, + list->bsslist[i].capinfo, + list->bsslist[i].rates, + list->bsslist[i].basic_rates); + return k; + } + break; + case OID_TYPE_FREQUENCIES:{ + struct obj_frequencies *freq = r->ptr; + int i, t; + printk("nr : %u\n", freq->nr); + t = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", freq->nr); + for (i = 0; i < freq->nr; i++) + t += snprintf(str + t, PRIV_STR_SIZE - t, + "mhz[%u]=%u\n", i, freq->mhz[i]); + return t; + } + break; + case OID_TYPE_MLME:{ + struct obj_mlme *mlme = r->ptr; + return snprintf(str, PRIV_STR_SIZE, + "id=0x%X\nstate=0x%X\ncode=0x%X\n", + mlme->id, mlme->state, mlme->code); + } + break; + case OID_TYPE_MLMEEX:{ + struct obj_mlmeex *mlme = r->ptr; + return snprintf(str, PRIV_STR_SIZE, + "id=0x%X\nstate=0x%X\n" + "code=0x%X\nsize=0x%X\n", mlme->id, + mlme->state, mlme->code, mlme->size); + } + break; + case OID_TYPE_SSID:{ + struct obj_ssid *ssid = r->ptr; + return snprintf(str, PRIV_STR_SIZE, + "length=%u\noctets=%s\n", + ssid->length, ssid->octets); + } + break; + case OID_TYPE_KEY:{ + struct obj_key *key = r->ptr; + int t, i; + t = snprintf(str, PRIV_STR_SIZE, + "type=0x%X\nlength=0x%X\nkey=0x", + key->type, key->length); + for (i = 0; i < key->length; i++) + t += snprintf(str + t, PRIV_STR_SIZE - t, + "%02X:", key->key[i]); + t += snprintf(str + t, PRIV_STR_SIZE - t, "\n"); + return t; + } + break; + case OID_TYPE_RAW: + case OID_TYPE_ADDR:{ + unsigned char *buff = r->ptr; + int t, i; + t = snprintf(str, PRIV_STR_SIZE, "hex data="); + for (i = 0; i < isl_oid[n].size; i++) + t += snprintf(str + t, PRIV_STR_SIZE - t, + "%02X:", buff[i]); + t += snprintf(str + t, PRIV_STR_SIZE - t, "\n"); + return t; + } + break; + default: + BUG(); + } return 0; } --- diff/drivers/net/wireless/prism54/oid_mgt.h 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/net/wireless/prism54/oid_mgt.h 2004-05-27 18:34:17.000000000 +0100 @@ -28,24 +28,31 @@ void mgt_clean(islpci_private *); +/* I don't know where to put these 3 */ extern const int frequency_list_bg[]; - extern const int frequency_list_a[]; +int channel_of_freq(int); + +void mgt_le_to_cpu(int, void *); int mgt_set_request(islpci_private *, enum oid_num_t, int, void *); int mgt_get_request(islpci_private *, enum oid_num_t, int, void *, - union oid_res_t *); + union oid_res_t *); int mgt_commit_list(islpci_private *, enum oid_num_t *, int); void mgt_set(islpci_private *, enum oid_num_t, void *); +void mgt_get(islpci_private *, enum oid_num_t, void *); + void mgt_commit(islpci_private *); int mgt_mlme_answer(islpci_private *); enum oid_num_t mgt_oidtonum(u32 oid); +int mgt_response_to_str(enum oid_num_t, union oid_res_t *, char *); + #endif /* !defined(_OID_MGT_H) */ /* EOF */ --- diff/drivers/net/yellowfin.c 2004-05-19 22:11:56.000000000 +0100 +++ source/drivers/net/yellowfin.c 2004-05-27 18:34:17.000000000 +0100 @@ -1201,13 +1201,8 @@ break; skb->dev = dev; skb_reserve(skb, 2); /* 16 byte align the IP header */ -#if HAS_IP_COPYSUM eth_copy_and_sum(skb, rx_skb->tail, pkt_len, 0); skb_put(skb, pkt_len); -#else - memcpy(skb_put(skb, pkt_len), - rx_skb->tail, pkt_len); -#endif pci_dma_sync_single_for_device(yp->pci_dev, desc->addr, yp->rx_buf_sz, PCI_DMA_FROMDEVICE); --- diff/drivers/parisc/ccio-dma.c 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/parisc/ccio-dma.c 2004-05-27 18:34:17.000000000 +0100 @@ -44,7 +44,6 @@ #include #include /* for L1_CACHE_BYTES */ #include -#include #include #include #include --- diff/drivers/parisc/ccio-rm-dma.c 2004-05-19 22:12:02.000000000 +0100 +++ source/drivers/parisc/ccio-rm-dma.c 2004-05-27 18:34:17.000000000 +0100 @@ -40,7 +40,6 @@ #include #include -#include #include #include --- diff/drivers/pci/pci.c 2004-05-27 13:41:20.000000000 +0100 +++ source/drivers/pci/pci.c 2004-05-27 18:34:17.000000000 +0100 @@ -247,6 +247,8 @@ int pm; u16 pmcsr; + might_sleep(); + /* bound the state we're entering */ if (state > 3) state = 3; --- diff/drivers/pcmcia/cs.c 2004-05-19 22:12:04.000000000 +0100 +++ source/drivers/pcmcia/cs.c 2004-05-27 18:34:17.000000000 +0100 @@ -789,9 +789,10 @@ return 1; for (i = 0; i < MAX_IO_WIN; i++) { if (s->io[i].NumPorts == 0) { - if (find_io_region(base, num, align, name, s) == 0) { + s->io[i].res = find_io_region(*base, num, align, name, s); + if (s->io[i].res) { s->io[i].Attributes = attr; - s->io[i].BasePort = *base; + s->io[i].BasePort = *base = s->io[i].res->start; s->io[i].NumPorts = s->io[i].InUse = num; break; } else @@ -801,7 +802,8 @@ /* Try to extend top of window */ try = s->io[i].BasePort + s->io[i].NumPorts; if ((*base == 0) || (*base == try)) - if (find_io_region(&try, num, 0, name, s) == 0) { + if (adjust_io_region(s->io[i].res, s->io[i].res->start, + s->io[i].res->end + num, s) == 0) { *base = try; s->io[i].NumPorts += num; s->io[i].InUse += num; @@ -810,7 +812,8 @@ /* Try to extend bottom of window */ try = s->io[i].BasePort - num; if ((*base == 0) || (*base == try)) - if (find_io_region(&try, num, 0, name, s) == 0) { + if (adjust_io_region(s->io[i].res, s->io[i].res->start - num, + s->io[i].res->end, s) == 0) { s->io[i].BasePort = *base = try; s->io[i].NumPorts += num; s->io[i].InUse += num; @@ -824,15 +827,18 @@ ioaddr_t num) { int i; - if(!(s->features & SS_CAP_STATIC_MAP)) - release_region(base, num); + for (i = 0; i < MAX_IO_WIN; i++) { if ((s->io[i].BasePort <= base) && (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) { s->io[i].InUse -= num; /* Free the window if no one else is using it */ - if (s->io[i].InUse == 0) + if (s->io[i].InUse == 0) { s->io[i].NumPorts = 0; + release_resource(s->io[i].res); + kfree(s->io[i].res); + s->io[i].res = NULL; + } } } } --- diff/drivers/pcmcia/cs_internal.h 2004-05-19 22:12:04.000000000 +0100 +++ source/drivers/pcmcia/cs_internal.h 2004-05-27 18:34:17.000000000 +0100 @@ -181,8 +181,10 @@ /* In rsrc_mgr */ void validate_mem(struct pcmcia_socket *s); -int find_io_region(ioaddr_t *base, ioaddr_t num, unsigned long align, +struct resource *find_io_region(unsigned long base, int num, unsigned long align, char *name, struct pcmcia_socket *s); +int adjust_io_region(struct resource *res, unsigned long r_start, + unsigned long r_end, struct pcmcia_socket *s); int find_mem_region(u_long *base, u_long num, u_long align, int low, char *name, struct pcmcia_socket *s); int try_irq(u_int Attributes, int irq, int specific); --- diff/drivers/pcmcia/i82365.c 2004-05-27 13:41:20.000000000 +0100 +++ source/drivers/pcmcia/i82365.c 2004-05-27 18:34:17.000000000 +0100 @@ -1372,8 +1372,15 @@ { int i, ret; - if (driver_register(&i82365_driver)) - return -1; + ret = driver_register(&i82365_driver); + if (ret) + return ret; + + ret = platform_device_register(&i82365_device); + if (ret) { + driver_unregister(&i82365_driver); + return ret; + } printk(KERN_INFO "Intel ISA PCIC probe: "); sockets = 0; @@ -1382,12 +1389,11 @@ if (sockets == 0) { printk("not found.\n"); + platform_device_unregister(&i82365_device); driver_unregister(&i82365_driver); return -ENODEV; } - platform_device_register(&i82365_device); - /* Set up interrupt handler(s) */ if (grab_irq != 0) request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt); --- diff/drivers/pcmcia/pxa2xx_lubbock.c 2004-05-27 13:41:20.000000000 +0100 +++ source/drivers/pcmcia/pxa2xx_lubbock.c 2004-05-27 18:34:17.000000000 +0100 @@ -20,9 +20,11 @@ #include #include #include +#include #include #include +#include #include "sa1111_generic.h" @@ -30,156 +32,170 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) { - unsigned long flags, gpio, misc_wr; - int ret = 1; - struct pcmcia_state new_state; - - local_irq_save(flags); - - gpio = PA_DWR; - misc_wr = LUB_MISC_WR; - - /* Lubbock uses the Maxim MAX1602, with the following connections: - * - * Socket 0 (PCMCIA): - * MAX1602 Lubbock Register - * Pin Signal - * ----- ------- ---------------------- - * A0VPP S0_PWR0 SA-1111 GPIO A<0> - * A1VPP S0_PWR1 SA-1111 GPIO A<1> - * A0VCC S0_PWR2 SA-1111 GPIO A<2> - * A1VCC S0_PWR3 SA-1111 GPIO A<3> - * VX VCC - * VY +3.3V - * 12IN +12V - * CODE +3.3V Cirrus Code, CODE = High (VY) - * - * Socket 1 (CF): - * MAX1602 Lubbock Register - * Pin Signal - * ----- ------- ---------------------- - * A0VPP GND VPP is not connected - * A1VPP GND VPP is not connected - * A0VCC S1_PWR0 MISC_WR<14> - * A1VCC S1_PWR0 MISC_WR<15> - * VX VCC - * VY +3.3V - * 12IN GND VPP is not connected - * CODE +3.3V Cirrus Code, CODE = High (VY) - * - */ - -again: - switch(skt->nr){ - case 0: - - switch(state->Vcc){ - case 0: - gpio &= ~(GPIO_bit(2) | GPIO_bit(3)); - break; - - case 33: - gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(3); - break; - - case 50: - gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2); - break; - - default: - printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc); - ret = -1; - } - - switch(state->Vpp){ - case 0: - gpio &= ~(GPIO_bit(0) | GPIO_bit(1)); - break; - - case 120: - gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(1); - break; - - default: - /* REVISIT: I'm not sure about this? Is this correct? - Is it always safe or do we have potential problems - with bogus combinations of Vcc and Vpp settings? */ - if(state->Vpp == state->Vcc) - gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(0); - else { - printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__, state->Vpp); - ret = -1; - break; - } - } - - break; - - case 1: - switch(state->Vcc){ - case 0: - misc_wr &= ~((1 << 15) | (1 << 14)); - break; - - case 33: - misc_wr = (misc_wr & ~(1 << 15)) | (1 << 14); - gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2); - break; - - case 50: - misc_wr = (misc_wr & ~(1 << 15)) | (1 << 14); - break; - - default: - printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc); - ret = -1; - break; - } - - if(state->Vpp!=state->Vcc && state->Vpp!=0){ - printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__, state->Vpp); - ret = -1; - break; - } - - break; - - default: - ret = -1; - } - - if (ret >= 0) { - sa1111_pcmcia_configure_socket(skt, state); - LUB_MISC_WR = misc_wr; - PA_DWR = gpio; - } + unsigned int pa_dwr_mask, pa_dwr_set, misc_mask, misc_set; + int ret = 0; + + pa_dwr_mask = pa_dwr_set = misc_mask = misc_set = 0; + + /* Lubbock uses the Maxim MAX1602, with the following connections: + * + * Socket 0 (PCMCIA): + * MAX1602 Lubbock Register + * Pin Signal + * ----- ------- ---------------------- + * A0VPP S0_PWR0 SA-1111 GPIO A<0> + * A1VPP S0_PWR1 SA-1111 GPIO A<1> + * A0VCC S0_PWR2 SA-1111 GPIO A<2> + * A1VCC S0_PWR3 SA-1111 GPIO A<3> + * VX VCC + * VY +3.3V + * 12IN +12V + * CODE +3.3V Cirrus Code, CODE = High (VY) + * + * Socket 1 (CF): + * MAX1602 Lubbock Register + * Pin Signal + * ----- ------- ---------------------- + * A0VPP GND VPP is not connected + * A1VPP GND VPP is not connected + * A0VCC S1_PWR0 MISC_WR<14> + * A1VCC S1_PWR1 MISC_WR<15> + * VX VCC + * VY +3.3V + * 12IN GND VPP is not connected + * CODE +3.3V Cirrus Code, CODE = High (VY) + * + */ + + again: + switch (skt->nr) { + case 0: + pa_dwr_mask = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3; + + switch (state->Vcc) { + case 0: /* Hi-Z */ + break; + + case 33: /* VY */ + pa_dwr_set |= GPIO_A3; + break; + + case 50: /* VX */ + pa_dwr_set |= GPIO_A2; + break; + + default: + printk(KERN_ERR "%s(): unrecognized Vcc %u\n", + __FUNCTION__, state->Vcc); + ret = -1; + } + + switch (state->Vpp) { + case 0: /* Hi-Z */ + break; + + case 120: /* 12IN */ + pa_dwr_set |= GPIO_A1; + break; + + default: /* VCC */ + if (state->Vpp == state->Vcc) + pa_dwr_set |= GPIO_A0; + else { + printk(KERN_ERR "%s(): unrecognized Vpp %u\n", + __FUNCTION__, state->Vpp); + ret = -1; + break; + } + } + break; + + case 1: + misc_mask = (1 << 15) | (1 << 14); + + switch (state->Vcc) { + case 0: /* Hi-Z */ + break; + + case 33: /* VY */ + misc_set |= 1 << 15; + break; + + case 50: /* VX */ + misc_set |= 1 << 14; + break; + + default: + printk(KERN_ERR "%s(): unrecognized Vcc %u\n", + __FUNCTION__, state->Vcc); + ret = -1; + break; + } + + if (state->Vpp != state->Vcc && state->Vpp != 0) { + printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", + __FUNCTION__, state->Vpp); + ret = -1; + break; + } + break; + + default: + ret = -1; + } + + if (ret == 0) + ret = sa1111_pcmcia_configure_socket(skt, state); + + if (ret == 0) { + lubbock_set_misc_wr(misc_mask, misc_set); + sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, pa_dwr_set); + } - if (ret > 0) { - ret = 0; #if 1 - /* - * HACK ALERT: - * We can't sense the voltage properly on Lubbock before actually - * applying some power to the socket (catch 22). - * Resense the socket Voltage Sense pins after applying socket power. - */ - sa1111_pcmcia_socket_state(skt, &new_state); - if (state->Vcc == 33 && !new_state.vs_3v && !new_state.vs_Xv) { - /* Switch to 5V, Configure socket with 5V voltage */ - PA_DWR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3)); - PA_DDR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3)); - /* We need to hack around the const qualifier as well to keep this - ugly workaround localized and not force it to the rest of the code. - Barf bags avaliable in the seat pocket in front of you! */ - ((socket_state_t *)state)->Vcc = 50; - ((socket_state_t *)state)->Vpp = 50; - goto again; - } + if (ret == 0 && state->Vcc == 33) { + struct pcmcia_state new_state; + + /* + * HACK ALERT: + * We can't sense the voltage properly on Lubbock before + * actually applying some power to the socket (catch 22). + * Resense the socket Voltage Sense pins after applying + * socket power. + * + * Note: It takes about 2.5ms for the MAX1602 VCC output + * to rise. + */ + mdelay(3); + + sa1111_pcmcia_socket_state(skt, &new_state); + + if (!new_state.vs_3v && !new_state.vs_Xv) { + /* + * Switch to 5V, Configure socket with 5V voltage + */ + lubbock_set_misc_wr(misc_mask, 0); + sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, 0); + + /* + * It takes about 100ms to turn off Vcc. + */ + mdelay(100); + + /* + * We need to hack around the const qualifier as + * well to keep this ugly workaround localized and + * not force it to the rest of the code. Barf bags + * avaliable in the seat pocket in front of you! + */ + ((socket_state_t *)state)->Vcc = 50; + ((socket_state_t *)state)->Vpp = 50; + goto again; + } + } #endif - } - local_irq_restore(flags); - return ret; + return ret; } static struct pcmcia_low_level lubbock_pcmcia_ops = { @@ -196,7 +212,7 @@ #include "pxa2xx_base.h" -int __init pcmcia_lubbock_init(struct device *dev) +int __init pcmcia_lubbock_init(struct sa1111_dev *sadev) { int ret = -ENODEV; @@ -205,16 +221,15 @@ * Set GPIO_A<3:0> to be outputs for the MAX1600, * and switch to standby mode. */ - PA_DWR = 0; - PA_DDR = 0; - PA_SDR = 0; - PA_SSR = 0; + sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0); + sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); + sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); /* Set CF Socket 1 power to standby mode. */ - LUB_MISC_WR &= ~(GPIO_bit(15) | GPIO_bit(14)); + lubbock_set_misc_wr((1 << 15) | (1 << 14), 0); - dev->platform_data = &lubbock_pcmcia_ops; - ret = pxa2xx_drv_pcmcia_probe(dev); + sadev->dev.platform_data = &lubbock_pcmcia_ops; + ret = pxa2xx_drv_pcmcia_probe(&sadev->dev); } return ret; --- diff/drivers/pcmcia/rsrc_mgr.c 2004-05-19 22:12:04.000000000 +0100 +++ source/drivers/pcmcia/rsrc_mgr.c 2004-05-27 18:34:17.000000000 +0100 @@ -550,7 +550,7 @@ for (m = data->map->next; m != data->map; m = m->next) { unsigned long start = m->base; - unsigned long end = m->base + m->num; + unsigned long end = m->base + m->num - 1; /* * If the lower resources are not available, try aligning @@ -569,7 +569,7 @@ if (res->start >= res->end) break; - if ((res->start + size) <= end) + if ((res->start + size - 1) <= end) break; } @@ -580,6 +580,32 @@ res->start = res->end; } +/* + * Adjust an existing IO region allocation, but making sure that we don't + * encroach outside the resources which the user supplied. + */ +int adjust_io_region(struct resource *res, unsigned long r_start, + unsigned long r_end, struct pcmcia_socket *s) +{ + resource_map_t *m; + int ret = -ENOMEM; + + down(&rsrc_sem); + for (m = io_db.next; m != &io_db; m = m->next) { + unsigned long start = m->base; + unsigned long end = m->base + m->num - 1; + + if (start > r_start || r_end > end) + continue; + + ret = adjust_resource(res, r_start, r_end - r_start + 1); + break; + } + up(&rsrc_sem); + + return ret; +} + /*====================================================================== These find ranges of I/O ports or memory addresses that are not @@ -593,40 +619,37 @@ ======================================================================*/ -int find_io_region(ioaddr_t *base, ioaddr_t num, unsigned long align, - char *name, struct pcmcia_socket *s) +struct resource *find_io_region(unsigned long base, int num, + unsigned long align, char *name, struct pcmcia_socket *s) { struct resource *res = make_resource(0, num, IORESOURCE_IO, name); struct pcmcia_align_data data; - unsigned long min = *base; + unsigned long min = base; int ret; if (align == 0) align = 0x10000; data.mask = align - 1; - data.offset = *base & data.mask; + data.offset = base & data.mask; data.map = &io_db; + down(&rsrc_sem); #ifdef CONFIG_PCI if (s->cb_dev) { ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1, min, 0, pcmcia_align, &data); } else #endif - { - down(&rsrc_sem); ret = allocate_resource(&ioport_resource, res, num, min, ~0UL, 0, pcmcia_align, &data); - up(&rsrc_sem); - } + up(&rsrc_sem); if (ret != 0) { kfree(res); - } else { - *base = res->start; + res = NULL; } - return ret; + return res; } int find_mem_region(u_long *base, u_long num, u_long align, @@ -652,6 +675,7 @@ min = 0x100000UL + *base; } + down(&rsrc_sem); #ifdef CONFIG_PCI if (s->cb_dev) { ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, @@ -659,12 +683,9 @@ pcmcia_align, &data); } else #endif - { - down(&rsrc_sem); ret = allocate_resource(&iomem_resource, res, num, min, max, 0, pcmcia_align, &data); - up(&rsrc_sem); - } + up(&rsrc_sem); if (ret == 0 || low) break; low = 1; --- diff/drivers/pcmcia/sa1111_generic.c 2004-05-27 13:41:20.000000000 +0100 +++ source/drivers/pcmcia/sa1111_generic.c 2004-05-27 18:34:17.000000000 +0100 @@ -149,7 +149,7 @@ pcmcia_jornada720_init(&dev->dev); #endif #ifdef CONFIG_ARCH_LUBBOCK - pcmcia_lubbock_init(&dev->dev); + pcmcia_lubbock_init(dev); #endif #ifdef CONFIG_ASSABET_NEPONSET pcmcia_neponset_init(dev); --- diff/drivers/pcmcia/sa1111_generic.h 2004-05-27 13:41:20.000000000 +0100 +++ source/drivers/pcmcia/sa1111_generic.h 2004-05-27 18:34:17.000000000 +0100 @@ -10,6 +10,6 @@ extern int pcmcia_badge4_init(struct device *); extern int pcmcia_jornada720_init(struct device *); -extern int pcmcia_lubbock_init(struct device *); +extern int pcmcia_lubbock_init(struct sa1111_dev *); extern int pcmcia_neponset_init(struct sa1111_dev *); --- diff/drivers/pcmcia/soc_common.c 2004-05-27 13:41:20.000000000 +0100 +++ source/drivers/pcmcia/soc_common.c 2004-05-27 18:34:17.000000000 +0100 @@ -772,3 +772,39 @@ return 0; } + } + + return 0; +} + +static struct notifier_block sa1100_pcmcia_notifier_block = { + .notifier_call = sa1100_pcmcia_notifier +}; + +static int __init sa11xx_pcmcia_init(void) +{ + int ret; + + printk(KERN_INFO "SA11xx PCMCIA\n"); + + ret = cpufreq_register_notifier(&sa1100_pcmcia_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + if (ret < 0) + printk(KERN_ERR "Unable to register CPU frequency change " + "notifier (%d)\n", ret); + + return ret; +} +module_init(sa11xx_pcmcia_init); + +static void __exit sa11xx_pcmcia_exit(void) +{ + cpufreq_unregister_notifier(&sa1100_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); +} + +module_exit(sa11xx_pcmcia_exit); +#endif + +MODULE_AUTHOR("John Dorsey "); +MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-11xx core socket driver"); +MODULE_LICENSE("Dual MPL/GPL"); --- diff/drivers/pnp/isapnp/core.c 2004-05-19 22:12:04.000000000 +0100 +++ source/drivers/pnp/isapnp/core.c 2004-05-27 18:34:17.000000000 +0100 @@ -68,13 +68,8 @@ MODULE_PARM_DESC(isapnp_verbose, "ISA Plug & Play verbose mode"); MODULE_LICENSE("GPL"); -#ifdef CONFIG_X86_PC9800 -#define _PIDXR 0x259 -#define _PNPWRP 0xa59 -#else #define _PIDXR 0x279 #define _PNPWRP 0xa79 -#endif /* short tags */ #define _STAG_PNPVERNO 0x01 --- diff/drivers/sbus/char/openprom.c 2004-05-19 22:12:07.000000000 +0100 +++ source/drivers/sbus/char/openprom.c 2004-05-27 18:34:17.000000000 +0100 @@ -149,7 +149,6 @@ char buffer[OPROMMAXPARAM+1], *buf; struct openpromio *opp; int bufsize, len, error = 0; - extern char saved_command_line[]; static int cnt; if (cmd == OPROMSETOPT) --- diff/drivers/scsi/Kconfig 2004-05-27 13:41:20.000000000 +0100 +++ source/drivers/scsi/Kconfig 2004-05-27 18:34:17.000000000 +0100 @@ -149,19 +149,8 @@ can say Y here to force the SCSI driver to probe for multiple LUNs. A SCSI device with multiple LUNs acts logically like multiple SCSI devices. The vast majority of SCSI devices have only one LUN, and - so most people can say N here and should in fact do so, because it - is safer. - -config SCSI_REPORT_LUNS - bool "Build with SCSI REPORT LUNS support" - depends on SCSI - default y - help - If you want support for SCSI REPORT LUNS, say Y here. - The REPORT LUNS command is useful for devices (such as disk arrays) - with large numbers of LUNs where the LUN values are not contiguous - (sparse LUN). REPORT LUNS scanning is done only for SCSI-3 devices. - Most users can safely answer N here. + so most people can say N here. The max_luns boot/module parameter + allows to override this setting. config SCSI_CONSTANTS bool "Verbose SCSI error reporting (kernel size +=12K)" @@ -238,7 +227,7 @@ depends on DECSTATION && SCSI config BLK_DEV_3W_XXXX_RAID - tristate "3ware Hardware ATA-RAID support" + tristate "3ware 5/6/7/8xxx ATA-RAID support" depends on PCI && SCSI help 3ware is the only hardware ATA-Raid product in Linux to date. @@ -250,6 +239,17 @@ Please read the comments at the top of . +config SCSI_3W_9XXX + tristate "3ware 9xxx SATA-RAID support" + depends on PCI && SCSI + help + This driver supports the 9000 series 3ware SATA-RAID cards. + + + + Please read the comments at the top of + . + config SCSI_7000FASST tristate "7000FASST SCSI support" depends on ISA && SCSI @@ -363,7 +363,7 @@ # All the I2O code and drivers do not seem to be 64bit safe. config SCSI_DPT_I2O tristate "Adaptec I2O RAID support " - depends on !64BIT && SCSI && BROKEN + depends on !64BIT && SCSI help This driver supports all of Adaptec's I2O based RAID controllers as well as the DPT SmartRaid V cards. This is an Adaptec maintained @@ -989,7 +989,7 @@ config SCSI_IPR tristate "IBM Power Linux RAID adapter support" - depends on PCI && SCSI + depends on PCI && SCSI && PPC select FW_LOADER ---help--- This driver supports the IBM Power Linux family RAID adapters. @@ -1721,18 +1721,6 @@ To compile this driver as a module, choose M here: the module will be called esp. -config SCSI_PC980155 - tristate "NEC PC-9801-55 SCSI support" - depends on X86_PC9800 && SCSI - help - If you have the NEC PC-9801-55 SCSI interface card or compatibles - for NEC PC-9801/PC-9821, say Y. - -config WD33C93_PIO - bool - depends on SCSI_PC980155 - default y - # bool 'Cyberstorm Mk III SCSI support (EXPERIMENTAL)' CONFIG_CYBERSTORMIII_SCSI config ZFCP --- diff/drivers/scsi/Makefile 2004-05-27 13:41:20.000000000 +0100 +++ source/drivers/scsi/Makefile 2004-05-27 18:34:17.000000000 +0100 @@ -34,7 +34,6 @@ obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o -obj-$(CONFIG_SCSI_PC980155) += pc980155.o wd33c93.o obj-$(CONFIG_MVME147_SCSI) += mvme147.o wd33c93.o obj-$(CONFIG_SGIWD93_SCSI) += sgiwd93.o wd33c93.o obj-$(CONFIG_CYBERSTORM_SCSI) += NCR53C9x.o cyberstorm.o @@ -109,6 +108,7 @@ obj-$(CONFIG_SCSI_PLUTO) += pluto.o obj-$(CONFIG_SCSI_DECNCR) += NCR53C9x.o dec_esp.o obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o +obj-$(CONFIG_SCSI_3W_9XXX) += 3w-9xxx.o obj-$(CONFIG_SCSI_PPA) += ppa.o obj-$(CONFIG_SCSI_IMM) += imm.o obj-$(CONFIG_JAZZ_ESP) += NCR53C9x.o jazz_esp.o @@ -142,7 +142,6 @@ scsi_devinfo.o scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o -scsi_mod-$(CONFIG_X86_PC9800) += scsi_pc98.o sd_mod-objs := sd.o sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o --- diff/drivers/scsi/NCR53c406a.c 2004-05-19 22:12:08.000000000 +0100 +++ source/drivers/scsi/NCR53c406a.c 2004-05-27 18:34:17.000000000 +0100 @@ -170,7 +170,6 @@ /* Static function prototypes */ static void NCR53c406a_intr(int, void *, struct pt_regs *); static irqreturn_t do_NCR53c406a_intr(int, void *, struct pt_regs *); -static void wait_intr(void); static void chip_init(void); static void calc_port_addr(void); #ifndef IRQ_LEV @@ -665,6 +664,7 @@ return (info_msg); } +#if 0 static void wait_intr(void) { unsigned long i = jiffies + WATCHDOG; @@ -684,6 +684,7 @@ NCR53c406a_intr(0, NULL, NULL); } +#endif static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) { --- diff/drivers/scsi/aacraid/README 2004-05-19 22:12:12.000000000 +0100 +++ source/drivers/scsi/aacraid/README 2004-05-27 18:34:17.000000000 +0100 @@ -38,15 +38,19 @@ (fixed 64bit and 64G memory model, changed confusing naming convention where fibs that go to the hardware are consistently called hw_fibs and not just fibs like the name of the driver tracking structure) +Mark Salyzyn Fixed panic issues and added some new product ids for upcoming hbas. + Original Driver ------------------------- Adaptec Unix OEM Product Group Mailing List ------------------------- -None currently. Also note this is very different to Brian's original driver +linux-aacraid-devel@dell.com (Interested parties troll here) +http://mbserver.adaptec.com/ (Currently more Community Support than Devel Support) +Also note this is very different to Brian's original driver so don't expect him to support it. -Adaptec does support this driver. Contact either tech support or deanna bonds. +Adaptec does support this driver. Contact either tech support or Mark Salyzyn. Original by Brian Boerner February 2001 Rewritten by Alan Cox, November 2001 --- diff/drivers/scsi/aacraid/aacraid.h 2004-05-19 22:12:12.000000000 +0100 +++ source/drivers/scsi/aacraid/aacraid.h 2004-05-27 18:34:17.000000000 +0100 @@ -1,18 +1,20 @@ -//#define dprintk(x) printk x -#define dprintk(x) +#if (!defined(dprintk)) +# define dprintk(x) +#endif /*------------------------------------------------------------------------------ * D E F I N E S *----------------------------------------------------------------------------*/ + #define MAXIMUM_NUM_CONTAINERS 31 #define MAXIMUM_NUM_ADAPTERS 8 -#define AAC_NUM_FIB 578 +#define AAC_NUM_FIB 578 //#define AAC_NUM_IO_FIB 512 -#define AAC_NUM_IO_FIB 100 +#define AAC_NUM_IO_FIB 100 -#define AAC_MAX_TARGET (MAXIMUM_NUM_CONTAINERS+1) -#define AAC_MAX_LUN (8) +#define AAC_MAX_TARGET (MAXIMUM_NUM_CONTAINERS+1) +#define AAC_MAX_LUN (8) #define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff) @@ -241,92 +243,6 @@ }; /* - * Implement our own version of these so we have 64 bit compatability - * The adapter uses these and can only handle 32 bit addresses - */ - -struct aac_list_head { - u32 next; - u32 prev; -}; - -#define AAC_INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (u32)(ulong)(ptr); \ - (ptr)->prev = (u32)(ulong)(ptr); \ -} while (0) -/** - * aac_list_empty - tests whether a list is empty - * @head: the list to test. - */ -static __inline__ int aac_list_empty(struct aac_list_head *head) -{ - return head->next == ((u32)(ulong)head); -} - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static __inline__ void aac_list_add(struct aac_list_head * n, - struct aac_list_head * prev, - struct aac_list_head * next) -{ - next->prev = (u32)(ulong)n; - n->next = (u32)(ulong)next; - n->prev = (u32)(ulong)prev; - prev->next = (u32)(ulong)n; -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static __inline__ void aac_list_add_tail(struct aac_list_head *n, struct aac_list_head *head) -{ - aac_list_add(n, (struct aac_list_head*)(ulong)(head->prev), head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static __inline__ void __aac_list_del(struct aac_list_head * p, - struct aac_list_head * n) -{ - n->prev = (u32)(ulong)p; - p->next = (u32)(ulong)n; -} - -/** - * aac_list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is in an undefined state. - */ -static __inline__ void aac_list_del(struct aac_list_head *entry) -{ - __aac_list_del((struct aac_list_head*)(ulong)entry->prev,(struct aac_list_head*)(ulong) entry->next); - entry->next = entry->prev = 0; -} - -/** - * aac_list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define aac_list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(ulong)(&((type *)0)->member))) - -/* * Assign type values to the FSA communication data structures */ @@ -339,11 +255,11 @@ #define FsaNormal 1 #define FsaHigh 2 - /* * Define the FIB. The FIB is the where all the requested data and * command information are put to the application on the FSA adapter. */ + struct aac_fibhdr { u32 XferState; // Current transfer state for this CCB u16 Command; // Routing information for the destination @@ -359,13 +275,9 @@ u32 _ReceiverTimeStart; // Timestamp for receipt of fib u32 _ReceiverTimeDone; // Timestamp for completion of fib } _s; - struct aac_list_head _FibLinks; // Used to link Adapter Initiated Fibs on the host -// struct list_head _FibLinks; // Used to link Adapter Initiated Fibs on the host } _u; }; -#define FibLinks _u._FibLinks - #define FIB_DATA_SIZE_IN_BYTES (512 - sizeof(struct aac_fibhdr)) @@ -558,12 +470,11 @@ spinlock_t lockdata; /* Actual lock (used only on one side of the lock) */ unsigned long SavedIrql; /* Previous IRQL when the spin lock is taken */ u32 padding; /* Padding - FIXME - can remove I believe */ - struct aac_list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ -// struct list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ - /* only valid for command queues which receive entries from the adapter. */ - struct list_head pendingq; /* A queue of outstanding fib's to the adapter. */ - u32 numpending; /* Number of entries on outstanding queue. */ - struct aac_dev * dev; /* Back pointer to adapter structure */ + struct list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ + /* only valid for command queues which receive entries from the adapter. */ + struct list_head pendingq; /* A queue of outstanding fib's to the adapter. */ + u32 numpending; /* Number of entries on outstanding queue. */ + struct aac_dev * dev; /* Back pointer to adapter structure */ }; /* @@ -744,7 +655,7 @@ struct semaphore wait_sem; // this is used to wait for the next fib to arrive. int wait; // Set to true when thread is in WaitForSingleObject unsigned long count; // total number of FIBs on FibList - struct aac_list_head hw_fib_list; // this holds hw_fibs which should be 32 bit addresses + struct list_head fib_list; // this holds fibs and their attachd hw_fibs }; struct fsa_scsi_hba { @@ -781,7 +692,11 @@ * Outstanding I/O queue. */ struct list_head queue; - + /* + * And for the internal issue/reply queues (we may be able + * to merge these two) + */ + struct list_head fiblink; void *data; struct hw_fib *hw_fib; /* Actual shared object */ dma_addr_t hw_fib_pa; /* physical address of hw_fib*/ @@ -836,19 +751,19 @@ /* * Supported Options */ -#define AAC_OPT_SNAPSHOT cpu_to_le32(1) -#define AAC_OPT_CLUSTERS cpu_to_le32(1<<1) -#define AAC_OPT_WRITE_CACHE cpu_to_le32(1<<2) -#define AAC_OPT_64BIT_DATA cpu_to_le32(1<<3) -#define AAC_OPT_HOST_TIME_FIB cpu_to_le32(1<<4) -#define AAC_OPT_RAID50 cpu_to_le32(1<<5) -#define AAC_OPT_4GB_WINDOW cpu_to_le32(1<<6) -#define AAC_OPT_SCSI_UPGRADEABLE cpu_to_le32(1<<7) -#define AAC_OPT_SOFT_ERR_REPORT cpu_to_le32(1<<8) -#define AAC_OPT_SUPPORTED_RECONDITION cpu_to_le32(1<<9) -#define AAC_OPT_SGMAP_HOST64 cpu_to_le32(1<<10) -#define AAC_OPT_ALARM cpu_to_le32(1<<11) -#define AAC_OPT_NONDASD cpu_to_le32(1<<12) +#define AAC_OPT_SNAPSHOT cpu_to_le32(1) +#define AAC_OPT_CLUSTERS cpu_to_le32(1<<1) +#define AAC_OPT_WRITE_CACHE cpu_to_le32(1<<2) +#define AAC_OPT_64BIT_DATA cpu_to_le32(1<<3) +#define AAC_OPT_HOST_TIME_FIB cpu_to_le32(1<<4) +#define AAC_OPT_RAID50 cpu_to_le32(1<<5) +#define AAC_OPT_4GB_WINDOW cpu_to_le32(1<<6) +#define AAC_OPT_SCSI_UPGRADEABLE cpu_to_le32(1<<7) +#define AAC_OPT_SOFT_ERR_REPORT cpu_to_le32(1<<8) +#define AAC_OPT_SUPPORTED_RECONDITION cpu_to_le32(1<<9) +#define AAC_OPT_SGMAP_HOST64 cpu_to_le32(1<<10) +#define AAC_OPT_ALARM cpu_to_le32(1<<11) +#define AAC_OPT_NONDASD cpu_to_le32(1<<12) struct aac_dev { @@ -862,11 +777,10 @@ */ dma_addr_t hw_fib_pa; struct hw_fib *hw_fib_va; - ulong fib_base_va; + struct hw_fib *aif_base_va; /* * Fib Headers */ -// dmb struct fib fibs[AAC_NUM_FIB]; /* Doing it here takes up too much from the scsi pool*/ struct fib *fibs; struct fib *free_fib; @@ -887,7 +801,6 @@ unsigned long fsrev; /* Main driver's revision number */ struct aac_init *init; /* Holds initialization info to communicate with adapter */ -// void * init_pa; /* Holds physical address of the init struct */ dma_addr_t init_pa; /* Holds physical address of the init struct */ struct pci_dev *pdev; /* Our PCI interface */ @@ -898,7 +811,7 @@ struct Scsi_Host *scsi_host_ptr; struct fsa_scsi_hba fsa_dev; - int thread_pid; + pid_t thread_pid; int cardtype; /* --- diff/drivers/scsi/aacraid/commctrl.c 2004-05-19 22:12:12.000000000 +0100 +++ source/drivers/scsi/aacraid/commctrl.c 2004-05-27 18:34:17.000000000 +0100 @@ -148,7 +148,7 @@ * the list to 0. */ fibctx->count = 0; - AAC_INIT_LIST_HEAD(&fibctx->hw_fib_list); + INIT_LIST_HEAD(&fibctx->fib_list); fibctx->jiffies = jiffies/HZ; /* * Now add this context onto the adapter's @@ -179,7 +179,7 @@ { struct fib_ioctl f; struct aac_fib_context *fibctx, *aifcp; - struct hw_fib * hw_fib; + struct fib *fib; int status; struct list_head * entry; int found; @@ -222,25 +222,27 @@ * -EAGAIN */ return_fib: - if (!aac_list_empty(&fibctx->hw_fib_list)) { - struct aac_list_head * entry; + if (!list_empty(&fibctx->fib_list)) { + struct list_head * entry; /* * Pull the next fib from the fibs */ - entry = (struct aac_list_head*)(ulong)fibctx->hw_fib_list.next; - aac_list_del(entry); + entry = fibctx->fib_list.next; + list_del(entry); - hw_fib = aac_list_entry(entry, struct hw_fib, header.FibLinks); + fib = list_entry(entry, struct fib, fiblink); fibctx->count--; spin_unlock_irqrestore(&dev->fib_lock, flags); - if (copy_to_user(f.fib, hw_fib, sizeof(struct hw_fib))) { - kfree(hw_fib); + if (copy_to_user(f.fib, fib->hw_fib, sizeof(struct hw_fib))) { + kfree(fib->hw_fib); + kfree(fib); return -EFAULT; } /* * Free the space occupied by this copy of the fib. */ - kfree(hw_fib); + kfree(fib->hw_fib); + kfree(fib); status = 0; fibctx->jiffies = jiffies/HZ; } else { @@ -262,24 +264,25 @@ int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx) { - struct hw_fib *hw_fib; + struct fib *fib; /* * First free any FIBs that have not been consumed. */ - while (!aac_list_empty(&fibctx->hw_fib_list)) { - struct aac_list_head * entry; + while (!list_empty(&fibctx->fib_list)) { + struct list_head * entry; /* * Pull the next fib from the fibs */ - entry = (struct aac_list_head*)(ulong)(fibctx->hw_fib_list.next); - aac_list_del(entry); - hw_fib = aac_list_entry(entry, struct hw_fib, header.FibLinks); + entry = fibctx->fib_list.next; + list_del(entry); + fib = list_entry(entry, struct fib, fiblink); fibctx->count--; /* * Free the space occupied by this copy of the fib. */ - kfree(hw_fib); + kfree(fib->hw_fib); + kfree(fib); } /* * Remove the Context from the AdapterFibContext List --- diff/drivers/scsi/aacraid/comminit.c 2004-05-19 22:12:12.000000000 +0100 +++ source/drivers/scsi/aacraid/comminit.c 2004-05-27 18:34:17.000000000 +0100 @@ -81,9 +81,9 @@ * Adapter Fibs are the first thing allocated so that they * start page aligned */ - dev->fib_base_va = (ulong)base; + dev->aif_base_va = (struct hw_fib *)base; - init->AdapterFibsVirtualAddress = cpu_to_le32((u32)(ulong)phys); + init->AdapterFibsVirtualAddress = cpu_to_le32(0); init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys); init->AdapterFibsSize = cpu_to_le32(fibsize); init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib)); @@ -94,6 +94,9 @@ * mapping system, but older Firmware did, and had *troubles* dealing * with the math overloading past 32 bits, thus we must limit this * field. + * + * FIXME: this assumes the memory is mapped zero->n, which isnt + * always true on real computers. */ if ((num_physpages << (PAGE_SHIFT - 12)) <= AAC_MAX_HOSTPHYSMEMPAGES) { init->HostPhysMemPages = @@ -140,7 +143,7 @@ q->dev = dev; INIT_LIST_HEAD(&q->pendingq); init_waitqueue_head(&q->cmdready); - AAC_INIT_LIST_HEAD(&q->cmdq); + INIT_LIST_HEAD(&q->cmdq); init_waitqueue_head(&q->qfull); spin_lock_init(&q->lockdata); q->lock = &q->lockdata; --- diff/drivers/scsi/aacraid/commsup.c 2004-05-19 22:12:12.000000000 +0100 +++ source/drivers/scsi/aacraid/commsup.c 2004-05-27 18:34:17.000000000 +0100 @@ -133,13 +133,10 @@ unsigned long flags; spin_lock_irqsave(&dev->fib_lock, flags); fibptr = dev->free_fib; - while(!fibptr){ - spin_unlock_irqrestore(&dev->fib_lock, flags); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - spin_lock_irqsave(&dev->fib_lock, flags); - fibptr = dev->free_fib; - } + /* Cannot sleep here or you get hangs. Instead we did the + maths at compile time. */ + if(!fibptr) + BUG(); dev->free_fib = fibptr->next; spin_unlock_irqrestore(&dev->fib_lock, flags); /* @@ -290,7 +287,7 @@ } } -/*Command thread: * +/** * aac_queue_get - get the next free QE * @dev: Adapter * @index: Returned index @@ -450,8 +447,7 @@ * Map the fib into 32bits by using the fib number */ -// hw_fib->header.SenderFibAddress = ((u32)(fibptr-dev->fibs)) << 1; - hw_fib->header.SenderFibAddress = cpu_to_le32((u32)(ulong)fibptr->hw_fib_pa); + hw_fib->header.SenderFibAddress = cpu_to_le32(((u32)(fibptr-dev->fibs)) << 1); hw_fib->header.SenderData = (u32)(fibptr - dev->fibs); /* * Set FIB state to indicate where it came from and if we want a @@ -492,7 +488,7 @@ dprintk((KERN_DEBUG " Command = %d.\n", hw_fib->header.Command)); dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState)); dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib)); - dprintk((KERN_DEBUG " hw_fib pa being sent=%xl\n",(ulong)fibptr->hw_fib_pa)); + dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); /* * Fill in the Callback and CallbackContext if we are not @@ -806,8 +802,8 @@ int aac_command_thread(struct aac_dev * dev) { - struct hw_fib *hw_fib, *newfib; - struct fib fibptr; /* for error logging */ + struct hw_fib *hw_fib, *hw_newfib; + struct fib *fib, *newfib; struct aac_queue_block *queues = dev->queues; struct aac_fib_context *fibctx; unsigned long flags; @@ -828,42 +824,44 @@ * Let the DPC know it has a place to send the AIF's to. */ dev->aif_thread = 1; - memset(&fibptr, 0, sizeof(struct fib)); add_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait); set_current_state(TASK_INTERRUPTIBLE); while(1) { spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); - while(!aac_list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) { - struct aac_list_head *entry; + while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) { + struct list_head *entry; struct aac_aifcmd * aifcmd; set_current_state(TASK_RUNNING); - entry = (struct aac_list_head*)(ulong)(queues->queue[HostNormCmdQueue].cmdq.next); - dprintk(("aacraid: Command thread: removing fib from cmdq (%p)\n",entry)); - aac_list_del(entry); + entry = queues->queue[HostNormCmdQueue].cmdq.next; + list_del(entry); spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags); - hw_fib = aac_list_entry(entry, struct hw_fib, header.FibLinks); + fib = list_entry(entry, struct fib, fiblink); /* * We will process the FIB here or pass it to a * worker thread that is TBD. We Really can't * do anything at this point since we don't have * anything defined for this thread to do. */ - memset(&fibptr, 0, sizeof(struct fib)); - fibptr.type = FSAFS_NTC_FIB_CONTEXT; - fibptr.size = sizeof( struct fib ); - fibptr.hw_fib = hw_fib; - fibptr.data = hw_fib->data; - fibptr.dev = dev; + hw_fib = fib->hw_fib; + memset(fib, 0, sizeof(struct fib)); + fib->type = FSAFS_NTC_FIB_CONTEXT; + fib->size = sizeof( struct fib ); + fib->hw_fib = hw_fib; + fib->data = hw_fib->data; + fib->dev = dev; /* * We only handle AifRequest fibs from the adapter. */ aifcmd = (struct aac_aifcmd *) hw_fib->data; - if (aifcmd->command == le16_to_cpu(AifCmdDriverNotify)) { - aac_handle_aif(dev, &fibptr); + if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) { + /* Handle Driver Notify Events */ + aac_handle_aif(dev, fib); + *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); + fib_adapter_complete(fib, sizeof(u32)); } else { struct list_head *entry; /* The u32 here is important and intended. We are using @@ -872,6 +870,10 @@ u32 time_now, time_last; unsigned long flagv; + /* Sniff events */ + if (aifcmd->command == cpu_to_le32(AifCmdEventNotify)) + aac_handle_aif(dev, fib); + time_now = jiffies/HZ; spin_lock_irqsave(&dev->fib_lock, flagv); @@ -893,6 +895,11 @@ */ if (fibctx->count > 20) { + /* + * It's *not* jiffies folks, + * but jiffies / HZ so do not + * panic ... + */ time_last = fibctx->jiffies; /* * Has it been > 2 minutes @@ -909,17 +916,20 @@ * Warning: no sleep allowed while * holding spinlock */ - newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); - if (newfib) { + hw_newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); + newfib = kmalloc(sizeof(struct fib), GFP_ATOMIC); + if (newfib && hw_newfib) { /* * Make the copy of the FIB */ - memcpy(newfib, hw_fib, sizeof(struct hw_fib)); + memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib)); + memcpy(newfib, fib, sizeof(struct fib)); + newfib->hw_fib = hw_newfib; /* * Put the FIB onto the * fibctx's fibs */ - aac_list_add_tail(&newfib->header.FibLinks, &fibctx->hw_fib_list); + list_add_tail(&newfib->fiblink, &fibctx->fib_list); fibctx->count++; /* * Set the event to wake up the @@ -928,6 +938,10 @@ up(&fibctx->wait_sem); } else { printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); + if(newfib) + kfree(newfib); + if(hw_newfib) + kfree(hw_newfib); } entry = entry->next; } @@ -935,10 +949,11 @@ * Set the status of this FIB */ *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); - fib_adapter_complete(&fibptr, sizeof(u32)); + fib_adapter_complete(fib, sizeof(u32)); spin_unlock_irqrestore(&dev->fib_lock, flagv); } spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); + kfree(fib); } /* * There are no more AIF's --- diff/drivers/scsi/aacraid/dpcsup.c 2004-05-19 22:12:12.000000000 +0100 +++ source/drivers/scsi/aacraid/dpcsup.c 2004-05-27 18:34:17.000000000 +0100 @@ -70,12 +70,12 @@ */ while(aac_consumer_get(dev, q, &entry)) { - u32 fast ; - fast = (entry->addr & cpu_to_le32(0x01)); - hwfib = (struct hw_fib *)((char *)dev->hw_fib_va + - ((entry->addr & ~0x01) - dev->hw_fib_pa)); - fib = &dev->fibs[hwfib->header.SenderData]; - + int fast; + u32 index = le32_to_cpu(entry->addr); + fast = index & 0x01; + fib = &dev->fibs[index >> 1]; + hwfib = fib->hw_fib; + aac_consumer_free(dev, q, HostNormRespQueue); /* * Remove this fib from the Outstanding I/O queue. @@ -169,29 +169,44 @@ */ while(aac_consumer_get(dev, q, &entry)) { + struct fib fibctx; struct hw_fib * hw_fib; - hw_fib = (struct hw_fib *)((char *)dev->hw_fib_va + - ((entry->addr & ~0x01) - dev->hw_fib_pa)); - - if (dev->aif_thread) { - aac_list_add_tail(&hw_fib->header.FibLinks, &q->cmdq); + u32 index; + struct fib *fib = &fibctx; + + index = le32_to_cpu(entry->addr) / sizeof(struct hw_fib); + hw_fib = &dev->aif_base_va[index]; + + /* + * Allocate a FIB at all costs. For non queued stuff + * we can just use the stack so we are happy. We need + * a fib object in order to manage the linked lists + */ + if (dev->aif_thread) + if((fib = kmalloc(sizeof(struct fib), GFP_ATOMIC)) == NULL) + fib = &fibctx; + + memset(fib, 0, sizeof(struct fib)); + INIT_LIST_HEAD(&fib->fiblink); + fib->type = FSAFS_NTC_FIB_CONTEXT; + fib->size = sizeof(struct fib); + fib->hw_fib = hw_fib; + fib->data = hw_fib->data; + fib->dev = dev; + + + if (dev->aif_thread && fib != &fibctx) { + list_add_tail(&fib->fiblink, &q->cmdq); aac_consumer_free(dev, q, HostNormCmdQueue); wake_up_interruptible(&q->cmdready); } else { - struct fib fibctx; aac_consumer_free(dev, q, HostNormCmdQueue); spin_unlock_irqrestore(q->lock, flags); - memset(&fibctx, 0, sizeof(struct fib)); - fibctx.type = FSAFS_NTC_FIB_CONTEXT; - fibctx.size = sizeof(struct fib); - fibctx.hw_fib = hw_fib; - fibctx.data = hw_fib->data; - fibctx.dev = dev; /* * Set the status of this FIB */ *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); - fib_adapter_complete(&fibctx, sizeof(u32)); + fib_adapter_complete(fib, sizeof(u32)); spin_lock_irqsave(q->lock, flags); } } --- diff/drivers/scsi/aacraid/sa.c 2004-05-19 22:12:12.000000000 +0100 +++ source/drivers/scsi/aacraid/sa.c 2004-05-27 18:34:17.000000000 +0100 @@ -419,6 +419,11 @@ * Start any kernel threads needed */ dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0); + if (dev->thread_pid < 0) { + printk(KERN_ERR "aacraid: Unable to create command thread.\n"); + return -1; + } + /* * Tell the adapter that all is configure, and it can start * accepting requests --- diff/drivers/scsi/advansys.c 2004-05-19 22:12:08.000000000 +0100 +++ source/drivers/scsi/advansys.c 2004-05-27 18:34:17.000000000 +0100 @@ -801,6 +801,7 @@ #include #include #include +#include #include #include @@ -4214,7 +4215,7 @@ STATIC int asc_execute_scsi_cmnd(Scsi_Cmnd *); STATIC int asc_build_req(asc_board_t *, Scsi_Cmnd *); STATIC int adv_build_req(asc_board_t *, Scsi_Cmnd *, ADV_SCSI_REQ_Q **); -STATIC int adv_get_sglist(asc_board_t *, adv_req_t *, Scsi_Cmnd *); +STATIC int adv_get_sglist(asc_board_t *, adv_req_t *, Scsi_Cmnd *, int); STATIC void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *); STATIC void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); STATIC void adv_async_callback(ADV_DVC_VAR *, uchar); @@ -6381,9 +6382,30 @@ ASC_DBG(2, "asc_scsi_done_list: begin\n"); while (scp != NULL) { + asc_board_t *boardp; + struct pci_dev *pci_dev; + int dir; + ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong) scp); tscp = REQPNEXT(scp); scp->host_scribble = NULL; + + boardp = ASC_BOARDP(scp->device->host); + + if (ASC_NARROW_BOARD(boardp)) + pci_dev = boardp->dvc_cfg.asc_dvc_cfg.pci_dev; + else + pci_dev = boardp->dvc_cfg.adv_dvc_cfg.pci_dev; + + dir = scsi_to_pci_dma_dir(scp->sc_data_direction); + + if (scp->use_sg) + pci_unmap_sg(pci_dev, (struct scatterlist *)scp->request_buffer, + scp->use_sg, dir); + else if (scp->request_bufflen) + pci_unmap_single(pci_dev, scp->SCp.dma_handle, + scp->request_bufflen, dir); + ASC_STATS(scp->device->host, done); ASC_ASSERT(scp->scsi_done != NULL); if (from_isr) @@ -6619,6 +6641,9 @@ STATIC int asc_build_req(asc_board_t *boardp, Scsi_Cmnd *scp) { + struct pci_dev *pci_dev = boardp->dvc_cfg.asc_dvc_cfg.pci_dev; + int dir = scsi_to_pci_dma_dir(scp->sc_data_direction); + /* * Mutually exclusive access is required to 'asc_scsi_q' and * 'asc_sg_head' until after the request is started. @@ -6679,8 +6704,10 @@ * CDB request of single contiguous buffer. */ ASC_STATS(scp->device->host, cont_cnt); - asc_scsi_q.q1.data_addr = - cpu_to_le32(virt_to_bus(scp->request_buffer)); + scp->SCp.dma_handle = scp->request_bufflen ? + pci_map_single(pci_dev, scp->request_buffer, + scp->request_bufflen, dir) : 0; + asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle); asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen); ASC_STATS_ADD(scp->device->host, cont_xfer, ASC_CEILING(scp->request_bufflen, 512)); @@ -6691,12 +6718,17 @@ * CDB scatter-gather request list. */ int sgcnt; + int use_sg; struct scatterlist *slp; - if (scp->use_sg > scp->device->host->sg_tablesize) { + slp = (struct scatterlist *)scp->request_buffer; + use_sg = pci_map_sg(pci_dev, slp, scp->use_sg, dir); + + if (use_sg > scp->device->host->sg_tablesize) { ASC_PRINT3( "asc_build_req: board %d: use_sg %d > sg_tablesize %d\n", - boardp->id, scp->use_sg, scp->device->host->sg_tablesize); + boardp->id, use_sg, scp->device->host->sg_tablesize); + pci_unmap_sg(pci_dev, slp, scp->use_sg, dir); scp->result = HOST_BYTE(DID_ERROR); asc_enqueue(&boardp->done, scp, ASC_BACK); return ASC_ERROR; @@ -6715,19 +6747,16 @@ asc_scsi_q.q1.data_cnt = 0; asc_scsi_q.q1.data_addr = 0; /* This is a byte value, otherwise it would need to be swapped. */ - asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = scp->use_sg; + asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg; ASC_STATS_ADD(scp->device->host, sg_elem, asc_sg_head.entry_cnt); /* * Convert scatter-gather list into ASC_SG_HEAD list. */ - slp = (struct scatterlist *) scp->request_buffer; - for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) { - asc_sg_head.sg_list[sgcnt].addr = - cpu_to_le32(virt_to_bus( - (unsigned char *)page_address(slp->page) + slp->offset)); - asc_sg_head.sg_list[sgcnt].bytes = cpu_to_le32(slp->length); - ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(slp->length, 512)); + for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) { + asc_sg_head.sg_list[sgcnt].addr = cpu_to_le32(sg_dma_address(slp)); + asc_sg_head.sg_list[sgcnt].bytes = cpu_to_le32(sg_dma_len(slp)); + ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(sg_dma_len(slp), 512)); } } @@ -6755,6 +6784,8 @@ ADV_SCSI_REQ_Q *scsiqp; int i; int ret; + struct pci_dev *pci_dev = boardp->dvc_cfg.adv_dvc_cfg.pci_dev; + int dir = scsi_to_pci_dma_dir(scp->sc_data_direction); /* * Allocate an adv_req_t structure from the board to execute @@ -6827,15 +6858,23 @@ * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather * buffer command. */ - scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); - scsiqp->vdata_addr = scp->request_buffer; - scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer)); if (scp->use_sg == 0) { /* * CDB request of single contiguous buffer. */ reqp->sgblkp = NULL; + scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); + if (scp->request_bufflen) { + scsiqp->vdata_addr = scp->request_buffer; + scp->SCp.dma_handle = + pci_map_single(pci_dev, scp->request_buffer, + scp->request_bufflen, dir); + } else { + scsiqp->vdata_addr = 0; + scp->SCp.dma_handle = 0; + } + scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle); scsiqp->sg_list_ptr = NULL; scsiqp->sg_real_addr = 0; ASC_STATS(scp->device->host, cont_cnt); @@ -6845,10 +6884,21 @@ /* * CDB scatter-gather request list. */ - if (scp->use_sg > ADV_MAX_SG_LIST) { + struct scatterlist *slp; + int use_sg; + + scsiqp->data_cnt = 0; + scsiqp->vdata_addr = 0; + scsiqp->data_addr = 0; + + slp = (struct scatterlist *)scp->request_buffer; + use_sg = pci_map_sg(pci_dev, slp, scp->use_sg, dir); + + if (use_sg > ADV_MAX_SG_LIST) { ASC_PRINT3( "adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n", - boardp->id, scp->use_sg, scp->device->host->sg_tablesize); + boardp->id, use_sg, scp->device->host->sg_tablesize); + pci_unmap_sg(pci_dev, slp, scp->use_sg, dir); scp->result = HOST_BYTE(DID_ERROR); asc_enqueue(&boardp->done, scp, ASC_BACK); @@ -6862,7 +6912,7 @@ return ASC_ERROR; } - if ((ret = adv_get_sglist(boardp, reqp, scp)) != ADV_SUCCESS) { + if ((ret = adv_get_sglist(boardp, reqp, scp, use_sg)) != ADV_SUCCESS) { /* * Free the adv_req_t structure by adding it back to the * board free list. @@ -6874,7 +6924,7 @@ } ASC_STATS(scp->device->host, sg_cnt); - ASC_STATS_ADD(scp->device->host, sg_elem, scp->use_sg); + ASC_STATS_ADD(scp->device->host, sg_elem, use_sg); } ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); @@ -6898,7 +6948,7 @@ * ADV_ERROR(-1) - SG List creation failed */ STATIC int -adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, Scsi_Cmnd *scp) +adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, Scsi_Cmnd *scp, int use_sg) { adv_sgblk_t *sgblkp; ADV_SCSI_REQ_Q *scsiqp; @@ -6910,7 +6960,7 @@ scsiqp = (ADV_SCSI_REQ_Q *) ADV_32BALIGN(&reqp->scsi_req_q); slp = (struct scatterlist *) scp->request_buffer; - sg_elem_cnt = scp->use_sg; + sg_elem_cnt = use_sg; prev_sg_block = NULL; reqp->sgblkp = NULL; @@ -6982,11 +7032,9 @@ for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) { - sg_block->sg_list[i].sg_addr = - cpu_to_le32(virt_to_bus( - (unsigned char *)page_address(slp->page) + slp->offset)); - sg_block->sg_list[i].sg_count = cpu_to_le32(slp->length); - ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(slp->length, 512)); + sg_block->sg_list[i].sg_addr = cpu_to_le32(sg_dma_address(slp)); + sg_block->sg_list[i].sg_count = cpu_to_le32(sg_dma_len(slp)); + ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(sg_dma_len(slp), 512)); if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */ --- diff/drivers/scsi/atp870u.c 2004-05-19 22:12:08.000000000 +0100 +++ source/drivers/scsi/atp870u.c 2004-05-27 18:34:17.000000000 +0100 @@ -4,6 +4,7 @@ * Copyright (C) 1997 Wu Ching Chen * 2.1.x update (C) 1998 Krzysztof G. Baranowski * 2.5.x update (C) 2002 Red Hat + * 2.6.x update (C) 2004 Red Hat * * Marcelo Tosatti : SMP fixes * @@ -126,9 +127,11 @@ /* * Issue more commands */ + spin_lock_irqsave(dev->host->host_lock, flags); if (((dev->quhdu != dev->quendu) || (dev->last_cmd != 0xff)) && (dev->in_snd == 0)) { send_s870(host); } + spin_unlock_irqrestore(dev->host->host_lock, flags); /* * Done */ @@ -371,9 +374,11 @@ /* * If there is stuff to send and nothing going then send it */ + spin_lock_irqsave(dev->host->host_lock, flags); if (((dev->last_cmd != 0xff) || (dev->quhdu != dev->quendu)) && (dev->in_snd == 0)) { send_s870(host); } + spin_unlock_irqrestore(dev->host->host_lock, flags); dev->in_int = 0; goto out; } @@ -443,9 +448,16 @@ return IRQ_HANDLED; } +/** + * atp870u_queuecommand - Queue SCSI command + * @req_p: request block + * @done: completion function + * + * Queue a command to the ATP queue. Called with the host lock held. + */ + static int atp870u_queuecommand(Scsi_Cmnd * req_p, void (*done) (Scsi_Cmnd *)) { - unsigned long flags; unsigned short int m; unsigned int tmport; struct Scsi_Host *host; @@ -484,7 +496,6 @@ * Count new command */ - spin_lock_irqsave(host->host_lock, flags); dev->quendu++; if (dev->quendu >= qcnt) { dev->quendu = 0; @@ -498,24 +509,31 @@ } dev->quendu--; req_p->result = 0x00020000; - spin_unlock_irqrestore(host->host_lock, flags); done(req_p); return 0; } dev->querequ[dev->quendu] = req_p; tmport = dev->ioport + 0x1c; - spin_unlock_irqrestore(host->host_lock, flags); if ((inb(tmport) == 0) && (dev->in_int == 0) && (dev->in_snd == 0)) { send_s870(host); } return 0; } +/** + * send_s870 - send a command to the controller + * @host: host + * + * On entry there is work queued to be done. We move some of that work to the + * controller itself. + * + * Caller holds the host lock. + */ + static void send_s870(struct Scsi_Host *host) { unsigned int tmport; Scsi_Cmnd *workrequ; - unsigned long flags; unsigned int i; unsigned char j, target_id; unsigned char *prd; @@ -527,10 +545,7 @@ struct atp_unit *dev = (struct atp_unit *)&host->hostdata; int sg_count; - spin_lock_irqsave(host->host_lock, flags); - if (dev->in_snd != 0) { - spin_unlock_irqrestore(host->host_lock, flags); return; } dev->in_snd = 1; @@ -543,13 +558,11 @@ dev->last_cmd = 0xff; if (dev->quhdu == dev->quendu) { dev->in_snd = 0; - spin_unlock_irqrestore(dev->host->host_lock, flags); return; } } if ((dev->last_cmd != 0xff) && (dev->working != 0)) { dev->in_snd = 0; - spin_unlock_irqrestore(dev->host->host_lock, flags); return; } dev->working++; @@ -567,7 +580,6 @@ dev->quhdu = j; dev->working--; dev->in_snd = 0; - spin_unlock_irqrestore(host->host_lock, flags); return; cmd_subp: workportu = dev->ioport; @@ -582,7 +594,6 @@ abortsnd: dev->last_cmd |= 0x40; dev->in_snd = 0; - spin_unlock_irqrestore(dev->host->host_lock, flags); return; oktosend: memcpy(&dev->ata_cdbu[0], &workrequ->cmnd[0], workrequ->cmd_len); @@ -684,7 +695,6 @@ dev->last_cmd |= 0x40; } dev->in_snd = 0; - spin_unlock_irqrestore(host->host_lock, flags); return; } tmpcip = dev->pciport; @@ -770,7 +780,6 @@ dev->last_cmd |= 0x40; } dev->in_snd = 0; - spin_unlock_irqrestore(host->host_lock, flags); return; } if (inb(tmport) == 0) { @@ -781,9 +790,6 @@ dev->last_cmd |= 0x40; } dev->in_snd = 0; - spin_unlock_irqrestore(host->host_lock, flags); - return; - } static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val) --- diff/drivers/scsi/dc390.h 2004-05-19 22:12:09.000000000 +0100 +++ source/drivers/scsi/dc390.h 2004-05-27 18:34:17.000000000 +0100 @@ -19,7 +19,7 @@ #endif #define DC390_BANNER "Tekram DC390/AM53C974" -#define DC390_VERSION "2.0f 2000-12-20" +#define DC390_VERSION "2.1b 2004-04-13" /* We don't have eh_abort_handler, eh_device_reset_handler, * eh_bus_reset_handler, eh_host_reset_handler yet! @@ -33,11 +33,11 @@ # define USE_NEW_EH #endif -extern int DC390_detect(Scsi_Host_Template *psht); -extern int DC390_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); -extern int DC390_abort(Scsi_Cmnd *cmd); -extern int DC390_reset(Scsi_Cmnd *cmd); -extern int DC390_bios_param(struct scsi_device *sdev, struct block_device *dev, +static int DC390_detect(Scsi_Host_Template *psht); +static int DC390_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); +static int DC390_abort(Scsi_Cmnd *cmd); +static int DC390_reset(Scsi_Cmnd *cmd); +static int DC390_bios_param(struct scsi_device *sdev, struct block_device *dev, sector_t capacity, int geom[]); static int DC390_release(struct Scsi_Host *); --- diff/drivers/scsi/dpt_i2o.c 2004-05-27 13:41:20.000000000 +0100 +++ source/drivers/scsi/dpt_i2o.c 2004-05-27 18:34:17.000000000 +0100 @@ -20,17 +20,21 @@ * (at your option) any later version. * * * ***************************************************************************/ +/*************************************************************************** + * Sat Dec 20 2003 Go Taniguchi + - Support 2.6 kernel and DMA-mapping + - ioctl fix for raid tools + - use schedule_timeout in long long loop + **************************************************************************/ -//#define DEBUG 1 -//#define UARTDELAY 1 +/*#define DEBUG 1 */ +/*#define UARTDELAY 1 */ -// On the real kernel ADDR32 should always be zero for 2.4. GFP_HIGH allocates -// high pages. Keep the macro around because of the broken unmerged ia64 tree +/* On the real kernel ADDR32 should always be zero for 2.4. GFP_HIGH allocates + high pages. Keep the macro around because of the broken unmerged ia64 tree */ #define ADDR32 (0) -#error Please convert me to Documentation/DMA-mapping.txt - #include #include @@ -53,6 +57,7 @@ #include /* for printk */ #include #include +#include #include #include @@ -85,7 +90,7 @@ #elif defined(__alpha__) PROC_ALPHA , #else - (-1),(-1) + (-1),(-1), #endif FT_HBADRVR, 0, OEM_DPT, OS_LINUX, CAP_OVERLAP, DEV_ALL, ADF_ALL_SC5, 0, 0, DPT_VERSION, DPT_REVISION, DPT_SUBREVISION, @@ -226,7 +231,7 @@ /* Active IOPs now in OPERATIONAL state */ PDEBUG("HBA's in OPERATIONAL state\n"); - printk(KERN_INFO"dpti: If you have a lot of devices this could take a few minutes.\n"); + printk("dpti: If you have a lot of devices this could take a few minutes.\n"); for (pHba = hba_chain; pHba; pHba = pHba->next) { printk(KERN_INFO"%s: Reading the hardware resource table.\n", pHba->name); if (adpt_i2o_lct_get(pHba) < 0){ @@ -269,6 +274,7 @@ adpt_hba* pHba = (adpt_hba*) host->hostdata[0]; // adpt_i2o_quiesce_hba(pHba); adpt_i2o_delete_hba(pHba); + scsi_unregister(host); return 0; } @@ -339,6 +345,8 @@ if (rcode != 0) { sprintf(pHba->detail, "Adaptec I2O RAID"); printk(KERN_INFO "%s: Inquiry Error (%d)\n",pHba->name,rcode); + if (rcode != -ETIME && rcode != -EINTR) + kfree(buf); } else { memset(pHba->detail, 0, sizeof(pHba->detail)); memcpy(&(pHba->detail), "Vendor: Adaptec ", 16); @@ -347,8 +355,8 @@ memcpy(&(pHba->detail[40]), " FW: ", 4); memcpy(&(pHba->detail[44]), (u8*) &buf[32], 4); pHba->detail[48] = '\0'; /* precautionary */ + kfree(buf); } - kfree(buf); adpt_i2o_status_get(pHba); return ; } @@ -478,7 +486,7 @@ heads = 255; sectors = 63; } - cylinders = capacity / (heads * sectors); + cylinders = sector_div(capacity, heads * sectors); // Special case if CDROM if(sdev->type == 5) { // CDROM @@ -871,6 +879,9 @@ return -EINVAL; } pci_set_master(pDev); + if (pci_set_dma_mask(pDev, 0xffffffffffffffffULL) && + pci_set_dma_mask(pDev, 0xffffffffULL)) + return -EINVAL; base_addr0_phys = pci_resource_start(pDev,0); hba_map0_area_size = pci_resource_len(pDev,0); @@ -963,6 +974,7 @@ // Initializing the spinlocks spin_lock_init(&pHba->state_lock); + spin_lock_init(&adpt_post_wait_lock); if(raptorFlag == 0){ printk(KERN_INFO"Adaptec I2O RAID controller %d at %lx size=%x irq=%d\n", @@ -1064,7 +1076,7 @@ { int i; - printk(KERN_INFO"Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); + printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); for (i = 0; i < DPTI_MAX_HBA; i++) { hbas[i] = NULL; } @@ -1152,12 +1164,22 @@ timeout *= HZ; if((status = adpt_i2o_post_this(pHba, msg, len)) == 0){ set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irq(pHba->host->host_lock); + if(pHba->host) + spin_unlock_irq(pHba->host->host_lock); if (!timeout) schedule(); - else + else{ + timeout = schedule_timeout(timeout); + if (timeout == 0) { + // I/O issued, but cannot get result in + // specified time. Freeing resorces is + // dangerous. + status = -ETIME; + } schedule_timeout(timeout*HZ); - spin_lock_irq(pHba->host->host_lock); + } + if(pHba->host) + spin_lock_irq(pHba->host->host_lock); } spin_lock_irq(&adpt_wq_i2o_post.lock); __remove_wait_queue(&adpt_wq_i2o_post, &wait); @@ -1209,6 +1231,8 @@ printk(KERN_WARNING"dpti%d: Timeout waiting for message frame!\n", pHba->unit); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while(m == EMPTY_QUEUE); msg = (u32*) (pHba->msg_addr_virt + m); @@ -1283,6 +1307,8 @@ printk(KERN_WARNING"Timeout waiting for message!\n"); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while (m == EMPTY_QUEUE); status = (u8*)kmalloc(4, GFP_KERNEL|ADDR32); @@ -1314,6 +1340,8 @@ return -ETIMEDOUT; } rmb(); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } if(*status == 0x01 /*I2O_EXEC_IOP_RESET_IN_PROGRESS*/) { @@ -1330,6 +1358,8 @@ printk(KERN_ERR "%s:Timeout waiting for IOP Reset.\n",pHba->name); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while (m == EMPTY_QUEUE); // Flush the offset adpt_send_nop(pHba, m); @@ -1695,15 +1725,20 @@ } do { - spin_lock_irqsave(pHba->host->host_lock, flags); + if(pHba->host) + spin_lock_irqsave(pHba->host->host_lock, flags); // This state stops any new commands from enterring the // controller while processing the ioctl // pHba->state |= DPTI_STATE_IOCTL; // We can't set this now - The scsi subsystem sets host_blocked and // the queue empties and stops. We need a way to restart the queue rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER); + if (rcode != 0) + printk("adpt_i2o_passthru: post wait failed %d %p\n", + rcode, reply); // pHba->state &= ~DPTI_STATE_IOCTL; - spin_unlock_irqrestore(pHba->host->host_lock, flags); + if(pHba->host) + spin_unlock_irqrestore(pHba->host->host_lock, flags); } while(rcode == -ETIMEDOUT); if(rcode){ @@ -1764,10 +1799,12 @@ cleanup: - kfree (reply); + if (rcode != -ETIME && rcode != -EINTR) + kfree (reply); while(sg_index) { if(sg_list[--sg_index]) { - kfree((void*)(sg_list[sg_index])); + if (rcode != -ETIME && rcode != -EINTR) + kfree((void*)(sg_list[sg_index])); } } return rcode; @@ -1875,7 +1912,7 @@ int minor; int error = 0; adpt_hba* pHba; - ulong flags; + ulong flags = 0; minor = iminor(inode); if (minor >= DPTI_MAX_HBA){ @@ -1941,9 +1978,11 @@ break; } case I2ORESETCMD: - spin_lock_irqsave(pHba->host->host_lock, flags); + if(pHba->host) + spin_lock_irqsave(pHba->host->host_lock, flags); adpt_hba_reset(pHba); - spin_unlock_irqrestore(pHba->host->host_lock, flags); + if(pHba->host) + spin_unlock_irqrestore(pHba->host->host_lock, flags); break; case I2ORESCANCMD: adpt_rescan(pHba); @@ -1956,7 +1995,7 @@ } -static void adpt_isr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t adpt_isr(int irq, void *dev_id, struct pt_regs *regs) { Scsi_Cmnd* cmd; adpt_hba* pHba = dev_id; @@ -1965,12 +2004,15 @@ u32 status=0; u32 context; ulong flags = 0; + int handled = 0; - if (pHba == NULL ){ + if (pHba == NULL){ printk(KERN_WARNING"adpt_isr: NULL dev_id\n"); - return; + return IRQ_NONE; } - spin_lock_irqsave(pHba->host->host_lock, flags); + if(pHba->host) + spin_lock_irqsave(pHba->host->host_lock, flags); + while( readl(pHba->irq_mask) & I2O_INTERRUPT_PENDING_B) { m = readl(pHba->reply_port); if(m == EMPTY_QUEUE){ @@ -2035,7 +2077,10 @@ wmb(); rmb(); } -out: spin_unlock_irqrestore(pHba->host->host_lock, flags); + handled = 1; +out: if(pHba->host) + spin_unlock_irqrestore(pHba->host->host_lock, flags); + return IRQ_RETVAL(handled); } static s32 adpt_scsi_to_i2o(adpt_hba* pHba, Scsi_Cmnd* cmd, struct adpt_device* d) @@ -2110,15 +2155,19 @@ /* Now fill in the SGList and command */ if(cmd->use_sg) { struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer; + int sg_count = pci_map_sg(pHba->pDev, sg, cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + + len = 0; - for(i = 0 ; i < cmd->use_sg; i++) { - *mptr++ = direction|0x10000000|sg->length; - len+=sg->length; - *mptr++ = virt_to_bus(sg->address); + for(i = 0 ; i < sg_count; i++) { + *mptr++ = direction|0x10000000|sg_dma_len(sg); + len+=sg_dma_len(sg); + *mptr++ = sg_dma_address(sg); sg++; } /* Make this an end of list */ - mptr[-2] = direction|0xD0000000|(sg-1)->length; + mptr[-2] = direction|0xD0000000|sg_dma_len(sg-1); reqlen = mptr - msg; *lenptr = len; @@ -2132,7 +2181,10 @@ reqlen = 12; } else { *mptr++ = 0xD0000000|direction|cmd->request_bufflen; - *mptr++ = virt_to_bus(cmd->request_buffer); + *mptr++ = pci_map_single(pHba->pDev, + cmd->request_buffer, + cmd->request_bufflen, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); } } @@ -2305,15 +2357,17 @@ static s32 adpt_rescan(adpt_hba* pHba) { s32 rcode; - ulong flags; + ulong flags = 0; - spin_lock_irqsave(pHba->host->host_lock, flags); + if(pHba->host) + spin_lock_irqsave(pHba->host->host_lock, flags); if ((rcode=adpt_i2o_lct_get(pHba)) < 0) goto out; if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0) goto out; rcode = 0; -out: spin_unlock_irqrestore(pHba->host->host_lock, flags); +out: if(pHba->host) + spin_unlock_irqrestore(pHba->host->host_lock, flags); return rcode; } @@ -2595,6 +2649,8 @@ printk(KERN_ERR "%s: Timeout waiting for message frame!\n",pHba->name); return 2; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } msg = (u32*)(pHba->msg_addr_virt + m); writel( THREE_WORD_MSG_SIZE | SGL_OFFSET_0,&msg[0]); @@ -2628,6 +2684,8 @@ printk(KERN_WARNING"%s: Timeout waiting for message frame\n",pHba->name); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while(m == EMPTY_QUEUE); msg=(u32 *)(pHba->msg_addr_virt+m); @@ -2663,9 +2721,10 @@ rmb(); if(time_after(jiffies,timeout)){ printk(KERN_WARNING"%s: Timeout Initializing\n",pHba->name); - kfree((void*)status); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while (1); // If the command was successful, fill the fifo with our reply @@ -2743,6 +2802,8 @@ pHba->name); return -ETIMEDOUT; } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } while(m==EMPTY_QUEUE); @@ -2769,6 +2830,8 @@ return -ETIMEDOUT; } rmb(); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); } // Set up our number of outbound and inbound messages @@ -3094,17 +3157,33 @@ int group, int field, void *buf, int buflen) { u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; - u8 resblk[8+buflen]; /* 8 bytes for header */ + u8 *resblk; + int size; + /* 8 bytes for header */ + resblk = kmalloc(sizeof(u8) * (8+buflen), GFP_KERNEL|ADDR32); + if (resblk == NULL) { + printk(KERN_CRIT "%s: query scalar failed; Out of memory.\n", pHba->name); + return -ENOMEM; + } + if (field == -1) /* whole group */ opblk[4] = -1; size = adpt_i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, pHba, tid, - opblk, sizeof(opblk), resblk, sizeof(resblk)); + opblk, sizeof(opblk), resblk, sizeof(u8)*(8+buflen)); + if (size == -ETIME) { + printk(KERN_WARNING "%s: issue params failed; Timed out.\n", pHba->name); + return -ETIME; + } else if (size == -EINTR) { + printk(KERN_WARNING "%s: issue params failed; Interrupted.\n", pHba->name); + return -EINTR; + } memcpy(buf, resblk+8, buflen); /* cut off header */ + kfree(resblk); if (size < 0) return size; @@ -3138,6 +3217,7 @@ msg[8] = virt_to_bus(resblk); if ((wait_status = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 20))) { + printk("adpt_i2o_issue_params: post_wait failed (%p)\n", resblk); return wait_status; /* -DetailedStatus */ } --- diff/drivers/scsi/dpti.h 2004-05-19 22:12:09.000000000 +0100 +++ source/drivers/scsi/dpti.h 2004-05-27 18:34:17.000000000 +0100 @@ -65,7 +65,7 @@ #include "dpt/dpti_i2o.h" #include "dpt/dpti_ioctl.h" -#define DPT_I2O_VERSION "2.4 Build 5" +#define DPT_I2O_VERSION "2.4 Build 5go" #define DPT_VERSION 2 #define DPT_REVISION '4' #define DPT_SUBREVISION '5' @@ -272,7 +272,7 @@ static void adpt_i2o_sys_shutdown(void); static int adpt_init(void); static int adpt_i2o_build_sys_table(void); -static void adpt_isr(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t adpt_isr(int irq, void *dev_id, struct pt_regs *regs); #ifdef REBOOT_NOTIFIER static int adpt_reboot_event(struct notifier_block *n, ulong code, void *p); #endif --- diff/drivers/scsi/gdth.c 2004-05-19 22:12:09.000000000 +0100 +++ source/drivers/scsi/gdth.c 2004-05-27 18:34:17.000000000 +0100 @@ -4,9 +4,9 @@ * Intel Corporation: Storage RAID Controllers * * * * gdth.c * - * Copyright (C) 1995-03 ICP vortex GmbH, Achim Leubner * - * Copyright (C) 2002-03 Intel Corporation * - * Copyright (C) 2003 Adaptec Inc. * + * Copyright (C) 1995-04 ICP vortex GmbH, Achim Leubner * + * Copyright (C) 2002-04 Intel Corporation * + * Copyright (C) 2003-04 Adaptec Inc. * * * * * * Additions/Fixes: * @@ -27,9 +27,42 @@ * along with this kernel; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * - * Tested with Linux 1.2.13, ..., 2.2.20, ..., 2.4.22 * + * Linux kernel 2.2.x, 2.4.x, 2.6.x supported * * * * $Log: gdth.c,v $ + * Revision 1.73 2004/03/31 13:33:03 achim + * Special command 0xfd implemented to detect 64-bit DMA support + * + * Revision 1.72 2004/03/17 08:56:04 achim + * 64-bit DMA only enabled if FW >= x.43 + * + * Revision 1.71 2004/03/05 15:51:29 achim + * Screen service: separate message buffer, bugfixes + * + * Revision 1.70 2004/02/27 12:19:07 achim + * Bugfix: Reset bit in config (0xfe) call removed + * + * Revision 1.69 2004/02/20 09:50:24 achim + * Compatibility changes for kernels < 2.4.20 + * Bugfix screen service command size + * pci_set_dma_mask() error handling added + * + * Revision 1.68 2004/02/19 15:46:54 achim + * 64-bit DMA bugfixes + * Drive size bugfix for drives > 1TB + * + * Revision 1.67 2004/01/14 13:11:57 achim + * Tool access over /proc no longer supported + * Bugfixes IOCTLs + * + * Revision 1.66 2003/12/19 15:04:06 achim + * Bugfixes support for drives > 2TB + * + * Revision 1.65 2003/12/15 11:21:56 achim + * 64-bit DMA support added + * Support for drives > 2 TB implemented + * Kernels 2.2.x, 2.4.x, 2.6.x supported + * * Revision 1.64 2003/09/17 08:30:26 achim * EISA/ISA controller scan disabled * Command line switch probe_eisa_isa added @@ -299,10 +332,12 @@ * shared_access:N enable driver reserve/release protocol * probe_eisa_isa:Y scan for EISA/ISA controllers * probe_eisa_isa:N do not scan for EISA/ISA controllers + * force_dma32:Y use only 32 bit DMA mode + * force_dma32:N use 64 bit DMA mode, if supported * * The default values are: "gdth=disable:N,reserve_mode:1,reverse_scan:N, * max_ids:127,rescan:N,virt_ctr:N,hdr_channel:0, - * shared_access:Y,probe_eisa_isa:N". + * shared_access:Y,probe_eisa_isa:N,force_dma32:N". * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y". * * When loading the gdth driver as a module, the same options are available. @@ -313,7 +348,7 @@ * * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0 * max_ids=127 rescan=0 virt_ctr=0 hdr_channel=0 shared_access=0 - * probe_eisa_isa=0" + * probe_eisa_isa=0 force_dma32=0" * The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1". */ @@ -330,9 +365,12 @@ * phase: Service/parameter/return code special command */ -/* default: activate /proc and character device IOCTL interface */ -#define GDTH_IOCTL_PROC -#define GDTH_IOCTL_CHRDEV + +/* interrupt coalescing */ +/* #define INT_COAL */ + +/* statistics */ +#define GDTH_STATISTICS #include @@ -353,35 +391,35 @@ #ifdef GDTH_RTC #include #endif -#if LINUX_VERSION_CODE >= 0x020100 #include -#else -#include -#endif #include #include #include #include -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #include -#elif LINUX_VERSION_CODE >= 0x02015F +#else #include #endif - +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #include - -#include "scsi.h" -#include "hosts.h" -#if LINUX_VERSION_CODE < 0x020503 +#else +#include #include "sd.h" #endif +#include "scsi.h" +#include "hosts.h" #include "gdth.h" static void gdth_delay(int milliseconds); -static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs); +static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static irqreturn_t gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs); +#else +static void gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs); +#endif static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp); static int gdth_async_event(int hanum); static void gdth_log_event(gdth_evt_data *dvr, char *buffer); @@ -419,31 +457,19 @@ static void gdth_release_event(int hanum); static int gdth_wait(int hanum,int index,ulong32 time); static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1, - ulong32 p2,ulong32 p3); + ulong64 p2,ulong64 p3); static int gdth_search_drives(int hanum); static int gdth_analyse_hdrive(int hanum, ushort hdrive); -static void *gdth_mmap(ulong paddr, ulong size); -static void gdth_munmap(void *addr); - static const char *gdth_ctr_name(int hanum); -#ifdef GDTH_IOCTL_CHRDEV static int gdth_open(struct inode *inode, struct file *filep); static int gdth_close(struct inode *inode, struct file *filep); static int gdth_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); -#endif -#if LINUX_VERSION_CODE >= 0x010300 static void gdth_flush(int hanum); -#if LINUX_VERSION_CODE >= 0x020100 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf); -#else -static int halt_called = FALSE; -void gdth_halt(void); -#endif -#endif #ifdef DEBUG_GDTH static unchar DebugState = DEBUG_GDTH; @@ -528,6 +554,9 @@ #ifdef GDTH_STATISTICS static ulong32 max_rq=0, max_index=0, max_sg=0; +#ifdef INT_COAL +static ulong32 max_int_coal=0; +#endif static ulong32 act_ints=0, act_ios=0, act_stats=0, act_rq=0; static struct timer_list gdth_timer; #endif @@ -542,80 +571,12 @@ #define BUS_L2P(a,b) ((b)>(a)->virt_bus ? (b-1):(b)) -#if LINUX_VERSION_CODE < 0x010300 -static void *gdth_mmap(ulong paddr, ulong size) -{ - if (paddr >= high_memory) - return NULL; - else - return (void *)paddr; -} -static void gdth_munmap(void *addr) -{ -} -inline ulong32 virt_to_phys(volatile void *addr) -{ - return (ulong32)addr; -} -inline void *phys_to_virt(ulong32 addr) -{ - return (void *)addr; -} -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt -#define gdth_readb(addr) (*(volatile unchar *)(addr)) -#define gdth_readw(addr) (*(volatile ushort *)(addr)) -#define gdth_readl(addr) (*(volatile ulong32 *)(addr)) -#define gdth_writeb(b,addr) (*(volatile unchar *)(addr) = (b)) -#define gdth_writew(b,addr) (*(volatile ushort *)(addr) = (b)) -#define gdth_writel(b,addr) (*(volatile ulong32 *)(addr) = (b)) -#define memset_io(a,b,c) memset((void *)(a),(b),(c)) -#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) -#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) - -#define PCI_SLOT(devfn) ((devfn >> 3) & 0x1f) - -#elif LINUX_VERSION_CODE < 0x020100 -static int remapped = FALSE; -static void *gdth_mmap(ulong paddr, ulong size) -{ - if ( paddr >= high_memory) { - remapped = TRUE; - return vremap(paddr, size); - } else { - return (void *)paddr; - } -} -static void gdth_munmap(void *addr) -{ - if (remapped) - vfree(addr); - remapped = FALSE; -} -#define gdth_readb(addr) readb((ulong)(addr)) -#define gdth_readw(addr) readw((ulong)(addr)) -#define gdth_readl(addr) (ulong32)readl((ulong)(addr)) -#define gdth_writeb(b,addr) writeb((b),(ulong)(addr)) -#define gdth_writew(b,addr) writew((b),(ulong)(addr)) -#define gdth_writel(b,addr) writel((ulong32)(b),(ulong)(addr)) - -#else -static void *gdth_mmap(ulong paddr, ulong size) -{ - return ioremap(paddr, size); -} -static void gdth_munmap(void *addr) -{ - return iounmap(addr); -} #define gdth_readb(addr) readb((ulong)(addr)) #define gdth_readw(addr) readw((ulong)(addr)) #define gdth_readl(addr) (ulong32)readl((ulong)(addr)) #define gdth_writeb(b,addr) writeb((b),(ulong)(addr)) #define gdth_writew(b,addr) writew((b),(ulong)(addr)) #define gdth_writel(b,addr) writel((ulong32)(b),(ulong)(addr)) -#endif - static unchar gdth_drq_tab[4] = {5,6,7,7}; /* DRQ table */ static unchar gdth_irq_tab[6] = {0,10,11,12,14,0}; /* IRQ table */ @@ -631,9 +592,7 @@ static gdth_evt_str ebuffer[MAX_EVENTS]; /* event buffer */ static int elastidx; static int eoldidx; -#ifdef GDTH_IOCTL_CHRDEV static int major; -#endif #define DIN 1 /* IN data direction */ #define DOU 2 /* OUT data direction */ @@ -648,8 +607,8 @@ DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, - DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, - DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, + DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DIN,DUN,DOU,DUN,DUN,DUN,DUN,DUN, + DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DIN,DUN, DUN,DUN,DUN,DUN,DUN,DNO,DNO,DUN,DIN,DNO,DOU,DUN,DNO,DUN,DOU,DOU, DOU,DOU,DOU,DNO,DUN,DIN,DOU,DIN,DIN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, @@ -659,47 +618,32 @@ }; /* __initfunc, __initdata macros */ -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#define __devinitdata +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #define GDTH_INITFUNC(type, func) type __init func #include -#elif LINUX_VERSION_CODE >= 0x020126 +#else #define GDTH_INITFUNC(type, func) __initfunc(type func) #include -#else -#define GDTH_INITFUNC(type, func) type func -#define __initdata -#define __init #endif -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock) #define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags) #define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags) #define GDTH_LOCK_SCSI_DONE(dev, flags) spin_lock_irqsave(dev->host_lock,flags) #define GDTH_UNLOCK_SCSI_DONE(dev, flags) spin_unlock_irqrestore(dev->host_lock,flags) -#define GDTH_LOCK_SCSI_DOCMD(dev) spin_lock_irq(dev->host_lock) -#define GDTH_UNLOCK_SCSI_DOCMD(dev) spin_unlock_irq(dev->host_lock) -#elif LINUX_VERSION_CODE >= 0x02015F +#else #define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock) #define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags) #define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags) #define GDTH_LOCK_SCSI_DONE(flags) spin_lock_irqsave(&io_request_lock,flags) #define GDTH_UNLOCK_SCSI_DONE(flags) spin_unlock_irqrestore(&io_request_lock,flags) -#define GDTH_LOCK_SCSI_DOCMD() spin_lock_irq(&io_request_lock) -#define GDTH_UNLOCK_SCSI_DOCMD() spin_unlock_irq(&io_request_lock) - -#else -#define GDTH_INIT_LOCK_HA(ha) do {} while (0) -#define GDTH_LOCK_HA(ha,flags) do {save_flags(flags); cli();} while (0) -#define GDTH_UNLOCK_HA(ha,flags) do {restore_flags(flags);} while (0) - -#define GDTH_LOCK_SCSI_DONE(flags) do {} while (0) -#define GDTH_UNLOCK_SCSI_DONE(flags) do {} while (0) -#define GDTH_LOCK_SCSI_DOCMD() do {} while (0) -#define GDTH_UNLOCK_SCSI_DOCMD() do {} while (0) #endif /* LILO and modprobe/insmod parameters */ @@ -730,9 +674,10 @@ static int shared_access = 1; /* enable support for EISA and ISA controllers */ static int probe_eisa_isa = 0; +/* 64 bit DMA mode, support for drives > 2 TB, if force_dma32 = 0 */ +static int force_dma32 = 0; #ifdef MODULE -#if LINUX_VERSION_CODE >= 0x02011A /* parameters for modprobe/insmod */ MODULE_PARM(irq, "i"); MODULE_PARM(disable, "i"); @@ -745,41 +690,42 @@ MODULE_PARM(virt_ctr, "i"); MODULE_PARM(shared_access, "i"); MODULE_PARM(probe_eisa_isa, "i"); +MODULE_PARM(force_dma32, "i"); MODULE_AUTHOR("Achim Leubner"); -#endif -#if LINUX_VERSION_CODE >= 0x02040B +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,11) MODULE_LICENSE("GPL"); #endif #endif -#ifdef GDTH_IOCTL_CHRDEV /* ioctl interface */ static struct file_operations gdth_fops = { - .ioctl = gdth_ioctl, - .open = gdth_open, - .release = gdth_close, -}; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + .ioctl = gdth_ioctl, + .open = gdth_open, + .release = gdth_close, +#else + ioctl:gdth_ioctl, + open:gdth_open, + release:gdth_close, #endif +}; /* /proc support */ -#if LINUX_VERSION_CODE >= 0x010300 #include -#if LINUX_VERSION_CODE < 0x020322 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) struct proc_dir_entry proc_scsi_gdth = { PROC_SCSI_GDTH, 4, "gdth", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; #endif + #include "gdth_proc.h" #include "gdth_proc.c" -#endif -#if LINUX_VERSION_CODE >= 0x020100 /* notifier block to get a notify on system shutdown/halt/reboot */ static struct notifier_block gdth_notifier = { gdth_halt, NULL, 0 }; -#endif static void gdth_delay(int milliseconds) @@ -787,17 +733,11 @@ if (milliseconds == 0) { udelay(1); } else { -#if LINUX_VERSION_CODE >= 0x020168 mdelay(milliseconds); -#else - int i; - for (i = 0; i < milliseconds; ++i) - udelay(1000); -#endif } } -static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs) +static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs) { *cyls = size /HEADS/SECS; if (*cyls <= MAXCYLS) { @@ -842,9 +782,9 @@ ulong32 id; TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr)); - if ((addr = gdth_mmap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) { + if ((addr = ioremap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) { id = gdth_readl(addr); - gdth_munmap(addr); + iounmap(addr); if (id == GDT2_ID) /* GDT2000 */ return 1; } @@ -866,6 +806,8 @@ gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device); gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, PCI_DEVICE_ID_VORTEX_GDTNEWRX); + gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, + PCI_DEVICE_ID_VORTEX_GDTNEWRX2); gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SRC); gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL, @@ -873,11 +815,11 @@ return cnt; } -#if LINUX_VERSION_CODE >= 0x20363 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* Vortex only makes RAID controllers. * We do not really want to specify all 550 ids here, so wildcard match. */ -static struct pci_device_id gdthtable[] = { +static struct pci_device_id gdthtable[] __devinitdata = { {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, @@ -890,17 +832,12 @@ ushort vendor, ushort device)) { ulong base0, base1, base2; -#if LINUX_VERSION_CODE >= 0x2015C struct pci_dev *pdev; -#else - int error; - ushort idx; -#endif TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n", *cnt, vendor, device)); -#if LINUX_VERSION_CODE >= 0x20363 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pdev = NULL; while ((pdev = pci_find_device(vendor, device, pdev)) != NULL) { @@ -938,7 +875,7 @@ pcistr[*cnt].irq, pcistr[*cnt].dpmem)); (*cnt)++; } -#elif LINUX_VERSION_CODE >= 0x2015C +#else pdev = NULL; while ((pdev = pci_find_device(vendor, device, pdev)) != NULL) { @@ -979,66 +916,6 @@ pcistr[*cnt].irq, pcistr[*cnt].dpmem)); (*cnt)++; } -#else - idx = 0; - while (!pcibios_find_device(vendor, device, idx++, - &pcistr[*cnt].bus,&pcistr[*cnt].device_fn)) { - if (*cnt >= MAXHA) - return; - /* GDT PCI ctr. found, now read resources from config space */ -#if LINUX_VERSION_CODE >= 0x010300 -#define GDTH_BASEP (int *) -#else -#define GDTH_BASEP -#endif - if ((error = pcibios_read_config_dword(pcistr[*cnt].bus, - pcistr[*cnt].device_fn, - PCI_BASE_ADDRESS_0, - GDTH_BASEP&base0)) || - (error = pcibios_read_config_dword(pcistr[*cnt].bus, - pcistr[*cnt].device_fn, - PCI_BASE_ADDRESS_1, - GDTH_BASEP&base1)) || - (error = pcibios_read_config_dword(pcistr[*cnt].bus, - pcistr[*cnt].device_fn, - PCI_BASE_ADDRESS_2, - GDTH_BASEP&base2)) || - (error = pcibios_read_config_word(pcistr[*cnt].bus, - pcistr[*cnt].device_fn, - PCI_SUBSYSTEM_ID, - &pcistr[*cnt].subdevice_id)) || - (error = pcibios_read_config_byte(pcistr[*cnt].bus, - pcistr[*cnt].device_fn, - PCI_INTERRUPT_LINE, - &pcistr[*cnt].irq))) { - printk("GDT-PCI: error %d reading configuration space", error); - continue; - } - pcistr[*cnt].vendor_id = vendor; - pcistr[*cnt].device_id = device; - if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ - device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ - if ((base0 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY) - continue; - pcistr[*cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK; - } else { /* GDT6110, GDT6120, .. */ - if ((base0 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY || - (base2 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_MEMORY || - (base1 & PCI_BASE_ADDRESS_SPACE) != - PCI_BASE_ADDRESS_SPACE_IO) - continue; - pcistr[*cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[*cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK; - pcistr[*cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK; - } - TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n", - pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn), - pcistr[*cnt].irq, pcistr[*cnt].dpmem)); - (*cnt)++; - } #endif } @@ -1168,6 +1045,8 @@ ha->type = GDT_EISA; ha->stype = id; } + + ha->dma64_support = 0; return 1; } @@ -1181,7 +1060,7 @@ TRACE(("gdth_init_isa() bios adr. %x\n",bios_adr)); - ha->brd = gdth_mmap(bios_adr, sizeof(gdt2_dpram_str)); + ha->brd = ioremap(bios_adr, sizeof(gdt2_dpram_str)); if (ha->brd == NULL) { printk("GDT-ISA: Initialization error (DPMEM remap error)\n"); return 0; @@ -1191,8 +1070,8 @@ /* reset interface area */ memset_io((char *)&dp2_ptr->u,0,sizeof(dp2_ptr->u)); if (gdth_readl(&dp2_ptr->u) != 0) { - printk("GDT-PCI: Initialization error (DPMEM write error)\n"); - gdth_munmap(ha->brd); + printk("GDT-ISA: Initialization error (DPMEM write error)\n"); + iounmap(ha->brd); return 0; } @@ -1227,7 +1106,7 @@ while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-ISA: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); @@ -1237,7 +1116,7 @@ gdth_writeb(0xff, &dp2_ptr->io.irqdel); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-ISA: Illegal protocol version\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1259,13 +1138,15 @@ while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-ISA: Initialization error\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); } gdth_writeb(0, &dp2_ptr->u.ic.Status); gdth_writeb(0xff, &dp2_ptr->io.irqdel); + + ha->dma64_support = 0; return 1; } @@ -1279,9 +1160,6 @@ unchar prot_ver; ushort command; int i, found = FALSE; -#if LINUX_VERSION_CODE < 0x2015C - int rom_addr; -#endif TRACE(("gdth_init_pci()\n")); @@ -1293,13 +1171,13 @@ ha->stype = (ulong32)pcistr->device_id; ha->subdevice_id = pcistr->subdevice_id; ha->irq = pcistr->irq; -#if LINUX_VERSION_CODE >= 0x20400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ha->pdev = pcistr->pdev; #endif if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */ TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq)); - ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6_dpram_str)); + ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1312,8 +1190,8 @@ pcistr->dpmem); found = FALSE; for (i = 0xC8000; i < 0xE8000; i += 0x4000) { - gdth_munmap(ha->brd); - ha->brd = gdth_mmap(i, sizeof(ushort)); + iounmap(ha->brd); + ha->brd = ioremap(i, sizeof(ushort)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1322,15 +1200,10 @@ TRACE2(("init_pci_old() address 0x%x busy\n", i)); continue; } - gdth_munmap(ha->brd); -#if LINUX_VERSION_CODE >= 0x2015C + iounmap(ha->brd); pci_write_config_dword(pcistr->pdev, PCI_BASE_ADDRESS_0, i); -#else - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_BASE_ADDRESS_0, i); -#endif - ha->brd = gdth_mmap(i, sizeof(gdt6_dpram_str)); + ha->brd = ioremap(i, sizeof(gdt6_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1345,14 +1218,14 @@ } if (!found) { printk("GDT-PCI: No free address found!\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } } memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u)); if (gdth_readl(&dp6_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1370,7 +1243,7 @@ while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); @@ -1380,7 +1253,7 @@ gdth_writeb(0xff, &dp6_ptr->io.irqdel); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1390,7 +1263,7 @@ /* special command to controller BIOS */ gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[0]); gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[1]); - gdth_writel(0x01, &dp6_ptr->u.ic.S_Info[2]); + gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[2]); gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[3]); gdth_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx); gdth_writeb(0, &dp6_ptr->io.event); @@ -1399,7 +1272,7 @@ while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); @@ -1407,14 +1280,16 @@ gdth_writeb(0, &dp6_ptr->u.ic.S_Status); gdth_writeb(0xff, &dp6_ptr->io.irqdel); + ha->dma64_support = 0; + } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, ... */ ha->plx = (gdt6c_plx_regs *)pcistr->io; TRACE2(("init_pci_new() dpmem %lx irq %d\n", pcistr->dpmem,ha->irq)); - ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6c_dpram_str)); + ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6c_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } /* check and reset interface area */ @@ -1425,8 +1300,8 @@ pcistr->dpmem); found = FALSE; for (i = 0xC8000; i < 0xE8000; i += 0x4000) { - gdth_munmap(ha->brd); - ha->brd = gdth_mmap(i, sizeof(ushort)); + iounmap(ha->brd); + ha->brd = ioremap(i, sizeof(ushort)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1435,15 +1310,10 @@ TRACE2(("init_pci_plx() address 0x%x busy\n", i)); continue; } - gdth_munmap(ha->brd); -#if LINUX_VERSION_CODE >= 0x2015C + iounmap(ha->brd); pci_write_config_dword(pcistr->pdev, PCI_BASE_ADDRESS_2, i); -#else - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_BASE_ADDRESS_2, i); -#endif - ha->brd = gdth_mmap(i, sizeof(gdt6c_dpram_str)); + ha->brd = ioremap(i, sizeof(gdt6c_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1458,14 +1328,14 @@ } if (!found) { printk("GDT-PCI: No free address found!\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } } memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u)); if (gdth_readl(&dp6c_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1486,7 +1356,7 @@ while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); @@ -1495,7 +1365,7 @@ gdth_writeb(0, &dp6c_ptr->u.ic.Status); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1505,7 +1375,7 @@ /* special command to controller BIOS */ gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]); gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]); - gdth_writel(0x01, &dp6c_ptr->u.ic.S_Info[2]); + gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[2]); gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]); gdth_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx); @@ -1516,23 +1386,25 @@ while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); } gdth_writeb(0, &dp6c_ptr->u.ic.S_Status); + ha->dma64_support = 0; + } else { /* MPR */ TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq)); - ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6m_dpram_str)); + ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6m_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; } /* manipulate config. space to enable DPMEM, start RP controller */ -#if LINUX_VERSION_CODE >= 0x20363 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command); command |= 6; pci_write_config_word(pcistr->pdev, PCI_COMMAND, command); @@ -1543,7 +1415,7 @@ gdth_delay(1); pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, pci_resource_start(pcistr->pdev, 8)); -#elif LINUX_VERSION_CODE >= 0x2015C +#else pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command); command |= 6; pci_write_config_word(pcistr->pdev, PCI_COMMAND, command); @@ -1554,22 +1426,6 @@ gdth_delay(1); pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, pcistr->pdev->rom_address); -#else - pcibios_read_config_word(pcistr->bus, pcistr->device_fn, - PCI_COMMAND, &command); - command |= 6; - pcibios_write_config_word(pcistr->bus, pcistr->device_fn, - PCI_COMMAND, command); - pcibios_read_config_dword(pcistr->bus, pcistr->device_fn, - PCI_ROM_ADDRESS, &rom_addr); - if (rom_addr == 1UL) - rom_addr = 0UL; - i = 0xFEFF0001UL; - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_ROM_ADDRESS, i); - gdth_delay(1); - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_ROM_ADDRESS, rom_addr); #endif /* Ensure that it is safe to access the non HW portions of DPMEM. @@ -1585,8 +1441,8 @@ pcistr->dpmem); found = FALSE; for (i = 0xC8000; i < 0xE8000; i += 0x4000) { - gdth_munmap(ha->brd); - ha->brd = gdth_mmap(i, sizeof(ushort)); + iounmap(ha->brd); + ha->brd = ioremap(i, sizeof(ushort)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1595,15 +1451,10 @@ TRACE2(("init_pci_mpr() address 0x%x busy\n", i)); continue; } - gdth_munmap(ha->brd); -#if LINUX_VERSION_CODE >= 0x2015C + iounmap(ha->brd); pci_write_config_dword(pcistr->pdev, PCI_BASE_ADDRESS_0, i); -#else - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_BASE_ADDRESS_0, i); -#endif - ha->brd = gdth_mmap(i, sizeof(gdt6m_dpram_str)); + ha->brd = ioremap(i, sizeof(gdt6m_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; @@ -1618,7 +1469,7 @@ } if (!found) { printk("GDT-PCI: No free address found!\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } } @@ -1639,7 +1490,7 @@ while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } gdth_delay(1); @@ -1648,7 +1499,7 @@ gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); return 0; } @@ -1658,7 +1509,7 @@ /* special command to controller BIOS */ gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[0]); gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[1]); - gdth_writel(0x01, &dp6m_ptr->u.ic.S_Info[2]); + gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[2]); gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[3]); gdth_writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx); gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg); @@ -1667,12 +1518,32 @@ while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); - gdth_munmap(ha->brd); + iounmap(ha->brd); + return 0; + } + gdth_delay(1); + } + gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); + + /* read FW version to detect 64-bit DMA support */ + gdth_writeb(0xfd, &dp6m_ptr->u.ic.S_Cmd_Indx); + gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg); + retries = INIT_RETRIES; + gdth_delay(20); + while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfd) { + if (--retries == 0) { + printk("GDT-PCI: Initialization error (DEINIT failed)\n"); + iounmap(ha->brd); return 0; } gdth_delay(1); } + prot_ver = (unchar)(gdth_readl(&dp6m_ptr->u.ic.S_Info[0]) >> 16); gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); + if (prot_ver < 0x2b) /* FW < x.43: no 64-bit DMA support */ + ha->dma64_support = 0; + else + ha->dma64_support = 1; } return 1; @@ -1950,7 +1821,7 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1, - ulong32 p2,ulong32 p3) + ulong64 p2,ulong64 p3) { register gdth_ha_str *ha; register gdth_cmd_str *cmd_ptr; @@ -1976,23 +1847,35 @@ if (service == CACHESERVICE) { if (opcode == GDT_IOCTL) { cmd_ptr->u.ioctl.subfunc = p1; - cmd_ptr->u.ioctl.channel = p2; + cmd_ptr->u.ioctl.channel = (ulong32)p2; cmd_ptr->u.ioctl.param_size = (ushort)p3; cmd_ptr->u.ioctl.p_param = ha->scratch_phys; } else { - cmd_ptr->u.cache.DeviceNo = (ushort)p1; - cmd_ptr->u.cache.BlockNo = p2; + if (ha->cache_feat & GDT_64BIT) { + cmd_ptr->u.cache64.DeviceNo = (ushort)p1; + cmd_ptr->u.cache64.BlockNo = p2; + } else { + cmd_ptr->u.cache.DeviceNo = (ushort)p1; + cmd_ptr->u.cache.BlockNo = (ulong32)p2; + } } } else if (service == SCSIRAWSERVICE) { - cmd_ptr->u.raw.direction = p1; - cmd_ptr->u.raw.bus = (unchar)p2; - cmd_ptr->u.raw.target = (unchar)p3; - cmd_ptr->u.raw.lun = (unchar)(p3 >> 8); + if (ha->raw_feat & GDT_64BIT) { + cmd_ptr->u.raw64.direction = p1; + cmd_ptr->u.raw64.bus = (unchar)p2; + cmd_ptr->u.raw64.target = (unchar)p3; + cmd_ptr->u.raw64.lun = (unchar)(p3 >> 8); + } else { + cmd_ptr->u.raw.direction = p1; + cmd_ptr->u.raw.bus = (unchar)p2; + cmd_ptr->u.raw.target = (unchar)p3; + cmd_ptr->u.raw.lun = (unchar)(p3 >> 8); + } } else if (service == SCREENSERVICE) { if (opcode == GDT_REALTIME) { *(ulong32 *)&cmd_ptr->u.screen.su.data[0] = p1; - *(ulong32 *)&cmd_ptr->u.screen.su.data[4] = p2; - *(ulong32 *)&cmd_ptr->u.screen.su.data[8] = p3; + *(ulong32 *)&cmd_ptr->u.screen.su.data[4] = (ulong32)p2; + *(ulong32 *)&cmd_ptr->u.screen.su.data[8] = (ulong32)p3; } } ha->cmd_len = sizeof(gdth_cmd_str); @@ -2020,6 +1903,7 @@ { register gdth_ha_str *ha; ushort cdev_cnt, i; + int ok; ulong32 bus_no, drv_cnt, drv_no, j; gdth_getch_str *chn; gdth_drlist_str *drl; @@ -2028,6 +1912,9 @@ gdth_arcdl_str *alst; gdth_alist_str *alst2; gdth_oem_str_ioctl *oemstr; +#ifdef INT_COAL + gdth_perf_modes *pmod; +#endif #ifdef GDTH_RTC unchar rtc[12]; @@ -2036,11 +1923,20 @@ TRACE(("gdth_search_drives() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); + ok = 0; /* initialize controller services, at first: screen service */ - if (!gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0)) { - printk("GDT: Initialization error screen service (code %d)\n", - ha->status); + ha->screen_feat = 0; + if (!force_dma32) { + ok = gdth_internal_cmd(hanum,SCREENSERVICE,GDT_X_INIT_SCR,0,0,0); + if (ok) + ha->screen_feat = GDT_64BIT; + } + if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC)) + ok = gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0); + if (!ok) { + printk("GDT-HA %d: Initialization error screen service (code %d)\n", + hanum, ha->status); return 0; } TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n")); @@ -2060,7 +1956,7 @@ for (j = 0; j < 12; ++j) rtc[j] = CMOS_READ(j); } while (rtc[0] != CMOS_READ(0)); - spin_unlock_irqrestore(&rtc_lock, flags); + spin_lock_irqrestore(&rtc_lock, flags); TRACE2(("gdth_search_drives(): RTC: %x/%x/%x\n",*(ulong32 *)&rtc[0], *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8])); /* 3. send to controller firmware */ @@ -2072,15 +1968,52 @@ gdth_internal_cmd(hanum,CACHESERVICE,GDT_UNFREEZE_IO,0,0,0); /* initialize cache service */ - if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) { - printk("GDT: Initialization error cache service (code %d)\n", - ha->status); + ha->cache_feat = 0; + if (!force_dma32) { + ok = gdth_internal_cmd(hanum,CACHESERVICE,GDT_X_INIT_HOST,LINUX_OS,0,0); + if (ok) + ha->cache_feat = GDT_64BIT; + } + if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC)) + ok = gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0); + if (!ok) { + printk("GDT-HA %d: Initialization error cache service (code %d)\n", + hanum, ha->status); return 0; } TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n")); cdev_cnt = (ushort)ha->info; ha->fw_vers = ha->service; +#ifdef INT_COAL + if (ha->type == GDT_PCIMPR) { + /* set perf. modes */ + pmod = (gdth_perf_modes *)ha->pscratch; + pmod->version = 1; + pmod->st_mode = 1; /* enable one status buffer */ + *((ulong64 *)&pmod->st_buff_addr1) = ha->coal_stat_phys; + pmod->st_buff_indx1 = COALINDEX; + pmod->st_buff_addr2 = 0; + pmod->st_buff_u_addr2 = 0; + pmod->st_buff_indx2 = 0; + pmod->st_buff_size = sizeof(gdth_coal_status) * MAXOFFSETS; + pmod->cmd_mode = 0; // disable all cmd buffers + pmod->cmd_buff_addr1 = 0; + pmod->cmd_buff_u_addr1 = 0; + pmod->cmd_buff_indx1 = 0; + pmod->cmd_buff_addr2 = 0; + pmod->cmd_buff_u_addr2 = 0; + pmod->cmd_buff_indx2 = 0; + pmod->cmd_buff_size = 0; + pmod->reserved1 = 0; + pmod->reserved2 = 0; + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,SET_PERF_MODES, + INVALID_CHANNEL,sizeof(gdth_perf_modes))) { + printk("GDT-HA %d: Interrupt coalescing activated\n", hanum); + } + } +#endif + /* detect number of buses - try new IOCTL */ iocr = (gdth_raw_iochan_str *)ha->pscratch; iocr->hdr.version = 0xffffffff; @@ -2108,8 +2041,8 @@ IO_CHANNEL | INVALID_CHANNEL, sizeof(gdth_getch_str))) { if (bus_no == 0) { - printk("GDT: Error detecting channel count (0x%x)\n", - ha->status); + printk("GDT-HA %d: Error detecting channel count (0x%x)\n", + hanum, ha->status); return 0; } break; @@ -2126,8 +2059,8 @@ /* read cache configuration */ if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_INFO, INVALID_CHANNEL,sizeof(gdth_cinfo_str))) { - printk("GDT: Initialization error cache service (code %d)\n", - ha->status); + printk("GDT-HA %d: Initialization error cache service (code %d)\n", + hanum, ha->status); return 0; } ha->cpar = ((gdth_cinfo_str *)ha->pscratch)->cpar; @@ -2246,9 +2179,17 @@ } /* initialize raw service */ - if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0)) { - printk("GDT: Initialization error raw service (code %d)\n", - ha->status); + ha->raw_feat = 0; + if (!force_dma32) { + ok = gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_X_INIT_RAW,0,0,0); + if (ok) + ha->raw_feat = GDT_64BIT; + } + if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC)) + ok = gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0); + if (!ok) { + printk("GDT-HA %d: Initialization error raw service (code %d)\n", + hanum, ha->status); return 0; } TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n")); @@ -2260,7 +2201,7 @@ if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) { TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n", ha->info)); - ha->raw_feat = (ushort)ha->info; + ha->raw_feat |= (ushort)ha->info; } } @@ -2271,7 +2212,7 @@ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_GET_FEAT,0,0,0)) { TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n", ha->info)); - ha->cache_feat = (ushort)ha->info; + ha->cache_feat |= (ushort)ha->info; } } @@ -2291,8 +2232,8 @@ if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE,0, reserve_list[i+1], reserve_list[i+2] | (reserve_list[i+3] << 8))) { - printk("GDT: Error raw service (RESERVE, code %d)\n", - ha->status); + printk("GDT-HA %d: Error raw service (RESERVE, code %d)\n", + hanum, ha->status); } } } @@ -2305,17 +2246,32 @@ CACHE_READ_OEM_STRING_RECORD,INVALID_CHANNEL, sizeof(gdth_oem_str_ioctl))) { TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD OK\n")); - printk("GDT CTR%d Vendor: %s\n",hanum,oemstr->text.oem_company_name); + printk("GDT-HA %d: Vendor: %s Name: %s\n", + hanum,oemstr->text.oem_company_name,ha->binfo.type_string); /* Save the Host Drive inquiry data */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) strlcpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id, - sizeof(ha->oem_name)); + sizeof(ha->oem_name)); +#else + strncpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,7); + ha->oem_name[7] = '\0'; +#endif } else { /* Old method, based on PCI ID */ TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD failed\n")); + printk("GDT-HA %d: Name: %s\n", + hanum,ha->binfo.type_string); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) if (ha->oem_id == OEM_ID_INTEL) strlcpy(ha->oem_name,"Intel ", sizeof(ha->oem_name)); else strlcpy(ha->oem_name,"ICP ", sizeof(ha->oem_name)); +#else + if (ha->oem_id == OEM_ID_INTEL) + strcpy(ha->oem_name,"Intel "); + else + strcpy(ha->oem_name,"ICP "); +#endif } /* scanning for host drives */ @@ -2329,7 +2285,8 @@ static int gdth_analyse_hdrive(int hanum,ushort hdrive) { register gdth_ha_str *ha; - int drv_cyls, drv_hds, drv_secs; + ulong32 drv_cyls; + int drv_hds, drv_secs; TRACE(("gdth_analyse_hdrive() hanum %d drive %d\n",hanum,hdrive)); if (hdrive >= MAX_HDRIVES) @@ -2340,7 +2297,7 @@ return 0; ha->hdr[hdrive].present = TRUE; ha->hdr[hdrive].size = ha->info; - + /* evaluate mapping (sectors per head, heads per cylinder) */ ha->hdr[hdrive].size &= ~SECS32; if (ha->info2 == 0) { @@ -2348,15 +2305,22 @@ } else { drv_hds = ha->info2 & 0xff; drv_secs = (ha->info2 >> 8) & 0xff; - drv_cyls = ha->hdr[hdrive].size /drv_hds/drv_secs; + drv_cyls = (ulong32)ha->hdr[hdrive].size / drv_hds / drv_secs; } ha->hdr[hdrive].heads = (unchar)drv_hds; ha->hdr[hdrive].secs = (unchar)drv_secs; /* round size */ ha->hdr[hdrive].size = drv_cyls * drv_hds * drv_secs; + + if (ha->cache_feat & GDT_64BIT) { + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_X_INFO,hdrive,0,0) + && ha->info2 != 0) { + ha->hdr[hdrive].size = ((ulong64)ha->info2 << 32) | ha->info; + } + } TRACE2(("gdth_search_dr() cdr. %d size %d hds %d scs %d\n", hdrive,ha->hdr[hdrive].size,drv_hds,drv_secs)); - + /* get informations about device */ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,hdrive,0,0)) { TRACE2(("gdth_search_dr() cache drive %d devtype %d\n", @@ -2398,14 +2362,13 @@ GDTH_LOCK_HA(ha, flags); scp->SCp.this_residual = (int)priority; -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; #else b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel; t = scp->target; #endif -#if LINUX_VERSION_CODE >= 0x010300 if (priority >= DEFAULT_PRI) { if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) { @@ -2413,7 +2376,6 @@ scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); } } -#endif if (ha->req_first==NULL) { ha->req_first = scp; /* queue was empty */ @@ -2465,7 +2427,7 @@ for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) { if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr) pscp = (Scsi_Cmnd *)pscp->SCp.ptr; -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) b = virt_ctr ? NUMDATA(nscp->device->host)->busnum : nscp->device->channel; t = nscp->device->id; l = nscp->device->lun; @@ -2493,10 +2455,7 @@ firsttime = FALSE; } -#if LINUX_VERSION_CODE >= 0x010300 - if (nscp->done != gdth_scsi_done || nscp->cmnd[0] != 0xff) -#endif - { + if (nscp->done != gdth_scsi_done || nscp->cmnd[0] != 0xff) { if (nscp->SCp.phase == -1) { nscp->SCp.phase = CACHESERVICE; /* default: cache svc. */ if (nscp->cmnd[0] == TEST_UNIT_READY) { @@ -2565,16 +2524,11 @@ GDTH_LOCK_HA(ha,flags); } } - } else - -#if LINUX_VERSION_CODE >= 0x010300 - if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) { + } else if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) { if (!(cmd_index=gdth_special_cmd(hanum,nscp))) this_cmd = FALSE; next_cmd = FALSE; - } else -#endif - if (b != ha->virt_bus) { + } else if (b != ha->virt_bus) { if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW || !(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b)))) this_cmd = FALSE; @@ -2603,6 +2557,9 @@ case VERIFY: case START_STOP: case MODE_SENSE: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + case SERVICE_ACTION_IN: +#endif TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0], nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], nscp->cmnd[4],nscp->cmnd[5])); @@ -2674,6 +2631,10 @@ case WRITE_6: case READ_10: case WRITE_10: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + case READ_16: + case WRITE_16: +#endif if (ha->hdr[t].media_changed) { /* return UNIT_ATTENTION */ TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n", @@ -2701,8 +2662,8 @@ TRACE2(("cache cmd %x/%x/%x/%x/%x/%x unknown\n",nscp->cmnd[0], nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], nscp->cmnd[4],nscp->cmnd[5])); - printk("GDT: Unknown SCSI command 0x%x to cache service !\n", - nscp->cmnd[0]); + printk("GDT-HA %d: Unknown SCSI command 0x%x to cache service !\n", + hanum, nscp->cmnd[0]); nscp->result = DID_ABORT << 16; if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; @@ -2737,11 +2698,11 @@ if (gdth_polling && ha->cmd_cnt > 0) { if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT)) - printk("GDT: Controller %d: Command %d timed out !\n", + printk("GDT-HA %d: Command %d timed out !\n", hanum,cmd_index); } } - + static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp, char *buffer,ushort count) { @@ -2757,7 +2718,7 @@ if (scp->use_sg) { sl = (struct scatterlist *)scp->request_buffer; -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,PCI_DMA_FROMDEVICE); for (i=0,cpsum=0; i cpcount) cpnow = cpcount - cpsum; cpsum += cpnow; - address = (char *)phys_to_virt(sg_dma_address(sl)); + if (!sl->page) { + printk("GDT-HA %d: invalid sc/gt element in gdth_copy_internal_data()\n", + hanum); + return; + } + address = (char *)(page_address(sl->page) + sl->offset); memcpy(address,buffer,cpnow); if (cpsum == cpcount) break; @@ -2806,7 +2772,7 @@ gdth_modep_data mpd; ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) t = scp->device->id; #else t = scp->target; @@ -2814,6 +2780,9 @@ TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n", scp->cmnd[0],t)); + scp->result = DID_OK << 16; + scp->sense_buffer[0] = 0; + switch (scp->cmnd[0]) { case TEST_UNIT_READY: case VERIFY: @@ -2864,19 +2833,35 @@ case READ_CAPACITY: TRACE2(("Read capacity hdrive %d\n",t)); - rdc.last_block_no = ntohl(ha->hdr[t].size-1); - rdc.block_length = ntohl(SECTOR_SIZE); + if (ha->hdr[t].size > (ulong64)0xffffffff) + rdc.last_block_no = 0xffffffff; + else + rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1); + rdc.block_length = cpu_to_be32(SECTOR_SIZE); gdth_copy_internal_data(hanum,scp,(char*)&rdc,sizeof(gdth_rdcap_data)); break; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + case SERVICE_ACTION_IN: + if ((scp->cmnd[1] & 0x1f) == SAI_READ_CAPACITY_16 && + (ha->cache_feat & GDT_64BIT)) { + gdth_rdcap16_data rdc16; + + TRACE2(("Read capacity (16) hdrive %d\n",t)); + rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1); + rdc16.block_length = cpu_to_be32(SECTOR_SIZE); + gdth_copy_internal_data(hanum,scp,(char*)&rdc16,sizeof(gdth_rdcap16_data)); + } else { + scp->result = DID_ABORT << 16; + } + break; +#endif + default: TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0])); break; } - scp->result = DID_OK << 16; - scp->sense_buffer[0] = 0; - if (!scp->SCp.have_data_in) scp->SCp.have_data_in++; else @@ -2890,9 +2875,14 @@ register gdth_ha_str *ha; register gdth_cmd_str *cmdp; struct scatterlist *sl; - ushort i, cnt; - ulong32 no, phys_addr; - int cmd_index, read_write, sgcnt; + ulong32 cnt, blockcnt; + ulong64 no, blockno; + dma_addr_t phys_addr; + int i, cmd_index, read_write, sgcnt, mode64; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) + struct page *page; + ulong offset; +#endif ha = HADATA(gdth_ctr_tab[hanum]); cmdp = ha->pccb; @@ -2902,6 +2892,11 @@ if (ha->type==GDT_EISA && ha->cmd_cnt>0) return 0; + mode64 = (ha->cache_feat & GDT_64BIT) ? TRUE : FALSE; + /* test for READ_16, WRITE_16 if !mode64 ? --- + not required, should not occur due to error return on + READ_CAPACITY_16 */ + cmdp->Service = CACHESERVICE; cmdp->RequestBuffer = scp; /* search free command index */ @@ -2929,7 +2924,11 @@ else cmdp->OpCode = GDT_FLUSH; } else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10 || - scp->cmnd[0] == WRITE_12) { + scp->cmnd[0] == WRITE_12 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + || scp->cmnd[0] == WRITE_16 +#endif + ) { read_write = 1; if (gdth_write_through || ((ha->hdr[hdrive].rw_attribs & 1) && (ha->cache_feat & GDT_WR_THROUGH))) @@ -2940,86 +2939,157 @@ read_write = 2; cmdp->OpCode = GDT_READ; } - - cmdp->BoardNode = LOCALBOARD; - cmdp->u.cache.DeviceNo = hdrive; - cmdp->u.cache.BlockNo = 1; - cmdp->u.cache.sg_canz = 0; + + cmdp->BoardNode = LOCALBOARD; + if (mode64) { + cmdp->u.cache64.DeviceNo = hdrive; + cmdp->u.cache64.BlockNo = 1; + cmdp->u.cache64.sg_canz = 0; + } else { + cmdp->u.cache.DeviceNo = hdrive; + cmdp->u.cache.BlockNo = 1; + cmdp->u.cache.sg_canz = 0; + } if (read_write) { - if (scp->cmd_len != 6) { + if (scp->cmd_len == 16) { + memcpy(&no, &scp->cmnd[2], sizeof(ulong64)); + blockno = be64_to_cpu(no); + memcpy(&cnt, &scp->cmnd[10], sizeof(ulong32)); + blockcnt = be32_to_cpu(cnt); + } else if (scp->cmd_len == 10) { memcpy(&no, &scp->cmnd[2], sizeof(ulong32)); - cmdp->u.cache.BlockNo = ntohl(no); + blockno = be32_to_cpu(no); memcpy(&cnt, &scp->cmnd[7], sizeof(ushort)); - cmdp->u.cache.BlockCnt = (ulong32)ntohs(cnt); + blockcnt = be16_to_cpu(cnt); } else { memcpy(&no, &scp->cmnd[0], sizeof(ulong32)); - cmdp->u.cache.BlockNo = ntohl(no) & 0x001fffffUL; - cmdp->u.cache.BlockCnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4]; + blockno = be32_to_cpu(no) & 0x001fffffUL; + blockcnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4]; + } + if (mode64) { + cmdp->u.cache64.BlockNo = blockno; + cmdp->u.cache64.BlockCnt = blockcnt; + } else { + cmdp->u.cache.BlockNo = (ulong32)blockno; + cmdp->u.cache.BlockCnt = blockcnt; } if (scp->use_sg) { - cmdp->u.cache.DestAddr= 0xffffffff; sl = (struct scatterlist *)scp->request_buffer; sgcnt = scp->use_sg; -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) scp->SCp.Status = GDTH_MAP_SG; scp->SCp.Message = (read_write == 1 ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message); - for (i=0; iu.cache.sg_lst[i].sg_ptr = sg_dma_address(sl); - cmdp->u.cache.sg_lst[i].sg_len = sg_dma_len(sl); + if (mode64) { + cmdp->u.cache64.DestAddr= (ulong64)-1; + cmdp->u.cache64.sg_canz = sgcnt; + for (i=0; iu.cache64.sg_lst[i].sg_ptr = sg_dma_address(sl); +#ifdef GDTH_DMA_STATISTICS + if (cmdp->u.cache64.sg_lst[i].sg_ptr > (ulong64)0xffffffff) + ha->dma64_cnt++; + else + ha->dma32_cnt++; +#endif + cmdp->u.cache64.sg_lst[i].sg_len = sg_dma_len(sl); + } + } else { + cmdp->u.cache.DestAddr= 0xffffffff; + cmdp->u.cache.sg_canz = sgcnt; + for (i=0; iu.cache.sg_lst[i].sg_ptr = sg_dma_address(sl); +#ifdef GDTH_DMA_STATISTICS + ha->dma32_cnt++; +#endif + cmdp->u.cache.sg_lst[i].sg_len = sg_dma_len(sl); + } } #else - for (i=0; iu.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address); - cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length; + if (mode64) { + cmdp->u.cache64.DestAddr= (ulong64)-1; + cmdp->u.cache64.sg_canz = sgcnt; + for (i=0; iu.cache64.sg_lst[i].sg_ptr = virt_to_bus(sl->address); + cmdp->u.cache64.sg_lst[i].sg_len = (ulong32)sl->length; + } + } else { + cmdp->u.cache.DestAddr= 0xffffffff; + cmdp->u.cache.sg_canz = sgcnt; + for (i=0; iu.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address); + cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length; + } } #endif - cmdp->u.cache.sg_canz = (ulong32)i; #ifdef GDTH_STATISTICS - if (max_sg < (ulong32)i) { - max_sg = (ulong32)i; - TRACE3(("GDT: max_sg = %d\n",i)); + if (max_sg < (ulong32)sgcnt) { + max_sg = (ulong32)sgcnt; + TRACE3(("GDT: max_sg = %d\n",max_sg)); } #endif - if (iu.cache.sg_lst[i].sg_len = 0; + } else { -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) scp->SCp.Status = GDTH_MAP_SINGLE; scp->SCp.Message = (read_write == 1 ? - PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - phys_addr = pci_map_single(ha->pdev,scp->request_buffer, - scp->request_bufflen,scp->SCp.Message); + PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); + page = virt_to_page(scp->request_buffer); + offset = (ulong)scp->request_buffer & ~PAGE_MASK; + phys_addr = pci_map_page(ha->pdev,page,offset, + scp->request_bufflen,scp->SCp.Message); scp->SCp.dma_handle = phys_addr; #else phys_addr = virt_to_bus(scp->request_buffer); #endif - if (ha->cache_feat & SCATTER_GATHER) { - cmdp->u.cache.DestAddr = 0xffffffff; - cmdp->u.cache.sg_canz = 1; - cmdp->u.cache.sg_lst[0].sg_ptr = phys_addr; - cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen; - cmdp->u.cache.sg_lst[1].sg_len = 0; + if (mode64) { + if (ha->cache_feat & SCATTER_GATHER) { + cmdp->u.cache64.DestAddr = (ulong64)-1; + cmdp->u.cache64.sg_canz = 1; + cmdp->u.cache64.sg_lst[0].sg_ptr = phys_addr; + cmdp->u.cache64.sg_lst[0].sg_len = scp->request_bufflen; + cmdp->u.cache64.sg_lst[1].sg_len = 0; + } else { + cmdp->u.cache64.DestAddr = phys_addr; + cmdp->u.cache64.sg_canz= 0; + } } else { - cmdp->u.cache.DestAddr = phys_addr; - cmdp->u.cache.sg_canz= 0; + if (ha->cache_feat & SCATTER_GATHER) { + cmdp->u.cache.DestAddr = 0xffffffff; + cmdp->u.cache.sg_canz = 1; + cmdp->u.cache.sg_lst[0].sg_ptr = phys_addr; + cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen; + cmdp->u.cache.sg_lst[1].sg_len = 0; + } else { + cmdp->u.cache.DestAddr = phys_addr; + cmdp->u.cache.sg_canz= 0; + } } } } - TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", - cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz, - cmdp->u.cache.sg_lst[0].sg_ptr, - cmdp->u.cache.sg_lst[0].sg_len)); - TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n", - cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt)); - /* evaluate command size, check space */ - ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + - (ushort)cmdp->u.cache.sg_canz * sizeof(gdth_sg_str); + if (mode64) { + TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", + cmdp->u.cache64.DestAddr,cmdp->u.cache64.sg_canz, + cmdp->u.cache64.sg_lst[0].sg_ptr, + cmdp->u.cache64.sg_lst[0].sg_len)); + TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n", + cmdp->OpCode,cmdp->u.cache64.BlockNo,cmdp->u.cache64.BlockCnt)); + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache64.sg_lst) + + (ushort)cmdp->u.cache64.sg_canz * sizeof(gdth_sg64_str); + } else { + TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", + cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz, + cmdp->u.cache.sg_lst[0].sg_ptr, + cmdp->u.cache.sg_lst[0].sg_len)); + TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n", + cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt)); + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + + (ushort)cmdp->u.cache.sg_canz * sizeof(gdth_sg_str); + } if (ha->cmd_len & 3) ha->cmd_len += (4 - (ha->cmd_len & 3)); @@ -3043,12 +3113,16 @@ register gdth_cmd_str *cmdp; struct scatterlist *sl; ushort i; - ulong32 phys_addr, sense_paddr; - int cmd_index, sgcnt; + dma_addr_t phys_addr, sense_paddr; + int cmd_index, sgcnt, mode64; unchar t,l; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) + struct page *page; + ulong offset; +#endif ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) t = scp->device->id; l = scp->device->lun; #else @@ -3062,6 +3136,8 @@ if (ha->type==GDT_EISA && ha->cmd_cnt>0) return 0; + mode64 = (ha->raw_feat & GDT_64BIT) ? TRUE : FALSE; + cmdp->Service = SCSIRAWSERVICE; cmdp->RequestBuffer = scp; /* search free command index */ @@ -3077,95 +3153,176 @@ if (scp->SCp.sent_command != -1) { cmdp->OpCode = scp->SCp.sent_command; /* special raw cmd. */ cmdp->BoardNode = LOCALBOARD; - cmdp->u.raw.direction = (scp->SCp.phase >> 8); - TRACE2(("special raw cmd 0x%x param 0x%x\n", - cmdp->OpCode, cmdp->u.raw.direction)); + if (mode64) { + cmdp->u.raw64.direction = (scp->SCp.phase >> 8); + TRACE2(("special raw cmd 0x%x param 0x%x\n", + cmdp->OpCode, cmdp->u.raw64.direction)); + /* evaluate command size */ + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst); + } else { + cmdp->u.raw.direction = (scp->SCp.phase >> 8); + TRACE2(("special raw cmd 0x%x param 0x%x\n", + cmdp->OpCode, cmdp->u.raw.direction)); + /* evaluate command size */ + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst); + } - /* evaluate command size */ - ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst); } else { -#if LINUX_VERSION_CODE >= 0x020400 - sense_paddr = pci_map_single(ha->pdev,scp->sense_buffer, - 16,PCI_DMA_FROMDEVICE); - scp->SCp.buffer = (struct scatterlist *)sense_paddr; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) + page = virt_to_page(scp->sense_buffer); + offset = (ulong)scp->sense_buffer & ~PAGE_MASK; + sense_paddr = pci_map_page(ha->pdev,page,offset, + 16,PCI_DMA_FROMDEVICE); + scp->SCp.buffer = (struct scatterlist *)((ulong32)sense_paddr); + /* high part, if 64bit */ + scp->host_scribble = (char *)(ulong32)((ulong64)sense_paddr >> 32); #else sense_paddr = virt_to_bus(scp->sense_buffer); #endif cmdp->OpCode = GDT_WRITE; /* always */ cmdp->BoardNode = LOCALBOARD; - cmdp->u.raw.reserved = 0; - cmdp->u.raw.mdisc_time = 0; - cmdp->u.raw.mcon_time = 0; - cmdp->u.raw.clen = scp->cmd_len; - cmdp->u.raw.target = t; - cmdp->u.raw.lun = l; - cmdp->u.raw.bus = b; - cmdp->u.raw.priority = 0; - cmdp->u.raw.link_p = 0; - cmdp->u.raw.sdlen = scp->request_bufflen; - cmdp->u.raw.sense_len = 16; - cmdp->u.raw.sense_data = sense_paddr; - cmdp->u.raw.direction = - gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN; - memcpy(cmdp->u.raw.cmd,scp->cmnd,12); + if (mode64) { + cmdp->u.raw64.reserved = 0; + cmdp->u.raw64.mdisc_time = 0; + cmdp->u.raw64.mcon_time = 0; + cmdp->u.raw64.clen = scp->cmd_len; + cmdp->u.raw64.target = t; + cmdp->u.raw64.lun = l; + cmdp->u.raw64.bus = b; + cmdp->u.raw64.priority = 0; + cmdp->u.raw64.sdlen = scp->request_bufflen; + cmdp->u.raw64.sense_len = 16; + cmdp->u.raw64.sense_data = sense_paddr; + cmdp->u.raw64.direction = + gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN; + memcpy(cmdp->u.raw64.cmd,scp->cmnd,16); + } else { + cmdp->u.raw.reserved = 0; + cmdp->u.raw.mdisc_time = 0; + cmdp->u.raw.mcon_time = 0; + cmdp->u.raw.clen = scp->cmd_len; + cmdp->u.raw.target = t; + cmdp->u.raw.lun = l; + cmdp->u.raw.bus = b; + cmdp->u.raw.priority = 0; + cmdp->u.raw.link_p = 0; + cmdp->u.raw.sdlen = scp->request_bufflen; + cmdp->u.raw.sense_len = 16; + cmdp->u.raw.sense_data = sense_paddr; + cmdp->u.raw.direction = + gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN; + memcpy(cmdp->u.raw.cmd,scp->cmnd,12); + } if (scp->use_sg) { - cmdp->u.raw.sdata = 0xffffffff; sl = (struct scatterlist *)scp->request_buffer; sgcnt = scp->use_sg; -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) scp->SCp.Status = GDTH_MAP_SG; scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message); - for (i=0; iu.raw.sg_lst[i].sg_ptr = sg_dma_address(sl); - cmdp->u.raw.sg_lst[i].sg_len = sg_dma_len(sl); + if (mode64) { + cmdp->u.raw64.sdata = (ulong64)-1; + cmdp->u.raw64.sg_ranz = sgcnt; + for (i=0; iu.raw64.sg_lst[i].sg_ptr = sg_dma_address(sl); +#ifdef GDTH_DMA_STATISTICS + if (cmdp->u.raw64.sg_lst[i].sg_ptr > (ulong64)0xffffffff) + ha->dma64_cnt++; + else + ha->dma32_cnt++; +#endif + cmdp->u.raw64.sg_lst[i].sg_len = sg_dma_len(sl); + } + } else { + cmdp->u.raw.sdata = 0xffffffff; + cmdp->u.raw.sg_ranz = sgcnt; + for (i=0; iu.raw.sg_lst[i].sg_ptr = sg_dma_address(sl); +#ifdef GDTH_DMA_STATISTICS + ha->dma32_cnt++; +#endif + cmdp->u.raw.sg_lst[i].sg_len = sg_dma_len(sl); + } } #else - for (i=0; iu.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address); - cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length; + if (mode64) { + cmdp->u.raw64.sdata = (ulong64)-1; + cmdp->u.raw64.sg_ranz = sgcnt; + for (i=0; iu.raw64.sg_lst[i].sg_ptr = virt_to_bus(sl->address); + cmdp->u.raw64.sg_lst[i].sg_len = (ulong32)sl->length; + } + } else { + cmdp->u.raw.sdata = 0xffffffff; + cmdp->u.raw.sg_ranz = sgcnt; + for (i=0; iu.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address); + cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length; + } } #endif - cmdp->u.raw.sg_ranz = (ulong32)i; #ifdef GDTH_STATISTICS - if (max_sg < (ulong32)i) { - max_sg = (ulong32)i; - TRACE3(("GDT: max_sg = %d\n",i)); + if (max_sg < sgcnt) { + max_sg = sgcnt; + TRACE3(("GDT: max_sg = %d\n",sgcnt)); } #endif - if (iu.raw.sg_lst[i].sg_len = 0; + } else { -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) scp->SCp.Status = GDTH_MAP_SINGLE; scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; - phys_addr = pci_map_single(ha->pdev,scp->request_buffer, - scp->request_bufflen,scp->SCp.Message); + page = virt_to_page(scp->request_buffer); + offset = (ulong)scp->request_buffer & ~PAGE_MASK; + phys_addr = pci_map_page(ha->pdev,page,offset, + scp->request_bufflen,scp->SCp.Message); scp->SCp.dma_handle = phys_addr; #else phys_addr = virt_to_bus(scp->request_buffer); #endif - if (ha->raw_feat & SCATTER_GATHER) { - cmdp->u.raw.sdata = 0xffffffff; - cmdp->u.raw.sg_ranz= 1; - cmdp->u.raw.sg_lst[0].sg_ptr = phys_addr; - cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen; - cmdp->u.raw.sg_lst[1].sg_len = 0; + if (mode64) { + if (ha->raw_feat & SCATTER_GATHER) { + cmdp->u.raw64.sdata = (ulong64)-1; + cmdp->u.raw64.sg_ranz= 1; + cmdp->u.raw64.sg_lst[0].sg_ptr = phys_addr; + cmdp->u.raw64.sg_lst[0].sg_len = scp->request_bufflen; + cmdp->u.raw64.sg_lst[1].sg_len = 0; + } else { + cmdp->u.raw64.sdata = phys_addr; + cmdp->u.raw64.sg_ranz= 0; + } } else { - cmdp->u.raw.sdata = phys_addr; - cmdp->u.raw.sg_ranz= 0; + if (ha->raw_feat & SCATTER_GATHER) { + cmdp->u.raw.sdata = 0xffffffff; + cmdp->u.raw.sg_ranz= 1; + cmdp->u.raw.sg_lst[0].sg_ptr = phys_addr; + cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen; + cmdp->u.raw.sg_lst[1].sg_len = 0; + } else { + cmdp->u.raw.sdata = phys_addr; + cmdp->u.raw.sg_ranz= 0; + } } } - TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", - cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz, - cmdp->u.raw.sg_lst[0].sg_ptr, - cmdp->u.raw.sg_lst[0].sg_len)); - - /* evaluate command size */ - ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + - (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str); + if (mode64) { + TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", + cmdp->u.raw64.sdata,cmdp->u.raw64.sg_ranz, + cmdp->u.raw64.sg_lst[0].sg_ptr, + cmdp->u.raw64.sg_lst[0].sg_len)); + /* evaluate command size */ + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst) + + (ushort)cmdp->u.raw64.sg_ranz * sizeof(gdth_sg64_str); + } else { + TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", + cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz, + cmdp->u.raw.sg_lst[0].sg_ptr, + cmdp->u.raw.sg_lst[0].sg_len)); + /* evaluate command size */ + ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + + (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str); + } } /* check space */ if (ha->cmd_len & 3) @@ -3215,15 +3372,23 @@ if (cmdp->OpCode == GDT_IOCTL) { TRACE2(("IOCTL\n")); ha->cmd_len = - GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong32); + GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong64); } else if (cmdp->Service == CACHESERVICE) { TRACE2(("cache command %d\n",cmdp->OpCode)); - ha->cmd_len = - GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str); + if (ha->cache_feat & GDT_64BIT) + ha->cmd_len = + GDTOFFSOF(gdth_cmd_str,u.cache64.sg_lst) + sizeof(gdth_sg64_str); + else + ha->cmd_len = + GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str); } else if (cmdp->Service == SCSIRAWSERVICE) { - TRACE2(("raw command %d/%d\n",cmdp->OpCode,cmdp->u.raw.cmd[0])); - ha->cmd_len = - GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str); + TRACE2(("raw command %d\n",cmdp->OpCode)); + if (ha->raw_feat & GDT_64BIT) + ha->cmd_len = + GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst) + sizeof(gdth_sg64_str); + else + ha->cmd_len = + GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str); } if (ha->cmd_len & 3) @@ -3366,10 +3531,14 @@ /* SCSI interface functions */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static irqreturn_t gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs) +#else +static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs) +#endif { register gdth_ha_str *ha; - gdt6m_dpram_str *dp6m_ptr; + gdt6m_dpram_str *dp6m_ptr = NULL; gdt6_dpram_str *dp6_ptr; gdt2_dpram_str *dp2_ptr; Scsi_Cmnd *scp; @@ -3377,13 +3546,23 @@ unchar IStatus; ushort Service; ulong flags = 0; +#ifdef INT_COAL + int coalesced = FALSE; + int next = FALSE; + gdth_coal_status *pcs = NULL; + int act_int_coal = 0; +#endif TRACE(("gdth_interrupt() IRQ %d\n",irq)); /* if polling and not from gdth_wait() -> return */ if (gdth_polling) { if (!gdth_from_wait) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) return IRQ_HANDLED; +#else + return; +#endif } } @@ -3396,174 +3575,261 @@ /* spurious interrupt */ if (!gdth_polling) GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - return IRQ_HANDLED; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + return IRQ_HANDLED; +#else + return; +#endif } + ha = HADATA(gdth_ctr_tab[hanum]); #ifdef GDTH_STATISTICS ++act_ints; #endif - - ha = HADATA(gdth_ctr_tab[hanum]); - if (ha->type == GDT_EISA) { - if (IStatus & 0x80) { /* error flag */ - IStatus &= ~0x80; - ha->status = inw(ha->bmic + MAILBOXREG+8); - TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); - } else /* no error */ - ha->status = S_OK; - ha->info = inl(ha->bmic + MAILBOXREG+12); - ha->service = inw(ha->bmic + MAILBOXREG+10); - ha->info2 = inl(ha->bmic + MAILBOXREG+4); - - outb(0xff, ha->bmic + EDOORREG); /* acknowledge interrupt */ - outb(0x00, ha->bmic + SEMA1REG); /* reset status semaphore */ - } else if (ha->type == GDT_ISA) { - dp2_ptr = (gdt2_dpram_str *)ha->brd; - if (IStatus & 0x80) { /* error flag */ - IStatus &= ~0x80; - ha->status = gdth_readw(&dp2_ptr->u.ic.Status); - TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); - } else /* no error */ - ha->status = S_OK; - ha->info = gdth_readl(&dp2_ptr->u.ic.Info[0]); - ha->service = gdth_readw(&dp2_ptr->u.ic.Service); - ha->info2 = gdth_readl(&dp2_ptr->u.ic.Info[1]); - - gdth_writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */ - gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index); /* reset command index */ - gdth_writeb(0, &dp2_ptr->io.Sema1); /* reset status semaphore */ - } else if (ha->type == GDT_PCI) { - dp6_ptr = (gdt6_dpram_str *)ha->brd; - if (IStatus & 0x80) { /* error flag */ - IStatus &= ~0x80; - ha->status = gdth_readw(&dp6_ptr->u.ic.Status); - TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); - } else /* no error */ - ha->status = S_OK; - ha->info = gdth_readl(&dp6_ptr->u.ic.Info[0]); - ha->service = gdth_readw(&dp6_ptr->u.ic.Service); - ha->info2 = gdth_readl(&dp6_ptr->u.ic.Info[1]); - - gdth_writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */ - gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index); /* reset command index */ - gdth_writeb(0, &dp6_ptr->io.Sema1); /* reset status semaphore */ - } else if (ha->type == GDT_PCINEW) { - if (IStatus & 0x80) { /* error flag */ - IStatus &= ~0x80; - ha->status = inw(PTR2USHORT(&ha->plx->status)); - TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); - } else - ha->status = S_OK; - ha->info = inl(PTR2USHORT(&ha->plx->info[0])); - ha->service = inw(PTR2USHORT(&ha->plx->service)); - ha->info2 = inl(PTR2USHORT(&ha->plx->info[1])); - outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); - outb(0x00, PTR2USHORT(&ha->plx->sema1_reg)); - } else if (ha->type == GDT_PCIMPR) { - dp6m_ptr = (gdt6m_dpram_str *)ha->brd; - if (IStatus & 0x80) { /* error flag */ - IStatus &= ~0x80; - ha->status = gdth_readw(&dp6m_ptr->i960r.status); - TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); - } else /* no error */ - ha->status = S_OK; - ha->info = gdth_readl(&dp6m_ptr->i960r.info[0]); - ha->service = gdth_readw(&dp6m_ptr->i960r.service); - ha->info2 = gdth_readl(&dp6m_ptr->i960r.info[1]); +#ifdef INT_COAL + /* See if the fw is returning coalesced status */ + if (IStatus == COALINDEX) { + /* Coalesced status. Setup the initial status + buffer pointer and flags */ + pcs = ha->coal_stat; + coalesced = TRUE; + next = TRUE; + } - /* event string */ - if (IStatus == ASYNCINDEX) { - if (ha->service != SCREENSERVICE && - (ha->fw_vers & 0xff) >= 0x1a) { - ha->dvr.severity = - gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.severity); - for (i = 0; i < 256; ++i) { - ha->dvr.event_string[i] = gdth_readb - (&((gdt6m_dpram_str *)ha->brd)->i960r.evt_str[i]); - if (ha->dvr.event_string[i] == 0) - break; - } - } + do { + if (coalesced) { + /* For coalesced requests all status + information is found in the status buffer */ + IStatus = (unchar)(pcs->status & 0xff); + } +#endif + + if (ha->type == GDT_EISA) { + if (IStatus & 0x80) { /* error flag */ + IStatus &= ~0x80; + ha->status = inw(ha->bmic + MAILBOXREG+8); + TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); + } else /* no error */ + ha->status = S_OK; + ha->info = inl(ha->bmic + MAILBOXREG+12); + ha->service = inw(ha->bmic + MAILBOXREG+10); + ha->info2 = inl(ha->bmic + MAILBOXREG+4); + + outb(0xff, ha->bmic + EDOORREG); /* acknowledge interrupt */ + outb(0x00, ha->bmic + SEMA1REG); /* reset status semaphore */ + } else if (ha->type == GDT_ISA) { + dp2_ptr = (gdt2_dpram_str *)ha->brd; + if (IStatus & 0x80) { /* error flag */ + IStatus &= ~0x80; + ha->status = gdth_readw(&dp2_ptr->u.ic.Status); + TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); + } else /* no error */ + ha->status = S_OK; + ha->info = gdth_readl(&dp2_ptr->u.ic.Info[0]); + ha->service = gdth_readw(&dp2_ptr->u.ic.Service); + ha->info2 = gdth_readl(&dp2_ptr->u.ic.Info[1]); + + gdth_writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */ + gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);/* reset command index */ + gdth_writeb(0, &dp2_ptr->io.Sema1); /* reset status semaphore */ + } else if (ha->type == GDT_PCI) { + dp6_ptr = (gdt6_dpram_str *)ha->brd; + if (IStatus & 0x80) { /* error flag */ + IStatus &= ~0x80; + ha->status = gdth_readw(&dp6_ptr->u.ic.Status); + TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); + } else /* no error */ + ha->status = S_OK; + ha->info = gdth_readl(&dp6_ptr->u.ic.Info[0]); + ha->service = gdth_readw(&dp6_ptr->u.ic.Service); + ha->info2 = gdth_readl(&dp6_ptr->u.ic.Info[1]); + + gdth_writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */ + gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);/* reset command index */ + gdth_writeb(0, &dp6_ptr->io.Sema1); /* reset status semaphore */ + } else if (ha->type == GDT_PCINEW) { + if (IStatus & 0x80) { /* error flag */ + IStatus &= ~0x80; + ha->status = inw(PTR2USHORT(&ha->plx->status)); + TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); + } else + ha->status = S_OK; + ha->info = inl(PTR2USHORT(&ha->plx->info[0])); + ha->service = inw(PTR2USHORT(&ha->plx->service)); + ha->info2 = inl(PTR2USHORT(&ha->plx->info[1])); + + outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); + outb(0x00, PTR2USHORT(&ha->plx->sema1_reg)); + } else if (ha->type == GDT_PCIMPR) { + dp6m_ptr = (gdt6m_dpram_str *)ha->brd; + if (IStatus & 0x80) { /* error flag */ + IStatus &= ~0x80; +#ifdef INT_COAL + if (coalesced) + ha->status = pcs->ext_status && 0xffff; + else +#endif + ha->status = gdth_readw(&dp6m_ptr->i960r.status); + TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); + } else /* no error */ + ha->status = S_OK; +#ifdef INT_COAL + /* get information */ + if (coalesced) { + ha->info = pcs->info0; + ha->info2 = pcs->info1; + ha->service = (pcs->ext_status >> 16) && 0xffff; + } else +#endif + { + ha->info = gdth_readl(&dp6m_ptr->i960r.info[0]); + ha->service = gdth_readw(&dp6m_ptr->i960r.service); + ha->info2 = gdth_readl(&dp6m_ptr->i960r.info[1]); + } + /* event string */ + if (IStatus == ASYNCINDEX) { + if (ha->service != SCREENSERVICE && + (ha->fw_vers & 0xff) >= 0x1a) { + ha->dvr.severity = gdth_readb + (&((gdt6m_dpram_str *)ha->brd)->i960r.severity); + for (i = 0; i < 256; ++i) { + ha->dvr.event_string[i] = gdth_readb + (&((gdt6m_dpram_str *)ha->brd)->i960r.evt_str[i]); + if (ha->dvr.event_string[i] == 0) + break; + } + } + } +#ifdef INT_COAL + /* Make sure that non coalesced interrupts get cleared + before being handled by gdth_async_event/gdth_sync_event */ + if (!coalesced) +#endif + { + gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg); + } + } else { + TRACE2(("gdth_interrupt() unknown controller type\n")); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + return IRQ_HANDLED; +#else + return; +#endif } - gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); - gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg); - } else { - TRACE2(("gdth_interrupt() unknown controller type\n")); - if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - return IRQ_HANDLED; - } - TRACE(("gdth_interrupt() index %d stat %d info %d\n", - IStatus,ha->status,ha->info)); + TRACE(("gdth_interrupt() index %d stat %d info %d\n", + IStatus,ha->status,ha->info)); - if (gdth_from_wait) { - wait_hanum = hanum; - wait_index = (int)IStatus; - } + if (gdth_from_wait) { + wait_hanum = hanum; + wait_index = (int)IStatus; + } - if (IStatus == ASYNCINDEX) { - TRACE2(("gdth_interrupt() async. event\n")); - gdth_async_event(hanum); - if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - gdth_next(hanum); - return IRQ_HANDLED; - } + if (IStatus == ASYNCINDEX) { + TRACE2(("gdth_interrupt() async. event\n")); + gdth_async_event(hanum); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); + gdth_next(hanum); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + return IRQ_HANDLED; +#else + return; +#endif + } - if (IStatus == SPEZINDEX) { - TRACE2(("Service unknown or not initialized !\n")); - ha->dvr.size = sizeof(ha->dvr.eu.driver); - ha->dvr.eu.driver.ionode = hanum; - gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr); - if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - return IRQ_HANDLED; - } - scp = ha->cmd_tab[IStatus-2].cmnd; - Service = ha->cmd_tab[IStatus-2].service; - ha->cmd_tab[IStatus-2].cmnd = UNUSED_CMND; - if (scp == UNUSED_CMND) { - TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus)); - ha->dvr.size = sizeof(ha->dvr.eu.driver); - ha->dvr.eu.driver.ionode = hanum; - ha->dvr.eu.driver.index = IStatus; - gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr); - if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - return IRQ_HANDLED; - } - if (scp == INTERNAL_CMND) { - TRACE(("gdth_interrupt() answer to internal command\n")); + if (IStatus == SPEZINDEX) { + TRACE2(("Service unknown or not initialized !\n")); + ha->dvr.size = sizeof(ha->dvr.eu.driver); + ha->dvr.eu.driver.ionode = hanum; + gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + return IRQ_HANDLED; +#else + return; +#endif + } + scp = ha->cmd_tab[IStatus-2].cmnd; + Service = ha->cmd_tab[IStatus-2].service; + ha->cmd_tab[IStatus-2].cmnd = UNUSED_CMND; + if (scp == UNUSED_CMND) { + TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus)); + ha->dvr.size = sizeof(ha->dvr.eu.driver); + ha->dvr.eu.driver.ionode = hanum; + ha->dvr.eu.driver.index = IStatus; + gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + return IRQ_HANDLED; +#else + return; +#endif + } + if (scp == INTERNAL_CMND) { + TRACE(("gdth_interrupt() answer to internal command\n")); + if (!gdth_polling) + GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + return IRQ_HANDLED; +#else + return; +#endif + } + + TRACE(("gdth_interrupt() sync. status\n")); + rval = gdth_sync_event(hanum,Service,IStatus,scp); if (!gdth_polling) GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - return IRQ_HANDLED; - } - - TRACE(("gdth_interrupt() sync. status\n")); - rval = gdth_sync_event(hanum,Service,IStatus,scp); - if (!gdth_polling) - GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags); - if (rval == 2) { - gdth_putq(hanum,scp,scp->SCp.this_residual); - } else if (rval == 1) { -#if LINUX_VERSION_CODE >= 0x02053C - GDTH_LOCK_SCSI_DONE(scp->device->host, flags); - scp->scsi_done(scp); - GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags); -#elif LINUX_VERSION_CODE >= 0x020503 - GDTH_LOCK_SCSI_DONE(scp->host, flags); - scp->scsi_done(scp); - GDTH_UNLOCK_SCSI_DONE(scp->host, flags); -#else - GDTH_LOCK_SCSI_DONE(flags); - scp->scsi_done(scp); - GDTH_UNLOCK_SCSI_DONE(flags); + if (rval == 2) { + gdth_putq(hanum,scp,scp->SCp.this_residual); + } else if (rval == 1) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + GDTH_LOCK_SCSI_DONE(scp->device->host, flags); + scp->scsi_done(scp); + GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags); +#else + GDTH_LOCK_SCSI_DONE(flags); + scp->scsi_done(scp); + GDTH_UNLOCK_SCSI_DONE(flags); #endif + } + +#ifdef INT_COAL + if (coalesced) { + /* go to the next status in the status buffer */ + ++pcs; +#ifdef GDTH_STATISTICS + ++act_int_coal; + if (act_int_coal > max_int_coal) { + max_int_coal = act_int_coal; + printk("GDT: max_int_coal = %d\n",(ushort)max_int_coal); + } +#endif + /* see if there is another status */ + if (pcs->status == 0) + /* Stop the coalesce loop */ + next = FALSE; + } + } while (next); + + /* coalescing only for new GDT_PCIMPR controllers available */ + if (ha->type == GDT_PCIMPR && coalesced) { + gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg); } +#endif + gdth_next(hanum); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) return IRQ_HANDLED; +#endif } static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) @@ -3579,10 +3845,11 @@ service,ha->status)); if (service == SCREENSERVICE) { - msg = (gdth_msg_str *)ha->pscratch; - ha->scratch_busy = FALSE; + msg = ha->pmsg; TRACE(("len: %d, answer: %d, ext: %d, alen: %d\n", msg->msg_len,msg->msg_answer,msg->msg_ext,msg->msg_alen)); + if (msg->msg_len > MSGLEN+1) + msg->msg_len = MSGLEN+1; if (msg->msg_len) if (!(msg->msg_answer && msg->msg_ext)) { msg->msg_text[msg->msg_len] = '\0'; @@ -3600,11 +3867,10 @@ cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.su.msg.msg_handle= msg->msg_handle; - cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys; - ha->scratch_busy = TRUE; + cmdp->u.screen.su.msg.msg_addr = ha->msg_phys; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) - + sizeof(ulong32); + + sizeof(ulong64); ha->cmd_cnt = 0; gdth_copy_command(hanum); gdth_release_event(hanum); @@ -3635,11 +3901,10 @@ cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.su.msg.msg_handle= msg->msg_handle; - cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys; - ha->scratch_busy = TRUE; + cmdp->u.screen.su.msg.msg_addr = ha->msg_phys; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) - + sizeof(ulong32); + + sizeof(ulong64); ha->cmd_cnt = 0; gdth_copy_command(hanum); gdth_release_event(hanum); @@ -3648,7 +3913,7 @@ printk("\n"); } else { -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; #else @@ -3666,16 +3931,20 @@ /* retry */ return 2; } -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13) if (scp->SCp.Status == GDTH_MAP_SG) pci_unmap_sg(ha->pdev,scp->request_buffer, scp->use_sg,scp->SCp.Message); else if (scp->SCp.Status == GDTH_MAP_SINGLE) - pci_unmap_single(ha->pdev,scp->SCp.dma_handle, - scp->request_bufflen,scp->SCp.Message); - if (scp->SCp.buffer) - pci_unmap_single(ha->pdev,(dma_addr_t)scp->SCp.buffer, - 16,PCI_DMA_FROMDEVICE); + pci_unmap_page(ha->pdev,scp->SCp.dma_handle, + scp->request_bufflen,scp->SCp.Message); + if (scp->SCp.buffer) { + dma_addr_t addr; + addr = (dma_addr_t)(ulong32)scp->SCp.buffer; + if (scp->host_scribble) + addr += (dma_addr_t)((ulong64)(ulong32)scp->host_scribble << 32); + pci_unmap_page(ha->pdev,addr,16,PCI_DMA_FROMDEVICE); + } #endif if (ha->status == S_OK) { scp->SCp.Status = S_OK; @@ -3754,10 +4023,7 @@ scp->sense_buffer[2] = NOT_READY; scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); } -#if LINUX_VERSION_CODE >= 0x010300 - if (scp->done != gdth_scsi_done) -#endif - { + if (scp->done != gdth_scsi_done) { ha->dvr.size = sizeof(ha->dvr.eu.sync); ha->dvr.eu.sync.ionode = hanum; ha->dvr.eu.sync.service = service; @@ -3946,13 +4212,11 @@ static int gdth_async_event(int hanum) { gdth_ha_str *ha; - gdth_msg_str *msg; gdth_cmd_str *cmdp; int cmd_index; ha = HADATA(gdth_ctr_tab[hanum]); cmdp= ha->pccb; - msg = (gdth_msg_str *)ha->pscratch; TRACE2(("gdth_async_event() ha %d serv %d\n", hanum,ha->service)); @@ -3968,11 +4232,10 @@ cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.su.msg.msg_handle= MSG_INV_HANDLE; - cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys; - ha->scratch_busy = TRUE; + cmdp->u.screen.su.msg.msg_addr = ha->msg_phys; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) - + sizeof(ulong32); + + sizeof(ulong64); ha->cmd_cnt = 0; gdth_copy_command(hanum); if (ha->type == GDT_EISA) @@ -4192,10 +4455,11 @@ GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp)) { struct Scsi_Host *shp; + gdth_pci_str pcistr[MAXHA]; gdth_ha_str *ha; ulong32 isa_bios; ushort eisa_slot; - int i,hanum,cnt,ctr; + int i,hanum,cnt,ctr,err; unchar b; @@ -4218,11 +4482,11 @@ TRACE(("gdth_detect()\n")); if (disable) { - printk("GDT: Controller driver disabled from command line !\n"); + printk("GDT-HA: Controller driver disabled from command line !\n"); return 0; } - printk("GDT: Storage RAID Controller Driver. Version: %s \n",GDTH_VERSION_STR); + printk("GDT-HA: Storage RAID Controller Driver. Version: %s \n",GDTH_VERSION_STR); /* initializations */ gdth_polling = TRUE; b = 0; gdth_clear_events(); @@ -4232,6 +4496,7 @@ /* scanning for controllers, at first: ISA controller */ for (isa_bios=0xc8000UL; isa_bios<=0xd8000UL; isa_bios+=0x8000UL) { dma_addr_t scratch_dma_handle; + scratch_dma_handle = 0; if (gdth_ctr_count >= MAXHA) break; @@ -4252,23 +4517,14 @@ printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n", isa_bios,ha->irq,ha->drq); -#if LINUX_VERSION_CODE >= 0x010346 - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) -#else - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) -#endif - { + if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) { printk("GDT-ISA: Unable to allocate IRQ\n"); scsi_unregister(shp); continue; } if (request_dma(ha->drq,"gdth")) { printk("GDT-ISA: Unable to allocate DMA channel\n"); -#if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,ha); -#else - free_irq(ha->irq); -#endif scsi_unregister(shp); continue; } @@ -4286,15 +4542,34 @@ ha->pccb = CMDDATA(shp); ha->ccb_phys = 0L; -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ha->pdev = NULL; ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, &scratch_dma_handle); - ha->scratch_phys = (ulong32)scratch_dma_handle; + ha->scratch_phys = scratch_dma_handle; + ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), + &scratch_dma_handle); + ha->msg_phys = scratch_dma_handle; +#ifdef INT_COAL + ha->coal_stat = (gdth_coal_status *) + pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, &scratch_dma_handle); + ha->coal_stat_phys = scratch_dma_handle; +#endif #else ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); if (ha->pscratch) ha->scratch_phys = virt_to_bus(ha->pscratch); + ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA); + if (ha->pmsg) + ha->msg_phys = virt_to_bus(ha->pmsg); +#ifdef INT_COAL + ha->coal_stat = + scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS, + GFP_ATOMIC | GFP_DMA); + if (ha->coal_stat) + ha->coal_stat_phys = virt_to_bus(ha->coal_stat); +#endif #endif ha->scratch_busy = FALSE; ha->req_first = NULL; @@ -4305,23 +4580,36 @@ ha->cmd_tab[i].cmnd = UNUSED_CMND; ha->scan_mode = rescan ? 0x10 : 0; - if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { + if (ha->pscratch == NULL || ha->pmsg == NULL || + !gdth_search_drives(hanum)) { printk("GDT-ISA: Error during device scan\n"); --gdth_ctr_count; --gdth_ctr_vcount; - if (ha->pscratch != NULL) { -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#ifdef INT_COAL + if (ha->coal_stat) + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, ha->coal_stat, + ha->coal_stat_phys); +#endif + if (ha->pscratch) pci_free_consistent(ha->pdev, GDTH_SCRATCH, ha->pscratch, ha->scratch_phys); -#else + if (ha->pmsg) + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); +#else +#ifdef INT_COAL + if (ha->coal_stat) + scsi_init_free((void *)ha->coal_stat, + sizeof(gdth_coal_status) * MAXOFFSETS); +#endif + if (ha->pscratch) scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); + if (ha->pmsg) + scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str)); #endif - } -#if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,ha); -#else - free_irq(ha->irq); -#endif scsi_unregister(shp); continue; } @@ -4329,13 +4617,18 @@ hdr_channel = ha->bus_cnt; ha->virt_bus = hdr_channel; -#if LINUX_VERSION_CODE >= 0x020000 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + shp->highmem_io = 0; +#endif + if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) + shp->max_cmd_len = 16; +#endif shp->max_id = ha->tid_cnt; shp->max_lun = MAXLUN; shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; - if (virt_ctr) -#endif - { + if (virt_ctr) { virt_ctr = 1; /* register addit. SCSI channels as virtual controllers */ for (b = 1; b < ha->bus_cnt + 1; ++b) { @@ -4358,6 +4651,7 @@ /* scanning for EISA controllers */ for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) { dma_addr_t scratch_dma_handle; + scratch_dma_handle = 0; if (gdth_ctr_count >= MAXHA) break; @@ -4373,14 +4667,9 @@ } /* controller found and initialized */ printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n", - eisa_slot>>12,ha->irq); + eisa_slot>>12,ha->irq); -#if LINUX_VERSION_CODE >= 0x010346 - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) -#else - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) -#endif - { + if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) { printk("GDT-EISA: Unable to allocate IRQ\n"); scsi_unregister(shp); continue; @@ -4399,11 +4688,20 @@ ha->pccb = CMDDATA(shp); ha->ccb_phys = 0L; -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ha->pdev = NULL; ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, &scratch_dma_handle); - ha->scratch_phys = (ulong32) scratch_dma_handle; + ha->scratch_phys = scratch_dma_handle; + ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), + &scratch_dma_handle); + ha->msg_phys = scratch_dma_handle; +#ifdef INT_COAL + ha->coal_stat = (gdth_coal_status *) + pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, &scratch_dma_handle); + ha->coal_stat_phys = scratch_dma_handle; +#endif ha->ccb_phys = pci_map_single(ha->pdev,ha->pccb, sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); @@ -4411,6 +4709,16 @@ ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); if (ha->pscratch) ha->scratch_phys = virt_to_bus(ha->pscratch); + ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA); + if (ha->pmsg) + ha->msg_phys = virt_to_bus(ha->pmsg); +#ifdef INT_COAL + ha->coal_stat = + scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS, + GFP_ATOMIC | GFP_DMA); + if (ha->coal_stat) + ha->coal_stat_phys = virt_to_bus(ha->coal_stat); +#endif ha->ccb_phys = virt_to_bus(ha->pccb); #endif ha->scratch_busy = FALSE; @@ -4419,28 +4727,42 @@ if (max_ids > 0 && max_ids < ha->tid_cnt) ha->tid_cnt = max_ids; for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; + ha->cmd_tab[i].cmnd = UNUSED_CMND; ha->scan_mode = rescan ? 0x10 : 0; - if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { + if (ha->pscratch == NULL || ha->pmsg == NULL || + !gdth_search_drives(hanum)) { printk("GDT-EISA: Error during device scan\n"); --gdth_ctr_count; --gdth_ctr_vcount; - if (ha->pscratch != NULL) { -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#ifdef INT_COAL + if (ha->coal_stat) + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, ha->coal_stat, + ha->coal_stat_phys); +#endif + if (ha->pscratch) pci_free_consistent(ha->pdev, GDTH_SCRATCH, ha->pscratch, ha->scratch_phys); + if (ha->pmsg) + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); + if (ha->ccb_phys) pci_unmap_single(ha->pdev,ha->ccb_phys, - sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); + sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); #else +#ifdef INT_COAL + if (ha->coal_stat) + scsi_init_free((void *)ha->coal_stat, + sizeof(gdth_coal_status) * MAXOFFSETS); +#endif + if (ha->pscratch) scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); + if (ha->pmsg) + scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str)); #endif - } -#if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,ha); -#else - free_irq(ha->irq); -#endif scsi_unregister(shp); continue; } @@ -4448,13 +4770,18 @@ hdr_channel = ha->bus_cnt; ha->virt_bus = hdr_channel; -#if LINUX_VERSION_CODE >= 0x020000 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + shp->highmem_io = 0; +#endif + if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) + shp->max_cmd_len = 16; +#endif shp->max_id = ha->tid_cnt; shp->max_lun = MAXLUN; shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; - if (virt_ctr) -#endif - { + if (virt_ctr) { virt_ctr = 1; /* register addit. SCSI channels as virtual controllers */ for (b = 1; b < ha->bus_cnt + 1; ++b) { @@ -4475,124 +4802,173 @@ } /* scanning for PCI controllers */ -#if LINUX_VERSION_CODE < 0x2015C - if (pcibios_present()) -#endif - { - gdth_pci_str pcistr[MAXHA]; + cnt = gdth_search_pci(pcistr); + printk("GDT-HA: Found %d PCI Storage RAID Controllers\n",cnt); + gdth_sort_pci(pcistr,cnt); + for (ctr = 0; ctr < cnt; ++ctr) { + dma_addr_t scratch_dma_handle; + scratch_dma_handle = 0; - cnt = gdth_search_pci(pcistr); - printk("GDT: Found %d PCI Storage RAID Controllers\n",cnt); - gdth_sort_pci(pcistr,cnt); - for (ctr = 0; ctr < cnt; ++ctr) { - dma_addr_t scratch_dma_handle; + if (gdth_ctr_count >= MAXHA) + break; + shp = scsi_register(shtp,sizeof(gdth_ext_str)); + if (shp == NULL) + continue; + + ha = HADATA(shp); + if (!gdth_init_pci(&pcistr[ctr],ha)) { + scsi_unregister(shp); + continue; + } + /* controller found and initialized */ + printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n", + pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq); - if (gdth_ctr_count >= MAXHA) - break; - shp = scsi_register(shtp,sizeof(gdth_ext_str)); - if (shp == NULL) - continue; - - ha = HADATA(shp); - if (!gdth_init_pci(&pcistr[ctr],ha)) { - scsi_unregister(shp); - continue; - } - /* controller found and initialized */ - printk("GDT CTR%d: Configuring GDT-PCI HA at %d/%d IRQ %u\n", - ctr,pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq); - -#if LINUX_VERSION_CODE >= 0x010346 - if (request_irq(ha->irq, gdth_interrupt, - SA_INTERRUPT|SA_SHIRQ, "gdth", ha)) -#else - if (request_irq(ha->irq, gdth_interrupt, - SA_INTERRUPT|SA_SHIRQ, "gdth")) -#endif - { - printk("GDT-PCI: Unable to allocate IRQ\n"); - scsi_unregister(shp); - continue; - } - shp->unchecked_isa_dma = 0; - shp->irq = ha->irq; - shp->dma_channel = 0xff; - hanum = gdth_ctr_count; - gdth_ctr_tab[gdth_ctr_count++] = shp; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum= 0; - - ha->pccb = CMDDATA(shp); - ha->ccb_phys = 0L; -#if LINUX_VERSION_CODE >= 0x020400 - ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, - &scratch_dma_handle); - ha->scratch_phys = (ulong32)scratch_dma_handle; -#else - ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); - if (ha->pscratch) - ha->scratch_phys = virt_to_bus(ha->pscratch); -#endif - ha->scratch_busy = FALSE; - ha->req_first = NULL; - ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES; - if (max_ids > 0 && max_ids < ha->tid_cnt) - ha->tid_cnt = max_ids; - for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; - ha->scan_mode = rescan ? 0x10 : 0; - - if (ha->pscratch == NULL || !gdth_search_drives(hanum)) { - printk("GDT-PCI: Error during device scan\n"); - --gdth_ctr_count; - --gdth_ctr_vcount; - if (ha->pscratch != NULL) { -#if LINUX_VERSION_CODE >= 0x020400 - pci_free_consistent(ha->pdev, GDTH_SCRATCH, - ha->pscratch, ha->scratch_phys); -#else - scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); + if (request_irq(ha->irq, gdth_interrupt, + SA_INTERRUPT|SA_SHIRQ, "gdth", ha)) + { + printk("GDT-PCI: Unable to allocate IRQ\n"); + scsi_unregister(shp); + continue; + } + shp->unchecked_isa_dma = 0; + shp->irq = ha->irq; + shp->dma_channel = 0xff; + hanum = gdth_ctr_count; + gdth_ctr_tab[gdth_ctr_count++] = shp; + gdth_ctr_vtab[gdth_ctr_vcount++] = shp; + + NUMDATA(shp)->hanum = (ushort)hanum; + NUMDATA(shp)->busnum= 0; + + ha->pccb = CMDDATA(shp); + ha->ccb_phys = 0L; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, + &scratch_dma_handle); + ha->scratch_phys = scratch_dma_handle; + ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), + &scratch_dma_handle); + ha->msg_phys = scratch_dma_handle; +#ifdef INT_COAL + ha->coal_stat = (gdth_coal_status *) + pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, &scratch_dma_handle); + ha->coal_stat_phys = scratch_dma_handle; +#endif +#else + ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); + if (ha->pscratch) + ha->scratch_phys = virt_to_bus(ha->pscratch); + ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA); + if (ha->pmsg) + ha->msg_phys = virt_to_bus(ha->pmsg); +#ifdef INT_COAL + ha->coal_stat = + scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS, + GFP_ATOMIC | GFP_DMA); + if (ha->coal_stat) + ha->coal_stat_phys = virt_to_bus(ha->coal_stat); #endif - } -#if LINUX_VERSION_CODE >= 0x010346 - free_irq(ha->irq,ha); -#else - free_irq(ha->irq); #endif - scsi_unregister(shp); - continue; - } + ha->scratch_busy = FALSE; + ha->req_first = NULL; + ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES; + if (max_ids > 0 && max_ids < ha->tid_cnt) + ha->tid_cnt = max_ids; + for (i=0; icmd_tab[i].cmnd = UNUSED_CMND; + ha->scan_mode = rescan ? 0x10 : 0; + + err = FALSE; + if (ha->pscratch == NULL || ha->pmsg == NULL || + !gdth_search_drives(hanum)) { + err = TRUE; + } else { if (hdr_channel < 0 || hdr_channel > ha->bus_cnt) hdr_channel = ha->bus_cnt; ha->virt_bus = hdr_channel; -#if LINUX_VERSION_CODE >= 0x020000 - shp->max_id = ha->tid_cnt; - shp->max_lun = MAXLUN; - shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; - if (virt_ctr) -#endif - { - virt_ctr = 1; - /* register addit. SCSI channels as virtual controllers */ - for (b = 1; b < ha->bus_cnt + 1; ++b) { - shp = scsi_register(shtp,sizeof(gdth_num_str)); - shp->unchecked_isa_dma = 0; - shp->irq = ha->irq; - shp->dma_channel = 0xff; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum = b; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + scsi_set_device(shp, &pcistr[ctr].pdev->dev); +#else + scsi_set_pci_device(shp, pcistr[ctr].pdev); +#endif + if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat &GDT_64BIT)|| + /* 64-bit DMA only supported from FW >= x.43 */ + (!ha->dma64_support)) { + if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) { + printk(KERN_WARNING "GDT-PCI %d: Unable to set 32-bit DMA\n", hanum); + err = TRUE; + } + } else { + shp->max_cmd_len = 16; + if (!pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffffffffffffULL)) { + printk("GDT-PCI %d: 64-bit DMA enabled\n", hanum); + } else if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) { + printk(KERN_WARNING "GDT-PCI %d: Unable to set 64/32-bit DMA\n", hanum); + err = TRUE; } - } + } +#endif + } - GDTH_INIT_LOCK_HA(ha); - gdth_enable_int(hanum); + if (err) { + printk("GDT-PCI %d: Error during device scan\n", hanum); + --gdth_ctr_count; + --gdth_ctr_vcount; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#ifdef INT_COAL + if (ha->coal_stat) + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, ha->coal_stat, + ha->coal_stat_phys); +#endif + if (ha->pscratch) + pci_free_consistent(ha->pdev, GDTH_SCRATCH, + ha->pscratch, ha->scratch_phys); + if (ha->pmsg) + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); +#else +#ifdef INT_COAL + if (ha->coal_stat) + scsi_init_free((void *)ha->coal_stat, + sizeof(gdth_coal_status) * MAXOFFSETS); +#endif + if (ha->pscratch) + scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); + if (ha->pmsg) + scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str)); +#endif + free_irq(ha->irq,ha); + scsi_unregister(shp); + continue; } - } + shp->max_id = ha->tid_cnt; + shp->max_lun = MAXLUN; + shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; + if (virt_ctr) { + virt_ctr = 1; + /* register addit. SCSI channels as virtual controllers */ + for (b = 1; b < ha->bus_cnt + 1; ++b) { + shp = scsi_register(shtp,sizeof(gdth_num_str)); + shp->unchecked_isa_dma = 0; + shp->irq = ha->irq; + shp->dma_channel = 0xff; + gdth_ctr_vtab[gdth_ctr_vcount++] = shp; + NUMDATA(shp)->hanum = (ushort)hanum; + NUMDATA(shp)->busnum = b; + } + } + + + GDTH_INIT_LOCK_HA(ha); + gdth_enable_int(hanum); + } + TRACE2(("gdth_detect() %d controller detected\n",gdth_ctr_count)); if (gdth_ctr_count > 0) { #ifdef GDTH_STATISTICS @@ -4603,12 +4979,8 @@ gdth_timer.function = gdth_timeout; add_timer(&gdth_timer); #endif -#ifdef GDTH_IOCTL_CHRDEV major = register_chrdev(0,"gdth",&gdth_fops); -#endif -#if LINUX_VERSION_CODE >= 0x020100 register_reboot_notifier(&gdth_notifier); -#endif } gdth_polling = FALSE; return gdth_ctr_vcount; @@ -4624,30 +4996,47 @@ if (NUMDATA(shp)->busnum == 0) { hanum = NUMDATA(shp)->hanum; ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x010300 - gdth_flush(hanum); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + if (ha->sdev) { + scsi_free_host_dev(ha->sdev); + ha->sdev = NULL; + } #endif + gdth_flush(hanum); if (shp->irq) { -#if LINUX_VERSION_CODE >= 0x010346 free_irq(shp->irq,ha); -#else - free_irq(shp->irq); -#endif } #ifndef __ia64__ if (shp->dma_channel != 0xff) { free_dma(shp->dma_channel); } #endif -#if LINUX_VERSION_CODE >= 0x020400 - pci_free_consistent(ha->pdev, GDTH_SCRATCH, - ha->pscratch, ha->scratch_phys); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) +#ifdef INT_COAL + if (ha->coal_stat) + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, ha->coal_stat, ha->coal_stat_phys); +#endif + if (ha->pscratch) + pci_free_consistent(ha->pdev, GDTH_SCRATCH, + ha->pscratch, ha->scratch_phys); + if (ha->pmsg) + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); if (ha->ccb_phys) pci_unmap_single(ha->pdev,ha->ccb_phys, sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); #else - scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); +#ifdef INT_COAL + if (ha->coal_stat) + scsi_init_free((void *)ha->coal_stat, + sizeof(gdth_coal_status) * MAXOFFSETS); +#endif + if (ha->pscratch) + scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); + if (ha->pmsg) + scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str)); #endif gdth_ctr_released++; TRACE2(("gdth_release(): HA %d of %d\n", @@ -4657,12 +5046,8 @@ #ifdef GDTH_STATISTICS del_timer(&gdth_timer); #endif -#ifdef GDTH_IOCTL_CHRDEV unregister_chrdev(major,"gdth"); -#endif -#if LINUX_VERSION_CODE >= 0x020100 unregister_reboot_notifier(&gdth_notifier); -#endif } } @@ -4715,6 +5100,7 @@ return ((const char *)ha->binfo.type_string); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) /* old error handling */ int gdth_abort(Scsi_Cmnd *scp) { @@ -4722,17 +5108,13 @@ return SCSI_ABORT_SNOOZE; } -#if LINUX_VERSION_CODE >= 0x010346 int gdth_reset(Scsi_Cmnd *scp, unsigned int reset_flags) -#else -int gdth_reset(Scsi_Cmnd *scp) -#endif { TRACE2(("gdth_reset()\n")); return SCSI_RESET_PUNT; } +#endif -#if LINUX_VERSION_CODE >= 0x02015F /* new error handling */ int gdth_eh_abort(Scsi_Cmnd *scp) { @@ -4755,7 +5137,7 @@ unchar b; TRACE2(("gdth_eh_bus_reset()\n")); -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) hanum = NUMDATA(scp->device->host)->hanum; b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; #else @@ -4768,7 +5150,7 @@ GDTH_LOCK_HA(ha, flags); for (i = 0; i < GDTH_MAXCMDS; ++i) { cmnd = ha->cmd_tab[i].cmnd; -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) if (!SPECIAL_SCP(cmnd) && cmnd->device->channel == b) #else if (!SPECIAL_SCP(cmnd) && cmnd->channel == b) @@ -4813,15 +5195,12 @@ TRACE2(("gdth_eh_host_reset()\n")); return FAILED; } -#endif -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) int gdth_bios_param(struct scsi_device *sdev,struct block_device *bdev,sector_t cap,int *ip) -#elif LINUX_VERSION_CODE >= 0x010300 -int gdth_bios_param(Disk *disk,kdev_t dev,int *ip) #else -int gdth_bios_param(Disk *disk,int dev,int *ip) +int gdth_bios_param(Disk *disk,kdev_t dev,int *ip) #endif { unchar b, t; @@ -4830,7 +5209,7 @@ struct scsi_device *sd; unsigned capacity; -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) sd = sdev; capacity = cap; #else @@ -4872,7 +5251,7 @@ scp->SCp.sent_command = -1; scp->SCp.Status = GDTH_MAP_NONE; scp->SCp.buffer = (struct scatterlist *)NULL; -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) hanum = NUMDATA(scp->device->host)->hanum; #else hanum = NUMDATA(scp->host)->hanum; @@ -4882,19 +5261,28 @@ #endif priority = DEFAULT_PRI; -#if LINUX_VERSION_CODE >= 0x010300 if (scp->done == gdth_scsi_done) priority = scp->SCp.this_residual; -#endif gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6); gdth_putq( hanum, scp, priority ); gdth_next( hanum ); return 0; } -#ifdef GDTH_IOCTL_CHRDEV + static int gdth_open(struct inode *inode, struct file *filep) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + gdth_ha_str *ha; + int i; + + for (i = 0; i < gdth_ctr_count; i++) { + ha = HADATA(gdth_ctr_tab[i]); + if (!ha->sdev) + ha->sdev = scsi_get_host_dev(gdth_ctr_tab[i]); + } +#endif + TRACE(("gdth_open()\n")); return 0; } @@ -4907,537 +5295,578 @@ static int ioc_event(unsigned long arg) { - gdth_ioctl_event evt; - gdth_ha_str *ha; - ulong flags; - - if (copy_from_user(&evt, (char *)arg, sizeof(gdth_ioctl_event)) || - evt.ionode >= gdth_ctr_count) - return -EFAULT; - ha = HADATA(gdth_ctr_tab[evt.ionode]); + gdth_ioctl_event evt; + gdth_ha_str *ha; + ulong flags; - if (evt.erase == 0xff) { - if (evt.event.event_source == ES_TEST) - evt.event.event_data.size=sizeof(evt.event.event_data.eu.test); - else if (evt.event.event_source == ES_DRIVER) - evt.event.event_data.size=sizeof(evt.event.event_data.eu.driver); - else if (evt.event.event_source == ES_SYNC) - evt.event.event_data.size=sizeof(evt.event.event_data.eu.sync); - else - evt.event.event_data.size=sizeof(evt.event.event_data.eu.async); - GDTH_LOCK_HA(ha, flags); - gdth_store_event(ha, evt.event.event_source, evt.event.event_idx, - &evt.event.event_data); - GDTH_UNLOCK_HA(ha, flags); - } else if (evt.erase == 0xfe) { - gdth_clear_events(); - } else if (evt.erase == 0) { - evt.handle = gdth_read_event(ha, evt.handle, &evt.event); - } else { - gdth_readapp_event(ha, evt.erase, &evt.event); - } - if (copy_to_user((char *)arg, &evt, sizeof(gdth_ioctl_event))) - return -EFAULT; - return 0; + if (copy_from_user(&evt, (char *)arg, sizeof(gdth_ioctl_event)) || + evt.ionode >= gdth_ctr_count) + return -EFAULT; + ha = HADATA(gdth_ctr_tab[evt.ionode]); + + if (evt.erase == 0xff) { + if (evt.event.event_source == ES_TEST) + evt.event.event_data.size=sizeof(evt.event.event_data.eu.test); + else if (evt.event.event_source == ES_DRIVER) + evt.event.event_data.size=sizeof(evt.event.event_data.eu.driver); + else if (evt.event.event_source == ES_SYNC) + evt.event.event_data.size=sizeof(evt.event.event_data.eu.sync); + else + evt.event.event_data.size=sizeof(evt.event.event_data.eu.async); + GDTH_LOCK_HA(ha, flags); + gdth_store_event(ha, evt.event.event_source, evt.event.event_idx, + &evt.event.event_data); + GDTH_UNLOCK_HA(ha, flags); + } else if (evt.erase == 0xfe) { + gdth_clear_events(); + } else if (evt.erase == 0) { + evt.handle = gdth_read_event(ha, evt.handle, &evt.event); + } else { + gdth_readapp_event(ha, evt.erase, &evt.event); + } + if (copy_to_user((char *)arg, &evt, sizeof(gdth_ioctl_event))) + return -EFAULT; + return 0; } static int ioc_lockdrv(unsigned long arg) { - gdth_ioctl_lockdrv ldrv; - unchar i, j; - ulong flags; - gdth_ha_str *ha; + gdth_ioctl_lockdrv ldrv; + unchar i, j; + ulong flags; + gdth_ha_str *ha; - if (copy_from_user(&ldrv, (char *)arg, sizeof(gdth_ioctl_lockdrv)) || - ldrv.ionode >= gdth_ctr_count) - return -EFAULT; - ha = HADATA(gdth_ctr_tab[ldrv.ionode]); + if (copy_from_user(&ldrv, (char *)arg, sizeof(gdth_ioctl_lockdrv)) || + ldrv.ionode >= gdth_ctr_count) + return -EFAULT; + ha = HADATA(gdth_ctr_tab[ldrv.ionode]); - for (i = 0; i < ldrv.drive_cnt && i < MAX_HDRIVES; ++i) { - j = ldrv.drives[i]; - if (j >= MAX_HDRIVES || !ha->hdr[j].present) - continue; - if (ldrv.lock) { - GDTH_LOCK_HA(ha, flags); - ha->hdr[j].lock = 1; - GDTH_UNLOCK_HA(ha, flags); - gdth_wait_completion(ldrv.ionode, ha->bus_cnt, j); - gdth_stop_timeout(ldrv.ionode, ha->bus_cnt, j); - } else { - GDTH_LOCK_HA(ha, flags); - ha->hdr[j].lock = 0; - GDTH_UNLOCK_HA(ha, flags); - gdth_start_timeout(ldrv.ionode, ha->bus_cnt, j); - gdth_next(ldrv.ionode); - } - } - return 0; + for (i = 0; i < ldrv.drive_cnt && i < MAX_HDRIVES; ++i) { + j = ldrv.drives[i]; + if (j >= MAX_HDRIVES || !ha->hdr[j].present) + continue; + if (ldrv.lock) { + GDTH_LOCK_HA(ha, flags); + ha->hdr[j].lock = 1; + GDTH_UNLOCK_HA(ha, flags); + gdth_wait_completion(ldrv.ionode, ha->bus_cnt, j); + gdth_stop_timeout(ldrv.ionode, ha->bus_cnt, j); + } else { + GDTH_LOCK_HA(ha, flags); + ha->hdr[j].lock = 0; + GDTH_UNLOCK_HA(ha, flags); + gdth_start_timeout(ldrv.ionode, ha->bus_cnt, j); + gdth_next(ldrv.ionode); + } + } + return 0; } static int ioc_resetdrv(unsigned long arg, char *cmnd) { - gdth_ioctl_reset res; - gdth_cmd_str cmd; - int hanum; - gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= 0x020503 - Scsi_Request *srp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 - Scsi_Cmnd *scp; - Scsi_Device *sdev; -#else - Scsi_Cmnd scp; - Scsi_Device sdev; + gdth_ioctl_reset res; + gdth_cmd_str cmd; + int hanum; + gdth_ha_str *ha; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + Scsi_Request *srp; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + Scsi_Cmnd *scp; +#else + Scsi_Cmnd scp; #endif - if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) || - res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES) - return -EFAULT; - hanum = res.ionode; - ha = HADATA(gdth_ctr_tab[hanum]); + if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) || + res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES) + return -EFAULT; + hanum = res.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); - if (!ha->hdr[res.number].present) - return 0; - cmd.Service = CACHESERVICE; - cmd.OpCode = GDT_CLUST_RESET; + if (!ha->hdr[res.number].present) + return 0; + memset(&cmd, 0, sizeof(gdth_cmd_str)); + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_CLUST_RESET; + if (ha->cache_feat & GDT_64BIT) + cmd.u.cache64.DeviceNo = res.number; + else cmd.u.cache.DeviceNo = res.number; -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; - gdth_do_req(srp, &cmd, cmnd, 30); - res.status = (ushort)srp->sr_command->SCp.Status; - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; - gdth_do_cmd(scp, &cmd, cmnd, 30); - res.status = (ushort)scp->SCp.Status; - scsi_release_command(scp); - scsi_free_host_dev(sdev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); + if (!srp) + return -ENOMEM; + srp->sr_cmd_len = 12; + srp->sr_use_sg = 0; + gdth_do_req(srp, &cmd, cmnd, 30); + res.status = (ushort)srp->sr_command->SCp.Status; + scsi_release_request(srp); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + scp = scsi_allocate_device(ha->sdev, 1, FALSE); + if (!scp) + return -ENOMEM; + scp->cmd_len = 12; + scp->use_sg = 0; + gdth_do_cmd(scp, &cmd, cmnd, 30); + res.status = (ushort)scp->SCp.Status; + scsi_release_command(scp); #else - memset(&sdev,0,sizeof(Scsi_Device)); - memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; - sdev.id = scp.target = sdev.host->this_id; - scp.device = &sdev; - gdth_do_cmd(&scp, &cmd, cmnd, 30); - res.status = (ushort)scp.SCp.Status; + memset(&ha->sdev,0,sizeof(Scsi_Device)); + memset(&scp, 0,sizeof(Scsi_Cmnd)); + ha->sdev.host = scp.host = gdth_ctr_tab[hanum]; + ha->sdev.id = scp.target = ha->sdev.host->this_id; + scp.device = &ha->sdev; + gdth_do_cmd(&scp, &cmd, cmnd, 30); + res.status = (ushort)scp.SCp.Status; #endif - if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset))) - return -EFAULT; - return 0; + if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset))) + return -EFAULT; + return 0; } static int ioc_general(unsigned long arg, char *cmnd) { - gdth_ioctl_general gen; - char *buf = NULL; - ulong32 paddr; - int hanum; - gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= 0x020503 - Scsi_Request *srp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 - Scsi_Cmnd *scp; - Scsi_Device *sdev; + gdth_ioctl_general gen; + char *buf = NULL; + ulong64 paddr; + int hanum; + gdth_ha_str *ha; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + Scsi_Request *srp; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + Scsi_Cmnd *scp; #else - Scsi_Cmnd scp; - Scsi_Device sdev; + Scsi_Cmnd scp; #endif - if (copy_from_user(&gen, (char *)arg, sizeof(gdth_ioctl_general)) || - gen.ionode >= gdth_ctr_count) + if (copy_from_user(&gen, (char *)arg, sizeof(gdth_ioctl_general)) || + gen.ionode >= gdth_ctr_count) + return -EFAULT; + hanum = gen.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); + if (gen.data_len + gen.sense_len != 0) { + if (!(buf = gdth_ioctl_alloc(hanum, gen.data_len + gen.sense_len, + FALSE, &paddr))) return -EFAULT; - hanum = gen.ionode; - ha = HADATA(gdth_ctr_tab[hanum]); - if (gen.data_len + gen.sense_len != 0) { - if (!(buf = gdth_ioctl_alloc(hanum, gen.data_len + gen.sense_len, - FALSE, &paddr))) - return -EFAULT; - if (copy_from_user(buf, (char *)arg + sizeof(gdth_ioctl_general), - gen.data_len + gen.sense_len)) { - gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); - return -EFAULT; - } + if (copy_from_user(buf, (char *)arg + sizeof(gdth_ioctl_general), + gen.data_len + gen.sense_len)) { + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + return -EFAULT; + } - if (gen.command.OpCode == GDT_IOCTL) { - gen.command.u.ioctl.p_param = paddr; - } else if (gen.command.Service == CACHESERVICE) { + if (gen.command.OpCode == GDT_IOCTL) { + gen.command.u.ioctl.p_param = paddr; + } else if (gen.command.Service == CACHESERVICE) { + if (ha->cache_feat & GDT_64BIT) { + /* copy elements from 32-bit IOCTL structure */ + gen.command.u.cache64.BlockCnt = gen.command.u.cache.BlockCnt; + gen.command.u.cache64.BlockNo = gen.command.u.cache.BlockNo; + gen.command.u.cache64.DeviceNo = gen.command.u.cache.DeviceNo; + /* addresses */ + if (ha->cache_feat & SCATTER_GATHER) { + gen.command.u.cache64.DestAddr = (ulong64)-1; + gen.command.u.cache64.sg_canz = 1; + gen.command.u.cache64.sg_lst[0].sg_ptr = paddr; + gen.command.u.cache64.sg_lst[0].sg_len = gen.data_len; + gen.command.u.cache64.sg_lst[1].sg_len = 0; + } else { + gen.command.u.cache64.DestAddr = paddr; + gen.command.u.cache64.sg_canz = 0; + } + } else { if (ha->cache_feat & SCATTER_GATHER) { gen.command.u.cache.DestAddr = 0xffffffff; gen.command.u.cache.sg_canz = 1; - gen.command.u.cache.sg_lst[0].sg_ptr = paddr; + gen.command.u.cache.sg_lst[0].sg_ptr = (ulong32)paddr; gen.command.u.cache.sg_lst[0].sg_len = gen.data_len; gen.command.u.cache.sg_lst[1].sg_len = 0; } else { gen.command.u.cache.DestAddr = paddr; gen.command.u.cache.sg_canz = 0; } - } else if (gen.command.Service == SCSIRAWSERVICE) { + } + } else if (gen.command.Service == SCSIRAWSERVICE) { + if (ha->raw_feat & GDT_64BIT) { + /* copy elements from 32-bit IOCTL structure */ + char cmd[16]; + gen.command.u.raw64.sense_len = gen.command.u.raw.sense_len; + gen.command.u.raw64.bus = gen.command.u.raw.bus; + gen.command.u.raw64.lun = gen.command.u.raw.lun; + gen.command.u.raw64.target = gen.command.u.raw.target; + memcpy(cmd, gen.command.u.raw.cmd, 16); + memcpy(gen.command.u.raw64.cmd, cmd, 16); + gen.command.u.raw64.clen = gen.command.u.raw.clen; + gen.command.u.raw64.sdlen = gen.command.u.raw.sdlen; + gen.command.u.raw64.direction = gen.command.u.raw.direction; + /* addresses */ + if (ha->raw_feat & SCATTER_GATHER) { + gen.command.u.raw64.sdata = (ulong64)-1; + gen.command.u.raw64.sg_ranz = 1; + gen.command.u.raw64.sg_lst[0].sg_ptr = paddr; + gen.command.u.raw64.sg_lst[0].sg_len = gen.data_len; + gen.command.u.raw64.sg_lst[1].sg_len = 0; + } else { + gen.command.u.raw64.sdata = paddr; + gen.command.u.raw64.sg_ranz = 0; + } + gen.command.u.raw64.sense_data = paddr + gen.data_len; + } else { if (ha->raw_feat & SCATTER_GATHER) { gen.command.u.raw.sdata = 0xffffffff; gen.command.u.raw.sg_ranz = 1; - gen.command.u.raw.sg_lst[0].sg_ptr = paddr; + gen.command.u.raw.sg_lst[0].sg_ptr = (ulong32)paddr; gen.command.u.raw.sg_lst[0].sg_len = gen.data_len; gen.command.u.raw.sg_lst[1].sg_len = 0; } else { gen.command.u.raw.sdata = paddr; gen.command.u.raw.sg_ranz = 0; } - gen.command.u.raw.sense_data = paddr + gen.data_len; - - } else { - gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); - return -EFAULT; + gen.command.u.raw.sense_data = (ulong32)paddr + gen.data_len; } + } else { + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + return -EFAULT; } + } -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; - gdth_do_req(srp, &gen.command, cmnd, gen.timeout); - gen.status = srp->sr_command->SCp.Status; - gen.info = srp->sr_command->SCp.Message; - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; - gdth_do_cmd(scp, &gen.command, cmnd, gen.timeout); - gen.status = scp->SCp.Status; - gen.info = scp->SCp.Message; - scsi_release_command(scp); - scsi_free_host_dev(sdev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); + if (!srp) + return -ENOMEM; + srp->sr_cmd_len = 12; + srp->sr_use_sg = 0; + gdth_do_req(srp, &gen.command, cmnd, gen.timeout); + gen.status = srp->sr_command->SCp.Status; + gen.info = srp->sr_command->SCp.Message; + scsi_release_request(srp); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + scp = scsi_allocate_device(ha->sdev, 1, FALSE); + if (!scp) + return -ENOMEM; + scp->cmd_len = 12; + scp->use_sg = 0; + gdth_do_cmd(scp, &gen.command, cmnd, gen.timeout); + gen.status = scp->SCp.Status; + gen.info = scp->SCp.Message; + scsi_release_command(scp); #else - memset(&sdev,0,sizeof(Scsi_Device)); - memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; - sdev.id = scp.target = sdev.host->this_id; - scp.device = &sdev; - gdth_do_cmd(&scp, &gen.command, cmnd, gen.timeout); - gen.status = scp.SCp.Status; - gen.info = scp.SCp.Message; + memset(&ha->sdev,0,sizeof(Scsi_Device)); + memset(&scp, 0,sizeof(Scsi_Cmnd)); + ha->sdev.host = scp.host = gdth_ctr_tab[hanum]; + ha->sdev.id = scp.target = ha->sdev.host->this_id; + scp.device = &ha->sdev; + gdth_do_cmd(&scp, &gen.command, cmnd, gen.timeout); + gen.status = scp.SCp.Status; + gen.info = scp.SCp.Message; #endif - if (copy_to_user((char *)arg + sizeof(gdth_ioctl_general), buf, - gen.data_len + gen.sense_len)) { - gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); - return -EFAULT; - } - if (copy_to_user((char *)arg, &gen, - sizeof(gdth_ioctl_general) - sizeof(gdth_cmd_str))) { - gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); - return -EFAULT; - } + if (copy_to_user((char *)arg + sizeof(gdth_ioctl_general), buf, + gen.data_len + gen.sense_len)) { gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); - return 0; + return -EFAULT; + } + if (copy_to_user((char *)arg, &gen, + sizeof(gdth_ioctl_general) - sizeof(gdth_cmd_str))) { + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + return -EFAULT; + } + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + return 0; } static int ioc_hdrlist(unsigned long arg, char *cmnd) { - gdth_ioctl_rescan rsc; - gdth_cmd_str cmd; - gdth_ha_str *ha; - unchar i; - int hanum; -#if LINUX_VERSION_CODE >= 0x020503 - Scsi_Request *srp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 - Scsi_Cmnd *scp; - Scsi_Device *sdev; + gdth_ioctl_rescan rsc; + gdth_cmd_str cmd; + gdth_ha_str *ha; + unchar i; + int hanum; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + Scsi_Request *srp; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + Scsi_Cmnd *scp; #else - Scsi_Cmnd scp; - Scsi_Device sdev; + Scsi_Cmnd scp; #endif - if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) || - rsc.ionode >= gdth_ctr_count) - return -EFAULT; - hanum = rsc.ionode; - ha = HADATA(gdth_ctr_tab[hanum]); + if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) || + rsc.ionode >= gdth_ctr_count) + return -EFAULT; + hanum = rsc.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); + memset(&cmd, 0, sizeof(gdth_cmd_str)); -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); + if (!srp) + return -ENOMEM; + srp->sr_cmd_len = 12; + srp->sr_use_sg = 0; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + scp = scsi_allocate_device(ha->sdev, 1, FALSE); + if (!scp) + return -ENOMEM; + scp->cmd_len = 12; + scp->use_sg = 0; #else - memset(&sdev,0,sizeof(Scsi_Device)); - memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; - sdev.id = scp.target = sdev.host->this_id; - scp.device = &sdev; + memset(&ha->sdev,0,sizeof(Scsi_Device)); + memset(&scp, 0,sizeof(Scsi_Cmnd)); + ha->sdev.host = scp.host = gdth_ctr_tab[hanum]; + ha->sdev.id = scp.target = ha->sdev.host->this_id; + scp.device = &ha->sdev; #endif - for (i = 0; i < MAX_HDRIVES; ++i) { - if (!ha->hdr[i].present) { - rsc.hdr_list[i].bus = 0xff; - continue; - } - rsc.hdr_list[i].bus = ha->virt_bus; - rsc.hdr_list[i].target = i; - rsc.hdr_list[i].lun = 0; - rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type; - if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) { - cmd.Service = CACHESERVICE; - cmd.OpCode = GDT_CLUST_INFO; + for (i = 0; i < MAX_HDRIVES; ++i) { + if (!ha->hdr[i].present) { + rsc.hdr_list[i].bus = 0xff; + continue; + } + rsc.hdr_list[i].bus = ha->virt_bus; + rsc.hdr_list[i].target = i; + rsc.hdr_list[i].lun = 0; + rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type; + if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) { + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_CLUST_INFO; + if (ha->cache_feat & GDT_64BIT) + cmd.u.cache64.DeviceNo = i; + else cmd.u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(srp, &cmd, cmnd, 30); - if (srp->sr_command->SCp.Status == S_OK) - rsc.hdr_list[i].cluster_type = srp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &cmd, cmnd, 30); - if (scp->SCp.Status == S_OK) - rsc.hdr_list[i].cluster_type = scp->SCp.Message; -#else - gdth_do_cmd(&scp, &cmd, cmnd, 30); - if (scp.SCp.Status == S_OK) - rsc.hdr_list[i].cluster_type = scp.SCp.Message; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + gdth_do_req(srp, &cmd, cmnd, 30); + if (srp->sr_command->SCp.Status == S_OK) + rsc.hdr_list[i].cluster_type = srp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + gdth_do_cmd(scp, &cmd, cmnd, 30); + if (scp->SCp.Status == S_OK) + rsc.hdr_list[i].cluster_type = scp->SCp.Message; +#else + gdth_do_cmd(&scp, &cmd, cmnd, 30); + if (scp.SCp.Status == S_OK) + rsc.hdr_list[i].cluster_type = scp.SCp.Message; #endif - } - } -#if LINUX_VERSION_CODE >= 0x020503 - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 - scsi_release_command(scp); - scsi_free_host_dev(sdev); + } + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + scsi_release_request(srp); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + scsi_release_command(scp); #endif - if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan))) - return -EFAULT; - return 0; + if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan))) + return -EFAULT; + return 0; } static int ioc_rescan(unsigned long arg, char *cmnd) { - gdth_ioctl_rescan rsc; - gdth_cmd_str cmd; - ushort i, status, hdr_cnt; - ulong32 info; - int hanum, cyls, hds, secs; - ulong flags; - gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= 0x020503 - Scsi_Request *srp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 - Scsi_Cmnd *scp; - Scsi_Device *sdev; + gdth_ioctl_rescan rsc; + gdth_cmd_str cmd; + ushort i, status, hdr_cnt; + ulong32 info; + int hanum, cyls, hds, secs; + ulong flags; + gdth_ha_str *ha; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + Scsi_Request *srp; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + Scsi_Cmnd *scp; #else - Scsi_Cmnd scp; - Scsi_Device sdev; + Scsi_Cmnd scp; #endif - if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) || - rsc.ionode >= gdth_ctr_count) - return -EFAULT; - hanum = rsc.ionode; - ha = HADATA(gdth_ctr_tab[hanum]); + if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) || + rsc.ionode >= gdth_ctr_count) + return -EFAULT; + hanum = rsc.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); + memset(&cmd, 0, sizeof(gdth_cmd_str)); -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - srp = scsi_allocate_request(sdev, GFP_KERNEL); - if (!srp) - return -ENOMEM; - srp->sr_cmd_len = 12; - srp->sr_use_sg = 0; -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + srp = scsi_allocate_request(ha->sdev, GFP_KERNEL); + if (!srp) + return -ENOMEM; + srp->sr_cmd_len = 12; + srp->sr_use_sg = 0; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + scp = scsi_allocate_device(ha->sdev, 1, FALSE); + if (!scp) + return -ENOMEM; + scp->cmd_len = 12; + scp->use_sg = 0; #else - memset(&sdev,0,sizeof(Scsi_Device)); - memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; - sdev.id = scp.target = sdev.host->this_id; - scp.device = &sdev; + memset(&ha->sdev,0,sizeof(Scsi_Device)); + memset(&scp, 0,sizeof(Scsi_Cmnd)); + ha->sdev.host = scp.host = gdth_ctr_tab[hanum]; + ha->sdev.id = scp.target = ha->sdev.host->this_id; + scp.device = &ha->sdev; #endif - if (rsc.flag == 0) { - /* old method: re-init. cache service */ - cmd.Service = CACHESERVICE; + if (rsc.flag == 0) { + /* old method: re-init. cache service */ + cmd.Service = CACHESERVICE; + if (ha->cache_feat & GDT_64BIT) { + cmd.OpCode = GDT_X_INIT_HOST; + cmd.u.cache64.DeviceNo = LINUX_OS; + } else { cmd.OpCode = GDT_INIT; cmd.u.cache.DeviceNo = LINUX_OS; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(srp, &cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + gdth_do_req(srp, &cmd, cmnd, 30); + status = (ushort)srp->sr_command->SCp.Status; + info = (ulong32)srp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + gdth_do_cmd(scp, &cmd, cmnd, 30); + status = (ushort)scp->SCp.Status; + info = (ulong32)scp->SCp.Message; #else - gdth_do_cmd(&scp, &cmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; + gdth_do_cmd(&scp, &cmd, cmnd, 30); + status = (ushort)scp.SCp.Status; + info = (ulong32)scp.SCp.Message; #endif - i = 0; - hdr_cnt = (status == S_OK ? (ushort)info : 0); - } else { - i = rsc.hdr_no; - hdr_cnt = i + 1; - } - for (; i < hdr_cnt && i < MAX_HDRIVES; ++i) { - cmd.Service = CACHESERVICE; - cmd.OpCode = GDT_INFO; + i = 0; + hdr_cnt = (status == S_OK ? (ushort)info : 0); + } else { + i = rsc.hdr_no; + hdr_cnt = i + 1; + } + for (; i < hdr_cnt && i < MAX_HDRIVES; ++i) { + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_INFO; + if (ha->cache_feat & GDT_64BIT) + cmd.u.cache64.DeviceNo = i; + else cmd.u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(srp, &cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + gdth_do_req(srp, &cmd, cmnd, 30); + status = (ushort)srp->sr_command->SCp.Status; + info = (ulong32)srp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + gdth_do_cmd(scp, &cmd, cmnd, 30); + status = (ushort)scp->SCp.Status; + info = (ulong32)scp->SCp.Message; #else - gdth_do_cmd(&scp, &cmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; + gdth_do_cmd(&scp, &cmd, cmnd, 30); + status = (ushort)scp.SCp.Status; + info = (ulong32)scp.SCp.Message; #endif - GDTH_LOCK_HA(ha, flags); - rsc.hdr_list[i].bus = ha->virt_bus; - rsc.hdr_list[i].target = i; - rsc.hdr_list[i].lun = 0; - if (status != S_OK) { - ha->hdr[i].present = FALSE; - } else { - ha->hdr[i].present = TRUE; - ha->hdr[i].size = info; - /* evaluate mapping */ - ha->hdr[i].size &= ~SECS32; - gdth_eval_mapping(ha->hdr[i].size,&cyls,&hds,&secs); - ha->hdr[i].heads = hds; - ha->hdr[i].secs = secs; - /* round size */ - ha->hdr[i].size = cyls * hds * secs; - } - GDTH_UNLOCK_HA(ha, flags); - if (status != S_OK) - continue; + GDTH_LOCK_HA(ha, flags); + rsc.hdr_list[i].bus = ha->virt_bus; + rsc.hdr_list[i].target = i; + rsc.hdr_list[i].lun = 0; + if (status != S_OK) { + ha->hdr[i].present = FALSE; + } else { + ha->hdr[i].present = TRUE; + ha->hdr[i].size = info; + /* evaluate mapping */ + ha->hdr[i].size &= ~SECS32; + gdth_eval_mapping(ha->hdr[i].size,&cyls,&hds,&secs); + ha->hdr[i].heads = hds; + ha->hdr[i].secs = secs; + /* round size */ + ha->hdr[i].size = cyls * hds * secs; + } + GDTH_UNLOCK_HA(ha, flags); + if (status != S_OK) + continue; + + /* extended info, if GDT_64BIT, for drives > 2 TB */ + /* but we need ha->info2, not yet stored in scp->SCp */ - /* devtype, cluster info, R/W attribs */ - cmd.Service = CACHESERVICE; - cmd.OpCode = GDT_DEVTYPE; + /* devtype, cluster info, R/W attribs */ + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_DEVTYPE; + if (ha->cache_feat & GDT_64BIT) + cmd.u.cache64.DeviceNo = i; + else cmd.u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(srp, &cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + gdth_do_req(srp, &cmd, cmnd, 30); + status = (ushort)srp->sr_command->SCp.Status; + info = (ulong32)srp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + gdth_do_cmd(scp, &cmd, cmnd, 30); + status = (ushort)scp->SCp.Status; + info = (ulong32)scp->SCp.Message; #else - gdth_do_cmd(&scp, &cmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; + gdth_do_cmd(&scp, &cmd, cmnd, 30); + status = (ushort)scp.SCp.Status; + info = (ulong32)scp.SCp.Message; #endif - GDTH_LOCK_HA(ha, flags); - ha->hdr[i].devtype = (status == S_OK ? (ushort)info : 0); - GDTH_UNLOCK_HA(ha, flags); + GDTH_LOCK_HA(ha, flags); + ha->hdr[i].devtype = (status == S_OK ? (ushort)info : 0); + GDTH_UNLOCK_HA(ha, flags); - cmd.Service = CACHESERVICE; - cmd.OpCode = GDT_CLUST_INFO; + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_CLUST_INFO; + if (ha->cache_feat & GDT_64BIT) + cmd.u.cache64.DeviceNo = i; + else cmd.u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(srp, &cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + gdth_do_req(srp, &cmd, cmnd, 30); + status = (ushort)srp->sr_command->SCp.Status; + info = (ulong32)srp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + gdth_do_cmd(scp, &cmd, cmnd, 30); + status = (ushort)scp->SCp.Status; + info = (ulong32)scp->SCp.Message; #else - gdth_do_cmd(&scp, &cmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; + gdth_do_cmd(&scp, &cmd, cmnd, 30); + status = (ushort)scp.SCp.Status; + info = (ulong32)scp.SCp.Message; #endif - GDTH_LOCK_HA(ha, flags); - ha->hdr[i].cluster_type = - ((status == S_OK && !shared_access) ? (ushort)info : 0); - GDTH_UNLOCK_HA(ha, flags); - rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type; + GDTH_LOCK_HA(ha, flags); + ha->hdr[i].cluster_type = + ((status == S_OK && !shared_access) ? (ushort)info : 0); + GDTH_UNLOCK_HA(ha, flags); + rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type; - cmd.Service = CACHESERVICE; - cmd.OpCode = GDT_RW_ATTRIBS; + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_RW_ATTRIBS; + if (ha->cache_feat & GDT_64BIT) + cmd.u.cache64.DeviceNo = i; + else cmd.u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(srp, &cmd, cmnd, 30); - status = (ushort)srp->sr_command->SCp.Status; - info = (ulong32)srp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &cmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + gdth_do_req(srp, &cmd, cmnd, 30); + status = (ushort)srp->sr_command->SCp.Status; + info = (ulong32)srp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + gdth_do_cmd(scp, &cmd, cmnd, 30); + status = (ushort)scp->SCp.Status; + info = (ulong32)scp->SCp.Message; #else - gdth_do_cmd(&scp, &cmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; + gdth_do_cmd(&scp, &cmd, cmnd, 30); + status = (ushort)scp.SCp.Status; + info = (ulong32)scp.SCp.Message; #endif - GDTH_LOCK_HA(ha, flags); - ha->hdr[i].rw_attribs = (status == S_OK ? (ushort)info : 0); - GDTH_UNLOCK_HA(ha, flags); - } -#if LINUX_VERSION_CODE >= 0x020503 - scsi_release_request(srp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 - scsi_release_command(scp); - scsi_free_host_dev(sdev); + GDTH_LOCK_HA(ha, flags); + ha->hdr[i].rw_attribs = (status == S_OK ? (ushort)info : 0); + GDTH_UNLOCK_HA(ha, flags); + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + scsi_release_request(srp); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + scsi_release_command(scp); #endif - if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan))) - return -EFAULT; - return 0; + if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan))) + return -EFAULT; + return 0; } static int gdth_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg) { gdth_ha_str *ha; -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) Scsi_Cmnd *scp; - Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) Scsi_Cmnd *scp; - Scsi_Device *sdev; #else Scsi_Cmnd scp; - Scsi_Device sdev; #endif ulong flags; char cmnd[MAX_COMMAND_SIZE]; @@ -5451,7 +5880,7 @@ { int cnt = gdth_ctr_count; if (put_user(cnt, (int *)arg)) - return -EFAULT; + return -EFAULT; break; } @@ -5459,7 +5888,7 @@ { int ver = (GDTH_VERSION<<8) | GDTH_SUBVERSION; if (put_user(ver, (int *)arg)) - return -EFAULT; + return -EFAULT; break; } @@ -5471,7 +5900,7 @@ osv.subversion = (unchar)(LINUX_VERSION_CODE >> 8); osv.revision = (ushort)(LINUX_VERSION_CODE & 0xff); if (copy_to_user((char *)arg, &osv, sizeof(gdth_ioctl_osvers))) - return -EFAULT; + return -EFAULT; break; } @@ -5507,13 +5936,13 @@ } case GDTIOCTL_GENERAL: - return ioc_general(arg, cmnd); + return ioc_general(arg, cmnd); case GDTIOCTL_EVENT: - return ioc_event(arg); + return ioc_event(arg); case GDTIOCTL_LOCKDRV: - return ioc_lockdrv(arg); + return ioc_lockdrv(arg); case GDTIOCTL_LOCKCHN: { @@ -5549,10 +5978,10 @@ } case GDTIOCTL_RESCAN: - return ioc_rescan(arg, cmnd); + return ioc_rescan(arg, cmnd); case GDTIOCTL_HDRLIST: - return ioc_hdrlist(arg, cmnd); + return ioc_hdrlist(arg, cmnd); case GDTIOCTL_RESET_BUS: { @@ -5563,11 +5992,11 @@ res.ionode >= gdth_ctr_count) return -EFAULT; hanum = res.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); - /* Because we need a Scsi_Cmnd struct., we make a scsi_allocate device also for kernels >=2.5.x */ -#if LINUX_VERSION_CODE >= 0x02053C - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_get_command(sdev, GFP_KERNEL); + /* Because we need a Scsi_Cmnd struct., we make a scsi_allocate device also for kernels >=2.6.x */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + scp = scsi_get_command(ha->sdev, GFP_KERNEL); if (!scp) return -ENOMEM; scp->cmd_len = 12; @@ -5576,14 +6005,8 @@ rval = gdth_eh_bus_reset(scp); res.status = (rval == SUCCESS ? S_OK : S_GENERR); scsi_put_command(scp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x020503 - scp = scsi_allocate_device(sdev, 1); -#else - scp = scsi_allocate_device(sdev, 1, FALSE); -#endif +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + scp = scsi_allocate_device(ha->sdev, 1, FALSE); if (!scp) return -ENOMEM; scp->cmd_len = 12; @@ -5592,18 +6015,15 @@ rval = gdth_eh_bus_reset(scp); res.status = (rval == SUCCESS ? S_OK : S_GENERR); scsi_release_command(scp); - scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x02015F - memset(&sdev,0,sizeof(Scsi_Device)); +#else + memset(&ha->sdev,0,sizeof(Scsi_Device)); memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; - sdev.id = scp.target = sdev.host->this_id; - scp.device = &sdev; + ha->sdev.host = scp.host = gdth_ctr_tab[hanum]; + ha->sdev.id = scp.target = ha->sdev.host->this_id; + scp.device = &ha->sdev; scp.channel = virt_ctr ? 0 : res.number; rval = gdth_eh_bus_reset(&scp); res.status = (rval == SUCCESS ? S_OK : S_GENERR); -#else - res.status = S_OK; #endif if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset))) return -EFAULT; @@ -5611,26 +6031,25 @@ } case GDTIOCTL_RESET_DRV: - return ioc_resetdrv(arg, cmnd); + return ioc_resetdrv(arg, cmnd); default: break; } return 0; } -#endif -#if LINUX_VERSION_CODE >= 0x010300 + /* flush routine */ static void gdth_flush(int hanum) { int i; gdth_ha_str *ha; gdth_cmd_str gdtcmd; -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) Scsi_Request *srp; Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) Scsi_Cmnd *scp; Scsi_Device *sdev; #else @@ -5643,14 +6062,14 @@ TRACE2(("gdth_flush() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) return; srp->sr_cmd_len = 12; srp->sr_use_sg = 0; -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); scp = scsi_allocate_device(sdev, 1, FALSE); if (!scp) @@ -5670,42 +6089,44 @@ gdtcmd.BoardNode = LOCALBOARD; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_FLUSH; - gdtcmd.u.cache.DeviceNo = i; - gdtcmd.u.cache.BlockNo = 1; - gdtcmd.u.cache.sg_canz = 0; + if (ha->cache_feat & GDT_64BIT) { + gdtcmd.u.cache64.DeviceNo = i; + gdtcmd.u.cache64.BlockNo = 1; + gdtcmd.u.cache64.sg_canz = 0; + } else { + gdtcmd.u.cache.DeviceNo = i; + gdtcmd.u.cache.BlockNo = 1; + gdtcmd.u.cache.sg_canz = 0; + } TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i)); -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) gdth_do_req(srp, &gdtcmd, cmnd, 30); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) gdth_do_cmd(scp, &gdtcmd, cmnd, 30); #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); #endif } } -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) scsi_release_request(srp); scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) scsi_release_command(scp); scsi_free_host_dev(sdev); #endif } /* shutdown routine */ -#if LINUX_VERSION_CODE >= 0x020100 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) -#else -void gdth_halt(void) -#endif { int hanum; #ifndef __alpha__ gdth_cmd_str gdtcmd; -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) Scsi_Request *srp; Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) Scsi_Cmnd *scp; Scsi_Device *sdev; #else @@ -5715,20 +6136,11 @@ char cmnd[MAX_COMMAND_SIZE]; #endif -#if LINUX_VERSION_CODE >= 0x020100 TRACE2(("gdth_halt() event %d\n",(int)event)); if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF) return NOTIFY_DONE; -#else - TRACE2(("gdth_halt()\n")); - if (halt_called) { - TRACE2(("already called\n")); - return; - } - halt_called = TRUE; -#endif - printk("GDT: Flushing all host drives .. "); + printk("GDT-HA: Flushing all host drives .. "); for (hanum = 0; hanum < gdth_ctr_count; ++hanum) { gdth_flush(hanum); @@ -5739,32 +6151,24 @@ gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_RESET; TRACE2(("gdth_halt(): reset controller %d\n", hanum)); -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); srp = scsi_allocate_request(sdev, GFP_KERNEL); if (!srp) { -#if LINUX_VERSION_CODE >= 0x020100 unregister_reboot_notifier(&gdth_notifier); return NOTIFY_OK; -#else - return; -#endif } srp->sr_cmd_len = 12; srp->sr_use_sg = 0; gdth_do_req(srp, &gdtcmd, cmnd, 10); scsi_release_request(srp); scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); scp = scsi_allocate_device(sdev, 1, FALSE); if (!scp) { -#if LINUX_VERSION_CODE >= 0x020100 unregister_reboot_notifier(&gdth_notifier); return NOTIFY_OK; -#else - return; -#endif } scp->cmd_len = 12; scp->use_sg = 0; @@ -5786,15 +6190,12 @@ #ifdef GDTH_STATISTICS del_timer(&gdth_timer); #endif -#if LINUX_VERSION_CODE >= 0x020100 unregister_reboot_notifier(&gdth_notifier); return NOTIFY_OK; -#endif } -#endif -#if LINUX_VERSION_CODE < 0x020400 && !defined(MODULE) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) && !defined(MODULE) GDTH_INITFUNC(void, gdth_setup(char *str,int *ints)) { @@ -5805,33 +6206,36 @@ #else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) static Scsi_Host_Template driver_template = { -#if LINUX_VERSION_CODE >= 0x02015F - .proc_name = "gdth", -#else - .proc_dir = &proc_scsi_gdth, + .proc_name = "gdth", + .proc_info = gdth_proc_info, + .name = "GDT SCSI Disk Array Controller", + .detect = gdth_detect, + .release = gdth_release, + .info = gdth_info, + .queuecommand = gdth_queuecommand, + .eh_abort_handler = gdth_eh_abort, + .eh_device_reset_handler = gdth_eh_device_reset, + .eh_bus_reset_handler = gdth_eh_bus_reset, + .eh_host_reset_handler = gdth_eh_host_reset, + .bios_param = gdth_bios_param, + .can_queue = GDTH_MAXCMDS, + .this_id = -1, + .sg_tablesize = GDTH_MAXSG, + .cmd_per_lun = GDTH_MAXC_P_L, + .unchecked_isa_dma = 1, + .use_clustering = ENABLE_CLUSTERING, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + .use_new_eh_code = 1, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) + .highmem_io = 1, #endif - .proc_info = gdth_proc_info, - .name = "GDT SCSI Disk Array Controller", - .detect = gdth_detect, - .release = gdth_release, - .info = gdth_info, - .queuecommand = gdth_queuecommand, - .eh_abort_handler = gdth_eh_abort, - .eh_device_reset_handler = gdth_eh_device_reset, - .eh_bus_reset_handler = gdth_eh_bus_reset, - .eh_host_reset_handler = gdth_eh_host_reset, - .bios_param = gdth_bios_param, - .can_queue = GDTH_MAXCMDS, - .this_id = -1, - .sg_tablesize = GDTH_MAXSG, - .cmd_per_lun = GDTH_MAXC_P_L, - .unchecked_isa_dma = 1, - .use_clustering = ENABLE_CLUSTERING, -#if LINUX_VERSION_CODE < 0x020501 - .use_new_eh_code = 1, #endif }; +#else +static Scsi_Host_Template driver_template = GDTH; +#endif #include "scsi_module.c" #ifndef MODULE --- diff/drivers/scsi/gdth.h 2004-05-19 22:12:09.000000000 +0100 +++ source/drivers/scsi/gdth.h 2004-05-27 18:34:17.000000000 +0100 @@ -10,7 +10,7 @@ * * * - * $Id: gdth.h,v 1.50 2003/09/17 08:29:58 achim Exp $ + * $Id: gdth.h,v 1.57 2004/03/31 11:52:09 achim Exp $ */ #include @@ -26,9 +26,9 @@ /* defines, macros */ /* driver version */ -#define GDTH_VERSION_STR "2.08" -#define GDTH_VERSION 2 -#define GDTH_SUBVERSION 8 +#define GDTH_VERSION_STR "3.04" +#define GDTH_VERSION 3 +#define GDTH_SUBVERSION 4 /* protocol version */ #define PROTOCOL_VERSION 1 @@ -133,7 +133,12 @@ /* new GDT Rx Controller */ #define PCI_DEVICE_ID_VORTEX_GDTNEWRX 0x300 #endif - + +#ifndef PCI_DEVICE_ID_VORTEX_GDTNEWRX2 +/* new(2) GDT Rx Controller */ +#define PCI_DEVICE_ID_VORTEX_GDTNEWRX2 0x301 +#endif + #ifndef PCI_DEVICE_ID_INTEL_SRC /* Intel Storage RAID Controller */ #define PCI_DEVICE_ID_INTEL_SRC 0x600 @@ -146,8 +151,7 @@ /* limits */ #define GDTH_SCRATCH PAGE_SIZE /* 4KB scratch buffer */ -#define GDTH_SCRATCH_ORD 0 /* order 0 means 1 page */ -#define GDTH_MAXCMDS 124 +#define GDTH_MAXCMDS 120 #define GDTH_MAXC_P_L 16 /* max. cmds per lun */ #define GDTH_MAX_RAW 2 /* max. cmds per raw device */ #define MAXOFFSETS 128 @@ -221,6 +225,8 @@ #define GDT_CLUST_RESET 24 /* releases the cluster drives*/ #define GDT_FREEZE_IO 25 /* freezes all IOs */ #define GDT_UNFREEZE_IO 26 /* unfreezes all IOs */ +#define GDT_X_INIT_HOST 29 /* ext. init: 64 bit support */ +#define GDT_X_INFO 30 /* ext. info for drives>2TB */ /* raw service commands */ #define GDT_RESERVE 14 /* reserve dev. to raw serv. */ @@ -230,9 +236,11 @@ #define GDT_RESET_BUS 18 /* reset bus */ #define GDT_SCAN_START 19 /* start device scan */ #define GDT_SCAN_END 20 /* stop device scan */ +#define GDT_X_INIT_RAW 21 /* ext. init: 64 bit support */ /* screen service commands */ #define GDT_REALTIME 3 /* realtime clock to screens. */ +#define GDT_X_INIT_SCR 4 /* ext. init: 64 bit support */ /* IOCTL command defines */ #define SCSI_DR_INFO 0x00 /* SCSI drive info */ @@ -254,6 +262,8 @@ #define CACHE_DRV_INFO 0x07 /* cache drive info */ #define BOARD_FEATURES 0x15 /* controller features */ #define BOARD_INFO 0x28 /* controller info */ +#define SET_PERF_MODES 0x82 /* set mode (coalescing,..) */ +#define GET_PERF_MODES 0x83 /* get mode */ #define CACHE_READ_OEM_STRING_RECORD 0x84 /* read OEM string record */ #define HOST_GET 0x10001L /* get host drive list */ #define IO_CHANNEL 0x00020000L /* default IO channel */ @@ -266,6 +276,7 @@ #define S_CACHE_UNKNOWN 12 /* cache serv.: drive unknown */ #define S_RAW_SCSI 12 /* raw serv.: target error */ #define S_RAW_ILL 0xff /* raw serv.: illegal */ +#define S_NOFUNC -2 /* unknown function */ #define S_CACHE_RESERV -24 /* cache: reserv. conflict */ /* timeout values */ @@ -307,7 +318,12 @@ #define LOCALBOARD 0 /* board node always 0 */ #define ASYNCINDEX 0 /* cmd index async. event */ #define SPEZINDEX 1 /* cmd index unknown service */ +#define COALINDEX (GDTH_MAXCMDS + 2) + +/* features */ +#define SCATTER_GATHER 1 /* s/g feature */ #define GDT_WR_THROUGH 0x100 /* WRITE_THROUGH supported */ +#define GDT_64BIT 0x200 /* 64bit / drv>2TB support */ #include "gdth_ioctl.h" @@ -322,7 +338,40 @@ char msg_text[MSGLEN+2]; /* the message text */ } PACKED gdth_msg_str; + /* IOCTL data structures */ + +/* Status coalescing buffer for returning multiple requests per interrupt */ +typedef struct { + ulong32 status; + ulong32 ext_status; + ulong32 info0; + ulong32 info1; +} PACKED gdth_coal_status; + +/* performance mode data structure */ +typedef struct { + ulong32 version; /* The version of this IOCTL structure. */ + ulong32 st_mode; /* 0=dis., 1=st_buf_addr1 valid, 2=both */ + ulong32 st_buff_addr1; /* physical address of status buffer 1 */ + ulong32 st_buff_u_addr1; /* reserved for 64 bit addressing */ + ulong32 st_buff_indx1; /* reserved command idx. for this buffer */ + ulong32 st_buff_addr2; /* physical address of status buffer 1 */ + ulong32 st_buff_u_addr2; /* reserved for 64 bit addressing */ + ulong32 st_buff_indx2; /* reserved command idx. for this buffer */ + ulong32 st_buff_size; /* size of each buffer in bytes */ + ulong32 cmd_mode; /* 0 = mode disabled, 1 = cmd_buff_addr1 */ + ulong32 cmd_buff_addr1; /* physical address of cmd buffer 1 */ + ulong32 cmd_buff_u_addr1; /* reserved for 64 bit addressing */ + ulong32 cmd_buff_indx1; /* cmd buf addr1 unique identifier */ + ulong32 cmd_buff_addr2; /* physical address of cmd buffer 1 */ + ulong32 cmd_buff_u_addr2; /* reserved for 64 bit addressing */ + ulong32 cmd_buff_indx2; /* cmd buf addr1 unique identifier */ + ulong32 cmd_buff_size; /* size of each cmd bufer in bytes */ + ulong32 reserved1; + ulong32 reserved2; +} PACKED gdth_perf_modes; + /* SCSI drive info */ typedef struct { unchar vendor[8]; /* vendor string */ @@ -795,9 +844,7 @@ /* PCI resources */ typedef struct { -#if LINUX_VERSION_CODE >= 0x02015C struct pci_dev *pdev; -#endif ushort vendor_id; /* vendor (ICP, Intel, ..) */ ushort device_id; /* device ID (0,..,9) */ ushort subdevice_id; /* sub device ID */ @@ -814,20 +861,28 @@ typedef struct { ushort oem_id; /* OEM */ ushort type; /* controller class */ - ushort raw_feat; /* feat. raw service (s/g,..) */ ulong32 stype; /* subtype (PCI: device ID) */ ushort subdevice_id; /* sub device ID (PCI) */ ushort fw_vers; /* firmware version */ - ushort cache_feat; /* feat. cache serv. (s/g,..) */ + ushort cache_feat; /* feat. cache serv. (s/g,..)*/ + ushort raw_feat; /* feat. raw service (s/g,..)*/ + ushort screen_feat; /* feat. raw service (s/g,..)*/ ushort bmic; /* BMIC address (EISA) */ void *brd; /* DPRAM address */ ulong32 brd_phys; /* slot number/BIOS address */ gdt6c_plx_regs *plx; /* PLX regs (new PCI contr.) */ gdth_cmd_str *pccb; /* address command structure */ ulong32 ccb_phys; /* phys. address */ +#ifdef INT_COAL + gdth_coal_status *coal_stat; /* buffer for coalescing int.*/ + ulong64 coal_stat_phys; /* phys. address */ +#endif char *pscratch; /* scratch (DMA) buffer */ - ulong32 scratch_phys; /* phys. address */ + ulong64 scratch_phys; /* phys. address */ unchar scratch_busy; /* in use? */ + unchar dma64_support; /* 64-bit DMA supported? */ + gdth_msg_str *pmsg; /* message buffer */ + ulong64 msg_phys; /* phys. address */ unchar scan_mode; /* current scan mode */ unchar irq; /* IRQ */ unchar drq; /* DRQ (ISA controllers) */ @@ -848,11 +903,11 @@ unchar heads; /* mapping */ unchar secs; ushort devtype; /* further information */ - ulong32 size; /* capacity */ + ulong64 size; /* capacity */ unchar ldr_no; /* log. drive no. */ unchar rw_attribs; /* r/w attributes */ unchar cluster_type; /* cluster properties */ - unchar media_changed; /* Flag:MOUNT/UNMOUNT occurred*/ + unchar media_changed; /* Flag:MOUNT/UNMOUNT occured */ ulong32 start_sec; /* start sector */ } hdr[MAX_LDRIVES]; /* host drives */ struct { @@ -880,13 +935,19 @@ gdth_bfeat_str bfeat; /* controller features */ gdth_binfo_str binfo; /* controller info */ gdth_evt_data dvr; /* event structure */ -#if LINUX_VERSION_CODE >= 0x02015F spinlock_t smp_lock; -#endif -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) struct pci_dev *pdev; #endif char oem_name[8]; +#ifdef GDTH_DMA_STATISTICS + ulong dma32_cnt, dma64_cnt; /* statistics: DMA buffer */ +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + Scsi_Device *sdev; +#else + Scsi_Device sdev; +#endif } gdth_ha_str; /* structure for scsi_register(), SCSI bus != 0 */ @@ -924,6 +985,12 @@ ulong32 block_length; } PACKED gdth_rdcap_data; +/* READ_CAPACITY (16) data format */ +typedef struct { + ulong64 last_block_no; + ulong32 block_length; +} PACKED gdth_rdcap16_data; + /* REQUEST_SENSE data format */ typedef struct { unchar errorcode; @@ -965,42 +1032,48 @@ int gdth_detect(Scsi_Host_Template *); int gdth_release(struct Scsi_Host *); int gdth_queuecommand(Scsi_Cmnd *,void (*done)(Scsi_Cmnd *)); -int gdth_abort(Scsi_Cmnd *); -#if LINUX_VERSION_CODE >= 0x010346 -int gdth_reset(Scsi_Cmnd *, unsigned int reset_flags); -#else -int gdth_reset(Scsi_Cmnd *); -#endif const char *gdth_info(struct Scsi_Host *); -#if LINUX_VERSION_CODE >= 0x020501 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) int gdth_bios_param(struct scsi_device *,struct block_device *,sector_t,int *); int gdth_proc_info(struct Scsi_Host *, char *,char **,off_t,int,int); -int gdth_eh_abort(Scsi_Cmnd *scp); -int gdth_eh_device_reset(Scsi_Cmnd *scp); -int gdth_eh_bus_reset(Scsi_Cmnd *scp); -int gdth_eh_host_reset(Scsi_Cmnd *scp); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) int gdth_bios_param(Disk *,kdev_t,int *); int gdth_proc_info(char *,char **,off_t,int,int,int); -int gdth_eh_abort(Scsi_Cmnd *scp); -int gdth_eh_device_reset(Scsi_Cmnd *scp); -int gdth_eh_bus_reset(Scsi_Cmnd *scp); -int gdth_eh_host_reset(Scsi_Cmnd *scp); -#elif LINUX_VERSION_CODE >= 0x02015F +#else int gdth_bios_param(Disk *,kdev_t,int *); extern struct proc_dir_entry proc_scsi_gdth; int gdth_proc_info(char *,char **,off_t,int,int,int); +int gdth_abort(Scsi_Cmnd *); +int gdth_reset(Scsi_Cmnd *,unsigned int); +#define GDTH { proc_dir: &proc_scsi_gdth, \ + proc_info: gdth_proc_info, \ + name: "GDT SCSI Disk Array Controller",\ + detect: gdth_detect, \ + release: gdth_release, \ + info: gdth_info, \ + command: NULL, \ + queuecommand: gdth_queuecommand, \ + eh_abort_handler: gdth_eh_abort, \ + eh_device_reset_handler: gdth_eh_device_reset, \ + eh_bus_reset_handler: gdth_eh_bus_reset, \ + eh_host_reset_handler: gdth_eh_host_reset, \ + abort: gdth_abort, \ + reset: gdth_reset, \ + bios_param: gdth_bios_param, \ + can_queue: GDTH_MAXCMDS, \ + this_id: -1, \ + sg_tablesize: GDTH_MAXSG, \ + cmd_per_lun: GDTH_MAXC_P_L, \ + present: 0, \ + unchecked_isa_dma: 1, \ + use_clustering: ENABLE_CLUSTERING, \ + use_new_eh_code: 1 /* use new error code */ } +#endif + int gdth_eh_abort(Scsi_Cmnd *scp); int gdth_eh_device_reset(Scsi_Cmnd *scp); int gdth_eh_bus_reset(Scsi_Cmnd *scp); int gdth_eh_host_reset(Scsi_Cmnd *scp); -#elif LINUX_VERSION_CODE >= 0x010300 -int gdth_bios_param(Disk *,kdev_t,int *); -extern struct proc_dir_entry proc_scsi_gdth; -int gdth_proc_info(char *,char **,off_t,int,int,int); -#else -int gdth_bios_param(Disk *,int,int *); -#endif -#endif +#endif --- diff/drivers/scsi/gdth_ioctl.h 2004-05-19 22:12:09.000000000 +0100 +++ source/drivers/scsi/gdth_ioctl.h 2004-05-27 18:34:17.000000000 +0100 @@ -2,7 +2,7 @@ #define _GDTH_IOCTL_H /* gdth_ioctl.h - * $Id: gdth_ioctl.h,v 1.11 2003/02/27 14:59:03 achim Exp $ + * $Id: gdth_ioctl.h,v 1.14 2004/02/19 15:43:15 achim Exp $ */ /* IOCTLs */ @@ -21,8 +21,8 @@ #define GDTIOCTL_RESCAN (GDTIOCTL_MASK |11) /* rescan host drives */ #define GDTIOCTL_RESET_DRV (GDTIOCTL_MASK |12) /* reset (remote) drv. res. */ -#define GDTIOCTL_MAGIC 0xaffe0004 -#define EVENT_SIZE 294 +#define GDTIOCTL_MAGIC 0xaffe0004 +#define EVENT_SIZE 294 #define GDTH_MAXSG 32 /* max. s/g elements */ #define MAX_LDRIVES 255 /* max. log. drive count */ @@ -35,7 +35,9 @@ /* typedefs */ #ifdef __KERNEL__ typedef u32 ulong32; +typedef u64 ulong64; #endif + #define PACKED __attribute__((packed)) /* scatter/gather element */ @@ -44,6 +46,12 @@ ulong32 sg_len; /* length */ } PACKED gdth_sg_str; +/* scatter/gather element - 64bit addresses */ +typedef struct { + ulong64 sg_ptr; /* address */ + ulong32 sg_len; /* length */ +} PACKED gdth_sg64_str; + /* command structure */ typedef struct { ulong32 BoardNode; /* board node (always 0) */ @@ -59,17 +67,25 @@ gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */ } PACKED cache; /* cache service cmd. str. */ struct { + ushort DeviceNo; /* number of cache drive */ + ulong64 BlockNo; /* block number */ + ulong32 BlockCnt; /* block count */ + ulong64 DestAddr; /* dest. addr. (if s/g: -1) */ + ulong32 sg_canz; /* s/g element count */ + gdth_sg64_str sg_lst[GDTH_MAXSG]; /* s/g list */ + } PACKED cache64; /* cache service cmd. str. */ + struct { ushort param_size; /* size of p_param buffer */ ulong32 subfunc; /* IOCTL function */ ulong32 channel; /* device */ - ulong32 p_param; /* buffer */ + ulong64 p_param; /* buffer */ } PACKED ioctl; /* IOCTL command structure */ struct { ushort reserved; union { struct { ulong32 msg_handle; /* message handle */ - ulong32 msg_addr; /* message buffer address */ + ulong64 msg_addr; /* message buffer address */ } PACKED msg; unchar data[12]; /* buffer for rtc data, ... */ } su; @@ -93,6 +109,24 @@ ulong32 sg_ranz; /* s/g element count */ gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */ } PACKED raw; /* raw service cmd. struct. */ + struct { + ushort reserved; + ulong32 direction; /* data direction */ + ulong32 mdisc_time; /* disc. time (0: no timeout)*/ + ulong32 mcon_time; /* connect time(0: no to.) */ + ulong64 sdata; /* dest. addr. (if s/g: -1) */ + ulong32 sdlen; /* data length (bytes) */ + ulong32 clen; /* SCSI cmd. length(6,..,16) */ + unchar cmd[16]; /* SCSI command */ + unchar target; /* target ID */ + unchar lun; /* LUN */ + unchar bus; /* SCSI bus number */ + unchar priority; /* only 0 used */ + ulong32 sense_len; /* sense data length */ + ulong64 sense_data; /* sense data addr. */ + ulong32 sg_ranz; /* s/g element count */ + gdth_sg64_str sg_lst[GDTH_MAXSG]; /* s/g list */ + } PACKED raw64; /* raw service cmd. struct. */ } u; /* additional variables */ unchar Service; /* controller service */ @@ -236,7 +270,6 @@ } gdth_iord_str; #endif -#ifdef GDTH_IOCTL_CHRDEV /* GDTIOCTL_GENERAL */ typedef struct { ushort ionode; /* controller number */ @@ -244,8 +277,8 @@ ulong32 info; /* error info */ ushort status; /* status */ ulong data_len; /* data buffer size */ - ulong sense_len; /* sense buffer size */ - gdth_cmd_str command; /* command */ + ulong sense_len; /* sense buffer size */ + gdth_cmd_str command; /* command */ } gdth_ioctl_general; /* GDTIOCTL_LOCKDRV */ @@ -310,6 +343,5 @@ ushort number; /* bus/host drive number */ ushort status; /* status */ } gdth_ioctl_reset; -#endif #endif --- diff/drivers/scsi/gdth_proc.c 2004-05-19 22:12:09.000000000 +0100 +++ source/drivers/scsi/gdth_proc.c 2004-05-27 18:34:18.000000000 +0100 @@ -1,56 +1,80 @@ /* gdth_proc.c - * $Id: gdth_proc.c,v 1.37 2003/09/17 08:31:53 achim Exp $ + * $Id: gdth_proc.c,v 1.42 2004/03/05 15:50:20 achim Exp $ */ -#if LINUX_VERSION_CODE >= 0x020407 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) #include #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) int gdth_proc_info(struct Scsi_Host *host, char *buffer,char **start,off_t offset,int length, int inout) { int hanum,busnum; - TRACE2(("gdth_proc_info() length %d ha %d offs %d inout %d\n", - length,hostno,(int)offset,inout)); + TRACE2(("gdth_proc_info() length %d offs %d inout %d\n", + length,(int)offset,inout)); hanum = NUMDATA(host)->hanum; busnum= NUMDATA(host)->busnum; if (inout) - return(gdth_set_info(buffer,length,hanum,busnum)); + return(gdth_set_info(buffer,length,host,hanum,busnum)); else - return(gdth_get_info(buffer,start,offset,length,hanum,busnum)); + return(gdth_get_info(buffer,start,offset,length,host,hanum,busnum)); } +#else +int gdth_proc_info(char *buffer,char **start,off_t offset,int length,int hostno, + int inout) +{ + int hanum,busnum,i; + + TRACE2(("gdth_proc_info() length %d offs %d inout %d\n", + length,(int)offset,inout)); + + for (i = 0; i < gdth_ctr_vcount; ++i) { + if (gdth_ctr_vtab[i]->host_no == hostno) + break; + } + if (i == gdth_ctr_vcount) + return(-EINVAL); + + hanum = NUMDATA(gdth_ctr_vtab[i])->hanum; + busnum= NUMDATA(gdth_ctr_vtab[i])->busnum; + + if (inout) + return(gdth_set_info(buffer,length,gdth_ctr_vtab[i],hanum,busnum)); + else + return(gdth_get_info(buffer,start,offset,length, + gdth_ctr_vtab[i],hanum,busnum)); +} +#endif -static int gdth_set_info(char *buffer,int length,int hanum,int busnum) +static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host, + int hanum,int busnum) { int ret_val = -EINVAL; -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) Scsi_Request *scp; Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) Scsi_Cmnd *scp; Scsi_Device *sdev; #else Scsi_Cmnd scp; Scsi_Device sdev; #endif -#ifdef GDTH_IOCTL_PROC - gdth_iowr_str *piowr; - piowr = (gdth_iowr_str *)buffer; -#endif TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum)); -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + sdev = scsi_get_host_dev(host); scp = scsi_allocate_request(sdev, GFP_KERNEL); if (!scp) return -ENOMEM; scp->sr_cmd_len = 12; scp->sr_use_sg = 0; -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + sdev = scsi_get_host_dev(host); scp = scsi_allocate_device(sdev, 1, FALSE); if (!scp) return -ENOMEM; @@ -59,7 +83,7 @@ #else memset(&sdev,0,sizeof(Scsi_Device)); memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; + sdev.host = scp.host = host; sdev.id = scp.target = sdev.host->this_id; scp.device = &sdev; #endif @@ -69,32 +93,21 @@ buffer += 5; length -= 5; ret_val = gdth_set_asc_info( buffer, length, hanum, scp ); -#ifdef GDTH_IOCTL_PROC - } else if (piowr->magic == GDTIOCTL_MAGIC) { - ret_val = gdth_set_bin_info( buffer, length, hanum, scp ); - } else { - printk("GDT: Wrong signature %x (%x required)!\n", - piowr->magic, GDTIOCTL_MAGIC); - if (piowr->magic > GDTIOCTL_MAGIC) - printk("GDT: Please update your driver.\n"); - else - printk("GDT: Please update your tool.\n"); -#endif } } -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) scsi_release_request(scp); scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) scsi_release_command(scp); scsi_free_host_dev(sdev); #endif return ret_val; } -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp) -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp) #else static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp) @@ -105,7 +118,7 @@ gdth_ha_str *ha; gdth_cmd_str gdtcmd; gdth_cpar_str *pcpar; - ulong32 paddr; + ulong64 paddr; char cmnd[MAX_COMMAND_SIZE]; memset(cmnd, 0xff, 12); @@ -139,11 +152,16 @@ found = TRUE; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_FLUSH; - gdtcmd.u.cache.DeviceNo = i; - gdtcmd.u.cache.BlockNo = 1; -#if LINUX_VERSION_CODE >= 0x020503 + if (ha->cache_feat & GDT_64BIT) { + gdtcmd.u.cache64.DeviceNo = i; + gdtcmd.u.cache64.BlockNo = 1; + } else { + gdtcmd.u.cache.DeviceNo = i; + gdtcmd.u.cache.BlockNo = 1; + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) gdth_do_req(scp, &gdtcmd, cmnd, 30); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) gdth_do_cmd(scp, &gdtcmd, cmnd, 30); #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); @@ -199,9 +217,9 @@ gdtcmd.u.ioctl.subfunc = CACHE_CONFIG; gdtcmd.u.ioctl.channel = INVALID_CHANNEL; pcpar->write_back = wb_mode==1 ? 0:1; -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) gdth_do_req(scp, &gdtcmd, cmnd, 30); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) gdth_do_cmd(scp, &gdtcmd, cmnd, 30); #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); @@ -215,562 +233,23 @@ return(-EINVAL); } -#ifdef GDTH_IOCTL_PROC -#if LINUX_VERSION_CODE >= 0x020503 -static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Request *scp) -#elif LINUX_VERSION_CODE >= 0x020322 -static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp) -#else -static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp) -#endif -{ - unchar i, j; - ushort k, hdr_cnt, status; - gdth_ha_str *ha; - gdth_iowr_str *piowr; - gdth_iord_str *piord; - gdth_cmd_str *pcmd; - gdth_evt_str *pevt; - ulong32 *ppadd, add_size, *ppadd2, add_size2, info, paddr; - ulong flags; - gdth_cmd_str gdtcmd; - int drv_cyls, drv_hds, drv_secs; - - char cmnd[MAX_COMMAND_SIZE]; - memset(cmnd, 0xff, 12); - memset(&gdtcmd, 0, sizeof(gdth_cmd_str)); - - TRACE2(("gdth_set_bin_info() ha %d\n",hanum)); - ha = HADATA(gdth_ctr_tab[hanum]); - piowr = (gdth_iowr_str *)buffer; - piord = NULL; - pcmd = NULL; - ppadd = ppadd2 = NULL; - add_size = add_size2 = 0; - - if (length < GDTOFFSOF(gdth_iowr_str,iu)) - return(-EINVAL); - - switch (piowr->ioctl) { - case GDTIOCTL_GENERAL: - if (length < GDTOFFSOF(gdth_iowr_str,iu.general.data[0])) - return(-EINVAL); - pcmd = (gdth_cmd_str *)piowr->iu.general.command; - pcmd->Service = piowr->service; - if (pcmd->OpCode == GDT_IOCTL) { - ppadd = &pcmd->u.ioctl.p_param; - add_size = pcmd->u.ioctl.param_size; - } else if (piowr->service == CACHESERVICE) { - add_size = pcmd->u.cache.BlockCnt * SECTOR_SIZE; - if (ha->cache_feat & SCATTER_GATHER) { - ppadd = &pcmd->u.cache.sg_lst[0].sg_ptr; - pcmd->u.cache.DestAddr = 0xffffffff; - pcmd->u.cache.sg_lst[0].sg_len = add_size; - pcmd->u.cache.sg_canz = 1; - } else { - ppadd = &pcmd->u.cache.DestAddr; - pcmd->u.cache.sg_canz = 0; - } - } else if (piowr->service == SCSIRAWSERVICE) { - add_size = pcmd->u.raw.sdlen; - add_size2 = pcmd->u.raw.sense_len; - if (ha->raw_feat & SCATTER_GATHER) { - ppadd = &pcmd->u.raw.sg_lst[0].sg_ptr; - pcmd->u.raw.sdata = 0xffffffff; - pcmd->u.raw.sg_lst[0].sg_len = add_size; - pcmd->u.raw.sg_ranz = 1; - } else { - ppadd = &pcmd->u.raw.sdata; - pcmd->u.raw.sg_ranz = 0; - } - ppadd2 = &pcmd->u.raw.sense_data; - } else { - return(-EINVAL); - } - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str)+add_size+add_size2, - TRUE, &paddr )) - return(-EBUSY); - piord = (gdth_iord_str *)ha->pscratch; - piord->size = sizeof(gdth_iord_str) + add_size + add_size2; - if (add_size > 0) { - memcpy(piord->iu.general.data, piowr->iu.general.data, add_size); - *ppadd = paddr + GDTOFFSOF(gdth_iord_str, iu.general.data[0]); - } - if (add_size2 > 0) { - memcpy(piord->iu.general.data+add_size, piowr->iu.general.data, add_size2); - *ppadd2 = paddr + GDTOFFSOF(gdth_iord_str, iu.general.data[0]) + add_size2; - } - - /* do IOCTL */ -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(scp, pcmd, cmnd, piowr->timeout); - piord->status = (scp->sr_command->SCp.Message << 16) | - scp->sr_command->SCp.Status; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, pcmd, cmnd, piowr->timeout); - piord->status = (scp->SCp.Message<<16)|scp->SCp.Status; -#else - gdth_do_cmd(&scp, pcmd, cmnd, piowr->timeout); - piord->status = (scp.SCp.Message<<16)|scp.SCp.Status; -#endif - break; - - case GDTIOCTL_DRVERS: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) - return(-EBUSY); - piord = (gdth_iord_str *)ha->pscratch; - piord->size = sizeof(gdth_iord_str); - piord->status = S_OK; - piord->iu.drvers.version = (GDTH_VERSION<<8) | GDTH_SUBVERSION; - break; - - case GDTIOCTL_CTRTYPE: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) - return(-EBUSY); - piord = (gdth_iord_str *)ha->pscratch; - piord->size = sizeof(gdth_iord_str); - piord->status = S_OK; - if (ha->type == GDT_ISA || ha->type == GDT_EISA) { - piord->iu.ctrtype.type = (unchar)((ha->stype>>20) - 0x10); - } else { - if (ha->type != GDT_PCIMPR) { - piord->iu.ctrtype.type = (unchar)((ha->stype<<4) + 6); - } else { - piord->iu.ctrtype.type = - (ha->oem_id == OEM_ID_INTEL ? 0xfd : 0xfe); - if (ha->stype >= 0x300) - piord->iu.ctrtype.ext_type = 0x6000 | ha->subdevice_id; - else - piord->iu.ctrtype.ext_type = 0x6000 | ha->stype; - } - piord->iu.ctrtype.device_id = ha->stype; - piord->iu.ctrtype.sub_device_id = ha->subdevice_id; - } - piord->iu.ctrtype.info = ha->brd_phys; - piord->iu.ctrtype.oem_id = ha->oem_id; - break; - - case GDTIOCTL_CTRCNT: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) - return(-EBUSY); - piord = (gdth_iord_str *)ha->pscratch; - piord->size = sizeof(gdth_iord_str); - piord->status = S_OK; - piord->iu.ctrcnt.count = (ushort)gdth_ctr_count; - break; - - case GDTIOCTL_OSVERS: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) - return(-EBUSY); - piord = (gdth_iord_str *)ha->pscratch; - piord->size = sizeof(gdth_iord_str); - piord->status = S_OK; - piord->iu.osvers.version = (unchar)(LINUX_VERSION_CODE >> 16); - piord->iu.osvers.subversion = (unchar)(LINUX_VERSION_CODE >> 8); - piord->iu.osvers.revision = (ushort)(LINUX_VERSION_CODE & 0xff); - break; - - case GDTIOCTL_LOCKDRV: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) - return(-EBUSY); - piord = (gdth_iord_str *)ha->pscratch; - for (i = 0; i < piowr->iu.lockdrv.drive_cnt; ++i) { - j = piowr->iu.lockdrv.drives[i]; - if (j >= MAX_HDRIVES || !ha->hdr[j].present) - continue; - if (piowr->iu.lockdrv.lock) { - GDTH_LOCK_HA(ha, flags); - ha->hdr[j].lock = 1; - GDTH_UNLOCK_HA(ha, flags); - gdth_wait_completion( hanum, ha->bus_cnt, j ); - gdth_stop_timeout( hanum, ha->bus_cnt, j ); - } else { - GDTH_LOCK_HA(ha, flags); - ha->hdr[j].lock = 0; - GDTH_UNLOCK_HA(ha, flags); - gdth_start_timeout( hanum, ha->bus_cnt, j ); - gdth_next( hanum ); - } - } - piord->size = sizeof(gdth_iord_str); - piord->status = S_OK; - break; - - case GDTIOCTL_LOCKCHN: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) - return(-EBUSY); - i = piowr->iu.lockchn.channel; - if (i < ha->bus_cnt) { - if (piowr->iu.lockchn.lock) { - GDTH_LOCK_HA(ha, flags); - ha->raw[i].lock = 1; - GDTH_UNLOCK_HA(ha, flags); - for (j = 0; j < ha->tid_cnt; ++j) { - gdth_wait_completion( hanum, i, j ); - gdth_stop_timeout( hanum, i, j ); - } - } else { - GDTH_LOCK_HA(ha, flags); - ha->raw[i].lock = 0; - GDTH_UNLOCK_HA(ha, flags); - for (j = 0; j < ha->tid_cnt; ++j) { - gdth_start_timeout( hanum, i, j ); - gdth_next( hanum ); - } - } - } - piord = (gdth_iord_str *)ha->pscratch; - piord->size = sizeof(gdth_iord_str); - piord->status = S_OK; - break; - - case GDTIOCTL_EVENT: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) - return(-EBUSY); - piord = (gdth_iord_str *)ha->pscratch; - if (piowr->iu.event.erase == 0xff) { - pevt = (gdth_evt_str *)piowr->iu.event.evt; - if (pevt->event_source == ES_TEST) - pevt->event_data.size = sizeof(pevt->event_data.eu.test); - else if (pevt->event_source == ES_DRIVER) - pevt->event_data.size = sizeof(pevt->event_data.eu.driver); - else if (pevt->event_source == ES_SYNC) - pevt->event_data.size = sizeof(pevt->event_data.eu.sync); - else { - pevt->event_data.size = sizeof(pevt->event_data.eu.async); - gdth_log_event(&pevt->event_data, NULL); - } - GDTH_LOCK_HA(ha, flags); - gdth_store_event(ha, pevt->event_source, pevt->event_idx, - &pevt->event_data); - GDTH_UNLOCK_HA(ha, flags); - } else if (piowr->iu.event.erase == 0xfe) { - gdth_clear_events(); - } else if (piowr->iu.event.erase == 0) { - piord->iu.event.handle = - gdth_read_event(ha,piowr->iu.event.handle, - (gdth_evt_str *)piord->iu.event.evt); - } else { - piord->iu.event.handle = piowr->iu.event.handle; - gdth_readapp_event(ha, (unchar)piowr->iu.event.erase, - (gdth_evt_str *)piord->iu.event.evt); - } - piord->size = sizeof(gdth_iord_str); - piord->status = S_OK; - break; - - case GDTIOCTL_SCSI: -#if LINUX_VERSION_CODE >= 0x020503 - return(-EINVAL); -#else - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) - return(-EBUSY); - piord = (gdth_iord_str *)ha->pscratch; - piord->size = sizeof(gdth_iord_str); - memcpy(cmnd, piowr->iu.scsi.cmd, 12); -#if LINUX_VERSION_CODE >= 0x020322 - scp->target = piowr->iu.scsi.target; - scp->channel = virt_ctr ? 0 : piowr->iu.scsi.bus; - scp->cmd_len = piowr->iu.scsi.cmd_len; - gdth_do_cmd(scp, pcmd, cmnd, piowr->timeout); - piord->status = (scp->SCp.Message<<16)|scp->SCp.Status; -#else - scp.target = piowr->iu.scsi.target; - scp.channel = virt_ctr ? 0 : piowr->iu.scsi.bus; - scp.cmd_len = piowr->iu.scsi.cmd_len; - gdth_do_cmd(&scp, pcmd, cmnd, piowr->timeout); - piord->status = (scp.SCp.Message<<16)|scp.SCp.Status; -#endif -#endif - break; - - case GDTIOCTL_RESET_BUS: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) - return(-EBUSY); - piord = (gdth_iord_str *)ha->pscratch; - piord->size = sizeof(gdth_iord_str); -#if LINUX_VERSION_CODE >= 0x02053C - { - Scsi_Device *sdev; - Scsi_Cmnd *scmnd; - - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scmnd= scsi_get_command(sdev, GFP_KERNEL); - if (!scmnd) - return(-ENOMEM); - scmnd->device->host = scp->sr_host; - scmnd->device->channel = virt_ctr ? 0 : piowr->iu.scsi.bus; - piord->status = (ulong32)gdth_eh_bus_reset( scmnd ); - if (piord->status == SUCCESS) - piord->status = S_OK; - else - piord->status = S_GENERR; - scsi_put_command(scmnd); - scsi_free_host_dev(sdev); - } -#elif LINUX_VERSION_CODE >= 0x020503 - { - Scsi_Cmnd scmnd; - - scmnd.host = scp->sr_host; - scmnd.channel = virt_ctr ? 0 : piowr->iu.scsi.bus; - piord->status = (ulong32)gdth_eh_bus_reset( &scmnd ); - if (piord->status == SUCCESS) - piord->status = S_OK; - else - piord->status = S_GENERR; - } -#elif LINUX_VERSION_CODE >= 0x020322 - scp->channel = virt_ctr ? 0 : piowr->iu.scsi.bus; - piord->status = (ulong32)gdth_eh_bus_reset( scp ); - if (piord->status == SUCCESS) - piord->status = S_OK; - else - piord->status = S_GENERR; -#elif LINUX_VERSION_CODE >= 0x02015F - scp.channel = virt_ctr ? 0 : piowr->iu.scsi.bus; - piord->status = (ulong32)gdth_eh_bus_reset( &scp ); - if (piord->status == SUCCESS) - piord->status = S_OK; - else - piord->status = S_GENERR; -#else - piord->status = S_OK; -#endif - break; - - case GDTIOCTL_HDRLIST: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) - return(-EBUSY); - piord = (gdth_iord_str *)ha->pscratch; - piord->size = sizeof(gdth_iord_str); - piord->status = S_OK; - for (i = 0; i < MAX_HDRIVES; ++i) { - if (ha->hdr[i].present) { - piord->iu.hdr_list[i].bus = ha->virt_bus; - piord->iu.hdr_list[i].target = i; - piord->iu.hdr_list[i].lun = 0; - piord->iu.hdr_list[i].cluster_type = ha->hdr[i].cluster_type; - if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) { - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_CLUST_INFO; - gdtcmd.u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(scp, &gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status == S_OK) - piord->iu.hdr_list[i].cluster_type = - (unchar)scp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - if (scp->SCp.Status == S_OK) - piord->iu.hdr_list[i].cluster_type = - (unchar)scp->SCp.Message; -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - if (scp.SCp.Status == S_OK) - piord->iu.hdr_list[i].cluster_type = - (unchar)scp.SCp.Message; -#endif - } - } else { - piord->iu.hdr_list[i].bus = 0xff; - } - } - break; - - case GDTIOCTL_RESCAN: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) - return(-EBUSY); - piord = (gdth_iord_str *)ha->pscratch; - piord->size = sizeof(gdth_iord_str); - piord->status = S_OK; - if (piowr->iu.rescan.flag == 0) { - /* old method: scan all host drives - re-initialize cache service to get host drive count - */ - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_INIT; - gdtcmd.u.cache.DeviceNo = LINUX_OS; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(scp, &gdtcmd, cmnd, 30); - status = (ushort)scp->sr_command->SCp.Status; - info = (ulong32)scp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif - if (status != S_OK) - break; - k = 0; - hdr_cnt = (ushort)info; - } else { - k = piowr->iu.rescan.hdr_no; - hdr_cnt = k + 1; - } - if (hdr_cnt > MAX_HDRIVES) - hdr_cnt = MAX_HDRIVES; - /* scanning for host drives */ - for (; k < hdr_cnt; ++k) { - /* info about host drive */ - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_INFO; - gdtcmd.u.cache.DeviceNo = k; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(scp, &gdtcmd, cmnd, 30); - status = (ushort)scp->sr_command->SCp.Status; - info = (ulong32)scp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif - GDTH_LOCK_HA(ha, flags); - piord->iu.hdr_list[k].bus = ha->virt_bus; - piord->iu.hdr_list[k].target = k; - piord->iu.hdr_list[k].lun = 0; - if (status != S_OK) { - ha->hdr[k].present = FALSE; - } else { - ha->hdr[k].present = TRUE; - ha->hdr[k].size = info; - /* evaluate mapping (sectors per head, heads per cylinder) */ - ha->hdr[k].size &= ~SECS32; - gdth_eval_mapping(ha->hdr[k].size,&drv_cyls,&drv_hds,&drv_secs); - ha->hdr[k].heads = (unchar)drv_hds; - ha->hdr[k].secs = (unchar)drv_secs; - /* round size */ - ha->hdr[k].size = drv_cyls * drv_hds * drv_secs; - } - GDTH_UNLOCK_HA(ha, flags); - if (status != S_OK) - continue; /* next host drive */ - - /* devtype, cluster info, R/W attributes */ - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_DEVTYPE; - gdtcmd.u.cache.DeviceNo = k; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(scp, &gdtcmd, cmnd, 30); - status = (ushort)scp->sr_command->SCp.Status; - info = (ulong32)scp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif - GDTH_LOCK_HA(ha, flags); - ha->hdr[k].devtype = 0; - if (status == S_OK) - ha->hdr[k].devtype = (ushort)info; - GDTH_UNLOCK_HA(ha, flags); - - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_CLUST_INFO; - gdtcmd.u.cache.DeviceNo = k; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(scp, &gdtcmd, cmnd, 30); - status = (ushort)scp->sr_command->SCp.Status; - info = (ulong32)scp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif - GDTH_LOCK_HA(ha, flags); - ha->hdr[k].cluster_type = 0; - if (status == S_OK && !shared_access) - ha->hdr[k].cluster_type = (ushort)info; - GDTH_UNLOCK_HA(ha, flags); - piord->iu.hdr_list[k].cluster_type = ha->hdr[k].cluster_type; - - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_RW_ATTRIBS; - gdtcmd.u.cache.DeviceNo = k; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(scp, &gdtcmd, cmnd, 30); - status = (ushort)scp->sr_command->SCp.Status; - info = (ulong32)scp->sr_command->SCp.Message; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - status = (ushort)scp->SCp.Status; - info = (ulong32)scp->SCp.Message; -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - status = (ushort)scp.SCp.Status; - info = (ulong32)scp.SCp.Message; -#endif - GDTH_LOCK_HA(ha, flags); - ha->hdr[k].rw_attribs = 0; - if (status == S_OK) - ha->hdr[k].rw_attribs = (ushort)info; - GDTH_UNLOCK_HA(ha, flags); - } - break; - - case GDTIOCTL_RESET_DRV: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) - return(-EBUSY); - piord = (gdth_iord_str *)ha->pscratch; - piord->size = sizeof(gdth_iord_str); - piord->status = S_OK; - i = piowr->iu.scsi.target; - if (ha->hdr[i].present) { - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_CLUST_RESET; - gdtcmd.u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(scp, &gdtcmd, cmnd, 30); - piord->status = (ushort)scp->sr_command->SCp.Status; -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - piord->status = (scp->SCp.Message<<16)|scp->SCp.Status; -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - piord->status = (scp.SCp.Message<<16)|scp.SCp.Status; -#endif - } - break; - - default: - return(-EINVAL); - } - return length; -} -#endif - -static int gdth_get_info(char *buffer,char **start,off_t offset, - int length,int hanum,int busnum) +static int gdth_get_info(char *buffer,char **start,off_t offset,int length, + struct Scsi_Host *host,int hanum,int busnum) { int size = 0,len = 0; off_t begin = 0,pos = 0; gdth_ha_str *ha; int id, i, j, k, sec, flag; int no_mdrv = 0, drv_no, is_mirr; - ulong32 cnt, paddr; + ulong32 cnt; + ulong64 paddr; gdth_cmd_str gdtcmd; gdth_evt_str estr; -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) Scsi_Request *scp; Scsi_Device *sdev; -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) Scsi_Cmnd *scp; Scsi_Device *sdev; #else @@ -795,15 +274,15 @@ TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum)); ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x020503 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + sdev = scsi_get_host_dev(host); scp = scsi_allocate_request(sdev, GFP_KERNEL); if (!scp) return -ENOMEM; scp->sr_cmd_len = 12; scp->sr_use_sg = 0; -#elif LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + sdev = scsi_get_host_dev(host); scp = scsi_allocate_device(sdev, 1, FALSE); if (!scp) return -ENOMEM; @@ -812,485 +291,415 @@ #else memset(&sdev,0,sizeof(Scsi_Device)); memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_tab[hanum]; + sdev.host = scp.host = host; sdev.id = scp.target = sdev.host->this_id; scp.device = &sdev; #endif - -#ifdef GDTH_IOCTL_PROC - /* ioctl from tool? */ - if (!gdth_ioctl_check_bin(hanum, (ushort)length)) { -#endif - /* request is i.e. "cat /proc/scsi/gdth/0" */ - /* format: %-15s\t%-10s\t%-15s\t%s */ - /* driver parameters */ - size = sprintf(buffer+len,"Driver Parameters:\n"); - len += size; pos = begin + len; - if (reserve_list[0] == 0xff) - strcpy(hrec, "--"); - else { - sprintf(hrec, "%d", reserve_list[0]); - for (i = 1; i < MAX_RES_ARGS; i++) { - if (reserve_list[i] == 0xff) - break; - sprintf(hrec,"%s,%d", hrec, reserve_list[i]); - } + + + /* request is i.e. "cat /proc/scsi/gdth/0" */ + /* format: %-15s\t%-10s\t%-15s\t%s */ + /* driver parameters */ + size = sprintf(buffer+len,"Driver Parameters:\n"); + len += size; pos = begin + len; + if (reserve_list[0] == 0xff) + strcpy(hrec, "--"); + else { + sprintf(hrec, "%d", reserve_list[0]); + for (i = 1; i < MAX_RES_ARGS; i++) { + if (reserve_list[i] == 0xff) + break; + sprintf(hrec,"%s,%d", hrec, reserve_list[i]); } - size = sprintf(buffer+len, - " reserve_mode: \t%d \treserve_list: \t%s\n", - reserve_mode, hrec); - len += size; pos = begin + len; - size = sprintf(buffer+len, - " max_ids: \t%-3d \thdr_channel: \t%d\n", - max_ids, hdr_channel); - len += size; pos = begin + len; + } + size = sprintf(buffer+len, + " reserve_mode: \t%d \treserve_list: \t%s\n", + reserve_mode, hrec); + len += size; pos = begin + len; + size = sprintf(buffer+len, + " max_ids: \t%-3d \thdr_channel: \t%d\n", + max_ids, hdr_channel); + len += size; pos = begin + len; + + /* controller information */ + size = sprintf(buffer+len,"\nDisk Array Controller Information:\n"); + len += size; pos = begin + len; + if (virt_ctr) + sprintf(hrec, "%s (Bus %d)", ha->binfo.type_string, busnum); + else + strcpy(hrec, ha->binfo.type_string); + size = sprintf(buffer+len, + " Number: \t%d \tName: \t%s\n", + hanum, hrec); + len += size; pos = begin + len; + + if (ha->more_proc) + sprintf(hrec, "%d.%02d.%02d-%c%03X", + (unchar)(ha->binfo.upd_fw_ver>>24), + (unchar)(ha->binfo.upd_fw_ver>>16), + (unchar)(ha->binfo.upd_fw_ver), + ha->bfeat.raid ? 'R':'N', + ha->binfo.upd_revision); + else + sprintf(hrec, "%d.%02d", (unchar)(ha->cpar.version>>8), + (unchar)(ha->cpar.version)); - /* controller information */ - size = sprintf(buffer+len,"\nDisk Array Controller Information:\n"); - len += size; pos = begin + len; - if (virt_ctr) - sprintf(hrec, "%s (Bus %d)", ha->binfo.type_string, busnum); - else - strcpy(hrec, ha->binfo.type_string); + size = sprintf(buffer+len, + " Driver Ver.: \t%-10s\tFirmware Ver.: \t%s\n", + GDTH_VERSION_STR, hrec); + len += size; pos = begin + len; + + if (ha->more_proc) { + /* more information: 1. about controller */ size = sprintf(buffer+len, - " Number: \t%d \tName: \t%s\n", - hanum, hrec); + " Serial No.: \t0x%8X\tCache RAM size:\t%d KB\n", + ha->binfo.ser_no, ha->binfo.memsize / 1024); len += size; pos = begin + len; + } - if (ha->more_proc) - sprintf(hrec, "%d.%02d.%02d-%c%03X", - (unchar)(ha->binfo.upd_fw_ver>>24), - (unchar)(ha->binfo.upd_fw_ver>>16), - (unchar)(ha->binfo.upd_fw_ver), - ha->bfeat.raid ? 'R':'N', - ha->binfo.upd_revision); - else - sprintf(hrec, "%d.%02d", (unchar)(ha->cpar.version>>8), - (unchar)(ha->cpar.version)); +#ifdef GDTH_DMA_STATISTICS + /* controller statistics */ + size = sprintf(buffer+len,"\nController Statistics:\n"); + len += size; pos = begin + len; + size = sprintf(buffer+len, + " 32-bit DMA buffer:\t%lu\t64-bit DMA buffer:\t%lu\n", + ha->dma32_cnt, ha->dma64_cnt); + len += size; pos = begin + len; +#endif - size = sprintf(buffer+len, - " Driver Ver.: \t%-10s\tFirmware Ver.: \t%s\n", - GDTH_VERSION_STR, hrec); + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) + goto stop_output; + + if (ha->more_proc) { + /* more information: 2. about physical devices */ + size = sprintf(buffer+len,"\nPhysical Devices:"); len += size; pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) + flag = FALSE; + + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); + if (!buf) goto stop_output; + for (i = 0; i < ha->bus_cnt; ++i) { + /* 2.a statistics (and retries/reassigns) */ + TRACE2(("pdr_statistics() chn %d\n",i)); + pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4); + gdtcmd.Service = CACHESERVICE; + gdtcmd.OpCode = GDT_IOCTL; + gdtcmd.u.ioctl.p_param = paddr + GDTH_SCRATCH/4; + gdtcmd.u.ioctl.param_size = 3*GDTH_SCRATCH/4; + gdtcmd.u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN; + gdtcmd.u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL; + pds->bid = ha->raw[i].local_no; + pds->first = 0; + pds->entries = ha->raw[i].pdev_cnt; + cnt = (3*GDTH_SCRATCH/4 - 5 * sizeof(ulong32)) / + sizeof(pds->list[0]); + if (pds->entries > cnt) + pds->entries = cnt; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + gdth_do_req(scp, &gdtcmd, cmnd, 30); + if (scp->sr_command->SCp.Status != S_OK) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + gdth_do_cmd(scp, &gdtcmd, cmnd, 30); + if (scp->SCp.Status != S_OK) +#else + gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); + if (scp.SCp.Status != S_OK) +#endif + { + pds->count = 0; + } - if (ha->more_proc) { - /* more information: 1. about controller */ - size = sprintf(buffer+len, - " Serial No.: \t0x%8X\tCache RAM size:\t%d KB\n", - ha->binfo.ser_no, ha->binfo.memsize / 1024); - len += size; pos = begin + len; - - /* 2. about physical devices */ - size = sprintf(buffer+len,"\nPhysical Devices:"); - len += size; pos = begin + len; - flag = FALSE; - - buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); - if (!buf) - goto stop_output; - for (i = 0; i < ha->bus_cnt; ++i) { - /* 2.a statistics (and retries/reassigns) */ - TRACE2(("pdr_statistics() chn %d\n",i)); - pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4); + /* other IOCTLs must fit into area GDTH_SCRATCH/4 */ + for (j = 0; j < ha->raw[i].pdev_cnt; ++j) { + /* 2.b drive info */ + TRACE2(("scsi_drv_info() chn %d dev %d\n", + i, ha->raw[i].id_list[j])); + pdi = (gdth_diskinfo_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; - gdtcmd.u.ioctl.p_param = paddr + GDTH_SCRATCH/4; - gdtcmd.u.ioctl.param_size = 3*GDTH_SCRATCH/4; - gdtcmd.u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN; - gdtcmd.u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL; - pds->bid = ha->raw[i].local_no; - pds->first = 0; - pds->entries = ha->raw[i].pdev_cnt; - cnt = (3*GDTH_SCRATCH/4 - 5 * sizeof(ulong32)) / - sizeof(pds->list[0]); - if (pds->entries > cnt) - pds->entries = cnt; -#if LINUX_VERSION_CODE >= 0x020503 + gdtcmd.u.ioctl.p_param = paddr; + gdtcmd.u.ioctl.param_size = sizeof(gdth_diskinfo_str); + gdtcmd.u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN; + gdtcmd.u.ioctl.channel = + ha->raw[i].address | ha->raw[i].id_list[j]; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) gdth_do_req(scp, &gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status != S_OK) -#elif LINUX_VERSION_CODE >= 0x020322 + if (scp->sr_command->SCp.Status == S_OK) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - if (scp->SCp.Status != S_OK) + if (scp->SCp.Status == S_OK) #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - if (scp.SCp.Status != S_OK) + if (scp.SCp.Status == S_OK) #endif - { - pds->count = 0; + { + strncpy(hrec,pdi->vendor,8); + strncpy(hrec+8,pdi->product,16); + strncpy(hrec+24,pdi->revision,4); + hrec[28] = 0; + size = sprintf(buffer+len, + "\n Chn/ID/LUN: \t%c/%02d/%d \tName: \t%s\n", + 'A'+i,pdi->target_id,pdi->lun,hrec); + len += size; pos = begin + len; + flag = TRUE; + pdi->no_ldrive &= 0xffff; + if (pdi->no_ldrive == 0xffff) + strcpy(hrec,"--"); + else + sprintf(hrec,"%d",pdi->no_ldrive); + size = sprintf(buffer+len, + " Capacity [MB]:\t%-6d \tTo Log. Drive: \t%s\n", + pdi->blkcnt/(1024*1024/pdi->blksize), + hrec); + len += size; pos = begin + len; + } else { + pdi->devtype = 0xff; } - - /* other IOCTLs must fit into area GDTH_SCRATCH/4 */ - for (j = 0; j < ha->raw[i].pdev_cnt; ++j) { - /* 2.b drive info */ - TRACE2(("scsi_drv_info() chn %d dev %d\n", - i, ha->raw[i].id_list[j])); - pdi = (gdth_diskinfo_str *)buf; - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_IOCTL; - gdtcmd.u.ioctl.p_param = paddr; - gdtcmd.u.ioctl.param_size = sizeof(gdth_diskinfo_str); - gdtcmd.u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN; - gdtcmd.u.ioctl.channel = - ha->raw[i].address | ha->raw[i].id_list[j]; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(scp, &gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status == S_OK) -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - if (scp->SCp.Status == S_OK) -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - if (scp.SCp.Status == S_OK) -#endif - { - strncpy(hrec,pdi->vendor,8); - strncpy(hrec+8,pdi->product,16); - strncpy(hrec+24,pdi->revision,4); - hrec[28] = 0; - size = sprintf(buffer+len, - "\n Chn/ID/LUN: \t%c/%02d/%d \tName: \t%s\n", - 'A'+i,pdi->target_id,pdi->lun,hrec); - len += size; pos = begin + len; - flag = TRUE; - pdi->no_ldrive &= 0xffff; - if (pdi->no_ldrive == 0xffff) - strcpy(hrec,"--"); - else - sprintf(hrec,"%d",pdi->no_ldrive); - size = sprintf(buffer+len, - " Capacity [MB]:\t%-6d \tTo Log. Drive: \t%s\n", - pdi->blkcnt/(1024*1024/pdi->blksize), - hrec); - len += size; pos = begin + len; - } else { - pdi->devtype = 0xff; - } - if (pdi->devtype == 0) { - /* search retries/reassigns */ - for (k = 0; k < pds->count; ++k) { - if (pds->list[k].tid == pdi->target_id && - pds->list[k].lun == pdi->lun) { - size = sprintf(buffer+len, - " Retries: \t%-6d \tReassigns: \t%d\n", - pds->list[k].retries, - pds->list[k].reassigns); - len += size; pos = begin + len; - break; - } - } - /* 2.c grown defects */ - TRACE2(("scsi_drv_defcnt() chn %d dev %d\n", - i, ha->raw[i].id_list[j])); - pdef = (gdth_defcnt_str *)buf; - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_IOCTL; - gdtcmd.u.ioctl.p_param = paddr; - gdtcmd.u.ioctl.param_size = sizeof(gdth_defcnt_str); - gdtcmd.u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN; - gdtcmd.u.ioctl.channel = - ha->raw[i].address | ha->raw[i].id_list[j]; - pdef->sddc_type = 0x08; -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(scp, &gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status == S_OK) -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - if (scp->SCp.Status == S_OK) -#else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - if (scp.SCp.Status == S_OK) -#endif - { + if (pdi->devtype == 0) { + /* search retries/reassigns */ + for (k = 0; k < pds->count; ++k) { + if (pds->list[k].tid == pdi->target_id && + pds->list[k].lun == pdi->lun) { size = sprintf(buffer+len, - " Grown Defects:\t%d\n", - pdef->sddc_cnt); + " Retries: \t%-6d \tReassigns: \t%d\n", + pds->list[k].retries, + pds->list[k].reassigns); len += size; pos = begin + len; + break; } } - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; - } - } - gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); - - if (!flag) { - size = sprintf(buffer+len, "\n --\n"); - len += size; pos = begin + len; - } - - /* 3. about logical drives */ - size = sprintf(buffer+len,"\nLogical Drives:"); - len += size; pos = begin + len; - flag = FALSE; - - buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); - if (!buf) - goto stop_output; - for (i = 0; i < MAX_LDRIVES; ++i) { - if (!ha->hdr[i].is_logdrv) - continue; - drv_no = i; - j = k = 0; - is_mirr = FALSE; - do { - /* 3.a log. drive info */ - TRACE2(("cache_drv_info() drive no %d\n",drv_no)); - pcdi = (gdth_cdrinfo_str *)buf; + /* 2.c grown defects */ + TRACE2(("scsi_drv_defcnt() chn %d dev %d\n", + i, ha->raw[i].id_list[j])); + pdef = (gdth_defcnt_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; gdtcmd.u.ioctl.p_param = paddr; - gdtcmd.u.ioctl.param_size = sizeof(gdth_cdrinfo_str); - gdtcmd.u.ioctl.subfunc = CACHE_DRV_INFO; - gdtcmd.u.ioctl.channel = drv_no; -#if LINUX_VERSION_CODE >= 0x020503 + gdtcmd.u.ioctl.param_size = sizeof(gdth_defcnt_str); + gdtcmd.u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN; + gdtcmd.u.ioctl.channel = + ha->raw[i].address | ha->raw[i].id_list[j]; + pdef->sddc_type = 0x08; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) gdth_do_req(scp, &gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status != S_OK) -#elif LINUX_VERSION_CODE >= 0x020322 + if (scp->sr_command->SCp.Status == S_OK) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - if (scp->SCp.Status != S_OK) + if (scp->SCp.Status == S_OK) #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - if (scp.SCp.Status != S_OK) + if (scp.SCp.Status == S_OK) #endif { - break; - } - pcdi->ld_dtype >>= 16; - j++; - if (pcdi->ld_dtype > 2) { - strcpy(hrec, "missing"); - } else if (pcdi->ld_error & 1) { - strcpy(hrec, "fault"); - } else if (pcdi->ld_error & 2) { - strcpy(hrec, "invalid"); - k++; j--; - } else { - strcpy(hrec, "ok"); - } - - if (drv_no == i) { - size = sprintf(buffer+len, - "\n Number: \t%-2d \tStatus: \t%s\n", - drv_no, hrec); - len += size; pos = begin + len; - flag = TRUE; - no_mdrv = pcdi->cd_ldcnt; - if (no_mdrv > 1 || pcdi->ld_slave != -1) { - is_mirr = TRUE; - strcpy(hrec, "RAID-1"); - } else if (pcdi->ld_dtype == 0) { - strcpy(hrec, "Disk"); - } else if (pcdi->ld_dtype == 1) { - strcpy(hrec, "RAID-0"); - } else if (pcdi->ld_dtype == 2) { - strcpy(hrec, "Chain"); - } else { - strcpy(hrec, "???"); - } - size = sprintf(buffer+len, - " Capacity [MB]:\t%-6d \tType: \t%s\n", - pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize), - hrec); - len += size; pos = begin + len; - } else { size = sprintf(buffer+len, - " Slave Number: \t%-2d \tStatus: \t%s\n", - drv_no & 0x7fff, hrec); + " Grown Defects:\t%d\n", + pdef->sddc_cnt); len += size; pos = begin + len; } - drv_no = pcdi->ld_slave; - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; - } while (drv_no != -1); - - if (is_mirr) { - size = sprintf(buffer+len, - " Missing Drv.: \t%-2d \tInvalid Drv.: \t%d\n", - no_mdrv - j - k, k); - len += size; pos = begin + len; } - - if (!ha->hdr[i].is_arraydrv) - strcpy(hrec, "--"); - else - sprintf(hrec, "%d", ha->hdr[i].master_no); - size = sprintf(buffer+len, - " To Array Drv.:\t%s\n", hrec); - len += size; pos = begin + len; if (pos < offset) { len = 0; begin = pos; } if (pos > offset + length) goto stop_output; - } - gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); - - if (!flag) { - size = sprintf(buffer+len, "\n --\n"); - len += size; pos = begin + len; - } + } + } + gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); - /* 4. about array drives */ - size = sprintf(buffer+len,"\nArray Drives:"); + if (!flag) { + size = sprintf(buffer+len, "\n --\n"); len += size; pos = begin + len; - flag = FALSE; + } - buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); - if (!buf) - goto stop_output; - for (i = 0; i < MAX_LDRIVES; ++i) { - if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master)) - continue; - /* 4.a array drive info */ - TRACE2(("array_info() drive no %d\n",i)); - pai = (gdth_arrayinf_str *)buf; + /* 3. about logical drives */ + size = sprintf(buffer+len,"\nLogical Drives:"); + len += size; pos = begin + len; + flag = FALSE; + + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); + if (!buf) + goto stop_output; + for (i = 0; i < MAX_LDRIVES; ++i) { + if (!ha->hdr[i].is_logdrv) + continue; + drv_no = i; + j = k = 0; + is_mirr = FALSE; + do { + /* 3.a log. drive info */ + TRACE2(("cache_drv_info() drive no %d\n",drv_no)); + pcdi = (gdth_cdrinfo_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; gdtcmd.u.ioctl.p_param = paddr; - gdtcmd.u.ioctl.param_size = sizeof(gdth_arrayinf_str); - gdtcmd.u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN; - gdtcmd.u.ioctl.channel = i; -#if LINUX_VERSION_CODE >= 0x020503 + gdtcmd.u.ioctl.param_size = sizeof(gdth_cdrinfo_str); + gdtcmd.u.ioctl.subfunc = CACHE_DRV_INFO; + gdtcmd.u.ioctl.channel = drv_no; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) gdth_do_req(scp, &gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status == S_OK) -#elif LINUX_VERSION_CODE >= 0x020322 + if (scp->sr_command->SCp.Status != S_OK) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - if (scp->SCp.Status == S_OK) + if (scp->SCp.Status != S_OK) #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - if (scp.SCp.Status == S_OK) + if (scp.SCp.Status != S_OK) #endif { - if (pai->ai_state == 0) - strcpy(hrec, "idle"); - else if (pai->ai_state == 2) - strcpy(hrec, "build"); - else if (pai->ai_state == 4) - strcpy(hrec, "ready"); - else if (pai->ai_state == 6) - strcpy(hrec, "fail"); - else if (pai->ai_state == 8 || pai->ai_state == 10) - strcpy(hrec, "rebuild"); - else - strcpy(hrec, "error"); - if (pai->ai_ext_state & 0x10) - strcat(hrec, "/expand"); - else if (pai->ai_ext_state & 0x1) - strcat(hrec, "/patch"); + break; + } + pcdi->ld_dtype >>= 16; + j++; + if (pcdi->ld_dtype > 2) { + strcpy(hrec, "missing"); + } else if (pcdi->ld_error & 1) { + strcpy(hrec, "fault"); + } else if (pcdi->ld_error & 2) { + strcpy(hrec, "invalid"); + k++; j--; + } else { + strcpy(hrec, "ok"); + } + + if (drv_no == i) { size = sprintf(buffer+len, "\n Number: \t%-2d \tStatus: \t%s\n", - i,hrec); + drv_no, hrec); len += size; pos = begin + len; flag = TRUE; - - if (pai->ai_type == 0) + no_mdrv = pcdi->cd_ldcnt; + if (no_mdrv > 1 || pcdi->ld_slave != -1) { + is_mirr = TRUE; + strcpy(hrec, "RAID-1"); + } else if (pcdi->ld_dtype == 0) { + strcpy(hrec, "Disk"); + } else if (pcdi->ld_dtype == 1) { strcpy(hrec, "RAID-0"); - else if (pai->ai_type == 4) - strcpy(hrec, "RAID-4"); - else if (pai->ai_type == 5) - strcpy(hrec, "RAID-5"); - else - strcpy(hrec, "RAID-10"); + } else if (pcdi->ld_dtype == 2) { + strcpy(hrec, "Chain"); + } else { + strcpy(hrec, "???"); + } size = sprintf(buffer+len, " Capacity [MB]:\t%-6d \tType: \t%s\n", - pai->ai_size/(1024*1024/pai->ai_secsize), + pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize), hrec); len += size; pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; + } else { + size = sprintf(buffer+len, + " Slave Number: \t%-2d \tStatus: \t%s\n", + drv_no & 0x7fff, hrec); + len += size; pos = begin + len; } - } - gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); - - if (!flag) { - size = sprintf(buffer+len, "\n --\n"); + drv_no = pcdi->ld_slave; + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) + goto stop_output; + } while (drv_no != -1); + + if (is_mirr) { + size = sprintf(buffer+len, + " Missing Drv.: \t%-2d \tInvalid Drv.: \t%d\n", + no_mdrv - j - k, k); len += size; pos = begin + len; } - - /* 5. about host drives */ - size = sprintf(buffer+len,"\nHost Drives:"); + + if (!ha->hdr[i].is_arraydrv) + strcpy(hrec, "--"); + else + sprintf(hrec, "%d", ha->hdr[i].master_no); + size = sprintf(buffer+len, + " To Array Drv.:\t%s\n", hrec); len += size; pos = begin + len; - flag = FALSE; - - buf = gdth_ioctl_alloc(hanum, sizeof(gdth_hget_str), FALSE, &paddr); - if (!buf) + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) goto stop_output; - for (i = 0; i < MAX_LDRIVES; ++i) { - if (!ha->hdr[i].is_logdrv || - (ha->hdr[i].is_arraydrv && !ha->hdr[i].is_master)) - continue; - /* 5.a get host drive list */ - TRACE2(("host_get() drv_no %d\n",i)); - phg = (gdth_hget_str *)buf; - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_IOCTL; - gdtcmd.u.ioctl.p_param = paddr; - gdtcmd.u.ioctl.param_size = sizeof(gdth_hget_str); - gdtcmd.u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN; - gdtcmd.u.ioctl.channel = i; - phg->entries = MAX_HDRIVES; - phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]); -#if LINUX_VERSION_CODE >= 0x020503 - gdth_do_req(scp, &gdtcmd, cmnd, 30); - if (scp->sr_command->SCp.Status != S_OK) -#elif LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &gdtcmd, cmnd, 30); - if (scp->SCp.Status != S_OK) + } + gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); + + if (!flag) { + size = sprintf(buffer+len, "\n --\n"); + len += size; pos = begin + len; + } + + /* 4. about array drives */ + size = sprintf(buffer+len,"\nArray Drives:"); + len += size; pos = begin + len; + flag = FALSE; + + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); + if (!buf) + goto stop_output; + for (i = 0; i < MAX_LDRIVES; ++i) { + if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master)) + continue; + /* 4.a array drive info */ + TRACE2(("array_info() drive no %d\n",i)); + pai = (gdth_arrayinf_str *)buf; + gdtcmd.Service = CACHESERVICE; + gdtcmd.OpCode = GDT_IOCTL; + gdtcmd.u.ioctl.p_param = paddr; + gdtcmd.u.ioctl.param_size = sizeof(gdth_arrayinf_str); + gdtcmd.u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN; + gdtcmd.u.ioctl.channel = i; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + gdth_do_req(scp, &gdtcmd, cmnd, 30); + if (scp->sr_command->SCp.Status == S_OK) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + gdth_do_cmd(scp, &gdtcmd, cmnd, 30); + if (scp->SCp.Status == S_OK) #else - gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); - if (scp.SCp.Status != S_OK) + gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); + if (scp.SCp.Status == S_OK) #endif - { - ha->hdr[i].ldr_no = i; - ha->hdr[i].rw_attribs = 0; - ha->hdr[i].start_sec = 0; - } else { - for (j = 0; j < phg->entries; ++j) { - k = phg->entry[j].host_drive; - if (k >= MAX_LDRIVES) - continue; - ha->hdr[k].ldr_no = phg->entry[j].log_drive; - ha->hdr[k].rw_attribs = phg->entry[j].rw_attribs; - ha->hdr[k].start_sec = phg->entry[j].start_sec; - } - } - } - gdth_ioctl_free(hanum, sizeof(gdth_hget_str), buf, paddr); - - for (i = 0; i < MAX_HDRIVES; ++i) { - if (!(ha->hdr[i].present)) - continue; - + { + if (pai->ai_state == 0) + strcpy(hrec, "idle"); + else if (pai->ai_state == 2) + strcpy(hrec, "build"); + else if (pai->ai_state == 4) + strcpy(hrec, "ready"); + else if (pai->ai_state == 6) + strcpy(hrec, "fail"); + else if (pai->ai_state == 8 || pai->ai_state == 10) + strcpy(hrec, "rebuild"); + else + strcpy(hrec, "error"); + if (pai->ai_ext_state & 0x10) + strcat(hrec, "/expand"); + else if (pai->ai_ext_state & 0x1) + strcat(hrec, "/patch"); size = sprintf(buffer+len, - "\n Number: \t%-2d \tArr/Log. Drive:\t%d\n", - i, ha->hdr[i].ldr_no); + "\n Number: \t%-2d \tStatus: \t%s\n", + i,hrec); len += size; pos = begin + len; flag = TRUE; + if (pai->ai_type == 0) + strcpy(hrec, "RAID-0"); + else if (pai->ai_type == 4) + strcpy(hrec, "RAID-4"); + else if (pai->ai_type == 5) + strcpy(hrec, "RAID-5"); + else + strcpy(hrec, "RAID-10"); size = sprintf(buffer+len, - " Capacity [MB]:\t%-6d \tStart Sector: \t%d\n", - ha->hdr[i].size/2048, ha->hdr[i].start_sec); + " Capacity [MB]:\t%-6d \tType: \t%s\n", + pai->ai_size/(1024*1024/pai->ai_secsize), + hrec); len += size; pos = begin + len; if (pos < offset) { len = 0; @@ -1299,60 +708,125 @@ if (pos > offset + length) goto stop_output; } + } + gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); - if (!flag) { - size = sprintf(buffer+len, "\n --\n"); - len += size; pos = begin + len; - } + if (!flag) { + size = sprintf(buffer+len, "\n --\n"); + len += size; pos = begin + len; } - /* controller events */ - size = sprintf(buffer+len,"\nController Events:\n"); + /* 5. about host drives */ + size = sprintf(buffer+len,"\nHost Drives:"); len += size; pos = begin + len; + flag = FALSE; - for (id = -1;;) { - id = gdth_read_event(ha, id, &estr); - if (estr.event_source == 0) - break; - if (estr.event_data.eu.driver.ionode == hanum && - estr.event_source == ES_ASYNC) { - gdth_log_event(&estr.event_data, hrec); - do_gettimeofday(&tv); - sec = (int)(tv.tv_sec - estr.first_stamp); - if (sec < 0) sec = 0; - size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n", - sec/3600, sec%3600/60, sec%60, hrec); - len += size; pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; + buf = gdth_ioctl_alloc(hanum, sizeof(gdth_hget_str), FALSE, &paddr); + if (!buf) + goto stop_output; + for (i = 0; i < MAX_LDRIVES; ++i) { + if (!ha->hdr[i].is_logdrv || + (ha->hdr[i].is_arraydrv && !ha->hdr[i].is_master)) + continue; + /* 5.a get host drive list */ + TRACE2(("host_get() drv_no %d\n",i)); + phg = (gdth_hget_str *)buf; + gdtcmd.Service = CACHESERVICE; + gdtcmd.OpCode = GDT_IOCTL; + gdtcmd.u.ioctl.p_param = paddr; + gdtcmd.u.ioctl.param_size = sizeof(gdth_hget_str); + gdtcmd.u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN; + gdtcmd.u.ioctl.channel = i; + phg->entries = MAX_HDRIVES; + phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + gdth_do_req(scp, &gdtcmd, cmnd, 30); + if (scp->sr_command->SCp.Status != S_OK) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + gdth_do_cmd(scp, &gdtcmd, cmnd, 30); + if (scp->SCp.Status != S_OK) +#else + gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); + if (scp.SCp.Status != S_OK) +#endif + { + ha->hdr[i].ldr_no = i; + ha->hdr[i].rw_attribs = 0; + ha->hdr[i].start_sec = 0; + } else { + for (j = 0; j < phg->entries; ++j) { + k = phg->entry[j].host_drive; + if (k >= MAX_LDRIVES) + continue; + ha->hdr[k].ldr_no = phg->entry[j].log_drive; + ha->hdr[k].rw_attribs = phg->entry[j].rw_attribs; + ha->hdr[k].start_sec = phg->entry[j].start_sec; } - if (pos > offset + length) - goto stop_output; } - if (id == -1) - break; } -#ifdef GDTH_IOCTL_PROC - } else { - gdth_iord_str *piord; + gdth_ioctl_free(hanum, sizeof(gdth_hget_str), buf, paddr); - /* request from tool (GDTMON,..) */ - piord = (gdth_iord_str *)ha->pscratch; - if (piord == NULL) - goto stop_output; - length = piord->size; - memcpy(buffer+len, (char *)piord, length); - gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr); - len = length; + for (i = 0; i < MAX_HDRIVES; ++i) { + if (!(ha->hdr[i].present)) + continue; + + size = sprintf(buffer+len, + "\n Number: \t%-2d \tArr/Log. Drive:\t%d\n", + i, ha->hdr[i].ldr_no); + len += size; pos = begin + len; + flag = TRUE; + + size = sprintf(buffer+len, + " Capacity [MB]:\t%-6d \tStart Sector: \t%d\n", + (ulong32)(ha->hdr[i].size/2048), ha->hdr[i].start_sec); + len += size; pos = begin + len; + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) + goto stop_output; + } + + if (!flag) { + size = sprintf(buffer+len, "\n --\n"); + len += size; pos = begin + len; + } + } + + /* controller events */ + size = sprintf(buffer+len,"\nController Events:\n"); + len += size; pos = begin + len; + + for (id = -1;;) { + id = gdth_read_event(ha, id, &estr); + if (estr.event_source == 0) + break; + if (estr.event_data.eu.driver.ionode == hanum && + estr.event_source == ES_ASYNC) { + gdth_log_event(&estr.event_data, hrec); + do_gettimeofday(&tv); + sec = (int)(tv.tv_sec - estr.first_stamp); + if (sec < 0) sec = 0; + size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n", + sec/3600, sec%3600/60, sec%60, hrec); + len += size; pos = begin + len; + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) + goto stop_output; + } + if (id == -1) + break; } -#endif stop_output: -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) scsi_release_request(scp); scsi_free_host_dev(sdev); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) scsi_release_command(scp); scsi_free_host_dev(sdev); #endif @@ -1365,7 +839,8 @@ return(len); } -#if LINUX_VERSION_CODE >= 0x020503 + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static void gdth_do_req(Scsi_Request *scp, gdth_cmd_str *gdtcmd, char *cmnd, int timeout) { @@ -1389,9 +864,9 @@ char *cmnd, int timeout) { unsigned bufflen; -#if LINUX_VERSION_CODE >= 0x020407 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) DECLARE_COMPLETION(wait); -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) DECLARE_MUTEX_LOCKED(sem); #else struct semaphore sem = MUTEX_LOCKED; @@ -1405,19 +880,19 @@ scp->SCp.this_residual = DEFAULT_PRI; bufflen = 0; } -#if LINUX_VERSION_CODE >= 0x020407 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) scp->request.rq_status = RQ_SCSI_BUSY; scp->request.waiting = &wait; scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); wait_for_completion(&wait); #else scp->request.sem = &sem; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); #else - GDTH_LOCK_SCSI_DOCMD(); + spin_lock_irq(&io_request_lock); scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); - GDTH_UNLOCK_SCSI_DOCMD(); + spin_unlock_irq(&io_request_lock); #endif down(&sem); #endif @@ -1428,11 +903,11 @@ { TRACE2(("gdth_scsi_done()\n")); -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) scp->request->rq_status = RQ_SCSI_DONE; if (scp->request->waiting != NULL) complete(scp->request->waiting); -#elif LINUX_VERSION_CODE >= 0x020407 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) scp->request.rq_status = RQ_SCSI_DONE; if (scp->request.waiting != NULL) complete(scp->request.waiting); @@ -1444,7 +919,7 @@ } static char *gdth_ioctl_alloc(int hanum, int size, int scratch, - ulong32 *paddr) + ulong64 *paddr) { gdth_ha_str *ha; ulong flags; @@ -1463,11 +938,11 @@ } else if (scratch) { ret_val = NULL; } else { -#if LINUX_VERSION_CODE >= 0x020400 - dma_addr_t dma_addr; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + dma_addr_t dma_addr; ret_val = pci_alloc_consistent(ha->pdev, size, &dma_addr); - *paddr = (ulong32)dma_addr; + *paddr = dma_addr; #else ret_val = scsi_init_malloc(size, GFP_ATOMIC | GFP_DMA); if (ret_val) @@ -1479,7 +954,7 @@ return ret_val; } -static void gdth_ioctl_free(int hanum, int size, char *buf, ulong32 paddr) +static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr) { gdth_ha_str *ha; ulong flags; @@ -1490,7 +965,7 @@ if (buf == ha->pscratch) { ha->scratch_busy = FALSE; } else { -#if LINUX_VERSION_CODE >= 0x020400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_free_consistent(ha->pdev, size, buf, paddr); #else scsi_init_free((void *)buf, size); @@ -1533,7 +1008,7 @@ for (i = 0; i < GDTH_MAXCMDS; ++i) { scp = ha->cmd_tab[i].cmnd; -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; #else @@ -1546,14 +1021,10 @@ GDTH_UNLOCK_HA(ha, flags); while (!scp->SCp.have_data_in) barrier(); -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) GDTH_LOCK_SCSI_DONE(scp->device->host, flags); scp->scsi_done(scp); GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags); -#elif LINUX_VERSION_CODE >= 0x020503 - GDTH_LOCK_SCSI_DONE(scp->host, flags); - scp->scsi_done(scp); - GDTH_UNLOCK_SCSI_DONE(scp->host, flags); #else GDTH_LOCK_SCSI_DONE(flags); scp->scsi_done(scp); @@ -1576,7 +1047,7 @@ GDTH_LOCK_HA(ha, flags); for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; #else @@ -1602,7 +1073,7 @@ GDTH_LOCK_HA(ha, flags); for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { -#if LINUX_VERSION_CODE >= 0x02053C +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; #else @@ -1624,7 +1095,6 @@ oldto = scp->timeout_per_command; scp->timeout_per_command = timeout; -#if LINUX_VERSION_CODE >= 0x02014B if (timeout == 0) { del_timer(&scp->eh_timeout); scp->eh_timeout.data = (unsigned long) NULL; @@ -1636,17 +1106,6 @@ scp->eh_timeout.expires = jiffies + timeout; add_timer(&scp->eh_timeout); } -#else - if (timeout > 0) { - if (timer_table[SCSI_TIMER].expires == 0) { - timer_table[SCSI_TIMER].expires = jiffies + timeout; - timer_active |= 1 << SCSI_TIMER; - } else { - if (jiffies + timeout < timer_table[SCSI_TIMER].expires) - timer_table[SCSI_TIMER].expires = jiffies + timeout; - } - } -#endif return oldto; } --- diff/drivers/scsi/gdth_proc.h 2004-05-19 22:12:09.000000000 +0100 +++ source/drivers/scsi/gdth_proc.h 2004-05-27 18:34:18.000000000 +0100 @@ -2,42 +2,31 @@ #define _GDTH_PROC_H /* gdth_proc.h - * $Id: gdth_proc.h,v 1.14 2003/08/27 11:37:35 achim Exp $ + * $Id: gdth_proc.h,v 1.16 2004/01/14 13:09:01 achim Exp $ */ -static int gdth_set_info(char *buffer,int length,int hanum,int busnum); -static int gdth_get_info(char *buffer,char **start,off_t offset, - int length,int hanum,int busnum); +static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host, + int hanum,int busnum); +static int gdth_get_info(char *buffer,char **start,off_t offset,int length, + struct Scsi_Host *host,int hanum,int busnum); -#if LINUX_VERSION_CODE >= 0x020503 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static void gdth_do_req(Scsi_Request *srp, gdth_cmd_str *cmd, char *cmnd, int timeout); static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp); -#ifdef GDTH_IOCTL_PROC -static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Request *scp); -#endif -#elif LINUX_VERSION_CODE >= 0x020322 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd, char *cmnd, int timeout); static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp); -#ifdef GDTH_IOCTL_PROC -static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp); -#endif #else static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd, char *cmnd, int timeout); static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp); -#ifdef GDTH_IOCTL_PROC -static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp); -#endif #endif static char *gdth_ioctl_alloc(int hanum, int size, int scratch, - ulong32 *paddr); -static void gdth_ioctl_free(int hanum, int size, char *buf, ulong32 paddr); -#ifdef GDTH_IOCTL_PROC -static int gdth_ioctl_check_bin(int hanum, ushort size); -#endif + ulong64 *paddr); +static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr); static void gdth_wait_completion(int hanum, int busnum, int id); static void gdth_stop_timeout(int hanum, int busnum, int id); static void gdth_start_timeout(int hanum, int busnum, int id); --- diff/drivers/scsi/ipr.c 2004-05-27 13:41:20.000000000 +0100 +++ source/drivers/scsi/ipr.c 2004-05-27 18:34:18.000000000 +0100 @@ -406,7 +406,7 @@ trace_entry->type = type; trace_entry->cmd_index = ipr_cmd->cmd_index; trace_entry->res_handle = ipr_cmd->ioarcb.res_handle; - trace_entry->add_data = add_data; + trace_entry->u.add_data = add_data; } #else #define ipr_trc_hook(ipr_cmd, type, add_data) do { } while(0) @@ -447,7 +447,7 @@ static void ipr_init_ipr_cmnd(struct ipr_cmnd *ipr_cmd) { ipr_reinit_ipr_cmnd(ipr_cmd); - ipr_cmd->scratch = 0; + ipr_cmd->u.scratch = 0; init_timer(&ipr_cmd->timer); } @@ -676,8 +676,8 @@ **/ static void ipr_internal_cmd_done(struct ipr_cmnd *ipr_cmd) { - if (ipr_cmd->sibling) - ipr_cmd->sibling = NULL; + if (ipr_cmd->u.sibling) + ipr_cmd->u.sibling = NULL; else complete(&ipr_cmd->completion); } @@ -729,20 +729,20 @@ list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q); list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_pending_q); - ipr_cmd->hostrcb = hostrcb; + ipr_cmd->u.hostrcb = hostrcb; ioarcb = &ipr_cmd->ioarcb; ioarcb->res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE); ioarcb->cmd_pkt.request_type = IPR_RQTYPE_HCAM; ioarcb->cmd_pkt.cdb[0] = IPR_HOST_CONTROLLED_ASYNC; ioarcb->cmd_pkt.cdb[1] = type; - ioarcb->cmd_pkt.cdb[7] = (IPR_HOSTRCB_SZ >> 8) & 0xff; - ioarcb->cmd_pkt.cdb[8] = IPR_HOSTRCB_SZ & 0xff; + ioarcb->cmd_pkt.cdb[7] = (sizeof(hostrcb->hcam) >> 8) & 0xff; + ioarcb->cmd_pkt.cdb[8] = sizeof(hostrcb->hcam) & 0xff; - ioarcb->read_data_transfer_length = cpu_to_be32(IPR_HOSTRCB_SZ); + ioarcb->read_data_transfer_length = cpu_to_be32(sizeof(hostrcb->hcam)); ioarcb->read_ioadl_len = cpu_to_be32(sizeof(struct ipr_ioadl_desc)); ipr_cmd->ioadl[0].flags_and_data_len = - cpu_to_be32(IPR_IOADL_FLAGS_READ_LAST | IPR_HOSTRCB_SZ); + cpu_to_be32(IPR_IOADL_FLAGS_READ_LAST | sizeof(hostrcb->hcam)); ipr_cmd->ioadl[0].address = cpu_to_be32(hostrcb->hostrcb_dma); if (type == IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE) @@ -794,7 +794,7 @@ struct ipr_config_table_entry *cfgte; u32 is_ndn = 1; - cfgte = &hostrcb->ccn.cfgte; + cfgte = &hostrcb->hcam.u.ccn.cfgte; list_for_each_entry(res, &ioa_cfg->used_res_q, queue) { if (!memcmp(&res->cfgte.res_addr, &cfgte->res_addr, @@ -822,7 +822,7 @@ memcpy(&res->cfgte, cfgte, sizeof(struct ipr_config_table_entry)); - if (hostrcb->notify_type == IPR_HOST_RCB_NOTIF_TYPE_REM_ENTRY) { + if (hostrcb->hcam.notify_type == IPR_HOST_RCB_NOTIF_TYPE_REM_ENTRY) { if (res->sdev) { res->sdev->hostdata = NULL; res->del_from_ml = 1; @@ -852,7 +852,7 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd) { struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; - struct ipr_hostrcb *hostrcb = ipr_cmd->hostrcb; + struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); list_del(&hostrcb->queue); @@ -902,7 +902,8 @@ static void ipr_log_cache_error(struct ipr_ioa_cfg *ioa_cfg, struct ipr_hostrcb *hostrcb) { - struct ipr_hostrcb_type_02_error *error = &hostrcb->error.type_02_error; + struct ipr_hostrcb_type_02_error *error = + &hostrcb->hcam.u.error.u.type_02_error; ipr_err("-----Current Configuration-----\n"); ipr_err("Cache Directory Card Information:\n"); @@ -937,14 +938,15 @@ { int errors_logged, i; struct ipr_hostrcb_device_data_entry *dev_entry; + struct ipr_hostrcb_type_03_error *error; - errors_logged = be32_to_cpu(hostrcb->error.type_03_error.errors_logged); + error = &hostrcb->hcam.u.error.u.type_03_error; + errors_logged = be32_to_cpu(error->errors_logged); ipr_err("Device Errors Detected/Logged: %d/%d\n", - be32_to_cpu(hostrcb->error.type_03_error.errors_detected), - errors_logged); + be32_to_cpu(error->errors_detected), errors_logged); - dev_entry = hostrcb->error.type_03_error.dev_entry; + dev_entry = error->dev_entry; for (i = 0; i < errors_logged; i++, dev_entry++) { ipr_err_separator; @@ -996,7 +998,7 @@ memset(zero_sn, '0', IPR_SERIAL_NUM_LEN); - error = &hostrcb->error.type_04_error; + error = &hostrcb->hcam.u.error.u.type_04_error; ipr_err_separator; @@ -1064,7 +1066,7 @@ struct ipr_hostrcb *hostrcb) { int i; - int ioa_data_len = be32_to_cpu(hostrcb->length); + int ioa_data_len = be32_to_cpu(hostrcb->hcam.length); if (ioa_data_len == 0) return; @@ -1074,10 +1076,10 @@ for (i = 0; i < ioa_data_len / 4; i += 4) { ipr_err("%08X: %08X %08X %08X %08X\n", i*4, - be32_to_cpu(hostrcb->raw.data[i]), - be32_to_cpu(hostrcb->raw.data[i+1]), - be32_to_cpu(hostrcb->raw.data[i+2]), - be32_to_cpu(hostrcb->raw.data[i+3])); + be32_to_cpu(hostrcb->hcam.u.raw.data[i]), + be32_to_cpu(hostrcb->hcam.u.raw.data[i+1]), + be32_to_cpu(hostrcb->hcam.u.raw.data[i+2]), + be32_to_cpu(hostrcb->hcam.u.raw.data[i+3])); } } @@ -1119,19 +1121,19 @@ u32 ioasc; int error_index; - if (hostrcb->notify_type != IPR_HOST_RCB_NOTIF_TYPE_ERROR_LOG_ENTRY) + if (hostrcb->hcam.notify_type != IPR_HOST_RCB_NOTIF_TYPE_ERROR_LOG_ENTRY) return; - if (hostrcb->notifications_lost == IPR_HOST_RCB_NOTIFICATIONS_LOST) + if (hostrcb->hcam.notifications_lost == IPR_HOST_RCB_NOTIFICATIONS_LOST) dev_err(&ioa_cfg->pdev->dev, "Error notifications lost\n"); - ioasc = be32_to_cpu(hostrcb->error.failing_dev_ioasc); + ioasc = be32_to_cpu(hostrcb->hcam.u.error.failing_dev_ioasc); if (ioasc == IPR_IOASC_BUS_WAS_RESET || ioasc == IPR_IOASC_BUS_WAS_RESET_BY_OTHER) { /* Tell the midlayer we had a bus reset so it will handle the UA properly */ scsi_report_bus_reset(ioa_cfg->host, - hostrcb->error.failing_dev_res_addr.bus); + hostrcb->hcam.u.error.failing_dev_res_addr.bus); } error_index = ipr_get_error(ioasc); @@ -1139,8 +1141,8 @@ if (!ipr_error_table[error_index].log_hcam) return; - if (ipr_is_device(&hostrcb->error.failing_dev_res_addr)) { - ipr_res_err(ioa_cfg, hostrcb->error.failing_dev_res_addr, + if (ipr_is_device(&hostrcb->hcam.u.error.failing_dev_res_addr)) { + ipr_res_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr, "%s\n", ipr_error_table[error_index].error); } else { dev_err(&ioa_cfg->pdev->dev, "%s\n", @@ -1153,7 +1155,7 @@ if (ioa_cfg->log_level < IPR_DEFAULT_LOG_LEVEL) return; - switch (hostrcb->overlay_id) { + switch (hostrcb->hcam.overlay_id) { case IPR_HOST_RCB_OVERLAY_ID_1: ipr_log_generic_error(ioa_cfg, hostrcb); break; @@ -1173,7 +1175,7 @@ default: dev_err(&ioa_cfg->pdev->dev, "Unknown error received. Overlay ID: %d\n", - hostrcb->overlay_id); + hostrcb->hcam.overlay_id); break; } } @@ -1192,7 +1194,7 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd) { struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; - struct ipr_hostrcb *hostrcb = ipr_cmd->hostrcb; + struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); list_del(&hostrcb->queue); @@ -2972,6 +2974,7 @@ cmd_pkt->request_type = IPR_RQTYPE_IOACMD; cmd_pkt->cdb[0] = IPR_RESET_DEVICE; + ipr_sdev_err(scsi_cmd->device, "Resetting device\n"); ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT); ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); @@ -3011,10 +3014,10 @@ * If abort has not completed, indicate the reset has, else call the * abort's done function to wake the sleeping eh thread */ - if (ipr_cmd->sibling->sibling) - ipr_cmd->sibling->sibling = NULL; + if (ipr_cmd->u.sibling->u.sibling) + ipr_cmd->u.sibling->u.sibling = NULL; else - ipr_cmd->sibling->done(ipr_cmd->sibling); + ipr_cmd->u.sibling->done(ipr_cmd->u.sibling); list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); LEAVE; @@ -3045,9 +3048,10 @@ return; } + ipr_sdev_err(ipr_cmd->u.sdev, "Abort timed out. Resetting bus\n"); reset_cmd = ipr_get_free_ipr_cmnd(ioa_cfg); - ipr_cmd->sibling = reset_cmd; - reset_cmd->sibling = ipr_cmd; + ipr_cmd->u.sibling = reset_cmd; + reset_cmd->u.sibling = ipr_cmd; reset_cmd->ioarcb.res_handle = ipr_cmd->ioarcb.res_handle; cmd_pkt = &reset_cmd->ioarcb.cmd_pkt; cmd_pkt->request_type = IPR_RQTYPE_IOACMD; @@ -3106,7 +3110,9 @@ cmd_pkt->cdb[3] = (ioarcb_addr >> 16) & 0xff; cmd_pkt->cdb[4] = (ioarcb_addr >> 8) & 0xff; cmd_pkt->cdb[5] = ioarcb_addr & 0xff; + ipr_cmd->u.sdev = scsi_cmd->device; + ipr_sdev_err(scsi_cmd->device, "Aborting command: %02X\n", scsi_cmd->cmnd[0]); ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_ABORT_TASK_TIMEOUT); ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); @@ -3175,6 +3181,7 @@ writel(IPR_PCII_IOA_TRANS_TO_OPER, ioa_cfg->regs.clr_interrupt_reg); int_reg = readl(ioa_cfg->regs.sense_interrupt_reg); + list_del(&ioa_cfg->reset_cmd->queue); del_timer(&ioa_cfg->reset_cmd->timer); ipr_reset_ioa_job(ioa_cfg->reset_cmd); } else { @@ -3570,12 +3577,12 @@ ipr_sdev_err(ipr_cmd->scsi_cmd->device, "%s\n", ipr_error_table[error_index].error); - if ((ioasa->gpdd.device_end_state <= ARRAY_SIZE(ipr_gpdd_dev_end_states)) && - (ioasa->gpdd.device_bus_phase <= ARRAY_SIZE(ipr_gpdd_dev_bus_phases))) { + if ((ioasa->u.gpdd.end_state <= ARRAY_SIZE(ipr_gpdd_dev_end_states)) && + (ioasa->u.gpdd.bus_phase <= ARRAY_SIZE(ipr_gpdd_dev_bus_phases))) { ipr_sdev_err(ipr_cmd->scsi_cmd->device, "Device End state: %s Phase: %s\n", - ipr_gpdd_dev_end_states[ioasa->gpdd.device_end_state], - ipr_gpdd_dev_bus_phases[ioasa->gpdd.device_bus_phase]); + ipr_gpdd_dev_end_states[ioasa->u.gpdd.end_state], + ipr_gpdd_dev_bus_phases[ioasa->u.gpdd.bus_phase]); } if (sizeof(struct ipr_ioasa) < be16_to_cpu(ioasa->ret_stat_len)) @@ -3619,7 +3626,7 @@ if (ipr_is_vset_device(res) && ioasc == IPR_IOASC_MED_DO_NOT_REALLOC && - ioasa->vset.failing_lba_hi != 0) { + ioasa->u.vset.failing_lba_hi != 0) { sense_buf[0] = 0x72; sense_buf[1] = IPR_IOASC_SENSE_KEY(ioasc); sense_buf[2] = IPR_IOASC_SENSE_CODE(ioasc); @@ -3630,14 +3637,14 @@ sense_buf[9] = 0x0A; sense_buf[10] = 0x80; - failing_lba = be32_to_cpu(ioasa->vset.failing_lba_hi); + failing_lba = be32_to_cpu(ioasa->u.vset.failing_lba_hi); sense_buf[12] = (failing_lba & 0xff000000) >> 24; sense_buf[13] = (failing_lba & 0x00ff0000) >> 16; sense_buf[14] = (failing_lba & 0x0000ff00) >> 8; sense_buf[15] = failing_lba & 0x000000ff; - failing_lba = be32_to_cpu(ioasa->vset.failing_lba_lo); + failing_lba = be32_to_cpu(ioasa->u.vset.failing_lba_lo); sense_buf[16] = (failing_lba & 0xff000000) >> 24; sense_buf[17] = (failing_lba & 0x00ff0000) >> 16; @@ -3669,9 +3676,9 @@ } else { if (ioasc == IPR_IOASC_MED_DO_NOT_REALLOC) { if (ipr_is_vset_device(res)) - failing_lba = be32_to_cpu(ioasa->vset.failing_lba_lo); + failing_lba = be32_to_cpu(ioasa->u.vset.failing_lba_lo); else - failing_lba = be32_to_cpu(ioasa->dasd.failing_lba); + failing_lba = be32_to_cpu(ioasa->u.dasd.failing_lba); sense_buf[0] |= 0x80; /* Or in the Valid bit */ sense_buf[3] = (failing_lba & 0xff000000) >> 24; @@ -4118,7 +4125,7 @@ struct ipr_supported_device *supp_dev = &ioa_cfg->vpd_cbs->supp_dev; struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl; struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; - struct ipr_resource_entry *res = ipr_cmd->res; + struct ipr_resource_entry *res = ipr_cmd->u.res; ipr_cmd->job_step = ipr_ioa_reset_done; @@ -4126,7 +4133,7 @@ if (!ipr_is_af_dasd_device(res)) continue; - ipr_cmd->res = res; + ipr_cmd->u.res = res; ipr_set_sup_dev_dflt(supp_dev, &res->cfgte.std_inq_data.vpids); ioarcb->res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE); @@ -4367,8 +4374,8 @@ length); ipr_cmd->job_step = ipr_set_supported_devs; - ipr_cmd->res = list_entry(ioa_cfg->used_res_q.next, - struct ipr_resource_entry, queue); + ipr_cmd->u.res = list_entry(ioa_cfg->used_res_q.next, + struct ipr_resource_entry, queue); ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, IPR_INTERNAL_TIMEOUT); @@ -4802,6 +4809,7 @@ ipr_cmd->timer.expires = jiffies + IPR_OPERATIONAL_TIMEOUT; ipr_cmd->timer.function = (void (*)(unsigned long))ipr_timeout; add_timer(&ipr_cmd->timer); + list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q); LEAVE; return IPR_RC_JOB_RETURN; @@ -4886,12 +4894,12 @@ hostrcb = list_entry(ioa_cfg->hostrcb_free_q.next, struct ipr_hostrcb, queue); list_del(&hostrcb->queue); - memset(hostrcb, 0, IPR_HOSTRCB_SZ); + memset(&hostrcb->hcam, 0, sizeof(hostrcb->hcam)); rc = ipr_get_ldump_data_section(ioa_cfg, be32_to_cpu(sdt.entry[0].bar_str_offset), - (u32 *)hostrcb, - min(length, (int)IPR_HOSTRCB_SZ) / sizeof(u32)); + (u32 *)&hostrcb->hcam, + min(length, (int)sizeof(hostrcb->hcam)) / sizeof(u32)); if (!rc) ipr_handle_log_data(ioa_cfg, hostrcb); @@ -5022,8 +5030,8 @@ struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; int rc = IPR_RC_JOB_RETURN; - if (!ipr_reset_allowed(ioa_cfg) && ipr_cmd->time_left) { - ipr_cmd->time_left -= IPR_CHECK_FOR_RESET_TIMEOUT; + if (!ipr_reset_allowed(ioa_cfg) && ipr_cmd->u.time_left) { + ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT; ipr_reset_start_timer(ipr_cmd, IPR_CHECK_FOR_RESET_TIMEOUT); } else { ipr_cmd->job_step = ipr_reset_start_bist; @@ -5062,7 +5070,7 @@ ipr_cmd->job_step = ipr_reset_start_bist; } - ipr_cmd->time_left = IPR_WAIT_FOR_RESET_TIMEOUT; + ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT; ipr_reset_start_timer(ipr_cmd, IPR_CHECK_FOR_RESET_TIMEOUT); LEAVE; @@ -5148,7 +5156,7 @@ static int ipr_reset_shutdown_ioa(struct ipr_cmnd *ipr_cmd) { struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; - enum ipr_shutdown_type shutdown_type = ipr_cmd->shutdown_type; + enum ipr_shutdown_type shutdown_type = ipr_cmd->u.shutdown_type; unsigned long timeout; int rc = IPR_RC_JOB_CONTINUE; @@ -5189,7 +5197,7 @@ static void ipr_reset_ioa_job(struct ipr_cmnd *ipr_cmd) { u32 rc, ioasc; - unsigned long scratch = ipr_cmd->scratch; + unsigned long scratch = ipr_cmd->u.scratch; struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; do { @@ -5215,7 +5223,7 @@ } ipr_reinit_ipr_cmnd(ipr_cmd); - ipr_cmd->scratch = scratch; + ipr_cmd->u.scratch = scratch; rc = ipr_cmd->job_step(ipr_cmd); } while(rc == IPR_RC_JOB_CONTINUE); } @@ -5247,7 +5255,7 @@ ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg); ioa_cfg->reset_cmd = ipr_cmd; ipr_cmd->job_step = job_step; - ipr_cmd->shutdown_type = shutdown_type; + ipr_cmd->u.shutdown_type = shutdown_type; ipr_reset_ioa_job(ipr_cmd); } @@ -5531,7 +5539,8 @@ goto cleanup; memset(ioa_cfg->hostrcb[i], 0, sizeof(struct ipr_hostrcb)); - ioa_cfg->hostrcb[i]->hostrcb_dma = ioa_cfg->hostrcb_dma[i]; + ioa_cfg->hostrcb[i]->hostrcb_dma = + ioa_cfg->hostrcb_dma[i] + offsetof(struct ipr_hostrcb, hcam); list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q); } --- diff/drivers/scsi/ipr.h 2004-05-27 13:41:20.000000000 +0100 +++ source/drivers/scsi/ipr.h 2004-05-27 18:34:18.000000000 +0100 @@ -36,8 +36,8 @@ /* * Literals */ -#define IPR_DRIVER_VERSION "2.0.6" -#define IPR_DRIVER_DATE "(May 3, 2004)" +#define IPR_DRIVER_VERSION "2.0.7" +#define IPR_DRIVER_DATE "(May 21, 2004)" /* * IPR_DBG_TRACE: Setting this to 1 will turn on some general function tracing @@ -413,8 +413,8 @@ }__attribute__((packed, aligned (4))); struct ipr_ioasa_gpdd { - u8 device_end_state; - u8 device_bus_phase; + u8 end_state; + u8 bus_phase; u16 reserved; u32 ioa_data[23]; }__attribute__((packed, aligned (4))); @@ -457,7 +457,7 @@ struct ipr_ioasa_af_dasd dasd; struct ipr_ioasa_gpdd gpdd; struct ipr_ioasa_raw raw; - }; + } u; }__attribute__((packed, aligned (4))); struct ipr_mode_parm_hdr { @@ -617,14 +617,14 @@ struct ipr_hostrcb_type_02_error type_02_error; struct ipr_hostrcb_type_03_error type_03_error; struct ipr_hostrcb_type_04_error type_04_error; - }; + } u; }__attribute__((packed, aligned (4))); struct ipr_hostrcb_raw { u32 data[sizeof(struct ipr_hostrcb_error)/sizeof(u32)]; }__attribute__((packed, aligned (4))); -struct ipr_hostrcb { +struct ipr_hcam { u8 op_code; #define IPR_HOST_RCB_OP_CODE_CONFIG_CHANGE 0xE1 #define IPR_HOST_RCB_OP_CODE_LOG_DATA 0xE2 @@ -662,14 +662,14 @@ struct ipr_hostrcb_error error; struct ipr_hostrcb_cfg_ch_not ccn; struct ipr_hostrcb_raw raw; - }; + } u; +}__attribute__((packed, aligned (4))); - /* Driver added data */ +struct ipr_hostrcb { + struct ipr_hcam hcam; u32 hostrcb_dma; struct list_head queue; -}__attribute__((packed, aligned (4))); - -#define IPR_HOSTRCB_SZ offsetof(struct ipr_hostrcb, hostrcb_dma) +}; /* IPR smart dump table structures */ struct ipr_sdt_entry { @@ -785,7 +785,7 @@ u32 ioasc; u32 add_data; u32 res_addr; - }; + } u; }; struct ipr_sglist { @@ -939,7 +939,8 @@ unsigned long scratch; struct ipr_resource_entry *res; struct ipr_cmnd *sibling; - }; + struct scsi_device *sdev; + } u; struct ipr_ioa_cfg *ioa_cfg; }; --- diff/drivers/scsi/megaraid.c 2004-05-27 13:41:20.000000000 +0100 +++ source/drivers/scsi/megaraid.c 2004-05-27 18:34:18.000000000 +0100 @@ -4612,6 +4612,26 @@ pci_dev_func = pdev->devfn; /* + * The megaraid3 stuff reports the ID of the Intel part which is not + * remotely specific to the megaraid + */ + if (pdev->vendor == PCI_VENDOR_ID_INTEL) { + u16 magic; + /* + * Don't fall over the Compaq management cards using the same + * PCI identifier + */ + if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ && + pdev->subsystem_device == 0xC000) + return -ENODEV; + /* Now check the magic signature byte */ + pci_read_config_word(pdev, PCI_CONF_AMISIG, &magic); + if (magic != HBA_SIGNATURE_471 && magic != HBA_SIGNATURE) + return -ENODEV; + /* Ok it is probably a megaraid */ + } + + /* * For these vendor and device ids, signature offsets are not * valid and 64 bit is implicit */ --- diff/drivers/scsi/nsp32.c 2004-05-27 13:41:20.000000000 +0100 +++ source/drivers/scsi/nsp32.c 2004-05-27 18:34:18.000000000 +0100 @@ -38,7 +38,6 @@ #include #include #include -#include #include #include --- diff/drivers/scsi/qla1280.c 2004-05-27 13:41:20.000000000 +0100 +++ source/drivers/scsi/qla1280.c 2004-05-27 18:34:18.000000000 +0100 @@ -3119,6 +3119,7 @@ * Returns: * 0 = success, was able to issue command. */ +#ifdef QLA_64BIT_PTR static int qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) { @@ -3381,9 +3382,8 @@ return status; } +#else /* !QLA_64BIT_PTR */ - -#ifndef QLA_64BIT_PTR /* * qla1280_32bit_start_scsi * The start SCSI is responsible for building request packets on --- diff/drivers/scsi/qlogicfas408.c 2004-05-27 13:41:21.000000000 +0100 +++ source/drivers/scsi/qlogicfas408.c 2004-05-27 18:34:18.000000000 +0100 @@ -538,7 +538,7 @@ * Return info string */ -char *qlogicfas408_info(struct Scsi_Host *host) +const char *qlogicfas408_info(struct Scsi_Host *host) { struct qlogicfas408_priv *priv = get_priv_by_host(host); return priv->qinfo; --- diff/drivers/scsi/qlogicfas408.h 2004-05-27 13:41:21.000000000 +0100 +++ source/drivers/scsi/qlogicfas408.h 2004-05-27 18:34:18.000000000 +0100 @@ -111,7 +111,7 @@ int qlogicfas408_bus_reset(Scsi_Cmnd * cmd); int qlogicfas408_host_reset(Scsi_Cmnd * cmd); int qlogicfas408_device_reset(Scsi_Cmnd * cmd); -char *qlogicfas408_info(struct Scsi_Host *host); +const char *qlogicfas408_info(struct Scsi_Host *host); int qlogicfas408_get_chip_type(int qbase, int int_type); void qlogicfas408_setup(int qbase, int id, int int_type); int qlogicfas408_detect(int qbase, int int_type); --- diff/drivers/scsi/scsi_lib.c 2004-05-19 22:12:11.000000000 +0100 +++ source/drivers/scsi/scsi_lib.c 2004-05-27 18:34:18.000000000 +0100 @@ -951,6 +951,22 @@ return BLKPREP_KILL; } +static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + struct scsi_device *sdev = q->queuedata; + struct scsi_driver *drv; + + if (sdev->sdev_state != SDEV_RUNNING) + return -ENXIO; + + drv = *(struct scsi_driver **) disk->private_data; + if (drv->issue_flush) + return drv->issue_flush(&sdev->sdev_gendev, error_sector); + + return -EOPNOTSUPP; +} + static int scsi_prep_fn(struct request_queue *q, struct request *req) { struct scsi_device *sdev = q->queuedata; @@ -1332,7 +1348,8 @@ blk_queue_max_sectors(q, shost->max_sectors); blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); blk_queue_segment_boundary(q, shost->dma_boundary); - + blk_queue_issue_flush_fn(q, scsi_issue_flush_fn); + if (!shost->use_clustering) clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); return q; @@ -1610,7 +1627,9 @@ case SDEV_CANCEL: switch (oldstate) { + case SDEV_CREATED: case SDEV_RUNNING: + case SDEV_OFFLINE: break; default: goto illegal; @@ -1619,9 +1638,7 @@ case SDEV_DEL: switch (oldstate) { - case SDEV_CREATED: case SDEV_CANCEL: - case SDEV_OFFLINE: break; default: goto illegal; --- diff/drivers/scsi/scsi_logging.h 2004-05-19 22:12:11.000000000 +0100 +++ source/drivers/scsi/scsi_logging.h 2004-05-27 18:34:18.000000000 +0100 @@ -46,7 +46,7 @@ #define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) \ { \ - if ((SCSI_LOG_LEVEL(SHIFT, BITS)) > (LEVEL)) \ + if (unlikely((SCSI_LOG_LEVEL(SHIFT, BITS)) > (LEVEL))) \ (CMD); \ } #else --- diff/drivers/scsi/scsi_scan.c 2004-05-27 13:41:21.000000000 +0100 +++ source/drivers/scsi/scsi_scan.c 2004-05-27 18:34:18.000000000 +0100 @@ -80,7 +80,6 @@ MODULE_PARM_DESC(max_luns, "last scsi LUN (should be between 1 and 2^32-1)"); -#ifdef CONFIG_SCSI_REPORT_LUNS /* * max_scsi_report_luns: the maximum number of LUNS that will be * returned from the REPORT LUNS command. 8 times this value must @@ -88,13 +87,19 @@ * in practice, the maximum number of LUNs suppored by any device * is about 16k. */ -static unsigned int max_scsi_report_luns = 128; +static unsigned int max_scsi_report_luns = 511; module_param_named(max_report_luns, max_scsi_report_luns, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(max_report_luns, "REPORT LUNS maximum number of LUNS received (should be" " between 1 and 16384)"); -#endif + +static unsigned int scsi_inq_timeout = SCSI_TIMEOUT/HZ+3; + +module_param_named(inq_timeout, scsi_inq_timeout, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(inq_timeout, + "Timeout (in seconds) waiting for devices to answer INQUIRY." + " Default is 5. Some non-compliant devices need more."); /** * scsi_unlock_floptical - unlock device via a special MODE SENSE command @@ -212,6 +217,11 @@ INIT_LIST_HEAD(&sdev->starved_entry); spin_lock_init(&sdev->list_lock); + + /* if the device needs this changing, it may do so in the + * slave_configure function */ + sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED; + /* * Some low level driver could use device->type */ @@ -346,7 +356,7 @@ memset(inq_result, 0, 36); scsi_wait_req(sreq, (void *) scsi_cmd, (void *) inq_result, 36, - SCSI_TIMEOUT + 4 * HZ, 3); + HZ/2 + HZ*scsi_inq_timeout, 3); SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: 1st INQUIRY %s with" " code 0x%x\n", sreq->sr_result ? @@ -400,7 +410,7 @@ memset(inq_result, 0, possible_inq_resp_len); scsi_wait_req(sreq, (void *) scsi_cmd, (void *) inq_result, - possible_inq_resp_len, SCSI_TIMEOUT + 4 * HZ, 3); + possible_inq_resp_len, (1+scsi_inq_timeout)*(HZ/2), 3); SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: 2nd INQUIRY" " %s with code 0x%x\n", sreq->sr_result ? "failed" : "successful", sreq->sr_result)); @@ -628,10 +638,6 @@ spin_unlock_irqrestore(sdev->host->host_lock, flags); } - /* if the device needs this changing, it may do so in the detect - * function */ - sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED; - sdev->use_10_for_rw = 1; if (*bflags & BLIST_MS_SKIP_PAGE_08) @@ -863,7 +869,6 @@ return; } -#ifdef CONFIG_SCSI_REPORT_LUNS /** * scsilun_to_int: convert a scsi_lun to an int * @scsilun: struct scsi_lun to be converted. @@ -924,9 +929,14 @@ u8 *data; /* - * Only support SCSI-3 and up devices. - */ - if (sdev->scsi_level < SCSI_3) + * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set. + * Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does + * support more than 8 LUNs. + */ + if ((bflags & BLIST_NOREPORTLUN) || + sdev->scsi_level < SCSI_2 || + (sdev->scsi_level < SCSI_3 && + (!(bflags & BLIST_REPORTLUN2) || sdev->host->max_lun <= 8)) ) return 1; if (bflags & BLIST_NOLUN) return 0; @@ -1090,9 +1100,6 @@ printk(ALLOC_FAILURE_MSG, __FUNCTION__); return 0; } -#else -# define scsi_report_lun_scan(sdev, blags, rescan) (1) -#endif /* CONFIG_SCSI_REPORT_LUNS */ struct scsi_device *scsi_add_device(struct Scsi_Host *shost, uint channel, uint id, uint lun) --- diff/drivers/scsi/scsiiom.c 2004-05-19 22:12:11.000000000 +0100 +++ source/drivers/scsi/scsiiom.c 2004-05-27 18:34:18.000000000 +0100 @@ -15,7 +15,7 @@ }; -UCHAR +static UCHAR dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ) { UCHAR cmd; UCHAR disc_allowed, try_sync_nego; @@ -227,7 +227,7 @@ #if DMA_INT UCHAR dstatus; #endif - DC390_AFLAGS DC390_IFLAGS; //DC390_DFLAGS + DC390_IFLAGS; pACB = (PACB)dev_id; for (pACB2 = dc390_pACB_start; (pACB2 && pACB2 != pACB); pACB2 = pACB2->pNextACB); @@ -237,26 +237,21 @@ return IRQ_NONE; } - //DC390_LOCK_DRV; - sstatus = DC390_read8 (Scsi_Status); if( !(sstatus & INTERRUPT) ) - { /*DC390_UNLOCK_DRV;*/ return IRQ_NONE; }; + return IRQ_NONE; DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus)); #if DMA_INT DC390_LOCK_IO(pACB->pScsiHost); - DC390_LOCK_ACB; dstatus = dc390_dma_intr (pACB); - DC390_UNLOCK_ACB; DC390_UNLOCK_IO(pACB->pScsiHost); DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus)); if (! (dstatus & SCSI_INTERRUPT)) { DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n")); - //DC390_UNLOCK_DRV; return IRQ_NONE; }; #else @@ -266,8 +261,6 @@ #endif DC390_LOCK_IO(pACB->pScsiHost); - DC390_LOCK_ACB; - //DC390_UNLOCK_DRV_NI; /* Allow _other_ CPUs to process IRQ (useful for shared IRQs) */ istate = DC390_read8 (Intern_State); istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */ @@ -339,14 +332,11 @@ } unlock: - //DC390_LOCK_DRV_NI; - DC390_UNLOCK_ACB; DC390_UNLOCK_IO(pACB->pScsiHost); - //DC390_UNLOCK_DRV; /* Restore initial flags */ return IRQ_HANDLED; } -irqreturn_t do_DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t do_DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs) { irqreturn_t ret; DEBUG1(printk (KERN_INFO "DC390: Irq (%i) caught: ", irq)); @@ -356,7 +346,7 @@ return ret; } -void +static void dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) { UCHAR sstatus; @@ -410,7 +400,7 @@ } } -void +static void dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) { UCHAR sstatus, residual, bval; @@ -521,7 +511,7 @@ { DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ - } + } } static void @@ -740,9 +730,9 @@ psgl = pSRB->pSegmentList; //dc390_pci_sync(pSRB); - while (pSRB->TotalXferredLen + (ULONG) psgl->length < pSRB->Saved_Ptr) + while (pSRB->TotalXferredLen + (ULONG) sg_dma_len(psgl) < pSRB->Saved_Ptr) { - pSRB->TotalXferredLen += (ULONG) psgl->length; + pSRB->TotalXferredLen += (ULONG) sg_dma_len(psgl); pSRB->SGIndex++; if( pSRB->SGIndex < pSRB->SGcount ) { @@ -762,7 +752,7 @@ } else if(pcmd->request_buffer) { //dc390_pci_sync(pSRB); - pSRB->Segmentx.length = pcmd->request_bufflen - pSRB->Saved_Ptr; + sg_dma_len(&pSRB->Segmentx) = pcmd->request_bufflen - pSRB->Saved_Ptr; pSRB->SGcount = 1; pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; } else { @@ -873,7 +863,7 @@ } -void +static void dc390_DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir) { PSGL psgl; @@ -885,6 +875,8 @@ if (pDCB) printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n", pDCB->TargetID, pDCB->TargetLUN); else printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n"); + + pSRB->pSRBDCB = pDCB; dc390_EnableMsgOut_Abort (pACB, pSRB); if (pDCB) pDCB->DCBFlag |= ABORT_DEV; return; @@ -1150,7 +1142,6 @@ pSRB = psrb; } pDCB->pGoingSRB = 0; - dc390_Query_to_Waiting (pACB); dc390_Waiting_process (pACB); } else @@ -1466,7 +1457,7 @@ ptr2 = pSRB->pSegmentList; for( i=pSRB->SGIndex; i < bval; i++) { - swlval += ptr2->length; + swlval += sg_dma_len(ptr2); ptr2++; } REMOVABLEDEBUG(printk(KERN_INFO "XferredLen=%08x,NotXferLen=%08x\n",\ @@ -1619,20 +1610,15 @@ pACB->scan_devices = 0; }; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,30) pcmd->resid = pcmd->request_bufflen - pSRB->TotalXferredLen; -#endif if (!DCB_removed) dc390_Going_remove (pDCB, pSRB); /* Add to free list */ dc390_Free_insert (pACB, pSRB); DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->pid)); - DC390_UNLOCK_ACB_NI; pcmd->scsi_done (pcmd); - DC390_LOCK_ACB_NI; - dc390_Query_to_Waiting (pACB); dc390_Waiting_process (pACB); return; } @@ -1668,9 +1654,7 @@ /* ReleaseSRB( pDCB, pSRB ); */ DEBUG0(printk (KERN_DEBUG "DC390: DoingSRB_Done: done pid %li\n", pcmd->pid)); - DC390_UNLOCK_ACB_NI; pcmd->scsi_done( pcmd ); - DC390_LOCK_ACB_NI; #endif psrb = psrb2; } @@ -1679,7 +1663,6 @@ pdcb->TagMask = 0; pdcb = pdcb->pNextDCB; } while( pdcb != pDCB ); - dc390_Query_to_Waiting (pACB); } --- diff/drivers/scsi/sd.c 2004-05-27 13:41:21.000000000 +0100 +++ source/drivers/scsi/sd.c 2004-05-27 18:34:18.000000000 +0100 @@ -111,6 +111,7 @@ static void sd_shutdown(struct device *dev); static void sd_rescan(struct device *); static int sd_init_command(struct scsi_cmnd *); +static int sd_issue_flush(struct device *, sector_t *); static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, struct scsi_request *SRpnt, unsigned char *buffer); @@ -124,6 +125,7 @@ }, .rescan = sd_rescan, .init_command = sd_init_command, + .issue_flush = sd_issue_flush, }; /* Device no to disk mapping: @@ -673,6 +675,62 @@ return 1; } +static int sd_sync_cache(struct scsi_device *sdp) +{ + struct scsi_request *sreq; + int retries, res; + + if (!scsi_device_online(sdp)) + return -ENODEV; + + sreq = scsi_allocate_request(sdp, GFP_KERNEL); + if (!sreq) { + printk("FAILED\n No memory for request\n"); + return -ENOMEM; + } + + sreq->sr_data_direction = DMA_NONE; + for (retries = 3; retries > 0; --retries) { + unsigned char cmd[10] = { 0 }; + + cmd[0] = SYNCHRONIZE_CACHE; + /* + * Leave the rest of the command zero to indicate + * flush everything. + */ + scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES); + if (sreq->sr_result == 0) + break; + } + + res = sreq->sr_result; + if (res) { + printk(KERN_WARNING "FAILED\n status = %x, message = %02x, " + "host = %d, driver = %02x\n ", + status_byte(res), msg_byte(res), + host_byte(res), driver_byte(res)); + if (driver_byte(res) & DRIVER_SENSE) + print_req_sense("sd", sreq); + } + + scsi_release_request(sreq); + return res; +} + +static int sd_issue_flush(struct device *dev, sector_t *error_sector) +{ + struct scsi_device *sdp = to_scsi_device(dev); + struct scsi_disk *sdkp = dev_get_drvdata(dev); + + if (!sdkp) + return -ENODEV; + + if (!sdkp->WCE) + return 0; + + return sd_sync_cache(sdp); +} + static void sd_rescan(struct device *dev) { struct scsi_disk *sdkp = dev_get_drvdata(dev); @@ -1500,52 +1558,17 @@ static void sd_shutdown(struct device *dev) { struct scsi_device *sdp = to_scsi_device(dev); - struct scsi_disk *sdkp; - struct scsi_request *sreq; - int retries, res; + struct scsi_disk *sdkp = dev_get_drvdata(dev); - sdkp = dev_get_drvdata(dev); if (!sdkp) return; /* this can happen */ - if (!scsi_device_online(sdp) || !sdkp->WCE) + if (!sdkp->WCE) return; - printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: ", + printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: \n", sdkp->disk->disk_name); - - sreq = scsi_allocate_request(sdp, GFP_KERNEL); - if (!sreq) { - printk("FAILED\n No memory for request\n"); - return; - } - - sreq->sr_data_direction = DMA_NONE; - for (retries = 3; retries > 0; --retries) { - unsigned char cmd[10] = { 0 }; - - cmd[0] = SYNCHRONIZE_CACHE; - /* - * Leave the rest of the command zero to indicate - * flush everything. - */ - scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES); - if (sreq->sr_result == 0) - break; - } - - res = sreq->sr_result; - if (res) { - printk(KERN_WARNING "FAILED\n status = %x, message = %02x, " - "host = %d, driver = %02x\n ", - status_byte(res), msg_byte(res), - host_byte(res), driver_byte(res)); - if (driver_byte(res) & DRIVER_SENSE) - print_req_sense("sd", sreq); - } - - scsi_release_request(sreq); - printk("\n"); + sd_sync_cache(sdp); } /** --- diff/drivers/scsi/sg.c 2004-05-27 13:41:21.000000000 +0100 +++ source/drivers/scsi/sg.c 2004-05-27 18:34:18.000000000 +0100 @@ -7,7 +7,7 @@ * Original driver (sg.c): * Copyright (C) 1992 Lawrence Foard * Version 2 and 3 extensions to driver: - * Copyright (C) 1998 - 2002 Douglas Gilbert + * Copyright (C) 1998 - 2004 Douglas Gilbert * * Modified 19-JAN-1998 Richard Gooch Devfs support * @@ -17,27 +17,18 @@ * any later version. * */ -#include -static int sg_version_num = 30530; /* 2 digits for each component */ + +static int sg_version_num = 30531; /* 2 digits for each component */ +#define SG_VERSION_STR "3.5.31" + /* * D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes: * - scsi logging is available via SCSI_LOG_TIMEOUT macros. First * the kernel/module needs to be built with CONFIG_SCSI_LOGGING * (otherwise the macros compile to empty statements). - * Then before running the program to be debugged enter: - * # echo "scsi log timeout 7" > /proc/scsi/scsi - * This will send copious output to the console and the log which - * is usually /var/log/messages. To turn off debugging enter: - * # echo "scsi log timeout 0" > /proc/scsi/scsi - * The 'timeout' token was chosen because it is relatively unused. - * The token 'hlcomplete' should be used but that triggers too - * much output from the sd device driver. To dump the current - * state of the SCSI mid level data structures enter: - * # echo "scsi dump 1" > /proc/scsi/scsi - * To dump the state of sg's data structures use: - * # cat /proc/scsi/sg/debug * */ +#include #include #include @@ -69,7 +60,7 @@ #ifdef CONFIG_SCSI_PROC_FS #include -static char *sg_version_str = "3.5.30 [20040124]"; +static char *sg_version_date = "20040513"; static int sg_proc_init(void); static void sg_proc_cleanup(void); @@ -110,7 +101,7 @@ #define SG_SECTOR_SZ 512 #define SG_SECTOR_MSK (SG_SECTOR_SZ - 1) -#define SG_DEV_ARR_LUMP 6 /* amount to over allocate sg_dev_arr by */ +#define SG_DEV_ARR_LUMP 32 /* amount to over allocate sg_dev_arr by */ static int sg_add(struct class_device *); static void sg_remove(struct class_device *); @@ -1333,85 +1324,44 @@ static int sg_sysfs_valid = 0; -static int -sg_add(struct class_device *cl_dev) +static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) { - struct scsi_device *scsidp = to_scsi_device(cl_dev->dev); - struct gendisk *disk; - Sg_device *sdp = NULL; + Sg_device *sdp; unsigned long iflags; - struct cdev * cdev = NULL; + void *old_sg_dev_arr = NULL; int k, error; - disk = alloc_disk(1); - if (!disk) + sdp = vmalloc(sizeof(Sg_device)); + if (!sdp) return -ENOMEM; - cdev = cdev_alloc(); - if (! cdev) - return -ENOMEM; write_lock_irqsave(&sg_dev_arr_lock, iflags); - if (sg_nr_dev >= sg_dev_max) { /* try to resize */ + if (unlikely(sg_nr_dev >= sg_dev_max)) { /* try to resize */ Sg_device **tmp_da; int tmp_dev_max = sg_nr_dev + SG_DEV_ARR_LUMP; - write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - tmp_da = (Sg_device **)vmalloc( - tmp_dev_max * sizeof(Sg_device *)); - if (NULL == tmp_da) { - printk(KERN_ERR - "sg_add: device array cannot be resized\n"); - error = -ENOMEM; - goto out; - } + + tmp_da = vmalloc(tmp_dev_max * sizeof(Sg_device *)); + if (unlikely(!tmp_da)) + goto expand_failed; + write_lock_irqsave(&sg_dev_arr_lock, iflags); - memset(tmp_da, 0, tmp_dev_max * sizeof (Sg_device *)); - memcpy(tmp_da, sg_dev_arr, - sg_dev_max * sizeof (Sg_device *)); - vfree((char *) sg_dev_arr); + memset(tmp_da, 0, tmp_dev_max * sizeof(Sg_device *)); + memcpy(tmp_da, sg_dev_arr, sg_dev_max * sizeof(Sg_device *)); + old_sg_dev_arr = sg_dev_arr; sg_dev_arr = tmp_da; sg_dev_max = tmp_dev_max; } -find_empty_slot: for (k = 0; k < sg_dev_max; k++) if (!sg_dev_arr[k]) break; - if (k >= SG_MAX_DEVS) { - write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - printk(KERN_WARNING - "Unable to attach sg device <%d, %d, %d, %d>" - " type=%d, minor number exceeds %d\n", - scsidp->host->host_no, scsidp->channel, scsidp->id, - scsidp->lun, scsidp->type, SG_MAX_DEVS - 1); - if (NULL != sdp) - vfree((char *) sdp); - error = -ENODEV; - goto out; - } - if (k < sg_dev_max) { - if (NULL == sdp) { - write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - sdp = (Sg_device *)vmalloc(sizeof(Sg_device)); - write_lock_irqsave(&sg_dev_arr_lock, iflags); - if (!sg_dev_arr[k]) - goto find_empty_slot; - } - } else - sdp = NULL; - if (NULL == sdp) { - write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - printk(KERN_ERR "sg_add: Sg_device cannot be allocated\n"); - error = -ENOMEM; - goto out; - } + if (unlikely(k >= SG_MAX_DEVS)) + goto overflow; - SCSI_LOG_TIMEOUT(3, printk("sg_add: dev=%d \n", k)); memset(sdp, 0, sizeof(*sdp)); + SCSI_LOG_TIMEOUT(3, printk("sg_alloc: dev=%d \n", k)); sprintf(disk->disk_name, "sg%d", k); - cdev->owner = THIS_MODULE; - cdev->ops = &sg_fops; - disk->major = SCSI_GENERIC_MAJOR; disk->first_minor = k; sdp->disk = disk; sdp->device = scsidp; @@ -1421,6 +1371,55 @@ sg_nr_dev++; sg_dev_arr[k] = sdp; write_unlock_irqrestore(&sg_dev_arr_lock, iflags); + error = k; + + out: + if (error < 0) + vfree(sdp); + vfree(old_sg_dev_arr); + return error; + + expand_failed: + printk(KERN_ERR "sg_alloc: device array cannot be resized\n"); + error = -ENOMEM; + goto out; + + overflow: + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); + printk(KERN_WARNING + "Unable to attach sg device <%d, %d, %d, %d> type=%d, minor " + "number exceeds %d\n", scsidp->host->host_no, scsidp->channel, + scsidp->id, scsidp->lun, scsidp->type, SG_MAX_DEVS - 1); + error = -ENODEV; + goto out; +} + +static int +sg_add(struct class_device *cl_dev) +{ + struct scsi_device *scsidp = to_scsi_device(cl_dev->dev); + struct gendisk *disk; + Sg_device *sdp = NULL; + struct cdev * cdev = NULL; + int error, k; + + disk = alloc_disk(1); + if (!disk) + return -ENOMEM; + disk->major = SCSI_GENERIC_MAJOR; + + error = -ENOMEM; + cdev = cdev_alloc(); + if (!cdev) + goto out; + cdev->owner = THIS_MODULE; + cdev->ops = &sg_fops; + + error = sg_alloc(disk, scsidp); + if (error < 0) + goto out; + k = error; + sdp = sg_dev_arr[k]; devfs_mk_cdev(MKDEV(SCSI_GENERIC_MAJOR, k), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, @@ -1543,6 +1542,7 @@ MODULE_AUTHOR("Douglas Gilbert"); MODULE_DESCRIPTION("SCSI generic (sg) driver"); MODULE_LICENSE("GPL"); +MODULE_VERSION(SG_VERSION_STR); MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd"); MODULE_PARM_DESC(allow_dio, "allow direct I/O (default: 0 (disallow))"); @@ -2844,7 +2844,8 @@ static int sg_proc_seq_show_version(struct seq_file *s, void *v) { - seq_printf(s, "%d\t%s\n", sg_version_num, sg_version_str); + seq_printf(s, "%d\t%s [%s]\n", sg_version_num, SG_VERSION_STR, + sg_version_date); return 0; } --- diff/drivers/scsi/sr_ioctl.c 2004-05-19 22:12:12.000000000 +0100 +++ source/drivers/scsi/sr_ioctl.c 2004-05-27 18:34:18.000000000 +0100 @@ -331,6 +331,9 @@ int result; unsigned char *buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd)); + if (!buffer) + return -ENOMEM; + memset(&cgc, 0, sizeof(struct cdrom_generic_command)); cgc.timeout = IOCTL_TIMEOUT; --- diff/drivers/scsi/st.c 2004-05-27 13:41:21.000000000 +0100 +++ source/drivers/scsi/st.c 2004-05-27 18:34:18.000000000 +0100 @@ -486,7 +486,7 @@ tape_name(STp), forward ? "forward" : "backward")); SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, - STp->timeout, MAX_RETRIES, TRUE); + STp->device->timeout, MAX_RETRIES, TRUE); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -544,7 +544,7 @@ cmd[4] = blks; SRpnt = st_do_scsi(NULL, STp, cmd, transfer, SCSI_DATA_WRITE, - STp->timeout, MAX_WRITE_RETRIES, TRUE); + STp->device->timeout, MAX_WRITE_RETRIES, TRUE); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -867,7 +867,7 @@ memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE); cmd[0] = READ_BLOCK_LIMITS; - SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, SCSI_DATA_READ, STp->timeout, + SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, SCSI_DATA_READ, STp->device->timeout, MAX_READY_RETRIES, TRUE); if (!SRpnt) { retval = (STp->buffer)->syscall_result; @@ -894,7 +894,7 @@ cmd[0] = MODE_SENSE; cmd[4] = 12; - SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, SCSI_DATA_READ, STp->timeout, + SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, SCSI_DATA_READ, STp->device->timeout, MAX_READY_RETRIES, TRUE); if (!SRpnt) { retval = (STp->buffer)->syscall_result; @@ -1116,7 +1116,7 @@ cmd[4] = 1 + STp->two_fm; SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, - STp->timeout, MAX_WRITE_RETRIES, TRUE); + STp->device->timeout, MAX_WRITE_RETRIES, TRUE); if (!SRpnt) { result = (STp->buffer)->syscall_result; goto out; @@ -1509,7 +1509,7 @@ cmd[4] = blks; SRpnt = st_do_scsi(SRpnt, STp, cmd, transfer, SCSI_DATA_WRITE, - STp->timeout, MAX_WRITE_RETRIES, !async_write); + STp->device->timeout, MAX_WRITE_RETRIES, !async_write); if (!SRpnt) { retval = STbp->syscall_result; goto out; @@ -1679,7 +1679,7 @@ SRpnt = *aSRpnt; SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, SCSI_DATA_READ, - STp->timeout, MAX_RETRIES, TRUE); + STp->device->timeout, MAX_RETRIES, TRUE); release_buffering(STp); *aSRpnt = SRpnt; if (!SRpnt) @@ -2081,7 +2081,7 @@ DEBC( printk(KERN_INFO "%s: Long timeout set to %d seconds.\n", name, (value & ~MT_ST_SET_LONG_TIMEOUT))); } else { - STp->timeout = value * HZ; + STp->device->timeout = value * HZ; DEBC( printk(KERN_INFO "%s: Normal timeout set to %d seconds.\n", name, value) ); } @@ -2189,7 +2189,7 @@ cmd[4] = 255; SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, - STp->timeout, 0, TRUE); + STp->device->timeout, 0, TRUE); if (SRpnt == NULL) return (STp->buffer)->syscall_result; @@ -2220,7 +2220,7 @@ (STp->buffer)->b_data[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR; SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, - (slow ? STp->long_timeout : STp->timeout), 0, TRUE); + (slow ? STp->long_timeout : STp->device->timeout), 0, TRUE); if (SRpnt == NULL) return (STp->buffer)->syscall_result; @@ -2332,7 +2332,7 @@ } if (STp->immediate) { cmd[1] = 1; /* Don't wait for completion */ - timeout = STp->timeout; + timeout = STp->device->timeout; } else timeout = STp->long_timeout; @@ -2512,7 +2512,7 @@ cmd[2] = (arg >> 16); cmd[3] = (arg >> 8); cmd[4] = arg; - timeout = STp->timeout; + timeout = STp->device->timeout; DEBC( if (cmd_in == MTWEOF) printk(ST_DEB_MSG "%s: Writing %d filemarks.\n", name, @@ -2530,7 +2530,7 @@ cmd[0] = REZERO_UNIT; if (STp->immediate) { cmd[1] = 1; /* Don't wait for completion */ - timeout = STp->timeout; + timeout = STp->device->timeout; } DEBC(printk(ST_DEB_MSG "%s: Rewinding tape.\n", name)); fileno = blkno = at_sm = 0; @@ -2543,7 +2543,7 @@ cmd[0] = START_STOP; if (STp->immediate) { cmd[1] = 1; /* Don't wait for completion */ - timeout = STp->timeout; + timeout = STp->device->timeout; } cmd[4] = 3; DEBC(printk(ST_DEB_MSG "%s: Retensioning tape.\n", name)); @@ -2576,7 +2576,7 @@ cmd[1] = (arg ? 1 : 0); /* Long erase with non-zero argument */ if (STp->immediate) { cmd[1] |= 2; /* Don't wait for completion */ - timeout = STp->timeout; + timeout = STp->device->timeout; } else timeout = STp->long_timeout * 8; @@ -2628,7 +2628,7 @@ (STp->buffer)->b_data[9] = (ltmp >> 16); (STp->buffer)->b_data[10] = (ltmp >> 8); (STp->buffer)->b_data[11] = ltmp; - timeout = STp->timeout; + timeout = STp->device->timeout; DEBC( if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) printk(ST_DEB_MSG @@ -2809,7 +2809,7 @@ if (!logical && !STp->scsi2_logical) scmd[1] = 1; } - SRpnt = st_do_scsi(NULL, STp, scmd, 20, SCSI_DATA_READ, STp->timeout, + SRpnt = st_do_scsi(NULL, STp, scmd, 20, SCSI_DATA_READ, STp->device->timeout, MAX_READY_RETRIES, TRUE); if (!SRpnt) return (STp->buffer)->syscall_result; @@ -2911,7 +2911,7 @@ } if (STp->immediate) { scmd[1] |= 1; /* Don't wait for completion */ - timeout = STp->timeout; + timeout = STp->device->timeout; } SRpnt = st_do_scsi(NULL, STp, scmd, 0, SCSI_DATA_NONE, @@ -3408,11 +3408,17 @@ goto out; } up(&STp->lock); - i = scsi_cmd_ioctl(STp->disk, cmd_in, arg); - if (i != -ENOTTY) - return i; - else - return scsi_ioctl(STp->device, cmd_in, (void *) arg); + switch (cmd_in) { + case SCSI_IOCTL_GET_IDLUN: + case SCSI_IOCTL_GET_BUS_NUMBER: + break; + default: + i = scsi_cmd_ioctl(STp->disk, cmd_in, arg); + if (i != -ENOTTY) + return i; + break; + } + return scsi_ioctl(STp->device, cmd_in, (void *) arg); out: up(&STp->lock); @@ -3832,7 +3838,7 @@ tpnt->partition = 0; tpnt->new_partition = 0; tpnt->nbr_partitions = 0; - tpnt->timeout = ST_TIMEOUT; + tpnt->device->timeout = ST_TIMEOUT; tpnt->long_timeout = ST_LONG_TIMEOUT; tpnt->try_dio = try_direct_io && !SDp->host->unchecked_isa_dma; --- diff/drivers/scsi/st.h 2004-05-19 22:12:12.000000000 +0100 +++ source/drivers/scsi/st.h 2004-05-27 18:34:18.000000000 +0100 @@ -100,7 +100,6 @@ unsigned char c_algo; /* compression algorithm */ unsigned char pos_unknown; /* after reset position unknown */ int tape_type; - int timeout; /* timeout for normal commands */ int long_timeout; /* timeout for commands known to take long time */ unsigned long max_pfn; /* the maximum page number reachable by the HBA */ --- diff/drivers/scsi/tmscsim.c 2004-05-19 22:12:12.000000000 +0100 +++ source/drivers/scsi/tmscsim.c 2004-05-27 18:34:18.000000000 +0100 @@ -168,6 +168,10 @@ * 2.1a 03/11/29 GL, KG Initial fixing for 2.6. Convert to * * use the current PCI-mapping API, update * * command-queuing. * + * 2.1b 04/04/13 GL Fix for 64-bit platforms * + * 2.1b1 04/01/31 GL (applied 05.04) Remove internal * + * command-queuing. * + * 2.1b2 04/02/01 CH (applied 05.04) Fix error-handling * ***********************************************************************/ /* Uncomment SA_INTERRUPT, if the driver refuses to share its IRQ with other devices */ @@ -260,16 +264,10 @@ * undef : traditional save_flags; cli; restore_flags; */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30) -# include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30) -# include -#else -# include -#endif -#endif +#include +#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,99) && defined(MODULE) +#if defined(MODULE) static struct pci_device_id tmscsim_pci_tbl[] = { { .vendor = PCI_VENDOR_ID_AMD, @@ -283,23 +281,10 @@ #endif #define USE_SPINLOCKS 1 -#define NEW_PCI 1 -#define DC390_AFLAGS #define DC390_IFLAGS unsigned long iflags -#define DC390_DFLAGS unsigned long dflags -spinlock_t dc390_drvlock = SPIN_LOCK_UNLOCKED; #define DC390_LOCK_IO(dev) spin_lock_irqsave (((struct Scsi_Host *)dev)->host_lock, iflags) #define DC390_UNLOCK_IO(dev) spin_unlock_irqrestore (((struct Scsi_Host *)dev)->host_lock, iflags) -#define DC390_LOCK_DRV spin_lock_irqsave (&dc390_drvlock, dflags) -#define DC390_UNLOCK_DRV spin_unlock_irqrestore (&dc390_drvlock, dflags) -#define DC390_LOCK_DRV_NI spin_lock (&dc390_drvlock) -#define DC390_UNLOCK_DRV_NI spin_unlock (&dc390_drvlock) -#define DC390_LOCK_ACB /* DC390_LOCK_IO */ -#define DC390_UNLOCK_ACB /* DC390_UNLOCK_IO */ -#define DC390_LOCK_ACB_NI /* spin_lock (&(pACB->lock)) */ -#define DC390_UNLOCK_ACB_NI /* spin_unlock (&(pACB->lock)) */ -#define DC390_LOCKA_INIT /* DC390_LOCKA_INIT */ /* These macros are used for uniform access to 2.0.x and 2.1.x PCI config space*/ @@ -313,10 +298,7 @@ #define PCI_READ_CONFIG_BYTE(pd, rv, bv) pci_read_config_byte (pd, rv, bv) #define PCI_WRITE_CONFIG_WORD(pd, rv, bv) pci_write_config_word (pd, rv, bv) #define PCI_READ_CONFIG_WORD(pd, rv, bv) pci_read_config_word (pd, rv, bv) -#define PCI_BUS_DEV pdev->bus->number, pdev->devfn #define PCI_PRESENT (1) -#define PCI_SET_MASTER pci_set_master (pdev) -#define PCI_FIND_DEVICE(vend, id) (pdev = pci_find_device (vend, id, pdev)) #define PCI_GET_IO_AND_IRQ do{io_port = pci_resource_start (pdev, 0); irq = pdev->irq;} while(0) #include "tmscsim.h" @@ -325,46 +307,42 @@ # define __init #endif -UCHAR dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ); -void dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); -void dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static UCHAR dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ); +static void dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); static void dc390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); static void dc390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); static void dc390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); -void dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); static void dc390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); static void dc390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); -void dc390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void dc390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); static void dc390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); -void dc390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); +static void dc390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); static void dc390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); static void dc390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); static void dc390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus); static void dc390_SetXferRate( PACB pACB, PDCB pDCB ); -void dc390_Disconnect( PACB pACB ); -void dc390_Reselect( PACB pACB ); -void dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ); -void dc390_DoingSRB_Done( PACB pACB, PSCSICMD cmd ); +static void dc390_Disconnect( PACB pACB ); +static void dc390_Reselect( PACB pACB ); +static void dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ); +static void dc390_DoingSRB_Done( PACB pACB, PSCSICMD cmd ); static void dc390_ScsiRstDetect( PACB pACB ); static void dc390_ResetSCSIBus( PACB pACB ); static void __inline__ dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ); static void __inline__ dc390_InvalidCmd( PACB pACB ); static void __inline__ dc390_EnableMsgOut_Abort (PACB, PSRB); static void dc390_remove_dev (PACB pACB, PDCB pDCB); -irqreturn_t do_DC390_Interrupt( int, void *, struct pt_regs *); +static irqreturn_t do_DC390_Interrupt( int, void *, struct pt_regs *); -int dc390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, UCHAR index ); -void dc390_initDCB( PACB pACB, PDCB *ppDCB, UCHAR id, UCHAR lun); -void dc390_updateDCB (PACB pACB, PDCB pDCB); +static int dc390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, UCHAR index ); +static void dc390_initDCB( PACB pACB, PDCB *ppDCB, UCHAR id, UCHAR lun); +static void dc390_updateDCB (PACB pACB, PDCB pDCB); static int DC390_release(struct Scsi_Host *host); static int dc390_shutdown (struct Scsi_Host *host); - -//static PSHT dc390_pSHT_start = NULL; -//static PSH dc390_pSH_start = NULL; -//static PSH dc390_pSH_current = NULL; static PACB dc390_pACB_start= NULL; static PACB dc390_pACB_current = NULL; static ULONG dc390_lastabortedpid = 0; @@ -372,14 +350,11 @@ static UCHAR dc390_adapterCnt = 0; /* Startup values, to be overriden on the commandline */ -int tmscsim[] = {-2, -2, -2, -2, -2, -2}; +static int tmscsim[] = {-2, -2, -2, -2, -2, -2}; -# if defined(MODULE) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30) +#if defined(MODULE) MODULE_PARM(tmscsim, "1-6i"); MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)"); -# endif - -#if defined(MODULE) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30) MODULE_AUTHOR("C.L. Huang / Kurt Garloff"); MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters"); MODULE_LICENSE("GPL"); @@ -438,22 +413,15 @@ #endif /* Devices erroneously pretending to be able to do TagQ */ -UCHAR dc390_baddevname1[2][28] ={ +static UCHAR dc390_baddevname1[2][28] ={ "SEAGATE ST3390N 9546", "HP C3323-300 4269"}; #define BADDEVCNT 2 static char* dc390_adapname = "DC390"; -UCHAR dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN]; -UCHAR dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20}; -UCHAR dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20}; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,30) -struct proc_dir_entry DC390_proc_scsi_tmscsim ={ - PROC_SCSI_DC390T, 7 ,"tmscsim", - S_IFDIR | S_IRUGO | S_IXUGO, 2 - }; -#endif +static UCHAR dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN]; +static UCHAR dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20}; +static UCHAR dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20}; /*********************************************************************** * Functions for access to DC390 EEPROM @@ -518,7 +486,7 @@ } -int __initdata tmscsim_def[] = {7, 0 /* 10MHz */, +static int __initdata tmscsim_def[] = {7, 0 /* 10MHz */, PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ | SYNC_NEGO_ | TAG_QUEUEING_, MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION @@ -549,8 +517,7 @@ /* Override defaults on cmdline: * tmscsim: AdaptID, MaxSpeed (Index), DevMode (Bitmapped), AdaptMode (Bitmapped) */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13) -int __init dc390_setup (char *str) +static int __init dc390_setup (char *str) { int ints[8]; int i, im; @@ -570,24 +537,6 @@ __setup("tmscsim=", dc390_setup); #endif -#else -void __init dc390_setup (char *str, int *ints) -{ - int i, im; - im = ints[0]; - if (im > 6) - { - printk (KERN_NOTICE "DC390: ignore extra params!\n"); - im = 6; - } - for (i = 0; i < im; i++) - tmscsim[i] = ints[i+1]; - /* dc390_checkparams (); */ -} -#endif - - - static void __init dc390_EEpromOutDI( PDEVDECL, PUCHAR regval, UCHAR Carry ) { UCHAR bval; @@ -751,37 +700,6 @@ return q; } #endif - - -/* Append to Query List */ -static void dc390_Query_append( PSCSICMD cmd, PACB pACB ) -{ - dc390_cmd_scp_t *cmdq = (dc390_cmd_scp_t *)&cmd->SCp; - - DEBUG0(printk ("DC390: Append cmd %li to Query\n", cmd->pid)); - - list_add_tail(&cmdq->list, &pACB->cmdq); - pACB->QueryCnt++; - pACB->CmdOutOfSRB++; -} - - -/* Return next cmd from Query list */ -static PSCSICMD dc390_Query_get ( PACB pACB ) -{ - PSCSICMD pcmd; - dc390_cmd_scp_t *cmdq; - if (list_empty(&pACB->cmdq)) - return NULL; - - pcmd = (PSCSICMD) list_entry(pACB->cmdq.next, struct scsi_cmnd_list, scp.list); - DEBUG0(printk ("DC390: Get cmd %li from Query\n", pcmd->pid)); - cmdq = (dc390_cmd_scp_t *)&pcmd->SCp; - list_del(&cmdq->list); - pACB->QueryCnt--; - return pcmd; -} - /* Return next free SRB */ static __inline__ PSRB dc390_Free_get ( PACB pACB ) @@ -891,17 +809,7 @@ dc390_Going_append (pDCB, pSRB); } -/* 2.0 timer compatibility */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,30) - static inline int timer_pending(struct timer_list * timer) - { - return timer->prev != NULL; - } - #define time_after(a,b) ((long)(b) - (long)(a) < 0) - #define time_before(a,b) time_after(b,a) -#endif - -void DC390_waiting_timed_out (unsigned long ptr); +static void DC390_waiting_timed_out (unsigned long ptr); /* Sets the timer to wake us up */ static void dc390_waiting_timer (PACB pACB, unsigned long to) { @@ -954,16 +862,13 @@ } /* Wake up waiting queue */ -void DC390_waiting_timed_out (unsigned long ptr) +static void DC390_waiting_timed_out (unsigned long ptr) { PACB pACB = (PACB)ptr; DC390_IFLAGS; - DC390_AFLAGS; DEBUG0(printk ("DC390: Debug: Waiting queue woken up by timer!\n")); DC390_LOCK_IO(pACB->pScsiHost); - DC390_LOCK_ACB; dc390_Waiting_process (pACB); - DC390_UNLOCK_ACB; DC390_UNLOCK_IO(pACB->pScsiHost); } @@ -1022,7 +927,7 @@ pci_map_page(pdev, virt_to_page(pcmd->sense_buffer), (unsigned long)pcmd->sense_buffer & ~PAGE_MASK, sizeof(pcmd->sense_buffer), DMA_FROM_DEVICE); - pSRB->Segmentx.length = sizeof(pcmd->sense_buffer); + sg_dma_len(&pSRB->Segmentx) = sizeof(pcmd->sense_buffer); pSRB->SGcount = 1; pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __FUNCTION__, pcmd->sense_buffer, cmdp->saved_dma_handle)); @@ -1043,7 +948,7 @@ (unsigned long)pcmd->request_buffer & ~PAGE_MASK, pcmd->request_bufflen, scsi_to_pci_dma_dir(pcmd->sc_data_direction)); /* TODO: error handling */ - pSRB->Segmentx.length = pcmd->request_bufflen; + sg_dma_len(&pSRB->Segmentx) = pcmd->request_bufflen; pSRB->SGcount = 1; pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; DEBUG1(printk("%s(): Mapped request buffer %p at %x\n", __FUNCTION__, pcmd->request_buffer, cmdp->saved_dma_handle)); @@ -1113,37 +1018,6 @@ /* KG: deferred PCI mapping to dc390_StartSCSI */ } -/* Put cmnd from Query to Waiting list and send next Waiting cmnd */ -static void dc390_Query_to_Waiting (PACB pACB) -{ - Scsi_Cmnd *pcmd; - PSRB pSRB; - PDCB pDCB; - - if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) - return; - - while (pACB->QueryCnt) - { - pSRB = dc390_Free_get ( pACB ); - if (!pSRB) return; - pcmd = dc390_Query_get ( pACB ); - if (!pcmd) { dc390_Free_insert (pACB, pSRB); return; } /* should not happen */ - pDCB = dc390_findDCB (pACB, pcmd->device->id, pcmd->device->lun); - if (!pDCB) - { - dc390_Free_insert (pACB, pSRB); - printk (KERN_ERR "DC390: Command in queue to non-existing device!\n"); - pcmd->result = MK_RES(DRIVER_ERROR,DID_ERROR,0,0); - DC390_UNLOCK_ACB_NI; - pcmd->done (pcmd); - DC390_LOCK_ACB_NI; - } - dc390_BuildSRB (pcmd, pDCB, pSRB); - dc390_Waiting_append ( pDCB, pSRB ); - } -} - /*********************************************************************** * Function : static int DC390_queue_command (Scsi_Cmnd *cmd, * void (*done)(Scsi_Cmnd *)) @@ -1163,24 +1037,17 @@ * ***********************************************************************/ -int DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) +static int DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) { PDCB pDCB; PSRB pSRB; PACB pACB = (PACB) cmd->device->host->hostdata; - DC390_AFLAGS; - DEBUG0(/* if(pACB->scan_devices) */ \ printk(KERN_INFO "DC390: Queue Cmd=%02x,Tgt=%d,LUN=%d (pid=%li), buffer=%p\n",\ cmd->cmnd[0],cmd->device->id,cmd->device->lun,cmd->pid, cmd->buffer)); - DC390_LOCK_ACB; - - /* Assume BAD_TARGET; will be cleared later */ - cmd->result = DID_BAD_TARGET << 16; - - /* TODO: Change the policy: Alway accept TEST_UNIT_READY or INQUIRY + /* TODO: Change the policy: Always accept TEST_UNIT_READY or INQUIRY * commands and alloc a DCB for the device if not yet there. DCB will * be removed in dc390_SRBdone if SEL_TIMEOUT */ @@ -1190,17 +1057,6 @@ else if( (pACB->scan_devices) && (cmd->cmnd[0] == READ_6) ) pACB->scan_devices = 0; - if ( ( cmd->device->id >= pACB->pScsiHost->max_id ) || - (cmd->device->lun >= pACB->pScsiHost->max_lun) ) - { -/* printk ("DC390: Ignore target %d lun %d\n", - cmd->device->id, cmd->device->lun); */ - DC390_UNLOCK_ACB; - //return (1); - done (cmd); - return (0); - } - if( (pACB->scan_devices || cmd->cmnd[0] == TEST_UNIT_READY || cmd->cmnd[0] == INQUIRY) && !(pACB->DCBmap[cmd->device->id] & (1 << cmd->device->lun)) ) { @@ -1211,14 +1067,7 @@ { printk (KERN_ERR "DC390: kmalloc for DCB failed, target %02x lun %02x\n", cmd->device->id, cmd->device->lun); - DC390_UNLOCK_ACB; - printk ("DC390: No DCB in queue_command!\n"); -#ifdef USE_NEW_EH - return (1); -#else - done (cmd); - return (0); -#endif + goto fail; } } @@ -1226,10 +1075,7 @@ { printk(KERN_INFO "DC390: Ignore target %02x lun %02x\n", cmd->device->id, cmd->device->lun); - DC390_UNLOCK_ACB; - //return (1); - done (cmd); - return (0); + goto fail; } else { @@ -1238,60 +1084,34 @@ { /* should never happen */ printk (KERN_ERR "DC390: no DCB failed, target %02x lun %02x\n", cmd->device->id, cmd->device->lun); - DC390_UNLOCK_ACB; - printk ("DC390: No DCB in queuecommand (2)!\n"); -#ifdef USE_NEW_EH - return (1); -#else - done (cmd); - return (0); -#endif + goto fail; } } pACB->Cmds++; cmd->scsi_done = done; cmd->result = 0; - - dc390_Query_to_Waiting (pACB); - if( pACB->QueryCnt ) /* Unsent commands ? */ - { - DEBUG0(printk ("DC390: QueryCnt != 0\n")); - dc390_Query_append ( cmd, pACB ); - dc390_Waiting_process (pACB); - } - else if (pDCB->pWaitingSRB) - { - pSRB = dc390_Free_get ( pACB ); - DEBUG0(if (!pSRB) printk ("DC390: No free SRB but Waiting\n"); else printk ("DC390: Free SRB w/ Waiting\n")); - if (!pSRB) dc390_Query_append (cmd, pACB); - else - { - dc390_BuildSRB (cmd, pDCB, pSRB); - dc390_Waiting_append (pDCB, pSRB); - } - dc390_Waiting_process (pACB); - } - else - { - pSRB = dc390_Free_get ( pACB ); - DEBUG0(if (!pSRB) printk ("DC390: No free SRB w/o Waiting\n"); else printk ("DC390: Free SRB w/o Waiting\n")); - if (!pSRB) - { - dc390_Query_append (cmd, pACB); - dc390_Waiting_process (pACB); - } - else - { - dc390_BuildSRB (cmd, pDCB, pSRB); - dc390_SendSRB (pACB, pSRB); - } - } + pSRB = dc390_Free_get(pACB); + if (!pSRB) + goto requeue; + + dc390_BuildSRB(cmd, pDCB, pSRB); + if (pDCB->pWaitingSRB) { + dc390_Waiting_append(pDCB, pSRB); + dc390_Waiting_process(pACB); + } else + dc390_SendSRB(pACB, pSRB); - DC390_UNLOCK_ACB; DEBUG1(printk (KERN_DEBUG " ... command (pid %li) queued successfully.\n", cmd->pid)); return(0); + + requeue: + return 1; + fail: + cmd->result = DID_BAD_TARGET << 16; + done(cmd); + return 0; } /* We ignore mapping problems, as we expect everybody to respect @@ -1384,8 +1204,8 @@ * Note: * In contrary to other externally callable funcs (DC390_), we don't lock ***********************************************************************/ -int DC390_bios_param (struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int geom[]) +static int DC390_bios_param (struct scsi_device *sdev, struct block_device *bdev, + sector_t capacity, int geom[]) { int heads, sectors, cylinders; PACB pACB = (PACB) sdev->host->hostdata; @@ -1421,15 +1241,14 @@ return (0); } #else -int DC390_bios_param (struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int geom[]) +static int DC390_bios_param (struct scsi_device *sdev, struct block_device *bdev, + sector_t capacity, int geom[]) { return scsicam_bios_param (bdev, capacity, geom); } #endif - -void dc390_dumpinfo (PACB pACB, PDCB pDCB, PSRB pSRB) +static void dc390_dumpinfo (PACB pACB, PDCB pDCB, PSRB pSRB) { USHORT pstat; PDEVDECL1; if (!pDCB) pDCB = pACB->pActiveDCB; @@ -1483,7 +1302,7 @@ * Status: Buggy ! ***********************************************************************/ -int DC390_abort (Scsi_Cmnd *cmd) +static int DC390_abort (Scsi_Cmnd *cmd) { PDCB pDCB; PSRB pSRB, psrb; @@ -1491,28 +1310,10 @@ int status; //ULONG sbac; PACB pACB = (PACB) cmd->device->host->hostdata; - DC390_AFLAGS; - - DC390_LOCK_ACB; printk ("DC390: Abort command (pid %li, Device %02i-%02i)\n", cmd->pid, cmd->device->id, cmd->device->lun); - /* First scan Query list */ - if( pACB->QueryCnt ) - { - struct scsi_cmnd_list *t, *pcmd_l; - list_for_each_entry_safe(pcmd_l, t, &pACB->cmdq, scp.list) - if( (struct scsi_cmnd*)pcmd_l == cmd ) - { - /* Found: Dequeue */ - list_del(&pcmd_l->scp.list); - pACB->QueryCnt--; - status = SCSI_ABORT_SUCCESS; - goto ABO_X; - } - } - pDCB = dc390_findDCB (pACB, cmd->device->id, cmd->device->lun); if( !pDCB ) goto NOT_RUN; @@ -1625,7 +1426,6 @@ } #endif dc390_lastabortedpid = cmd->pid; - DC390_UNLOCK_ACB; //do_DC390_Interrupt (pACB->IRQLevel, 0, 0); #ifndef USE_NEW_EH if (status == SCSI_ABORT_SUCCESS) cmd->scsi_done(cmd); @@ -1708,15 +1508,13 @@ * Returns : 0 on success. ***********************************************************************/ -int DC390_reset (Scsi_Cmnd *cmd) +static int DC390_reset (Scsi_Cmnd *cmd) { UCHAR bval; PACB pACB = (PACB) cmd->device->host->hostdata; - DC390_AFLAGS; printk(KERN_INFO "DC390: RESET ... "); - DC390_LOCK_ACB; if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer); bval = DC390_read8 (CtrlReg1); bval |= DIS_INT_ON_SCSI_RST; @@ -1745,7 +1543,6 @@ dc390_Waiting_process( pACB ); printk("done\n"); - DC390_UNLOCK_ACB; return( SCSI_RESET_SUCCESS ); } @@ -1760,14 +1557,14 @@ * Inputs : SCSI id and lun ***********************************************************************/ -void dc390_initDCB( PACB pACB, PDCB *ppDCB, UCHAR id, UCHAR lun ) +static void dc390_initDCB( PACB pACB, PDCB *ppDCB, UCHAR id, UCHAR lun ) { PEEprom prom; UCHAR index; PDCB pDCB, pDCB2; pDCB = kmalloc (sizeof(DC390_DCB), GFP_ATOMIC); - DCBDEBUG(printk (KERN_INFO "DC390: alloc mem for DCB (ID %i, LUN %i): %p\n" \ + DCBDEBUG(printk (KERN_INFO "DC390: alloc mem for DCB (ID %i, LUN %i): %p\n", \ id, lun, pDCB)); *ppDCB = pDCB; @@ -1845,7 +1642,7 @@ * Purpose : Set the configuration dependent DCB parameters ***********************************************************************/ -void dc390_updateDCB (PACB pACB, PDCB pDCB) +static void dc390_updateDCB (PACB pACB, PDCB pDCB) { pDCB->SyncMode &= EN_TAG_QUEUEING | SYNC_NEGO_DONE /*| EN_ATN_STOP*/; if (pDCB->DevMode & TAG_QUEUEING_) { @@ -1869,25 +1666,6 @@ pDCB->CtrlR1 |= PARITY_ERR_REPO; } - -/*********************************************************************** - * Function : static void dc390_updateDCBs () - * - * Purpose : Set the configuration dependent DCB params for all DCBs - ***********************************************************************/ - -static void dc390_updateDCBs (PACB pACB) -{ - int i; - PDCB pDCB = pACB->pLinkDCB; - for (i = 0; i < pACB->DCBCnt; i++) - { - dc390_updateDCB (pACB, pDCB); - pDCB = pDCB->pNextDCB; - } -} - - /*********************************************************************** * Function : static void dc390_initSRB() * @@ -1902,7 +1680,7 @@ } -void dc390_linkSRB( PACB pACB ) +static void dc390_linkSRB( PACB pACB ) { UINT count, i; @@ -1927,11 +1705,10 @@ * io_port, Irq, index: Resources and adapter index ***********************************************************************/ -void __init dc390_initACB (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index) +static void __init dc390_initACB (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index) { PACB pACB; UCHAR i; - DC390_AFLAGS; psh->can_queue = MAX_CMD_QUEUE; psh->cmd_per_lun = MAX_CMD_PER_LUN; @@ -1939,11 +1716,7 @@ psh->io_port = io_port; psh->n_io_port = 0x80; psh->irq = Irq; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,50) psh->base = io_port; -#else - psh->base = (char*)io_port; -#endif psh->unique_id = io_port; psh->dma_channel = -1; psh->last_reset = jiffies; @@ -1970,8 +1743,6 @@ pACB->pActiveDCB = NULL; pACB->pFreeSRB = pACB->SRB_array; pACB->SRBCount = MAX_SRB_CNT; - pACB->QueryCnt = 0; - INIT_LIST_HEAD(&pACB->cmdq); pACB->AdapterIndex = index; pACB->status = 0; psh->this_id = dc390_eepromBuf[index][EE_ADAPT_SCSI_ID]; @@ -2007,7 +1778,7 @@ * Outputs: 0 on success, -1 on error ***********************************************************************/ -int __init dc390_initAdapter (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index) +static int __init dc390_initAdapter (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index) { PACB pACB, pACB2; UCHAR dstate; @@ -2086,7 +1857,7 @@ * Inputs : host - pointer to this host adapter's structure * io_port - IO ports mapped to this adapter * Irq - IRQ assigned to this adpater - * PDEVDECL - PCI access handle + * struct pci_dev - PCI access handle * index - Adapter index * * Outputs: 0 on success, -1 on error @@ -2095,12 +1866,11 @@ * not in DC390_detect, called from outside ***********************************************************************/ -static int __init DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, PDEVDECL, UCHAR index) +static int __init DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, struct pci_dev *pdev, UCHAR index) { PSH psh; PACB pACB; - DC390_AFLAGS; - + if (dc390_CheckEEpromCheckSum (PDEV, index)) { int speed; @@ -2126,21 +1896,6 @@ scsi_set_device(psh, &pdev->dev); pACB = (PACB) psh->hostdata; - DC390_LOCKA_INIT; - DC390_LOCK_ACB; - -#if 0 - if( !dc390_pSH_start ) - { - dc390_pSH_start = psh; - dc390_pSH_current = psh; - } - else - { - dc390_pSH_current->next = psh; - dc390_pSH_current = psh; - } -#endif DEBUG0(printk(KERN_INFO "DC390: pSH = %8x, Index %02i\n", (UINT) psh, index)); @@ -2154,59 +1909,15 @@ (UINT) pACB, (UINT) pACB->DCBmap, (UINT) pACB->SRB_array)); DEBUG0(printk("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n",\ sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) )); - - DC390_UNLOCK_ACB; return (0); } else { - //dc390_pSH_start = NULL; scsi_unregister( psh ); - DC390_UNLOCK_ACB; return( -1 ); } } - -/*********************************************************************** - * Function : int DC390_detect(Scsi_Host_Template *psht) - * - * Purpose : detects and initializes AMD53C974 SCSI chips - * that were autoprobed, overridden on the LILO command line, - * or specified at compile time. - * - * Inputs : psht - template for this SCSI adapter - * - * Returns : number of host adapters detected - * - ***********************************************************************/ - -#ifndef NEW_PCI -/* Acc. to PCI 2.1 spec it's up to the driver to enable Bus mastering: - * We use pci_set_master () for 2.1.x and this func for 2.0.x: */ -static void __init dc390_set_master (PDEVDECL) -{ - USHORT cmd; - UCHAR lat; - - PCI_READ_CONFIG_WORD (PDEV, PCI_COMMAND, &cmd); - - if (! (cmd & PCI_COMMAND_MASTER)) { - printk("PCI: Enabling bus mastering for device %02x:%02x\n", - PCI_BUS_DEV); - cmd |= PCI_COMMAND_MASTER; - PCI_WRITE_CONFIG_WORD(PDEV, PCI_COMMAND, cmd); - } - PCI_READ_CONFIG_BYTE (PDEV, PCI_LATENCY_TIMER, &lat); - if (lat < 16 /* || lat == 255 */) { - printk("PCI: Setting latency timer of device %02x:%02x from %i to 64\n", - PCI_BUS_DEV, lat); - PCI_WRITE_CONFIG_BYTE(PDEV, PCI_LATENCY_TIMER, 64); - } - -} -#endif /* ! NEW_PCI */ - static void __init dc390_set_pci_cfg (PDEVDECL) { USHORT cmd; @@ -2215,30 +1926,31 @@ PCI_WRITE_CONFIG_WORD (PDEV, PCI_COMMAND, cmd); PCI_WRITE_CONFIG_WORD (PDEV, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY)); } - int __init DC390_detect (Scsi_Host_Template *psht) { - PDEVDECL0; + struct pci_dev *pdev = NULL; UCHAR irq; ULONG io_port; - //dc390_pSHT_start = psht; dc390_pACB_start = NULL; if ( PCI_PRESENT ) - while (PCI_FIND_DEVICE (PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974)) + while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974, pdev))) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,30) if (pci_enable_device (pdev)) continue; -#endif + + if (pci_set_dma_mask(pdev, 0xffffffff)) { + printk(KERN_ERR "DC390(%i): No suitable DMA available.\n", dc390_adapterCnt); + continue; + } PCI_GET_IO_AND_IRQ; DEBUG0(printk(KERN_INFO "DC390(%i): IO_PORT=%04x,IRQ=%x\n", dc390_adapterCnt, (UINT) io_port, irq)); if( !DC390_init(psht, io_port, irq, PDEV, dc390_adapterCnt)) { - PCI_SET_MASTER; + pci_set_master(pdev); dc390_set_pci_cfg (PDEV); dc390_adapterCnt++; } @@ -2247,495 +1959,12 @@ printk (KERN_ERR "DC390: No PCI BIOS found!\n"); if (dc390_adapterCnt) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30) psht->proc_name = "tmscsim"; -#else - psht->proc_dir = &DC390_proc_scsi_tmscsim; -#endif + printk(KERN_INFO "DC390: %i adapters found\n", dc390_adapterCnt); return( dc390_adapterCnt ); } - -/*********************************************************************** - * Functions: dc390_inquiry(), dc390_inquiry_done() - * - * Purpose: When changing speed etc., we have to issue an INQUIRY - * command to make sure, we agree upon the nego parameters - * with the device - ***********************************************************************/ - -static void dc390_inquiry_done (Scsi_Cmnd* cmd) -{ - printk (KERN_INFO "DC390: INQUIRY (ID %02x LUN %02x) returned %08x\n", - cmd->device->id, cmd->device->lun, cmd->result); - if (cmd->result) - { - PACB pACB = (PACB)cmd->device->host->hostdata; - PDCB pDCB = dc390_findDCB (pACB, cmd->device->id, cmd->device->lun); - printk ("DC390: Unsetting DsCn, Sync and TagQ!\n"); - if (pDCB) - { - pDCB->DevMode &= ~(SYNC_NEGO_ | TAG_QUEUEING_ | EN_DISCONNECT_ ); - dc390_updateDCB (pACB, pDCB); - } - } - kfree (cmd); -} - -void dc390_inquiry (PACB pACB, PDCB pDCB) -{ - char* buffer; - Scsi_Cmnd* cmd; - cmd = kmalloc (sizeof(Scsi_Cmnd) + 256, GFP_ATOMIC); - if (!cmd) { printk ("DC390: kmalloc failed in inquiry!\n"); return; } - buffer = (char*)cmd + sizeof(Scsi_Cmnd); - - memset (cmd, 0, sizeof(Scsi_Cmnd) + 256); - cmd->cmnd[0] = INQUIRY; - cmd->cmnd[1] = (pDCB->TargetLUN << 5) & 0xe0; - cmd->cmnd[4] = 0xff; - - cmd->cmd_len = 6; cmd->old_cmd_len = 6; -/* TODO FIXME */ -/* cmd->host = pACB->pScsiHost; */ - cmd->device->id = pDCB->TargetID; - cmd->device->lun = pDCB->TargetLUN; - cmd->serial_number = 1; - cmd->pid = 390; - cmd->bufflen = 128; - cmd->buffer = buffer; - cmd->request_bufflen = 128; - cmd->request_buffer = &buffer[128]; - cmd->done = dc390_inquiry_done; - cmd->scsi_done = dc390_inquiry_done; - cmd->timeout_per_command = HZ; - - cmd->request->rq_status = RQ_SCSI_BUSY; - - pDCB->SyncMode &= ~SYNC_NEGO_DONE; - printk (KERN_INFO "DC390: Queue INQUIRY command to dev ID %02x LUN %02x\n", - pDCB->TargetID, pDCB->TargetLUN); - DC390_queue_command (cmd, dc390_inquiry_done); -} - -/*********************************************************************** - * Functions: dc390_sendstart(), dc390_sendstart_done() - * - * Purpose: When changing speed etc., we have to issue an INQUIRY - * command to make sure, we agree upon the nego parameters - * with the device - ***********************************************************************/ - -static void dc390_sendstart_done (Scsi_Cmnd* cmd) -{ - printk (KERN_INFO "DC390: SENDSTART (ID %02x LUN %02x) returned %08x\n", - cmd->device->id, cmd->device->lun, cmd->result); - kfree (cmd); -} - -void dc390_sendstart (PACB pACB, PDCB pDCB) -{ - char* buffer; - Scsi_Cmnd* cmd; - cmd = kmalloc (sizeof(Scsi_Cmnd) + 256, GFP_ATOMIC); - if (!cmd) { printk ("DC390: kmalloc failed in sendstart!\n"); return; } - buffer = (char*)cmd + sizeof(Scsi_Cmnd); - - memset (cmd, 0, sizeof(Scsi_Cmnd) + 256); - cmd->cmnd[0] = 0x1b; /* START_STOP_UNIT */ - cmd->cmnd[1] = (pDCB->TargetLUN << 5) & 0xe0; - cmd->cmnd[4] = 0x01; /* START */ - - cmd->cmd_len = 6; cmd->old_cmd_len = 6; -/* TODO FIXME */ -/* cmd->host = pACB->pScsiHost; */ - cmd->device->id = pDCB->TargetID; - cmd->device->lun = pDCB->TargetLUN; - cmd->serial_number = 1; - cmd->pid = 310; - cmd->bufflen = 128; - cmd->buffer = buffer; - cmd->request_bufflen = 128; - cmd->request_buffer = &buffer[128]; - cmd->done = dc390_sendstart_done; - cmd->scsi_done = dc390_sendstart_done; - cmd->timeout_per_command = 5*HZ; - - cmd->request->rq_status = RQ_SCSI_BUSY; - - pDCB->SyncMode &= ~SYNC_NEGO_DONE; - printk (KERN_INFO "DC390: Queue SEND_START command to dev ID %02x LUN %02x\n", - pDCB->TargetID, pDCB->TargetLUN); - DC390_queue_command (cmd, dc390_sendstart_done); -} - -/******************************************************************** - * Function: dc390_set_info() - * - * Purpose: Change adapter config - * - * Strings are parsed similar to the output of tmscsim_proc_info () - * '-' means no change - *******************************************************************/ - -static int dc390_scanf (char** buffer, char** pos, char** p0, int* var) -{ - *p0 = *pos; - *var = simple_strtoul (*p0, pos, 10); - if (*p0 == *pos) return -1; - *pos = strsep (buffer, " \t\n:=,;."); - return 0; -} - -#define SCANF(buffer, pos, p0, var, min, max) \ -if (dc390_scanf (&buffer, &pos, &p0, &var)) goto einv; \ -else if (varmax) goto einv2 - -static int dc390_yesno (char** buffer, char** pos, char* var, char bmask) -{ - switch (**pos) - { - case 'Y': *var |= bmask; break; - case 'N': *var &= ~bmask; break; - case '-': break; - default: return -1; - } - *pos = strsep (buffer, " \t\n:=,;"); - return 0; -} - -#define YESNO(buffer, pos, var, bmask) \ - if (dc390_yesno (&buffer, &pos, &var, bmask)) goto einv; \ - else dc390_updateDCB (pACB, pDCB); \ - if (!pos) goto ok - -static int dc390_search (char** buffer, char** pos, char** p0, char* var, char* txt, int max, int scale, char* ign) -{ - int dum; - if (! memcmp (*pos, txt, strlen(txt))) - { - *p0 = strsep (buffer, " \t\n:=,;"); - if (!*p0) return -1; - dum = simple_strtoul (*p0, pos, 10); - if (*p0 == *pos) return -1; - if (dum >= 0 && dum <= max) - { *var = (dum * 100) / scale; } - else return -2; - *pos = strsep (buffer, " \t\n:=,;"); - if (*ign && *pos && strlen(*pos) >= strlen(ign) && - !(memcmp (*pos, ign, strlen(ign)))) - *pos = strsep (buffer, " \t\n:=,;"); - - } - return 0; -} - -#define SEARCH(buffer, pos, p0, var, txt, max) \ -if (dc390_search (&buffer, &pos, &p0, (PUCHAR)(&var), txt, max, 100, "")) goto einv2; \ -else if (!p1) goto ok2 - -#define SEARCH2(buffer, pos, p0, var, txt, max, scale) \ -if (dc390_search (&buffer, &pos, &p0, &var, txt, max, scale, "")) goto einv2; \ -else if (!p1) goto ok2 - -#define SEARCH3(buffer, pos, p0, var, txt, max, scale, ign) \ -if (dc390_search (&buffer, &pos, &p0, &var, txt, max, scale, ign)) goto einv2; \ -else if (!p1) goto ok2 - - -#ifdef DC390_PARSEDEBUG -static char _prstr[256]; -char* prstr (char* p, char* e) -{ - char* c = _prstr; - while (p < e) - if (*p == 0) { *c++ = ':'; p++; } - else if (*p == 10) { *c++ = '\\'; *c++ = 'n'; p++; } - else *c++ = *p++; - *c = 0; - return _prstr; -} -#endif - -int dc390_set_info (char *buffer, int length, PACB pACB) -{ - char *pos = buffer, *p0 = buffer; - char needs_inquiry = 0; - int dum = 0; - char dev; - PDCB pDCB = pACB->pLinkDCB; - DC390_IFLAGS; - DC390_AFLAGS; - pos[length] = 0; - - DC390_LOCK_IO(pACB->pScsiHost); - DC390_LOCK_ACB; - /* UPPERCASE */ - /* Don't use kernel toupper, because of 2.0.x bug: ctmp unexported */ - while (*pos) - { if (*pos >='a' && *pos <= 'z') *pos = *pos + 'A' - 'a'; pos++; } - - /* Remove WS */ - pos = strsep (&buffer, " \t:\n=,;"); - if (!*pos) goto ok; - - next: - if (!memcmp (pos, "RESET", 5)) goto reset; - else if (!memcmp (pos, "INQUIRY", 7)) goto inquiry; - else if (!memcmp (pos, "REMOVE", 6)) goto remove; - else if (!memcmp (pos, "ADD", 3)) goto add; - else if (!memcmp (pos, "START", 5)) goto start; - else if (!memcmp (pos, "DUMP", 4)) goto dump; - - if (isdigit (*pos)) - { - /* Device config line */ - int dev, id, lun; char* pdec; - char olddevmode; - - SCANF (buffer, pos, p0, dev, 0, pACB->DCBCnt-1); - if (*pos) { SCANF (buffer, pos, p0, id, 0, 7); } else goto einv; - if (*pos) { SCANF (buffer, pos, p0, lun, 0, 7); } else goto einv; - if (!*pos) goto einv; - - PARSEDEBUG(printk (KERN_INFO "DC390: config line %i %i %i:\"%s\"\n", dev, id, lun, prstr (pos, &buffer[length]))); - pDCB = pACB->pLinkDCB; - for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB; - /* Sanity Check */ - if (pDCB->TargetID != id || pDCB->TargetLUN != lun) - { - printk (KERN_ERR "DC390: no such device: Idx=%02i ID=%02i LUN=%02i\n", - dev, id, lun); - goto einv2; - } - - if (pDCB->pWaitingSRB || pDCB->pGoingSRB) - { - printk ("DC390: Cannot change dev (%i-%i) cfg: Pending requests\n", - pDCB->TargetID, pDCB->TargetLUN); - goto einv; - } - - olddevmode = pDCB->DevMode; - YESNO (buffer, pos, pDCB->DevMode, PARITY_CHK_); - needs_inquiry++; - YESNO (buffer, pos, pDCB->DevMode, SYNC_NEGO_); - if ((olddevmode & SYNC_NEGO_) == (pDCB->DevMode & SYNC_NEGO_)) needs_inquiry--; - needs_inquiry++; - YESNO (buffer, pos, pDCB->DevMode, EN_DISCONNECT_); - if ((olddevmode & EN_DISCONNECT_) == (pDCB->DevMode & EN_DISCONNECT_)) needs_inquiry--; - YESNO (buffer, pos, pDCB->DevMode, SEND_START_); - needs_inquiry++; - YESNO (buffer, pos, pDCB->DevMode, TAG_QUEUEING_); - if ((olddevmode & TAG_QUEUEING_) == (pDCB->DevMode & TAG_QUEUEING_)) needs_inquiry--; - - dc390_updateDCB (pACB, pDCB); - if (!*pos) goto ok; - - olddevmode = pDCB->NegoPeriod; - /* Look for decimal point (Speed) */ - pdec = pos; - while (pdec++ < &buffer[length]) if (*pdec == '.') break; - /* NegoPeriod */ - if (*pos != '-') - { - SCANF (buffer, pos, p0, dum, 72, 800); - pDCB->NegoPeriod = dum >> 2; - if (pDCB->NegoPeriod != olddevmode) needs_inquiry++; - if (!pos) goto ok; - if (memcmp (pos, "NS", 2) == 0) pos = strsep (&pos, " \t\n:=,;."); - } - else pos = strsep (&pos, " \t\n:=,;."); - if (!*pos) goto ok; - - /* Sync Speed in MHz */ - if (*pos != '-') - { - SCANF (buffer, pos, p0, dum, 1, 13); - pDCB->NegoPeriod = (1000/dum) >> 2; - if (pDCB->NegoPeriod != olddevmode && !pos) needs_inquiry++; - if (!*pos) goto ok; - /* decimal */ - if (pos-1 == pdec) - { - int dumold = dum; - dum = simple_strtoul (pos, &p0, 10) * 10; - for (; p0-pos > 1; p0--) dum /= 10; - pDCB->NegoPeriod = (100000/(100*dumold + dum)) >> 2; - if (pDCB->NegoPeriod < 19) pDCB->NegoPeriod = 19; - pos = strsep (&pos, " \t\n:=,;"); - if (!*pos) goto ok; - } - if (*pos == 'M') pos = strsep (&pos, " \t\n:=,;"); - if (pDCB->NegoPeriod != olddevmode) needs_inquiry++; - } - else pos = strsep (&pos, " \t\n:=,;"); - /* dc390_updateDCB (pACB, pDCB); */ - if (!*pos) goto ok; - - olddevmode = pDCB->SyncOffset; - /* SyncOffs */ - if (*pos != '-') - { - SCANF (buffer, pos, p0, dum, 0, 0x0f); - pDCB->SyncOffset = dum; - if (pDCB->SyncOffset > olddevmode) needs_inquiry++; - } - else pos = strsep (&pos, " \t\n:=,;"); - if (!*pos) goto ok; - dc390_updateDCB (pACB, pDCB); - - //olddevmode = pDCB->MaxCommand; - /* MaxCommand (Tags) */ - if (*pos != '-') - { - SCANF (buffer, pos, p0, dum, 1, 32 /*pACB->TagMaxNum*/); - if (pDCB->SyncMode & EN_TAG_QUEUEING) - pDCB->MaxCommand = dum; - else printk (KERN_INFO "DC390: Can't set MaxCmd larger than one without Tag Queueing!\n"); - } - else pos = strsep (&pos, " \t\n:=,;"); - - } - else - { - char* p1 = pos; UCHAR dum, newadaptid; - PARSEDEBUG(printk (KERN_INFO "DC390: chg adapt cfg \"%s\"\n", prstr (pos, &buffer[length]))); - dum = GLITCH_TO_NS (pACB->glitch_cfg); - /* Adapter setting */ - SEARCH (buffer, pos, p0, pACB->pScsiHost->max_id, "MAXID", 8); - SEARCH (buffer, pos, p0, pACB->pScsiHost->max_lun, "MAXLUN", 8); - SEARCH (buffer, pos, p0, newadaptid, "ADAPTERID", 7); - SEARCH (buffer, pos, p0, pACB->TagMaxNum, "TAGMAXNUM", 32); - SEARCH (buffer, pos, p0, pACB->ACBFlag, "ACBFLAG", 255); - SEARCH3 (buffer, pos, p0, dum, "GLITCHEATER", 40, 1000, "NS"); - SEARCH3 (buffer, pos, p0, pACB->sel_timeout, "SELTIMEOUT", 400, 163, "MS"); - SEARCH3 (buffer, pos, p0, dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY], "DELAYRESET", 180, 100, "S"); - ok2: - pACB->glitch_cfg = NS_TO_GLITCH (dum); - if (pACB->sel_timeout < 60) pACB->sel_timeout = 60; - DC390_write8 (Scsi_TimeOut, pACB->sel_timeout); - if (newadaptid != pACB->pScsiHost->this_id) - { - pACB->pScsiHost->this_id = newadaptid; - dc390_ResetDevParam (pACB); - } - //dum = 0; while (1 << dum <= pACB->TagMaxNum) dum ++; - //pACB->TagMaxNum &= (1 << --dum); - dc390_updateDCBs (pACB); - // All devs should be INQUIRED now - if (pos == p1) goto einv; - } - if (*pos) goto next; - - ok: - DC390_UNLOCK_ACB; - if (needs_inquiry) - { dc390_updateDCB (pACB, pDCB); dc390_inquiry (pACB, pDCB); } - DC390_UNLOCK_IO(pACB->pScsiHost); - return (length); - - einv2: - pos = p0; - einv: - DC390_UNLOCK_ACB; - DC390_UNLOCK_IO(pACB->pScsiHost); - printk (KERN_WARNING "DC390: parse error near \"%s\"\n", (pos? pos: "NULL")); - return (-EINVAL); - - reset: - { - Scsi_Cmnd cmd; - /* TODO FIXME */ - /* cmd.host = pACB->pScsiHost; */ - printk (KERN_WARNING "DC390: Driver reset requested!\n"); - DC390_UNLOCK_ACB; - DC390_reset (&cmd); - DC390_UNLOCK_IO(pACB->pScsiHost); - } - return (length); - - dump: - { - dc390_dumpinfo (pACB, 0, 0); - DC390_UNLOCK_ACB; - DC390_UNLOCK_IO(pACB->pScsiHost); - } - return (length); - - inquiry: - { - pos = strsep (&pos, " \t\n.:;="); if (!*pos) goto einv; - dev = simple_strtoul (pos, &p0, 10); - if (dev >= pACB->DCBCnt) goto einv_dev; - for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB; - printk (KERN_NOTICE " DC390: Issue INQUIRY command to Dev(Idx) %i SCSI ID %i LUN %i\n", - dev, pDCB->TargetID, pDCB->TargetLUN); - DC390_UNLOCK_ACB; - dc390_inquiry (pACB, pDCB); - DC390_UNLOCK_IO(pACB->pScsiHost); - } - return (length); - - remove: - { - pos = strsep (&pos, " \t\n.:;="); if (!*pos) goto einv; - dev = simple_strtoul (pos, &p0, 10); - if (dev >= pACB->DCBCnt) goto einv_dev; - for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB; - printk (KERN_NOTICE " DC390: Remove DCB for Dev(Idx) %i SCSI ID %i LUN %i\n", - dev, pDCB->TargetID, pDCB->TargetLUN); - /* TO DO: We should make sure no pending commands are left */ - dc390_remove_dev (pACB, pDCB); - DC390_UNLOCK_ACB; - DC390_UNLOCK_IO(pACB->pScsiHost); - } - return (length); - - add: - { - int id, lun; - pos = strsep (&pos, " \t\n.:;="); - if (*pos) { SCANF (buffer, pos, p0, id, 0, 7); } else goto einv; - if (*pos) { SCANF (buffer, pos, p0, lun, 0, 7); } else goto einv; - pDCB = dc390_findDCB (pACB, id, lun); - if (pDCB) { printk ("DC390: ADD: Device already existing\n"); goto einv; } - dc390_initDCB (pACB, &pDCB, id, lun); - DC390_UNLOCK_ACB; - dc390_inquiry (pACB, pDCB); - DC390_UNLOCK_IO(pACB->pScsiHost); - } - return (length); - - start: - { - int id, lun; - pos = strsep (&pos, " \t\n.:;="); - if (*pos) { SCANF (buffer, pos, p0, id, 0, 7); } else goto einv; - if (*pos) { SCANF (buffer, pos, p0, lun, 0, 7); } else goto einv; - pDCB = dc390_findDCB (pACB, id, lun); - if (pDCB) printk ("DC390: SendStart: Device already existing ...\n"); - else dc390_initDCB (pACB, &pDCB, id, lun); - DC390_UNLOCK_ACB; - dc390_sendstart (pACB, pDCB); - dc390_inquiry (pACB, pDCB); - DC390_UNLOCK_IO(pACB->pScsiHost); - } - return (length); - - einv_dev: - printk (KERN_WARNING "DC390: Ignore cmnd to invalid Dev(Idx) %i. Valid range: 0 - %i.\n", - dev, pACB->DCBCnt - 1); - DC390_UNLOCK_ACB; - DC390_UNLOCK_IO(pACB->pScsiHost); - return (-EINVAL); -} - -#undef SEARCH -#undef YESNO -#undef SCANF - /******************************************************************** * Function: DC390_proc_info(char* buffer, char **start, * off_t offset, int length, int hostno, int inout) @@ -2763,15 +1992,13 @@ else SPRINTF(" No ") -int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start, - off_t offset, int length, int inout) +static int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start, + off_t offset, int length, int inout) { int dev, spd, spd1; char *pos = buffer; - struct scsi_cmnd_list *cl; PACB pACB; PDCB pDCB; - DC390_AFLAGS; pACB = dc390_pACB_start; @@ -2785,13 +2012,11 @@ if (pACB == (PACB)-1) return(-ESRCH); if(inout) /* Has data been written to the file ? */ - return dc390_set_info(buffer, length, pACB); + return -ENOSYS; SPRINTF("Tekram DC390/AM53C974 PCI SCSI Host Adapter, "); SPRINTF("Driver Version %s\n", DC390_VERSION); - DC390_LOCK_ACB; - SPRINTF("SCSI Host Nr %i, ", shpnt->host_no); SPRINTF("%s Adapter Nr %i\n", dc390_adapname, pACB->AdapterIndex); SPRINTF("IOPortBase 0x%04x, ", pACB->IOPortBase); @@ -2839,9 +2064,6 @@ SPRINTF (" %02i\n", pDCB->MaxCommand); pDCB = pDCB->pNextDCB; } - SPRINTF ("Commands in Queues: Query: %li:", pACB->QueryCnt); - list_for_each_entry(cl, &pACB->cmdq, scp.list) - SPRINTF (" %li", ((struct scsi_cmnd*)cl)->pid); if (timer_pending(&pACB->Waiting_Timer)) SPRINTF ("Waiting queue timer running\n"); else SPRINTF ("\n"); pDCB = pACB->pLinkDCB; @@ -2876,8 +2098,6 @@ SPRINTF("\n"); #endif - - DC390_UNLOCK_ACB; *start = buffer + offset; if (pos - buffer < offset) @@ -2919,7 +2139,7 @@ return( 0 ); } -void dc390_freeDCBs (struct Scsi_Host *host) +static void dc390_freeDCBs (struct Scsi_Host *host) { PDCB pDCB, nDCB; PACB pACB = (PACB)(host->hostdata); @@ -2938,13 +2158,12 @@ } -int DC390_release (struct Scsi_Host *host) +static int DC390_release (struct Scsi_Host *host) { - DC390_AFLAGS DC390_IFLAGS; + DC390_IFLAGS; PACB pACB = (PACB)(host->hostdata); DC390_LOCK_IO(host); - DC390_LOCK_ACB; /* TO DO: We should check for outstanding commands first. */ dc390_shutdown (host); @@ -2957,7 +2176,6 @@ release_region(host->io_port,host->n_io_port); dc390_freeDCBs (host); - DC390_UNLOCK_ACB; DC390_UNLOCK_IO(host); scsi_unregister(host); return( 1 ); --- diff/drivers/scsi/tmscsim.h 2004-05-19 22:12:12.000000000 +0100 +++ source/drivers/scsi/tmscsim.h 2004-05-27 18:34:18.000000000 +0100 @@ -214,16 +214,12 @@ PSRB pTmpSRB; /* 0x2c: */ -ULONG QueryCnt; -struct list_head cmdq; - -/* 0x38: */ UCHAR msgin123[4]; UCHAR DCBmap[MAX_SCSI_ID]; UCHAR Connected; UCHAR pad; -/* 0x3c: */ +/* 0x30: */ #if defined(USE_SPINLOCKS) && USE_SPINLOCKS > 1 && (defined(CONFIG_SMP) || DEBUG_SPINLOCKS > 0) spinlock_t lock; #endif @@ -234,20 +230,20 @@ UCHAR Ignore_IRQ; /* Not used */ PDEVDECL1; /* Pointer to PCI cfg. space */ -/* 0x4c/0x48: */ +/* 0x40/0x3c: */ ULONG Cmds; UINT SelLost; UINT SelConn; UINT CmdInQ; UINT CmdOutOfSRB; -/* 0x60/0x5c: */ +/* 0x54/0x50: */ struct timer_list Waiting_Timer; -/* 0x74/0x70: */ +/* 0x68/0x64: */ DC390_SRB TmpSRB; -/* 0xd8/0xd4: */ +/* 0xcc/0xc8: */ DC390_SRB SRB_array[MAX_SRB_CNT]; /* 50 SRBs */ -/* 0xfb0/0xfac: */ +/* 0xfa4/0xfa0: */ }; typedef struct _ACB DC390_ACB, *PACB; @@ -406,16 +402,9 @@ * SISC query queue */ typedef struct { - struct list_head list; dma_addr_t saved_dma_handle; } dc390_cmd_scp_t; -struct scsi_cmnd_list -{ - char dummy[offsetof(struct scsi_cmnd, SCp)]; - dc390_cmd_scp_t scp; -}; - /* ** Inquiry Data format */ --- diff/drivers/scsi/wd7000.c 2004-05-19 22:12:12.000000000 +0100 +++ source/drivers/scsi/wd7000.c 2004-05-27 18:34:18.000000000 +0100 @@ -165,6 +165,7 @@ * Removed now obsolete wd7000.h */ +#include #include #include #include @@ -846,7 +847,7 @@ static inline Scb *alloc_scbs(struct Scsi_Host *host, int needed) { register Scb *scb, *p = NULL; - register unsigned long flags; + unsigned long flags; register unsigned long timeout = jiffies + WAITnexttimeout; register unsigned long now; int i; @@ -898,7 +899,7 @@ static inline void free_scb(Scb * scb) { - register unsigned long flags; + unsigned long flags; spin_lock_irqsave(&scbpool_lock, flags); @@ -936,7 +937,7 @@ */ { register int i, ogmb; - register unsigned long flags; + unsigned long flags; unchar start_ogmb; Mailbox *ogmbs = host->mb.ogmb; int *next_ogmb = &(host->next_ogmb); --- diff/drivers/serial/8250.c 2004-05-19 22:12:15.000000000 +0100 +++ source/drivers/serial/8250.c 2004-05-27 18:34:18.000000000 +0100 @@ -832,7 +832,7 @@ if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { tty->flip.work.func((void *)tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) - return; // if TTY_DONT_FLIP is set + return; /* if TTY_DONT_FLIP is set */ } ch = serial_inp(up, UART_RX); *tty->flip.char_buf_ptr = ch; @@ -1193,12 +1193,21 @@ spin_unlock_irqrestore(&up->port.lock, flags); } +#ifdef CONFIG_KGDB +static int kgdb_irq = -1; +#endif + static int serial8250_startup(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; unsigned long flags; int retval; +#ifdef CONFIG_KGDB + if (up->port.irq == kgdb_irq) + return -EBUSY; +#endif + up->capabilities = uart_config[up->port.type].flags; up->mcr = 0; @@ -1888,6 +1897,10 @@ for (i = 0; i < UART_NR; i++) { struct uart_8250_port *up = &serial8250_ports[i]; +#ifdef CONFIG_KGDB + if (up->port.irq == kgdb_irq) + up->port.kgdb = 1; +#endif up->port.line = i; up->port.ops = &serial8250_pops; init_timer(&up->timer); @@ -2171,6 +2184,31 @@ uart_resume_port(&serial8250_reg, &serial8250_ports[line].port); } +#ifdef CONFIG_KGDB +/* + * Find all the ports using the given irq and shut them down. + * Result should be that the irq will be released. + */ +void shutdown_for_kgdb(struct async_struct * info) +{ + int irq = info->state->irq; + struct uart_8250_port *up; + int ttyS; + + kgdb_irq = irq; /* save for later init */ + for (ttyS = 0; ttyS < UART_NR; ttyS++){ + up = &serial8250_ports[ttyS]; + if (up->port.irq == irq && (irq_lists + irq)->head) { +#ifdef CONFIG_DEBUG_SPINLOCK /* ugly business... */ + if(up->port.lock.magic != SPINLOCK_MAGIC) + spin_lock_init(&up->port.lock); +#endif + serial8250_shutdown(&up->port); + } + } +} +#endif /* CONFIG_KGDB */ + static int __init serial8250_init(void) { int ret, i; --- diff/drivers/serial/8250_acpi.c 2004-05-27 13:41:21.000000000 +0100 +++ source/drivers/serial/8250_acpi.c 2004-05-27 18:34:18.000000000 +0100 @@ -57,28 +57,18 @@ static acpi_status acpi_serial_ext_irq(struct serial_struct *req, struct acpi_resource_ext_irq *ext_irq) { - if (ext_irq->number_of_interrupts > 0) { -#ifdef CONFIG_IA64 - req->irq = acpi_register_irq(ext_irq->interrupts[0], - ext_irq->active_high_low, ext_irq->edge_level); -#else - req->irq = ext_irq->interrupts[0]; -#endif - } + if (ext_irq->number_of_interrupts > 0) + req->irq = acpi_register_gsi(ext_irq->interrupts[0], + ext_irq->edge_level, ext_irq->active_high_low); return AE_OK; } static acpi_status acpi_serial_irq(struct serial_struct *req, struct acpi_resource_irq *irq) { - if (irq->number_of_interrupts > 0) { -#ifdef CONFIG_IA64 - req->irq = acpi_register_irq(irq->interrupts[0], - irq->active_high_low, irq->edge_level); -#else - req->irq = irq->interrupts[0]; -#endif - } + if (irq->number_of_interrupts > 0) + req->irq = acpi_register_gsi(irq->interrupts[0], + irq->edge_level, irq->active_high_low); return AE_OK; } --- diff/drivers/serial/8250_hcdp.c 2004-05-19 22:12:15.000000000 +0100 +++ source/drivers/serial/8250_hcdp.c 2004-05-27 18:34:18.000000000 +0100 @@ -96,7 +96,11 @@ * of the entries for the same type device that has already * been parsed and initialized */ +#ifndef CONFIG_KGDB_EARLY if (hcdp_dev->type != HCDP_DEV_CONSOLE) +#else + if (hcdp_dev->type != HCDP_DEV_CONSOLE && hcdp_dev->type != HCDP_DEV_DEBUG) +#endif continue; iobase = ((u64) hcdp_dev->base_addr.addrhi << 32) | @@ -183,16 +187,12 @@ } if (HCDP_IRQ_SUPPORTED(hcdp_dev)) { -#ifdef CONFIG_IA64 if (HCDP_PCI_UART(hcdp_dev)) - port.irq = acpi_register_irq(gsi, - ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE); + port.irq = acpi_register_gsi(gsi, + ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW); else - port.irq = acpi_register_irq(gsi, - ACPI_ACTIVE_HIGH, ACPI_EDGE_SENSITIVE); -#else - port.irq = gsi; -#endif + port.irq = acpi_register_gsi(gsi, + ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH); port.flags |= UPF_AUTO_IRQ; if (HCDP_PCI_UART(hcdp_dev)) @@ -205,6 +205,7 @@ * Note: the above memset() initializes port.line to 0, * so we register this port as ttyS0. */ + port.line = (hcdp_dev->type == HCDP_DEV_CONSOLE) ? 0 : 1; if (early_serial_setup(&port) < 0) { printk("setup_serial_hcdp(): early_serial_setup() " "for HCDP serial console port failed. " @@ -218,7 +219,9 @@ hcdp_dev->baud, hcdp_dev->bits); add_preferred_console("ttyS", port.line, options); } +#ifndef CONFIG_KGDB_EARLY break; +#endif } #ifdef SERIAL_DEBUG_HCDP --- diff/drivers/serial/8250_pnp.c 2004-05-19 22:12:15.000000000 +0100 +++ source/drivers/serial/8250_pnp.c 2004-05-27 18:34:18.000000000 +0100 @@ -361,9 +361,6 @@ ((port->min == 0x2f8) || (port->min == 0x3f8) || (port->min == 0x2e8) || -#ifdef CONFIG_X86_PC9800 - (port->min == 0x8b0) || -#endif (port->min == 0x3e8))) return 1; } --- diff/drivers/serial/Kconfig 2004-05-19 22:12:15.000000000 +0100 +++ source/drivers/serial/Kconfig 2004-05-27 18:34:18.000000000 +0100 @@ -517,19 +517,6 @@ depends on V850E_UART select SERIAL_CORE_CONSOLE -config SERIAL98 - tristate "PC-9800 8251-based primary serial port support" - depends on X86_PC9800 - select SERIAL_CORE - help - If you want to use standard primary serial ports on PC-9800, - say Y. Otherwise, say N. - -config SERIAL98_CONSOLE - bool "Support for console on PC-9800 standard serial port" - depends on SERIAL98=y - select SERIAL_CORE_CONSOLE - config SERIAL_SH_SCI tristate "SH SCI(F) serial port support" depends on SUPERH || H8300 --- diff/drivers/serial/Makefile 2004-05-19 22:12:15.000000000 +0100 +++ source/drivers/serial/Makefile 2004-05-27 18:34:18.000000000 +0100 @@ -33,7 +33,6 @@ obj-$(CONFIG_SERIAL_68360) += 68360serial.o obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o obj-$(CONFIG_V850E_UART) += v850e_uart.o -obj-$(CONFIG_SERIAL98) += serial98.o obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o obj-$(CONFIG_SERIAL_AU1X00) += au1x00_uart.o obj-$(CONFIG_SERIAL_DZ) += dz.o --- diff/drivers/serial/pxa.c 2004-05-19 22:12:15.000000000 +0100 +++ source/drivers/serial/pxa.c 2004-05-27 18:34:18.000000000 +0100 @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -386,9 +385,6 @@ if (retval) return retval; - CKEN |= up->cken; - udelay(1); - /* * Clear the FIFO buffers and disable them. * (they will be reenabled in set_termios()) @@ -461,8 +457,6 @@ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); serial_out(up, UART_FCR, 0); - - CKEN &= ~up->cken; } static void @@ -576,10 +570,14 @@ serial_pxa_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) { + struct uart_pxa_port *up = (struct uart_pxa_port *)port; if (state) { /* sleep */ + CKEN &= ~up->cken; } else { /* wake */ + CKEN |= up->cken; + udelay(1); } } @@ -760,13 +758,12 @@ .cken = CKEN6_FFUART, .port = { .type = PORT_PXA, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .membase = (void *)&FFUART, .mapbase = __PREG(FFUART), .irq = IRQ_FFUART, .uartclk = 921600 * 16, .fifosize = 64, - .flags = ASYNC_SKIP_TEST, .ops = &serial_pxa_pops, .line = 0, }, @@ -775,13 +772,12 @@ .cken = CKEN7_BTUART, .port = { .type = PORT_PXA, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .membase = (void *)&BTUART, .mapbase = __PREG(BTUART), .irq = IRQ_BTUART, .uartclk = 921600 * 16, .fifosize = 64, - .flags = ASYNC_SKIP_TEST, .ops = &serial_pxa_pops, .line = 1, }, @@ -790,13 +786,12 @@ .cken = CKEN5_STUART, .port = { .type = PORT_PXA, - .iotype = SERIAL_IO_MEM, + .iotype = UPIO_MEM, .membase = (void *)&STUART, .mapbase = __PREG(STUART), .irq = IRQ_STUART, .uartclk = 921600 * 16, .fifosize = 64, - .flags = ASYNC_SKIP_TEST, .ops = &serial_pxa_pops, .line = 2, }, @@ -830,6 +825,10 @@ static void __exit serial_pxa_exit(void) { + int i; + + for (i = 0; i < ARRAY_SIZE(serial_pxa_ports); i++) + uart_remove_one_port(&serial_pxa_reg, &serial_pxa_ports[i].port); uart_unregister_driver(&serial_pxa_reg); } --- diff/drivers/serial/serial_core.c 2004-05-19 22:12:15.000000000 +0100 +++ source/drivers/serial/serial_core.c 2004-05-27 18:34:18.000000000 +0100 @@ -1985,6 +1985,11 @@ { unsigned int flags; +#ifdef CONFIG_KGDB + if (port->kgdb) + return; +#endif + /* * If there isn't a port here, don't do anything further. */ --- diff/drivers/usb/class/audio.c 2004-05-19 22:12:16.000000000 +0100 +++ source/drivers/usb/class/audio.c 2004-05-27 18:34:18.000000000 +0100 @@ -212,9 +212,6 @@ #define dprintk(x) -#undef abs -extern int abs(int __x) __attribute_const__; /* Shut up warning */ - /* --------------------------------------------------------------------- */ /* @@ -398,17 +395,6 @@ /* --------------------------------------------------------------------- */ -/* prevent picking up a bogus abs macro */ -#undef abs -static inline int abs(int x) -{ - if (x < 0) - return -x; - return x; -} - -/* --------------------------------------------------------------------- */ - static inline unsigned ld2(unsigned int x) { unsigned r = 0; --- diff/drivers/usb/class/usblp.c 2004-05-19 22:12:16.000000000 +0100 +++ source/drivers/usb/class/usblp.c 2004-05-27 18:34:18.000000000 +0100 @@ -226,11 +226,21 @@ static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, int recip, int value, void *buf, int len) { - int retval = usb_control_msg(usblp->dev, + int retval; + int index = usblp->ifnum; + + /* High byte has the interface index. + Low byte has the alternate setting. + */ + if ((request == USBLP_REQ_GET_ID) && (type == USB_TYPE_CLASS)) { + index = (usblp->ifnum<<8)|usblp->protocol[usblp->current_protocol].alt_setting; + } + + retval = usb_control_msg(usblp->dev, dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0), - request, type | dir | recip, value, usblp->ifnum, buf, len, USBLP_WRITE_TIMEOUT); - dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d len: %#x result: %d", - request, !!dir, recip, value, len, retval); + request, type | dir | recip, value, index, buf, len, USBLP_WRITE_TIMEOUT); + dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d idx: %d len: %#x result: %d", + request, !!dir, recip, value, index, len, retval); return retval < 0 ? retval : 0; } @@ -440,6 +450,9 @@ goto done; } + dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd), + _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) ); + if (_IOC_TYPE(cmd) == 'P') /* new-style ioctl number */ switch (_IOC_NR(cmd)) { --- diff/drivers/usb/core/Makefile 2004-05-19 22:12:16.000000000 +0100 +++ source/drivers/usb/core/Makefile 2004-05-27 18:34:18.000000000 +0100 @@ -3,7 +3,7 @@ # usbcore-objs := usb.o hub.o hcd.o urb.o message.o \ - config.o file.o buffer.o driverfs.o + config.o file.o buffer.o sysfs.o ifeq ($(CONFIG_PCI),y) usbcore-objs += hcd-pci.o --- diff/drivers/usb/core/config.c 2004-05-27 13:41:21.000000000 +0100 +++ source/drivers/usb/core/config.c 2004-05-27 18:34:18.000000000 +0100 @@ -465,23 +465,24 @@ goto err2; memset(dev->rawdescriptors, 0, length); - buffer = kmalloc(8, GFP_KERNEL); + buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL); if (!buffer) goto err2; desc = (struct usb_config_descriptor *)buffer; for (cfgno = 0; cfgno < ncfg; cfgno++) { - /* We grab the first 8 bytes so we know how long the whole */ - /* configuration is */ + /* We grab just the first descriptor so we know how long + * the whole configuration is */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, - buffer, 8); + buffer, USB_DT_CONFIG_SIZE); if (result < 0) { dev_err(ddev, "unable to read config index %d " - "descriptor\n", cfgno); + "descriptor/%s\n", cfgno, "start"); goto err; - } else if (result < 8) { + } else if (result < 4) { dev_err(ddev, "config index %d descriptor too short " - "(expected %i, got %i)\n", cfgno, 8, result); + "(expected %i, got %i)\n", cfgno, + USB_DT_CONFIG_SIZE, result); result = -EINVAL; goto err; } @@ -498,7 +499,7 @@ bigbuffer, length); if (result < 0) { dev_err(ddev, "unable to read config index %d " - "descriptor\n", cfgno); + "descriptor/%s\n", cfgno, "all"); kfree(bigbuffer); goto err; } --- diff/drivers/usb/core/hcd.h 2004-05-27 13:41:21.000000000 +0100 +++ source/drivers/usb/core/hcd.h 2004-05-27 18:34:18.000000000 +0100 @@ -243,13 +243,13 @@ extern struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *, unsigned port); extern int usb_new_device(struct usb_device *dev); -extern void usb_choose_address(struct usb_device *dev); extern void usb_disconnect(struct usb_device **); +extern void usb_choose_address(struct usb_device *dev); +extern void usb_release_address(struct usb_device *dev); /* exported to hub driver ONLY to support usb_reset_device () */ extern int usb_get_configuration(struct usb_device *dev); extern void usb_destroy_configuration(struct usb_device *dev); -extern int usb_set_address(struct usb_device *dev); /* use these only before the device's address has been set */ #define usb_snddefctrl(dev) ((PIPE_CONTROL << 30)) --- diff/drivers/usb/core/hub.c 2004-05-27 13:41:21.000000000 +0100 +++ source/drivers/usb/core/hub.c 2004-05-27 18:34:18.000000000 +0100 @@ -65,15 +65,15 @@ #endif /* for dev_info, dev_dbg, etc */ -static inline struct device *hubdev (struct usb_device *dev) +static inline struct device *hubdev (struct usb_device *hdev) { - return &dev->actconfig->interface[0]->dev; + return &hdev->actconfig->interface[0]->dev; } /* USB 2.0 spec Section 11.24.4.5 */ -static int get_hub_descriptor(struct usb_device *dev, void *data, int size) +static int get_hub_descriptor(struct usb_device *hdev, void *data, int size) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, USB_DT_HUB << 8, 0, data, size, HZ * USB_CTRL_GET_TIMEOUT); } @@ -81,27 +81,27 @@ /* * USB 2.0 spec Section 11.24.2.1 */ -static int clear_hub_feature(struct usb_device *dev, int feature) +static int clear_hub_feature(struct usb_device *hdev, int feature) { - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, HZ); } /* * USB 2.0 spec Section 11.24.2.2 */ -static int clear_port_feature(struct usb_device *dev, int port, int feature) +static int clear_port_feature(struct usb_device *hdev, int port, int feature) { - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port, NULL, 0, HZ); } /* * USB 2.0 spec Section 11.24.2.13 */ -static int set_port_feature(struct usb_device *dev, int port, int feature) +static int set_port_feature(struct usb_device *hdev, int port, int feature) { - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port, NULL, 0, HZ); } @@ -110,16 +110,15 @@ * for info about using port indicators */ static void set_port_led( - struct usb_device *dev, - struct usb_hub *hub, + struct usb_device *hdev, int port, int selector ) { - int status = set_port_feature(dev, (selector << 8) | port, + int status = set_port_feature(hdev, (selector << 8) | port, USB_PORT_FEAT_INDICATOR); if (status < 0) - dev_dbg (&hub->intf->dev, + dev_dbg (hubdev (hdev), "port %d indicator %s status %d\n", port, ({ char *s; switch (selector) { @@ -137,12 +136,12 @@ static void led_work (void *__hub) { struct usb_hub *hub = __hub; - struct usb_device *dev = interface_to_usbdev (hub->intf); + struct usb_device *hdev = interface_to_usbdev (hub->intf); unsigned i; unsigned changed = 0; int cursor = -1; - if (dev->state != USB_STATE_CONFIGURED) + if (hdev->state != USB_STATE_CONFIGURED) return; for (i = 0; i < hub->descriptor->bNbrPorts; i++) { @@ -189,13 +188,13 @@ } if (selector != HUB_LED_AUTO) changed = 1; - set_port_led(dev, hub, i + 1, selector); + set_port_led(hdev, i + 1, selector); hub->indicator[i] = mode; } if (!changed && blinkenlights) { cursor++; cursor %= hub->descriptor->bNbrPorts; - set_port_led(dev, hub, cursor + 1, HUB_LED_GREEN); + set_port_led(hdev, cursor + 1, HUB_LED_GREEN); hub->indicator[cursor] = INDICATOR_CYCLE; changed++; } @@ -206,10 +205,10 @@ /* * USB 2.0 spec Section 11.24.2.6 */ -static int get_hub_status(struct usb_device *dev, +static int get_hub_status(struct usb_device *hdev, struct usb_hub_status *data) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0, data, sizeof(*data), HZ * USB_CTRL_GET_TIMEOUT); } @@ -217,10 +216,10 @@ /* * USB 2.0 spec Section 11.24.2.7 */ -static int get_port_status(struct usb_device *dev, int port, +static int get_port_status(struct usb_device *hdev, int port, struct usb_port_status *data) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port, data, sizeof(*data), HZ * USB_CTRL_GET_TIMEOUT); } @@ -278,9 +277,9 @@ /* USB 2.0 spec Section 11.24.2.3 */ static inline int -hub_clear_tt_buffer (struct usb_device *hub, u16 devinfo, u16 tt) +hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt) { - return usb_control_msg (hub, usb_rcvctrlpipe (hub, 0), + return usb_control_msg (hdev, usb_rcvctrlpipe (hdev, 0), HUB_CLEAR_TT_BUFFER, USB_RT_PORT, devinfo, tt, 0, 0, HZ); } @@ -300,7 +299,7 @@ while (!list_empty (&hub->tt.clear_list)) { struct list_head *temp; struct usb_tt_clear *clear; - struct usb_device *dev; + struct usb_device *hdev; int status; temp = hub->tt.clear_list.next; @@ -309,12 +308,13 @@ /* drop lock so HCD can concurrently report other TT errors */ spin_unlock_irqrestore (&hub->tt.lock, flags); - dev = interface_to_usbdev (hub->intf); - status = hub_clear_tt_buffer (dev, clear->devinfo, clear->tt); + hdev = interface_to_usbdev (hub->intf); + status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt); spin_lock_irqsave (&hub->tt.lock, flags); if (status) - dev_err (&dev->dev, "clear tt %d (%04x) error %d\n", + dev_err (&hdev->dev, + "clear tt %d (%04x) error %d\n", clear->tt, clear->devinfo, status); kfree (clear); } @@ -334,9 +334,9 @@ * It may not be possible for that hub to handle additional full (or low) * speed transactions until that state is fully cleared out. */ -void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe) +void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe) { - struct usb_tt *tt = dev->tt; + struct usb_tt *tt = udev->tt; unsigned long flags; struct usb_tt_clear *clear; @@ -345,15 +345,15 @@ * there can be many TTs per hub). even if they're uncommon. */ if ((clear = kmalloc (sizeof *clear, SLAB_ATOMIC)) == 0) { - dev_err (&dev->dev, "can't save CLEAR_TT_BUFFER state\n"); + dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n"); /* FIXME recover somehow ... RESET_TT? */ return; } /* info that CLEAR_TT_BUFFER needs */ - clear->tt = tt->multi ? dev->ttport : 1; + clear->tt = tt->multi ? udev->ttport : 1; clear->devinfo = usb_pipeendpoint (pipe); - clear->devinfo |= dev->devnum << 4; + clear->devinfo |= udev->devnum << 4; clear->devinfo |= usb_pipecontrol (pipe) ? (USB_ENDPOINT_XFER_CONTROL << 11) : (USB_ENDPOINT_XFER_BULK << 11); @@ -369,15 +369,15 @@ static void hub_power_on(struct usb_hub *hub) { - struct usb_device *dev; + struct usb_device *hdev; int i; /* if hub supports power switching, enable power on each port */ if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) { dev_dbg(&hub->intf->dev, "enabling power on all ports\n"); - dev = interface_to_usbdev(hub->intf); + hdev = interface_to_usbdev(hub->intf); for (i = 0; i < hub->descriptor->bNbrPorts; i++) - set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); + set_port_feature(hdev, i + 1, USB_PORT_FEAT_POWER); } /* Wait for power to be enabled */ @@ -387,12 +387,12 @@ static int hub_hub_status(struct usb_hub *hub, u16 *status, u16 *change) { - struct usb_device *dev = interface_to_usbdev (hub->intf); + struct usb_device *hdev = interface_to_usbdev (hub->intf); int ret; - ret = get_hub_status(dev, &hub->status->hub); + ret = get_hub_status(hdev, &hub->status->hub); if (ret < 0) - dev_err (hubdev (dev), + dev_err (&hub->intf->dev, "%s failed (err = %d)\n", __FUNCTION__, ret); else { *status = le16_to_cpu(hub->status->hub.wHubStatus); @@ -405,14 +405,14 @@ static int hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint) { - struct usb_device *dev = interface_to_usbdev (hub->intf); - struct device *hub_dev; + struct usb_device *hdev = interface_to_usbdev (hub->intf); + struct device *hub_dev = &hub->intf->dev; u16 hubstatus, hubchange; unsigned int pipe; int maxp, ret; char *message; - hub->buffer = usb_buffer_alloc(dev, sizeof(*hub->buffer), GFP_KERNEL, + hub->buffer = usb_buffer_alloc(hdev, sizeof(*hub->buffer), GFP_KERNEL, &hub->buffer_dma); if (!hub->buffer) { message = "can't allocate hub irq buffer"; @@ -438,7 +438,7 @@ * hub->descriptor can handle USB_MAXCHILDREN ports, * but the hub can/will return fewer bytes here. */ - ret = get_hub_descriptor(dev, hub->descriptor, + ret = get_hub_descriptor(hdev, hub->descriptor, sizeof(*hub->descriptor)); if (ret < 0) { message = "can't read hub descriptor"; @@ -449,10 +449,9 @@ goto fail; } - hub_dev = hubdev(dev); - dev->maxchild = hub->descriptor->bNbrPorts; - dev_info (hub_dev, "%d port%s detected\n", dev->maxchild, - (dev->maxchild == 1) ? "" : "s"); + hdev->maxchild = hub->descriptor->bNbrPorts; + dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild, + (hdev->maxchild == 1) ? "" : "s"); le16_to_cpus(&hub->descriptor->wHubCharacteristics); @@ -460,11 +459,11 @@ int i; char portstr [USB_MAXCHILDREN + 1]; - for (i = 0; i < dev->maxchild; i++) + for (i = 0; i < hdev->maxchild; i++) portstr[i] = hub->descriptor->DeviceRemovable [((i + 1) / 8)] & (1 << ((i + 1) % 8)) ? 'F' : 'R'; - portstr[dev->maxchild] = 0; + portstr[hdev->maxchild] = 0; dev_dbg(hub_dev, "compound device; port removable status: %s\n", portstr); } else dev_dbg(hub_dev, "standalone hub\n"); @@ -498,32 +497,32 @@ spin_lock_init (&hub->tt.lock); INIT_LIST_HEAD (&hub->tt.clear_list); INIT_WORK (&hub->tt.kevent, hub_tt_kevent, hub); - switch (dev->descriptor.bDeviceProtocol) { + switch (hdev->descriptor.bDeviceProtocol) { case 0: break; case 1: dev_dbg(hub_dev, "Single TT\n"); - hub->tt.hub = dev; + hub->tt.hub = hdev; break; case 2: - ret = usb_set_interface(dev, 0, 1); + ret = usb_set_interface(hdev, 0, 1); if (ret == 0) { dev_dbg(hub_dev, "TT per port\n"); hub->tt.multi = 1; } else dev_err(hub_dev, "Using single TT (err %d)\n", ret); - hub->tt.hub = dev; + hub->tt.hub = hdev; break; default: dev_dbg(hub_dev, "Unrecognized hub protocol %d\n", - dev->descriptor.bDeviceProtocol); + hdev->descriptor.bDeviceProtocol); break; } switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) { case 0x00: - if (dev->descriptor.bDeviceProtocol != 0) + if (hdev->descriptor.bDeviceProtocol != 0) dev_dbg(hub_dev, "TT requires at most 8 FS bit times\n"); break; case 0x20: @@ -549,9 +548,9 @@ /* power budgeting mostly matters with bus-powered hubs, * and battery-powered root hubs (may provide just 8 mA). */ - ret = usb_get_status(dev, USB_RECIP_DEVICE, 0, &hubstatus); + ret = usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus); if (ret < 0) { - message = "can't get hubdev status"; + message = "can't get hub status"; goto fail; } cpu_to_le16s(&hubstatus); @@ -572,7 +571,7 @@ } /* local power status reports aren't always correct */ - if (dev->actconfig->desc.bmAttributes & USB_CONFIG_ATT_SELFPOWER) + if (hdev->actconfig->desc.bmAttributes & USB_CONFIG_ATT_SELFPOWER) dev_dbg(hub_dev, "local power source is %s\n", (hubstatus & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good"); @@ -582,8 +581,8 @@ (hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no "); /* Start the interrupt endpoint */ - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); + pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress); + maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe)); if (maxp > sizeof(*hub->buffer)) maxp = sizeof(*hub->buffer); @@ -595,7 +594,7 @@ goto fail; } - usb_fill_int_urb(hub->urb, dev, pipe, *hub->buffer, maxp, hub_irq, + usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq, hub, endpoint->bInterval); hub->urb->transfer_dma = hub->buffer_dma; hub->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -611,7 +610,7 @@ /* maybe start cycling the hub leds */ if (hub->has_indicators && blinkenlights) { - set_port_led(dev, hub, 1, HUB_LED_GREEN); + set_port_led(hdev, 1, HUB_LED_GREEN); hub->indicator [0] = INDICATOR_CYCLE; schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD); } @@ -621,7 +620,7 @@ return 0; fail: - dev_err (&hub->intf->dev, "config failed, %s (err %d)\n", + dev_err (hub_dev, "config failed, %s (err %d)\n", message, ret); /* hub_disconnect() frees urb and descriptor */ return ret; @@ -693,19 +692,21 @@ { struct usb_host_interface *desc; struct usb_endpoint_descriptor *endpoint; - struct usb_device *dev; + struct usb_device *hdev; struct usb_hub *hub; + struct device *hub_dev; unsigned long flags; desc = intf->cur_altsetting; - dev = interface_to_usbdev(intf); + hdev = interface_to_usbdev(intf); + hub_dev = &intf->dev; /* Some hubs have a subclass of 1, which AFAICT according to the */ /* specs is not defined, but it works */ if ((desc->desc.bInterfaceSubClass != 0) && (desc->desc.bInterfaceSubClass != 1)) { descriptor_error: - dev_err (&intf->dev, "bad descriptor, ignoring hub\n"); + dev_err (hub_dev, "bad descriptor, ignoring hub\n"); return -EIO; } @@ -729,11 +730,11 @@ } /* We found a hub */ - dev_info (hubdev (dev), "USB hub found\n"); + dev_info (hub_dev, "USB hub found\n"); hub = kmalloc(sizeof(*hub), GFP_KERNEL); if (!hub) { - dev_dbg (hubdev(dev), "couldn't kmalloc hub struct\n"); + dev_dbg (hub_dev, "couldn't kmalloc hub struct\n"); return -ENOMEM; } @@ -752,7 +753,7 @@ usb_set_intfdata (intf, hub); - if (dev->speed == USB_SPEED_HIGH) + if (hdev->speed == USB_SPEED_HIGH) highspeed_hubs++; if (hub_configure(hub, endpoint) >= 0) @@ -765,7 +766,7 @@ static int hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) { - struct usb_device *hub = interface_to_usbdev (intf); + struct usb_device *hdev = interface_to_usbdev (intf); /* assert ifno == 0 (part of hub spec) */ switch (code) { @@ -775,16 +776,16 @@ int i; spin_lock_irqsave(&hub_event_lock, flags); - if (hub->devnum <= 0) + if (hdev->devnum <= 0) info->nports = 0; else { - info->nports = hub->maxchild; + info->nports = hdev->maxchild; for (i = 0; i < info->nports; i++) { - if (hub->children[i] == NULL) + if (hdev->children[i] == NULL) info->port[i] = 0; else info->port[i] = - hub->children[i]->devnum; + hdev->children[i]->devnum; } } spin_unlock_irqrestore(&hub_event_lock, flags); @@ -799,13 +800,13 @@ static int hub_reset(struct usb_hub *hub) { - struct usb_device *dev = interface_to_usbdev(hub->intf); + struct usb_device *hdev = interface_to_usbdev(hub->intf); int i; /* Disconnect any attached devices */ for (i = 0; i < hub->descriptor->bNbrPorts; i++) { - if (dev->children[i]) - usb_disconnect(&dev->children[i]); + if (hdev->children[i]) + usb_disconnect(&hdev->children[i]); } /* Attempt to reset the hub */ @@ -814,10 +815,10 @@ else return -1; - if (usb_reset_device(dev)) + if (usb_reset_device(hdev)) return -1; - hub->urb->dev = dev; + hub->urb->dev = hdev; if (usb_submit_urb(hub->urb, GFP_KERNEL)) return -1; @@ -826,36 +827,36 @@ return 0; } -static void hub_start_disconnect(struct usb_device *dev) +static void hub_start_disconnect(struct usb_device *hdev) { - struct usb_device *parent = dev->parent; + struct usb_device *parent = hdev->parent; int i; /* Find the device pointer to disconnect */ if (parent) { for (i = 0; i < parent->maxchild; i++) { - if (parent->children[i] == dev) { + if (parent->children[i] == hdev) { usb_disconnect(&parent->children[i]); return; } } } - dev_err(&dev->dev, "cannot disconnect hub!\n"); + dev_err(&hdev->dev, "cannot disconnect hub!\n"); } -static int hub_port_status(struct usb_device *dev, int port, +static int hub_port_status(struct usb_device *hdev, int port, u16 *status, u16 *change) { - struct usb_hub *hub = usb_get_intfdata(dev->actconfig->interface[0]); + struct usb_hub *hub = usb_get_intfdata(hdev->actconfig->interface[0]); int ret; if (!hub) return -ENODEV; - ret = get_port_status(dev, port + 1, &hub->status->port); + ret = get_port_status(hdev, port + 1, &hub->status->port); if (ret < 0) - dev_err (hubdev (dev), + dev_err (&hub->intf->dev, "%s failed (err = %d)\n", __FUNCTION__, ret); else { *status = le16_to_cpu(hub->status->port.wPortStatus); @@ -876,8 +877,8 @@ #define HUB_RESET_TIMEOUT 500 /* return: -1 on error, 0 on success, 1 on disconnect. */ -static int hub_port_wait_reset(struct usb_device *hub, int port, - struct usb_device *dev, unsigned int delay) +static int hub_port_wait_reset(struct usb_device *hdev, int port, + struct usb_device *udev, unsigned int delay) { int delay_time, ret; u16 portstatus; @@ -890,7 +891,7 @@ msleep(delay); /* read and decode port status */ - ret = hub_port_status(hub, port, &portstatus, &portchange); + ret = hub_port_status(hdev, port, &portstatus, &portchange); if (ret < 0) { return -1; } @@ -907,11 +908,11 @@ if (!(portstatus & USB_PORT_STAT_RESET) && (portstatus & USB_PORT_STAT_ENABLE)) { if (portstatus & USB_PORT_STAT_HIGH_SPEED) - dev->speed = USB_SPEED_HIGH; + udev->speed = USB_SPEED_HIGH; else if (portstatus & USB_PORT_STAT_LOW_SPEED) - dev->speed = USB_SPEED_LOW; + udev->speed = USB_SPEED_LOW; else - dev->speed = USB_SPEED_FULL; + udev->speed = USB_SPEED_FULL; return 0; } @@ -919,7 +920,7 @@ if (delay_time >= 2 * HUB_SHORT_RESET_TIME) delay = HUB_LONG_RESET_TIME; - dev_dbg (hubdev (hub), + dev_dbg (hubdev (hdev), "port %d not reset yet, waiting %dms\n", port + 1, delay); } @@ -928,46 +929,47 @@ } /* return: -1 on error, 0 on success, 1 on disconnect. */ -static int hub_port_reset(struct usb_device *hub, int port, - struct usb_device *dev, unsigned int delay) +static int hub_port_reset(struct usb_device *hdev, int port, + struct usb_device *udev, unsigned int delay) { int i, status; + struct device *hub_dev = hubdev (hdev); /* Reset the port */ for (i = 0; i < PORT_RESET_TRIES; i++) { - set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET); + set_port_feature(hdev, port + 1, USB_PORT_FEAT_RESET); /* return on disconnect or reset */ - status = hub_port_wait_reset(hub, port, dev, delay); + status = hub_port_wait_reset(hdev, port, udev, delay); if (status != -1) { - clear_port_feature(hub, + clear_port_feature(hdev, port + 1, USB_PORT_FEAT_C_RESET); - dev->state = status + udev->state = status ? USB_STATE_NOTATTACHED : USB_STATE_DEFAULT; return status; } - dev_dbg (hubdev (hub), + dev_dbg (hub_dev, "port %d not enabled, trying reset again...\n", port + 1); delay = HUB_LONG_RESET_TIME; } - dev_err (hubdev (hub), + dev_err (hub_dev, "Cannot enable port %i. Maybe the USB cable is bad?\n", port + 1); return -1; } -static int hub_port_disable(struct usb_device *hub, int port) +static int hub_port_disable(struct usb_device *hdev, int port) { int ret; - ret = clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE); + ret = clear_port_feature(hdev, port + 1, USB_PORT_FEAT_ENABLE); if (ret) - dev_err(hubdev(hub), "cannot disable port %d (err = %d)\n", + dev_err(hubdev(hdev), "cannot disable port %d (err = %d)\n", port + 1, ret); return ret; @@ -992,7 +994,7 @@ #define HUB_DEBOUNCE_STABLE 4 /* return: -1 on error, 0 on success, 1 on disconnect. */ -static int hub_port_debounce(struct usb_device *hub, int port) +static int hub_port_debounce(struct usb_device *hdev, int port) { int ret; int delay_time, stable_count; @@ -1004,7 +1006,7 @@ for (delay_time = 0; delay_time < HUB_DEBOUNCE_TIMEOUT; delay_time += HUB_DEBOUNCE_STEP) { msleep(HUB_DEBOUNCE_STEP); - ret = hub_port_status(hub, port, &portstatus, &portchange); + ret = hub_port_status(hdev, port, &portstatus, &portchange); if (ret < 0) return -1; @@ -1019,17 +1021,34 @@ connection = portstatus & USB_PORT_STAT_CONNECTION; if ((portchange & USB_PORT_STAT_C_CONNECTION)) { - clear_port_feature(hub, port+1, USB_PORT_FEAT_C_CONNECTION); + clear_port_feature(hdev, port+1, USB_PORT_FEAT_C_CONNECTION); } } - dev_dbg (hubdev (hub), + dev_dbg (hubdev (hdev), "debounce: port %d: delay %dms stable %d status 0x%x\n", port + 1, delay_time, stable_count, portstatus); return ((portstatus&USB_PORT_STAT_CONNECTION)) ? 0 : 1; } +static int hub_set_address(struct usb_device *udev) +{ + int retval; + + if (udev->devnum == 0) + return -EINVAL; + if (udev->state != USB_STATE_DEFAULT && + udev->state != USB_STATE_ADDRESS) + return -EINVAL; + retval = usb_control_msg(udev, usb_snddefctrl(udev), + USB_REQ_SET_ADDRESS, 0, udev->devnum, 0, + NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); + if (retval == 0) + udev->state = USB_STATE_ADDRESS; + return retval; +} + /* reset device, (re)assign address, get device descriptor. * device connection is stable, no more debouncing needed. * returns device in USB_STATE_ADDRESS, except on error. @@ -1039,18 +1058,18 @@ * config changes and disconnect processing. */ static int -hub_port_init (struct usb_device *hub, struct usb_device *dev, int port) +hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port) { static DECLARE_MUTEX(usb_address0_sem); int i, j, retval = -ENODEV; unsigned delay = HUB_SHORT_RESET_TIME; - enum usb_device_speed oldspeed = dev->speed; + enum usb_device_speed oldspeed = udev->speed; /* root hub ports have a slightly longer reset period * (from USB 2.0 spec, section 7.1.7.5) */ - if (!hub->parent) + if (!hdev->parent) delay = HUB_ROOT_RESET_TIME; /* Some low speed devices have problems with the quick delay, so */ @@ -1061,7 +1080,7 @@ down(&usb_address0_sem); /* Reset the device; full speed may morph to high speed */ - switch (hub_port_reset(hub, port, dev, delay)) { + switch (hub_port_reset(hdev, port, udev, delay)) { case 0: /* success, speed is known */ break; case 1: /* disconnect, give to companion */ @@ -1070,15 +1089,15 @@ default: /* error */ goto fail; } - if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != dev->speed) { - dev_dbg(&dev->dev, "device reset changed speed!\n"); + if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != udev->speed) { + dev_dbg(&udev->dev, "device reset changed speed!\n"); goto fail; } /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... * it's fixed size except for full speed devices. */ - switch (dev->speed) { + switch (udev->speed) { case USB_SPEED_HIGH: /* fixed at 64 */ i = 64; break; @@ -1094,43 +1113,43 @@ default: goto fail; } - dev->epmaxpacketin [0] = i; - dev->epmaxpacketout[0] = i; + udev->epmaxpacketin [0] = i; + udev->epmaxpacketout[0] = i; /* set the address */ - if (dev->devnum <= 0) { - usb_choose_address(dev); - if (dev->devnum <= 0) + if (udev->devnum <= 0) { + usb_choose_address(udev); + if (udev->devnum <= 0) goto fail; /* Set up TT records, if needed */ - if (hub->tt) { - dev->tt = hub->tt; - dev->ttport = hub->ttport; - } else if (dev->speed != USB_SPEED_HIGH - && hub->speed == USB_SPEED_HIGH) { - struct usb_hub *hubstate; + if (hdev->tt) { + udev->tt = hdev->tt; + udev->ttport = hdev->ttport; + } else if (udev->speed != USB_SPEED_HIGH + && hdev->speed == USB_SPEED_HIGH) { + struct usb_hub *hub; - hubstate = usb_get_intfdata (hub->actconfig + hub = usb_get_intfdata (hdev->actconfig ->interface[0]); - dev->tt = &hubstate->tt; - dev->ttport = port + 1; + udev->tt = &hub->tt; + udev->ttport = port + 1; } /* force the right log message (below) at low speed */ oldspeed = USB_SPEED_UNKNOWN; } - dev_info (&dev->dev, + dev_info (&udev->dev, "%s %s speed USB device using address %d\n", (oldspeed == USB_SPEED_UNKNOWN) ? "new" : "reset", - ({ char *speed; switch (dev->speed) { + ({ char *speed; switch (udev->speed) { case USB_SPEED_LOW: speed = "low"; break; case USB_SPEED_FULL: speed = "full"; break; case USB_SPEED_HIGH: speed = "high"; break; default: speed = "?"; break; }; speed;}), - dev->devnum); + udev->devnum); /* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way? * Because device hardware and firmware is sometimes buggy in @@ -1143,20 +1162,19 @@ */ for (i = 0; i < GET_DESCRIPTOR_TRIES; ++i) { for (j = 0; j < SET_ADDRESS_TRIES; ++j) { - retval = usb_set_address(dev); + retval = hub_set_address(udev); if (retval >= 0) break; msleep(200); } if (retval < 0) { - dev_err(&dev->dev, + dev_err(&udev->dev, "device not accepting address %d, error %d\n", - dev->devnum, retval); + udev->devnum, retval); fail: - hub_port_disable(hub, port); - clear_bit(dev->devnum, dev->bus->devmap.devicemap); - dev->devnum = -1; - usb_put_dev(dev); + hub_port_disable(hdev, port); + usb_release_address(udev); + usb_put_dev(udev); up(&usb_address0_sem); return retval; } @@ -1166,31 +1184,31 @@ * - read ep0 maxpacket even for high and low speed, */ msleep(10); - retval = usb_get_device_descriptor(dev, 8); + retval = usb_get_device_descriptor(udev, 8); if (retval >= 8) break; msleep(100); } if (retval != 8) { - dev_err(&dev->dev, "device descriptor read/%s, error %d\n", + dev_err(&udev->dev, "device descriptor read/%s, error %d\n", "8", retval); if (retval >= 0) retval = -EMSGSIZE; goto fail; } - if (dev->speed == USB_SPEED_FULL - && (dev->epmaxpacketin [0] - != dev->descriptor.bMaxPacketSize0)) { - usb_disable_endpoint(dev, 0); - usb_endpoint_running(dev, 0, 1); - usb_endpoint_running(dev, 0, 0); - dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; - dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; + if (udev->speed == USB_SPEED_FULL + && (udev->epmaxpacketin [0] + != udev->descriptor.bMaxPacketSize0)) { + usb_disable_endpoint(udev, 0); + usb_endpoint_running(udev, 0, 1); + usb_endpoint_running(udev, 0, 0); + udev->epmaxpacketin [0] = udev->descriptor.bMaxPacketSize0; + udev->epmaxpacketout[0] = udev->descriptor.bMaxPacketSize0; } - retval = usb_get_device_descriptor(dev, USB_DT_DEVICE_SIZE); - if (retval < (signed)sizeof(dev->descriptor)) { - dev_err(&dev->dev, "device descriptor read/%s, error %d\n", + retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE); + if (retval < (signed)sizeof(udev->descriptor)) { + dev_err(&udev->dev, "device descriptor read/%s, error %d\n", "all", retval); if (retval >= 0) retval = -ENOMSG; @@ -1198,14 +1216,14 @@ } /* now dev is visible to other tasks */ - hub->children[port] = dev; + hdev->children[port] = udev; up(&usb_address0_sem); return 0; } static void -check_highspeed (struct usb_hub *hub, struct usb_device *dev, int port) +check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port) { struct usb_qualifier_descriptor *qual; int status; @@ -1214,10 +1232,10 @@ if (qual == 0) return; - status = usb_get_descriptor (dev, USB_DT_DEVICE_QUALIFIER, 0, + status = usb_get_descriptor (udev, USB_DT_DEVICE_QUALIFIER, 0, qual, sizeof *qual); if (status == sizeof *qual) { - dev_info(&dev->dev, "not running at top speed; " + dev_info(&udev->dev, "not running at top speed; " "connect to a high speed hub\n"); /* hub LEDs are probably harder to miss than syslog */ if (hub->has_indicators) { @@ -1229,31 +1247,31 @@ } static unsigned -hub_power_remaining (struct usb_hub *hubstate, struct usb_device *hub) +hub_power_remaining (struct usb_hub *hub, struct usb_device *hdev) { int remaining; unsigned i; - remaining = hubstate->power_budget; + remaining = hub->power_budget; if (!remaining) /* self-powered */ return 0; - for (i = 0; i < hub->maxchild; i++) { - struct usb_device *dev = hub->children[i]; + for (i = 0; i < hdev->maxchild; i++) { + struct usb_device *udev = hdev->children[i]; int delta; - if (!dev) + if (!udev) continue; - if (dev->actconfig) - delta = dev->actconfig->desc.bMaxPower; + if (udev->actconfig) + delta = udev->actconfig->desc.bMaxPower; else delta = 50; - // dev_dbg(&dev->dev, "budgeted %dmA\n", 2 * delta); + // dev_dbg(&udev->dev, "budgeted %dmA\n", 2 * delta); remaining -= delta; } if (remaining < 0) { - dev_warn(&hubstate->intf->dev, + dev_warn(&hub->intf->dev, "%dmA over power budget!\n", -2 * remaining); remaining = 0; @@ -1261,72 +1279,73 @@ return remaining; } -static void hub_port_connect_change(struct usb_hub *hubstate, int port, +static void hub_port_connect_change(struct usb_hub *hub, int port, u16 portstatus, u16 portchange) { - struct usb_device *hub = interface_to_usbdev(hubstate->intf); + struct usb_device *hdev = interface_to_usbdev(hub->intf); + struct device *hub_dev = &hub->intf->dev; int status, i; - dev_dbg (&hubstate->intf->dev, + dev_dbg (hub_dev, "port %d, status %04x, change %04x, %s\n", port + 1, portstatus, portchange, portspeed (portstatus)); /* Clear the connection change status */ - clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION); + clear_port_feature(hdev, port + 1, USB_PORT_FEAT_C_CONNECTION); - if (hubstate->has_indicators) { - set_port_led(hub, hubstate, port + 1, HUB_LED_AUTO); - hubstate->indicator[port] = INDICATOR_AUTO; + if (hub->has_indicators) { + set_port_led(hdev, port + 1, HUB_LED_AUTO); + hub->indicator[port] = INDICATOR_AUTO; } /* Disconnect any existing devices under this port */ - if (hub->children[port]) - usb_disconnect(&hub->children[port]); + if (hdev->children[port]) + usb_disconnect(&hdev->children[port]); /* Return now if nothing is connected */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) { /* maybe switch power back on (e.g. root hub was reset) */ - if ((hubstate->descriptor->wHubCharacteristics + if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2 && !(portstatus & (1 << USB_PORT_FEAT_POWER))) - set_port_feature(hub, port + 1, USB_PORT_FEAT_POWER); + set_port_feature(hdev, port + 1, USB_PORT_FEAT_POWER); if (portstatus & USB_PORT_STAT_ENABLE) goto done; return; } - if (hub_port_debounce(hub, port)) { - dev_err (&hubstate->intf->dev, + if (hub_port_debounce(hdev, port)) { + dev_err (hub_dev, "connect-debounce failed, port %d disabled\n", port+1); goto done; } for (i = 0; i < SET_CONFIG_TRIES; i++) { - struct usb_device *dev; + struct usb_device *udev; /* reallocate for each attempt, since references * to the previous one can escape in various ways */ - dev = usb_alloc_dev(hub, hub->bus, port); - if (!dev) { - dev_err (&hubstate->intf->dev, + udev = usb_alloc_dev(hdev, hdev->bus, port); + if (!udev) { + dev_err (hub_dev, "couldn't allocate port %d usb_device\n", port+1); goto done; } - dev->state = USB_STATE_POWERED; + udev->state = USB_STATE_POWERED; /* hub can tell if it's lowspeed already: D- pullup (not D+) */ if (portstatus & USB_PORT_STAT_LOW_SPEED) - dev->speed = USB_SPEED_LOW; + udev->speed = USB_SPEED_LOW; else - dev->speed = USB_SPEED_UNKNOWN; + udev->speed = USB_SPEED_UNKNOWN; /* reset, set address, get descriptor, add to hub's children */ - down (&dev->serialize); - status = hub_port_init(hub, dev, port); + down (&udev->serialize); + status = hub_port_init(hdev, udev, port); if (status == -EBUSY) break; if (status < 0) @@ -1338,50 +1357,50 @@ * (without reading syslog), even without per-port LEDs * on the parent. */ - if (dev->descriptor.bDeviceClass == USB_CLASS_HUB - && hubstate->power_budget) { + if (udev->descriptor.bDeviceClass == USB_CLASS_HUB + && hub->power_budget) { u16 devstat; - status = usb_get_status(dev, USB_RECIP_DEVICE, 0, + status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstat); if (status < 0) { - dev_dbg(&dev->dev, "get status %d ?\n", status); + dev_dbg(&udev->dev, "get status %d ?\n", status); continue; } cpu_to_le16s(&devstat); if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) { - dev_err(&dev->dev, + dev_err(&udev->dev, "can't connect bus-powered hub " "to this port\n"); - if (hubstate->has_indicators) { - hubstate->indicator[port] = + if (hub->has_indicators) { + hub->indicator[port] = INDICATOR_AMBER_BLINK; - schedule_work (&hubstate->leds); + schedule_work (&hub->leds); } - hub->children[port] = NULL; - usb_put_dev(dev); - hub_port_disable(hub, port); + hdev->children[port] = NULL; + usb_put_dev(udev); + hub_port_disable(hdev, port); return; } } /* check for devices running slower than they could */ - if (dev->descriptor.bcdUSB >= 0x0200 - && dev->speed == USB_SPEED_FULL + if (udev->descriptor.bcdUSB >= 0x0200 + && udev->speed == USB_SPEED_FULL && highspeed_hubs != 0) - check_highspeed (hubstate, dev, port); + check_highspeed (hub, udev, port); /* Run it through the hoops (find a driver, etc) */ - status = usb_new_device(dev); + status = usb_new_device(udev); if (status != 0) { - hub->children[port] = NULL; + hdev->children[port] = NULL; continue; } - up (&dev->serialize); + up (&udev->serialize); - status = hub_power_remaining(hubstate, hub); + status = hub_power_remaining(hub, hdev); if (status) - dev_dbg(&hubstate->intf->dev, + dev_dbg(hub_dev, "%dmA power budget left\n", 2 * status); @@ -1389,15 +1408,16 @@ } done: - hub_port_disable(hub, port); + hub_port_disable(hdev, port); } static void hub_events(void) { unsigned long flags; struct list_head *tmp; - struct usb_device *dev; + struct usb_device *hdev; struct usb_hub *hub; + struct device *hub_dev; u16 hubstatus; u16 hubchange; u16 portstatus; @@ -1420,7 +1440,8 @@ tmp = hub_event_list.next; hub = list_entry(tmp, struct usb_hub, event_list); - dev = interface_to_usbdev(hub->intf); + hdev = interface_to_usbdev(hub->intf); + hub_dev = &hub->intf->dev; list_del_init(tmp); @@ -1430,14 +1451,14 @@ spin_unlock_irqrestore(&hub_event_lock, flags); if (hub->error) { - dev_dbg (&hub->intf->dev, "resetting for error %d\n", + dev_dbg (hub_dev, "resetting for error %d\n", hub->error); if (hub_reset(hub)) { - dev_dbg (&hub->intf->dev, + dev_dbg (hub_dev, "can't reset; disconnecting\n"); up(&hub->khubd_sem); - hub_start_disconnect(dev); + hub_start_disconnect(hdev); continue; } @@ -1446,7 +1467,7 @@ } for (i = 0; i < hub->descriptor->bNbrPorts; i++) { - ret = hub_port_status(dev, i, &portstatus, &portchange); + ret = hub_port_status(hdev, i, &portstatus, &portchange); if (ret < 0) { continue; } @@ -1454,10 +1475,10 @@ if (portchange & USB_PORT_STAT_C_CONNECTION) { hub_port_connect_change(hub, i, portstatus, portchange); } else if (portchange & USB_PORT_STAT_C_ENABLE) { - dev_dbg (hubdev (dev), + dev_dbg (hub_dev, "port %d enable change, status %08x\n", i + 1, portstatus); - clear_port_feature(dev, + clear_port_feature(hdev, i + 1, USB_PORT_FEAT_C_ENABLE); /* @@ -1468,8 +1489,8 @@ */ if (!(portstatus & USB_PORT_STAT_ENABLE) && (portstatus & USB_PORT_STAT_CONNECTION) - && (dev->children[i])) { - dev_err (&hub->intf->dev, + && (hdev->children[i])) { + dev_err (hub_dev, "port %i " "disabled by hub (EMI?), " "re-enabling...", @@ -1480,43 +1501,43 @@ } if (portchange & USB_PORT_STAT_C_SUSPEND) { - dev_dbg (&hub->intf->dev, + dev_dbg (hub_dev, "suspend change on port %d\n", i + 1); - clear_port_feature(dev, + clear_port_feature(hdev, i + 1, USB_PORT_FEAT_C_SUSPEND); } if (portchange & USB_PORT_STAT_C_OVERCURRENT) { - dev_err (&hub->intf->dev, + dev_err (hub_dev, "over-current change on port %d\n", i + 1); - clear_port_feature(dev, + clear_port_feature(hdev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT); hub_power_on(hub); } if (portchange & USB_PORT_STAT_C_RESET) { - dev_dbg (&hub->intf->dev, + dev_dbg (hub_dev, "reset change on port %d\n", i + 1); - clear_port_feature(dev, + clear_port_feature(hdev, i + 1, USB_PORT_FEAT_C_RESET); } } /* end for i */ /* deal with hub status changes */ if (hub_hub_status(hub, &hubstatus, &hubchange) < 0) - dev_err (&hub->intf->dev, "get_hub_status failed\n"); + dev_err (hub_dev, "get_hub_status failed\n"); else { if (hubchange & HUB_CHANGE_LOCAL_POWER) { - dev_dbg (&hub->intf->dev, "power change\n"); - clear_hub_feature(dev, C_HUB_LOCAL_POWER); + dev_dbg (hub_dev, "power change\n"); + clear_hub_feature(hdev, C_HUB_LOCAL_POWER); } if (hubchange & HUB_CHANGE_OVERCURRENT) { - dev_dbg (&hub->intf->dev, "overcurrent change\n"); + dev_dbg (hub_dev, "overcurrent change\n"); msleep(500); /* Cool down */ - clear_hub_feature(dev, C_HUB_OVER_CURRENT); + clear_hub_feature(hdev, C_HUB_OVER_CURRENT); hub_power_on(hub); } } @@ -1526,7 +1547,7 @@ spin_unlock_irqrestore(&hub_event_lock, flags); } -static int hub_thread(void *__hub) +static int hub_thread(void *__unused) { /* * This thread doesn't need any user-level access, @@ -1614,36 +1635,36 @@ } /* usb_hub_cleanup() */ -static int config_descriptors_changed(struct usb_device *dev) +static int config_descriptors_changed(struct usb_device *udev) { unsigned index; unsigned len = 0; struct usb_config_descriptor *buf; - for (index = 0; index < dev->descriptor.bNumConfigurations; index++) { - if (len < dev->config[index].desc.wTotalLength) - len = dev->config[index].desc.wTotalLength; + for (index = 0; index < udev->descriptor.bNumConfigurations; index++) { + if (len < udev->config[index].desc.wTotalLength) + len = udev->config[index].desc.wTotalLength; } buf = kmalloc (len, SLAB_KERNEL); if (buf == 0) { - dev_err(&dev->dev, "no mem to re-read configs after reset\n"); + dev_err(&udev->dev, "no mem to re-read configs after reset\n"); /* assume the worst */ return 1; } - for (index = 0; index < dev->descriptor.bNumConfigurations; index++) { + for (index = 0; index < udev->descriptor.bNumConfigurations; index++) { int length; - int old_length = dev->config[index].desc.wTotalLength; + int old_length = udev->config[index].desc.wTotalLength; - length = usb_get_descriptor(dev, USB_DT_CONFIG, index, buf, + length = usb_get_descriptor(udev, USB_DT_CONFIG, index, buf, old_length); if (length < old_length) { - dev_dbg(&dev->dev, "config index %d, error %d\n", + dev_dbg(&udev->dev, "config index %d, error %d\n", index, length); break; } - if (memcmp (buf, dev->rawdescriptors[index], old_length) + if (memcmp (buf, udev->rawdescriptors[index], old_length) != 0) { - dev_dbg(&dev->dev, "config index %d changed (#%d)\n", + dev_dbg(&udev->dev, "config index %d changed (#%d)\n", index, buf->bConfigurationValue); /* FIXME enable this when we can re-enumerate after reset; * until then DFU-ish drivers need this and other workarounds @@ -1652,7 +1673,7 @@ } } kfree(buf); - return index != dev->descriptor.bNumConfigurations; + return index != udev->descriptor.bNumConfigurations; } /* @@ -1664,22 +1685,22 @@ * already holds dev->serialize. For example, it's safe to use * this from a driver probe() routine after downloading new firmware. */ -int __usb_reset_device(struct usb_device *dev) +int __usb_reset_device(struct usb_device *udev) { - struct usb_device *parent = dev->parent; - struct usb_device_descriptor descriptor = dev->descriptor; + struct usb_device *parent = udev->parent; + struct usb_device_descriptor descriptor = udev->descriptor; int i, ret, port = -1; - if (dev->maxchild) { + if (udev->maxchild) { /* this requires hub- or hcd-specific logic; * see hub_reset() and OHCI hc_restart() */ - dev_dbg(&dev->dev, "%s for hub!\n", __FUNCTION__); + dev_dbg(&udev->dev, "%s for hub!\n", __FUNCTION__); return -EINVAL; } for (i = 0; i < parent->maxchild; i++) - if (parent->children[i] == dev) { + if (parent->children[i] == udev) { port = i; break; } @@ -1687,45 +1708,45 @@ if (port < 0) return -ENOENT; - ret = hub_port_init(parent, dev, port); + ret = hub_port_init(parent, udev, port); if (ret < 0) goto re_enumerate; /* Device might have changed firmware (DFU or similar) */ - if (memcmp(&dev->descriptor, &descriptor, sizeof descriptor) - || config_descriptors_changed (dev)) { - dev_info(&dev->dev, "device firmware changed\n"); - dev->descriptor = descriptor; /* for disconnect() calls */ + if (memcmp(&udev->descriptor, &descriptor, sizeof descriptor) + || config_descriptors_changed (udev)) { + dev_info(&udev->dev, "device firmware changed\n"); + udev->descriptor = descriptor; /* for disconnect() calls */ goto re_enumerate; } - if (!dev->actconfig) + if (!udev->actconfig) return 0; - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), USB_REQ_SET_CONFIGURATION, 0, - dev->actconfig->desc.bConfigurationValue, 0, + udev->actconfig->desc.bConfigurationValue, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); if (ret < 0) { - dev_err(&dev->dev, + dev_err(&udev->dev, "can't restore configuration #%d (error=%d)\n", - dev->actconfig->desc.bConfigurationValue, ret); + udev->actconfig->desc.bConfigurationValue, ret); goto re_enumerate; } - dev->state = USB_STATE_CONFIGURED; + udev->state = USB_STATE_CONFIGURED; - for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { - struct usb_interface *intf = dev->actconfig->interface[i]; + for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { + struct usb_interface *intf = udev->actconfig->interface[i]; struct usb_interface_descriptor *desc; /* set_interface resets host side toggle and halt status even * for altsetting zero. the interface may have no driver. */ desc = &intf->cur_altsetting->desc; - ret = usb_set_interface(dev, desc->bInterfaceNumber, + ret = usb_set_interface(udev, desc->bInterfaceNumber, desc->bAlternateSetting); if (ret < 0) { - dev_err(&dev->dev, "failed to restore interface %d " + dev_err(&udev->dev, "failed to restore interface %d " "altsetting %d (error=%d)\n", desc->bInterfaceNumber, desc->bAlternateSetting, @@ -1738,7 +1759,7 @@ re_enumerate: /* FIXME make some task re-enumerate; don't just mark unusable */ - dev->state = USB_STATE_NOTATTACHED; + udev->state = USB_STATE_NOTATTACHED; return -ENODEV; } EXPORT_SYMBOL(__usb_reset_device); --- diff/drivers/usb/core/message.c 2004-05-27 13:41:21.000000000 +0100 +++ source/drivers/usb/core/message.c 2004-05-27 18:34:18.000000000 +0100 @@ -1252,7 +1252,7 @@ ret); continue; } - usb_create_driverfs_intf_files (intf); + usb_create_sysfs_intf_files (intf); } } --- diff/drivers/usb/core/usb.c 2004-05-27 13:41:21.000000000 +0100 +++ source/drivers/usb/core/usb.c 2004-05-27 18:34:18.000000000 +0100 @@ -998,12 +998,10 @@ */ usb_disable_device(dev, 0); - dev_dbg (&dev->dev, "unregistering device\n"); /* Free the device number and remove the /proc/bus/usb entry */ - if (dev->devnum > 0) { - clear_bit(dev->devnum, dev->bus->devmap.devicemap); - usbfs_remove_device(dev); - } + dev_dbg (&dev->dev, "unregistering device\n"); + usb_release_address(dev); + usbfs_remove_device(dev); up(&dev->serialize); device_unregister(&dev->dev); } @@ -1038,24 +1036,23 @@ } } - -// hub-only!! ... and only exported for reset/reinit path. -// otherwise used internally, for usb_new_device() -int usb_set_address(struct usb_device *dev) +/** + * usb_release_address - deallocate device address (usbcore-internal) + * @dev: newly removed device + * + * Removes and deallocates the address assigned to a device. + * Only hub drivers (but not virtual root hub drivers for host + * controllers) should ever call this. + */ +void usb_release_address(struct usb_device *dev) { - int retval; - - if (dev->devnum == 0) - return -EINVAL; - if (dev->state != USB_STATE_DEFAULT && dev->state != USB_STATE_ADDRESS) - return -EINVAL; - retval = usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS, - 0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); - if (retval == 0) - dev->state = USB_STATE_ADDRESS; - return retval; + if (dev->devnum > 0) { + clear_bit(dev->devnum, dev->bus->devmap.devicemap); + dev->devnum = -1; + } } + static inline void usb_show_string(struct usb_device *dev, char *id, int index) { char *buf; @@ -1069,6 +1066,37 @@ kfree(buf); } +static int usb_choose_configuration(struct usb_device *dev) +{ + int c, i; + + c = dev->config[0].desc.bConfigurationValue; + if (dev->descriptor.bNumConfigurations != 1) { + for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { + struct usb_interface_descriptor *desc; + + /* heuristic: Linux is more likely to have class + * drivers, so avoid vendor-specific interfaces. + */ + desc = &dev->config[i].intf_cache[0] + ->altsetting->desc; + if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC) + continue; + /* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS */ + if (desc->bInterfaceClass == USB_CLASS_COMM + && desc->bInterfaceSubClass == 2 + && desc->bInterfaceProtocol == 0xff) + continue; + c = dev->config[i].desc.bConfigurationValue; + break; + } + dev_info(&dev->dev, + "configuration #%d chosen from %d choices\n", + c, dev->descriptor.bNumConfigurations); + } + return c; +} + /* * usb_new_device - perform initial device setup (usbcore-internal) * @dev: newly addressed device (in ADDRESS state) @@ -1090,8 +1118,7 @@ int usb_new_device(struct usb_device *dev) { int err; - int i; - int config; + int c; err = usb_get_configuration(dev); if (err < 0) { @@ -1119,41 +1146,16 @@ dev_err(&dev->dev, "can't device_add, error %d\n", err); goto fail; } - usb_create_driverfs_dev_files (dev); + usb_create_sysfs_dev_files (dev); /* choose and set the configuration. that registers the interfaces * with the driver core, and lets usb device drivers bind to them. * NOTE: should interact with hub power budgeting. */ - config = dev->config[0].desc.bConfigurationValue; - if (dev->descriptor.bNumConfigurations != 1) { - for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { - struct usb_interface_descriptor *desc; - - /* heuristic: Linux is more likely to have class - * drivers, so avoid vendor-specific interfaces. - */ - desc = &dev->config[i].intf_cache[0] - ->altsetting->desc; - if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC) - continue; - /* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS */ - if (desc->bInterfaceClass == USB_CLASS_COMM - && desc->bInterfaceSubClass == 2 - && desc->bInterfaceProtocol == 0xff) - continue; - config = dev->config[i].desc.bConfigurationValue; - break; - } - dev_info(&dev->dev, - "configuration #%d chosen from %d choices\n", - config, - dev->descriptor.bNumConfigurations); - } - err = usb_set_configuration(dev, config); + c = usb_choose_configuration(dev); + err = usb_set_configuration(dev, c); if (err) { - dev_err(&dev->dev, "can't set config #%d, error %d\n", - config, err); + dev_err(&dev->dev, "can't set config #%d, error %d\n", c, err); device_del(&dev->dev); goto fail; } @@ -1166,8 +1168,7 @@ return 0; fail: dev->state = USB_STATE_NOTATTACHED; - clear_bit(dev->devnum, dev->bus->devmap.devicemap); - dev->devnum = -1; + usb_release_address(dev); usb_put_dev(dev); return err; } --- diff/drivers/usb/core/usb.h 2004-05-19 22:12:17.000000000 +0100 +++ source/drivers/usb/core/usb.h 2004-05-27 18:34:18.000000000 +0100 @@ -1,7 +1,7 @@ /* Functions local to drivers/usb/core/ */ -extern void usb_create_driverfs_dev_files (struct usb_device *dev); -extern void usb_create_driverfs_intf_files (struct usb_interface *intf); +extern void usb_create_sysfs_dev_files (struct usb_device *dev); +extern void usb_create_sysfs_intf_files (struct usb_interface *intf); extern int usb_probe_interface (struct device *dev); extern int usb_unbind_interface (struct device *dev); --- diff/drivers/usb/gadget/Kconfig 2004-05-19 22:12:17.000000000 +0100 +++ source/drivers/usb/gadget/Kconfig 2004-05-27 18:34:18.000000000 +0100 @@ -95,6 +95,7 @@ config USB_PXA2XX_SMALL depends on USB_GADGET_PXA2XX bool + default n if USB_ETH_RNDIS default y if USB_ZERO default y if USB_ETH default y if USB_G_SERIAL --- diff/drivers/usb/gadget/epautoconf.c 2004-05-19 22:12:17.000000000 +0100 +++ source/drivers/usb/gadget/epautoconf.c 2004-05-27 18:34:18.000000000 +0100 @@ -96,7 +96,8 @@ /* for now, avoid PXA "interrupt-in"; * it's documented as never using DATA1. */ - if (gadget_is_pxa (gadget)) + if (gadget_is_pxa (gadget) + && 'i' == tmp [1]) return 0; break; case USB_ENDPOINT_XFER_BULK: --- diff/drivers/usb/gadget/pxa2xx_udc.c 2004-05-19 22:12:17.000000000 +0100 +++ source/drivers/usb/gadget/pxa2xx_udc.c 2004-05-27 18:34:18.000000000 +0100 @@ -51,6 +51,7 @@ #include #include #include +#include #include #include --- diff/drivers/usb/gadget/serial.c 2004-05-27 13:41:21.000000000 +0100 +++ source/drivers/usb/gadget/serial.c 2004-05-27 18:34:18.000000000 +0100 @@ -154,14 +154,9 @@ #define GS_CLOSE_TIMEOUT 15 -/* debug macro */ +/* debug settings */ #if G_SERIAL_DEBUG static int debug = G_SERIAL_DEBUG; -#else -static int debug = 0; -#endif - -#if G_SERIAL_DEBUG #define gs_debug(format, arg...) \ do { if (debug) printk(KERN_DEBUG format, ## arg); } while(0) @@ -598,8 +593,10 @@ MODULE_AUTHOR("Al Borchers"); MODULE_LICENSE("GPL"); +#if G_SERIAL_DEBUG MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on"); +#endif MODULE_PARM(read_q_size, "i"); MODULE_PARM_DESC(read_q_size, "Read request queue size, default=32"); --- diff/drivers/usb/host/uhci-hcd.c 2004-05-27 13:41:21.000000000 +0100 +++ source/drivers/usb/host/uhci-hcd.c 2004-05-27 18:34:18.000000000 +0100 @@ -95,6 +95,10 @@ static int uhci_get_current_frame_number(struct uhci_hcd *uhci); static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb); static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb); +static void uhci_remove_pending_urbps(struct uhci_hcd *uhci); +static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs); +static void uhci_free_pending_qhs(struct uhci_hcd *uhci); +static void uhci_free_pending_tds(struct uhci_hcd *uhci); static void hc_state_transitions(struct uhci_hcd *uhci); @@ -373,6 +377,7 @@ { struct uhci_qh *pqh; u32 newlink; + unsigned int age; if (!qh) return; @@ -425,6 +430,12 @@ list_del_init(&qh->urbp->queue_list); qh->urbp = NULL; + age = uhci_get_current_frame_number(uhci); + if (age != uhci->qh_remove_age) { + uhci_free_pending_qhs(uhci); + uhci->qh_remove_age = age; + } + /* Check to see if the remove list is empty. Set the IOC bit */ /* to force an interrupt so we can remove the QH */ if (list_empty(&uhci->qh_remove_list)) @@ -628,6 +639,7 @@ { struct list_head *head, *tmp; struct urb_priv *urbp; + unsigned int age; urbp = (struct urb_priv *)urb->hcpriv; if (!urbp) @@ -637,6 +649,12 @@ dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list " "or uhci->remove_list!\n", urb); + age = uhci_get_current_frame_number(uhci); + if (age != uhci->td_remove_age) { + uhci_free_pending_tds(uhci); + uhci->td_remove_age = age; + } + /* Check to see if the remove list is empty. Set the IOC bit */ /* to force an interrupt so we can remove the TD's*/ if (list_empty(&uhci->td_remove_list)) @@ -1512,6 +1530,7 @@ struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned long flags; struct urb_priv *urbp; + unsigned int age; spin_lock_irqsave(&uhci->schedule_lock, flags); urbp = urb->hcpriv; @@ -1521,6 +1540,12 @@ uhci_unlink_generic(uhci, urb); + age = uhci_get_current_frame_number(uhci); + if (age != uhci->urb_remove_age) { + uhci_remove_pending_urbps(uhci); + uhci->urb_remove_age = age; + } + /* If we're the first, set the next interrupt bit */ if (list_empty(&uhci->urb_remove_list)) uhci_set_next_interrupt(uhci); @@ -1590,6 +1615,12 @@ INIT_LIST_HEAD(&list); spin_lock_irqsave(&uhci->schedule_lock, flags); + if (!list_empty(&uhci->urb_remove_list) && + uhci_get_current_frame_number(uhci) != uhci->urb_remove_age) { + uhci_remove_pending_urbps(uhci); + uhci_finish_completion(hcd, NULL); + } + head = &uhci->urb_list; tmp = head->next; while (tmp != head) { @@ -1728,6 +1759,7 @@ unsigned int io_addr = uhci->io_addr; unsigned short status; struct list_head *tmp, *head; + unsigned int age; /* * Read the interrupt status, and write it back to clear the @@ -1758,11 +1790,20 @@ spin_lock(&uhci->schedule_lock); - uhci_free_pending_qhs(uhci); - uhci_free_pending_tds(uhci); - uhci_remove_pending_urbps(uhci); - - uhci_clear_next_interrupt(uhci); + age = uhci_get_current_frame_number(uhci); + if (age != uhci->qh_remove_age) + uhci_free_pending_qhs(uhci); + if (age != uhci->td_remove_age) + uhci_free_pending_tds(uhci); + if (age != uhci->urb_remove_age) + uhci_remove_pending_urbps(uhci); + + if (list_empty(&uhci->urb_remove_list) && + list_empty(&uhci->td_remove_list) && + list_empty(&uhci->qh_remove_list)) + uhci_clear_next_interrupt(uhci); + else + uhci_set_next_interrupt(uhci); /* Walk the list of pending URB's to see which ones completed */ head = &uhci->urb_list; --- diff/drivers/usb/host/uhci-hcd.h 2004-05-27 13:41:21.000000000 +0100 +++ source/drivers/usb/host/uhci-hcd.h 2004-05-27 18:34:18.000000000 +0100 @@ -357,12 +357,15 @@ /* List of QH's that are done, but waiting to be unlinked (race) */ struct list_head qh_remove_list; /* P: uhci->schedule_lock */ + unsigned int qh_remove_age; /* Age in frames */ /* List of TD's that are done, but waiting to be freed (race) */ struct list_head td_remove_list; /* P: uhci->schedule_lock */ + unsigned int td_remove_age; /* Age in frames */ /* List of asynchronously unlinked URB's */ struct list_head urb_remove_list; /* P: uhci->schedule_lock */ + unsigned int urb_remove_age; /* Age in frames */ /* List of URB's awaiting completion callback */ struct list_head complete_list; /* P: uhci->schedule_lock */ --- diff/drivers/usb/input/hiddev.c 2004-05-19 22:12:18.000000000 +0100 +++ source/drivers/usb/input/hiddev.c 2004-05-27 18:34:18.000000000 +0100 @@ -232,7 +232,7 @@ static struct usb_class_driver hiddev_class; static void hiddev_cleanup(struct hiddev *hiddev) { - hiddev_table[hiddev->hid->minor] = NULL; + hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL; usb_deregister_dev(hiddev->hid->intf, &hiddev_class); kfree(hiddev); } @@ -612,7 +612,7 @@ uref = &uref_multi->uref; if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { if (copy_from_user(uref_multi, (void *) arg, - sizeof(uref_multi))) + sizeof(*uref_multi))) goto fault; } else { if (copy_from_user(uref, (void *) arg, sizeof(*uref))) --- diff/drivers/usb/input/powermate.c 2004-05-19 22:12:18.000000000 +0100 +++ source/drivers/usb/input/powermate.c 2004-05-27 18:34:18.000000000 +0100 @@ -33,6 +33,7 @@ #include #include #include +#include #include #define POWERMATE_VENDOR 0x077d /* Griffin Technology, Inc. */ @@ -67,7 +68,7 @@ dma_addr_t configcr_dma; struct usb_device *udev; struct input_dev input; - struct semaphore lock; + spinlock_t lock; int static_brightness; int pulse_speed; int pulse_table; @@ -116,7 +117,7 @@ __FUNCTION__, retval); } -/* Decide if we need to issue a control message and do so. Must be called with pm->lock down */ +/* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */ static void powermate_sync_state(struct powermate_device *pm) { if (pm->requires_update == 0) @@ -194,19 +195,22 @@ static void powermate_config_complete(struct urb *urb, struct pt_regs *regs) { struct powermate_device *pm = urb->context; + unsigned long flags; if (urb->status) printk(KERN_ERR "powermate: config urb returned %d\n", urb->status); - down(&pm->lock); + spin_lock_irqsave(&pm->lock, flags); powermate_sync_state(pm); - up(&pm->lock); + spin_unlock_irqrestore(&pm->lock, flags); } /* Set the LED up as described and begin the sync with the hardware if required */ static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed, int pulse_table, int pulse_asleep, int pulse_awake) { + unsigned long flags; + if (pulse_speed < 0) pulse_speed = 0; if (pulse_table < 0) @@ -219,7 +223,8 @@ pulse_asleep = !!pulse_asleep; pulse_awake = !!pulse_awake; - down(&pm->lock); + + spin_lock_irqsave(&pm->lock, flags); /* mark state updates which are required */ if (static_brightness != pm->static_brightness){ @@ -242,7 +247,7 @@ powermate_sync_state(pm); - up(&pm->lock); + spin_unlock_irqrestore(&pm->lock, flags); } /* Callback from the Input layer when an event arrives from userspace to configure the LED */ @@ -344,7 +349,7 @@ return -ENOMEM; } - init_MUTEX(&pm->lock); + pm->lock = SPIN_LOCK_UNLOCKED; init_input_dev(&pm->input); /* get a handle to the interrupt data pipe */ @@ -411,7 +416,6 @@ usb_set_intfdata(intf, NULL); if (pm) { - down(&pm->lock); pm->requires_update = 0; usb_unlink_urb(pm->irq); input_unregister_device(&pm->input); --- diff/drivers/usb/misc/emi26.c 2004-05-27 13:41:22.000000000 +0100 +++ source/drivers/usb/misc/emi26.c 2004-05-27 18:34:18.000000000 +0100 @@ -194,7 +194,7 @@ /* return 1 to fail the driver inialization * and give real driver change to load */ - return 1; + err = 1; wraperr: kfree(buf); --- diff/drivers/usb/misc/emi62.c 2004-05-27 13:41:22.000000000 +0100 +++ source/drivers/usb/misc/emi62.c 2004-05-27 18:34:18.000000000 +0100 @@ -229,6 +229,8 @@ goto wraperr; } + kfree(buf); + /* return 1 to fail the driver inialization * and give real driver change to load */ return 1; --- diff/drivers/usb/net/kaweth.c 2004-05-27 13:41:22.000000000 +0100 +++ source/drivers/usb/net/kaweth.c 2004-05-27 18:34:18.000000000 +0100 @@ -1240,20 +1240,21 @@ init_waitqueue_head(&awd.wqh); awd.done = 0; - set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&awd.wqh, &wait); urb->context = &awd; - status = usb_submit_urb(urb, GFP_ATOMIC); + status = usb_submit_urb(urb, GFP_NOIO); if (status) { // something went wrong usb_free_urb(urb); - set_current_state(TASK_RUNNING); remove_wait_queue(&awd.wqh, &wait); return status; } - while (timeout && !awd.done) + set_current_state(TASK_UNINTERRUPTIBLE); + while (timeout && !awd.done) { timeout = schedule_timeout(timeout); + set_current_state(TASK_UNINTERRUPTIBLE); + } set_current_state(TASK_RUNNING); remove_wait_queue(&awd.wqh, &wait); --- diff/drivers/usb/net/pegasus.h 2004-05-19 22:12:19.000000000 +0100 +++ source/drivers/usb/net/pegasus.h 2004-05-27 18:34:18.000000000 +0100 @@ -136,6 +136,7 @@ #define VENDOR_LANEED 0x056e #define VENDOR_LINKSYS 0x066b #define VENDOR_MELCO 0x0411 +#define VENDOR_MICROSOFT 0x045e #define VENDOR_MOBILITY 0x1342 #define VENDOR_NETGEAR 0x0846 #define VENDOR_OCT 0x0b39 @@ -265,6 +266,8 @@ DEFAULT_GPIO_RESET ) PEGASUS_DEV( "MELCO/BUFFALO LUA2-TX", VENDOR_MELCO, 0x0009, DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "Microsoft MN-110", VENDOR_MICROSOFT, 0x007a, + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "NETGEAR FA101", VENDOR_NETGEAR, 0x1020, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "OCT Inc.", VENDOR_OCT, 0x0109, --- diff/drivers/usb/serial/Kconfig 2004-05-19 22:12:19.000000000 +0100 +++ source/drivers/usb/serial/Kconfig 2004-05-27 18:34:18.000000000 +0100 @@ -314,8 +314,8 @@ module will be called kl5kusb105. config USB_SERIAL_KOBIL_SCT - tristate "USB KOBIL chipcard reader (EXPERIMENTAL)" - depends on USB_SERIAL && EXPERIMENTAL + tristate "USB KOBIL chipcard reader" + depends on USB_SERIAL ---help--- Say Y here if you want to use one of the following KOBIL USB chipcard readers: --- diff/drivers/usb/serial/kobil_sct.c 2004-05-27 13:41:22.000000000 +0100 +++ source/drivers/usb/serial/kobil_sct.c 2004-05-27 18:34:18.000000000 +0100 @@ -21,6 +21,9 @@ * Supported readers: USB TWIN, KAAN Standard Plus and SecOVID Reader Plus * (Adapter K), B1 Professional and KAAN Professional (Adapter B) * + * (21/05/2004) tw + * Fix bug with P'n'P readers + * * (28/05/2003) tw * Add support for KAAN SIM * @@ -59,7 +62,7 @@ #include "usb-serial.h" /* Version Information */ -#define DRIVER_VERSION "28/05/2003" +#define DRIVER_VERSION "21/05/2004" #define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com" #define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)" @@ -339,6 +342,12 @@ ); dbg("%s - port %d Send reset_all_queues URB returns: %i", __FUNCTION__, port->number, result); } + if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || + priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { + // start reading (Adapter B 'cause PNP string) + result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC ); + dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result); + } kfree(transfer_buffer); return 0; @@ -456,6 +465,11 @@ if ( ((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) || ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4))) ) { + // stop reading (except TWIN and KAAN SIM) + if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) ) { + usb_unlink_urb( port->interrupt_in_urb ); + } + todo = priv->filled - priv->cur_pos; while(todo > 0) { @@ -463,25 +477,23 @@ length = (todo < 8) ? todo : 8; // copy data to transfer buffer memcpy(port->write_urb->transfer_buffer, priv->buf + priv->cur_pos, length ); - - usb_fill_bulk_urb( port->write_urb, - port->serial->dev, - usb_sndbulkpipe( port->serial->dev, priv->write_int_endpoint_address), - port->write_urb->transfer_buffer, - length, - kobil_write_callback, - port + usb_fill_int_urb( port->write_urb, + port->serial->dev, + usb_sndintpipe(port->serial->dev, priv->write_int_endpoint_address), + port->write_urb->transfer_buffer, + length, + kobil_write_callback, + port, + 8 ); priv->cur_pos = priv->cur_pos + length; - result = usb_submit_urb( port->write_urb, GFP_ATOMIC ); + result = usb_submit_urb( port->write_urb, GFP_NOIO ); dbg("%s - port %d Send write URB returns: %i", __FUNCTION__, port->number, result); todo = priv->filled - priv->cur_pos; if (todo > 0) { - //mdelay(16); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(24 * HZ / 1000); + msleep(24); } } // end while @@ -492,9 +504,14 @@ // someone sets the dev to 0 if the close method has been called port->interrupt_in_urb->dev = port->serial->dev; - // start reading - result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC ); - dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result); + // start reading (except TWIN and KAAN SIM) + if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) ) { + // someone sets the dev to 0 if the close method has been called + port->interrupt_in_urb->dev = port->serial->dev; + + result = usb_submit_urb( port->interrupt_in_urb, GFP_NOIO ); + dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result); + } } return count; } --- diff/drivers/usb/serial/visor.c 2004-05-27 13:41:22.000000000 +0100 +++ source/drivers/usb/serial/visor.c 2004-05-27 18:34:18.000000000 +0100 @@ -680,7 +680,7 @@ char *string; int retval = 0; int i; - int num_ports; + int num_ports = 0; dbg("%s", __FUNCTION__); @@ -702,41 +702,50 @@ __FUNCTION__, retval); goto exit; } - - connection_info = (struct visor_connection_info *)transfer_buffer; - le16_to_cpus(&connection_info->num_ports); - num_ports = connection_info->num_ports; - /* handle devices that report invalid stuff here */ - if (num_ports > 2) - num_ports = 2; - dev_info(dev, "%s: Number of ports: %d\n", serial->type->name, - connection_info->num_ports); + if (retval == sizeof(*connection_info)) { + connection_info = (struct visor_connection_info *)transfer_buffer; - for (i = 0; i < num_ports; ++i) { - switch (connection_info->connections[i].port_function_id) { - case VISOR_FUNCTION_GENERIC: - string = "Generic"; - break; - case VISOR_FUNCTION_DEBUGGER: - string = "Debugger"; - break; - case VISOR_FUNCTION_HOTSYNC: - string = "HotSync"; - break; - case VISOR_FUNCTION_CONSOLE: - string = "Console"; - break; - case VISOR_FUNCTION_REMOTE_FILE_SYS: - string = "Remote File System"; - break; - default: - string = "unknown"; - break; + le16_to_cpus(&connection_info->num_ports); + num_ports = connection_info->num_ports; + + for (i = 0; i < num_ports; ++i) { + switch (connection_info->connections[i].port_function_id) { + case VISOR_FUNCTION_GENERIC: + string = "Generic"; + break; + case VISOR_FUNCTION_DEBUGGER: + string = "Debugger"; + break; + case VISOR_FUNCTION_HOTSYNC: + string = "HotSync"; + break; + case VISOR_FUNCTION_CONSOLE: + string = "Console"; + break; + case VISOR_FUNCTION_REMOTE_FILE_SYS: + string = "Remote File System"; + break; + default: + string = "unknown"; + break; + } + dev_info(dev, "%s: port %d, is for %s use\n", + serial->type->name, + connection_info->connections[i].port, string); } - dev_info(dev, "%s: port %d, is for %s use\n", serial->type->name, - connection_info->connections[i].port, string); } + /* + * Handle devices that report invalid stuff here. + */ + if (num_ports == 0 || num_ports > 2) { + dev_warn (dev, "%s: No valid connect info available\n", + serial->type->name); + num_ports = 2; + } + + dev_info(dev, "%s: Number of ports: %d\n", serial->type->name, + num_ports); /* * save off our num_ports info so that we can use it in the @@ -868,8 +877,7 @@ static int treo_attach (struct usb_serial *serial) { - struct usb_serial_port *port; - int i; + struct usb_serial_port *swap_port; /* Only do this endpoint hack for the Handspring devices with * interrupt in endpoints, which for now are the Treo devices. */ @@ -879,31 +887,28 @@ dbg("%s", __FUNCTION__); - /* Ok, this is pretty ugly, but these devices want to use the - * interrupt endpoint as paired up with a bulk endpoint for a - * "virtual serial port". So let's force the endpoints to be - * where we want them to be. */ - for (i = serial->num_bulk_in; i < serial->num_ports; ++i) { - port = serial->port[i]; - port->read_urb = serial->port[0]->read_urb; - port->bulk_in_endpointAddress = serial->port[0]->bulk_in_endpointAddress; - port->bulk_in_buffer = serial->port[0]->bulk_in_buffer; - } - - for (i = serial->num_bulk_out; i < serial->num_ports; ++i) { - port = serial->port[i]; - port->write_urb = serial->port[0]->write_urb; - port->bulk_out_size = serial->port[0]->bulk_out_size; - port->bulk_out_endpointAddress = serial->port[0]->bulk_out_endpointAddress; - port->bulk_out_buffer = serial->port[0]->bulk_out_buffer; - } - - for (i = serial->num_interrupt_in; i < serial->num_ports; ++i) { - port = serial->port[i]; - port->interrupt_in_urb = serial->port[0]->interrupt_in_urb; - port->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress; - port->interrupt_in_buffer = serial->port[0]->interrupt_in_buffer; - } + /* + * It appears that Treos want to use the 1st interrupt endpoint to + * communicate with the 2nd bulk out endpoint, so let's swap the 1st + * and 2nd bulk in and interrupt endpoints. Note that swapping the + * bulk out endpoints would break lots of apps that want to communicate + * on the second port. + */ +#define COPY_PORT(dest, src) \ + dest->read_urb = src->read_urb; \ + dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress; \ + dest->bulk_in_buffer = src->bulk_in_buffer; \ + dest->interrupt_in_urb = src->interrupt_in_urb; \ + dest->interrupt_in_endpointAddress = src->interrupt_in_endpointAddress; \ + dest->interrupt_in_buffer = src->interrupt_in_buffer; + + swap_port = kmalloc(sizeof(*swap_port), GFP_KERNEL); + if (!swap_port) + return -ENOMEM; + COPY_PORT(swap_port, serial->port[0]); + COPY_PORT(serial->port[0], serial->port[1]); + COPY_PORT(serial->port[1], swap_port); + kfree(swap_port); return 0; } --- diff/drivers/usb/storage/transport.c 2004-05-27 13:41:22.000000000 +0100 +++ source/drivers/usb/storage/transport.c 2004-05-27 18:34:18.000000000 +0100 @@ -1112,8 +1112,7 @@ /* long wait for reset, so unlock to allow disconnects */ up(&us->dev_semaphore); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ*6); + msleep(6000); down(&us->dev_semaphore); if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { US_DEBUGP("Reset interrupted by disconnect\n"); --- diff/drivers/usb/storage/unusual_devs.h 2004-05-27 13:41:22.000000000 +0100 +++ source/drivers/usb/storage/unusual_devs.h 2004-05-27 18:34:18.000000000 +0100 @@ -366,6 +366,12 @@ "USB Hard Disk", US_SC_RBC, US_PR_CB, NULL, 0 ), +/* Submitted by Jol Bourquard */ +UNUSUAL_DEV( 0x05ab, 0x0060, 0x1104, 0x1110, + "In-System", + "PyroGate External CD-ROM Enclosure (FCD-523)", + US_SC_SCSI, US_PR_BULK, NULL, 0 ), + #ifdef CONFIG_USB_STORAGE_ISD200 UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110, "In-System", --- diff/drivers/video/aty/atyfb_base.c 2004-05-27 13:41:22.000000000 +0100 +++ source/drivers/video/aty/atyfb_base.c 2004-05-27 18:34:18.000000000 +0100 @@ -1938,6 +1938,19 @@ if (i < 0) continue; + rp = &pdev->resource[0]; + if (rp->flags & IORESOURCE_IO) + rp = &pdev->resource[1]; + addr = rp->start; + if (!addr) + continue; + + res_start = rp->start; + res_size = rp->end - rp->start + 1; + if (!request_mem_region + (res_start, res_size, "atyfb")) + continue; + info = kmalloc(sizeof(struct fb_info), GFP_ATOMIC); if (!info) { @@ -1960,19 +1973,6 @@ info->fix = atyfb_fix; info->par = default_par; - rp = &pdev->resource[0]; - if (rp->flags & IORESOURCE_IO) - rp = &pdev->resource[1]; - addr = rp->start; - if (!addr) - continue; - - res_start = rp->start; - res_size = rp->end - rp->start + 1; - if (!request_mem_region - (res_start, res_size, "atyfb")) - continue; - #ifdef __sparc__ /* * Map memory-mapped registers. @@ -2000,6 +2000,7 @@ if (!default_par->mmap_map) { printk ("atyfb_init: can't alloc mmap_map\n"); + kfree(default_par); kfree(info); release_mem_region(res_start, res_size); return -ENXIO; @@ -2217,6 +2218,9 @@ ioremap(info->fix.mmio_start, 0x1000); if (!default_par->ati_regbase) { +#ifdef __sparc__ + kfree(default_par->mmap_map); +#endif kfree(default_par); kfree(info); release_mem_region(res_start, res_size); @@ -2247,6 +2251,10 @@ (char *) ioremap(addr, 0x800000); if (!info->screen_base) { +#ifdef __sparc__ + kfree(default_par->mmap_map); +#endif + kfree(default_par); kfree(info); release_mem_region(res_start, res_size); return -ENXIO; @@ -2258,6 +2266,7 @@ if (default_par->mmap_map) kfree(default_par->mmap_map); #endif + kfree(default_par); kfree(info); release_mem_region(res_start, res_size); return -ENXIO; @@ -2326,6 +2335,7 @@ memset(default_par, 0, sizeof(struct atyfb_par)); info->fix = atyfb_fix; + info->par = default_par; /* * Map the video memory (physical address given) to somewhere in the @@ -2357,6 +2367,7 @@ } if (!aty_init(info, "ISA bus")) { + kfree(default_par); kfree(info); /* This is insufficient! kernel_map has added two large chunks!! */ return -ENXIO; --- diff/drivers/video/aty/radeon_accel.c 2004-05-27 13:41:22.000000000 +0100 +++ source/drivers/video/aty/radeon_accel.c 2004-05-27 18:34:18.000000000 +0100 @@ -13,7 +13,10 @@ rinfo->dp_gui_master_cntl /* contains, like GMC_DST_32BPP */ | GMC_BRUSH_SOLID_COLOR | ROP3_P); - OUTREG(DP_BRUSH_FRGD_CLR, region->color); + if (radeon_get_dstbpp(rinfo->depth) != DST_8BPP) + OUTREG(DP_BRUSH_FRGD_CLR, rinfo->pseudo_palette[region->color]); + else + OUTREG(DP_BRUSH_FRGD_CLR, region->color); OUTREG(DP_WRITE_MSK, 0xffffffff); OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); --- diff/drivers/video/aty/radeon_pm.c 2004-05-19 22:12:22.000000000 +0100 +++ source/drivers/video/aty/radeon_pm.c 2004-05-27 18:34:18.000000000 +0100 @@ -867,7 +867,7 @@ } /* Blank display and LCD */ - radeonfb_blank(VESA_POWERDOWN+1, info); + radeonfb_blank(VESA_POWERDOWN, info); /* Sleep */ rinfo->asleep = 1; --- diff/drivers/video/console/sticore.c 2004-05-19 22:12:22.000000000 +0100 +++ source/drivers/video/console/sticore.c 2004-05-27 18:34:18.000000000 +0100 @@ -22,7 +22,6 @@ #include #include -#include #include #include #include --- diff/drivers/video/matrox/matroxfb_DAC1064.c 2004-05-19 22:12:23.000000000 +0100 +++ source/drivers/video/matrox/matroxfb_DAC1064.c 2004-05-27 18:34:18.000000000 +0100 @@ -660,7 +660,7 @@ ACCESS_FBINFO(features.accel.has_cacheflush) = 1; ACCESS_FBINFO(outputs[0]).output = &m1064; - ACCESS_FBINFO(outputs[0]).src = MATROXFB_SRC_CRTC1; + ACCESS_FBINFO(outputs[0]).src = ACCESS_FBINFO(outputs[0]).default_src; ACCESS_FBINFO(outputs[0]).data = MINFO; ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR; @@ -859,7 +859,7 @@ { ACCESS_FBINFO(outputs[0]).output = &m1064; } - ACCESS_FBINFO(outputs[0]).src = MATROXFB_SRC_CRTC1; + ACCESS_FBINFO(outputs[0]).src = ACCESS_FBINFO(outputs[0]).default_src; ACCESS_FBINFO(outputs[0]).data = MINFO; ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR; --- diff/drivers/video/matrox/matroxfb_Ti3026.c 2004-05-19 22:12:23.000000000 +0100 +++ source/drivers/video/matrox/matroxfb_Ti3026.c 2004-05-27 18:34:18.000000000 +0100 @@ -692,7 +692,7 @@ ACCESS_FBINFO(outputs[0]).data = MINFO; ACCESS_FBINFO(outputs[0]).output = &ti3026_output; - ACCESS_FBINFO(outputs[0]).src = MATROXFB_SRC_CRTC1; + ACCESS_FBINFO(outputs[0]).src = ACCESS_FBINFO(outputs[0]).default_src; ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR; if (ACCESS_FBINFO(devflags.noinit)) --- diff/drivers/video/matrox/matroxfb_base.c 2004-05-19 22:12:23.000000000 +0100 +++ source/drivers/video/matrox/matroxfb_base.c 2004-05-27 18:34:18.000000000 +0100 @@ -1272,6 +1272,7 @@ static int dfp; /* "matrox:dfp */ static int dfp_type = -1; /* "matrox:dfp:xxx */ static int memtype = -1; /* "matrox:memtype:xxx" */ +static char outputs[8]; /* "matrox:outputs:xxx" */ #ifndef MODULE static char videomode[64]; /* "matrox:mode:xxxxx" or "matrox:xxxxx" */ @@ -1537,6 +1538,39 @@ static int hotplug = 0; +static void setDefaultOutputs(WPMINFO2) { + unsigned int i; + const char* ptr; + + ACCESS_FBINFO(outputs[0]).default_src = MATROXFB_SRC_CRTC1; + if (ACCESS_FBINFO(devflags.g450dac)) { + ACCESS_FBINFO(outputs[1]).default_src = MATROXFB_SRC_CRTC1; + ACCESS_FBINFO(outputs[2]).default_src = MATROXFB_SRC_CRTC1; + } else if (dfp) { + ACCESS_FBINFO(outputs[2]).default_src = MATROXFB_SRC_CRTC1; + } + ptr = outputs; + for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { + char c = *ptr++; + + if (c == 0) { + break; + } + if (c == '0') { + ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_NONE; + } else if (c == '1') { + ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_CRTC1; + } else if (c == '2' && ACCESS_FBINFO(devflags.crtc2)) { + ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_CRTC2; + } else { + printk(KERN_ERR "matroxfb: Unknown outputs setting\n"); + break; + } + } + /* Nullify this option for subsequent adapters */ + outputs[0] = 0; +} + static int initMatrox2(WPMINFO struct board* b){ unsigned long ctrlptr_phys = 0; unsigned long video_base_phys = 0; @@ -1577,20 +1611,18 @@ ACCESS_FBINFO(devflags.crtc2) = (b->flags & DEVF_CRTC2) != 0; ACCESS_FBINFO(devflags.maven_capable) = (b->flags & DEVF_MAVEN_CAPABLE) != 0; ACCESS_FBINFO(devflags.dualhead) = (b->flags & DEVF_DUALHEAD) != 0; + ACCESS_FBINFO(devflags.dfp_type) = dfp_type; + ACCESS_FBINFO(devflags.g450dac) = (b->flags & DEVF_G450DAC) != 0; + ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode); + ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode); + setDefaultOutputs(PMINFO2); if (b->flags & DEVF_PANELLINK_CAPABLE) { ACCESS_FBINFO(outputs[2]).data = MINFO; ACCESS_FBINFO(outputs[2]).output = &panellink_output; - if (dfp) - ACCESS_FBINFO(outputs[2]).src = MATROXFB_SRC_CRTC1; - else - ACCESS_FBINFO(outputs[2]).src = MATROXFB_SRC_NONE; + ACCESS_FBINFO(outputs[2]).src = ACCESS_FBINFO(outputs[2]).default_src; ACCESS_FBINFO(outputs[2]).mode = MATROXFB_OUTPUT_MODE_MONITOR; ACCESS_FBINFO(devflags.panellink) = 1; } - ACCESS_FBINFO(devflags.dfp_type) = dfp_type; - ACCESS_FBINFO(devflags.g450dac) = (b->flags & DEVF_G450DAC) != 0; - ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode); - ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode); if (ACCESS_FBINFO(capable.cross4MB) < 0) ACCESS_FBINFO(capable.cross4MB) = b->flags & DEVF_CROSS4MB; @@ -1813,6 +1845,13 @@ to yres_virtual * xres_virtual < 2^32 */ } matroxfb_init_fix(PMINFO2); + /* Normalize values (namely yres_virtual) */ + matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon)); + /* And put it into "current" var. Do NOT program hardware yet, or we'll not take over + * vgacon correctly. fbcon_startup will call fb_set_par for us, WITHOUT check_var, + * and unfortunately it will do it BEFORE vgacon contents is saved, so it won't work + * anyway. But we at least tried... */ + ACCESS_FBINFO(fbcon.var) = vesafb_defined; err = -EINVAL; printk(KERN_INFO "matroxfb: %dx%dx%dbpp (virtual: %dx%d)\n", @@ -1834,6 +1873,9 @@ * until someone tells me what is proper thing to do */ printk(KERN_INFO "fb%d: initializing hardware\n", ACCESS_FBINFO(fbcon.node)); + /* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var + * already before, so register_framebuffer works correctly. */ + vesafb_defined.activate |= FB_ACTIVATE_FORCE; fb_set_var(&ACCESS_FBINFO(fbcon), &vesafb_defined); } return 0; @@ -2288,6 +2330,8 @@ mem = simple_strtoul(this_opt+4, NULL, 0); else if (!strncmp(this_opt, "mode:", 5)) strlcpy(videomode, this_opt+5, sizeof(videomode)); + else if (!strncmp(this_opt, "outputs:", 8)) + strlcpy(outputs, this_opt+8, sizeof(outputs)); else if (!strncmp(this_opt, "dfp:", 4)) { dfp_type = simple_strtoul(this_opt+4, NULL, 0); dfp = 1; @@ -2463,6 +2507,8 @@ MODULE_PARM_DESC(dfp, "Specifies whether to use digital flat panel interface of G200/G400 (0 or 1) (default=0)"); MODULE_PARM(dfp_type, "i"); MODULE_PARM_DESC(dfp_type, "Specifies DFP interface type (0 to 255) (default=read from hardware)"); +MODULE_PARM(outputs, "c8"); +MODULE_PARM_DESC(outputs, "Specifies which CRTC is mapped to which output (string of up to three letters, consisting of 0 (disabled), 1 (CRTC1), 2 (CRTC2)) (default=111 for Gx50, 101 for G200/G400 with DFP, and 100 for all other devices)"); #ifdef CONFIG_PPC_PMAC MODULE_PARM(vmode, "i"); MODULE_PARM_DESC(vmode, "Specify the vmode mode number that should be used (640x480 default)"); --- diff/drivers/video/matrox/matroxfb_base.h 2004-05-19 22:12:23.000000000 +0100 +++ source/drivers/video/matrox/matroxfb_base.h 2004-05-27 18:34:18.000000000 +0100 @@ -479,6 +479,7 @@ struct matrox_altout* output; void* data; unsigned int mode; + unsigned int default_src; } outputs[MATROXFB_MAX_OUTPUTS]; #define MATROXFB_MAX_FB_DRIVERS 5 --- diff/drivers/video/matrox/matroxfb_crtc2.c 2004-05-19 22:12:23.000000000 +0100 +++ source/drivers/video/matrox/matroxfb_crtc2.c 2004-05-27 18:34:18.000000000 +0100 @@ -628,15 +628,6 @@ m2info->mmio.vbase = ACCESS_FBINFO(mmio.vbase); m2info->mmio.len = ACCESS_FBINFO(mmio.len); - /* - * If we have unused output, connect CRTC2 to it... - */ - if (ACCESS_FBINFO(outputs[1]).output && - ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_NONE && - ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_NONE) { - ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_CRTC2; - } - matroxfb_dh_init_fix(m2info); if (register_framebuffer(&m2info->fbcon)) { return -ENXIO; --- diff/drivers/video/matrox/matroxfb_g450.c 2004-05-19 22:12:23.000000000 +0100 +++ source/drivers/video/matrox/matroxfb_g450.c 2004-05-27 18:34:18.000000000 +0100 @@ -591,11 +591,11 @@ if (ACCESS_FBINFO(devflags.g450dac)) { down_write(&ACCESS_FBINFO(altout.lock)); tvo_fill_defaults(PMINFO2); - ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_CRTC1; + ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src; ACCESS_FBINFO(outputs[1]).data = MINFO; ACCESS_FBINFO(outputs[1]).output = &matroxfb_g450_altout; ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR; - ACCESS_FBINFO(outputs[2]).src = MATROXFB_SRC_CRTC1; + ACCESS_FBINFO(outputs[2]).src = ACCESS_FBINFO(outputs[2]).default_src; ACCESS_FBINFO(outputs[2]).data = MINFO; ACCESS_FBINFO(outputs[2]).output = &matroxfb_g450_dvi; ACCESS_FBINFO(outputs[2]).mode = MATROXFB_OUTPUT_MODE_MONITOR; --- diff/drivers/video/matrox/matroxfb_maven.c 2004-05-19 22:12:23.000000000 +0100 +++ source/drivers/video/matrox/matroxfb_maven.c 2004-05-27 18:34:18.000000000 +0100 @@ -1188,7 +1188,7 @@ md->client = clnt; down_write(&ACCESS_FBINFO(altout.lock)); ACCESS_FBINFO(outputs[1]).output = &maven_altout; - ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_NONE; + ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src; ACCESS_FBINFO(outputs[1]).data = md; ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR; up_write(&ACCESS_FBINFO(altout.lock)); @@ -1249,6 +1249,7 @@ err = -ENOMEM; goto ERROR0; } + memset(new_client, 0, sizeof(*new_client) + sizeof(*data)); data = (struct maven_data*)(new_client + 1); i2c_set_clientdata(new_client, data); new_client->addr = address; --- diff/drivers/video/pxafb.c 2004-05-27 13:41:22.000000000 +0100 +++ source/drivers/video/pxafb.c 2004-05-27 18:34:18.000000000 +0100 @@ -153,7 +153,7 @@ * 12 or 16-bit True Colour. We encode the RGB value * according to the RGB bitfield information. */ - if (regno <= 16) { + if (regno < 16) { u32 *pal = fbi->fb.pseudo_palette; val = chan_to_field(red, &fbi->fb.var.red); @@ -448,7 +448,7 @@ { struct pxafb_lcd_reg new_regs; u_long flags; - u_int pcd = get_pcd(var->pixclock); + u_int lines_per_panel, pcd = get_pcd(var->pixclock); DPRINTK("Configuring PXA LCD\n"); @@ -509,8 +509,16 @@ LCCR1_BegLnDel(var->left_margin) + LCCR1_EndLnDel(var->right_margin); + /* + * If we have a dual scan LCD, we need to halve + * the YRES parameter. + */ + lines_per_panel = var->yres; + if (fbi->lccr0 & LCCR0_SDS) + lines_per_panel /= 2; + new_regs.lccr2 = - LCCR2_DisHght(var->yres) + + LCCR2_DisHght(lines_per_panel) + LCCR2_VrtSnchWdth(var->vsync_len) + LCCR2_BegFrmDel(var->upper_margin) + LCCR2_EndFrmDel(var->lower_margin); @@ -540,9 +548,7 @@ fbi->dmadesc_fbhigh_dma = fbi->palette_dma - 2*16; fbi->dmadesc_palette_dma = fbi->palette_dma - 1*16; - #define BYTES_PER_PANEL ((fbi->lccr0 & LCCR0_SDS) == LCCR0_Dual ? \ - (var->xres * var->yres * var->bits_per_pixel / 8 / 2) : \ - (var->xres * var->yres * var->bits_per_pixel / 8)) +#define BYTES_PER_PANEL (lines_per_panel * fbi->fb.fix.line_length) /* populate descriptors */ fbi->dmadesc_fblow_cpu->fdadr = fbi->dmadesc_fblow_dma; @@ -733,8 +739,7 @@ LCSR = 0xffffffff; /* Clear LCD Status Register */ LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */ - //TODO?enable_irq(IRQ_LCD); /* Enable LCD IRQ */ - LCCR0 &= ~LCCR0_ENB; /* Disable LCD Controller */ + LCCR0 |= LCCR0_DIS; /* Disable LCD Controller */ schedule_timeout(20 * HZ / 1000); remove_wait_queue(&fbi->ctrlr_wait, &wait); @@ -1137,25 +1142,25 @@ } } else if (!strncmp(this_opt, "pixclock:", 9)) { inf->pixclock = simple_strtoul(this_opt+9, NULL, 0); - dev_info(dev, "override pixclock: %uld\n", inf->pixclock); + dev_info(dev, "override pixclock: %u\n", inf->pixclock); } else if (!strncmp(this_opt, "left:", 5)) { inf->left_margin = simple_strtoul(this_opt+5, NULL, 0); - dev_info(dev, "override left: %d\n", inf->left_margin); + dev_info(dev, "override left: %u\n", inf->left_margin); } else if (!strncmp(this_opt, "right:", 6)) { inf->right_margin = simple_strtoul(this_opt+6, NULL, 0); - dev_info(dev, "override right: %d\n", inf->right_margin); + dev_info(dev, "override right: %u\n", inf->right_margin); } else if (!strncmp(this_opt, "upper:", 6)) { inf->upper_margin = simple_strtoul(this_opt+6, NULL, 0); - dev_info(dev, "override upper: %d\n", inf->upper_margin); + dev_info(dev, "override upper: %u\n", inf->upper_margin); } else if (!strncmp(this_opt, "lower:", 6)) { inf->lower_margin = simple_strtoul(this_opt+6, NULL, 0); - dev_info(dev, "override lower: %d\n", inf->lower_margin); + dev_info(dev, "override lower: %u\n", inf->lower_margin); } else if (!strncmp(this_opt, "hsynclen:", 9)) { inf->hsync_len = simple_strtoul(this_opt+9, NULL, 0); - dev_info(dev, "override hsynclen: %d\n", inf->hsync_len); + dev_info(dev, "override hsynclen: %u\n", inf->hsync_len); } else if (!strncmp(this_opt, "vsynclen:", 9)) { inf->vsync_len = simple_strtoul(this_opt+9, NULL, 0); - dev_info(dev, "override vsynclen: %d\n", inf->vsync_len); + dev_info(dev, "override vsynclen: %u\n", inf->vsync_len); } else if (!strncmp(this_opt, "hsync:", 6)) { if ( simple_strtoul(this_opt+6, NULL, 0) == 0 ) { dev_info(dev, "override hsync: Active Low\n"); --- diff/drivers/video/tgafb.c 2004-05-19 22:12:21.000000000 +0100 +++ source/drivers/video/tgafb.c 2004-05-27 18:34:18.000000000 +0100 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include