diff --git a/[refs] b/[refs] index bff74753324c..c2d91d4a9d88 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 0ab598099c18affd73a21482274c00e8119236be +refs/heads/master: b38d06d8c48e8a866bf8f0ae5dabd9eea9c63f7c diff --git a/trunk/CREDITS b/trunk/CREDITS index 6829e91a88d4..80e241304b8e 100644 --- a/trunk/CREDITS +++ b/trunk/CREDITS @@ -380,7 +380,7 @@ S: FutureTV Labs Ltd S: Brunswick House, 61-69 Newmarket Rd, Cambridge CB5 8EG S: United Kingdom -N: Thomas Bogendörfer +N: Thomas Bogendrfer E: tsbogend@alpha.franken.de D: PCnet32 driver, SONIC driver, JAZZ_ESP driver D: newport abscon driver, g364 framebuffer driver @@ -400,7 +400,7 @@ W: http://math-www.uni-paderborn.de/~axel/ D: Configuration help text support D: Linux CD and Support Giveaway List -N: Erik Inge Bolsø +N: Erik Inge Bols E: knan@mo.himolde.no D: Misc kernel hacks @@ -428,7 +428,7 @@ D: Various fixes (mostly networking) S: Montreal, Quebec S: Canada -N: Zoltán Böszörményi +N: Zoltn Bszrmnyi E: zboszor@mail.externet.hu D: MTRR emulation with Cyrix style ARR registers, Athlon MTRR support @@ -1029,11 +1029,11 @@ D: Future Domain TMC-16x0 SCSI driver (author) D: APM driver (early port) D: DRM drivers (author of several) -N: János Farkas +N: Jnos Farkas E: chexum@shadow.banki.hu D: romfs, various (mostly networking) fixes P: 1024/F81FB2E1 41 B7 E4 E6 3E D4 A6 71 6D 9C F3 9F F2 BF DF 6E -S: Madarász Viktor utca 25 +S: Madarsz Viktor utca 25 S: 1131 Budapest S: Hungary @@ -1044,10 +1044,10 @@ D: UDF filesystem S: (ask for current address) S: USA -N: Jürgen Fischer -E: fischer@norbit.de +N: Jrgen Fischer +E: fischer@norbit.de (=?iso-8859-1?q?J=FCrgen?= Fischer) D: Author of Adaptec AHA-152x SCSI driver -S: Schulstraße 18 +S: Schulstrae 18 S: 26506 Norden S: Germany @@ -1113,7 +1113,7 @@ E: fuganti@netbank.com.br D: random kernel hacker, ZF MachZ Watchdog driver S: Conectiva S.A. S: R. Tocantins, 89 - Cristo Rei -S: 80050-430 - Curitiba - Paraná +S: 80050-430 - Curitiba - Paran S: Brazil N: Kumar Gala @@ -1258,12 +1258,12 @@ S: 44 St. Joseph Street, Suite 506 S: Toronto, Ontario, M4Y 2W4 S: Canada -N: Richard Günther +N: Richard Gnther E: rguenth@tat.physik.uni-tuebingen.de W: http://www.tat.physik.uni-tuebingen.de/~rguenth P: 2048/2E829319 2F 83 FC 93 E9 E4 19 E2 93 7A 32 42 45 37 23 57 D: binfmt_misc -S: 72074 Tübingen +S: 72074 Tbingen S: Germany N: Justin Guyett @@ -1287,7 +1287,7 @@ N: Bruno Haible E: haible@ma2s2.mathematik.uni-karlsruhe.de D: SysV FS, shm swapping, memory management fixes S: 17 rue Danton -S: F - 94270 Le Kremlin-Bicêtre +S: F - 94270 Le Kremlin-Bictre S: France N: Greg Hankins @@ -1701,7 +1701,7 @@ S: Czech Republic N: Jakob Kemi E: jakob.kemi@telia.com D: V4L W9966 Webcam driver -S: Forsbyvägen 33 +S: Forsbyvgen 33 S: 74143 Knivsta S: Sweden @@ -2065,7 +2065,7 @@ D: misc. kernel hacking and debugging S: Cambridge, MA 02139 S: USA -N: Martin von Löwis +N: Martin von Lwis E: loewis@informatik.hu-berlin.de D: script binary format D: NTFS driver @@ -2142,7 +2142,7 @@ S: PO BOX 220, HFX. CENTRAL S: Halifax, Nova Scotia S: Canada B3J 3C8 -N: Kai Mäkisara +N: Kai Mkisara E: Kai.Makisara@kolumbus.fi D: SCSI Tape Driver @@ -2785,10 +2785,10 @@ N: Juan Quintela E: quintela@fi.udc.es D: Memory Management hacking S: LFCIA -S: Departamento de Computación -S: Universidade da Coruña +S: Departamento de Computacin +S: Universidade da Corua S: E-15071 -S: A Coruña +S: A Corua S: Spain N: Augusto Cesar Radtke @@ -2939,7 +2939,7 @@ E: aris@cathedrallabs.org D: Support for EtherExpress 10 ISA (i82595) in eepro driver D: User level driver support for input S: R. Jose Serrato, 130 - Santa Candida -S: 82640-320 - Curitiba - Paraná +S: 82640-320 - Curitiba - Paran S: Brazil N: Alessandro Rubini @@ -3345,15 +3345,15 @@ P: 1024D/D0FE7AFB B24A 65C9 1D71 2AC2 DE87 CA26 189B 9946 D0FE 7AFB D: rcutorture maintainer D: lock annotations, finding and fixing lock bugs -N: Winfried Trümper +N: Winfried Trmper E: winni@xpilot.org W: http://www.shop.de/~winni/ D: German HOWTO, Crash-Kurs Linux (German, 100 comprehensive pages) D: CD-Writing HOWTO, various mini-HOWTOs D: One-week tutorials on Linux twice a year (free of charge) -D: Linux-Workshop Köln (aka LUG Cologne, Germany), Installfests +D: Linux-Workshop Kln (aka LUG Cologne, Germany), Installfests S: Tacitusstr. 6 -S: D-50968 Köln +S: D-50968 Kln N: Tsu-Sheng Tsao E: tsusheng@scf.usc.edu diff --git a/trunk/Documentation/ABI/removed/devfs b/trunk/Documentation/ABI/removed/devfs index 8ffd28bf6598..8195c4e0d0a1 100644 --- a/trunk/Documentation/ABI/removed/devfs +++ b/trunk/Documentation/ABI/removed/devfs @@ -6,7 +6,7 @@ Description: races, contains a naming policy within the kernel that is against the LSB, and can be replaced by using udev. The files fs/devfs/*, include/linux/devfs_fs*.h were removed, - along with the assorted devfs function calls throughout the + along with the the assorted devfs function calls throughout the kernel tree. Users: diff --git a/trunk/Documentation/DocBook/kernel-api.tmpl b/trunk/Documentation/DocBook/kernel-api.tmpl index 38f88b6ae405..a2b2b4d187c5 100644 --- a/trunk/Documentation/DocBook/kernel-api.tmpl +++ b/trunk/Documentation/DocBook/kernel-api.tmpl @@ -84,10 +84,6 @@ X!Iinclude/linux/kobject.h !Ekernel/rcupdate.c - Device Resource Management -!Edrivers/base/devres.c - - diff --git a/trunk/Documentation/MSI-HOWTO.txt b/trunk/Documentation/MSI-HOWTO.txt index 0d8240774fca..d389388c733e 100644 --- a/trunk/Documentation/MSI-HOWTO.txt +++ b/trunk/Documentation/MSI-HOWTO.txt @@ -480,8 +480,8 @@ The PCI stack provides 3 possible levels of MSI disabling: 6.1. Disabling MSI on a single device -Under some circumstances it might be required to disable MSI on a -single device. This may be achieved by either not calling pci_enable_msi() +Under some circumstances, it might be required to disable MSI on a +single device, It may be achived by either not calling pci_enable_msi() or all, or setting the pci_dev->no_msi flag before (most of the time in a quirk). @@ -492,7 +492,7 @@ being able to route MSI between busses. In this case, MSI have to be disabled on all devices behind this bridge. It is achieves by setting the PCI_BUS_FLAGS_NO_MSI flag in the pci_bus->bus_flags of the bridge subordinate bus. There is no need to set the same flag on bridges that -are below the broken bridge. When pci_enable_msi() is called to enable +are below the broken brigde. When pci_enable_msi() is called to enable MSI on a device, pci_msi_supported() takes care of checking the NO_MSI flag in all parent busses of the device. diff --git a/trunk/Documentation/SubmitChecklist b/trunk/Documentation/SubmitChecklist index 6491b2c45dd4..bd23dc0bc0c7 100644 --- a/trunk/Documentation/SubmitChecklist +++ b/trunk/Documentation/SubmitChecklist @@ -80,7 +80,3 @@ kernel patches. 23: Tested after it has been merged into the -mm patchset to make sure that it still works with all of the other queued patches and various changes in the VM, VFS, and other subsystems. - -24: Avoid whitespace damage such as indenting with spaces or whitespace - at the end of lines. You can test this by feeding the patch to - "git apply --check --whitespace=error-all" diff --git a/trunk/Documentation/SubmittingPatches b/trunk/Documentation/SubmittingPatches index a417b25fb1aa..b0d0043f7c46 100644 --- a/trunk/Documentation/SubmittingPatches +++ b/trunk/Documentation/SubmittingPatches @@ -363,8 +363,7 @@ area or subsystem of the kernel is being patched. The "summary phrase" in the email's Subject should concisely describe the patch which that email contains. The "summary phrase" should not be a filename. Do not use the same "summary -phrase" for every patch in a whole patch series (where a "patch -series" is an ordered sequence of multiple, related patches). +phrase" for every patch in a whole patch series. Bear in mind that the "summary phrase" of your email becomes a globally-unique identifier for that patch. It propagates diff --git a/trunk/Documentation/arm/Interrupts b/trunk/Documentation/arm/Interrupts index 0d3dbf1099bc..72c93de8cd4e 100644 --- a/trunk/Documentation/arm/Interrupts +++ b/trunk/Documentation/arm/Interrupts @@ -149,7 +149,7 @@ So, what's changed? 3. set_GPIO_IRQ_edge() is obsolete, and should be replaced by set_irq_type. -4. Direct access to SA1111 INTPOL is deprecated. Use set_irq_type instead. +4. Direct access to SA1111 INTPOL is depreciated. Use set_irq_type instead. 5. A handler is expected to perform any necessary acknowledgement of the parent IRQ via the correct chip specific function. For instance, if diff --git a/trunk/Documentation/arm/Samsung-S3C24XX/H1940.txt b/trunk/Documentation/arm/Samsung-S3C24XX/H1940.txt index f4a7b22c8664..d6b1de92b111 100644 --- a/trunk/Documentation/arm/Samsung-S3C24XX/H1940.txt +++ b/trunk/Documentation/arm/Samsung-S3C24XX/H1940.txt @@ -23,7 +23,7 @@ Support http://handhelds.org/moin/moin.cgi/HpIpaqH1940 - Herbert Pötzl pages: + Herbert Ptzl pages: http://vserver.13thfloor.at/H1940/ @@ -32,7 +32,7 @@ Maintainers ----------- This project is being maintained and developed by a variety - of people, including Ben Dooks, Arnaud Patard, and Herbert Pötzl. + of people, including Ben Dooks, Arnaud Patard, and Herbert Ptzl. Thanks to the many others who have also provided support. diff --git a/trunk/Documentation/auxdisplay/cfag12864b b/trunk/Documentation/auxdisplay/cfag12864b index b714183d4125..3572b98f45b8 100644 --- a/trunk/Documentation/auxdisplay/cfag12864b +++ b/trunk/Documentation/auxdisplay/cfag12864b @@ -78,9 +78,9 @@ Select (17)------------------------------(16) Data / Instruction Ground (18)---[GND] [+5v]---(19) LED + Ground (19)---[GND] Ground (20)---[GND] E A Values: -Ground (21)---[GND] [GND]---[P1]---(18) Vee - R = Resistor = 22 ohm -Ground (22)---[GND] | - P1 = Preset = 10 Kohm -Ground (23)---[GND] ---- S ------( 3) V0 - P2 = Preset = 1 Kohm +Ground (21)---[GND] [GND]---[P1]---(18) Vee R = Resistor = 22 ohm +Ground (22)---[GND] | P1 = Preset = 10 Kohm +Ground (23)---[GND] ---- S ------( 3) V0 P2 = Preset = 1 Kohm Ground (24)---[GND] | | Ground (25)---[GND] [GND]---[P2]---[R]---(20) LED - diff --git a/trunk/Documentation/binfmt_misc.txt b/trunk/Documentation/binfmt_misc.txt index f609ebf9c78f..d097f09ee15a 100644 --- a/trunk/Documentation/binfmt_misc.txt +++ b/trunk/Documentation/binfmt_misc.txt @@ -113,4 +113,4 @@ cause unexpected behaviour and can be a security hazard. There is a web page about binfmt_misc at http://www.tat.physik.uni-tuebingen.de/~rguenth/linux/binfmt_misc.html -Richard Günther +Richard Gnther diff --git a/trunk/Documentation/block/ioprio.txt b/trunk/Documentation/block/ioprio.txt index 1b930ef5a079..96ccf681075e 100644 --- a/trunk/Documentation/block/ioprio.txt +++ b/trunk/Documentation/block/ioprio.txt @@ -6,10 +6,10 @@ Intro ----- With the introduction of cfq v3 (aka cfq-ts or time sliced cfq), basic io -priorities are supported for reads on files. This enables users to io nice -processes or process groups, similar to what has been possible with cpu -scheduling for ages. This document mainly details the current possibilities -with cfq; other io schedulers do not support io priorities thus far. +priorities is supported for reads on files. This enables users to io nice +processes or process groups, similar to what has been possible to cpu +scheduling for ages. This document mainly details the current possibilites +with cfq, other io schedulers do not support io priorities so far. Scheduling classes ------------------ diff --git a/trunk/Documentation/cpu-freq/cpufreq-stats.txt b/trunk/Documentation/cpu-freq/cpufreq-stats.txt index fc647492e940..53d62c1e1c94 100644 --- a/trunk/Documentation/cpu-freq/cpufreq-stats.txt +++ b/trunk/Documentation/cpu-freq/cpufreq-stats.txt @@ -17,7 +17,7 @@ Contents 1. Introduction -cpufreq-stats is a driver that provides CPU frequency statistics for each CPU. +cpufreq-stats is a driver that provices CPU frequency statistics for each CPU. These statistics are provided in /sysfs as a bunch of read_only interfaces. This interface (when configured) will appear in a separate directory under cpufreq in /sysfs (/devices/system/cpu/cpuX/cpufreq/stats/) for each CPU. diff --git a/trunk/Documentation/cpu-hotplug.txt b/trunk/Documentation/cpu-hotplug.txt index b6d24c22274b..cc60d29b954c 100644 --- a/trunk/Documentation/cpu-hotplug.txt +++ b/trunk/Documentation/cpu-hotplug.txt @@ -217,17 +217,14 @@ Q: What happens when a CPU is being logically offlined? A: The following happen, listed in no particular order :-) - A notification is sent to in-kernel registered modules by sending an event - CPU_DOWN_PREPARE or CPU_DOWN_PREPARE_FROZEN, depending on whether or not the - CPU is being offlined while tasks are frozen due to a suspend operation in - progress + CPU_DOWN_PREPARE - All process is migrated away from this outgoing CPU to a new CPU - All interrupts targeted to this CPU is migrated to a new CPU - timers/bottom half/task lets are also migrated to a new CPU - Once all services are migrated, kernel calls an arch specific routine __cpu_disable() to perform arch specific cleanup. - Once this is successful, an event for successful cleanup is sent by an event - CPU_DEAD (or CPU_DEAD_FROZEN if tasks are frozen due to a suspend while the - CPU is being offlined). + CPU_DEAD. "It is expected that each service cleans up when the CPU_DOWN_PREPARE notifier is called, when CPU_DEAD is called its expected there is nothing @@ -245,11 +242,9 @@ A: This is what you would need in your kernel code to receive notifications. switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: foobar_online_action(cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: foobar_dead_action(cpu); break; } diff --git a/trunk/Documentation/crypto/api-intro.txt b/trunk/Documentation/crypto/api-intro.txt index a2ac6d294793..9b84b805ab75 100644 --- a/trunk/Documentation/crypto/api-intro.txt +++ b/trunk/Documentation/crypto/api-intro.txt @@ -177,7 +177,7 @@ Portions of this API were derived from the following projects: and; Nettle (http://www.lysator.liu.se/~nisse/nettle/) - Niels Möller + Niels Mller Original developers of the crypto algorithms: @@ -200,8 +200,8 @@ SHA1 algorithm contributors: DES algorithm contributors: Raimar Falke - Gisle Sælensminde - Niels Möller + Gisle Slensminde + Niels Mller Blowfish algorithm contributors: Herbert Valerio Riedel diff --git a/trunk/Documentation/device-mapper/delay.txt b/trunk/Documentation/device-mapper/delay.txt deleted file mode 100644 index 15adc55359e5..000000000000 --- a/trunk/Documentation/device-mapper/delay.txt +++ /dev/null @@ -1,26 +0,0 @@ -dm-delay -======== - -Device-Mapper's "delay" target delays reads and/or writes -and maps them to different devices. - -Parameters: - [ ] - -With separate write parameters, the first set is only used for reads. -Delays are specified in milliseconds. - -Example scripts -=============== -[[ -#!/bin/sh -# Create device delaying rw operation for 500ms -echo "0 `blockdev --getsize $1` delay $1 0 500" | dmsetup create delayed -]] - -[[ -#!/bin/sh -# Create device delaying only write operation for 500ms and -# splitting reads and writes to different devices $1 $2 -echo "0 `blockdev --getsize $1` delay $1 0 0 $2 0 500" | dmsetup create delayed -]] diff --git a/trunk/Documentation/driver-model/platform.txt b/trunk/Documentation/driver-model/platform.txt index 19c4a6e13676..f7c9262b2dc8 100644 --- a/trunk/Documentation/driver-model/platform.txt +++ b/trunk/Documentation/driver-model/platform.txt @@ -16,7 +16,7 @@ host bridges to peripheral buses, and most controllers integrated into system-on-chip platforms. What they usually have in common is direct addressing from a CPU bus. Rarely, a platform_device will be connected through a segment of some other kind of bus; but its -registers will still be directly addressable. +registers will still be directly addressible. Platform devices are given a name, used in driver binding, and a list of resources such as addresses and IRQs. @@ -125,7 +125,7 @@ three different ways to find such a match: usually register later during booting, or by module loading. - Registering a driver using platform_driver_probe() works just like - using platform_driver_register(), except that the driver won't + using platform_driver_register(), except that the the driver won't be probed later if another device registers. (Which is OK, since this interface is only for use with non-hotpluggable devices.) diff --git a/trunk/Documentation/dvb/README.dvb-usb b/trunk/Documentation/dvb/README.dvb-usb index bf2a9cdfe7bb..46b78b7331c2 100644 --- a/trunk/Documentation/dvb/README.dvb-usb +++ b/trunk/Documentation/dvb/README.dvb-usb @@ -228,5 +228,5 @@ Patches, comments and suggestions are very very welcome. Ulf Hermenau for helping me out with traditional chinese. - André Smoktun and Christian Frömmel for supporting me with + Andr Smoktun and Christian Frmmel for supporting me with hardware and listening to my problems very patiently. diff --git a/trunk/Documentation/dvb/contributors.txt b/trunk/Documentation/dvb/contributors.txt index 4865addebe1c..4c33cced5f65 100644 --- a/trunk/Documentation/dvb/contributors.txt +++ b/trunk/Documentation/dvb/contributors.txt @@ -66,7 +66,7 @@ Michael Dreher Andreas 'randy' Weinberger for the support of the Fujitsu-Siemens Activy budget DVB-S -Kenneth Aafløy +Kenneth Aafly for adding support for Typhoon DVB-S budget card Ernst Peinlich diff --git a/trunk/Documentation/fb/arkfb.txt b/trunk/Documentation/fb/arkfb.txt deleted file mode 100644 index e8487a9d6a05..000000000000 --- a/trunk/Documentation/fb/arkfb.txt +++ /dev/null @@ -1,68 +0,0 @@ - - arkfb - fbdev driver for ARK Logic chips - ======================================== - - -Supported Hardware -================== - - ARK 2000PV chip - ICS 5342 ramdac - - - only BIOS initialized VGA devices supported - - probably not working on big endian - - -Supported Features -================== - - * 4 bpp pseudocolor modes (with 18bit palette, two variants) - * 8 bpp pseudocolor mode (with 18bit palette) - * 16 bpp truecolor modes (RGB 555 and RGB 565) - * 24 bpp truecolor mode (RGB 888) - * 32 bpp truecolor mode (RGB 888) - * text mode (activated by bpp = 0) - * doublescan mode variant (not available in text mode) - * panning in both directions - * suspend/resume support - -Text mode is supported even in higher resolutions, but there is limitation to -lower pixclocks (i got maximum about 70 MHz, it is dependent on specific -hardware). This limitation is not enforced by driver. Text mode supports 8bit -wide fonts only (hardware limitation) and 16bit tall fonts (driver -limitation). Unfortunately character attributes (like color) in text mode are -broken for unknown reason, so its usefulness is limited. - -There are two 4 bpp modes. First mode (selected if nonstd == 0) is mode with -packed pixels, high nibble first. Second mode (selected if nonstd == 1) is mode -with interleaved planes (1 byte interleave), MSB first. Both modes support -8bit wide fonts only (driver limitation). - -Suspend/resume works on systems that initialize video card during resume and -if device is active (for example used by fbcon). - - -Missing Features -================ -(alias TODO list) - - * secondary (not initialized by BIOS) device support - * big endian support - * DPMS support - * MMIO support - * interlaced mode variant - * support for fontwidths != 8 in 4 bpp modes - * support for fontheight != 16 in text mode - * hardware cursor - * vsync synchronization - * feature connector support - * acceleration support (8514-like 2D) - - -Known bugs -========== - - * character attributes (and cursor) in text mode are broken - --- -Ondrej Zajicek diff --git a/trunk/Documentation/fb/aty128fb.txt b/trunk/Documentation/fb/aty128fb.txt index b605204fcfe1..069262fb619d 100644 --- a/trunk/Documentation/fb/aty128fb.txt +++ b/trunk/Documentation/fb/aty128fb.txt @@ -54,8 +54,8 @@ Accepted options: noaccel - do not use acceleration engine. It is default. accel - use acceleration engine. Not finished. -vmode:x - chooses PowerMacintosh video mode . Deprecated. -cmode:x - chooses PowerMacintosh colour mode . Deprecated. +vmode:x - chooses PowerMacintosh video mode . Depreciated. +cmode:x - chooses PowerMacintosh colour mode . Depreciated. - selects startup videomode. See modedb.txt for detailed explanation. Default is 640x480x8bpp. diff --git a/trunk/Documentation/fb/framebuffer.txt b/trunk/Documentation/fb/framebuffer.txt index b3e3a0356839..610e7801207b 100644 --- a/trunk/Documentation/fb/framebuffer.txt +++ b/trunk/Documentation/fb/framebuffer.txt @@ -215,11 +215,11 @@ vertical retrace time is the sum of the upper margin, the lower margin and the vsync length. +----------+---------------------------------------------+----------+-------+ - | | ↑ | | | + | | ^ | | | | | |upper_margin | | | - | | ↓ | | | + | | | | | +----------###############################################----------+-------+ - | # ↑ # | | + | # ^ # | | | # | # | | | # | # | | | # | # | | @@ -238,15 +238,15 @@ vsync length. | # | # | | | # | # | | | # | # | | - | # ↓ # | | + | # # | | +----------###############################################----------+-------+ - | | ↑ | | | + | | ^ | | | | | |lower_margin | | | - | | ↓ | | | + | | | | | +----------+---------------------------------------------+----------+-------+ - | | ↑ | | | + | | ^ | | | | | |vsync_len | | | - | | ↓ | | | + | | | | | +----------+---------------------------------------------+----------+-------+ The frame buffer device expects all horizontal timings in number of dotclocks diff --git a/trunk/Documentation/fb/imacfb.txt b/trunk/Documentation/fb/imacfb.txt index 316ec9bb7deb..759028545a7e 100644 --- a/trunk/Documentation/fb/imacfb.txt +++ b/trunk/Documentation/fb/imacfb.txt @@ -17,7 +17,7 @@ How to use it? ============== Imacfb does not have any kind of autodetection of your machine. -You have to add the following kernel parameters in your elilo.conf: +You have to add the fillowing kernel parameters in your elilo.conf: Macbook : video=imacfb:macbook MacMini : diff --git a/trunk/Documentation/fb/sstfb.txt b/trunk/Documentation/fb/sstfb.txt index 550ca775a4cb..df27f5bf15db 100644 --- a/trunk/Documentation/fb/sstfb.txt +++ b/trunk/Documentation/fb/sstfb.txt @@ -2,9 +2,9 @@ Introduction This is a frame buffer device driver for 3dfx' Voodoo Graphics - (aka voodoo 1, aka sst1) and Voodoo² (aka Voodoo 2, aka CVG) based + (aka voodoo 1, aka sst1) and Voodoo (aka Voodoo 2, aka CVG) based video boards. It's highly experimental code, but is guaranteed to work - on my computer, with my "Maxi Gamer 3D" and "Maxi Gamer 3d²" boards, + on my computer, with my "Maxi Gamer 3D" and "Maxi Gamer 3d" boards, and with me "between chair and keyboard". Some people tested other combinations and it seems that it works. The main page is located at , and if diff --git a/trunk/Documentation/fb/vt8623fb.txt b/trunk/Documentation/fb/vt8623fb.txt deleted file mode 100644 index f654576c56b7..000000000000 --- a/trunk/Documentation/fb/vt8623fb.txt +++ /dev/null @@ -1,64 +0,0 @@ - - vt8623fb - fbdev driver for graphics core in VIA VT8623 chipset - =============================================================== - - -Supported Hardware -================== - - VIA VT8623 [CLE266] chipset and its graphics core - (known as CastleRock or Unichrome) - -I tested vt8623fb on VIA EPIA ML-6000 - - -Supported Features -================== - - * 4 bpp pseudocolor modes (with 18bit palette, two variants) - * 8 bpp pseudocolor mode (with 18bit palette) - * 16 bpp truecolor mode (RGB 565) - * 32 bpp truecolor mode (RGB 888) - * text mode (activated by bpp = 0) - * doublescan mode variant (not available in text mode) - * panning in both directions - * suspend/resume support - * DPMS support - -Text mode is supported even in higher resolutions, but there is limitation to -lower pixclocks (maximum about 100 MHz). This limitation is not enforced by -driver. Text mode supports 8bit wide fonts only (hardware limitation) and -16bit tall fonts (driver limitation). - -There are two 4 bpp modes. First mode (selected if nonstd == 0) is mode with -packed pixels, high nibble first. Second mode (selected if nonstd == 1) is mode -with interleaved planes (1 byte interleave), MSB first. Both modes support -8bit wide fonts only (driver limitation). - -Suspend/resume works on systems that initialize video card during resume and -if device is active (for example used by fbcon). - - -Missing Features -================ -(alias TODO list) - - * secondary (not initialized by BIOS) device support - * MMIO support - * interlaced mode variant - * support for fontwidths != 8 in 4 bpp modes - * support for fontheight != 16 in text mode - * hardware cursor - * video overlay support - * vsync synchronization - * acceleration support (8514-like 2D, busmaster transfers) - - -Known bugs -========== - - * cursor disable in text mode doesn't work - - --- -Ondrej Zajicek diff --git a/trunk/Documentation/filesystems/Locking b/trunk/Documentation/filesystems/Locking index d866551be037..59c14159cc47 100644 --- a/trunk/Documentation/filesystems/Locking +++ b/trunk/Documentation/filesystems/Locking @@ -54,7 +54,7 @@ ata *); locking rules: all may block, none have BKL - i_mutex(inode) + i_sem(inode) lookup: yes create: yes link: yes (both) @@ -74,7 +74,7 @@ setxattr: yes getxattr: no listxattr: no removexattr: yes - Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on + Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_sem on victim. cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem. ->truncate() is never called directly - it's a callback, not a @@ -461,7 +461,7 @@ doesn't take the BKL. ->read on directories probably must go away - we should just enforce -EISDIR in sys_read() and friends. -->fsync() has i_mutex on inode. +->fsync() has i_sem on inode. --------------------------- dquot_operations ------------------------------- prototypes: diff --git a/trunk/Documentation/filesystems/hpfs.txt b/trunk/Documentation/filesystems/hpfs.txt index fa45c3baed98..38aba03efc5e 100644 --- a/trunk/Documentation/filesystems/hpfs.txt +++ b/trunk/Documentation/filesystems/hpfs.txt @@ -290,7 +290,7 @@ History 2.07 More fixes for Warp Server. Now it really works 2.08 Creating new files is not so slow on large disks An attempt to sync deleted file does not generate filesystem error -2.09 Fixed error on extremely fragmented files +2.09 Fixed error on extremly fragmented files vim: set textwidth=80: diff --git a/trunk/Documentation/filesystems/ntfs.txt b/trunk/Documentation/filesystems/ntfs.txt index 8ee10ec88293..81779068b09b 100644 --- a/trunk/Documentation/filesystems/ntfs.txt +++ b/trunk/Documentation/filesystems/ntfs.txt @@ -349,7 +349,7 @@ end of the line. Note the "Should sync?" parameter "nosync" means that the two mirrors are already in sync which will be the case on a clean shutdown of Windows. If the mirrors are not clean, you can specify the "sync" option instead of "nosync" -and the Device-Mapper driver will then copy the entirety of the "Source Device" +and the Device-Mapper driver will then copy the entirey of the "Source Device" to the "Target Device" or if you specified multipled target devices to all of them. diff --git a/trunk/Documentation/filesystems/proc.txt b/trunk/Documentation/filesystems/proc.txt index 8756a07f4dc3..4f3e84c520a5 100644 --- a/trunk/Documentation/filesystems/proc.txt +++ b/trunk/Documentation/filesystems/proc.txt @@ -229,7 +229,7 @@ Table 1-3: Kernel info in /proc mounts Mounted filesystems net Networking info (see text) partitions Table of partitions known to the system - pci Deprecated info of PCI bus (new way -> /proc/bus/pci/, + pci Depreciated info of PCI bus (new way -> /proc/bus/pci/, decoupled by lspci (2.4) rtc Real time clock scsi SCSI info (see text) diff --git a/trunk/Documentation/filesystems/relay.txt b/trunk/Documentation/filesystems/relay.txt index 18d23f9a18c7..7fbb6ffe5769 100644 --- a/trunk/Documentation/filesystems/relay.txt +++ b/trunk/Documentation/filesystems/relay.txt @@ -351,7 +351,7 @@ If the current buffer is full, i.e. all sub-buffers remain unconsumed, the callback returns 0 to indicate that the buffer switch should not occur yet, i.e. until the consumer has had a chance to read the current set of ready sub-buffers. For the relay_buf_full() function -to make sense, the consumer is responsible for notifying the relay +to make sense, the consumer is reponsible for notifying the relay interface when sub-buffers have been consumed via relay_subbufs_consumed(). Any subsequent attempts to write into the buffer will again invoke the subbuf_start() callback with the same diff --git a/trunk/Documentation/filesystems/xip.txt b/trunk/Documentation/filesystems/xip.txt index 3cc4010521a0..6c0cef10eb4d 100644 --- a/trunk/Documentation/filesystems/xip.txt +++ b/trunk/Documentation/filesystems/xip.txt @@ -19,7 +19,7 @@ completely. With execute-in-place, read&write type operations are performed directly from/to the memory backed storage device. For file mappings, the storage device itself is mapped directly into userspace. -This implementation was initially written for shared memory segments between +This implementation was initialy written for shared memory segments between different virtual machines on s390 hardware to allow multiple machines to share the same binaries and libraries. diff --git a/trunk/Documentation/fujitsu/frv/gdbstub.txt b/trunk/Documentation/fujitsu/frv/gdbstub.txt index b92bfd902a4e..9304fb36ae8a 100644 --- a/trunk/Documentation/fujitsu/frv/gdbstub.txt +++ b/trunk/Documentation/fujitsu/frv/gdbstub.txt @@ -126,5 +126,5 @@ GDB stub and the debugger: Furthermore, the GDB stub will intercept a number of exceptions automatically if they are caused by kernel execution. It will also intercept BUG() macro -invocation. +invokation. diff --git a/trunk/Documentation/hwmon/adm1026 b/trunk/Documentation/hwmon/adm1026 index f4327db2307e..473c689d7924 100644 --- a/trunk/Documentation/hwmon/adm1026 +++ b/trunk/Documentation/hwmon/adm1026 @@ -80,7 +80,7 @@ temperature sensor inputs. Both the PWM output and the DAC output can be used to control fan speed. Usually only one of these two outputs will be used. Write the minimum PWM or DAC value to the appropriate control register. Then set the low temperature limit in the tmin values for each -temperature sensor. The range of control is fixed at 20 °C, and the +temperature sensor. The range of control is fixed at 20 C, and the largest difference between current and tmin of the temperature sensors sets the control output. See the datasheet for several example circuits for controlling fan speed with the PWM and DAC outputs. The fan speed sensors diff --git a/trunk/Documentation/hwmon/gl518sm b/trunk/Documentation/hwmon/gl518sm index 229f8b789185..ce0881883bca 100644 --- a/trunk/Documentation/hwmon/gl518sm +++ b/trunk/Documentation/hwmon/gl518sm @@ -13,7 +13,7 @@ Supported chips: Authors: Frodo Looijaard , - Kyösti Mälkki + Kysti Mlkki Hong-Gunn Chew Jean Delvare diff --git a/trunk/Documentation/hwmon/lm83 b/trunk/Documentation/hwmon/lm83 index a04d1fe9269c..f7aad1489cb0 100644 --- a/trunk/Documentation/hwmon/lm83 +++ b/trunk/Documentation/hwmon/lm83 @@ -45,7 +45,7 @@ Unconfirmed motherboards: The LM82 is confirmed to have been found on most AMD Geode reference designs and test platforms. -The driver has been successfully tested by Magnus Forsström, who I'd +The driver has been successfully tested by Magnus Forsstrm, who I'd like to thank here. More testers will be of course welcome. The fact that the LM83 is only scarcely used can be easily explained. diff --git a/trunk/Documentation/hwmon/sis5595 b/trunk/Documentation/hwmon/sis5595 index 4f8877a34f37..b7ae36b8cdf5 100644 --- a/trunk/Documentation/hwmon/sis5595 +++ b/trunk/Documentation/hwmon/sis5595 @@ -8,7 +8,7 @@ Supported chips: Datasheet: Publicly available at the Silicon Integrated Systems Corp. site. Authors: - Kyösti Mälkki , + Kysti Mlkki , Mark D. Studebaker , Aurelien Jarno 2.6 port diff --git a/trunk/Documentation/hwmon/via686a b/trunk/Documentation/hwmon/via686a index d651b25f7519..a936fb3824b2 100644 --- a/trunk/Documentation/hwmon/via686a +++ b/trunk/Documentation/hwmon/via686a @@ -8,7 +8,7 @@ Supported chips: Datasheet: On request through web form (http://www.via.com.tw/en/support/datasheets/) Authors: - Kyösti Mälkki , + Kysti Mlkki , Mark D. Studebaker Bob Dougherty (Some conversion-factor data were contributed by diff --git a/trunk/Documentation/hwmon/w83792d b/trunk/Documentation/hwmon/w83792d index 14a668ed8aaa..8171c285bb55 100644 --- a/trunk/Documentation/hwmon/w83792d +++ b/trunk/Documentation/hwmon/w83792d @@ -107,7 +107,7 @@ Known problems: by CR[0x49h]. - The function of vid and vrm has not been finished, because I'm NOT very familiar with them. Adding support is welcome. -  - The function of chassis open detection needs more tests. + - The function of chassis open detection needs more tests. - If you have ASUS server board and chip was not found: Then you will need to upgrade to latest (or beta) BIOS. If it does not help please contact us. diff --git a/trunk/Documentation/i2c/busses/i2c-i810 b/trunk/Documentation/i2c/busses/i2c-i810 index 778210ee1583..83c3b9743c3c 100644 --- a/trunk/Documentation/i2c/busses/i2c-i810 +++ b/trunk/Documentation/i2c/busses/i2c-i810 @@ -7,7 +7,7 @@ Supported adapters: Authors: Frodo Looijaard , Philip Edelbrock , - Kyösti Mälkki , + Kysti Mlkki , Ralph Metzler , Mark D. Studebaker diff --git a/trunk/Documentation/i2c/busses/i2c-sis96x b/trunk/Documentation/i2c/busses/i2c-sis96x index 266481fd26e2..08d7b2dac69a 100644 --- a/trunk/Documentation/i2c/busses/i2c-sis96x +++ b/trunk/Documentation/i2c/busses/i2c-sis96x @@ -60,7 +60,7 @@ Mark D. Studebaker - design hints and bug fixes Alexander Maylsh - ditto, plus an important datasheet... almost the one I really wanted -Hans-Günter Lütke Uphues +Hans-Gnter Ltke Uphues - patch for SiS735 Robert Zwerus - testing for SiS645DX diff --git a/trunk/Documentation/i2c/busses/i2c-via b/trunk/Documentation/i2c/busses/i2c-via index 343870661ac3..55edfe1a640b 100644 --- a/trunk/Documentation/i2c/busses/i2c-via +++ b/trunk/Documentation/i2c/busses/i2c-via @@ -4,7 +4,7 @@ Supported adapters: * VIA Technologies, InC. VT82C586B Datasheet: Publicly available at the VIA website -Author: Kyösti Mälkki +Author: Kysti Mlkki Description ----------- diff --git a/trunk/Documentation/i2c/busses/i2c-viapro b/trunk/Documentation/i2c/busses/i2c-viapro index 06b4be3ef6d8..775f489e86f6 100644 --- a/trunk/Documentation/i2c/busses/i2c-viapro +++ b/trunk/Documentation/i2c/busses/i2c-viapro @@ -17,7 +17,7 @@ Supported adapters: Datasheet: available on request and under NDA from VIA Authors: - Kyösti Mälkki , + Kysti Mlkki , Mark D. Studebaker , Jean Delvare diff --git a/trunk/Documentation/i2c/i2c-protocol b/trunk/Documentation/i2c/i2c-protocol index 579b92d5f3a3..b4022c914210 100644 --- a/trunk/Documentation/i2c/i2c-protocol +++ b/trunk/Documentation/i2c/i2c-protocol @@ -68,7 +68,7 @@ We have found some I2C devices that needs the following modifications: Flags I2C_M_IGNORE_NAK Normally message is interrupted immediately if there is [NA] from the - client. Setting this flag treats any [NA] as [A], and all of + client. Setting this flag treats any [NA] as[A], and all of message is sent. These messages may still fail to SCL lo->hi timeout. diff --git a/trunk/Documentation/i2o/README b/trunk/Documentation/i2o/README index 0ebf58c73f54..9aa6ddb446eb 100644 --- a/trunk/Documentation/i2o/README +++ b/trunk/Documentation/i2o/README @@ -30,13 +30,13 @@ Juha Sievanen, University of Helsinki Finland Bug fixes Core code extensions -Auvo Häkkinen, University of Helsinki Finland +Auvo Hkkinen, University of Helsinki Finland LAN OSM code /Proc interface to LAN class Bug fixes Core code extensions -Taneli Vähäkangas, University of Helsinki Finland +Taneli Vhkangas, University of Helsinki Finland Fixes to i2o_config CREDITS diff --git a/trunk/Documentation/input/atarikbd.txt b/trunk/Documentation/input/atarikbd.txt index ab050621e20f..668f4d0d97d6 100644 --- a/trunk/Documentation/input/atarikbd.txt +++ b/trunk/Documentation/input/atarikbd.txt @@ -179,9 +179,9 @@ reporting mode for joystick 1, with both buttons being logically assigned to the mouse. After any joystick command, the ikbd assumes that joysticks are connected to both Joystick0 and Joystick1. Any mouse command (except MOUSE DISABLE) then causes port 0 to again be scanned as if it were a mouse, and -both buttons are logically connected to it. If a mouse disable command is +both buttons are logically connected to it. If a mouse diable command is received while port 0 is presumed to be a mouse, the button is logically -assigned to Joystick1 (until the mouse is reenabled by another mouse command). +assigned to Joystick1 ( until the mouse is reenabled by another mouse command). 9. ikbd Command Set diff --git a/trunk/Documentation/input/xpad.txt b/trunk/Documentation/input/xpad.txt index aae0d404c566..5427bdf225ed 100644 --- a/trunk/Documentation/input/xpad.txt +++ b/trunk/Documentation/input/xpad.txt @@ -65,15 +65,15 @@ of buttons, see section 0.3 - Unknown Controllers I've tested this with Stepmania, and it works quite well. -0.3 Unknown Controllers +0.3 Unkown Controllers ---------------------- -If you have an unknown xbox controller, it should work just fine with +If you have an unkown xbox controller, it should work just fine with the default settings. HOWEVER if you have an unknown dance pad not listed below, it will not work UNLESS you set "dpad_to_buttons" to 1 in the module configuration. -PLEASE, if you have an unknown controller, email Dom with +PLEASE if you have an unkown controller, email Dom with a dump from /proc/bus/usb and a description of the pad (manufacturer, country, whether it is a dance pad or normal controller) so that we can add your pad to the list of supported devices, ensuring that it will work out of the diff --git a/trunk/Documentation/isdn/CREDITS b/trunk/Documentation/isdn/CREDITS index 7c17c837064f..e1b3023efaa8 100644 --- a/trunk/Documentation/isdn/CREDITS +++ b/trunk/Documentation/isdn/CREDITS @@ -2,7 +2,7 @@ I want to thank all who contributed to this project and especially to: (in alphabetical order) -Thomas Bogendörfer (tsbogend@bigbug.franken.de) +Thomas Bogendrfer (tsbogend@bigbug.franken.de) Tester, lots of bugfixes and hints. Alan Cox (alan@redhat.com) @@ -11,7 +11,7 @@ Alan Cox (alan@redhat.com) Henner Eisen (eis@baty.hanse.de) For X.25 implementation. -Volker Götz (volker@oops.franken.de) +Volker Gtz (volker@oops.franken.de) For contribution of man-pages, the imontty-tool and a perfect maintaining of the mailing-list at hub-wue. diff --git a/trunk/Documentation/isdn/README b/trunk/Documentation/isdn/README index 6783437f21c2..761595243931 100644 --- a/trunk/Documentation/isdn/README +++ b/trunk/Documentation/isdn/README @@ -402,7 +402,7 @@ README for the ISDN-subsystem the script tools/tcltk/isdnmon. You can add actions for line-status changes. See the comments at the beginning of the script for how to do that. There are other tty-based tools in the tools-subdirectory - contributed by Michael Knigge (imon), Volker Götz (imontty) and + contributed by Michael Knigge (imon), Volker Gtz (imontty) and Andreas Kool (isdnmon). l) For initial testing, you can set the verbose-level to 2 (default: 0). diff --git a/trunk/Documentation/isdn/README.icn b/trunk/Documentation/isdn/README.icn index 13f833d4e910..a5f55eadb3ca 100644 --- a/trunk/Documentation/isdn/README.icn +++ b/trunk/Documentation/isdn/README.icn @@ -3,8 +3,8 @@ $Id: README.icn,v 1.7 2000/08/06 09:22:51 armin Exp $ You can get the ICN-ISDN-card from: Thinking Objects Software GmbH -Versbacher Röthe 159 -97078 Würzburg +Versbacher Rthe 159 +97078 Wrzburg Tel: +49 931 2877950 Fax: +49 931 2877951 diff --git a/trunk/Documentation/java.txt b/trunk/Documentation/java.txt index 3cce3fbb6644..c768dc63b34e 100644 --- a/trunk/Documentation/java.txt +++ b/trunk/Documentation/java.txt @@ -390,7 +390,7 @@ the execution bit, then just do originally by Brian A. Lantz, brian@lantz.com -heavily edited for binfmt_misc by Richard Günther +heavily edited for binfmt_misc by Richard Gnther new scripts by Colin J. Watson added executable Jar file support by Kurt Huwig diff --git a/trunk/Documentation/kernel-docs.txt b/trunk/Documentation/kernel-docs.txt index d9e3b199929b..c68dafeda7a7 100644 --- a/trunk/Documentation/kernel-docs.txt +++ b/trunk/Documentation/kernel-docs.txt @@ -236,7 +236,7 @@ * Title: "Design and Implementation of the Second Extended Filesystem" - Author: Rémy Card, Theodore Ts'o, Stephen Tweedie. + Author: Rmy Card, Theodore Ts'o, Stephen Tweedie. URL: http://web.mit.edu/tytso/www/linux/ext2intro.html Keywords: ext2, linux fs history, inode, directory, link, devices, VFS, physical structure, performance, benchmarks, ext2fs library, diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 09220a1e22d9..6b8ad06846c4 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -754,6 +754,14 @@ and is between 256 and 4096 characters. It is defined in the file inport.irq= [HW] Inport (ATI XL and Microsoft) busmouse driver Format: + combined_mode= [HW] control which driver uses IDE ports in combined + mode: legacy IDE driver, libata, or both + (in the libata case, libata.atapi_enabled=1 may be + useful as well). Note that using the ide or libata + options may affect your device naming (e.g. by + changing hdc to sdb). + Format: combined (default), ide, or libata + inttest= [IA64] io7= [HW] IO7 for Marvel based alpha systems diff --git a/trunk/Documentation/m68k/README.buddha b/trunk/Documentation/m68k/README.buddha index 3ea9827ba3c7..ef484a719bb9 100644 --- a/trunk/Documentation/m68k/README.buddha +++ b/trunk/Documentation/m68k/README.buddha @@ -204,7 +204,7 @@ always shows a "no IRQ here" on the Buddha, and accesses to the third IDE port are going into data's Nirwana on the Buddha. - Jens Schönfeld february 19th, 1997 + Jens Schnfeld february 19th, 1997 updated may 27th, 1997 eMail: sysop@nostlgic.tng.oche.de diff --git a/trunk/Documentation/magic-number.txt b/trunk/Documentation/magic-number.txt index bd450e797558..0e740c812d12 100644 --- a/trunk/Documentation/magic-number.txt +++ b/trunk/Documentation/magic-number.txt @@ -129,7 +129,7 @@ SAVEKMSG_MAGIC1 0x53415645 savekmsg arch/*/amiga/config.c GDA_MAGIC 0x58464552 gda include/asm-mips64/sn/gda.h RED_MAGIC1 0x5a2cf071 (any) mm/slab.c STL_PORTMAGIC 0x5a7182c9 stlport include/linux/stallion.h -EEPROM_MAGIC_VALUE 0x5ab478d2 lanai_dev drivers/atm/lanai.c +EEPROM_MAGIC_VALUE 0X5ab478d2 lanai_dev drivers/atm/lanai.c HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state include/linux/hdlcdrv.h EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h PCXX_MAGIC 0x5c6df104 channel drivers/char/pcxx.h diff --git a/trunk/Documentation/md.txt b/trunk/Documentation/md.txt index 5818628207b5..2202f5dc8ac2 100644 --- a/trunk/Documentation/md.txt +++ b/trunk/Documentation/md.txt @@ -178,21 +178,6 @@ All md devices contain: The size should be at least PAGE_SIZE (4k) and should be a power of 2. This can only be set while assembling an array - layout - The "layout" for the array for the particular level. This is - simply a number that is interpretted differently by different - levels. It can be written while assembling an array. - - reshape_position - This is either "none" or a sector number within the devices of - the array where "reshape" is up to. If this is set, the three - attributes mentioned above (raid_disks, chunk_size, layout) can - potentially have 2 values, an old and a new value. If these - values differ, reading the attribute returns - new (old) - and writing will effect the 'new' value, leaving the 'old' - unchanged. - component_size For arrays with data redundancy (i.e. not raid0, linear, faulty, multipath), all components must be the same size - or at least @@ -208,6 +193,11 @@ All md devices contain: 1.2 (newer format in varying locations) or "none" indicating that the kernel isn't managing metadata at all. + layout + The "layout" for the array for the particular level. This is + simply a number that is interpretted differently by different + levels. It can be written while assembling an array. + resync_start The point at which resync should start. If no resync is needed, this will be a very large number. At array creation it will @@ -269,6 +259,29 @@ All md devices contain: like active, but no writes have been seen for a while (safe_mode_delay). + sync_speed_min + sync_speed_max + This are similar to /proc/sys/dev/raid/speed_limit_{min,max} + however they only apply to the particular array. + If no value has been written to these, of if the word 'system' + is written, then the system-wide value is used. If a value, + in kibibytes-per-second is written, then it is used. + When the files are read, they show the currently active value + followed by "(local)" or "(system)" depending on whether it is + a locally set or system-wide value. + + sync_completed + This shows the number of sectors that have been completed of + whatever the current sync_action is, followed by the number of + sectors in total that could need to be processed. The two + numbers are separated by a '/' thus effectively showing one + value, a fraction of the process that is complete. + + sync_speed + This shows the current actual speed, in K/sec, of the current + sync_action. It is averaged over the last 30 seconds. + + As component devices are added to an md array, they appear in the 'md' directory as new directories named dev-XXX @@ -399,35 +412,6 @@ also have Note that the numbers are 'bit' numbers, not 'block' numbers. They should be scaled by the bitmap_chunksize. - sync_speed_min - sync_speed_max - This are similar to /proc/sys/dev/raid/speed_limit_{min,max} - however they only apply to the particular array. - If no value has been written to these, of if the word 'system' - is written, then the system-wide value is used. If a value, - in kibibytes-per-second is written, then it is used. - When the files are read, they show the currently active value - followed by "(local)" or "(system)" depending on whether it is - a locally set or system-wide value. - - sync_completed - This shows the number of sectors that have been completed of - whatever the current sync_action is, followed by the number of - sectors in total that could need to be processed. The two - numbers are separated by a '/' thus effectively showing one - value, a fraction of the process that is complete. - - sync_speed - This shows the current actual speed, in K/sec, of the current - sync_action. It is averaged over the last 30 seconds. - - suspend_lo - suspend_hi - The two values, given as numbers of sectors, indicate a range - within the array where IO will be blocked. This is currently - only supported for raid4/5/6. - - Each active md device may also have attributes specific to the personality module that manages it. These are specific to the implementation of the module and could diff --git a/trunk/Documentation/netlabel/introduction.txt b/trunk/Documentation/netlabel/introduction.txt index 5ecd8d1dcf4e..a4ffba1694c8 100644 --- a/trunk/Documentation/netlabel/introduction.txt +++ b/trunk/Documentation/netlabel/introduction.txt @@ -30,7 +30,7 @@ The communication layer exists to allow NetLabel configuration and monitoring from user space. The NetLabel communication layer uses a message based protocol built on top of the Generic NETLINK transport mechanism. The exact formatting of these NetLabel messages as well as the Generic NETLINK family -names can be found in the 'net/netlabel/' directory as comments in the +names can be found in the the 'net/netlabel/' directory as comments in the header files as well as in 'include/net/netlabel.h'. * Security Module API diff --git a/trunk/Documentation/networking/6pack.txt b/trunk/Documentation/networking/6pack.txt index d0777a1200e1..48ed2b711bd2 100644 --- a/trunk/Documentation/networking/6pack.txt +++ b/trunk/Documentation/networking/6pack.txt @@ -1,6 +1,6 @@ This is the 6pack-mini-HOWTO, written by -Andreas Könsgen DG3KQ +Andreas Knsgen DG3KQ Internet: ajk@iehk.rwth-aachen.de AMPR-net: dg3kq@db0pra.ampr.org AX.25: dg3kq@db0ach.#nrw.deu.eu diff --git a/trunk/Documentation/networking/NAPI_HOWTO.txt b/trunk/Documentation/networking/NAPI_HOWTO.txt index 7907435a661c..fb8dc6422a52 100644 --- a/trunk/Documentation/networking/NAPI_HOWTO.txt +++ b/trunk/Documentation/networking/NAPI_HOWTO.txt @@ -160,7 +160,7 @@ on current cpu. This primitive is called by dev->poll(), when it completes its work. The device cannot be out of poll list at this call, if it is then clearly it is a BUG(). You'll know ;-> -All of the above methods are used below, so keep reading for clarity. +All these above nethods are used below. So keep reading for clarity. Device driver changes to be made when porting NAPI ================================================== diff --git a/trunk/Documentation/networking/packet_mmap.txt b/trunk/Documentation/networking/packet_mmap.txt index db0cd5169581..5a232d946be3 100644 --- a/trunk/Documentation/networking/packet_mmap.txt +++ b/trunk/Documentation/networking/packet_mmap.txt @@ -13,7 +13,7 @@ You can find the latest version of this document at Please send me your comments to - Ulisses Alonso Camaró + Ulisses Alonso Camar ------------------------------------------------------------------------------- + Why use PACKET_MMAP diff --git a/trunk/Documentation/networking/slicecom.hun b/trunk/Documentation/networking/slicecom.hun index bed2f045e550..5acf1918694a 100644 --- a/trunk/Documentation/networking/slicecom.hun +++ b/trunk/Documentation/networking/slicecom.hun @@ -1,7 +1,7 @@ SliceCOM adapter felhasznaloi dokumentacioja - 0.51 verziohoz -Bartók István +Bartk Istvn Utolso modositas: Wed Aug 29 17:26:58 CEST 2001 ----------------------------------------------------------------- diff --git a/trunk/Documentation/networking/slicecom.txt b/trunk/Documentation/networking/slicecom.txt index c82c0cf981b4..32d3b916afad 100644 --- a/trunk/Documentation/networking/slicecom.txt +++ b/trunk/Documentation/networking/slicecom.txt @@ -1,9 +1,9 @@ SliceCOM adapter user's documentation - for the 0.51 driver version -Written by Bartók István +Written by Bartk Istvn -English translation: Lakatos György +English translation: Lakatos Gyrgy Mon Dec 11 15:28:42 CET 2000 Last modified: Wed Aug 29 17:25:37 CEST 2001 diff --git a/trunk/Documentation/networking/tms380tr.txt b/trunk/Documentation/networking/tms380tr.txt index 1f73e13058df..c169a57bc925 100644 --- a/trunk/Documentation/networking/tms380tr.txt +++ b/trunk/Documentation/networking/tms380tr.txt @@ -71,24 +71,24 @@ Below find attached the setting for the SK NET TR 4/16 ISA adapters CHAPTER 1 LOCATION OF DIP-SWITCH ============================================================== -UÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ -þUÄÄÄÄÄÄ¿ UÄÄÄÄÄ¿ UÄÄÄ¿ þ -þAÄÄÄÄÄÄU W1 AÄÄÄÄÄU UÄÄÄÄ¿ þ þ þ -þUÄÄÄÄÄÄ¿ þ þ þ þ UÄÄÅ¿ -þAÄÄÄÄÄÄU UÄÄÄÄÄÄÄÄÄÄÄ¿ AÄÄÄÄU þ þ þ þþ -þUÄÄÄÄÄÄ¿ þ þ UÄÄÄ¿ AÄÄÄU AÄÄÅU -þAÄÄÄÄÄÄU þ TMS380C26 þ þ þ þ -þUÄÄÄÄÄÄ¿ þ þ AÄÄÄU AÄ¿ -þAÄÄÄÄÄÄU þ þ þ þ -þ AÄÄÄÄÄÄÄÄÄÄÄU þ þ -þ þ þ -þ AÄU -þ þ -þ þ -þ þ -þ þ -AÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄU - AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU +UĿ +UĿ UĿ UĿ +AU W1 AU UĿ +UĿ Uſ +AU UĿ AU +UĿ UĿ AU AU +AU TMS380C26 +UĿ AU AĿ +AU + AU + + AU + + + + +AAAAAU + AU AU ============================================================== CHAPTER 2 DEFAULT SETTINGS @@ -108,9 +108,9 @@ AÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄAÄÄÄÄÄÄÄÄ CHAPTER 3 DIP SWITCH W1 DESCRIPTION ============================================================== - UÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄ¿ ON - þ 1 þ 2 þ 3 þ 4 þ 5 þ 6 þ 7 þ 8 þ - AÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄU OFF + UAAAAAAAĿ ON + 1 2 3 4 5 6 7 8 + AAAAAAAAU OFF |AD | BootROM Addr. | I/O | +-+-+-------+-------+-----+-----+ | | | diff --git a/trunk/Documentation/networking/udplite.txt b/trunk/Documentation/networking/udplite.txt index 6be09ba24a36..dd6f46b83dab 100644 --- a/trunk/Documentation/networking/udplite.txt +++ b/trunk/Documentation/networking/udplite.txt @@ -139,7 +139,7 @@ 3) Disabling the Checksum Computation On both sender and receiver, checksumming will always be performed - and cannot be disabled using SO_NO_CHECK. Thus + and can not be disabled using SO_NO_CHECK. Thus setsockopt(sockfd, SOL_SOCKET, SO_NO_CHECK, ... ); diff --git a/trunk/Documentation/networking/wan-router.txt b/trunk/Documentation/networking/wan-router.txt index bc2ab419a74a..07dd6d9930a1 100644 --- a/trunk/Documentation/networking/wan-router.txt +++ b/trunk/Documentation/networking/wan-router.txt @@ -335,7 +335,7 @@ REVISION HISTORY creating applications using BiSync streaming. -2.0.5 Aug 04, 1999 CHDLC initialization bug fix. +2.0.5 Aug 04, 1999 CHDLC initializatin bug fix. PPP interrupt driven driver: Fix to the PPP line hangup problem. New PPP firmware @@ -372,7 +372,7 @@ REVISION HISTORY o cfgft1 GUI csu/dsu configurator o wancfg GUI configuration file configurator. - o Architectural directory changes. + o Architectual directory changes. beta-2.1.4 Jul 2000 o Dynamic interface configuration: Network interfaces reflect the state diff --git a/trunk/Documentation/pci.txt b/trunk/Documentation/pci.txt index d38261b67905..e2c9d0a0c43d 100644 --- a/trunk/Documentation/pci.txt +++ b/trunk/Documentation/pci.txt @@ -373,7 +373,7 @@ E.g. clearing pending interrupts. 3.6 Register IRQ handler ~~~~~~~~~~~~~~~~~~~~~~~~ -While calling request_irq() is the last step described here, +While calling request_irq() is the the last step described here, this is often just another intermediate step to initialize a device. This step can often be deferred until the device is opened for use. diff --git a/trunk/Documentation/pcieaer-howto.txt b/trunk/Documentation/pcieaer-howto.txt index d5da86170106..16c251230c82 100644 --- a/trunk/Documentation/pcieaer-howto.txt +++ b/trunk/Documentation/pcieaer-howto.txt @@ -13,7 +13,7 @@ Reporting (AER) driver and provides information on how to use it, as well as how to enable the drivers of endpoint devices to conform with PCI Express AER driver. -1.2 Copyright © Intel Corporation 2006. +1.2 Copyright Intel Corporation 2006. 1.3 What is the PCI Express AER Driver? diff --git a/trunk/Documentation/pnp.txt b/trunk/Documentation/pnp.txt index 481faf515d53..28037aa1846c 100644 --- a/trunk/Documentation/pnp.txt +++ b/trunk/Documentation/pnp.txt @@ -140,7 +140,7 @@ Plug and Play but it is planned to be in the near future. Requirements for a Linux PnP protocol: 1.) the protocol must use EISA IDs 2.) the protocol must inform the PnP Layer of a devices current configuration -- the ability to set resources is optional but preferred. +- the ability to set resources is optional but prefered. The following are PnP protocol related functions: diff --git a/trunk/Documentation/power/swsusp.txt b/trunk/Documentation/power/swsusp.txt index 5b8d6953f05e..c55bd5079b90 100644 --- a/trunk/Documentation/power/swsusp.txt +++ b/trunk/Documentation/power/swsusp.txt @@ -48,7 +48,7 @@ before suspend (it is limited to 500 MB by default). Article about goals and implementation of Software Suspend for Linux ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Author: G‚ábor Kuti +Author: Gbor Kuti Last revised: 2003-10-20 by Pavel Machek Idea and goals to achieve diff --git a/trunk/Documentation/power/userland-swsusp.txt b/trunk/Documentation/power/userland-swsusp.txt index e00c6cf09e85..000556c932e9 100644 --- a/trunk/Documentation/power/userland-swsusp.txt +++ b/trunk/Documentation/power/userland-swsusp.txt @@ -93,23 +93,21 @@ SNAPSHOT_S2RAM - suspend to RAM; using this call causes the kernel to to resume the system from RAM if there's enough battery power or restore its state on the basis of the saved suspend image otherwise) -SNAPSHOT_PMOPS - enable the usage of the hibernation_ops->prepare, - hibernate_ops->enter and hibernation_ops->finish methods (the in-kernel - swsusp knows these as the "platform method") which are needed on many - machines to (among others) speed up the resume by letting the BIOS skip - some steps or to let the system recognise the correct state of the - hardware after the resume (in particular on many machines this ensures - that unplugged AC adapters get correctly detected and that kacpid does - not run wild after the resume). The last ioctl() argument can take one - of the three values, defined in kernel/power/power.h: +SNAPSHOT_PMOPS - enable the usage of the pmops->prepare, pmops->enter and + pmops->finish methods (the in-kernel swsusp knows these as the "platform + method") which are needed on many machines to (among others) speed up + the resume by letting the BIOS skip some steps or to let the system + recognise the correct state of the hardware after the resume (in + particular on many machines this ensures that unplugged AC + adapters get correctly detected and that kacpid does not run wild after + the resume). The last ioctl() argument can take one of the three + values, defined in kernel/power/power.h: PMOPS_PREPARE - make the kernel carry out the - hibernation_ops->prepare() operation + pm_ops->prepare(PM_SUSPEND_DISK) operation PMOPS_ENTER - make the kernel power off the system by calling - hibernation_ops->enter() + pm_ops->enter(PM_SUSPEND_DISK) PMOPS_FINISH - make the kernel carry out the - hibernation_ops->finish() operation - Note that the actual constants are misnamed because they surface - internal kernel implementation details that have changed. + pm_ops->finish(PM_SUSPEND_DISK) operation The device's read() operation can be used to transfer the snapshot image from the kernel. It has the following limitations: diff --git a/trunk/Documentation/powerpc/booting-without-of.txt b/trunk/Documentation/powerpc/booting-without-of.txt index b49ce169a63a..d4bfae75c946 100644 --- a/trunk/Documentation/powerpc/booting-without-of.txt +++ b/trunk/Documentation/powerpc/booting-without-of.txt @@ -1444,7 +1444,7 @@ platforms are moved over to use the flattened-device-tree model. Basically, it is a bus of devices, that could act more or less as a complete entity (UCC, USB etc ). All of them should be siblings on the "root" qe node, using the common properties from there. - The description below applies to the qe of MPC8360 and + The description below applies to the the qe of MPC8360 and more nodes and properties would be extended in the future. i) Root QE device @@ -1633,7 +1633,7 @@ platforms are moved over to use the flattened-device-tree model. - assignment : function number of the pin according to the Pin Assignment tables in User Manual. Each pin can have up to 4 possible functions in QE and two options for CPM. - - has_irq : indicates if the pin is used as source of external + - has_irq : indicates if the pin is used as source of exteral interrupts. Example: diff --git a/trunk/Documentation/s390/Debugging390.txt b/trunk/Documentation/s390/Debugging390.txt index d30a281c570f..0993969609cf 100644 --- a/trunk/Documentation/s390/Debugging390.txt +++ b/trunk/Documentation/s390/Debugging390.txt @@ -2209,7 +2209,7 @@ Breakpoint 2 at 0x4d87a4: file top.c, line 2609. #3 0x5167e6 in readline_internal_char () at readline.c:454 #4 0x5168ee in readline_internal_charloop () at readline.c:507 #5 0x51692c in readline_internal () at readline.c:521 -#6 0x5164fe in readline (prompt=0x7ffff810 "\177ÿøx\177ÿ÷Ø\177ÿøxÀ") +#6 0x5164fe in readline (prompt=0x7ffff810 "\177x\177\177x") at readline.c:349 #7 0x4d7a8a in command_line_input (prrompt=0x564420 "(gdb) ", repeat=1, annotation_suffix=0x4d6b44 "prompt") at top.c:2091 diff --git a/trunk/Documentation/scsi/aha152x.txt b/trunk/Documentation/scsi/aha152x.txt index 29ce6d87e451..2ce022cec9be 100644 --- a/trunk/Documentation/scsi/aha152x.txt +++ b/trunk/Documentation/scsi/aha152x.txt @@ -1,7 +1,7 @@ $Id: README.aha152x,v 1.2 1999/12/25 15:32:30 fischer Exp fischer $ Adaptec AHA-1520/1522 SCSI driver for Linux (aha152x) -Copyright 1993-1999 Jürgen Fischer +Copyright 1993-1999 Jrgen Fischer TC1550 patches by Luuk van Dijk (ldz@xs4all.nl) diff --git a/trunk/Documentation/scsi/aic7xxx.txt b/trunk/Documentation/scsi/aic7xxx.txt index 5f34d2ba69b4..9b894f116d95 100644 --- a/trunk/Documentation/scsi/aic7xxx.txt +++ b/trunk/Documentation/scsi/aic7xxx.txt @@ -40,7 +40,7 @@ The following information is available in this file: 2. Multi-function Twin Channel Device - Two controllers on one chip. 3. Command Channel Secondary DMA Engine - Allows scatter gather list and SCB prefetch. - 4. 64 Byte SCB Support - Allows disconnected, untagged request table + 4. 64 Byte SCB Support - Allows disconnected, unttagged request table for all possible target/lun combinations. 5. Block Move Instruction Support - Doubles the speed of certain sequencer operations. diff --git a/trunk/Documentation/scsi/aic7xxx_old.txt b/trunk/Documentation/scsi/aic7xxx_old.txt index 7bd210ab45a1..05667e7308d4 100644 --- a/trunk/Documentation/scsi/aic7xxx_old.txt +++ b/trunk/Documentation/scsi/aic7xxx_old.txt @@ -356,7 +356,7 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD or enable Tagged Command Queueing (TCQ) on specific devices. As of driver version 5.1.11, TCQ is now either on or off by default according to the setting you choose during the make config process. - In order to en/disable TCQ for certain devices at boot time, a user + In order to en/disable TCQ for certian devices at boot time, a user may use this boot param. The driver will then parse this message out and en/disable the specific device entries that are present based upon the value given. The param line is parsed in the following manner: diff --git a/trunk/Documentation/scsi/ncr53c8xx.txt b/trunk/Documentation/scsi/ncr53c8xx.txt index 39d409a8efe5..88ef88b949f7 100644 --- a/trunk/Documentation/scsi/ncr53c8xx.txt +++ b/trunk/Documentation/scsi/ncr53c8xx.txt @@ -1260,7 +1260,7 @@ then the request of the IRQ obviously will not succeed for all the drivers. 15.1 Problem tracking Most SCSI problems are due to a non conformant SCSI bus or to buggy -devices. If unfortunately you have SCSI problems, you can check the +devices. If infortunately you have SCSI problems, you can check the following things: - SCSI bus cables diff --git a/trunk/Documentation/scsi/st.txt b/trunk/Documentation/scsi/st.txt index b7be95b5bd24..3c12422f7f41 100644 --- a/trunk/Documentation/scsi/st.txt +++ b/trunk/Documentation/scsi/st.txt @@ -1,5 +1,5 @@ This file contains brief information about the SCSI tape driver. -The driver is currently maintained by Kai Mäkisara (email +The driver is currently maintained by Kai Mkisara (email Kai.Makisara@kolumbus.fi) Last modified: Mon Mar 7 21:14:44 2005 by kai.makisara diff --git a/trunk/Documentation/scsi/sym53c8xx_2.txt b/trunk/Documentation/scsi/sym53c8xx_2.txt index 3d9f06bb3d00..2c1745a9df00 100644 --- a/trunk/Documentation/scsi/sym53c8xx_2.txt +++ b/trunk/Documentation/scsi/sym53c8xx_2.txt @@ -587,7 +587,7 @@ devices, ... may cause a SCSI signal to be wrong when te driver reads it. 15.1 Problem tracking Most SCSI problems are due to a non conformant SCSI bus or too buggy -devices. If unfortunately you have SCSI problems, you can check the +devices. If infortunately you have SCSI problems, you can check the following things: - SCSI bus cables diff --git a/trunk/Documentation/scsi/tmscsim.txt b/trunk/Documentation/scsi/tmscsim.txt index 61c0531e044a..8b2168aa4fc7 100644 --- a/trunk/Documentation/scsi/tmscsim.txt +++ b/trunk/Documentation/scsi/tmscsim.txt @@ -426,7 +426,7 @@ Thanks to Linus Torvalds, Alan Cox, the FSF people, the XFree86 team and all the others for the wonderful OS and software. Thanks to C.L. Huang and Philip Giang (Tekram) for the initial driver release and support. -Thanks to Doug Ledford, Gérard Roudier for support with SCSI coding. +Thanks to Doug Ledford, Grard Roudier for support with SCSI coding. Thanks to a lot of people (espec. Chiaki Ishikawa, Andreas Haumer, Hubert Tonneau) for intensively testing the driver (and even risking data loss doing this during early revisions). diff --git a/trunk/Documentation/sonypi.txt b/trunk/Documentation/sonypi.txt index 4857acfc50f1..c1237a925505 100644 --- a/trunk/Documentation/sonypi.txt +++ b/trunk/Documentation/sonypi.txt @@ -1,7 +1,7 @@ Sony Programmable I/O Control Device Driver Readme -------------------------------------------------- Copyright (C) 2001-2004 Stelian Pop - Copyright (C) 2001-2002 Alcôve + Copyright (C) 2001-2002 Alcve Copyright (C) 2001 Michael Ashley Copyright (C) 2001 Junichi Morita Copyright (C) 2000 Takaya Kinjo diff --git a/trunk/Documentation/sound/oss/mwave b/trunk/Documentation/sound/oss/mwave index 5fbcb1609275..858334bb46b0 100644 --- a/trunk/Documentation/sound/oss/mwave +++ b/trunk/Documentation/sound/oss/mwave @@ -163,7 +163,7 @@ OR the Default= line COULD be Default=SBPRO Reboot to Windows 95 and choose Linux. When booted, use sndconfig to configure -the sound modules and voilà - ThinkPad sound with Linux. +the sound modules and voil - ThinkPad sound with Linux. Now the gotchas - you can either have CD sound OR Mixers but not both. That's a problem with the SB1.5 (CD sound) or SBPRO (Mixers) settings. No one knows why diff --git a/trunk/Documentation/sysctl/kernel.txt b/trunk/Documentation/sysctl/kernel.txt index 111fd28727ec..5922e84d9133 100644 --- a/trunk/Documentation/sysctl/kernel.txt +++ b/trunk/Documentation/sysctl/kernel.txt @@ -221,14 +221,14 @@ Controls the kernel's behaviour when an oops or BUG is encountered. 0: try to continue operation -1: panic immediately. If the `panic' sysctl is also non-zero then the +1: panic immediatly. If the `panic' sysctl is also non-zero then the machine will be rebooted. ============================================================== pid_max: -PID allocation wrap value. When the kernel's next PID value +PID allocation wrap value. When the kenrel's next PID value reaches this value, it wraps back to a minimum PID value. PIDs of value pid_max or larger are not allocated. diff --git a/trunk/Documentation/usb/CREDITS b/trunk/Documentation/usb/CREDITS index 67c59cdc9959..27a721635f92 100644 --- a/trunk/Documentation/usb/CREDITS +++ b/trunk/Documentation/usb/CREDITS @@ -65,7 +65,7 @@ THANKS file in Inaky's driver): will sell keyboards to some of the 3 million (at least) Linux users. - - Many thanks to ing büro h doran [http://www.ibhdoran.com]! + - Many thanks to ing bro h doran [http://www.ibhdoran.com]! It was almost impossible to get a PC backplate USB connector for the motherboard here at Europe (mine, home-made, was quite lousy :). Now I know where to acquire nice USB stuff! diff --git a/trunk/Documentation/usb/usb-serial.txt b/trunk/Documentation/usb/usb-serial.txt index 5b635ae84944..b18e86a22506 100644 --- a/trunk/Documentation/usb/usb-serial.txt +++ b/trunk/Documentation/usb/usb-serial.txt @@ -45,9 +45,9 @@ ConnectTech WhiteHEAT 4 port converter Connect Tech's Support Department at support@connecttech.com -HandSpring Visor, Palm USB, and Clié USB driver +HandSpring Visor, Palm USB, and Cli USB driver - This driver works with all HandSpring USB, Palm USB, and Sony Clié USB + This driver works with all HandSpring USB, Palm USB, and Sony Cli USB devices. Only when the device tries to connect to the host, will the device show @@ -69,7 +69,7 @@ HandSpring Visor, Palm USB, and Clié USB driver the port to use for the HotSync transfer. The "Generic" port can be used for other device communication, such as a PPP link. - For some Sony Clié devices, /dev/ttyUSB0 must be used to talk to the + For some Sony Cli devices, /dev/ttyUSB0 must be used to talk to the device. This is true for all OS version 3.5 devices, and most devices that have had a flash upgrade to a newer version of the OS. See the kernel system log for information on which is the correct port to use. diff --git a/trunk/Documentation/video4linux/README.pvrusb2 b/trunk/Documentation/video4linux/README.pvrusb2 index a747200fe67c..a4b7ae800866 100644 --- a/trunk/Documentation/video4linux/README.pvrusb2 +++ b/trunk/Documentation/video4linux/README.pvrusb2 @@ -8,7 +8,7 @@ Background: This driver is intended for the "Hauppauge WinTV PVR USB 2.0", which is a USB 2.0 hosted TV Tuner. This driver is a work in progress. - Its history started with the reverse-engineering effort by Björn + Its history started with the reverse-engineering effort by Bjrn Danielsson whose web page can be found here: http://pvrusb2.dax.nu/ diff --git a/trunk/Documentation/video4linux/Zoran b/trunk/Documentation/video4linux/Zoran index 295462b2317a..85c575ac4fb9 100644 --- a/trunk/Documentation/video4linux/Zoran +++ b/trunk/Documentation/video4linux/Zoran @@ -242,7 +242,7 @@ can generate: PAL , NTSC , SECAM Conexant bt866 TV encoder is used in AVS6EYES, and -can generate: NTSC/PAL, PAL­M, PAL­N +can generate: NTSC/PAL, PALM, PALN The adv717x, should be able to produce PAL N. But you find nothing PAL N specific in the registers. Seem that you have to reuse a other standard diff --git a/trunk/Documentation/video4linux/meye.txt b/trunk/Documentation/video4linux/meye.txt index bf3af5fe558f..5e51c59bf2b0 100644 --- a/trunk/Documentation/video4linux/meye.txt +++ b/trunk/Documentation/video4linux/meye.txt @@ -1,7 +1,7 @@ Vaio Picturebook Motion Eye Camera Driver Readme ------------------------------------------------ Copyright (C) 2001-2004 Stelian Pop - Copyright (C) 2001-2002 Alcôve + Copyright (C) 2001-2002 Alcve Copyright (C) 2000 Andrew Tridgell This driver enable the use of video4linux compatible applications with the diff --git a/trunk/Documentation/video4linux/ov511.txt b/trunk/Documentation/video4linux/ov511.txt index b3326b167ada..79af610d4ba5 100644 --- a/trunk/Documentation/video4linux/ov511.txt +++ b/trunk/Documentation/video4linux/ov511.txt @@ -195,11 +195,11 @@ MODULE PARAMETERS: NAME: bandingfilter TYPE: integer (Boolean) DEFAULT: 0 (off) - DESC: Enables the sensor´s banding filter exposure algorithm. This reduces + DESC: Enables the sensors banding filter exposure algorithm. This reduces or stabilizes the "banding" caused by some artificial light sources (especially fluorescent). You might have to set lightfreq correctly for this to work right. As an added bonus, this sometimes makes it - possible to capture your monitor´s output. + possible to capture your monitors output. NAME: fastset TYPE: integer (Boolean) diff --git a/trunk/Documentation/vm/slabinfo.c b/trunk/Documentation/vm/slabinfo.c index 686a8e04a4f3..41710ccf3a29 100644 --- a/trunk/Documentation/vm/slabinfo.c +++ b/trunk/Documentation/vm/slabinfo.c @@ -16,7 +16,6 @@ #include #include #include -#include #define MAX_SLABS 500 #define MAX_ALIASES 500 @@ -42,15 +41,12 @@ struct aliasinfo { } aliasinfo[MAX_ALIASES]; int slabs = 0; -int actual_slabs = 0; int aliases = 0; int alias_targets = 0; int highest_node = 0; char buffer[4096]; -int show_empty = 0; -int show_report = 0; int show_alias = 0; int show_slab = 0; int skip_zero = 1; @@ -63,15 +59,6 @@ int show_inverted = 0; int show_single_ref = 0; int show_totals = 0; int sort_size = 0; -int set_debug = 0; -int show_ops = 0; - -/* Debug options */ -int sanity = 0; -int redzone = 0; -int poison = 0; -int tracking = 0; -int tracing = 0; int page_size; @@ -89,33 +76,20 @@ void fatal(const char *x, ...) void usage(void) { - printf("slabinfo 5/7/2007. (c) 2007 sgi. clameter@sgi.com\n\n" - "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n" + printf("slabinfo [-ahnpvtsz] [slab-regexp]\n" "-a|--aliases Show aliases\n" - "-d|--debug= Set/Clear Debug options\n" - "-e|--empty Show empty slabs\n" - "-f|--first-alias Show first alias\n" "-h|--help Show usage information\n" - "-i|--inverted Inverted list\n" - "-l|--slabs Show slabs\n" "-n|--numa Show NUMA information\n" - "-o|--ops Show kmem_cache_ops\n" "-s|--shrink Shrink slabs\n" - "-r|--report Detailed report on single slabs\n" - "-S|--Size Sort by size\n" + "-v|--validate Validate slabs\n" "-t|--tracking Show alloc/free information\n" "-T|--Totals Show summary information\n" - "-v|--validate Validate slabs\n" + "-l|--slabs Show slabs\n" + "-S|--Size Sort by size\n" "-z|--zero Include empty slabs\n" + "-f|--first-alias Show first alias\n" + "-i|--inverted Inverted list\n" "-1|--1ref Single reference\n" - "\nValid debug options (FZPUT may be combined)\n" - "a / A Switch on all debug options (=FZUP)\n" - "- Switch off all debug options\n" - "f / F Sanity Checks (SLAB_DEBUG_FREE)\n" - "z / Z Redzoning\n" - "p / P Poisoning\n" - "u / U Tracking\n" - "t / T Tracing\n" ); } @@ -169,10 +143,11 @@ unsigned long get_obj_and_str(char *name, char **x) void set_obj(struct slabinfo *s, char *name, int n) { char x[100]; - FILE *f; sprintf(x, "%s/%s", s->name, name); - f = fopen(x, "w"); + + FILE *f = fopen(x, "w"); + if (!f) fatal("Cannot write to %s\n", x); @@ -180,26 +155,6 @@ void set_obj(struct slabinfo *s, char *name, int n) fclose(f); } -unsigned long read_slab_obj(struct slabinfo *s, char *name) -{ - char x[100]; - FILE *f; - int l; - - sprintf(x, "%s/%s", s->name, name); - f = fopen(x, "r"); - if (!f) { - buffer[0] = 0; - l = 0; - } else { - l = fread(buffer, 1, sizeof(buffer), f); - buffer[l] = 0; - fclose(f); - } - return l; -} - - /* * Put a size string together */ @@ -271,7 +226,7 @@ int line = 0; void first_line(void) { - printf("Name Objects Objsize Space " + printf("Name Objects Objsize Space " "Slabs/Part/Cpu O/S O %%Fr %%Ef Flg\n"); } @@ -291,7 +246,10 @@ struct aliasinfo *find_one_alias(struct slabinfo *find) return best; } } - return best; + if (best) + return best; + fatal("Cannot find alias for %s\n", find->name); + return NULL; } unsigned long slab_size(struct slabinfo *s) @@ -299,126 +257,6 @@ unsigned long slab_size(struct slabinfo *s) return s->slabs * (page_size << s->order); } -void slab_numa(struct slabinfo *s, int mode) -{ - int node; - - if (strcmp(s->name, "*") == 0) - return; - - if (!highest_node) { - printf("\n%s: No NUMA information available.\n", s->name); - return; - } - - if (skip_zero && !s->slabs) - return; - - if (!line) { - printf("\n%-21s:", mode ? "NUMA nodes" : "Slab"); - for(node = 0; node <= highest_node; node++) - printf(" %4d", node); - printf("\n----------------------"); - for(node = 0; node <= highest_node; node++) - printf("-----"); - printf("\n"); - } - printf("%-21s ", mode ? "All slabs" : s->name); - for(node = 0; node <= highest_node; node++) { - char b[20]; - - store_size(b, s->numa[node]); - printf(" %4s", b); - } - printf("\n"); - if (mode) { - printf("%-21s ", "Partial slabs"); - for(node = 0; node <= highest_node; node++) { - char b[20]; - - store_size(b, s->numa_partial[node]); - printf(" %4s", b); - } - printf("\n"); - } - line++; -} - -void show_tracking(struct slabinfo *s) -{ - printf("\n%s: Kernel object allocation\n", s->name); - printf("-----------------------------------------------------------------------\n"); - if (read_slab_obj(s, "alloc_calls")) - printf(buffer); - else - printf("No Data\n"); - - printf("\n%s: Kernel object freeing\n", s->name); - printf("------------------------------------------------------------------------\n"); - if (read_slab_obj(s, "free_calls")) - printf(buffer); - else - printf("No Data\n"); - -} - -void ops(struct slabinfo *s) -{ - if (strcmp(s->name, "*") == 0) - return; - - if (read_slab_obj(s, "ops")) { - printf("\n%s: kmem_cache operations\n", s->name); - printf("--------------------------------------------\n"); - printf(buffer); - } else - printf("\n%s has no kmem_cache operations\n", s->name); -} - -const char *onoff(int x) -{ - if (x) - return "On "; - return "Off"; -} - -void report(struct slabinfo *s) -{ - if (strcmp(s->name, "*") == 0) - return; - printf("\nSlabcache: %-20s Aliases: %2d Order : %2d\n", s->name, s->aliases, s->order); - if (s->hwcache_align) - printf("** Hardware cacheline aligned\n"); - if (s->cache_dma) - printf("** Memory is allocated in a special DMA zone\n"); - if (s->destroy_by_rcu) - printf("** Slabs are destroyed via RCU\n"); - if (s->reclaim_account) - printf("** Reclaim accounting active\n"); - - printf("\nSizes (bytes) Slabs Debug Memory\n"); - printf("------------------------------------------------------------------------\n"); - printf("Object : %7d Total : %7ld Sanity Checks : %s Total: %7ld\n", - s->object_size, s->slabs, onoff(s->sanity_checks), - s->slabs * (page_size << s->order)); - printf("SlabObj: %7d Full : %7ld Redzoning : %s Used : %7ld\n", - s->slab_size, s->slabs - s->partial - s->cpu_slabs, - onoff(s->red_zone), s->objects * s->object_size); - printf("SlabSiz: %7d Partial: %7ld Poisoning : %s Loss : %7ld\n", - page_size << s->order, s->partial, onoff(s->poison), - s->slabs * (page_size << s->order) - s->objects * s->object_size); - printf("Loss : %7d CpuSlab: %7d Tracking : %s Lalig: %7ld\n", - s->slab_size - s->object_size, s->cpu_slabs, onoff(s->store_user), - (s->slab_size - s->object_size) * s->objects); - printf("Align : %7d Objects: %7d Tracing : %s Lpadd: %7ld\n", - s->align, s->objs_per_slab, onoff(s->trace), - ((page_size << s->order) - s->objs_per_slab * s->slab_size) * - s->slabs); - - ops(s); - show_tracking(s); - slab_numa(s, 1); -} void slabcache(struct slabinfo *s) { @@ -427,18 +265,7 @@ void slabcache(struct slabinfo *s) char flags[20]; char *p = flags; - if (strcmp(s->name, "*") == 0) - return; - - if (actual_slabs == 1) { - report(s); - return; - } - - if (skip_zero && !show_empty && !s->slabs) - return; - - if (show_empty && s->slabs) + if (skip_zero && !s->slabs) return; store_size(size_str, slab_size(s)); @@ -476,128 +303,48 @@ void slabcache(struct slabinfo *s) flags); } -/* - * Analyze debug options. Return false if something is amiss. - */ -int debug_opt_scan(char *opt) +void slab_numa(struct slabinfo *s) { - if (!opt || !opt[0] || strcmp(opt, "-") == 0) - return 1; - - if (strcasecmp(opt, "a") == 0) { - sanity = 1; - poison = 1; - redzone = 1; - tracking = 1; - return 1; - } + int node; - for ( ; *opt; opt++) - switch (*opt) { - case 'F' : case 'f': - if (sanity) - return 0; - sanity = 1; - break; - case 'P' : case 'p': - if (poison) - return 0; - poison = 1; - break; + if (!highest_node) + fatal("No NUMA information available.\n"); - case 'Z' : case 'z': - if (redzone) - return 0; - redzone = 1; - break; + if (skip_zero && !s->slabs) + return; - case 'U' : case 'u': - if (tracking) - return 0; - tracking = 1; - break; + if (!line) { + printf("\nSlab Node "); + for(node = 0; node <= highest_node; node++) + printf(" %4d", node); + printf("\n----------------------"); + for(node = 0; node <= highest_node; node++) + printf("-----"); + printf("\n"); + } + printf("%-21s ", s->name); + for(node = 0; node <= highest_node; node++) { + char b[20]; - case 'T' : case 't': - if (tracing) - return 0; - tracing = 1; - break; - default: - return 0; - } - return 1; + store_size(b, s->numa[node]); + printf(" %4s", b); + } + printf("\n"); + line++; } -int slab_empty(struct slabinfo *s) +void show_tracking(struct slabinfo *s) { - if (s->objects > 0) - return 0; - - /* - * We may still have slabs even if there are no objects. Shrinking will - * remove them. - */ - if (s->slabs != 0) - set_obj(s, "shrink", 1); + printf("\n%s: Calls to allocate a slab object\n", s->name); + printf("---------------------------------------------------\n"); + if (read_obj("alloc_calls")) + printf(buffer); - return 1; -} + printf("%s: Calls to free a slab object\n", s->name); + printf("-----------------------------------------------\n"); + if (read_obj("free_calls")) + printf(buffer); -void slab_debug(struct slabinfo *s) -{ - if (sanity && !s->sanity_checks) { - set_obj(s, "sanity", 1); - } - if (!sanity && s->sanity_checks) { - if (slab_empty(s)) - set_obj(s, "sanity", 0); - else - fprintf(stderr, "%s not empty cannot disable sanity checks\n", s->name); - } - if (redzone && !s->red_zone) { - if (slab_empty(s)) - set_obj(s, "red_zone", 1); - else - fprintf(stderr, "%s not empty cannot enable redzoning\n", s->name); - } - if (!redzone && s->red_zone) { - if (slab_empty(s)) - set_obj(s, "red_zone", 0); - else - fprintf(stderr, "%s not empty cannot disable redzoning\n", s->name); - } - if (poison && !s->poison) { - if (slab_empty(s)) - set_obj(s, "poison", 1); - else - fprintf(stderr, "%s not empty cannot enable poisoning\n", s->name); - } - if (!poison && s->poison) { - if (slab_empty(s)) - set_obj(s, "poison", 0); - else - fprintf(stderr, "%s not empty cannot disable poisoning\n", s->name); - } - if (tracking && !s->store_user) { - if (slab_empty(s)) - set_obj(s, "store_user", 1); - else - fprintf(stderr, "%s not empty cannot enable tracking\n", s->name); - } - if (!tracking && s->store_user) { - if (slab_empty(s)) - set_obj(s, "store_user", 0); - else - fprintf(stderr, "%s not empty cannot disable tracking\n", s->name); - } - if (tracing && !s->trace) { - if (slabs == 1) - set_obj(s, "trace", 1); - else - fprintf(stderr, "%s can only enable trace for one slab at a time\n", s->name); - } - if (!tracing && s->trace) - set_obj(s, "trace", 1); } void totals(void) @@ -926,7 +673,7 @@ void link_slabs(void) for (a = aliasinfo; a < aliasinfo + aliases; a++) { - for (s = slabinfo; s < slabinfo + slabs; s++) + for(s = slabinfo; s < slabinfo + slabs; s++) if (strcmp(a->ref, s->name) == 0) { a->slab = s; s->refs++; @@ -957,7 +704,7 @@ void alias(void) continue; } } - printf("\n%-12s <- %s", a->slab->name, a->name); + printf("\n%-20s <- %s", a->slab->name, a->name); active = a->slab->name; } else @@ -982,12 +729,7 @@ void rename_slabs(void) a = find_one_alias(s); - if (a) - s->name = a->name; - else { - s->name = "*"; - actual_slabs--; - } + s->name = a->name; } } @@ -1006,14 +748,11 @@ void read_slab_dir(void) char *t; int count; - if (chdir("/sys/slab")) - fatal("SYSFS support for SLUB not active\n"); - dir = opendir("."); while ((de = readdir(dir))) { if (de->d_name[0] == '.' || - (de->d_name[0] != ':' && slab_mismatch(de->d_name))) - continue; + slab_mismatch(de->d_name)) + continue; switch (de->d_type) { case DT_LNK: alias->name = strdup(de->d_name); @@ -1068,7 +807,6 @@ void read_slab_dir(void) } closedir(dir); slabs = slab - slabinfo; - actual_slabs = slabs; aliases = alias - aliasinfo; if (slabs > MAX_SLABS) fatal("Too many slabs\n"); @@ -1087,37 +825,34 @@ void output_slabs(void) if (show_numa) - slab_numa(slab, 0); - else if (show_track) + slab_numa(slab); + else + if (show_track) show_tracking(slab); - else if (validate) + else + if (validate) slab_validate(slab); - else if (shrink) + else + if (shrink) slab_shrink(slab); - else if (set_debug) - slab_debug(slab); - else if (show_ops) - ops(slab); - else if (show_slab) - slabcache(slab); + else { + if (show_slab) + slabcache(slab); + } } } struct option opts[] = { { "aliases", 0, NULL, 'a' }, - { "debug", 2, NULL, 'd' }, - { "empty", 0, NULL, 'e' }, - { "first-alias", 0, NULL, 'f' }, - { "help", 0, NULL, 'h' }, - { "inverted", 0, NULL, 'i'}, + { "slabs", 0, NULL, 'l' }, { "numa", 0, NULL, 'n' }, - { "ops", 0, NULL, 'o' }, - { "report", 0, NULL, 'r' }, + { "zero", 0, NULL, 'z' }, + { "help", 0, NULL, 'h' }, + { "validate", 0, NULL, 'v' }, + { "first-alias", 0, NULL, 'f' }, { "shrink", 0, NULL, 's' }, - { "slabs", 0, NULL, 'l' }, { "track", 0, NULL, 't'}, - { "validate", 0, NULL, 'v' }, - { "zero", 0, NULL, 'z' }, + { "inverted", 0, NULL, 'i'}, { "1ref", 0, NULL, '1'}, { NULL, 0, NULL, 0 } }; @@ -1129,9 +864,10 @@ int main(int argc, char *argv[]) char *pattern_source; page_size = getpagesize(); + if (chdir("/sys/slab")) + fatal("This kernel does not have SLUB support.\n"); - while ((c = getopt_long(argc, argv, "ad::efhil1noprstvzTS", - opts, NULL)) != -1) + while ((c = getopt_long(argc, argv, "afhil1npstvzTS", opts, NULL)) != -1) switch(c) { case '1': show_single_ref = 1; @@ -1139,14 +875,6 @@ int main(int argc, char *argv[]) case 'a': show_alias = 1; break; - case 'd': - set_debug = 1; - if (!debug_opt_scan(optarg)) - fatal("Invalid debug option '%s'\n", optarg); - break; - case 'e': - show_empty = 1; - break; case 'f': show_first_alias = 1; break; @@ -1159,12 +887,6 @@ int main(int argc, char *argv[]) case 'n': show_numa = 1; break; - case 'o': - show_ops = 1; - break; - case 'r': - show_report = 1; - break; case 's': shrink = 1; break; @@ -1192,8 +914,8 @@ int main(int argc, char *argv[]) } - if (!show_slab && !show_alias && !show_track && !show_report - && !validate && !shrink && !set_debug && !show_ops) + if (!show_slab && !show_alias && !show_track + && !validate && !shrink) show_slab = 1; if (argc > optind) diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index cfd26ddccd7a..41a4b477c576 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1038,8 +1038,6 @@ S: Maintained CONEXANT ACCESSRUNNER USB DRIVER P: Simon Arlott M: cxacru@fire.lp0.eu -L: accessrunner-general@lists.sourceforge.net -W: http://accessrunner.sourceforge.net/ S: Maintained CORETEMP HARDWARE MONITORING DRIVER @@ -2648,12 +2646,6 @@ M: corbet@lwn.net L: video4linux-list@redhat.com S: Maintained -ONENAND FLASH DRIVER -P: Kyungmin Park -M: kyungmin.park@samsung.com -L: linux-mtd@lists.infradead.org -S: Maintained - ONSTREAM SCSI TAPE DRIVER P: Willem Riede M: osst@riede.org @@ -2808,7 +2800,7 @@ L: linux-abi-devel@lists.sourceforge.net S: Maintained PHRAM MTD DRIVER -P: Jörn Engel +P: Jrn Engel M: joern@wh.fh-wedel.de L: linux-mtd@lists.infradead.org S: Maintained @@ -3082,7 +3074,7 @@ T: git kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git S: Maintained SCSI TAPE DRIVER -P: Kai Mäkisara +P: Kai Mkisara M: Kai.Makisara@kolumbus.fi L: linux-scsi@vger.kernel.org S: Maintained diff --git a/trunk/arch/arm/Kconfig b/trunk/arch/arm/Kconfig index d7c0984d4a86..0d8fac3b0371 100644 --- a/trunk/arch/arm/Kconfig +++ b/trunk/arch/arm/Kconfig @@ -354,7 +354,6 @@ config ARCH_SA1100 config ARCH_S3C2410 bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443" select GENERIC_GPIO - select GENERIC_TIME help Samsung S3C2410X CPU based systems, such as the Simtec Electronics BAST (), the IPAQ 1940 or diff --git a/trunk/arch/arm/Makefile b/trunk/arch/arm/Makefile index 00ea4305ad5d..ab9f2d4bd04e 100644 --- a/trunk/arch/arm/Makefile +++ b/trunk/arch/arm/Makefile @@ -47,13 +47,8 @@ comma = , # Note that GCC does not numerically define an architecture version # macro, but instead defines a whole series of macros which makes # testing for a specific architecture or later rather impossible. -arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7a,-march=armv5t -Wa$(comma)-march=armv7a) arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) -# Only override the compiler option if ARMv6. The ARMv6K extensions are -# always available in ARMv7 -ifeq ($(CONFIG_CPU_32v6),y) arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k) -endif arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t) arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 diff --git a/trunk/arch/arm/kernel/head-nommu.S b/trunk/arch/arm/kernel/head-nommu.S index 5d78ffb8a9a7..0119c0d5f978 100644 --- a/trunk/arch/arm/kernel/head-nommu.S +++ b/trunk/arch/arm/kernel/head-nommu.S @@ -33,7 +33,7 @@ * numbers for r1. * */ - .section ".text.head", "ax" + __INIT .type stext, %function ENTRY(stext) msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode diff --git a/trunk/arch/arm/kernel/head.S b/trunk/arch/arm/kernel/head.S index 41f98b4ba2ee..1d35edacc011 100644 --- a/trunk/arch/arm/kernel/head.S +++ b/trunk/arch/arm/kernel/head.S @@ -73,7 +73,7 @@ * crap here - that's what the boot loader (or in extreme, well justified * circumstances, zImage) is for. */ - .section ".text.head", "ax" + __INIT .type stext, %function ENTRY(stext) msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode diff --git a/trunk/arch/arm/kernel/init_task.c b/trunk/arch/arm/kernel/init_task.c index bd4ef53bc6b9..a00cca0000bd 100644 --- a/trunk/arch/arm/kernel/init_task.c +++ b/trunk/arch/arm/kernel/init_task.c @@ -31,7 +31,7 @@ EXPORT_SYMBOL(init_mm); * The things we do for performance.. */ union thread_union init_thread_union - __attribute__((__section__(".data.init_task"))) = + __attribute__((__section__(".init.task"))) = { INIT_THREAD_INFO(init_task) }; /* diff --git a/trunk/arch/arm/kernel/module.c b/trunk/arch/arm/kernel/module.c index 79b7e5cf5416..1b061583408e 100644 --- a/trunk/arch/arm/kernel/module.c +++ b/trunk/arch/arm/kernel/module.c @@ -116,8 +116,8 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, offset += sym->st_value - loc; if (offset & 3 || - offset <= (s32)0xfe000000 || - offset >= (s32)0x02000000) { + offset <= (s32)0xfc000000 || + offset >= (s32)0x04000000) { printk(KERN_ERR "%s: relocation out of range, section " "%d reloc %d sym '%s'\n", module->name, diff --git a/trunk/arch/arm/kernel/smp.c b/trunk/arch/arm/kernel/smp.c index 1b76d87fa335..070bcb7a6306 100644 --- a/trunk/arch/arm/kernel/smp.c +++ b/trunk/arch/arm/kernel/smp.c @@ -486,7 +486,7 @@ static void ipi_timer(void) } #ifdef CONFIG_LOCAL_TIMERS -asmlinkage void __exception do_local_timer(struct pt_regs *regs) +asmlinkage void do_local_timer(struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); int cpu = smp_processor_id(); @@ -551,7 +551,7 @@ static void ipi_cpu_stop(unsigned int cpu) * * Bit 0 - Inter-processor function call */ -asmlinkage void __exception do_IPI(struct pt_regs *regs) +asmlinkage void do_IPI(struct pt_regs *regs) { unsigned int cpu = smp_processor_id(); struct ipi_data *ipi = &per_cpu(ipi_data, cpu); diff --git a/trunk/arch/arm/kernel/vmlinux.lds.S b/trunk/arch/arm/kernel/vmlinux.lds.S index e4156e7868ce..6be67296f333 100644 --- a/trunk/arch/arm/kernel/vmlinux.lds.S +++ b/trunk/arch/arm/kernel/vmlinux.lds.S @@ -23,15 +23,11 @@ SECTIONS #else . = PAGE_OFFSET + TEXT_OFFSET; #endif - .text.head : { - _stext = .; - _sinittext = .; - *(.text.head) - } - .init : { /* Init code and data */ + _stext = .; + _sinittext = .; *(.init.text) - _einittext = .; + _einittext = .; __proc_info_begin = .; *(.proc.info.init) __proc_info_end = .; @@ -123,7 +119,7 @@ SECTIONS * first, the init task union, aligned * to an 8192 byte boundary. */ - *(.data.init_task) + *(.init.task) #ifdef CONFIG_XIP_KERNEL . = ALIGN(4096); diff --git a/trunk/arch/arm/mach-at91/Kconfig b/trunk/arch/arm/mach-at91/Kconfig index 018d637f87fc..e238ad8cfd8f 100644 --- a/trunk/arch/arm/mach-at91/Kconfig +++ b/trunk/arch/arm/mach-at91/Kconfig @@ -107,7 +107,7 @@ config ARCH_AT91SAM9260_SAM9XE depends on ARCH_AT91SAM9260 help Select this if you are using Atmel's AT91SAM9XE System-on-Chip. - They are basically AT91SAM9260s with various sizes of embedded Flash. + They are basicaly AT91SAM9260s with various sizes of embedded Flash. comment "AT91SAM9260 / AT91SAM9XE Board Type" diff --git a/trunk/arch/arm/mach-omap1/Kconfig b/trunk/arch/arm/mach-omap1/Kconfig index 856c681ebbbc..8781aaeb576b 100644 --- a/trunk/arch/arm/mach-omap1/Kconfig +++ b/trunk/arch/arm/mach-omap1/Kconfig @@ -22,7 +22,6 @@ comment "OMAP Board Type" config MACH_OMAP_INNOVATOR bool "TI Innovator" depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX) - select OMAP_MCBSP help TI OMAP 1510 or 1610 Innovator board support. Say Y here if you have such a board. @@ -30,7 +29,6 @@ config MACH_OMAP_INNOVATOR config MACH_OMAP_H2 bool "TI H2 Support" depends on ARCH_OMAP1 && ARCH_OMAP16XX - select OMAP_MCBSP help TI OMAP 1610/1611B H2 board support. Say Y here if you have such a board. @@ -38,7 +36,6 @@ config MACH_OMAP_H2 config MACH_OMAP_H3 bool "TI H3 Support" depends on ARCH_OMAP1 && ARCH_OMAP16XX - select GPIOEXPANDER_OMAP help TI OMAP 1710 H3 board support. Say Y here if you have such a board. @@ -46,7 +43,7 @@ config MACH_OMAP_H3 config MACH_OMAP_OSK bool "TI OSK Support" depends on ARCH_OMAP1 && ARCH_OMAP16XX - select OMAP_MCBSP + select TPS65010 help TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here if you have such a board. @@ -87,7 +84,7 @@ config MACH_OMAP_PALMTE Support for the Palm Tungsten E PDA. Currently only the LCD panel is supported. To boot the kernel, you'll need a PalmOS compatible bootloader; check out http://palmtelinux.sourceforge.net for more - information. + informations. Say Y here if you have such a PDA, say NO otherwise. config MACH_NOKIA770 diff --git a/trunk/arch/arm/mach-omap1/Makefile b/trunk/arch/arm/mach-omap1/Makefile index a8b9a00cea22..7165f74f78da 100644 --- a/trunk/arch/arm/mach-omap1/Makefile +++ b/trunk/arch/arm/mach-omap1/Makefile @@ -37,3 +37,4 @@ led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o led-$(CONFIG_MACH_OMAP_OSK) += leds-osk.o obj-$(CONFIG_LEDS) += $(led-y) + diff --git a/trunk/arch/arm/mach-omap1/board-fsample.c b/trunk/arch/arm/mach-omap1/board-fsample.c index f65baa95986e..62e42c7a628e 100644 --- a/trunk/arch/arm/mach-omap1/board-fsample.c +++ b/trunk/arch/arm/mach-omap1/board-fsample.c @@ -246,7 +246,7 @@ static void __init fsample_init_smc91x(void) mdelay(50); } -static void __init omap_fsample_init_irq(void) +void omap_fsample_init_irq(void) { omap1_init_common_hw(); omap_init_irq(); diff --git a/trunk/arch/arm/mach-omap1/board-h3.c b/trunk/arch/arm/mach-omap1/board-h3.c index 7b260b7c537b..9d2346fb68f4 100644 --- a/trunk/arch/arm/mach-omap1/board-h3.c +++ b/trunk/arch/arm/mach-omap1/board-h3.c @@ -455,7 +455,7 @@ static void __init h3_init_smc91x(void) } } -static void __init h3_init_irq(void) +void h3_init_irq(void) { omap1_init_common_hw(); omap_init_irq(); diff --git a/trunk/arch/arm/mach-omap1/board-innovator.c b/trunk/arch/arm/mach-omap1/board-innovator.c index 7e63a41e37c6..cb00530ad279 100644 --- a/trunk/arch/arm/mach-omap1/board-innovator.c +++ b/trunk/arch/arm/mach-omap1/board-innovator.c @@ -308,7 +308,7 @@ static void __init innovator_init_smc91x(void) } } -static void __init innovator_init_irq(void) +void innovator_init_irq(void) { omap1_init_common_hw(); omap_init_irq(); diff --git a/trunk/arch/arm/mach-omap1/board-perseus2.c b/trunk/arch/arm/mach-omap1/board-perseus2.c index 1d5c8d509722..fa4be962df67 100644 --- a/trunk/arch/arm/mach-omap1/board-perseus2.c +++ b/trunk/arch/arm/mach-omap1/board-perseus2.c @@ -246,7 +246,7 @@ static void __init perseus2_init_smc91x(void) mdelay(50); } -static void __init omap_perseus2_init_irq(void) +void omap_perseus2_init_irq(void) { omap1_init_common_hw(); omap_init_irq(); diff --git a/trunk/arch/arm/mach-omap1/devices.c b/trunk/arch/arm/mach-omap1/devices.c index da8a3ac47e13..6dcd10ab4496 100644 --- a/trunk/arch/arm/mach-omap1/devices.c +++ b/trunk/arch/arm/mach-omap1/devices.c @@ -24,6 +24,35 @@ #include #include +#if defined(CONFIG_OMAP1610_IR) || defined(CONFIG_OMAP161O_IR_MODULE) + +static u64 irda_dmamask = 0xffffffff; + +static struct platform_device omap1610ir_device = { + .name = "omap1610-ir", + .id = -1, + .dev = { + .dma_mask = &irda_dmamask, + }, +}; + +static void omap_init_irda(void) +{ + /* FIXME define and use a boot tag, members something like: + * u8 uart; // uart1, or uart3 + * ... but driver only handles uart3 for now + * s16 fir_sel; // gpio for SIR vs FIR + * ... may prefer a callback for SIR/MIR/FIR mode select; + * while h2 uses a GPIO, H3 uses a gpio expander + */ + if (machine_is_omap_h2() + || machine_is_omap_h3()) + (void) platform_device_register(&omap1610ir_device); +} +#else +static inline void omap_init_irda(void) {} +#endif + /*-------------------------------------------------------------------------*/ #if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE) @@ -61,45 +90,6 @@ static void omap_init_rtc(void) static inline void omap_init_rtc(void) {} #endif -#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) - -#if defined(CONFIG_ARCH_OMAP15XX) -# define OMAP1_MBOX_SIZE 0x23 -# define INT_DSP_MAILBOX1 INT_1510_DSP_MAILBOX1 -#elif defined(CONFIG_ARCH_OMAP16XX) -# define OMAP1_MBOX_SIZE 0x2f -# define INT_DSP_MAILBOX1 INT_1610_DSP_MAILBOX1 -#endif - -#define OMAP1_MBOX_BASE IO_ADDRESS(OMAP16XX_MAILBOX_BASE) - -static struct resource mbox_resources[] = { - { - .start = OMAP1_MBOX_BASE, - .end = OMAP1_MBOX_BASE + OMAP1_MBOX_SIZE, - .flags = IORESOURCE_MEM, - }, - { - .start = INT_DSP_MAILBOX1, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device mbox_device = { - .name = "mailbox", - .id = -1, - .num_resources = ARRAY_SIZE(mbox_resources), - .resource = mbox_resources, -}; - -static inline void omap_init_mbox(void) -{ - platform_device_register(&mbox_device); -} -#else -static inline void omap_init_mbox(void) { } -#endif - #if defined(CONFIG_OMAP_STI) #define OMAP1_STI_BASE IO_ADDRESS(0xfffea000) @@ -164,8 +154,7 @@ static int __init omap1_init_devices(void) /* please keep these calls, and their implementations above, * in alphabetical order so they're easier to sort through. */ - - omap_init_mbox(); + omap_init_irda(); omap_init_rtc(); omap_init_sti(); diff --git a/trunk/arch/arm/mach-omap1/io.c b/trunk/arch/arm/mach-omap1/io.c index 81c4e738506c..fab8b0b27cfb 100644 --- a/trunk/arch/arm/mach-omap1/io.c +++ b/trunk/arch/arm/mach-omap1/io.c @@ -17,11 +17,11 @@ #include #include #include +#include extern int omap1_clk_init(void); extern void omap_check_revision(void); extern void omap_sram_init(void); -extern void omapfb_reserve_sdram(void); /* * The machine specific code may provide the extra mapping besides the @@ -121,7 +121,7 @@ void __init omap1_map_common_io(void) #endif omap_sram_init(); - omapfb_reserve_sdram(); + omapfb_reserve_mem(); } /* diff --git a/trunk/arch/arm/mach-omap1/mailbox.c b/trunk/arch/arm/mach-omap1/mailbox.c deleted file mode 100644 index d3abf5609902..000000000000 --- a/trunk/arch/arm/mach-omap1/mailbox.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Mailbox reservation modules for DSP - * - * Copyright (C) 2006 Nokia Corporation - * Written by: Hiroshi DOYU - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define MAILBOX_ARM2DSP1 0x00 -#define MAILBOX_ARM2DSP1b 0x04 -#define MAILBOX_DSP2ARM1 0x08 -#define MAILBOX_DSP2ARM1b 0x0c -#define MAILBOX_DSP2ARM2 0x10 -#define MAILBOX_DSP2ARM2b 0x14 -#define MAILBOX_ARM2DSP1_Flag 0x18 -#define MAILBOX_DSP2ARM1_Flag 0x1c -#define MAILBOX_DSP2ARM2_Flag 0x20 - -unsigned long mbox_base; - -struct omap_mbox1_fifo { - unsigned long cmd; - unsigned long data; - unsigned long flag; -}; - -struct omap_mbox1_priv { - struct omap_mbox1_fifo tx_fifo; - struct omap_mbox1_fifo rx_fifo; -}; - -static inline int mbox_read_reg(unsigned int reg) -{ - return __raw_readw(mbox_base + reg); -} - -static inline void mbox_write_reg(unsigned int val, unsigned int reg) -{ - __raw_writew(val, mbox_base + reg); -} - -/* msg */ -static inline mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox) -{ - struct omap_mbox1_fifo *fifo = - &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo; - mbox_msg_t msg; - - msg = mbox_read_reg(fifo->data); - msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16; - - return msg; -} - -static inline void -omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) -{ - struct omap_mbox1_fifo *fifo = - &((struct omap_mbox1_priv *)mbox->priv)->tx_fifo; - - mbox_write_reg(msg & 0xffff, fifo->data); - mbox_write_reg(msg >> 16, fifo->cmd); -} - -static inline int omap1_mbox_fifo_empty(struct omap_mbox *mbox) -{ - return 0; -} - -static inline int omap1_mbox_fifo_full(struct omap_mbox *mbox) -{ - struct omap_mbox1_fifo *fifo = - &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo; - - return (mbox_read_reg(fifo->flag)); -} - -/* irq */ -static inline void -omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) -{ - if (irq == IRQ_RX) - enable_irq(mbox->irq); -} - -static inline void -omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) -{ - if (irq == IRQ_RX) - disable_irq(mbox->irq); -} - -static inline int -omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) -{ - if (irq == IRQ_TX) - return 0; - return 1; -} - -static struct omap_mbox_ops omap1_mbox_ops = { - .type = OMAP_MBOX_TYPE1, - .fifo_read = omap1_mbox_fifo_read, - .fifo_write = omap1_mbox_fifo_write, - .fifo_empty = omap1_mbox_fifo_empty, - .fifo_full = omap1_mbox_fifo_full, - .enable_irq = omap1_mbox_enable_irq, - .disable_irq = omap1_mbox_disable_irq, - .is_irq = omap1_mbox_is_irq, -}; - -/* FIXME: the following struct should be created automatically by the user id */ - -/* DSP */ -static struct omap_mbox1_priv omap1_mbox_dsp_priv = { - .tx_fifo = { - .cmd = MAILBOX_ARM2DSP1b, - .data = MAILBOX_ARM2DSP1, - .flag = MAILBOX_ARM2DSP1_Flag, - }, - .rx_fifo = { - .cmd = MAILBOX_DSP2ARM1b, - .data = MAILBOX_DSP2ARM1, - .flag = MAILBOX_DSP2ARM1_Flag, - }, -}; - -struct omap_mbox mbox_dsp_info = { - .name = "dsp", - .ops = &omap1_mbox_ops, - .priv = &omap1_mbox_dsp_priv, -}; -EXPORT_SYMBOL(mbox_dsp_info); - -static int __init omap1_mbox_probe(struct platform_device *pdev) -{ - struct resource *res; - int ret = 0; - - if (pdev->num_resources != 2) { - dev_err(&pdev->dev, "invalid number of resources: %d\n", - pdev->num_resources); - return -ENODEV; - } - - /* MBOX base */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (unlikely(!res)) { - dev_err(&pdev->dev, "invalid mem resource\n"); - return -ENODEV; - } - mbox_base = res->start; - - /* DSP IRQ */ - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (unlikely(!res)) { - dev_err(&pdev->dev, "invalid irq resource\n"); - return -ENODEV; - } - mbox_dsp_info.irq = res->start; - - ret = omap_mbox_register(&mbox_dsp_info); - - return ret; -} - -static int omap1_mbox_remove(struct platform_device *pdev) -{ - omap_mbox_unregister(&mbox_dsp_info); - - return 0; -} - -static struct platform_driver omap1_mbox_driver = { - .probe = omap1_mbox_probe, - .remove = omap1_mbox_remove, - .driver = { - .name = "mailbox", - }, -}; - -static int __init omap1_mbox_init(void) -{ - return platform_driver_register(&omap1_mbox_driver); -} - -static void __exit omap1_mbox_exit(void) -{ - platform_driver_unregister(&omap1_mbox_driver); -} - -module_init(omap1_mbox_init); -module_exit(omap1_mbox_exit); - -MODULE_LICENSE("GPL"); diff --git a/trunk/arch/arm/mach-omap2/Kconfig b/trunk/arch/arm/mach-omap2/Kconfig index 7393109f5c30..aab97ccf1e63 100644 --- a/trunk/arch/arm/mach-omap2/Kconfig +++ b/trunk/arch/arm/mach-omap2/Kconfig @@ -9,7 +9,6 @@ config ARCH_OMAP2420 bool "OMAP2420 support" depends on ARCH_OMAP24XX select OMAP_DM_TIMER - select ARCH_OMAP_OTG comment "OMAP Board Type" depends on ARCH_OMAP2 @@ -21,7 +20,6 @@ config MACH_OMAP_GENERIC config MACH_OMAP_H4 bool "OMAP 2420 H4 board" depends on ARCH_OMAP2 && ARCH_OMAP24XX - select OMAP_DEBUG_LEDS if LEDS || LEDS_OMAP_DEBUG config MACH_OMAP_APOLLON bool "OMAP 2420 Apollon board" diff --git a/trunk/arch/arm/mach-omap2/board-h4.c b/trunk/arch/arm/mach-omap2/board-h4.c index 452193f01531..1e7ed6d22ca9 100644 --- a/trunk/arch/arm/mach-omap2/board-h4.c +++ b/trunk/arch/arm/mach-omap2/board-h4.c @@ -266,26 +266,12 @@ static struct platform_device h4_lcd_device = { .id = -1, }; -static struct resource h4_led_resources[] = { - [0] = { - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device h4_led_device = { - .name = "omap_dbg_led", - .id = -1, - .num_resources = ARRAY_SIZE(h4_led_resources), - .resource = h4_led_resources, -}; - static struct platform_device *h4_devices[] __initdata = { &h4_smc91x_device, &h4_flash_device, &h4_irda_device, &h4_kp_device, &h4_lcd_device, - &h4_led_device, }; static inline void __init h4_init_smc91x(void) diff --git a/trunk/arch/arm/mach-omap2/devices.c b/trunk/arch/arm/mach-omap2/devices.c index 52ec2f2d6360..aa4322451e8b 100644 --- a/trunk/arch/arm/mach-omap2/devices.c +++ b/trunk/arch/arm/mach-omap2/devices.c @@ -24,7 +24,7 @@ #include #include -#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) +#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) #define OMAP2_I2C_BASE2 0x48072000 #define OMAP2_I2C_INT2 57 @@ -42,8 +42,8 @@ static struct resource i2c_resources2[] = { }; static struct platform_device omap_i2c_device2 = { - .name = "i2c_omap", - .id = 2, + .name = "i2c_omap", + .id = 2, .num_resources = ARRAY_SIZE(i2c_resources2), .resource = i2c_resources2, }; @@ -66,40 +66,6 @@ static void omap_init_i2c(void) {} #endif -#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) -#define OMAP2_MBOX_BASE IO_ADDRESS(OMAP24XX_MAILBOX_BASE) - -static struct resource mbox_resources[] = { - { - .start = OMAP2_MBOX_BASE, - .end = OMAP2_MBOX_BASE + 0x11f, - .flags = IORESOURCE_MEM, - }, - { - .start = INT_24XX_MAIL_U0_MPU, - .flags = IORESOURCE_IRQ, - }, - { - .start = INT_24XX_MAIL_U3_MPU, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device mbox_device = { - .name = "mailbox", - .id = -1, - .num_resources = ARRAY_SIZE(mbox_resources), - .resource = mbox_resources, -}; - -static inline void omap_init_mbox(void) -{ - platform_device_register(&mbox_device); -} -#else -static inline void omap_init_mbox(void) { } -#endif - #if defined(CONFIG_OMAP_STI) #define OMAP2_STI_BASE IO_ADDRESS(0x48068000) @@ -145,45 +111,29 @@ static inline void omap_init_sti(void) {} #define OMAP2_MCSPI1_BASE 0x48098000 #define OMAP2_MCSPI2_BASE 0x4809a000 +/* FIXME: use resources instead */ + static struct omap2_mcspi_platform_config omap2_mcspi1_config = { + .base = io_p2v(OMAP2_MCSPI1_BASE), .num_cs = 4, }; -static struct resource omap2_mcspi1_resources[] = { - { - .start = OMAP2_MCSPI1_BASE, - .end = OMAP2_MCSPI1_BASE + 0xff, - .flags = IORESOURCE_MEM, - }, -}; - struct platform_device omap2_mcspi1 = { .name = "omap2_mcspi", .id = 1, - .num_resources = ARRAY_SIZE(omap2_mcspi1_resources), - .resource = omap2_mcspi1_resources, .dev = { .platform_data = &omap2_mcspi1_config, }, }; static struct omap2_mcspi_platform_config omap2_mcspi2_config = { + .base = io_p2v(OMAP2_MCSPI2_BASE), .num_cs = 2, }; -static struct resource omap2_mcspi2_resources[] = { - { - .start = OMAP2_MCSPI2_BASE, - .end = OMAP2_MCSPI2_BASE + 0xff, - .flags = IORESOURCE_MEM, - }, -}; - struct platform_device omap2_mcspi2 = { .name = "omap2_mcspi", .id = 2, - .num_resources = ARRAY_SIZE(omap2_mcspi2_resources), - .resource = omap2_mcspi2_resources, .dev = { .platform_data = &omap2_mcspi2_config, }, @@ -207,10 +157,10 @@ static int __init omap2_init_devices(void) * in alphabetical order so they're easier to sort through. */ omap_init_i2c(); - omap_init_mbox(); omap_init_mcspi(); omap_init_sti(); return 0; } arch_initcall(omap2_init_devices); + diff --git a/trunk/arch/arm/mach-omap2/gpmc.c b/trunk/arch/arm/mach-omap2/gpmc.c index 54c836a98456..d8f57824423f 100644 --- a/trunk/arch/arm/mach-omap2/gpmc.c +++ b/trunk/arch/arm/mach-omap2/gpmc.c @@ -246,22 +246,14 @@ static int gpmc_cs_mem_enabled(int cs) return l & (1 << 6); } -int gpmc_cs_set_reserved(int cs, int reserved) +static void gpmc_cs_set_reserved(int cs, int reserved) { - if (cs > GPMC_CS_NUM) - return -ENODEV; - gpmc_cs_map &= ~(1 << cs); gpmc_cs_map |= (reserved ? 1 : 0) << cs; - - return 0; } -int gpmc_cs_reserved(int cs) +static int gpmc_cs_reserved(int cs) { - if (cs > GPMC_CS_NUM) - return -ENODEV; - return gpmc_cs_map & (1 << cs); } diff --git a/trunk/arch/arm/mach-omap2/io.c b/trunk/arch/arm/mach-omap2/io.c index 82dc70f6b779..a0728c33e5d9 100644 --- a/trunk/arch/arm/mach-omap2/io.c +++ b/trunk/arch/arm/mach-omap2/io.c @@ -27,7 +27,6 @@ extern void omap_sram_init(void); extern int omap2_clk_init(void); extern void omap2_check_revision(void); extern void gpmc_init(void); -extern void omapfb_reserve_sdram(void); /* * The machine specific code may provide the extra mapping besides the @@ -41,21 +40,9 @@ static struct map_desc omap2_io_desc[] __initdata = { .type = MT_DEVICE }, { - .virtual = DSP_MEM_24XX_VIRT, - .pfn = __phys_to_pfn(DSP_MEM_24XX_PHYS), - .length = DSP_MEM_24XX_SIZE, - .type = MT_DEVICE - }, - { - .virtual = DSP_IPI_24XX_VIRT, - .pfn = __phys_to_pfn(DSP_IPI_24XX_PHYS), - .length = DSP_IPI_24XX_SIZE, - .type = MT_DEVICE - }, - { - .virtual = DSP_MMU_24XX_VIRT, - .pfn = __phys_to_pfn(DSP_MMU_24XX_PHYS), - .length = DSP_MMU_24XX_SIZE, + .virtual = L4_24XX_VIRT, + .pfn = __phys_to_pfn(L4_24XX_PHYS), + .length = L4_24XX_SIZE, .type = MT_DEVICE } }; @@ -73,7 +60,7 @@ void __init omap2_map_common_io(void) omap2_check_revision(); omap_sram_init(); - omapfb_reserve_sdram(); + omapfb_reserve_mem(); } void __init omap2_init_common_hw(void) diff --git a/trunk/arch/arm/mach-omap2/mailbox.c b/trunk/arch/arm/mach-omap2/mailbox.c deleted file mode 100644 index b03cd06e055b..000000000000 --- a/trunk/arch/arm/mach-omap2/mailbox.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Mailbox reservation modules for OMAP2 - * - * Copyright (C) 2006 Nokia Corporation - * Written by: Hiroshi DOYU - * and Paul Mundt - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define MAILBOX_REVISION 0x00 -#define MAILBOX_SYSCONFIG 0x10 -#define MAILBOX_SYSSTATUS 0x14 -#define MAILBOX_MESSAGE_0 0x40 -#define MAILBOX_MESSAGE_1 0x44 -#define MAILBOX_MESSAGE_2 0x48 -#define MAILBOX_MESSAGE_3 0x4c -#define MAILBOX_MESSAGE_4 0x50 -#define MAILBOX_MESSAGE_5 0x54 -#define MAILBOX_FIFOSTATUS_0 0x80 -#define MAILBOX_FIFOSTATUS_1 0x84 -#define MAILBOX_FIFOSTATUS_2 0x88 -#define MAILBOX_FIFOSTATUS_3 0x8c -#define MAILBOX_FIFOSTATUS_4 0x90 -#define MAILBOX_FIFOSTATUS_5 0x94 -#define MAILBOX_MSGSTATUS_0 0xc0 -#define MAILBOX_MSGSTATUS_1 0xc4 -#define MAILBOX_MSGSTATUS_2 0xc8 -#define MAILBOX_MSGSTATUS_3 0xcc -#define MAILBOX_MSGSTATUS_4 0xd0 -#define MAILBOX_MSGSTATUS_5 0xd4 -#define MAILBOX_IRQSTATUS_0 0x100 -#define MAILBOX_IRQENABLE_0 0x104 -#define MAILBOX_IRQSTATUS_1 0x108 -#define MAILBOX_IRQENABLE_1 0x10c -#define MAILBOX_IRQSTATUS_2 0x110 -#define MAILBOX_IRQENABLE_2 0x114 -#define MAILBOX_IRQSTATUS_3 0x118 -#define MAILBOX_IRQENABLE_3 0x11c - -static unsigned long mbox_base; - -#define MAILBOX_IRQ_NOTFULL(n) (1 << (2 * (n) + 1)) -#define MAILBOX_IRQ_NEWMSG(n) (1 << (2 * (n))) - -struct omap_mbox2_fifo { - unsigned long msg; - unsigned long fifo_stat; - unsigned long msg_stat; -}; - -struct omap_mbox2_priv { - struct omap_mbox2_fifo tx_fifo; - struct omap_mbox2_fifo rx_fifo; - unsigned long irqenable; - unsigned long irqstatus; - u32 newmsg_bit; - u32 notfull_bit; -}; - -static struct clk *mbox_ick_handle; - -static inline unsigned int mbox_read_reg(unsigned int reg) -{ - return __raw_readl(mbox_base + reg); -} - -static inline void mbox_write_reg(unsigned int val, unsigned int reg) -{ - __raw_writel(val, mbox_base + reg); -} - -/* Mailbox H/W preparations */ -static inline int omap2_mbox_startup(struct omap_mbox *mbox) -{ - unsigned int l; - - mbox_ick_handle = clk_get(NULL, "mailboxes_ick"); - if (IS_ERR(mbox_ick_handle)) { - printk("Could not get mailboxes_ick\n"); - return -ENODEV; - } - clk_enable(mbox_ick_handle); - - /* set smart-idle & autoidle */ - l = mbox_read_reg(MAILBOX_SYSCONFIG); - l |= 0x00000011; - mbox_write_reg(l, MAILBOX_SYSCONFIG); - - return 0; -} - -static inline void omap2_mbox_shutdown(struct omap_mbox *mbox) -{ - clk_disable(mbox_ick_handle); - clk_put(mbox_ick_handle); -} - -/* Mailbox FIFO handle functions */ -static inline mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox) -{ - struct omap_mbox2_fifo *fifo = - &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo; - return (mbox_msg_t) mbox_read_reg(fifo->msg); -} - -static inline void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) -{ - struct omap_mbox2_fifo *fifo = - &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo; - mbox_write_reg(msg, fifo->msg); -} - -static inline int omap2_mbox_fifo_empty(struct omap_mbox *mbox) -{ - struct omap_mbox2_fifo *fifo = - &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo; - return (mbox_read_reg(fifo->msg_stat) == 0); -} - -static inline int omap2_mbox_fifo_full(struct omap_mbox *mbox) -{ - struct omap_mbox2_fifo *fifo = - &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo; - return (mbox_read_reg(fifo->fifo_stat)); -} - -/* Mailbox IRQ handle functions */ -static inline void omap2_mbox_enable_irq(struct omap_mbox *mbox, - omap_mbox_type_t irq) -{ - struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; - u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; - - l = mbox_read_reg(p->irqenable); - l |= bit; - mbox_write_reg(l, p->irqenable); -} - -static inline void omap2_mbox_disable_irq(struct omap_mbox *mbox, - omap_mbox_type_t irq) -{ - struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; - u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; - - l = mbox_read_reg(p->irqenable); - l &= ~bit; - mbox_write_reg(l, p->irqenable); -} - -static inline void omap2_mbox_ack_irq(struct omap_mbox *mbox, - omap_mbox_type_t irq) -{ - struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; - u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; - - mbox_write_reg(bit, p->irqstatus); -} - -static inline int omap2_mbox_is_irq(struct omap_mbox *mbox, - omap_mbox_type_t irq) -{ - struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; - u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; - u32 enable = mbox_read_reg(p->irqenable); - u32 status = mbox_read_reg(p->irqstatus); - - return (enable & status & bit); -} - -static struct omap_mbox_ops omap2_mbox_ops = { - .type = OMAP_MBOX_TYPE2, - .startup = omap2_mbox_startup, - .shutdown = omap2_mbox_shutdown, - .fifo_read = omap2_mbox_fifo_read, - .fifo_write = omap2_mbox_fifo_write, - .fifo_empty = omap2_mbox_fifo_empty, - .fifo_full = omap2_mbox_fifo_full, - .enable_irq = omap2_mbox_enable_irq, - .disable_irq = omap2_mbox_disable_irq, - .ack_irq = omap2_mbox_ack_irq, - .is_irq = omap2_mbox_is_irq, -}; - -/* - * MAILBOX 0: ARM -> DSP, - * MAILBOX 1: ARM <- DSP. - * MAILBOX 2: ARM -> IVA, - * MAILBOX 3: ARM <- IVA. - */ - -/* FIXME: the following structs should be filled automatically by the user id */ - -/* DSP */ -static struct omap_mbox2_priv omap2_mbox_dsp_priv = { - .tx_fifo = { - .msg = MAILBOX_MESSAGE_0, - .fifo_stat = MAILBOX_FIFOSTATUS_0, - }, - .rx_fifo = { - .msg = MAILBOX_MESSAGE_1, - .msg_stat = MAILBOX_MSGSTATUS_1, - }, - .irqenable = MAILBOX_IRQENABLE_0, - .irqstatus = MAILBOX_IRQSTATUS_0, - .notfull_bit = MAILBOX_IRQ_NOTFULL(0), - .newmsg_bit = MAILBOX_IRQ_NEWMSG(1), -}; - -struct omap_mbox mbox_dsp_info = { - .name = "dsp", - .ops = &omap2_mbox_ops, - .priv = &omap2_mbox_dsp_priv, -}; -EXPORT_SYMBOL(mbox_dsp_info); - -/* IVA */ -static struct omap_mbox2_priv omap2_mbox_iva_priv = { - .tx_fifo = { - .msg = MAILBOX_MESSAGE_2, - .fifo_stat = MAILBOX_FIFOSTATUS_2, - }, - .rx_fifo = { - .msg = MAILBOX_MESSAGE_3, - .msg_stat = MAILBOX_MSGSTATUS_3, - }, - .irqenable = MAILBOX_IRQENABLE_3, - .irqstatus = MAILBOX_IRQSTATUS_3, - .notfull_bit = MAILBOX_IRQ_NOTFULL(2), - .newmsg_bit = MAILBOX_IRQ_NEWMSG(3), -}; - -static struct omap_mbox mbox_iva_info = { - .name = "iva", - .ops = &omap2_mbox_ops, - .priv = &omap2_mbox_iva_priv, -}; - -static int __init omap2_mbox_probe(struct platform_device *pdev) -{ - struct resource *res; - int ret = 0; - - if (pdev->num_resources != 3) { - dev_err(&pdev->dev, "invalid number of resources: %d\n", - pdev->num_resources); - return -ENODEV; - } - - /* MBOX base */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (unlikely(!res)) { - dev_err(&pdev->dev, "invalid mem resource\n"); - return -ENODEV; - } - mbox_base = res->start; - - /* DSP IRQ */ - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (unlikely(!res)) { - dev_err(&pdev->dev, "invalid irq resource\n"); - return -ENODEV; - } - mbox_dsp_info.irq = res->start; - - ret = omap_mbox_register(&mbox_dsp_info); - - /* IVA IRQ */ - res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); - if (unlikely(!res)) { - dev_err(&pdev->dev, "invalid irq resource\n"); - return -ENODEV; - } - mbox_iva_info.irq = res->start; - - ret = omap_mbox_register(&mbox_iva_info); - - return ret; -} - -static int omap2_mbox_remove(struct platform_device *pdev) -{ - omap_mbox_unregister(&mbox_dsp_info); - return 0; -} - -static struct platform_driver omap2_mbox_driver = { - .probe = omap2_mbox_probe, - .remove = omap2_mbox_remove, - .driver = { - .name = "mailbox", - }, -}; - -static int __init omap2_mbox_init(void) -{ - return platform_driver_register(&omap2_mbox_driver); -} - -static void __exit omap2_mbox_exit(void) -{ - platform_driver_unregister(&omap2_mbox_driver); -} - -module_init(omap2_mbox_init); -module_exit(omap2_mbox_exit); - -MODULE_LICENSE("GPL"); diff --git a/trunk/arch/arm/mach-s3c2410/sleep.S b/trunk/arch/arm/mach-s3c2410/sleep.S index d1eeed2ad47c..637aaba65390 100644 --- a/trunk/arch/arm/mach-s3c2410/sleep.S +++ b/trunk/arch/arm/mach-s3c2410/sleep.S @@ -1,4 +1,4 @@ -/* linux/arch/arm/mach-s3c2410/sleep.S +/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S * * Copyright (c) 2004 Simtec Electronics * Ben Dooks diff --git a/trunk/arch/arm/mm/Kconfig b/trunk/arch/arm/mm/Kconfig index b81391a4e374..e684e9b38216 100644 --- a/trunk/arch/arm/mm/Kconfig +++ b/trunk/arch/arm/mm/Kconfig @@ -366,19 +366,6 @@ config CPU_32v6K enabled will not boot on processors with do not support these instructions. -# ARMv7 -config CPU_V7 - bool "Support ARM V7 processor" - depends on ARCH_INTEGRATOR - select CPU_32v6K - select CPU_32v7 - select CPU_ABRT_EV7 - select CPU_CACHE_V7 - select CPU_CACHE_VIPT - select CPU_CP15_MMU - select CPU_COPY_V6 if MMU - select CPU_TLB_V6 if MMU - # Figure out what processor architecture version we should be using. # This defines the compiler instruction set which depends on the machine type. config CPU_32v3 @@ -404,9 +391,6 @@ config CPU_32v5 config CPU_32v6 bool -config CPU_32v7 - bool - # The abort model config CPU_ABRT_NOMMU bool @@ -429,9 +413,6 @@ config CPU_ABRT_EV5TJ config CPU_ABRT_EV6 bool -config CPU_ABRT_EV7 - bool - # The cache model config CPU_CACHE_V3 bool @@ -448,9 +429,6 @@ config CPU_CACHE_V4WB config CPU_CACHE_V6 bool -config CPU_CACHE_V7 - bool - config CPU_CACHE_VIVT bool @@ -525,7 +503,7 @@ comment "Processor Features" config ARM_THUMB bool "Support Thumb user binaries" - depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6 || CPU_V7 + depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6 default y help Say Y if you want to include kernel support for running user space @@ -600,15 +578,9 @@ config CPU_CACHE_ROUND_ROBIN Say Y here to use the predictable round-robin cache replacement policy. Unless you specifically require this or are unsure, say N. -config CPU_L2CACHE_DISABLE - bool "Disable level 2 cache" - depends on CPU_V7 - help - Say Y here to disable the level 2 cache. If unsure, say N. - config CPU_BPREDICT_DISABLE bool "Disable branch prediction" - depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3 || CPU_V7 + depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3 help Say Y here to disable branch prediction. If unsure, say N. diff --git a/trunk/arch/arm/mm/Makefile b/trunk/arch/arm/mm/Makefile index b5bd335ff14a..2f8b95947774 100644 --- a/trunk/arch/arm/mm/Makefile +++ b/trunk/arch/arm/mm/Makefile @@ -24,14 +24,12 @@ obj-$(CONFIG_CPU_ABRT_LV4T) += abort-lv4t.o obj-$(CONFIG_CPU_ABRT_EV5T) += abort-ev5t.o obj-$(CONFIG_CPU_ABRT_EV5TJ) += abort-ev5tj.o obj-$(CONFIG_CPU_ABRT_EV6) += abort-ev6.o -obj-$(CONFIG_CPU_ABRT_EV7) += abort-ev7.o obj-$(CONFIG_CPU_CACHE_V3) += cache-v3.o obj-$(CONFIG_CPU_CACHE_V4) += cache-v4.o obj-$(CONFIG_CPU_CACHE_V4WT) += cache-v4wt.o obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o -obj-$(CONFIG_CPU_CACHE_V7) += cache-v7.o obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o @@ -68,6 +66,5 @@ obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o obj-$(CONFIG_CPU_V6) += proc-v6.o -obj-$(CONFIG_CPU_V7) += proc-v7.o obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o diff --git a/trunk/arch/arm/mm/abort-ev7.S b/trunk/arch/arm/mm/abort-ev7.S deleted file mode 100644 index eb90bce38e14..000000000000 --- a/trunk/arch/arm/mm/abort-ev7.S +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include -/* - * Function: v7_early_abort - * - * Params : r2 = address of aborted instruction - * : r3 = saved SPSR - * - * Returns : r0 = address of abort - * : r1 = FSR, bit 11 = write - * : r2-r8 = corrupted - * : r9 = preserved - * : sp = pointer to registers - * - * Purpose : obtain information about current aborted instruction. - */ - .align 5 -ENTRY(v7_early_abort) - /* - * The effect of data aborts on on the exclusive access monitor are - * UNPREDICTABLE. Do a CLREX to clear the state - */ - clrex - - mrc p15, 0, r1, c5, c0, 0 @ get FSR - mrc p15, 0, r0, c6, c0, 0 @ get FAR - - /* - * V6 code adjusts the returned DFSR. - * New designs should not need to patch up faults. - */ - mov pc, lr diff --git a/trunk/arch/arm/mm/cache-v7.S b/trunk/arch/arm/mm/cache-v7.S deleted file mode 100644 index 35ffc4d95997..000000000000 --- a/trunk/arch/arm/mm/cache-v7.S +++ /dev/null @@ -1,253 +0,0 @@ -/* - * linux/arch/arm/mm/cache-v7.S - * - * Copyright (C) 2001 Deep Blue Solutions Ltd. - * Copyright (C) 2005 ARM Ltd. - * - * 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 the Free Software Foundation. - * - * This is the "shell" of the ARMv7 processor support. - */ -#include -#include -#include - -#include "proc-macros.S" - -/* - * v7_flush_dcache_all() - * - * Flush the whole D-cache. - * - * Corrupted registers: r0-r5, r7, r9-r11 - * - * - mm - mm_struct describing address space - */ -ENTRY(v7_flush_dcache_all) - mrc p15, 1, r0, c0, c0, 1 @ read clidr - ands r3, r0, #0x7000000 @ extract loc from clidr - mov r3, r3, lsr #23 @ left align loc bit field - beq finished @ if loc is 0, then no need to clean - mov r10, #0 @ start clean at cache level 0 -loop1: - add r2, r10, r10, lsr #1 @ work out 3x current cache level - mov r1, r0, lsr r2 @ extract cache type bits from clidr - and r1, r1, #7 @ mask of the bits for current cache only - cmp r1, #2 @ see what cache we have at this level - blt skip @ skip if no cache, or just i-cache - mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr - isb @ isb to sych the new cssr&csidr - mrc p15, 1, r1, c0, c0, 0 @ read the new csidr - and r2, r1, #7 @ extract the length of the cache lines - add r2, r2, #4 @ add 4 (line length offset) - ldr r4, =0x3ff - ands r4, r4, r1, lsr #3 @ find maximum number on the way size - clz r5, r4 @ find bit position of way size increment - ldr r7, =0x7fff - ands r7, r7, r1, lsr #13 @ extract max number of the index size -loop2: - mov r9, r4 @ create working copy of max way size -loop3: - orr r11, r10, r9, lsl r5 @ factor way and cache number into r11 - orr r11, r11, r7, lsl r2 @ factor index number into r11 - mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way - subs r9, r9, #1 @ decrement the way - bge loop3 - subs r7, r7, #1 @ decrement the index - bge loop2 -skip: - add r10, r10, #2 @ increment cache number - cmp r3, r10 - bgt loop1 -finished: - mov r10, #0 @ swith back to cache level 0 - mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr - isb - mov pc, lr - -/* - * v7_flush_cache_all() - * - * Flush the entire cache system. - * The data cache flush is now achieved using atomic clean / invalidates - * working outwards from L1 cache. This is done using Set/Way based cache - * maintainance instructions. - * The instruction cache can still be invalidated back to the point of - * unification in a single instruction. - * - */ -ENTRY(v7_flush_kern_cache_all) - stmfd sp!, {r4-r5, r7, r9-r11, lr} - bl v7_flush_dcache_all - mov r0, #0 - mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate - ldmfd sp!, {r4-r5, r7, r9-r11, lr} - mov pc, lr - -/* - * v7_flush_cache_all() - * - * Flush all TLB entries in a particular address space - * - * - mm - mm_struct describing address space - */ -ENTRY(v7_flush_user_cache_all) - /*FALLTHROUGH*/ - -/* - * v7_flush_cache_range(start, end, flags) - * - * Flush a range of TLB entries in the specified address space. - * - * - start - start address (may not be aligned) - * - end - end address (exclusive, may not be aligned) - * - flags - vm_area_struct flags describing address space - * - * It is assumed that: - * - we have a VIPT cache. - */ -ENTRY(v7_flush_user_cache_range) - mov pc, lr - -/* - * v7_coherent_kern_range(start,end) - * - * Ensure that the I and D caches are coherent within specified - * region. This is typically used when code has been written to - * a memory region, and will be executed. - * - * - start - virtual start address of region - * - end - virtual end address of region - * - * It is assumed that: - * - the Icache does not read data from the write buffer - */ -ENTRY(v7_coherent_kern_range) - /* FALLTHROUGH */ - -/* - * v7_coherent_user_range(start,end) - * - * Ensure that the I and D caches are coherent within specified - * region. This is typically used when code has been written to - * a memory region, and will be executed. - * - * - start - virtual start address of region - * - end - virtual end address of region - * - * It is assumed that: - * - the Icache does not read data from the write buffer - */ -ENTRY(v7_coherent_user_range) - dcache_line_size r2, r3 - sub r3, r2, #1 - bic r0, r0, r3 -1: mcr p15, 0, r0, c7, c11, 1 @ clean D line to the point of unification - dsb - mcr p15, 0, r0, c7, c5, 1 @ invalidate I line - add r0, r0, r2 - cmp r0, r1 - blo 1b - mov r0, #0 - mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB - dsb - isb - mov pc, lr - -/* - * v7_flush_kern_dcache_page(kaddr) - * - * Ensure that the data held in the page kaddr is written back - * to the page in question. - * - * - kaddr - kernel address (guaranteed to be page aligned) - */ -ENTRY(v7_flush_kern_dcache_page) - dcache_line_size r2, r3 - add r1, r0, #PAGE_SZ -1: - mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line / unified line - add r0, r0, r2 - cmp r0, r1 - blo 1b - dsb - mov pc, lr - -/* - * v7_dma_inv_range(start,end) - * - * Invalidate the data cache within the specified region; we will - * be performing a DMA operation in this region and we want to - * purge old data in the cache. - * - * - start - virtual start address of region - * - end - virtual end address of region - */ -ENTRY(v7_dma_inv_range) - dcache_line_size r2, r3 - sub r3, r2, #1 - tst r0, r3 - bic r0, r0, r3 - mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line - - tst r1, r3 - bic r1, r1, r3 - mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D / U line -1: - mcr p15, 0, r0, c7, c6, 1 @ invalidate D / U line - add r0, r0, r2 - cmp r0, r1 - blo 1b - dsb - mov pc, lr - -/* - * v7_dma_clean_range(start,end) - * - start - virtual start address of region - * - end - virtual end address of region - */ -ENTRY(v7_dma_clean_range) - dcache_line_size r2, r3 - sub r3, r2, #1 - bic r0, r0, r3 -1: - mcr p15, 0, r0, c7, c10, 1 @ clean D / U line - add r0, r0, r2 - cmp r0, r1 - blo 1b - dsb - mov pc, lr - -/* - * v7_dma_flush_range(start,end) - * - start - virtual start address of region - * - end - virtual end address of region - */ -ENTRY(v7_dma_flush_range) - dcache_line_size r2, r3 - sub r3, r2, #1 - bic r0, r0, r3 -1: - mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line - add r0, r0, r2 - cmp r0, r1 - blo 1b - dsb - mov pc, lr - - __INITDATA - - .type v7_cache_fns, #object -ENTRY(v7_cache_fns) - .long v7_flush_kern_cache_all - .long v7_flush_user_cache_all - .long v7_flush_user_cache_range - .long v7_coherent_kern_range - .long v7_coherent_user_range - .long v7_flush_kern_dcache_page - .long v7_dma_inv_range - .long v7_dma_clean_range - .long v7_dma_flush_range - .size v7_cache_fns, . - v7_cache_fns diff --git a/trunk/arch/arm/mm/context.c b/trunk/arch/arm/mm/context.c index fc84fcc74380..9da43a0fdcdf 100644 --- a/trunk/arch/arm/mm/context.c +++ b/trunk/arch/arm/mm/context.c @@ -14,8 +14,7 @@ #include #include -static DEFINE_SPINLOCK(cpu_asid_lock); -unsigned int cpu_last_asid = ASID_FIRST_VERSION; +unsigned int cpu_last_asid = { 1 << ASID_BITS }; /* * We fork()ed a process, and we need a new context for the child @@ -32,16 +31,15 @@ void __new_context(struct mm_struct *mm) { unsigned int asid; - spin_lock(&cpu_asid_lock); asid = ++cpu_last_asid; if (asid == 0) - asid = cpu_last_asid = ASID_FIRST_VERSION; + asid = cpu_last_asid = 1 << ASID_BITS; /* * If we've used up all our ASIDs, we need * to start a new version and flush the TLB. */ - if (unlikely((asid & ~ASID_MASK) == 0)) { + if ((asid & ~ASID_MASK) == 0) { asid = ++cpu_last_asid; /* set the reserved ASID before flushing the TLB */ asm("mcr p15, 0, %0, c13, c0, 1 @ set reserved context ID\n" @@ -49,16 +47,7 @@ void __new_context(struct mm_struct *mm) : "r" (0)); isb(); flush_tlb_all(); - if (icache_is_vivt_asid_tagged()) { - asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n" - "mcr p15, 0, %0, c7, c5, 6 @ flush BTAC/BTB\n" - : - : "r" (0)); - dsb(); - } } - spin_unlock(&cpu_asid_lock); - mm->cpu_vm_mask = cpumask_of_cpu(smp_processor_id()); mm->context.id = asid; } diff --git a/trunk/arch/arm/mm/proc-macros.S b/trunk/arch/arm/mm/proc-macros.S index b13150052a76..9e2c89eb2115 100644 --- a/trunk/arch/arm/mm/proc-macros.S +++ b/trunk/arch/arm/mm/proc-macros.S @@ -59,15 +59,3 @@ .word \ucset #endif .endm - -/* - * cache_line_size - get the cache line size from the CSIDR register - * (available on ARMv7+). It assumes that the CSSR register was configured - * to access the L1 data cache CSIDR. - */ - .macro dcache_line_size, reg, tmp - mrc p15, 1, \tmp, c0, c0, 0 @ read CSIDR - and \tmp, \tmp, #7 @ cache line size encoding - mov \reg, #16 @ size offset - mov \reg, \reg, lsl \tmp @ actual cache line size - .endm diff --git a/trunk/arch/arm/mm/proc-v7.S b/trunk/arch/arm/mm/proc-v7.S deleted file mode 100644 index dd823dd4a374..000000000000 --- a/trunk/arch/arm/mm/proc-v7.S +++ /dev/null @@ -1,262 +0,0 @@ -/* - * linux/arch/arm/mm/proc-v7.S - * - * Copyright (C) 2001 Deep Blue Solutions Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This is the "shell" of the ARMv7 processor support. - */ -#include -#include -#include -#include -#include -#include - -#include "proc-macros.S" - -#define TTB_C (1 << 0) -#define TTB_S (1 << 1) -#define TTB_RGN_OC_WT (2 << 3) -#define TTB_RGN_OC_WB (3 << 3) - -ENTRY(cpu_v7_proc_init) - mov pc, lr - -ENTRY(cpu_v7_proc_fin) - mov pc, lr - -/* - * cpu_v7_reset(loc) - * - * Perform a soft reset of the system. Put the CPU into the - * same state as it would be if it had been reset, and branch - * to what would be the reset vector. - * - * - loc - location to jump to for soft reset - * - * It is assumed that: - */ - .align 5 -ENTRY(cpu_v7_reset) - mov pc, r0 - -/* - * cpu_v7_do_idle() - * - * Idle the processor (eg, wait for interrupt). - * - * IRQs are already disabled. - */ -ENTRY(cpu_v7_do_idle) - .long 0xe320f003 @ ARM V7 WFI instruction - mov pc, lr - -ENTRY(cpu_v7_dcache_clean_area) -#ifndef TLB_CAN_READ_FROM_L1_CACHE - dcache_line_size r2, r3 -1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry - add r0, r0, r2 - subs r1, r1, r2 - bhi 1b - dsb -#endif - mov pc, lr - -/* - * cpu_v7_switch_mm(pgd_phys, tsk) - * - * Set the translation table base pointer to be pgd_phys - * - * - pgd_phys - physical address of new TTB - * - * It is assumed that: - * - we are not using split page tables - */ -ENTRY(cpu_v7_switch_mm) - mov r2, #0 - ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id - orr r0, r0, #TTB_RGN_OC_WB @ mark PTWs outer cacheable, WB - mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID - isb -1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 - isb - mcr p15, 0, r1, c13, c0, 1 @ set context ID - isb - mov pc, lr - -/* - * cpu_v7_set_pte_ext(ptep, pte) - * - * Set a level 2 translation table entry. - * - * - ptep - pointer to level 2 translation table entry - * (hardware version is stored at -1024 bytes) - * - pte - PTE value to store - * - ext - value for extended PTE bits - * - * Permissions: - * YUWD APX AP1 AP0 SVC User - * 0xxx 0 0 0 no acc no acc - * 100x 1 0 1 r/o no acc - * 10x0 1 0 1 r/o no acc - * 1011 0 0 1 r/w no acc - * 110x 0 1 0 r/w r/o - * 11x0 0 1 0 r/w r/o - * 1111 0 1 1 r/w r/w - */ -ENTRY(cpu_v7_set_pte_ext) - str r1, [r0], #-2048 @ linux version - - bic r3, r1, #0x000003f0 - bic r3, r3, #0x00000003 - orr r3, r3, r2 - orr r3, r3, #PTE_EXT_AP0 | 2 - - tst r1, #L_PTE_WRITE - tstne r1, #L_PTE_DIRTY - orreq r3, r3, #PTE_EXT_APX - - tst r1, #L_PTE_USER - orrne r3, r3, #PTE_EXT_AP1 - tstne r3, #PTE_EXT_APX - bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 - - tst r1, #L_PTE_YOUNG - biceq r3, r3, #PTE_EXT_APX | PTE_EXT_AP_MASK - - tst r1, #L_PTE_EXEC - orreq r3, r3, #PTE_EXT_XN - - tst r1, #L_PTE_PRESENT - moveq r3, #0 - - str r3, [r0] - mcr p15, 0, r0, c7, c10, 1 @ flush_pte - mov pc, lr - -cpu_v7_name: - .ascii "ARMv7 Processor" - .align - - .section ".text.init", #alloc, #execinstr - -/* - * __v7_setup - * - * Initialise TLB, Caches, and MMU state ready to switch the MMU - * on. Return in r0 the new CP15 C1 control register setting. - * - * We automatically detect if we have a Harvard cache, and use the - * Harvard cache control instructions insead of the unified cache - * control instructions. - * - * This should be able to cover all ARMv7 cores. - * - * It is assumed that: - * - cache type register is implemented - */ -__v7_setup: - adr r12, __v7_setup_stack @ the local stack - stmia r12, {r0-r5, r7, r9, r11, lr} - bl v7_flush_dcache_all - ldmia r12, {r0-r5, r7, r9, r11, lr} - mov r10, #0 -#ifdef HARVARD_CACHE - mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate -#endif - dsb - mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs - mcr p15, 0, r10, c2, c0, 2 @ TTB control register - orr r4, r4, #TTB_RGN_OC_WB @ mark PTWs outer cacheable, WB - mcr p15, 0, r4, c2, c0, 0 @ load TTB0 - mcr p15, 0, r4, c2, c0, 1 @ load TTB1 - mov r10, #0x1f @ domains 0, 1 = manager - mcr p15, 0, r10, c3, c0, 0 @ load domain access register -#ifndef CONFIG_CPU_L2CACHE_DISABLE - @ L2 cache configuration in the L2 aux control register - mrc p15, 1, r10, c9, c0, 2 - bic r10, r10, #(1 << 16) @ L2 outer cache - mcr p15, 1, r10, c9, c0, 2 - @ L2 cache is enabled in the aux control register - mrc p15, 0, r10, c1, c0, 1 - orr r10, r10, #2 - mcr p15, 0, r10, c1, c0, 1 -#endif - mrc p15, 0, r0, c1, c0, 0 @ read control register - ldr r10, cr1_clear @ get mask for bits to clear - bic r0, r0, r10 @ clear bits them - ldr r10, cr1_set @ get mask for bits to set - orr r0, r0, r10 @ set them - mov pc, lr @ return to head.S:__ret - - /* - * V X F I D LR - * .... ...E PUI. .T.T 4RVI ZFRS BLDP WCAM - * rrrr rrrx xxx0 0101 xxxx xxxx x111 xxxx < forced - * 0 110 0011 1.00 .111 1101 < we want - */ - .type cr1_clear, #object - .type cr1_set, #object -cr1_clear: - .word 0x0120c302 -cr1_set: - .word 0x00c0387d - -__v7_setup_stack: - .space 4 * 11 @ 11 registers - - .type v7_processor_functions, #object -ENTRY(v7_processor_functions) - .word v7_early_abort - .word cpu_v7_proc_init - .word cpu_v7_proc_fin - .word cpu_v7_reset - .word cpu_v7_do_idle - .word cpu_v7_dcache_clean_area - .word cpu_v7_switch_mm - .word cpu_v7_set_pte_ext - .size v7_processor_functions, . - v7_processor_functions - - .type cpu_arch_name, #object -cpu_arch_name: - .asciz "armv7" - .size cpu_arch_name, . - cpu_arch_name - - .type cpu_elf_name, #object -cpu_elf_name: - .asciz "v7" - .size cpu_elf_name, . - cpu_elf_name - .align - - .section ".proc.info.init", #alloc, #execinstr - - /* - * Match any ARMv7 processor core. - */ - .type __v7_proc_info, #object -__v7_proc_info: - .long 0x000f0000 @ Required ID value - .long 0x000f0000 @ Mask for ID - .long PMD_TYPE_SECT | \ - PMD_SECT_BUFFERABLE | \ - PMD_SECT_CACHEABLE | \ - PMD_SECT_AP_WRITE | \ - PMD_SECT_AP_READ - .long PMD_TYPE_SECT | \ - PMD_SECT_XN | \ - PMD_SECT_AP_WRITE | \ - PMD_SECT_AP_READ - b __v7_setup - .long cpu_arch_name - .long cpu_elf_name - .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP - .long cpu_v7_name - .long v7_processor_functions - .long v6wbi_tlb_fns - .long v6_user_fns - .long v7_cache_fns - .size __v7_proc_info, . - __v7_proc_info diff --git a/trunk/arch/arm/plat-omap/Kconfig b/trunk/arch/arm/plat-omap/Kconfig index cfc69f3842fd..9e8d21eca4ec 100644 --- a/trunk/arch/arm/plat-omap/Kconfig +++ b/trunk/arch/arm/plat-omap/Kconfig @@ -20,11 +20,6 @@ endchoice comment "OMAP Feature Selections" -config OMAP_DEBUG_LEDS - bool - help - For debug card leds on TI reference boards. - config OMAP_RESET_CLOCKS bool "Reset unused clocks during boot" depends on ARCH_OMAP @@ -63,14 +58,6 @@ config OMAP_MUX_WARNINGS to change the pin multiplexing setup. When there are no warnings printed, it's safe to deselect OMAP_MUX for your product. -config OMAP_MCBSP - bool "McBSP support" - depends on ARCH_OMAP - default y - help - Say Y here if you want support for the OMAP Multichannel - Buffered Serial Port. - choice prompt "System timer" default OMAP_MPU_TIMER diff --git a/trunk/arch/arm/plat-omap/Makefile b/trunk/arch/arm/plat-omap/Makefile index 41a3c1cf3bd4..2896b4546411 100644 --- a/trunk/arch/arm/plat-omap/Makefile +++ b/trunk/arch/arm/plat-omap/Makefile @@ -3,8 +3,7 @@ # # Common support -obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o \ - usb.o fb.o +obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o fb.o obj-m := obj-n := obj- := @@ -17,4 +16,4 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o obj-$(CONFIG_CPU_FREQ) += cpu-omap.o obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o -obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o + diff --git a/trunk/arch/arm/plat-omap/clock.c b/trunk/arch/arm/plat-omap/clock.c index 0a603242f367..f1179ad4be1b 100644 --- a/trunk/arch/arm/plat-omap/clock.c +++ b/trunk/arch/arm/plat-omap/clock.c @@ -33,41 +33,6 @@ static DEFINE_SPINLOCK(clockfw_lock); static struct clk_functions *arch_clock; -#ifdef CONFIG_PM_DEBUG - -static void print_parents(struct clk *clk) -{ - struct clk *p; - int printed = 0; - - list_for_each_entry(p, &clocks, node) { - if (p->parent == clk && p->usecount) { - if (!clk->usecount && !printed) { - printk("MISMATCH: %s\n", clk->name); - printed = 1; - } - printk("\t%-15s\n", p->name); - } - } -} - -void clk_print_usecounts(void) -{ - unsigned long flags; - struct clk *p; - - spin_lock_irqsave(&clockfw_lock, flags); - list_for_each_entry(p, &clocks, node) { - if (p->usecount) - printk("%-15s: %d\n", p->name, p->usecount); - print_parents(p); - - } - spin_unlock_irqrestore(&clockfw_lock, flags); -} - -#endif - /*------------------------------------------------------------------------- * Standard clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ @@ -284,8 +249,6 @@ void followparent_recalc(struct clk *clk) return; clk->rate = clk->parent->rate; - if (unlikely(clk->flags & RATE_PROPAGATES)) - propagate_rate(clk); } /* Propagate rate to children */ diff --git a/trunk/arch/arm/plat-omap/common.c b/trunk/arch/arm/plat-omap/common.c index dd8708ad0a71..fecd3d625995 100644 --- a/trunk/arch/arm/plat-omap/common.c +++ b/trunk/arch/arm/plat-omap/common.c @@ -93,12 +93,8 @@ static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out) * in the kernel. */ for (i = 0; i < omap_board_config_size; i++) { if (omap_board_config[i].tag == tag) { - if (skip == 0) { - kinfo = &omap_board_config[i]; - break; - } else { - skip--; - } + kinfo = &omap_board_config[i]; + break; } } if (kinfo == NULL) diff --git a/trunk/arch/arm/plat-omap/debug-leds.c b/trunk/arch/arm/plat-omap/debug-leds.c deleted file mode 100644 index 9128a80d228f..000000000000 --- a/trunk/arch/arm/plat-omap/debug-leds.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * linux/arch/arm/plat-omap/debug-leds.c - * - * Copyright 2003 by Texas Instruments Incorporated - * - * 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 the Free Software Foundation. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - - -/* Many OMAP development platforms reuse the same "debug board"; these - * platforms include H2, H3, H4, and Perseus2. There are 16 LEDs on the - * debug board (all green), accessed through FPGA registers. - * - * The "surfer" expansion board and H2 sample board also have two-color - * green+red LEDs (in parallel), used here for timer and idle indicators - * in preference to the ones on the debug board, for a "Disco LED" effect. - * - * This driver exports either the original ARM LED API, the new generic - * one, or both. - */ - -static spinlock_t lock; -static struct h2p2_dbg_fpga __iomem *fpga; -static u16 led_state, hw_led_state; - - -#ifdef CONFIG_LEDS_OMAP_DEBUG -#define new_led_api() 1 -#else -#define new_led_api() 0 -#endif - - -/*-------------------------------------------------------------------------*/ - -/* original ARM debug LED API: - * - timer and idle leds (some boards use non-FPGA leds here); - * - up to 4 generic leds, easily accessed in-kernel (any context) - */ - -#define GPIO_LED_RED 3 -#define GPIO_LED_GREEN OMAP_MPUIO(4) - -#define LED_STATE_ENABLED 0x01 -#define LED_STATE_CLAIMED 0x02 -#define LED_TIMER_ON 0x04 - -#define GPIO_IDLE GPIO_LED_GREEN -#define GPIO_TIMER GPIO_LED_RED - -static void h2p2_dbg_leds_event(led_event_t evt) -{ - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - - if (!(led_state & LED_STATE_ENABLED) && evt != led_start) - goto done; - - switch (evt) { - case led_start: - if (fpga) - led_state |= LED_STATE_ENABLED; - break; - - case led_stop: - case led_halted: - /* all leds off during suspend or shutdown */ - - if (!(machine_is_omap_perseus2() || machine_is_omap_h4())) { - omap_set_gpio_dataout(GPIO_TIMER, 0); - omap_set_gpio_dataout(GPIO_IDLE, 0); - } - - __raw_writew(~0, &fpga->leds); - led_state &= ~LED_STATE_ENABLED; - goto done; - - case led_claim: - led_state |= LED_STATE_CLAIMED; - hw_led_state = 0; - break; - - case led_release: - led_state &= ~LED_STATE_CLAIMED; - break; - -#ifdef CONFIG_LEDS_TIMER - case led_timer: - led_state ^= LED_TIMER_ON; - - if (machine_is_omap_perseus2() || machine_is_omap_h4()) - hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER; - else { - omap_set_gpio_dataout(GPIO_TIMER, - led_state & LED_TIMER_ON); - goto done; - } - - break; -#endif - -#ifdef CONFIG_LEDS_CPU - /* LED lit iff busy */ - case led_idle_start: - if (machine_is_omap_perseus2() || machine_is_omap_h4()) - hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE; - else { - omap_set_gpio_dataout(GPIO_IDLE, 1); - goto done; - } - - break; - - case led_idle_end: - if (machine_is_omap_perseus2() || machine_is_omap_h4()) - hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE; - else { - omap_set_gpio_dataout(GPIO_IDLE, 0); - goto done; - } - - break; -#endif - - case led_green_on: - hw_led_state |= H2P2_DBG_FPGA_LED_GREEN; - break; - case led_green_off: - hw_led_state &= ~H2P2_DBG_FPGA_LED_GREEN; - break; - - case led_amber_on: - hw_led_state |= H2P2_DBG_FPGA_LED_AMBER; - break; - case led_amber_off: - hw_led_state &= ~H2P2_DBG_FPGA_LED_AMBER; - break; - - case led_red_on: - hw_led_state |= H2P2_DBG_FPGA_LED_RED; - break; - case led_red_off: - hw_led_state &= ~H2P2_DBG_FPGA_LED_RED; - break; - - case led_blue_on: - hw_led_state |= H2P2_DBG_FPGA_LED_BLUE; - break; - case led_blue_off: - hw_led_state &= ~H2P2_DBG_FPGA_LED_BLUE; - break; - - default: - break; - } - - - /* - * Actually burn the LEDs - */ - if (led_state & LED_STATE_ENABLED) - __raw_writew(~hw_led_state, &fpga->leds); - -done: - spin_unlock_irqrestore(&lock, flags); -} - -/*-------------------------------------------------------------------------*/ - -/* "new" LED API - * - with syfs access and generic triggering - * - not readily accessible to in-kernel drivers - */ - -struct dbg_led { - struct led_classdev cdev; - u16 mask; -}; - -static struct dbg_led dbg_leds[] = { - /* REVISIT at least H2 uses different timer & cpu leds... */ -#ifndef CONFIG_LEDS_TIMER - { .mask = 1 << 0, .cdev.name = "d4:green", - .cdev.default_trigger = "heartbeat", }, -#endif -#ifndef CONFIG_LEDS_CPU - { .mask = 1 << 1, .cdev.name = "d5:green", }, /* !idle */ -#endif - { .mask = 1 << 2, .cdev.name = "d6:green", }, - { .mask = 1 << 3, .cdev.name = "d7:green", }, - - { .mask = 1 << 4, .cdev.name = "d8:green", }, - { .mask = 1 << 5, .cdev.name = "d9:green", }, - { .mask = 1 << 6, .cdev.name = "d10:green", }, - { .mask = 1 << 7, .cdev.name = "d11:green", }, - - { .mask = 1 << 8, .cdev.name = "d12:green", }, - { .mask = 1 << 9, .cdev.name = "d13:green", }, - { .mask = 1 << 10, .cdev.name = "d14:green", }, - { .mask = 1 << 11, .cdev.name = "d15:green", }, - -#ifndef CONFIG_LEDS - { .mask = 1 << 12, .cdev.name = "d16:green", }, - { .mask = 1 << 13, .cdev.name = "d17:green", }, - { .mask = 1 << 14, .cdev.name = "d18:green", }, - { .mask = 1 << 15, .cdev.name = "d19:green", }, -#endif -}; - -static void -fpga_led_set(struct led_classdev *cdev, enum led_brightness value) -{ - struct dbg_led *led = container_of(cdev, struct dbg_led, cdev); - unsigned long flags; - - spin_lock_irqsave(&lock, flags); - if (value == LED_OFF) - hw_led_state &= ~led->mask; - else - hw_led_state |= led->mask; - __raw_writew(~hw_led_state, &fpga->leds); - spin_unlock_irqrestore(&lock, flags); -} - -static void __init newled_init(struct device *dev) -{ - unsigned i; - struct dbg_led *led; - int status; - - for (i = 0, led = dbg_leds; i < ARRAY_SIZE(dbg_leds); i++, led++) { - led->cdev.brightness_set = fpga_led_set; - status = led_classdev_register(dev, &led->cdev); - if (status < 0) - break; - } - return; -} - - -/*-------------------------------------------------------------------------*/ - -static int /* __init */ fpga_probe(struct platform_device *pdev) -{ - struct resource *iomem; - - spin_lock_init(&lock); - - iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iomem) - return -ENODEV; - - fpga = ioremap(iomem->start, H2P2_DBG_FPGA_SIZE); - __raw_writew(~0, &fpga->leds); - -#ifdef CONFIG_LEDS - leds_event = h2p2_dbg_leds_event; - leds_event(led_start); -#endif - - if (new_led_api()) { - newled_init(&pdev->dev); - } - - return 0; -} - -static int fpga_suspend_late(struct platform_device *pdev, pm_message_t mesg) -{ - __raw_writew(~0, &fpga->leds); - return 0; -} - -static int fpga_resume_early(struct platform_device *pdev) -{ - __raw_writew(~hw_led_state, &fpga->leds); - return 0; -} - - -static struct platform_driver led_driver = { - .driver.name = "omap_dbg_led", - .probe = fpga_probe, - .suspend_late = fpga_suspend_late, - .resume_early = fpga_resume_early, -}; - -static int __init fpga_init(void) -{ - if (machine_is_omap_h4() - || machine_is_omap_h3() - || machine_is_omap_h2() - || machine_is_omap_perseus2() - ) - return platform_driver_register(&led_driver); - return 0; -} -fs_initcall(fpga_init); diff --git a/trunk/arch/arm/plat-omap/devices.c b/trunk/arch/arm/plat-omap/devices.c index c5dab1d6417e..eeb33fed6f7c 100644 --- a/trunk/arch/arm/plat-omap/devices.c +++ b/trunk/arch/arm/plat-omap/devices.c @@ -25,71 +25,7 @@ #include #include -#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) - -#include "../plat-omap/dsp/dsp_common.h" - -static struct dsp_platform_data dsp_pdata = { - .kdev_list = LIST_HEAD_INIT(dsp_pdata.kdev_list), -}; - -static struct resource omap_dsp_resources[] = { - { - .name = "dsp_mmu", - .start = -1, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device omap_dsp_device = { - .name = "dsp", - .id = -1, - .num_resources = ARRAY_SIZE(omap_dsp_resources), - .resource = omap_dsp_resources, - .dev = { - .platform_data = &dsp_pdata, - }, -}; - -static inline void omap_init_dsp(void) -{ - struct resource *res; - int irq; - - if (cpu_is_omap15xx()) - irq = INT_1510_DSP_MMU; - else if (cpu_is_omap16xx()) - irq = INT_1610_DSP_MMU; - else if (cpu_is_omap24xx()) - irq = INT_24XX_DSP_MMU; - - res = platform_get_resource_byname(&omap_dsp_device, - IORESOURCE_IRQ, "dsp_mmu"); - res->start = irq; - - platform_device_register(&omap_dsp_device); -} - -int dsp_kfunc_device_register(struct dsp_kfunc_device *kdev) -{ - static DEFINE_MUTEX(dsp_pdata_lock); - - mutex_init(&kdev->lock); - - mutex_lock(&dsp_pdata_lock); - list_add_tail(&kdev->entry, &dsp_pdata.kdev_list); - mutex_unlock(&dsp_pdata_lock); - - return 0; -} -EXPORT_SYMBOL(dsp_kfunc_device_register); - -#else -static inline void omap_init_dsp(void) { } -#endif /* CONFIG_OMAP_DSP */ - -/*-------------------------------------------------------------------------*/ -#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) +#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) #define OMAP1_I2C_BASE 0xfffb3800 #define OMAP2_I2C_BASE1 0x48070000 @@ -112,8 +48,8 @@ static struct resource i2c_resources1[] = { /* DMA not used; works around erratum writing to non-empty i2c fifo */ static struct platform_device omap_i2c_device1 = { - .name = "i2c_omap", - .id = 1, + .name = "i2c_omap", + .id = 1, .num_resources = ARRAY_SIZE(i2c_resources1), .resource = i2c_resources1, }; @@ -440,7 +376,7 @@ static inline void omap_init_wdt(void) {} /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_HW_RANDOM_OMAP) || defined(CONFIG_HW_RANDOM_OMAP_MODULE) +#if defined(CONFIG_OMAP_RNG) || defined(CONFIG_OMAP_RNG_MODULE) #ifdef CONFIG_ARCH_OMAP24XX #define OMAP_RNG_BASE 0x480A0000 @@ -500,7 +436,6 @@ static int __init omap_init_devices(void) /* please keep these calls, and their implementations above, * in alphabetical order so they're easier to sort through. */ - omap_init_dsp(); omap_init_i2c(); omap_init_kp(); omap_init_mmc(); @@ -511,3 +446,4 @@ static int __init omap_init_devices(void) return 0; } arch_initcall(omap_init_devices); + diff --git a/trunk/arch/arm/plat-omap/dma.c b/trunk/arch/arm/plat-omap/dma.c index 2d86b106ff3e..f3f84fbf8b87 100644 --- a/trunk/arch/arm/plat-omap/dma.c +++ b/trunk/arch/arm/plat-omap/dma.c @@ -925,17 +925,10 @@ static int omap2_dma_handle_ch(int ch) { u32 status = OMAP_DMA_CSR_REG(ch); - if (!status) { - if (printk_ratelimit()) - printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n", ch); + if (!status) return 0; - } - if (unlikely(dma_chan[ch].dev_id == -1)) { - if (printk_ratelimit()) - printk(KERN_WARNING "IRQ %04x for non-allocated DMA" - "channel %d\n", status, ch); + if (unlikely(dma_chan[ch].dev_id == -1)) return 0; - } if (unlikely(status & OMAP_DMA_DROP_IRQ)) printk(KERN_INFO "DMA synchronization event drop occurred with device " @@ -966,15 +959,11 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id) int i; val = omap_readl(OMAP_DMA4_IRQSTATUS_L0); - if (val == 0) { - if (printk_ratelimit()) - printk(KERN_WARNING "Spurious DMA IRQ\n"); - return IRQ_HANDLED; - } - for (i = 0; i < OMAP_LOGICAL_DMA_CH_COUNT && val != 0; i++) { - if (val & 1) - omap2_dma_handle_ch(i); - val >>= 1; + + for (i = 1; i <= OMAP_LOGICAL_DMA_CH_COUNT; i++) { + int active = val & (1 << (i - 1)); + if (active) + omap2_dma_handle_ch(i - 1); } return IRQ_HANDLED; diff --git a/trunk/arch/arm/plat-omap/dmtimer.c b/trunk/arch/arm/plat-omap/dmtimer.c index 36073dfaa4db..659619f235ca 100644 --- a/trunk/arch/arm/plat-omap/dmtimer.c +++ b/trunk/arch/arm/plat-omap/dmtimer.c @@ -372,7 +372,7 @@ void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) /* When the functional clock disappears, too quick writes seem to * cause an abort. */ - __delay(150000); + __delay(15000); } #endif diff --git a/trunk/arch/arm/plat-omap/fb.c b/trunk/arch/arm/plat-omap/fb.c index 4493bcff5172..56acb8720f78 100644 --- a/trunk/arch/arm/plat-omap/fb.c +++ b/trunk/arch/arm/plat-omap/fb.c @@ -1,26 +1,3 @@ -/* - * File: arch/arm/plat-omap/fb.c - * - * Framebuffer device registration for TI OMAP platforms - * - * Copyright (C) 2006 Nokia Corporation - * Author: Imre Deak - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - #include #include #include @@ -39,8 +16,6 @@ #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) static struct omapfb_platform_data omapfb_config; -static int config_invalid; -static int configured_regions; static u64 omap_fb_dma_mask = ~(u32)0; @@ -55,270 +30,39 @@ static struct platform_device omap_fb_device = { .num_resources = 0, }; -static inline int ranges_overlap(unsigned long start1, unsigned long size1, - unsigned long start2, unsigned long size2) -{ - return (start1 >= start2 && start1 < start2 + size2) || - (start2 >= start1 && start2 < start1 + size1); -} - -static inline int range_included(unsigned long start1, unsigned long size1, - unsigned long start2, unsigned long size2) -{ - return start1 >= start2 && start1 + size1 <= start2 + size2; -} - - -/* Check if there is an overlapping region. */ -static int fbmem_region_reserved(unsigned long start, size_t size) -{ - struct omapfb_mem_region *rg; - int i; - - rg = &omapfb_config.mem_desc.region[0]; - for (i = 0; i < OMAPFB_PLANE_NUM; i++, rg++) { - if (!rg->paddr) - /* Empty slot. */ - continue; - if (ranges_overlap(start, size, rg->paddr, rg->size)) - return 1; - } - return 0; -} - -/* - * Get the region_idx`th region from board config/ATAG and convert it to - * our internal format. - */ -static int get_fbmem_region(int region_idx, struct omapfb_mem_region *rg) -{ - const struct omap_fbmem_config *conf; - u32 paddr; - - conf = omap_get_nr_config(OMAP_TAG_FBMEM, - struct omap_fbmem_config, region_idx); - if (conf == NULL) - return -ENOENT; - - paddr = conf->start; - /* - * Low bits encode the page allocation mode, if high bits - * are zero. Otherwise we need a page aligned fixed - * address. - */ - memset(rg, 0, sizeof(*rg)); - rg->type = paddr & ~PAGE_MASK; - rg->paddr = paddr & PAGE_MASK; - rg->size = PAGE_ALIGN(conf->size); - return 0; -} - -static int set_fbmem_region_type(struct omapfb_mem_region *rg, int mem_type, - unsigned long mem_start, - unsigned long mem_size) -{ - /* - * Check if the configuration specifies the type explicitly. - * type = 0 && paddr = 0, a default don't care case maps to - * the SDRAM type. - */ - if (rg->type || (!rg->type && !rg->paddr)) - return 0; - if (ranges_overlap(rg->paddr, rg->size, mem_start, mem_size)) { - rg->type = mem_type; - return 0; - } - /* Can't determine it. */ - return -1; -} - -static int check_fbmem_region(int region_idx, struct omapfb_mem_region *rg, - unsigned long start_avail, unsigned size_avail) -{ - unsigned long paddr = rg->paddr; - size_t size = rg->size; - - if (rg->type > OMAPFB_MEMTYPE_MAX) { - printk(KERN_ERR - "Invalid start address for FB region %d\n", region_idx); - return -EINVAL; - } - - if (!rg->size) { - printk(KERN_ERR "Zero size for FB region %d\n", region_idx); - return -EINVAL; - } - - if (!paddr) - /* Allocate this dynamically, leave paddr 0 for now. */ - return 0; - - /* - * Fixed region for the given RAM range. Check if it's already - * reserved by the FB code or someone else. - */ - if (fbmem_region_reserved(paddr, size) || - !range_included(paddr, size, start_avail, size_avail)) { - printk(KERN_ERR "Trying to use reserved memory " - "for FB region %d\n", region_idx); - return -EINVAL; - } - - return 0; -} - -/* - * Called from map_io. We need to call to this early enough so that we - * can reserve the fixed SDRAM regions before VM could get hold of them. - */ -void omapfb_reserve_sdram(void) +/* called from map_io */ +void omapfb_reserve_mem(void) { - struct bootmem_data *bdata; - unsigned long sdram_start, sdram_size; - unsigned long reserved; - int i; - - if (config_invalid) - return; + const struct omap_fbmem_config *fbmem_conf; - bdata = NODE_DATA(0)->bdata; - sdram_start = bdata->node_boot_start; - sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start; - reserved = 0; - for (i = 0; ; i++) { - struct omapfb_mem_region rg; + omapfb_config.fbmem.fb_sram_start = omap_fb_sram_start; + omapfb_config.fbmem.fb_sram_size = omap_fb_sram_size; - if (get_fbmem_region(i, &rg) < 0) - break; - if (i == OMAPFB_PLANE_NUM) { - printk(KERN_ERR - "Extraneous FB mem configuration entries\n"); - config_invalid = 1; - return; - } - /* Check if it's our memory type. */ - if (set_fbmem_region_type(&rg, OMAPFB_MEMTYPE_SDRAM, - sdram_start, sdram_size) < 0 || - (rg.type != OMAPFB_MEMTYPE_SDRAM)) - continue; - BUG_ON(omapfb_config.mem_desc.region[i].size); - if (check_fbmem_region(i, &rg, sdram_start, sdram_size) < 0) { - config_invalid = 1; - return; - } - if (rg.paddr) - reserve_bootmem(rg.paddr, rg.size); - reserved += rg.size; - omapfb_config.mem_desc.region[i] = rg; - configured_regions++; - } - omapfb_config.mem_desc.region_cnt = i; - if (reserved) - pr_info("Reserving %lu bytes SDRAM for frame buffer\n", - reserved); -} + fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); -/* - * Called at sram init time, before anything is pushed to the SRAM stack. - * Because of the stack scheme, we will allocate everything from the - * start of the lowest address region to the end of SRAM. This will also - * include padding for page alignment and possible holes between regions. - * - * As opposed to the SDRAM case, we'll also do any dynamic allocations at - * this point, since the driver built as a module would have problem with - * freeing / reallocating the regions. - */ -unsigned long omapfb_reserve_sram(unsigned long sram_pstart, - unsigned long sram_vstart, - unsigned long sram_size, - unsigned long pstart_avail, - unsigned long size_avail) -{ - struct omapfb_mem_region rg; - unsigned long pend_avail; - unsigned long reserved; - int i; - - if (config_invalid) - return 0; - - reserved = 0; - pend_avail = pstart_avail + size_avail; - for (i = 0; ; i++) { - if (get_fbmem_region(i, &rg) < 0) - break; - if (i == OMAPFB_PLANE_NUM) { - printk(KERN_ERR - "Extraneous FB mem configuration entries\n"); - config_invalid = 1; - return 0; - } - - /* Check if it's our memory type. */ - if (set_fbmem_region_type(&rg, OMAPFB_MEMTYPE_SRAM, - sram_pstart, sram_size) < 0 || - (rg.type != OMAPFB_MEMTYPE_SRAM)) - continue; - BUG_ON(omapfb_config.mem_desc.region[i].size); - - if (check_fbmem_region(i, &rg, pstart_avail, size_avail) < 0) { - config_invalid = 1; - return 0; - } - - if (!rg.paddr) { - /* Dynamic allocation */ - if ((size_avail & PAGE_MASK) < rg.size) { - printk("Not enough SRAM for FB region %d\n", - i); - config_invalid = 1; - return 0; - } - size_avail = (size_avail - rg.size) & PAGE_MASK; - rg.paddr = pstart_avail + size_avail; - } - /* Reserve everything above the start of the region. */ - if (pend_avail - rg.paddr > reserved) - reserved = pend_avail - rg.paddr; - size_avail = pend_avail - reserved - pstart_avail; - - /* - * We have a kernel mapping for this already, so the - * driver won't have to make one. + if (fbmem_conf != NULL) { + /* indicate that the bootloader already initialized the + * fb device, so we'll skip that part in the fb driver */ - rg.vaddr = (void *)(sram_vstart + rg.paddr - sram_pstart); - omapfb_config.mem_desc.region[i] = rg; - configured_regions++; + omapfb_config.fbmem.fb_sdram_start = fbmem_conf->fb_sdram_start; + omapfb_config.fbmem.fb_sdram_size = fbmem_conf->fb_sdram_size; + if (fbmem_conf->fb_sdram_size) { + pr_info("Reserving %u bytes SDRAM for frame buffer\n", + fbmem_conf->fb_sdram_size); + reserve_bootmem(fbmem_conf->fb_sdram_start, + fbmem_conf->fb_sdram_size); + } } - omapfb_config.mem_desc.region_cnt = i; - if (reserved) - pr_info("Reserving %lu bytes SRAM for frame buffer\n", - reserved); - return reserved; -} - -void omapfb_set_ctrl_platform_data(void *data) -{ - omapfb_config.ctrl_platform_data = data; } static inline int omap_init_fb(void) { const struct omap_lcd_config *conf; - if (config_invalid) - return 0; - if (configured_regions != omapfb_config.mem_desc.region_cnt) { - printk(KERN_ERR "Invalid FB mem configuration entries\n"); - return 0; - } conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); - if (conf == NULL) { - if (configured_regions) - /* FB mem config, but no LCD config? */ - printk(KERN_ERR "Missing LCD configuration\n"); + if (conf == NULL) return 0; - } + omapfb_config.lcd = *conf; return platform_device_register(&omap_fb_device); @@ -328,16 +72,7 @@ arch_initcall(omap_init_fb); #else -void omapfb_reserve_sdram(void) {} -unsigned long omapfb_reserve_sram(unsigned long sram_pstart, - unsigned long sram_vstart, - unsigned long sram_size, - unsigned long start_avail, - unsigned long size_avail) -{ - return 0; -} - +void omapfb_reserve_mem(void) {} #endif diff --git a/trunk/arch/arm/plat-omap/gpio.c b/trunk/arch/arm/plat-omap/gpio.c index 337455dfe64d..9dc6d3617bdb 100644 --- a/trunk/arch/arm/plat-omap/gpio.c +++ b/trunk/arch/arm/plat-omap/gpio.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -1544,7 +1545,7 @@ void omap2_gpio_resume_after_retention(void) * This may get called early from board specific init * for boards that have interrupts routed via FPGA. */ -int __init omap_gpio_init(void) +int omap_gpio_init(void) { if (!initialized) return _omap_gpio_init(); diff --git a/trunk/arch/arm/plat-omap/mailbox.c b/trunk/arch/arm/plat-omap/mailbox.c deleted file mode 100644 index de7e6ef48bd0..000000000000 --- a/trunk/arch/arm/plat-omap/mailbox.c +++ /dev/null @@ -1,509 +0,0 @@ -/* - * OMAP mailbox driver - * - * Copyright (C) 2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * Restructured by Hiroshi DOYU - * - * 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 the Free Software Foundation. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mailbox.h" - -static struct omap_mbox *mboxes; -static DEFINE_RWLOCK(mboxes_lock); - -/* Mailbox Sequence Bit function */ -void omap_mbox_init_seq(struct omap_mbox *mbox) -{ - mbox_seq_init(mbox); -} -EXPORT_SYMBOL(omap_mbox_init_seq); - -/* - * message sender - */ -static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg) -{ - int ret = 0, i = 1000; - - while (mbox_fifo_full(mbox)) { - if (mbox->ops->type == OMAP_MBOX_TYPE2) - return -1; - if (--i == 0) - return -1; - udelay(1); - } - - if (arg && mbox->txq->callback) { - ret = mbox->txq->callback(arg); - if (ret) - goto out; - } - - mbox_seq_toggle(mbox, &msg); - mbox_fifo_write(mbox, msg); - out: - return ret; -} - -int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg) -{ - struct request *rq; - struct request_queue *q = mbox->txq->queue; - int ret = 0; - - rq = blk_get_request(q, WRITE, GFP_ATOMIC); - if (unlikely(!rq)) { - ret = -ENOMEM; - goto fail; - } - - rq->data = (void *)msg; - blk_insert_request(q, rq, 0, arg); - - schedule_work(&mbox->txq->work); - fail: - return ret; -} -EXPORT_SYMBOL(omap_mbox_msg_send); - -static void mbox_tx_work(struct work_struct *work) -{ - int ret; - struct request *rq; - struct omap_mbox_queue *mq = container_of(work, - struct omap_mbox_queue, work); - struct omap_mbox *mbox = mq->queue->queuedata; - struct request_queue *q = mbox->txq->queue; - - while (1) { - spin_lock(q->queue_lock); - rq = elv_next_request(q); - spin_unlock(q->queue_lock); - - if (!rq) - break; - - ret = __mbox_msg_send(mbox, (mbox_msg_t) rq->data, rq->special); - if (ret) { - enable_mbox_irq(mbox, IRQ_TX); - return; - } - - spin_lock(q->queue_lock); - blkdev_dequeue_request(rq); - end_that_request_last(rq, 0); - spin_unlock(q->queue_lock); - } -} - -/* - * Message receiver(workqueue) - */ -static void mbox_rx_work(struct work_struct *work) -{ - struct omap_mbox_queue *mq = - container_of(work, struct omap_mbox_queue, work); - struct omap_mbox *mbox = mq->queue->queuedata; - struct request_queue *q = mbox->rxq->queue; - struct request *rq; - mbox_msg_t msg; - unsigned long flags; - - if (mbox->rxq->callback == NULL) { - sysfs_notify(&mbox->dev.kobj, NULL, "mbox"); - return; - } - - while (1) { - spin_lock_irqsave(q->queue_lock, flags); - rq = elv_next_request(q); - spin_unlock_irqrestore(q->queue_lock, flags); - if (!rq) - break; - - msg = (mbox_msg_t) rq->data; - - spin_lock_irqsave(q->queue_lock, flags); - blkdev_dequeue_request(rq); - end_that_request_last(rq, 0); - spin_unlock_irqrestore(q->queue_lock, flags); - - mbox->rxq->callback((void *)msg); - } -} - -/* - * Mailbox interrupt handler - */ -static void mbox_txq_fn(request_queue_t * q) -{ -} - -static void mbox_rxq_fn(request_queue_t * q) -{ -} - -static void __mbox_tx_interrupt(struct omap_mbox *mbox) -{ - disable_mbox_irq(mbox, IRQ_TX); - ack_mbox_irq(mbox, IRQ_TX); - schedule_work(&mbox->txq->work); -} - -static void __mbox_rx_interrupt(struct omap_mbox *mbox) -{ - struct request *rq; - mbox_msg_t msg; - request_queue_t *q = mbox->rxq->queue; - - disable_mbox_irq(mbox, IRQ_RX); - - while (!mbox_fifo_empty(mbox)) { - rq = blk_get_request(q, WRITE, GFP_ATOMIC); - if (unlikely(!rq)) - goto nomem; - - msg = mbox_fifo_read(mbox); - rq->data = (void *)msg; - - if (unlikely(mbox_seq_test(mbox, msg))) { - pr_info("mbox: Illegal seq bit!(%08x)\n", msg); - if (mbox->err_notify) - mbox->err_notify(); - } - - blk_insert_request(q, rq, 0, NULL); - if (mbox->ops->type == OMAP_MBOX_TYPE1) - break; - } - - /* no more messages in the fifo. clear IRQ source. */ - ack_mbox_irq(mbox, IRQ_RX); - enable_mbox_irq(mbox, IRQ_RX); - nomem: - schedule_work(&mbox->rxq->work); -} - -static irqreturn_t mbox_interrupt(int irq, void *p) -{ - struct omap_mbox *mbox = (struct omap_mbox *)p; - - if (is_mbox_irq(mbox, IRQ_TX)) - __mbox_tx_interrupt(mbox); - - if (is_mbox_irq(mbox, IRQ_RX)) - __mbox_rx_interrupt(mbox); - - return IRQ_HANDLED; -} - -/* - * sysfs files - */ -static ssize_t -omap_mbox_write(struct device *dev, struct device_attribute *attr, - const char * buf, size_t count) -{ - int ret; - mbox_msg_t *p = (mbox_msg_t *)buf; - struct omap_mbox *mbox = dev_get_drvdata(dev); - - for (; count >= sizeof(mbox_msg_t); count -= sizeof(mbox_msg_t)) { - ret = omap_mbox_msg_send(mbox, be32_to_cpu(*p), NULL); - if (ret) - return -EAGAIN; - p++; - } - - return (size_t)((char *)p - buf); -} - -static ssize_t -omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf) -{ - unsigned long flags; - struct request *rq; - mbox_msg_t *p = (mbox_msg_t *) buf; - struct omap_mbox *mbox = dev_get_drvdata(dev); - struct request_queue *q = mbox->rxq->queue; - - while (1) { - spin_lock_irqsave(q->queue_lock, flags); - rq = elv_next_request(q); - spin_unlock_irqrestore(q->queue_lock, flags); - - if (!rq) - break; - - *p = (mbox_msg_t) rq->data; - - spin_lock_irqsave(q->queue_lock, flags); - blkdev_dequeue_request(rq); - end_that_request_last(rq, 0); - spin_unlock_irqrestore(q->queue_lock, flags); - - if (unlikely(mbox_seq_test(mbox, *p))) { - pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p); - continue; - } - p++; - } - - pr_debug("%02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]); - - return (size_t) ((char *)p - buf); -} - -static DEVICE_ATTR(mbox, S_IRUGO | S_IWUSR, omap_mbox_read, omap_mbox_write); - -static ssize_t mbox_show(struct class *class, char *buf) -{ - return sprintf(buf, "mbox"); -} - -static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL); - -static struct class omap_mbox_class = { - .name = "omap_mbox", -}; - -static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, - request_fn_proc * proc, - void (*work) (struct work_struct *)) -{ - request_queue_t *q; - struct omap_mbox_queue *mq; - - mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL); - if (!mq) - return NULL; - - spin_lock_init(&mq->lock); - - q = blk_init_queue(proc, &mq->lock); - if (!q) - goto error; - q->queuedata = mbox; - mq->queue = q; - - INIT_WORK(&mq->work, work); - - return mq; -error: - kfree(mq); - return NULL; -} - -static void mbox_queue_free(struct omap_mbox_queue *q) -{ - blk_cleanup_queue(q->queue); - kfree(q); -} - -static int omap_mbox_init(struct omap_mbox *mbox) -{ - int ret; - struct omap_mbox_queue *mq; - - if (likely(mbox->ops->startup)) { - ret = mbox->ops->startup(mbox); - if (unlikely(ret)) - return ret; - } - - mbox->dev.class = &omap_mbox_class; - strlcpy(mbox->dev.bus_id, mbox->name, KOBJ_NAME_LEN); - dev_set_drvdata(&mbox->dev, mbox); - - ret = device_register(&mbox->dev); - if (unlikely(ret)) - goto fail_device_reg; - - ret = device_create_file(&mbox->dev, &dev_attr_mbox); - if (unlikely(ret)) { - printk(KERN_ERR - "device_create_file failed: %d\n", ret); - goto fail_create_mbox; - } - - ret = request_irq(mbox->irq, mbox_interrupt, IRQF_DISABLED, - mbox->name, mbox); - if (unlikely(ret)) { - printk(KERN_ERR - "failed to register mailbox interrupt:%d\n", ret); - goto fail_request_irq; - } - enable_mbox_irq(mbox, IRQ_RX); - - mq = mbox_queue_alloc(mbox, mbox_txq_fn, mbox_tx_work); - if (!mq) { - ret = -ENOMEM; - goto fail_alloc_txq; - } - mbox->txq = mq; - - mq = mbox_queue_alloc(mbox, mbox_rxq_fn, mbox_rx_work); - if (!mq) { - ret = -ENOMEM; - goto fail_alloc_rxq; - } - mbox->rxq = mq; - - return 0; - - fail_alloc_rxq: - mbox_queue_free(mbox->txq); - fail_alloc_txq: - free_irq(mbox->irq, mbox); - fail_request_irq: - device_remove_file(&mbox->dev, &dev_attr_mbox); - fail_create_mbox: - device_unregister(&mbox->dev); - fail_device_reg: - if (unlikely(mbox->ops->shutdown)) - mbox->ops->shutdown(mbox); - - return ret; -} - -static void omap_mbox_fini(struct omap_mbox *mbox) -{ - mbox_queue_free(mbox->txq); - mbox_queue_free(mbox->rxq); - - free_irq(mbox->irq, mbox); - device_remove_file(&mbox->dev, &dev_attr_mbox); - class_unregister(&omap_mbox_class); - - if (unlikely(mbox->ops->shutdown)) - mbox->ops->shutdown(mbox); -} - -static struct omap_mbox **find_mboxes(const char *name) -{ - struct omap_mbox **p; - - for (p = &mboxes; *p; p = &(*p)->next) { - if (strcmp((*p)->name, name) == 0) - break; - } - - return p; -} - -struct omap_mbox *omap_mbox_get(const char *name) -{ - struct omap_mbox *mbox; - int ret; - - read_lock(&mboxes_lock); - mbox = *(find_mboxes(name)); - if (mbox == NULL) { - read_unlock(&mboxes_lock); - return ERR_PTR(-ENOENT); - } - - read_unlock(&mboxes_lock); - - ret = omap_mbox_init(mbox); - if (ret) - return ERR_PTR(-ENODEV); - - return mbox; -} -EXPORT_SYMBOL(omap_mbox_get); - -void omap_mbox_put(struct omap_mbox *mbox) -{ - omap_mbox_fini(mbox); -} -EXPORT_SYMBOL(omap_mbox_put); - -int omap_mbox_register(struct omap_mbox *mbox) -{ - int ret = 0; - struct omap_mbox **tmp; - - if (!mbox) - return -EINVAL; - if (mbox->next) - return -EBUSY; - - write_lock(&mboxes_lock); - tmp = find_mboxes(mbox->name); - if (*tmp) - ret = -EBUSY; - else - *tmp = mbox; - write_unlock(&mboxes_lock); - - return ret; -} -EXPORT_SYMBOL(omap_mbox_register); - -int omap_mbox_unregister(struct omap_mbox *mbox) -{ - struct omap_mbox **tmp; - - write_lock(&mboxes_lock); - tmp = &mboxes; - while (*tmp) { - if (mbox == *tmp) { - *tmp = mbox->next; - mbox->next = NULL; - write_unlock(&mboxes_lock); - return 0; - } - tmp = &(*tmp)->next; - } - write_unlock(&mboxes_lock); - - return -EINVAL; -} -EXPORT_SYMBOL(omap_mbox_unregister); - -static int __init omap_mbox_class_init(void) -{ - int ret = class_register(&omap_mbox_class); - if (!ret) - ret = class_create_file(&omap_mbox_class, &class_attr_mbox); - - return ret; -} - -static void __exit omap_mbox_class_exit(void) -{ - class_remove_file(&omap_mbox_class, &class_attr_mbox); - class_unregister(&omap_mbox_class); -} - -subsys_initcall(omap_mbox_class_init); -module_exit(omap_mbox_class_exit); - -MODULE_LICENSE("GPL"); diff --git a/trunk/arch/arm/plat-omap/mailbox.h b/trunk/arch/arm/plat-omap/mailbox.h deleted file mode 100644 index 67c6740b8ad5..000000000000 --- a/trunk/arch/arm/plat-omap/mailbox.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Mailbox internal functions - * - * Copyright (C) 2006 Nokia Corporation - * Written by: Hiroshi DOYU - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef __ARCH_ARM_PLAT_MAILBOX_H -#define __ARCH_ARM_PLAT_MAILBOX_H - -/* - * Mailbox sequence bit API - */ -#if defined(CONFIG_ARCH_OMAP1) -# define MBOX_USE_SEQ_BIT -#elif defined(CONFIG_ARCH_OMAP2) -# define MBOX_USE_SEQ_BIT -#endif - -#ifdef MBOX_USE_SEQ_BIT -/* seq_rcv should be initialized with any value other than - * 0 and 1 << 31, to allow either value for the first - * message. */ -static inline void mbox_seq_init(struct omap_mbox *mbox) -{ - /* any value other than 0 and 1 << 31 */ - mbox->seq_rcv = 0xffffffff; -} - -static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) -{ - /* add seq_snd to msg */ - *msg = (*msg & 0x7fffffff) | mbox->seq_snd; - /* flip seq_snd */ - mbox->seq_snd ^= 1 << 31; -} - -static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) -{ - mbox_msg_t seq = msg & (1 << 31); - if (seq == mbox->seq_rcv) - return -1; - mbox->seq_rcv = seq; - return 0; -} -#else -static inline void mbox_seq_init(struct omap_mbox *mbox) -{ -} -static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) -{ -} -static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) -{ - return 0; -} -#endif - -/* Mailbox FIFO handle functions */ -static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) -{ - return mbox->ops->fifo_read(mbox); -} -static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) -{ - mbox->ops->fifo_write(mbox, msg); -} -static inline int mbox_fifo_empty(struct omap_mbox *mbox) -{ - return mbox->ops->fifo_empty(mbox); -} -static inline int mbox_fifo_full(struct omap_mbox *mbox) -{ - return mbox->ops->fifo_full(mbox); -} - -/* Mailbox IRQ handle functions */ -static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) -{ - mbox->ops->enable_irq(mbox, irq); -} -static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) -{ - mbox->ops->disable_irq(mbox, irq); -} -static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) -{ - if (mbox->ops->ack_irq) - mbox->ops->ack_irq(mbox, irq); -} -static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) -{ - return mbox->ops->is_irq(mbox, irq); -} - -#endif /* __ARCH_ARM_PLAT_MAILBOX_H */ diff --git a/trunk/arch/arm/plat-omap/sram.c b/trunk/arch/arm/plat-omap/sram.c index bc46f33aede3..19014b2ff4c6 100644 --- a/trunk/arch/arm/plat-omap/sram.c +++ b/trunk/arch/arm/plat-omap/sram.c @@ -46,19 +46,14 @@ #define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) -static unsigned long omap_sram_start; static unsigned long omap_sram_base; static unsigned long omap_sram_size; static unsigned long omap_sram_ceil; -extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart, - unsigned long sram_vstart, - unsigned long sram_size, - unsigned long pstart_avail, - unsigned long size_avail); +unsigned long omap_fb_sram_start; +unsigned long omap_fb_sram_size; -/* - * Depending on the target RAMFS firewall setup, the public usable amount of +/* Depending on the target RAMFS firewall setup, the public usable amount of * SRAM varies. The default accessable size for all device types is 2k. A GP * device allows ARM11 but not other initators for full size. This * functionality seems ok until some nice security API happens. @@ -82,6 +77,32 @@ static int is_sram_locked(void) return 1; /* assume locked with no PPA or security driver */ } +void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail, + unsigned long *start, unsigned long *size) +{ + const struct omap_fbmem_config *fbmem_conf; + + fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); + if (fbmem_conf != NULL) { + *start = fbmem_conf->fb_sram_start; + *size = fbmem_conf->fb_sram_size; + } else { + *size = 0; + *start = 0; + } + + if (*size && ( + *start < start_avail || + *start + *size > start_avail + size_avail)) { + printk(KERN_ERR "invalid FB SRAM configuration\n"); + *start = start_avail; + *size = size_avail; + } + + if (*size) + pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size); +} + /* * The amount of SRAM depends on the core type. * Note that we cannot try to test for SRAM here because writes @@ -90,16 +111,16 @@ static int is_sram_locked(void) */ void __init omap_detect_sram(void) { - unsigned long reserved; + unsigned long sram_start; if (cpu_is_omap24xx()) { if (is_sram_locked()) { omap_sram_base = OMAP2_SRAM_PUB_VA; - omap_sram_start = OMAP2_SRAM_PUB_PA; + sram_start = OMAP2_SRAM_PUB_PA; omap_sram_size = 0x800; /* 2K */ } else { omap_sram_base = OMAP2_SRAM_VA; - omap_sram_start = OMAP2_SRAM_PA; + sram_start = OMAP2_SRAM_PA; if (cpu_is_omap242x()) omap_sram_size = 0xa0000; /* 640K */ else if (cpu_is_omap243x()) @@ -107,7 +128,7 @@ void __init omap_detect_sram(void) } } else { omap_sram_base = OMAP1_SRAM_VA; - omap_sram_start = OMAP1_SRAM_PA; + sram_start = OMAP1_SRAM_PA; if (cpu_is_omap730()) omap_sram_size = 0x32000; /* 200K */ @@ -123,11 +144,12 @@ void __init omap_detect_sram(void) omap_sram_size = 0x4000; } } - reserved = omapfb_reserve_sram(omap_sram_start, omap_sram_base, - omap_sram_size, - omap_sram_start + SRAM_BOOTLOADER_SZ, - omap_sram_size - SRAM_BOOTLOADER_SZ); - omap_sram_size -= reserved; + get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ, + omap_sram_size - SRAM_BOOTLOADER_SZ, + &omap_fb_sram_start, &omap_fb_sram_size); + if (omap_fb_sram_size) + omap_sram_size -= sram_start + omap_sram_size - + omap_fb_sram_start; omap_sram_ceil = omap_sram_base + omap_sram_size; } diff --git a/trunk/arch/arm/plat-omap/usb.c b/trunk/arch/arm/plat-omap/usb.c index 25489aafb113..7e8096809be2 100644 --- a/trunk/arch/arm/plat-omap/usb.c +++ b/trunk/arch/arm/plat-omap/usb.c @@ -37,27 +37,9 @@ #include #include -#ifdef CONFIG_ARCH_OMAP1 - -#define INT_USB_IRQ_GEN IH2_BASE + 20 -#define INT_USB_IRQ_NISO IH2_BASE + 30 -#define INT_USB_IRQ_ISO IH2_BASE + 29 -#define INT_USB_IRQ_HGEN INT_USB_HHC_1 -#define INT_USB_IRQ_OTG IH2_BASE + 8 - -#else - -#define INT_USB_IRQ_GEN INT_24XX_USB_IRQ_GEN -#define INT_USB_IRQ_NISO INT_24XX_USB_IRQ_NISO -#define INT_USB_IRQ_ISO INT_24XX_USB_IRQ_ISO -#define INT_USB_IRQ_HGEN INT_24XX_USB_IRQ_HGEN -#define INT_USB_IRQ_OTG INT_24XX_USB_IRQ_OTG - -#endif - - /* These routines should handle the standard chip-specific modes * for usb0/1/2 ports, covering basic mux and transceiver setup. + * Call omap_usb_init() once, from INIT_MACHINE(). * * Some board-*.c files will need to set up additional mux options, * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup. @@ -114,26 +96,19 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) { u32 syscon1 = 0; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG &= ~USBT0WRMODEI(USB_BIDIR_TLL); - if (nwires == 0) { - if (cpu_class_is_omap1() && !cpu_is_omap15xx()) { + if (!cpu_is_omap15xx()) { /* pulldown D+/D- */ USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1); } return 0; } - if (is_device) { - if (cpu_is_omap24xx()) - omap_cfg_reg(J20_24XX_USB0_PUEN); - else - omap_cfg_reg(W4_USB_PUEN); - } + if (is_device) + omap_cfg_reg(W4_USB_PUEN); - /* internal transceiver (unavailable on 17xx, 24xx) */ - if (!cpu_class_is_omap2() && nwires == 2) { + /* internal transceiver */ + if (nwires == 2) { // omap_cfg_reg(P9_USB_DP); // omap_cfg_reg(R8_USB_DM); @@ -161,50 +136,29 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) return 0; } - if (cpu_is_omap24xx()) { - omap_cfg_reg(K18_24XX_USB0_DAT); - omap_cfg_reg(K19_24XX_USB0_TXEN); - omap_cfg_reg(J14_24XX_USB0_SE0); - if (nwires != 3) - omap_cfg_reg(J18_24XX_USB0_RCV); - } else { - omap_cfg_reg(V6_USB0_TXD); - omap_cfg_reg(W9_USB0_TXEN); - omap_cfg_reg(W5_USB0_SE0); - if (nwires != 3) - omap_cfg_reg(Y5_USB0_RCV); - } + omap_cfg_reg(V6_USB0_TXD); + omap_cfg_reg(W9_USB0_TXEN); + omap_cfg_reg(W5_USB0_SE0); - /* NOTE: SPEED and SUSP aren't configured here. OTG hosts - * may be able to use I2C requests to set those bits along - * with VBUS switching and overcurrent detction. - */ + /* NOTE: SPEED and SUSP aren't configured here */ - if (cpu_class_is_omap1() && nwires != 6) + if (nwires != 3) + omap_cfg_reg(Y5_USB0_RCV); + if (nwires != 6) USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; switch (nwires) { case 3: syscon1 = 2; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR); break; case 4: syscon1 = 1; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR); break; case 6: syscon1 = 3; - if (cpu_is_omap24xx()) { - omap_cfg_reg(J19_24XX_USB0_VP); - omap_cfg_reg(K20_24XX_USB0_VM); - CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_UNIDIR); - } else { - omap_cfg_reg(AA9_USB0_VP); - omap_cfg_reg(R9_USB0_VM); - USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; - } + omap_cfg_reg(AA9_USB0_VP); + omap_cfg_reg(R9_USB0_VM); + USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; break; default: printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", @@ -217,22 +171,14 @@ static u32 __init omap_usb1_init(unsigned nwires) { u32 syscon1 = 0; - if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) + if (nwires != 6 && !cpu_is_omap15xx()) USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG &= ~USBT1WRMODEI(USB_BIDIR_TLL); - if (nwires == 0) return 0; /* external transceiver */ - if (cpu_class_is_omap1()) { - omap_cfg_reg(USB1_TXD); - omap_cfg_reg(USB1_TXEN); - if (nwires != 3) - omap_cfg_reg(USB1_RCV); - } - + omap_cfg_reg(USB1_TXD); + omap_cfg_reg(USB1_TXEN); if (cpu_is_omap15xx()) { omap_cfg_reg(USB1_SEO); omap_cfg_reg(USB1_SPEED); @@ -244,38 +190,20 @@ static u32 __init omap_usb1_init(unsigned nwires) } else if (cpu_is_omap1710()) { omap_cfg_reg(R13_1710_USB1_SE0); // SUSP - } else if (cpu_is_omap24xx()) { - /* NOTE: board-specific code must set up pin muxing for usb1, - * since each signal could come out on either of two balls. - */ } else { - pr_debug("usb%d cpu unrecognized\n", 1); - return 0; + pr_debug("usb unrecognized\n"); } + if (nwires != 3) + omap_cfg_reg(USB1_RCV); switch (nwires) { - case 2: - if (!cpu_is_omap24xx()) - goto bad; - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM - */ - syscon1 = 1; - CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR_TLL); - break; case 3: syscon1 = 2; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR); break; case 4: syscon1 = 1; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR); break; case 6: - if (cpu_is_omap24xx()) - goto bad; syscon1 = 3; omap_cfg_reg(USB1_VP); omap_cfg_reg(USB1_VM); @@ -283,7 +211,6 @@ static u32 __init omap_usb1_init(unsigned nwires) USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R; break; default: -bad: printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", 1, nwires); } @@ -294,17 +221,10 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) { u32 syscon1 = 0; - if (cpu_is_omap24xx()) { - CONTROL_DEVCONF_REG &= ~(USBT2WRMODEI(USB_BIDIR_TLL) - | USBT2TLL5PI); - alt_pingroup = 0; - } - - /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */ + /* NOTE erratum: must leave USB2_UNI_R set if usb0 in use */ if (alt_pingroup || nwires == 0) return 0; - - if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) + if (nwires != 6 && !cpu_is_omap15xx()) USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; /* external transceiver */ @@ -322,54 +242,19 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) if (nwires != 3) omap_cfg_reg(Y5_USB2_RCV); // FIXME omap_cfg_reg(USB2_SPEED); - } else if (cpu_is_omap24xx()) { - omap_cfg_reg(Y11_24XX_USB2_DAT); - omap_cfg_reg(AA10_24XX_USB2_SE0); - if (nwires > 2) - omap_cfg_reg(AA12_24XX_USB2_TXEN); - if (nwires > 3) - omap_cfg_reg(AA6_24XX_USB2_RCV); } else { - pr_debug("usb%d cpu unrecognized\n", 1); - return 0; + pr_debug("usb unrecognized\n"); } - // if (cpu_class_is_omap1()) omap_cfg_reg(USB2_SUSP); + // omap_cfg_reg(USB2_SUSP); switch (nwires) { - case 2: - if (!cpu_is_omap24xx()) - goto bad; - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM - */ - syscon1 = 1; - CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR_TLL); - break; case 3: syscon1 = 2; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR); break; case 4: syscon1 = 1; - if (cpu_is_omap24xx()) - CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR); - break; - case 5: - if (!cpu_is_omap24xx()) - goto bad; - omap_cfg_reg(AA4_24XX_USB2_TLLSE0); - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM. Something must also - * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED} - */ - syscon1 = 3; - CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_UNIDIR_TLL) - | USBT2TLL5PI; break; case 6: - if (cpu_is_omap24xx()) - goto bad; syscon1 = 3; if (cpu_is_omap15xx()) { omap_cfg_reg(USB2_VP); @@ -381,7 +266,6 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) } break; default: -bad: printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", 2, nwires); } @@ -410,13 +294,13 @@ static struct resource udc_resources[] = { .end = UDC_BASE + 0xff, .flags = IORESOURCE_MEM, }, { /* general IRQ */ - .start = INT_USB_IRQ_GEN, + .start = IH2_BASE + 20, .flags = IORESOURCE_IRQ, }, { /* PIO IRQ */ - .start = INT_USB_IRQ_NISO, + .start = IH2_BASE + 30, .flags = IORESOURCE_IRQ, }, { /* SOF IRQ */ - .start = INT_USB_IRQ_ISO, + .start = IH2_BASE + 29, .flags = IORESOURCE_IRQ, }, }; @@ -445,11 +329,11 @@ static u64 ohci_dmamask = ~(u32)0; static struct resource ohci_resources[] = { { .start = OMAP_OHCI_BASE, - .end = OMAP_OHCI_BASE + 0xff, + .end = OMAP_OHCI_BASE + 4096 - 1, .flags = IORESOURCE_MEM, }, { - .start = INT_USB_IRQ_HGEN, + .start = INT_USB_HHC_1, .flags = IORESOURCE_IRQ, }, }; @@ -477,7 +361,7 @@ static struct resource otg_resources[] = { .end = OTG_BASE + 0xff, .flags = IORESOURCE_MEM, }, { - .start = INT_USB_IRQ_OTG, + .start = IH2_BASE + 8, .flags = IORESOURCE_IRQ, }, }; @@ -501,7 +385,7 @@ static struct platform_device otg_device = { // FIXME correct answer depends on hmc_mode, -// as does (on omap1) any nonzero value for config->otg port number +// as does any nonzero value for config->otg port number #ifdef CONFIG_USB_GADGET_OMAP #define is_usb0_device(config) 1 #else @@ -542,13 +426,12 @@ omap_otg_init(struct omap_usb_config *config) if (config->otg) syscon |= OTG_EN; #endif - if (cpu_class_is_omap1()) - pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG); + pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG); pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon); OTG_SYSCON_2_REG = syscon; printk("USB: hmc %d", config->hmc_mode); - if (!alt_pingroup) + if (alt_pingroup) printk(", usb2 alt %d wires", config->pins[2]); else if (config->pins[0]) printk(", usb0 %d wires%s", config->pins[0], @@ -561,12 +444,10 @@ omap_otg_init(struct omap_usb_config *config) printk(", Mini-AB on usb%d", config->otg - 1); printk("\n"); - if (cpu_class_is_omap1()) { - /* leave USB clocks/controllers off until needed */ - ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ; - ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN; - ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK; - } + /* leave USB clocks/controllers off until needed */ + ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ; + ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN; + ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK; syscon = OTG_SYSCON_1_REG; syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN; @@ -704,7 +585,7 @@ omap_usb_init(void) } platform_data = *config; - if (cpu_is_omap730() || cpu_is_omap16xx() || cpu_is_omap24xx()) + if (cpu_is_omap730() || cpu_is_omap16xx()) omap_otg_init(&platform_data); else if (cpu_is_omap15xx()) omap_1510_usb_init(&platform_data); diff --git a/trunk/arch/arm/plat-s3c24xx/sleep.S b/trunk/arch/arm/plat-s3c24xx/sleep.S index 7b7ae790b00d..435349dc3243 100644 --- a/trunk/arch/arm/plat-s3c24xx/sleep.S +++ b/trunk/arch/arm/plat-s3c24xx/sleep.S @@ -1,4 +1,4 @@ -/* linux/arch/arm/plat-s3c24xx/sleep.S +/* linux/arch/arm/mach-s3c2410/sleep.S * * Copyright (c) 2004 Simtec Electronics * Ben Dooks diff --git a/trunk/arch/avr32/Makefile b/trunk/arch/avr32/Makefile index dc6bc01f232c..6115fc1f0cfa 100644 --- a/trunk/arch/avr32/Makefile +++ b/trunk/arch/avr32/Makefile @@ -16,7 +16,7 @@ AFLAGS += -mrelax -mno-pic CFLAGS_MODULE += -mno-relax LDFLAGS_vmlinux += --relax -cpuflags-$(CONFIG_CPU_AT32AP7000) += -mcpu=ap7000 +cpuflags-$(CONFIG_CPU_AP7000) += -mcpu=ap7000 CFLAGS += $(cpuflags-y) AFLAGS += $(cpuflags-y) diff --git a/trunk/arch/avr32/kernel/process.c b/trunk/arch/avr32/kernel/process.c index 13f988402613..4e4181ed1c6d 100644 --- a/trunk/arch/avr32/kernel/process.c +++ b/trunk/arch/avr32/kernel/process.c @@ -330,13 +330,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, { struct pt_regs *childregs; - childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)task_stack_page(p))) - 1; + childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)p->thread_info)) - 1; *childregs = *regs; if (user_mode(regs)) childregs->sp = usp; else - childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; + childregs->sp = (unsigned long)p->thread_info + THREAD_SIZE; childregs->r12 = 0; /* Set return value for child */ @@ -403,7 +403,7 @@ unsigned long get_wchan(struct task_struct *p) if (!p || p == current || p->state == TASK_RUNNING) return 0; - stack_page = (unsigned long)task_stack_page(p); + stack_page = (unsigned long)p->thread_info; BUG_ON(!stack_page); /* diff --git a/trunk/arch/avr32/kernel/ptrace.c b/trunk/arch/avr32/kernel/ptrace.c index 3c36c2d16148..8ac74dddbbde 100644 --- a/trunk/arch/avr32/kernel/ptrace.c +++ b/trunk/arch/avr32/kernel/ptrace.c @@ -24,7 +24,7 @@ static struct pt_regs *get_user_regs(struct task_struct *tsk) { - return (struct pt_regs *)((unsigned long)task_stack_page(tsk) + + return (struct pt_regs *)((unsigned long) tsk->thread_info + THREAD_SIZE - sizeof(struct pt_regs)); } diff --git a/trunk/arch/avr32/kernel/syscall_table.S b/trunk/arch/avr32/kernel/syscall_table.S index 07f6a6fa340d..7c279586fbba 100644 --- a/trunk/arch/avr32/kernel/syscall_table.S +++ b/trunk/arch/avr32/kernel/syscall_table.S @@ -291,5 +291,4 @@ sys_call_table: .long sys_shmget /* 275 */ .long sys_shmdt .long sys_shmctl - .long sys_utimensat .long sys_ni_syscall /* r8 is saturated at nr_syscalls */ diff --git a/trunk/arch/avr32/kernel/traps.c b/trunk/arch/avr32/kernel/traps.c index 86d107511dd4..4de9edf96ed2 100644 --- a/trunk/arch/avr32/kernel/traps.c +++ b/trunk/arch/avr32/kernel/traps.c @@ -123,7 +123,7 @@ asmlinkage void do_address_exception(unsigned long ecr, struct pt_regs *regs) /* This way of handling undefined instructions is stolen from ARM */ static LIST_HEAD(undef_hook); -static DEFINE_SPINLOCK(undef_lock); +static spinlock_t undef_lock = SPIN_LOCK_UNLOCKED; void register_undef_hook(struct undef_hook *hook) { diff --git a/trunk/arch/avr32/kernel/vmlinux.lds.c b/trunk/arch/avr32/kernel/vmlinux.lds.c index e7f72c995a32..7ad20cfb48a8 100644 --- a/trunk/arch/avr32/kernel/vmlinux.lds.c +++ b/trunk/arch/avr32/kernel/vmlinux.lds.c @@ -35,7 +35,7 @@ SECTIONS _einittext = .; . = ALIGN(4); __tagtable_begin = .; - *(.taglist.init) + *(.taglist) __tagtable_end = .; *(.init.data) . = ALIGN(16); diff --git a/trunk/arch/avr32/mach-at32ap/clock.c b/trunk/arch/avr32/mach-at32ap/clock.c index 0f8c89c9f832..00c435452d7e 100644 --- a/trunk/arch/avr32/mach-at32ap/clock.c +++ b/trunk/arch/avr32/mach-at32ap/clock.c @@ -18,7 +18,7 @@ #include "clock.h" -static DEFINE_SPINLOCK(clk_lock); +static spinlock_t clk_lock = SPIN_LOCK_UNLOCKED; struct clk *clk_get(struct device *dev, const char *id) { diff --git a/trunk/arch/avr32/mm/dma-coherent.c b/trunk/arch/avr32/mm/dma-coherent.c index 099212d4567c..b68d669f823d 100644 --- a/trunk/arch/avr32/mm/dma-coherent.c +++ b/trunk/arch/avr32/mm/dma-coherent.c @@ -112,21 +112,16 @@ void dma_free_coherent(struct device *dev, size_t size, } EXPORT_SYMBOL(dma_free_coherent); +#if 0 void *dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp) { struct page *page; - dma_addr_t phys; page = __dma_alloc(dev, size, handle, gfp); - if (!page) - return NULL; - - phys = page_to_phys(page); - *handle = phys; /* Now, map the page into P3 with write-combining turned on */ - return __ioremap(phys, size, _PAGE_BUFFER); + return __ioremap(page_to_phys(page), size, _PAGE_BUFFER); } EXPORT_SYMBOL(dma_alloc_writecombine); @@ -137,7 +132,8 @@ void dma_free_writecombine(struct device *dev, size_t size, iounmap(cpu_addr); - page = phys_to_page(handle); + page = bus_to_page(handle); __dma_free(dev, size, page, handle); } EXPORT_SYMBOL(dma_free_writecombine); +#endif diff --git a/trunk/arch/blackfin/kernel/asm-offsets.c b/trunk/arch/blackfin/kernel/asm-offsets.c index e455f4504509..41d9a9f89700 100644 --- a/trunk/arch/blackfin/kernel/asm-offsets.c +++ b/trunk/arch/blackfin/kernel/asm-offsets.c @@ -46,7 +46,7 @@ int main(void) DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked)); DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); - DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack)); + DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info)); DEFINE(TASK_MM, offsetof(struct task_struct, mm)); DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, pending)); diff --git a/trunk/arch/blackfin/kernel/ptrace.c b/trunk/arch/blackfin/kernel/ptrace.c index e718bb4a1ef0..d7c8e514cb92 100644 --- a/trunk/arch/blackfin/kernel/ptrace.c +++ b/trunk/arch/blackfin/kernel/ptrace.c @@ -73,7 +73,7 @@ static inline struct pt_regs *get_user_regs(struct task_struct *task) { return (struct pt_regs *) - ((unsigned long)task_stack_page(task) + + ((unsigned long)task->thread_info + (THREAD_SIZE - sizeof(struct pt_regs))); } @@ -99,7 +99,7 @@ static inline long get_reg(struct task_struct *task, int regno) unsigned char *reg_ptr; struct pt_regs *regs = - (struct pt_regs *)((unsigned long)task_stack_page(task) + + (struct pt_regs *)((unsigned long)task->thread_info + (THREAD_SIZE - sizeof(struct pt_regs))); reg_ptr = (char *)regs; @@ -125,7 +125,7 @@ put_reg(struct task_struct *task, int regno, unsigned long data) char * reg_ptr; struct pt_regs *regs = - (struct pt_regs *)((unsigned long)task_stack_page(task) + + (struct pt_regs *)((unsigned long)task->thread_info + (THREAD_SIZE - sizeof(struct pt_regs))); reg_ptr = (char *)regs; diff --git a/trunk/arch/cris/arch-v32/drivers/Kconfig b/trunk/arch/cris/arch-v32/drivers/Kconfig index 1d859c16931e..f64624fc4504 100644 --- a/trunk/arch/cris/arch-v32/drivers/Kconfig +++ b/trunk/arch/cris/arch-v32/drivers/Kconfig @@ -603,7 +603,7 @@ config ETRAX_CARDBUS select HOTPLUG select PCCARD_NONSTATIC help - Enabled the ETRAX Cardbus driver. + Enabled the ETRAX Carbus driver. config PCI bool diff --git a/trunk/arch/frv/Kconfig b/trunk/arch/frv/Kconfig index 114738a45582..eed694312a79 100644 --- a/trunk/arch/frv/Kconfig +++ b/trunk/arch/frv/Kconfig @@ -45,15 +45,15 @@ config TIME_LOW_RES bool default y -config QUICKLIST +config ARCH_HAS_ILOG2_U32 bool default y -config ARCH_HAS_ILOG2_U32 +config ARCH_HAS_ILOG2_U64 bool default y -config ARCH_HAS_ILOG2_U64 +config ARCH_USES_SLAB_PAGE_STRUCT bool default y diff --git a/trunk/arch/frv/kernel/process.c b/trunk/arch/frv/kernel/process.c index 9583a338e9d6..515a5cea5469 100644 --- a/trunk/arch/frv/kernel/process.c +++ b/trunk/arch/frv/kernel/process.c @@ -25,14 +25,12 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include @@ -90,8 +88,6 @@ void cpu_idle(void) while (!need_resched()) { irq_stat[cpu].idle_timestamp = jiffies; - check_pgt_cache(); - if (!frv_dma_inprogress && idle) idle(); } diff --git a/trunk/arch/frv/mm/pgalloc.c b/trunk/arch/frv/mm/pgalloc.c index 7787c3cc52c6..598a26ab8ad8 100644 --- a/trunk/arch/frv/mm/pgalloc.c +++ b/trunk/arch/frv/mm/pgalloc.c @@ -13,12 +13,12 @@ #include #include #include -#include #include #include #include pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((aligned(PAGE_SIZE))); +struct kmem_cache *pgd_cache; pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) { @@ -100,7 +100,7 @@ static inline void pgd_list_del(pgd_t *pgd) set_page_private(next, (unsigned long) pprev); } -void pgd_ctor(void *pgd) +void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused) { unsigned long flags; @@ -120,7 +120,7 @@ void pgd_ctor(void *pgd) } /* never called when PTRS_PER_PMD > 1 */ -void pgd_dtor(void *pgd) +void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused) { unsigned long flags; /* can be called from interrupt context */ @@ -133,7 +133,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm) { pgd_t *pgd; - pgd = quicklist_alloc(0, GFP_KERNEL, pgd_ctor); + pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL); if (!pgd) return pgd; @@ -143,15 +143,15 @@ pgd_t *pgd_alloc(struct mm_struct *mm) void pgd_free(pgd_t *pgd) { /* in the non-PAE case, clear_page_tables() clears user pgd entries */ - quicklist_free(0, pgd_dtor, pgd); + kmem_cache_free(pgd_cache, pgd); } void __init pgtable_cache_init(void) { + pgd_cache = kmem_cache_create("pgd", + PTRS_PER_PGD * sizeof(pgd_t), + PTRS_PER_PGD * sizeof(pgd_t), + SLAB_PANIC, + pgd_ctor, + pgd_dtor); } - -void check_pgt_cache(void) -{ - quicklist_trim(0, pgd_dtor, 25, 16); -} - diff --git a/trunk/arch/h8300/Kconfig.debug b/trunk/arch/h8300/Kconfig.debug index 554efe604a08..e0e9bcb015a9 100644 --- a/trunk/arch/h8300/Kconfig.debug +++ b/trunk/arch/h8300/Kconfig.debug @@ -21,12 +21,12 @@ config GDB_MAGICPRINT bool "Message Output for GDB MagicPrint service" depends on (H8300H_SIM || H8S_SIM) help - kernel messages output using MagicPrint service from GDB + kernel messages output useing MagicPrint service from GDB config SYSCALL_PRINT bool "SystemCall trace print" help - output history of systemcall + outout history of systemcall config GDB_DEBUG bool "Use gdb stub" diff --git a/trunk/arch/h8300/kernel/asm-offsets.c b/trunk/arch/h8300/kernel/asm-offsets.c index fc30b4fd0914..b78b82ad28a3 100644 --- a/trunk/arch/h8300/kernel/asm-offsets.c +++ b/trunk/arch/h8300/kernel/asm-offsets.c @@ -30,7 +30,7 @@ int main(void) DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked)); DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); - DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack)); + DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info)); DEFINE(TASK_MM, offsetof(struct task_struct, mm)); DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); diff --git a/trunk/arch/i386/Kconfig b/trunk/arch/i386/Kconfig index 30944ee2e61a..64ad10f984a1 100644 --- a/trunk/arch/i386/Kconfig +++ b/trunk/arch/i386/Kconfig @@ -858,9 +858,9 @@ config RELOCATABLE bool "Build a relocatable kernel(EXPERIMENTAL)" depends on EXPERIMENTAL help - This builds a kernel image that retains relocation information + This build a kernel image that retains relocation information so it can be loaded someplace besides the default 1MB. - The relocations tend to make the kernel binary about 10% larger, + The relocations tend to the kernel binary about 10% larger, but are discarded at runtime. One use is for the kexec on panic case where the recovery kernel diff --git a/trunk/arch/i386/Kconfig.cpu b/trunk/arch/i386/Kconfig.cpu index d7f6fb0b30f2..dce6124cb842 100644 --- a/trunk/arch/i386/Kconfig.cpu +++ b/trunk/arch/i386/Kconfig.cpu @@ -108,7 +108,7 @@ config MCORE2 bool "Core 2/newer Xeon" help Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and 53xx) - CPUs. You can distinguish newer from older Xeons by the CPU family + CPUs. You can distingush newer from older Xeons by the CPU family in /proc/cpuinfo. Newer ones have 6. config MPENTIUM4 @@ -172,7 +172,7 @@ config MWINCHIP3D help Select this for an IDT Winchip-2A or 3. Linux and GCC treat this chip as a 586TSC with some extended instructions - and alignment requirements. Also enable out of order memory + and alignment reqirements. Also enable out of order memory stores for this CPU, which can increase performance of some operations. diff --git a/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c b/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c index e5be819492ef..80b4c5d421b1 100644 --- a/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c +++ b/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c @@ -733,11 +733,9 @@ static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb, sys_dev = get_cpu_sysdev(cpu); switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: cache_add_dev(sys_dev); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: cache_remove_dev(sys_dev); break; } diff --git a/trunk/arch/i386/kernel/cpu/mcheck/therm_throt.c b/trunk/arch/i386/kernel/cpu/mcheck/therm_throt.c index 7ba7c3abd3a4..065005c3f168 100644 --- a/trunk/arch/i386/kernel/cpu/mcheck/therm_throt.c +++ b/trunk/arch/i386/kernel/cpu/mcheck/therm_throt.c @@ -1,5 +1,5 @@ /* - * linux/arch/i386/kernel/cpu/mcheck/therm_throt.c + * linux/arch/i386/kerne/cpu/mcheck/therm_throt.c * * Thermal throttle event support code (such as syslog messaging and rate * limiting) that was factored out from x86_64 (mce_intel.c) and i386 (p4.c). @@ -137,12 +137,10 @@ static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb, mutex_lock(&therm_cpu_lock); switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: err = thermal_throttle_add_dev(sys_dev); WARN_ON(err); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: thermal_throttle_remove_dev(sys_dev); break; } diff --git a/trunk/arch/i386/kernel/cpu/transmeta.c b/trunk/arch/i386/kernel/cpu/transmeta.c index 200fb3f9ebfb..6471a5a13202 100644 --- a/trunk/arch/i386/kernel/cpu/transmeta.c +++ b/trunk/arch/i386/kernel/cpu/transmeta.c @@ -77,10 +77,8 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c) set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); /* If we can run i686 user-space code, call us an i686 */ -#define USER686 ((1 << X86_FEATURE_TSC)|\ - (1 << X86_FEATURE_CX8)|\ - (1 << X86_FEATURE_CMOV)) - if (c->x86 == 5 && (c->x86_capability[0] & USER686) == USER686) +#define USER686 (X86_FEATURE_TSC|X86_FEATURE_CX8|X86_FEATURE_CMOV) + if ( c->x86 == 5 && (c->x86_capability[0] & USER686) == USER686 ) c->x86 = 6; #ifdef CONFIG_SYSCTL diff --git a/trunk/arch/i386/kernel/cpuid.c b/trunk/arch/i386/kernel/cpuid.c index 5c2faa10e9fa..eeae0d992337 100644 --- a/trunk/arch/i386/kernel/cpuid.c +++ b/trunk/arch/i386/kernel/cpuid.c @@ -169,11 +169,9 @@ static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long ac switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: cpuid_device_create(cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu)); break; } diff --git a/trunk/arch/i386/kernel/head.S b/trunk/arch/i386/kernel/head.S index f74dfc419b56..9b10af65faaa 100644 --- a/trunk/arch/i386/kernel/head.S +++ b/trunk/arch/i386/kernel/head.S @@ -71,6 +71,12 @@ INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_ .section .text.head,"ax",@progbits ENTRY(startup_32) +#ifdef CONFIG_PARAVIRT + movl %cs, %eax + testl $0x3, %eax + jnz startup_paravirt +#endif + /* * Set segments to known values. */ @@ -495,6 +501,38 @@ ignore_int: iret .section .text +#ifdef CONFIG_PARAVIRT +startup_paravirt: + cld + movl $(init_thread_union+THREAD_SIZE),%esp + + /* We take pains to preserve all the regs. */ + pushl %edx + pushl %ecx + pushl %eax + + pushl $__start_paravirtprobe +1: + movl 0(%esp), %eax + cmpl $__stop_paravirtprobe, %eax + je unhandled_paravirt + pushl (%eax) + movl 8(%esp), %eax + call *(%esp) + popl %eax + + movl 4(%esp), %eax + movl 8(%esp), %ecx + movl 12(%esp), %edx + + addl $4, (%esp) + jmp 1b + +unhandled_paravirt: + /* Nothing wanted us: we're screwed. */ + ud2 +#endif + /* * Real beginning of normal "text" segment */ diff --git a/trunk/arch/i386/kernel/microcode.c b/trunk/arch/i386/kernel/microcode.c index 83f825f2e2d7..cbe7ec8dbb9f 100644 --- a/trunk/arch/i386/kernel/microcode.c +++ b/trunk/arch/i386/kernel/microcode.c @@ -567,7 +567,7 @@ static int cpu_request_microcode(int cpu) return error; } -static int apply_microcode_check_cpu(int cpu) +static int apply_microcode_on_cpu(int cpu) { struct cpuinfo_x86 *c = cpu_data + cpu; struct ucode_cpu_info *uci = ucode_cpu_info + cpu; @@ -575,9 +575,8 @@ static int apply_microcode_check_cpu(int cpu) unsigned int val[2]; int err = 0; - /* Check if the microcode is available */ if (!uci->mc) - return 0; + return -EINVAL; old = current->cpus_allowed; set_cpus_allowed(current, cpumask_of_cpu(cpu)); @@ -615,7 +614,7 @@ static int apply_microcode_check_cpu(int cpu) return err; } -static void microcode_init_cpu(int cpu, int resume) +static void microcode_init_cpu(int cpu) { cpumask_t old; struct ucode_cpu_info *uci = ucode_cpu_info + cpu; @@ -625,7 +624,8 @@ static void microcode_init_cpu(int cpu, int resume) set_cpus_allowed(current, cpumask_of_cpu(cpu)); mutex_lock(µcode_mutex); collect_cpu_info(cpu); - if (uci->valid && system_state == SYSTEM_RUNNING && !resume) + if (uci->valid && system_state == SYSTEM_RUNNING && + !suspend_cpu_hotplug) cpu_request_microcode(cpu); mutex_unlock(µcode_mutex); set_cpus_allowed(current, old); @@ -702,7 +702,7 @@ static struct attribute_group mc_attr_group = { .name = "microcode", }; -static int __mc_sysdev_add(struct sys_device *sys_dev, int resume) +static int mc_sysdev_add(struct sys_device *sys_dev) { int err, cpu = sys_dev->id; struct ucode_cpu_info *uci = ucode_cpu_info + cpu; @@ -711,31 +711,39 @@ static int __mc_sysdev_add(struct sys_device *sys_dev, int resume) return 0; pr_debug("Microcode:CPU %d added\n", cpu); - memset(uci, 0, sizeof(*uci)); + /* If suspend_cpu_hotplug is set, the system is resuming and we should + * use the data from before the suspend. + */ + if (suspend_cpu_hotplug) { + err = apply_microcode_on_cpu(cpu); + if (err) + microcode_fini_cpu(cpu); + } + if (!uci->valid) + memset(uci, 0, sizeof(*uci)); err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); if (err) return err; - microcode_init_cpu(cpu, resume); + if (!uci->valid) + microcode_init_cpu(cpu); return 0; } -static int mc_sysdev_add(struct sys_device *sys_dev) -{ - return __mc_sysdev_add(sys_dev, 0); -} - static int mc_sysdev_remove(struct sys_device *sys_dev) { int cpu = sys_dev->id; if (!cpu_online(cpu)) return 0; - pr_debug("Microcode:CPU %d removed\n", cpu); - microcode_fini_cpu(cpu); + /* If suspend_cpu_hotplug is set, the system is suspending and we should + * keep the microcode in memory for the resume. + */ + if (!suspend_cpu_hotplug) + microcode_fini_cpu(cpu); sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); return 0; } @@ -766,34 +774,13 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) sys_dev = get_cpu_sysdev(cpu); switch (action) { - case CPU_UP_CANCELED_FROZEN: - /* The CPU refused to come up during a system resume */ - microcode_fini_cpu(cpu); - break; case CPU_ONLINE: case CPU_DOWN_FAILED: mc_sysdev_add(sys_dev); break; - case CPU_ONLINE_FROZEN: - /* System-wide resume is in progress, try to apply microcode */ - if (apply_microcode_check_cpu(cpu)) { - /* The application of microcode failed */ - microcode_fini_cpu(cpu); - __mc_sysdev_add(sys_dev, 1); - break; - } - case CPU_DOWN_FAILED_FROZEN: - if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) - printk(KERN_ERR "Microcode: Failed to create the sysfs " - "group for CPU%d\n", cpu); - break; case CPU_DOWN_PREPARE: mc_sysdev_remove(sys_dev); break; - case CPU_DOWN_PREPARE_FROZEN: - /* Suspend is in progress, only remove the interface */ - sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); - break; } return NOTIFY_OK; } diff --git a/trunk/arch/i386/kernel/msr.c b/trunk/arch/i386/kernel/msr.c index 0c1069b8d638..8cd0a91ce107 100644 --- a/trunk/arch/i386/kernel/msr.c +++ b/trunk/arch/i386/kernel/msr.c @@ -153,11 +153,9 @@ static int msr_class_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: msr_device_create(cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu)); break; } diff --git a/trunk/arch/i386/kernel/paravirt.c b/trunk/arch/i386/kernel/paravirt.c index faab09abca5e..5c10f376bce1 100644 --- a/trunk/arch/i386/kernel/paravirt.c +++ b/trunk/arch/i386/kernel/paravirt.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include diff --git a/trunk/arch/i386/kernel/traps.c b/trunk/arch/i386/kernel/traps.c index c05e7e861b29..4bec0cbf407a 100644 --- a/trunk/arch/i386/kernel/traps.c +++ b/trunk/arch/i386/kernel/traps.c @@ -305,7 +305,7 @@ void show_registers(struct pt_regs *regs) regs->xds & 0xffff, regs->xes & 0xffff, regs->xfs & 0xffff, gs, ss); printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)", TASK_COMM_LEN, current->comm, current->pid, - current_thread_info(), current, task_thread_info(current)); + current_thread_info(), current, current->thread_info); /* * When in-kernel, we also print out the stack and code at the * time of the fault.. diff --git a/trunk/arch/i386/kernel/vmlinux.lds.S b/trunk/arch/i386/kernel/vmlinux.lds.S index 80bec6640230..23e8614edeee 100644 --- a/trunk/arch/i386/kernel/vmlinux.lds.S +++ b/trunk/arch/i386/kernel/vmlinux.lds.S @@ -78,6 +78,12 @@ SECTIONS CONSTRUCTORS } :data + .paravirtprobe : AT(ADDR(.paravirtprobe) - LOAD_OFFSET) { + __start_paravirtprobe = .; + *(.paravirtprobe) + __stop_paravirtprobe = .; + } + . = ALIGN(4096); .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { __nosave_begin = .; diff --git a/trunk/arch/i386/mach-generic/probe.c b/trunk/arch/i386/mach-generic/probe.c index 74f3da634423..a7b3999bb37a 100644 --- a/trunk/arch/i386/mach-generic/probe.c +++ b/trunk/arch/i386/mach-generic/probe.c @@ -119,7 +119,9 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) return 0; } +#ifdef CONFIG_SMP int hard_smp_processor_id(void) { return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID)); } +#endif diff --git a/trunk/arch/i386/mach-voyager/voyager_basic.c b/trunk/arch/i386/mach-voyager/voyager_basic.c index 9b77b39b71a6..8fe7e4593d5f 100644 --- a/trunk/arch/i386/mach-voyager/voyager_basic.c +++ b/trunk/arch/i386/mach-voyager/voyager_basic.c @@ -292,8 +292,8 @@ machine_emergency_restart(void) void mca_nmi_hook(void) { - __u8 dumpval __maybe_unused = inb(0xf823); - __u8 swnmi __maybe_unused = inb(0xf813); + __u8 dumpval __attribute__((unused)) = inb(0xf823); + __u8 swnmi __attribute__((unused)) = inb(0xf813); /* FIXME: assume dump switch pressed */ /* check to see if the dump switch was pressed */ diff --git a/trunk/arch/i386/pci/init.c b/trunk/arch/i386/pci/init.c index 3de9f9ba2da6..1cf11af96de2 100644 --- a/trunk/arch/i386/pci/init.c +++ b/trunk/arch/i386/pci/init.c @@ -6,7 +6,7 @@ in the right sequence from here. */ static __init int pci_access_init(void) { - int type __maybe_unused = 0; + int type __attribute__((unused)) = 0; #ifdef CONFIG_PCI_DIRECT type = pci_direct_probe(); diff --git a/trunk/arch/ia64/Kconfig b/trunk/arch/ia64/Kconfig index 6e41471449c0..e23af4b6ae8c 100644 --- a/trunk/arch/ia64/Kconfig +++ b/trunk/arch/ia64/Kconfig @@ -468,7 +468,7 @@ config KEXEC help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot - but it is independent of the system firmware. And like a reboot + but it is indepedent of the system firmware. And like a reboot you can start any kernel with it, not just Linux. The name comes from the similiarity to the exec system call. diff --git a/trunk/arch/ia64/ia32/ia32_entry.S b/trunk/arch/ia64/ia32/ia32_entry.S index 99b665e2b1d5..687e5fdc9683 100644 --- a/trunk/arch/ia64/ia32/ia32_entry.S +++ b/trunk/arch/ia64/ia32/ia32_entry.S @@ -52,6 +52,43 @@ ENTRY(ia32_clone) br.ret.sptk.many rp END(ia32_clone) +ENTRY(sys32_rt_sigsuspend) + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) + alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs + mov loc0=rp + mov out0=in0 // mask + mov out1=in1 // sigsetsize + mov out2=sp // out2 = &sigscratch + .fframe 16 + adds sp=-16,sp // allocate dummy "sigscratch" + ;; + .body + br.call.sptk.many rp=ia32_rt_sigsuspend +1: .restore sp + adds sp=16,sp + mov rp=loc0 + mov ar.pfs=loc1 + br.ret.sptk.many rp +END(sys32_rt_sigsuspend) + +ENTRY(sys32_sigsuspend) + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) + alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs + mov loc0=rp + mov out0=in2 // mask (first two args are ignored) + ;; + mov out1=sp // out1 = &sigscratch + .fframe 16 + adds sp=-16,sp // allocate dummy "sigscratch" + .body + br.call.sptk.many rp=ia32_sigsuspend +1: .restore sp + adds sp=16,sp + mov rp=loc0 + mov ar.pfs=loc1 + br.ret.sptk.many rp +END(sys32_sigsuspend) + GLOBAL_ENTRY(ia32_ret_from_clone) PT_REGS_UNWIND_INFO(0) { /* @@ -352,7 +389,7 @@ ia32_syscall_table: data8 sys_rt_sigpending data8 compat_sys_rt_sigtimedwait data8 sys32_rt_sigqueueinfo - data8 compat_sys_rt_sigsuspend + data8 sys32_rt_sigsuspend data8 sys32_pread /* 180 */ data8 sys32_pwrite data8 sys_chown /* 16-bit version */ diff --git a/trunk/arch/ia64/ia32/ia32_signal.c b/trunk/arch/ia64/ia32/ia32_signal.c index 85e82f32e480..10510e585204 100644 --- a/trunk/arch/ia64/ia32/ia32_signal.c +++ b/trunk/arch/ia64/ia32/ia32_signal.c @@ -451,20 +451,59 @@ sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int r sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler); } -asmlinkage long -sys32_sigsuspend (int history0, int history1, old_sigset_t mask) +long +__ia32_rt_sigsuspend (compat_sigset_t *sset, unsigned int sigsetsize, struct sigscratch *scr) { - mask &= _BLOCKABLE; + extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall); + sigset_t oldset, set; + + scr->scratch_unat = 0; /* avoid leaking kernel bits to user level */ + memset(&set, 0, sizeof(set)); + + memcpy(&set.sig, &sset->sig, sigsetsize); + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); + { + oldset = current->blocked; + current->blocked = set; + recalc_sigpending(); + } spin_unlock_irq(¤t->sighand->siglock); - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_thread_flag(TIF_RESTORE_SIGMASK); - return -ERESTARTNOHAND; + /* + * The return below usually returns to the signal handler. We need to pre-set the + * correct error code here to ensure that the right values get saved in sigcontext + * by ia64_do_signal. + */ + scr->pt.r8 = -EINTR; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (ia64_do_signal(&oldset, scr, 1)) + return -EINTR; + } +} + +asmlinkage long +ia32_rt_sigsuspend (compat_sigset_t __user *uset, unsigned int sigsetsize, struct sigscratch *scr) +{ + compat_sigset_t set; + + if (sigsetsize > sizeof(compat_sigset_t)) + return -EINVAL; + + if (copy_from_user(&set.sig, &uset->sig, sigsetsize)) + return -EFAULT; + + return __ia32_rt_sigsuspend(&set, sigsetsize, scr); +} + +asmlinkage long +ia32_sigsuspend (unsigned int mask, struct sigscratch *scr) +{ + return __ia32_rt_sigsuspend((compat_sigset_t *) &mask, sizeof(mask), scr); } asmlinkage long @@ -771,11 +810,7 @@ get_sigframe (struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) } /* Legacy stack switching not supported */ - esp -= frame_size; - /* Align the stack pointer according to the i386 ABI, - * i.e. so that on function entry ((sp + 4) & 15) == 0. */ - esp = ((esp + 4) & -16ul) - 4; - return (void __user *) esp; + return (void __user *)((esp - frame_size) & -8ul); } static int diff --git a/trunk/arch/ia64/kernel/entry.S b/trunk/arch/ia64/kernel/entry.S index b50bf208678e..55fd2d5471e1 100644 --- a/trunk/arch/ia64/kernel/entry.S +++ b/trunk/arch/ia64/kernel/entry.S @@ -1199,6 +1199,32 @@ ENTRY(notify_resume_user) br.ret.sptk.many rp END(notify_resume_user) +GLOBAL_ENTRY(sys_rt_sigsuspend) + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) + alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart! + mov r9=ar.unat + mov loc0=rp // save return address + mov out0=in0 // mask + mov out1=in1 // sigsetsize + adds out2=8,sp // out2=&sigscratch->ar_pfs + ;; + .fframe 16 + .spillsp ar.unat, 16 + st8 [sp]=r9,-16 // allocate space for ar.unat and save it + st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch + .body + br.call.sptk.many rp=ia64_rt_sigsuspend +.ret17: .restore sp + adds sp=16,sp // pop scratch stack space + ;; + ld8 r9=[sp] // load new unat from sw->caller_unat + mov rp=loc0 + ;; + mov ar.unat=r9 + mov ar.pfs=loc1 + br.ret.sptk.many rp +END(sys_rt_sigsuspend) + ENTRY(sys_rt_sigreturn) PT_REGS_UNWIND_INFO(0) /* @@ -1572,8 +1598,8 @@ sys_call_table: data8 sys_readlinkat data8 sys_fchmodat data8 sys_faccessat - data8 sys_pselect6 - data8 sys_ppoll + data8 sys_ni_syscall // reserved for pselect + data8 sys_ni_syscall // 1295 reserved for ppoll data8 sys_unshare data8 sys_splice data8 sys_set_robust_list diff --git a/trunk/arch/ia64/kernel/err_inject.c b/trunk/arch/ia64/kernel/err_inject.c index 6a49600cf337..d3e9f33e8bdd 100644 --- a/trunk/arch/ia64/kernel/err_inject.c +++ b/trunk/arch/ia64/kernel/err_inject.c @@ -236,11 +236,9 @@ static int __cpuinit err_inject_cpu_callback(struct notifier_block *nfb, sys_dev = get_cpu_sysdev(cpu); switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: err_inject_add_dev(sys_dev); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: err_inject_remove_dev(sys_dev); break; } diff --git a/trunk/arch/ia64/kernel/iosapic.c b/trunk/arch/ia64/kernel/iosapic.c index 37f46527d233..93d9ab14ba24 100644 --- a/trunk/arch/ia64/kernel/iosapic.c +++ b/trunk/arch/ia64/kernel/iosapic.c @@ -1012,7 +1012,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, /* * ACPI calls this when it finds an entry for a legacy ISA IRQ override. */ -void __devinit +void __init iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, unsigned long polarity, unsigned long trigger) diff --git a/trunk/arch/ia64/kernel/irq_ia64.c b/trunk/arch/ia64/kernel/irq_ia64.c index bc47049f060f..1c5044a80958 100644 --- a/trunk/arch/ia64/kernel/irq_ia64.c +++ b/trunk/arch/ia64/kernel/irq_ia64.c @@ -38,7 +38,6 @@ #include #include #include -#include #ifdef CONFIG_PERFMON # include @@ -127,10 +126,8 @@ void destroy_irq(unsigned int irq) #ifdef CONFIG_SMP # define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE) -# define IS_LOCAL_TLB_FLUSH(vec) (vec == IA64_IPI_LOCAL_TLB_FLUSH) #else # define IS_RESCHEDULE(vec) (0) -# define IS_LOCAL_TLB_FLUSH(vec) (0) #endif /* * That's where the IVT branches when we get an external @@ -182,11 +179,8 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) saved_tpr = ia64_getreg(_IA64_REG_CR_TPR); ia64_srlz_d(); while (vector != IA64_SPURIOUS_INT_VECTOR) { - if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { - smp_local_flush_tlb(); - kstat_this_cpu.irqs[vector]++; - } else if (unlikely(IS_RESCHEDULE(vector))) - kstat_this_cpu.irqs[vector]++; + if (unlikely(IS_RESCHEDULE(vector))) + kstat_this_cpu.irqs[vector]++; else { ia64_setreg(_IA64_REG_CR_TPR, vector); ia64_srlz_d(); @@ -232,11 +226,8 @@ void ia64_process_pending_intr(void) * Perform normal interrupt style processing */ while (vector != IA64_SPURIOUS_INT_VECTOR) { - if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { - smp_local_flush_tlb(); - kstat_this_cpu.irqs[vector]++; - } else if (unlikely(IS_RESCHEDULE(vector))) - kstat_this_cpu.irqs[vector]++; + if (unlikely(IS_RESCHEDULE(vector))) + kstat_this_cpu.irqs[vector]++; else { struct pt_regs *old_regs = set_irq_regs(NULL); @@ -268,12 +259,12 @@ void ia64_process_pending_intr(void) #ifdef CONFIG_SMP +extern irqreturn_t handle_IPI (int irq, void *dev_id); static irqreturn_t dummy_handler (int irq, void *dev_id) { BUG(); } -extern irqreturn_t handle_IPI (int irq, void *dev_id); static struct irqaction ipi_irqaction = { .handler = handle_IPI, @@ -286,13 +277,6 @@ static struct irqaction resched_irqaction = { .flags = IRQF_DISABLED, .name = "resched" }; - -static struct irqaction tlb_irqaction = { - .handler = dummy_handler, - .flags = IRQF_DISABLED, - .name = "tlb_flush" -}; - #endif void @@ -318,7 +302,6 @@ init_IRQ (void) #ifdef CONFIG_SMP register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction); register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction); - register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &tlb_irqaction); #endif #ifdef CONFIG_PERFMON pfm_init_percpu(); diff --git a/trunk/arch/ia64/kernel/mca.c b/trunk/arch/ia64/kernel/mca.c index f8ae709de0b5..1d7cc7e2ce32 100644 --- a/trunk/arch/ia64/kernel/mca.c +++ b/trunk/arch/ia64/kernel/mca.c @@ -1689,7 +1689,7 @@ format_mca_init_stack(void *mca_data, unsigned long offset, ti->preempt_count = 1; ti->task = p; ti->cpu = cpu; - p->stack = ti; + p->thread_info = ti; p->state = TASK_UNINTERRUPTIBLE; cpu_set(cpu, p->cpus_allowed); INIT_LIST_HEAD(&p->tasks); diff --git a/trunk/arch/ia64/kernel/palinfo.c b/trunk/arch/ia64/kernel/palinfo.c index 85829e27785c..a71df9ae0397 100644 --- a/trunk/arch/ia64/kernel/palinfo.c +++ b/trunk/arch/ia64/kernel/palinfo.c @@ -975,11 +975,9 @@ static int palinfo_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: create_palinfo_proc_entries(hotcpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: remove_palinfo_proc_entries(hotcpu); break; } diff --git a/trunk/arch/ia64/kernel/process.c b/trunk/arch/ia64/kernel/process.c index d1c3ed9943e5..8bb571a8a738 100644 --- a/trunk/arch/ia64/kernel/process.c +++ b/trunk/arch/ia64/kernel/process.c @@ -155,7 +155,7 @@ show_regs (struct pt_regs *regs) } void -do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall) +do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall) { if (fsys_mode(current, &scr->pt)) { /* defer signal-handling etc. until we return to privilege-level 0. */ @@ -170,8 +170,8 @@ do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall #endif /* deal with pending signal delivery */ - if (test_thread_flag(TIF_SIGPENDING)||test_thread_flag(TIF_RESTORE_SIGMASK)) - ia64_do_signal(scr, in_syscall); + if (test_thread_flag(TIF_SIGPENDING)) + ia64_do_signal(oldset, scr, in_syscall); } static int pal_halt = 1; @@ -236,7 +236,6 @@ void cpu_idle_wait(void) { unsigned int cpu, this_cpu = get_cpu(); cpumask_t map; - cpumask_t tmp = current->cpus_allowed; set_cpus_allowed(current, cpumask_of_cpu(this_cpu)); put_cpu(); @@ -258,7 +257,6 @@ void cpu_idle_wait(void) } cpus_and(map, map, cpu_online_map); } while (!cpus_empty(map)); - set_cpus_allowed(current, tmp); } EXPORT_SYMBOL_GPL(cpu_idle_wait); diff --git a/trunk/arch/ia64/kernel/relocate_kernel.S b/trunk/arch/ia64/kernel/relocate_kernel.S index 903babd22d62..ae473e3f2a0d 100644 --- a/trunk/arch/ia64/kernel/relocate_kernel.S +++ b/trunk/arch/ia64/kernel/relocate_kernel.S @@ -94,7 +94,7 @@ GLOBAL_ENTRY(relocate_new_kernel) 4: srlz.i ;; - // purge TR entry for kernel text and data + //purge TR entry for kernel text and data movl r16=KERNEL_START mov r18=KERNEL_TR_PAGE_SHIFT<<2 ;; @@ -104,6 +104,15 @@ GLOBAL_ENTRY(relocate_new_kernel) srlz.i ;; + // purge TR entry for percpu data + movl r16=PERCPU_ADDR + mov r18=PERCPU_PAGE_SHIFT<<2 + ;; + ptr.d r16,r18 + ;; + srlz.d + ;; + // purge TR entry for pal code mov r16=in3 mov r18=IA64_GRANULE_SHIFT<<2 diff --git a/trunk/arch/ia64/kernel/salinfo.c b/trunk/arch/ia64/kernel/salinfo.c index 89f6b138a62c..a51f1d0bfb70 100644 --- a/trunk/arch/ia64/kernel/salinfo.c +++ b/trunk/arch/ia64/kernel/salinfo.c @@ -582,7 +582,6 @@ salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu struct salinfo_data *data; switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: spin_lock_irqsave(&data_saved_lock, flags); for (i = 0, data = salinfo_data; i < ARRAY_SIZE(salinfo_data); @@ -593,7 +592,6 @@ salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu spin_unlock_irqrestore(&data_saved_lock, flags); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: spin_lock_irqsave(&data_saved_lock, flags); for (i = 0, data = salinfo_data; i < ARRAY_SIZE(salinfo_data); diff --git a/trunk/arch/ia64/kernel/setup.c b/trunk/arch/ia64/kernel/setup.c index 9df1efe7487d..6e19da122ae3 100644 --- a/trunk/arch/ia64/kernel/setup.c +++ b/trunk/arch/ia64/kernel/setup.c @@ -786,7 +786,7 @@ identify_cpu (struct cpuinfo_ia64 *c) c->unimpl_pa_mask = ~((1L<<63) | ((1L << phys_addr_size) - 1)); } -void __init +void setup_per_cpu_areas (void) { /* start_kernel() requires this... */ diff --git a/trunk/arch/ia64/kernel/sigframe.h b/trunk/arch/ia64/kernel/sigframe.h index 9fd9a1933b3d..37b986cb86e0 100644 --- a/trunk/arch/ia64/kernel/sigframe.h +++ b/trunk/arch/ia64/kernel/sigframe.h @@ -22,4 +22,4 @@ struct sigframe { struct sigcontext sc; }; -extern void ia64_do_signal (struct sigscratch *, long); +extern long ia64_do_signal (sigset_t *, struct sigscratch *, long); diff --git a/trunk/arch/ia64/kernel/signal.c b/trunk/arch/ia64/kernel/signal.c index aeec8184e862..0dcd56da6001 100644 --- a/trunk/arch/ia64/kernel/signal.c +++ b/trunk/arch/ia64/kernel/signal.c @@ -40,6 +40,47 @@ # define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0]) #endif +long +ia64_rt_sigsuspend (sigset_t __user *uset, size_t sigsetsize, struct sigscratch *scr) +{ + sigset_t oldset, set; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + if (!access_ok(VERIFY_READ, uset, sigsetsize)) + return -EFAULT; + + if (GET_SIGSET(&set, uset)) + return -EFAULT; + + sigdelsetmask(&set, ~_BLOCKABLE); + + spin_lock_irq(¤t->sighand->siglock); + { + oldset = current->blocked; + current->blocked = set; + recalc_sigpending(); + } + spin_unlock_irq(¤t->sighand->siglock); + + /* + * The return below usually returns to the signal handler. We need to + * pre-set the correct error code here to ensure that the right values + * get saved in sigcontext by ia64_do_signal. + */ + scr->pt.r8 = EINTR; + scr->pt.r10 = -1; + + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (ia64_do_signal(&oldset, scr, 1)) + return -EINTR; + } +} + asmlinkage long sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7, @@ -436,11 +477,10 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse * Note that `init' is a special process: it doesn't get signals it doesn't want to * handle. Thus you cannot kill init even with a SIGKILL even by mistake. */ -void -ia64_do_signal (struct sigscratch *scr, long in_syscall) +long +ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) { struct k_sigaction ka; - sigset_t *oldset; siginfo_t info; long restart = in_syscall; long errno = scr->pt.r8; @@ -452,11 +492,9 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) * doing anything if so. */ if (!user_mode(&scr->pt)) - return; + return 0; - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else + if (!oldset) oldset = ¤t->blocked; /* @@ -519,15 +557,8 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) * Whee! Actually deliver the signal. If the delivery failed, we need to * continue to iterate in this loop so we can deliver the SIGSEGV... */ - if (handle_signal(signr, &ka, &info, oldset, scr)) { - /* a signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - return; - } + if (handle_signal(signr, &ka, &info, oldset, scr)) + return 1; } /* Did we come from a system call? */ @@ -553,11 +584,5 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) } } } - - /* if there's no signal to deliver, we just put the saved sigmask - * back */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } + return 0; } diff --git a/trunk/arch/ia64/kernel/smp.c b/trunk/arch/ia64/kernel/smp.c index 221de3804560..55ddd809b02d 100644 --- a/trunk/arch/ia64/kernel/smp.c +++ b/trunk/arch/ia64/kernel/smp.c @@ -49,18 +49,6 @@ #include #include -/* - * Note: alignment of 4 entries/cacheline was empirically determined - * to be a good tradeoff between hot cachelines & spreading the array - * across too many cacheline. - */ -static struct local_tlb_flush_counts { - unsigned int count; -} __attribute__((__aligned__(32))) local_tlb_flush_counts[NR_CPUS]; - -static DEFINE_PER_CPU(unsigned int, shadow_flush_counts[NR_CPUS]) ____cacheline_aligned; - - /* * Structure and data for smp_call_function(). This is designed to minimise static memory * requirements. It also looks cleaner. @@ -260,62 +248,6 @@ smp_send_reschedule (int cpu) platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0); } -/* - * Called with preeemption disabled. - */ -static void -smp_send_local_flush_tlb (int cpu) -{ - platform_send_ipi(cpu, IA64_IPI_LOCAL_TLB_FLUSH, IA64_IPI_DM_INT, 0); -} - -void -smp_local_flush_tlb(void) -{ - /* - * Use atomic ops. Otherwise, the load/increment/store sequence from - * a "++" operation can have the line stolen between the load & store. - * The overhead of the atomic op in negligible in this case & offers - * significant benefit for the brief periods where lots of cpus - * are simultaneously flushing TLBs. - */ - ia64_fetchadd(1, &local_tlb_flush_counts[smp_processor_id()].count, acq); - local_flush_tlb_all(); -} - -#define FLUSH_DELAY 5 /* Usec backoff to eliminate excessive cacheline bouncing */ - -void -smp_flush_tlb_cpumask(cpumask_t xcpumask) -{ - unsigned int *counts = __ia64_per_cpu_var(shadow_flush_counts); - cpumask_t cpumask = xcpumask; - int mycpu, cpu, flush_mycpu = 0; - - preempt_disable(); - mycpu = smp_processor_id(); - - for_each_cpu_mask(cpu, cpumask) - counts[cpu] = local_tlb_flush_counts[cpu].count; - - mb(); - for_each_cpu_mask(cpu, cpumask) { - if (cpu == mycpu) - flush_mycpu = 1; - else - smp_send_local_flush_tlb(cpu); - } - - if (flush_mycpu) - smp_local_flush_tlb(); - - for_each_cpu_mask(cpu, cpumask) - while(counts[cpu] == local_tlb_flush_counts[cpu].count) - udelay(FLUSH_DELAY); - - preempt_enable(); -} - void smp_flush_tlb_all (void) { diff --git a/trunk/arch/ia64/kernel/topology.c b/trunk/arch/ia64/kernel/topology.c index 94ae3c87d828..687500ddb4b8 100644 --- a/trunk/arch/ia64/kernel/topology.c +++ b/trunk/arch/ia64/kernel/topology.c @@ -412,11 +412,9 @@ static int __cpuinit cache_cpu_callback(struct notifier_block *nfb, sys_dev = get_cpu_sysdev(cpu); switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: cache_add_dev(sys_dev); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: cache_remove_dev(sys_dev); break; } diff --git a/trunk/arch/ia64/kernel/traps.c b/trunk/arch/ia64/kernel/traps.c index b8e0d70bf989..5bfb8be02b70 100644 --- a/trunk/arch/ia64/kernel/traps.c +++ b/trunk/arch/ia64/kernel/traps.c @@ -43,9 +43,9 @@ die (const char *str, struct pt_regs *regs, long err) u32 lock_owner; int lock_owner_depth; } die = { - .lock = __SPIN_LOCK_UNLOCKED(die.lock), - .lock_owner = -1, - .lock_owner_depth = 0 + .lock = SPIN_LOCK_UNLOCKED, + .lock_owner = -1, + .lock_owner_depth = 0 }; static int die_counter; int cpu = get_cpu(); diff --git a/trunk/arch/ia64/kernel/unwind.c b/trunk/arch/ia64/kernel/unwind.c index fe1426266b9b..93d5a3b41f69 100644 --- a/trunk/arch/ia64/kernel/unwind.c +++ b/trunk/arch/ia64/kernel/unwind.c @@ -60,7 +60,6 @@ # define UNW_DEBUG_ON(n) unw_debug_level >= n /* Do not code a printk level, not all debug lines end in newline */ # define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__) -# undef inline # define inline #else /* !UNW_DEBUG */ # define UNW_DEBUG_ON(n) 0 @@ -146,7 +145,7 @@ static struct { # endif } unw = { .tables = &unw.kernel_table, - .lock = __SPIN_LOCK_UNLOCKED(unw.lock), + .lock = SPIN_LOCK_UNLOCKED, .save_order = { UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR, UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR @@ -1944,9 +1943,9 @@ EXPORT_SYMBOL(unw_unwind); int unw_unwind_to_user (struct unw_frame_info *info) { - unsigned long ip, sp, pr = info->pr; + unsigned long ip, sp, pr = 0; - do { + while (unw_unwind(info) >= 0) { unw_get_sp(info, &sp); if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp) < IA64_PT_REGS_SIZE) { @@ -1964,7 +1963,7 @@ unw_unwind_to_user (struct unw_frame_info *info) __FUNCTION__, ip); return -1; } - } while (unw_unwind(info) >= 0); + } unw_get_ip(info, &ip); UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip); diff --git a/trunk/arch/ia64/mm/tlb.c b/trunk/arch/ia64/mm/tlb.c index fa4e6d4810f3..ffad7624436c 100644 --- a/trunk/arch/ia64/mm/tlb.c +++ b/trunk/arch/ia64/mm/tlb.c @@ -32,9 +32,9 @@ static struct { } purge; struct ia64_ctx ia64_ctx = { - .lock = __SPIN_LOCK_UNLOCKED(ia64_ctx.lock), - .next = 1, - .max_ctx = ~0U + .lock = SPIN_LOCK_UNLOCKED, + .next = 1, + .max_ctx = ~0U }; DEFINE_PER_CPU(u8, ia64_need_tlb_flush); diff --git a/trunk/arch/ia64/sn/kernel/irq.c b/trunk/arch/ia64/sn/kernel/irq.c index 7f6d2360a262..8d2a1bfbfe7c 100644 --- a/trunk/arch/ia64/sn/kernel/irq.c +++ b/trunk/arch/ia64/sn/kernel/irq.c @@ -59,22 +59,6 @@ void sn_intr_free(nasid_t local_nasid, int local_widget, (u64) sn_irq_info->irq_cookie, 0, 0); } -u64 sn_intr_redirect(nasid_t local_nasid, int local_widget, - struct sn_irq_info *sn_irq_info, - nasid_t req_nasid, int req_slice) -{ - struct ia64_sal_retval ret_stuff; - ret_stuff.status = 0; - ret_stuff.v0 = 0; - - SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT, - (u64) SAL_INTR_REDIRECT, (u64) local_nasid, - (u64) local_widget, __pa(sn_irq_info), - (u64) req_nasid, (u64) req_slice, 0); - - return ret_stuff.status; -} - static unsigned int sn_startup_irq(unsigned int irq) { return 0; @@ -143,8 +127,15 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, struct sn_irq_info *new_irq_info; struct sn_pcibus_provider *pci_provider; - bridge = (u64) sn_irq_info->irq_bridge; + new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); + if (new_irq_info == NULL) + return NULL; + + memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); + + bridge = (u64) new_irq_info->irq_bridge; if (!bridge) { + kfree(new_irq_info); return NULL; /* irq is not a device interrupt */ } @@ -154,25 +145,8 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, local_widget = TIO_SWIN_WIDGETNUM(bridge); else local_widget = SWIN_WIDGETNUM(bridge); - vector = sn_irq_info->irq_irq; - - /* Make use of SAL_INTR_REDIRECT if PROM supports it */ - status = sn_intr_redirect(local_nasid, local_widget, sn_irq_info, nasid, slice); - if (!status) { - new_irq_info = sn_irq_info; - goto finish_up; - } - - /* - * PROM does not support SAL_INTR_REDIRECT, or it failed. - * Revert to old method. - */ - new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); - if (new_irq_info == NULL) - return NULL; - - memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); + vector = sn_irq_info->irq_irq; /* Free the old PROM new_irq_info structure */ sn_intr_free(local_nasid, local_widget, new_irq_info); unregister_intr_pda(new_irq_info); @@ -188,18 +162,11 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, return NULL; } - register_intr_pda(new_irq_info); - spin_lock(&sn_irq_info_lock); - list_replace_rcu(&sn_irq_info->list, &new_irq_info->list); - spin_unlock(&sn_irq_info_lock); - call_rcu(&sn_irq_info->rcu, sn_irq_info_free); - - -finish_up: /* Update kernels new_irq_info with new target info */ cpuid = nasid_slice_to_cpuid(new_irq_info->irq_nasid, new_irq_info->irq_slice); new_irq_info->irq_cpuid = cpuid; + register_intr_pda(new_irq_info); pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type]; @@ -211,6 +178,11 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, pci_provider && pci_provider->target_interrupt) (pci_provider->target_interrupt)(new_irq_info); + spin_lock(&sn_irq_info_lock); + list_replace_rcu(&sn_irq_info->list, &new_irq_info->list); + spin_unlock(&sn_irq_info_lock); + call_rcu(&sn_irq_info->rcu, sn_irq_info_free); + #ifdef CONFIG_SMP cpuphys = cpu_physical_id(cpuid); set_irq_affinity_info((vector & 0xff), cpuphys, 0); diff --git a/trunk/arch/ia64/sn/kernel/sn2/sn2_smp.c b/trunk/arch/ia64/sn/kernel/sn2/sn2_smp.c index 5d318b579fb1..601747b1e22a 100644 --- a/trunk/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/trunk/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -46,9 +46,6 @@ DECLARE_PER_CPU(struct ptc_stats, ptcstats); static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); -/* 0 = old algorithm (no IPI flushes), 1 = ipi deadlock flush, 2 = ipi instead of SHUB ptc, >2 = always ipi */ -static int sn2_flush_opt = 0; - extern unsigned long sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long, @@ -79,8 +76,6 @@ struct ptc_stats { unsigned long shub_itc_clocks; unsigned long shub_itc_clocks_max; unsigned long shub_ptc_flushes_not_my_mm; - unsigned long shub_ipi_flushes; - unsigned long shub_ipi_flushes_itc_clocks; }; #define sn2_ptctest 0 @@ -126,18 +121,6 @@ void sn_tlb_migrate_finish(struct mm_struct *mm) flush_tlb_mm(mm); } -static void -sn2_ipi_flush_all_tlb(struct mm_struct *mm) -{ - unsigned long itc; - - itc = ia64_get_itc(); - smp_flush_tlb_cpumask(mm->cpu_vm_mask); - itc = ia64_get_itc() - itc; - __get_cpu_var(ptcstats).shub_ipi_flushes_itc_clocks += itc; - __get_cpu_var(ptcstats).shub_ipi_flushes++; -} - /** * sn2_global_tlb_purge - globally purge translation cache of virtual address range * @mm: mm_struct containing virtual address range @@ -171,12 +154,7 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value, old_rr = 0; short nasids[MAX_NUMNODES], nix; nodemask_t nodes_flushed; - int active, max_active, deadlock, flush_opt = sn2_flush_opt; - - if (flush_opt > 2) { - sn2_ipi_flush_all_tlb(mm); - return; - } + int active, max_active, deadlock; nodes_clear(nodes_flushed); i = 0; @@ -211,12 +189,6 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, return; } - if (flush_opt == 2) { - sn2_ipi_flush_all_tlb(mm); - preempt_enable(); - return; - } - itc = ia64_get_itc(); nix = 0; for_each_node_mask(cnode, nodes_flushed) @@ -284,8 +256,6 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, } if (active >= max_active || i == (nix - 1)) { if ((deadlock = wait_piowc())) { - if (flush_opt == 1) - goto done; sn2_ptc_deadlock_recovery(nasids, ibegin, i, mynasid, ptc0, data0, ptc1, data1); if (reset_max_active_on_deadlock()) max_active = 1; @@ -297,7 +267,6 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, start += (1UL << nbits); } while (start < end); -done: itc2 = ia64_get_itc() - itc2; __get_cpu_var(ptcstats).shub_itc_clocks += itc2; if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max) @@ -310,11 +279,6 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, spin_unlock_irqrestore(PTC_LOCK(shub1), flags); - if (flush_opt == 1 && deadlock) { - __get_cpu_var(ptcstats).deadlocks++; - sn2_ipi_flush_all_tlb(mm); - } - preempt_enable(); } @@ -461,42 +425,24 @@ static int sn2_ptc_seq_show(struct seq_file *file, void *data) if (!cpu) { seq_printf(file, - "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2 ipi_fluches ipi_nsec\n"); - seq_printf(file, "# ptctest %d, flushopt %d\n", sn2_ptctest, sn2_flush_opt); + "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2\n"); + seq_printf(file, "# ptctest %d\n", sn2_ptctest); } if (cpu < NR_CPUS && cpu_online(cpu)) { stat = &per_cpu(ptcstats, cpu); - seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, + seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed, stat->deadlocks, 1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, 1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec, stat->shub_ptc_flushes_not_my_mm, - stat->deadlocks2, - stat->shub_ipi_flushes, - 1000 * stat->shub_ipi_flushes_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec); + stat->deadlocks2); } return 0; } -static ssize_t sn2_ptc_proc_write(struct file *file, const char __user *user, size_t count, loff_t *data) -{ - int cpu; - char optstr[64]; - - if (copy_from_user(optstr, user, count)) - return -EFAULT; - optstr[count - 1] = '\0'; - sn2_flush_opt = simple_strtoul(optstr, NULL, 0); - - for_each_online_cpu(cpu) - memset(&per_cpu(ptcstats, cpu), 0, sizeof(struct ptc_stats)); - - return count; -} - static struct seq_operations sn2_ptc_seq_ops = { .start = sn2_ptc_seq_start, .next = sn2_ptc_seq_next, @@ -512,7 +458,6 @@ static int sn2_ptc_proc_open(struct inode *inode, struct file *file) static const struct file_operations proc_sn2_ptc_operations = { .open = sn2_ptc_proc_open, .read = seq_read, - .write = sn2_ptc_proc_write, .llseek = seq_lseek, .release = seq_release, }; diff --git a/trunk/arch/m68knommu/Kconfig.debug b/trunk/arch/m68knommu/Kconfig.debug index 9ff47bd09aee..763c9aa0b4fd 100644 --- a/trunk/arch/m68knommu/Kconfig.debug +++ b/trunk/arch/m68knommu/Kconfig.debug @@ -5,7 +5,7 @@ source "lib/Kconfig.debug" config FULLDEBUG bool "Full Symbolic/Source Debugging support" help - Enable debugging symbols on kernel build. + Enable debuging symbols on kernel build. config HIGHPROFILE bool "Use fast second timer for profiling" diff --git a/trunk/arch/m68knommu/kernel/asm-offsets.c b/trunk/arch/m68knommu/kernel/asm-offsets.c index 7cd183d346ef..b988c7bdc6e4 100644 --- a/trunk/arch/m68knommu/kernel/asm-offsets.c +++ b/trunk/arch/m68knommu/kernel/asm-offsets.c @@ -31,7 +31,7 @@ int main(void) DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked)); DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); - DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack)); + DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info)); DEFINE(TASK_MM, offsetof(struct task_struct, mm)); DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); diff --git a/trunk/arch/mips/Kconfig b/trunk/arch/mips/Kconfig index 16ecea3c0813..b7cb048bc771 100644 --- a/trunk/arch/mips/Kconfig +++ b/trunk/arch/mips/Kconfig @@ -956,7 +956,7 @@ choice byte order. These modes require different kernels and a different Linux distribution. In general there is one preferred byteorder for a particular system but some systems are just as commonly used in the - one or the other endianness. + one or the other endianess. config CPU_BIG_ENDIAN bool "Big endian" @@ -1750,7 +1750,7 @@ config ARCH_DISCONTIGMEM_ENABLE bool default y if SGI_IP27 help - Say Y to support efficient handling of discontiguous physical memory, + Say Y to upport efficient handling of discontiguous physical memory, for architectures which are either NUMA (Non-Uniform Memory Access) or have huge holes in the physical address space for other reasons. See for more. @@ -1938,7 +1938,7 @@ config KEXEC help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot - but it is independent of the system firmware. And like a reboot + but it is indepedent of the system firmware. And like a reboot you can start any kernel with it, not just Linux. The name comes from the similiarity to the exec system call. diff --git a/trunk/arch/mips/Makefile b/trunk/arch/mips/Makefile index 4892db88a86a..f2f742df32c7 100644 --- a/trunk/arch/mips/Makefile +++ b/trunk/arch/mips/Makefile @@ -92,7 +92,7 @@ cflags-y += -ffreestanding # when fed the toolchain default! # # Certain gcc versions upto gcc 4.1.1 (probably 4.2-subversion as of -# 2006-10-10 don't properly change the predefined symbols if -EB / -EL +# 2006-10-10 don't properly change the the predefined symbols if -EB / -EL # are used, so we kludge that here. A bug has been filed at # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29413. # diff --git a/trunk/arch/mips/kernel/asm-offsets.c b/trunk/arch/mips/kernel/asm-offsets.c index 3b27309d54b1..761a779d5c4f 100644 --- a/trunk/arch/mips/kernel/asm-offsets.c +++ b/trunk/arch/mips/kernel/asm-offsets.c @@ -82,7 +82,7 @@ void output_task_defines(void) { text("/* MIPS task_struct offsets. */"); offset("#define TASK_STATE ", struct task_struct, state); - offset("#define TASK_THREAD_INFO ", struct task_struct, stack); + offset("#define TASK_THREAD_INFO ", struct task_struct, thread_info); offset("#define TASK_FLAGS ", struct task_struct, flags); offset("#define TASK_MM ", struct task_struct, mm); offset("#define TASK_PID ", struct task_struct, pid); diff --git a/trunk/arch/mips/kernel/smtc.c b/trunk/arch/mips/kernel/smtc.c index b361edb83dc6..5dcfab6b288e 100644 --- a/trunk/arch/mips/kernel/smtc.c +++ b/trunk/arch/mips/kernel/smtc.c @@ -560,7 +560,7 @@ void smtc_boot_secondary(int cpu, struct task_struct *idle) write_tc_gpr_sp(__KSTK_TOS(idle)); /* global pointer */ - write_tc_gpr_gp((unsigned long)task_thread_info(idle)); + write_tc_gpr_gp((unsigned long)idle->thread_info); smtc_status |= SMTC_MTC_ACTIVE; write_tc_c0_tchalt(0); diff --git a/trunk/arch/mips/pci/fixup-sb1250.c b/trunk/arch/mips/pci/fixup-sb1250.c index 0ad39e53f7b1..7a7444874e80 100644 --- a/trunk/arch/mips/pci/fixup-sb1250.c +++ b/trunk/arch/mips/pci/fixup-sb1250.c @@ -14,7 +14,7 @@ #include /* - * Set the BCM1250, etc. PCI host bridge's TRDY timeout + * Set the the BCM1250, etc. PCI host bridge's TRDY timeout * to the finite max. */ static void __init quirk_sb1250_pci(struct pci_dev *dev) @@ -35,7 +35,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_HT, quirk_sb1250_ht); /* - * Set the SP1011 HT/PCI bridge's TRDY timeout to the finite max. + * Set the the SP1011 HT/PCI bridge's TRDY timeout to the finite max. */ static void __init quirk_sp1011(struct pci_dev *dev) { diff --git a/trunk/arch/parisc/kernel/asm-offsets.c b/trunk/arch/parisc/kernel/asm-offsets.c index d3b7917a87cb..54fdb959149c 100644 --- a/trunk/arch/parisc/kernel/asm-offsets.c +++ b/trunk/arch/parisc/kernel/asm-offsets.c @@ -54,7 +54,7 @@ int main(void) { - DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack)); + DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info)); DEFINE(TASK_STATE, offsetof(struct task_struct, state)); DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, pending)); diff --git a/trunk/arch/powerpc/Kconfig.debug b/trunk/arch/powerpc/Kconfig.debug index 346cd3befe1e..f70e795c262e 100644 --- a/trunk/arch/powerpc/Kconfig.debug +++ b/trunk/arch/powerpc/Kconfig.debug @@ -32,7 +32,7 @@ config HCALL_STATS depends on PPC_PSERIES && DEBUG_FS help Adds code to keep track of the number of hypervisor calls made and - the amount of time spent in hypervisor calls. Wall time spent in + the amount of time spent in hypervisor callsr. Wall time spent in each call is always calculated, and if available CPU cycles spent are also calculated. A directory named hcall_inst is added at the root of the debugfs filesystem. Within the hcall_inst directory diff --git a/trunk/arch/powerpc/kernel/asm-offsets.c b/trunk/arch/powerpc/kernel/asm-offsets.c index 2cb1d9487796..d6803fb7b28b 100644 --- a/trunk/arch/powerpc/kernel/asm-offsets.c +++ b/trunk/arch/powerpc/kernel/asm-offsets.c @@ -58,7 +58,7 @@ int main(void) #ifdef CONFIG_PPC64 DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context)); #else - DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); + DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info)); DEFINE(PTRACE, offsetof(struct task_struct, ptrace)); #endif /* CONFIG_PPC64 */ diff --git a/trunk/arch/powerpc/kernel/sysfs.c b/trunk/arch/powerpc/kernel/sysfs.c index 68991c2d4a1b..cae39d9dfe48 100644 --- a/trunk/arch/powerpc/kernel/sysfs.c +++ b/trunk/arch/powerpc/kernel/sysfs.c @@ -342,12 +342,10 @@ static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: register_cpu_online(cpu); break; #ifdef CONFIG_HOTPLUG_CPU case CPU_DEAD: - case CPU_DEAD_FROZEN: unregister_cpu_online(cpu); break; #endif diff --git a/trunk/arch/powerpc/mm/numa.c b/trunk/arch/powerpc/mm/numa.c index de45aa82d97b..b3a592b25ab3 100644 --- a/trunk/arch/powerpc/mm/numa.c +++ b/trunk/arch/powerpc/mm/numa.c @@ -252,15 +252,12 @@ static int __cpuinit cpu_numa_callback(struct notifier_block *nfb, switch (action) { case CPU_UP_PREPARE: - case CPU_UP_PREPARE_FROZEN: numa_setup_cpu(lcpu); ret = NOTIFY_OK; break; #ifdef CONFIG_HOTPLUG_CPU case CPU_DEAD: - case CPU_DEAD_FROZEN: case CPU_UP_CANCELED: - case CPU_UP_CANCELED_FROZEN: unmap_cpu_from_node(lcpu); break; ret = NOTIFY_OK; diff --git a/trunk/arch/powerpc/oprofile/op_model_cell.c b/trunk/arch/powerpc/oprofile/op_model_cell.c index c29293befba9..626b29f38304 100644 --- a/trunk/arch/powerpc/oprofile/op_model_cell.c +++ b/trunk/arch/powerpc/oprofile/op_model_cell.c @@ -747,7 +747,7 @@ cell_handle_interrupt(struct pt_regs *regs, struct op_counter_config *ctr) * counter value etc.) are not copied to the actual registers * until the performance monitor is enabled. In order to get * this to work as desired, the permormance monitor needs to - * be disabled while writing to the latches. This is a + * be disabled while writting to the latches. This is a * HW design issue. */ cbe_enable_pm(cpu); diff --git a/trunk/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/trunk/arch/powerpc/platforms/83xx/mpc8313_rdb.c index 32e9e9492841..96970ac887ee 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc8313_rdb.c +++ b/trunk/arch/powerpc/platforms/83xx/mpc8313_rdb.c @@ -40,7 +40,9 @@ unsigned long isa_mem_base = 0; */ static void __init mpc8313_rdb_setup_arch(void) { +#ifdef CONFIG_PCI struct device_node *np; +#endif if (ppc_md.progress) ppc_md.progress("mpc8313_rdb_setup_arch()", 0); diff --git a/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c b/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c index 3c009f6d4a4f..40a01947d684 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c +++ b/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c @@ -50,7 +50,9 @@ unsigned long isa_mem_base = 0; */ static void __init mpc834x_itx_setup_arch(void) { +#ifdef CONFIG_PCI struct device_node *np; +#endif if (ppc_md.progress) ppc_md.progress("mpc834x_itx_setup_arch()", 0); diff --git a/trunk/arch/powerpc/platforms/83xx/mpc834x_mds.c b/trunk/arch/powerpc/platforms/83xx/mpc834x_mds.c index 8aa9a93e2aa2..10394b2d7e7a 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc834x_mds.c +++ b/trunk/arch/powerpc/platforms/83xx/mpc834x_mds.c @@ -120,7 +120,9 @@ static int mpc834x_usb_cfg(void) */ static void __init mpc834x_mds_setup_arch(void) { +#ifdef CONFIG_PCI struct device_node *np; +#endif if (ppc_md.progress) ppc_md.progress("mpc834x_mds_setup_arch()", 0); diff --git a/trunk/arch/powerpc/platforms/8xx/mpc86xads_setup.c b/trunk/arch/powerpc/platforms/8xx/mpc86xads_setup.c index cf0e7bc8c2e7..a35315af5c53 100644 --- a/trunk/arch/powerpc/platforms/8xx/mpc86xads_setup.c +++ b/trunk/arch/powerpc/platforms/8xx/mpc86xads_setup.c @@ -1,4 +1,4 @@ -/*arch/powerpc/platforms/8xx/mpc86xads_setup.c +/*arch/ppc/platforms/mpc86xads-setup.c * * Platform setup for the Freescale mpc86xads board * diff --git a/trunk/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/trunk/arch/powerpc/platforms/8xx/mpc885ads_setup.c index c36e475d93dc..a57b57785acd 100644 --- a/trunk/arch/powerpc/platforms/8xx/mpc885ads_setup.c +++ b/trunk/arch/powerpc/platforms/8xx/mpc885ads_setup.c @@ -1,4 +1,4 @@ -/*arch/powerpc/platforms/8xx/mpc885ads_setup.c +/*arch/ppc/platforms/mpc885ads-setup.c * * Platform setup for the Freescale mpc885ads board * diff --git a/trunk/arch/powerpc/platforms/cell/io-workarounds.c b/trunk/arch/powerpc/platforms/cell/io-workarounds.c index 7fb92f23f380..d68d920eb2c4 100644 --- a/trunk/arch/powerpc/platforms/cell/io-workarounds.c +++ b/trunk/arch/powerpc/platforms/cell/io-workarounds.c @@ -74,7 +74,7 @@ static void spider_io_flush(const volatile void __iomem *addr) /* Fast path if we have a non-0 token, it indicates which bus we * are on. * - * If the token is 0, that means either that the ioremap was done + * If the token is 0, that means either the the ioremap was done * before we initialized this layer, or it's a PIO operation. We * fallback to a low path in this case. Hopefully, internal devices * which are ioremap'ed early should use in_XX/out_XX functions diff --git a/trunk/arch/ppc/kernel/asm-offsets.c b/trunk/arch/ppc/kernel/asm-offsets.c index e8e94321b59e..c5850a272650 100644 --- a/trunk/arch/ppc/kernel/asm-offsets.c +++ b/trunk/arch/ppc/kernel/asm-offsets.c @@ -35,7 +35,7 @@ int main(void) { DEFINE(THREAD, offsetof(struct task_struct, thread)); - DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); + DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info)); DEFINE(MM, offsetof(struct task_struct, mm)); DEFINE(PTRACE, offsetof(struct task_struct, ptrace)); DEFINE(KSP, offsetof(struct thread_struct, ksp)); diff --git a/trunk/arch/ppc/platforms/mpc866ads_setup.c b/trunk/arch/ppc/platforms/mpc866ads_setup.c index bf72204125c5..7ce5364fdb3b 100644 --- a/trunk/arch/ppc/platforms/mpc866ads_setup.c +++ b/trunk/arch/ppc/platforms/mpc866ads_setup.c @@ -1,4 +1,4 @@ -/*arch/ppc/platforms/mpc866ads_setup.c +/*arch/ppc/platforms/mpc866ads-setup.c * * Platform setup for the Freescale mpc866ads board * diff --git a/trunk/arch/ppc/syslib/ipic.c b/trunk/arch/ppc/syslib/ipic.c index 9192777d0f78..10659c24b1be 100644 --- a/trunk/arch/ppc/syslib/ipic.c +++ b/trunk/arch/ppc/syslib/ipic.c @@ -1,5 +1,5 @@ /* - * arch/ppc/syslib/ipic.c + * include/asm-ppc/ipic.c * * IPIC routines implementations. * diff --git a/trunk/arch/s390/Kconfig b/trunk/arch/s390/Kconfig index 098c62c29f9c..1a84719be264 100644 --- a/trunk/arch/s390/Kconfig +++ b/trunk/arch/s390/Kconfig @@ -4,23 +4,27 @@ # config MMU - def_bool y + bool + default y config ZONE_DMA def_bool y depends on 64BIT config LOCKDEP_SUPPORT - def_bool y + bool + default y config STACKTRACE_SUPPORT - def_bool y + bool + default y config RWSEM_GENERIC_SPINLOCK bool config RWSEM_XCHGADD_ALGORITHM - def_bool y + bool + default y config ARCH_HAS_ILOG2_U32 bool @@ -31,7 +35,8 @@ config ARCH_HAS_ILOG2_U64 default n config GENERIC_HWEIGHT - def_bool y + bool + default y config GENERIC_TIME def_bool y @@ -50,7 +55,8 @@ config NO_DMA mainmenu "Linux Kernel Configuration" config S390 - def_bool y + bool + default y source "init/Kconfig" @@ -274,10 +280,6 @@ config WARN_STACK_SIZE config ARCH_POPULATES_NODE_MAP def_bool y -comment "Kernel preemption" - -source "kernel/Kconfig.preempt" - source "mm/Kconfig" config HOLES_IN_ZONE @@ -318,6 +320,17 @@ config QDIO_DEBUG comment "Misc" +config PREEMPT + bool "Preemptible Kernel" + help + This option reduces the latency of the kernel when reacting to + real-time or interactive events by allowing a low priority process to + be preempted even if it is in kernel mode executing a system call. + This allows applications to run more reliably even when the system is + under load. + + Say N if you are unsure. + config IPL bool "Builtin IPL record support" help @@ -475,8 +488,6 @@ config APPLDATA_NET_SUM This can also be compiled as a module, which will be called appldata_net_sum.o. -source kernel/Kconfig.hz - config NO_IDLE_HZ bool "No HZ timer ticks in idle" help @@ -524,12 +535,18 @@ endmenu source "net/Kconfig" config PCMCIA - def_bool n + bool + default n -config CCW - def_bool y +source "drivers/base/Kconfig" + +source "drivers/connector/Kconfig" + +source "drivers/scsi/Kconfig" + +source "drivers/s390/Kconfig" -source "drivers/Kconfig" +source "drivers/net/Kconfig" source "fs/Kconfig" diff --git a/trunk/arch/s390/appldata/appldata_base.c b/trunk/arch/s390/appldata/appldata_base.c index 81a2b92ab0c2..ee89b33145d5 100644 --- a/trunk/arch/s390/appldata/appldata_base.c +++ b/trunk/arch/s390/appldata/appldata_base.c @@ -567,11 +567,9 @@ appldata_cpu_notify(struct notifier_block *self, { switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: appldata_online_cpu((long) hcpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: appldata_offline_cpu((long) hcpu); break; default: diff --git a/trunk/arch/s390/crypto/Kconfig b/trunk/arch/s390/crypto/Kconfig index d1defbbfcd81..99ff9f08e4d7 100644 --- a/trunk/arch/s390/crypto/Kconfig +++ b/trunk/arch/s390/crypto/Kconfig @@ -54,7 +54,7 @@ config S390_PRNG default "m" help Select this option if you want to use the s390 pseudo random number - generator. The PRNG is part of the cryptographic processor functions + generator. The PRNG is part of the cryptograhic processor functions and uses triple-DES to generate secure random numbers like the ANSI X9.17 standard. The PRNG is usable via the char device /dev/prandom. diff --git a/trunk/arch/s390/defconfig b/trunk/arch/s390/defconfig index 485b60c1983c..0e4da8a7d826 100644 --- a/trunk/arch/s390/defconfig +++ b/trunk/arch/s390/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.21 -# Thu May 10 15:18:19 2007 +# Linux kernel version: 2.6.21-rc1 +# Wed Feb 21 10:44:30 2007 # CONFIG_MMU=y CONFIG_ZONE_DMA=y @@ -14,7 +14,6 @@ CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_BUG=y CONFIG_NO_IOMEM=y -CONFIG_NO_DMA=y CONFIG_S390=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -42,11 +41,9 @@ CONFIG_AUDIT=y # CONFIG_AUDITSYSCALL is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=17 # CONFIG_CPUSETS is not set CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set -CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y @@ -63,14 +60,12 @@ CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y CONFIG_SLAB=y -# CONFIG_SLUB is not set -# CONFIG_SLOB is not set +CONFIG_VM_EVENT_COUNTERS=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set # # Loadable module support @@ -133,14 +128,6 @@ CONFIG_CHECK_STACK=y CONFIG_STACK_GUARD=256 # CONFIG_WARN_STACK is not set CONFIG_ARCH_POPULATES_NODE_MAP=y - -# -# Kernel preemption -# -# CONFIG_PREEMPT_NONE is not set -# CONFIG_PREEMPT_VOLUNTARY is not set -CONFIG_PREEMPT=y -CONFIG_PREEMPT_BKL=y CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -163,6 +150,7 @@ CONFIG_QDIO=y # # Misc # +CONFIG_PREEMPT=y CONFIG_IPL=y # CONFIG_IPL_TAPE is not set CONFIG_IPL_VM=y @@ -175,11 +163,6 @@ CONFIG_PFAULT=y CONFIG_VIRT_TIMER=y CONFIG_VIRT_CPU_ACCOUNTING=y # CONFIG_APPLDATA_BASE is not set -CONFIG_HZ_100=y -# CONFIG_HZ_250 is not set -# CONFIG_HZ_300 is not set -# CONFIG_HZ_1000 is not set -CONFIG_HZ=100 CONFIG_NO_IDLE_HZ=y CONFIG_NO_IDLE_HZ_INIT=y CONFIG_S390_HYPFS_FS=y @@ -194,6 +177,7 @@ CONFIG_NET=y # # Networking options # +# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -232,7 +216,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_IPV6=y # CONFIG_IPV6_PRIVACY is not set # CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_OPTIMISTIC_DAD is not set # CONFIG_INET6_AH is not set # CONFIG_INET6_ESP is not set # CONFIG_INET6_IPCOMP is not set @@ -257,12 +240,7 @@ CONFIG_IPV6_SIT=y # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IP_SCTP=m -# CONFIG_SCTP_DBG_MSG is not set -# CONFIG_SCTP_DBG_OBJCNT is not set -# CONFIG_SCTP_HMAC_NONE is not set -# CONFIG_SCTP_HMAC_SHA1 is not set -CONFIG_SCTP_HMAC_MD5=y +# CONFIG_IP_SCTP is not set # # TIPC Configuration (EXPERIMENTAL) @@ -285,6 +263,9 @@ CONFIG_SCTP_HMAC_MD5=y # CONFIG_NET_SCHED=y CONFIG_NET_SCH_FIFO=y +CONFIG_NET_SCH_CLK_JIFFIES=y +# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set +# CONFIG_NET_SCH_CLK_CPU is not set # # Queueing/Scheduling @@ -327,14 +308,11 @@ CONFIG_NET_ESTIMATOR=y # # CONFIG_NET_PKTGEN is not set # CONFIG_NET_TCPPROBE is not set -# CONFIG_AF_RXRPC is not set -# CONFIG_RFKILL is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set # CONFIG_PCMCIA is not set -CONFIG_CCW=y - -# -# Device Drivers -# # # Generic Driver Options @@ -351,37 +329,6 @@ CONFIG_SYS_HYPERVISOR=y # # CONFIG_CONNECTOR is not set -# -# Block devices -# -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set - -# -# S/390 block device drivers -# -CONFIG_BLK_DEV_XPRAM=m -# CONFIG_DCSSBLK is not set -CONFIG_DASD=y -CONFIG_DASD_PROFILE=y -CONFIG_DASD_ECKD=y -CONFIG_DASD_FBA=y -CONFIG_DASD_DIAG=y -CONFIG_DASD_EER=y - -# -# Misc devices -# -# CONFIG_BLINK is not set - # # SCSI device support # @@ -409,7 +356,6 @@ CONFIG_SCSI_MULTI_LUN=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SCAN_ASYNC=y -CONFIG_SCSI_WAIT_SCAN=m # # SCSI Transports @@ -426,6 +372,34 @@ CONFIG_SCSI_FC_ATTRS=y # CONFIG_ISCSI_TCP is not set # CONFIG_SCSI_DEBUG is not set CONFIG_ZFCP=y +CONFIG_CCW=y + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set + +# +# S/390 block device drivers +# +CONFIG_BLK_DEV_XPRAM=m +# CONFIG_DCSSBLK is not set +CONFIG_DASD=y +CONFIG_DASD_PROFILE=y +CONFIG_DASD_ECKD=y +CONFIG_DASD_FBA=y +CONFIG_DASD_DIAG=y +CONFIG_DASD_EER=y +# CONFIG_ATA_OVER_ETH is not set # # Multi-device support (RAID and LVM) @@ -447,7 +421,56 @@ CONFIG_DM_MIRROR=y CONFIG_DM_ZERO=y CONFIG_DM_MULTIPATH=y # CONFIG_DM_MULTIPATH_EMC is not set -# CONFIG_DM_DELAY is not set + +# +# Character device drivers +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=2048 +# CONFIG_HANGCHECK_TIMER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set + +# +# S/390 character device drivers +# +CONFIG_TN3270=y +CONFIG_TN3270_TTY=y +CONFIG_TN3270_FS=m +CONFIG_TN3270_CONSOLE=y +CONFIG_TN3215=y +CONFIG_TN3215_CONSOLE=y +CONFIG_CCW_CONSOLE=y +CONFIG_SCLP_TTY=y +CONFIG_SCLP_CONSOLE=y +CONFIG_SCLP_VT220_TTY=y +CONFIG_SCLP_VT220_CONSOLE=y +CONFIG_SCLP_CPI=m +CONFIG_S390_TAPE=m + +# +# S/390 tape interface support +# +CONFIG_S390_TAPE_BLOCK=y + +# +# S/390 tape hardware support +# +CONFIG_S390_TAPE_34XX=m +# CONFIG_S390_TAPE_3590 is not set +# CONFIG_VMLOGRDR is not set +# CONFIG_VMCP is not set +# CONFIG_MONREADER is not set +CONFIG_MONWRITER=m + +# +# Cryptographic devices +# +CONFIG_ZCRYPT=m +# CONFIG_ZCRYPT_MONOLITHIC is not set # # Network device support @@ -458,6 +481,10 @@ CONFIG_BONDING=m CONFIG_EQUALIZER=m CONFIG_TUN=m +# +# PHY device support +# + # # Ethernet (10 or 100Mbit) # @@ -471,13 +498,17 @@ CONFIG_NET_ETHERNET=y # # Ethernet (10000 Mbit) # -CONFIG_MLX4_DEBUG=y # # Token Ring devices # # CONFIG_TR is not set +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + # # Wan interfaces # @@ -505,56 +536,6 @@ CONFIG_CCWGROUP=y # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set -# -# Character devices -# -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -CONFIG_HW_RANDOM=m -# CONFIG_R3964 is not set -CONFIG_RAW_DRIVER=m -CONFIG_MAX_RAW_DEVS=256 -# CONFIG_HANGCHECK_TIMER is not set - -# -# S/390 character device drivers -# -CONFIG_TN3270=y -CONFIG_TN3270_TTY=y -CONFIG_TN3270_FS=m -CONFIG_TN3270_CONSOLE=y -CONFIG_TN3215=y -CONFIG_TN3215_CONSOLE=y -CONFIG_CCW_CONSOLE=y -CONFIG_SCLP=y -CONFIG_SCLP_TTY=y -CONFIG_SCLP_CONSOLE=y -CONFIG_SCLP_VT220_TTY=y -CONFIG_SCLP_VT220_CONSOLE=y -CONFIG_SCLP_CPI=m -CONFIG_S390_TAPE=m - -# -# S/390 tape interface support -# -CONFIG_S390_TAPE_BLOCK=y - -# -# S/390 tape hardware support -# -CONFIG_S390_TAPE_34XX=m -# CONFIG_S390_TAPE_3590 is not set -# CONFIG_VMLOGRDR is not set -# CONFIG_VMCP is not set -# CONFIG_MONREADER is not set -CONFIG_MONWRITER=m - # # File systems # @@ -647,7 +628,6 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y -# CONFIG_SUNRPC_BIND34 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -678,7 +658,6 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_SUN_PARTITION is not set # CONFIG_KARMA_PARTITION is not set # CONFIG_EFI_PARTITION is not set -# CONFIG_SYSV68_PARTITION is not set # # Native Language Support @@ -689,6 +668,8 @@ CONFIG_MSDOS_PARTITION=y # Distributed Lock Manager # CONFIG_DLM=m +CONFIG_DLM_TCP=y +# CONFIG_DLM_SCTP is not set # CONFIG_DLM_DEBUG is not set # @@ -712,6 +693,7 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y CONFIG_HEADERS_CHECK=y CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_SLAB is not set @@ -747,13 +729,12 @@ CONFIG_FORCED_INLINING=y CONFIG_CRYPTO=y CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_HASH=m CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_HMAC=m +# CONFIG_CRYPTO_HMAC is not set # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_MD4 is not set -CONFIG_CRYPTO_MD5=m +# CONFIG_CRYPTO_MD5 is not set # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set @@ -764,7 +745,6 @@ CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_CRYPTD is not set # CONFIG_CRYPTO_DES is not set CONFIG_CRYPTO_FCRYPT=m # CONFIG_CRYPTO_BLOWFISH is not set @@ -791,8 +771,6 @@ CONFIG_CRYPTO_CAMELLIA=m # CONFIG_CRYPTO_DES_S390 is not set # CONFIG_CRYPTO_AES_S390 is not set CONFIG_S390_PRNG=m -CONFIG_ZCRYPT=m -# CONFIG_ZCRYPT_MONOLITHIC is not set # # Library routines diff --git a/trunk/arch/s390/hypfs/inode.c b/trunk/arch/s390/hypfs/inode.c index 8e1ea1c40128..ba5d3167df0d 100644 --- a/trunk/arch/s390/hypfs/inode.c +++ b/trunk/arch/s390/hypfs/inode.c @@ -477,7 +477,7 @@ static int __init hypfs_init(void) goto fail_diag; } } - kobj_set_kset_s(&s390_subsys, hypervisor_subsys); + kset_set_kset_s(&s390_subsys, hypervisor_subsys); rc = subsystem_register(&s390_subsys); if (rc) goto fail_sysfs; diff --git a/trunk/arch/s390/kernel/asm-offsets.c b/trunk/arch/s390/kernel/asm-offsets.c index 1375f8a4469e..ec514fe5ccd0 100644 --- a/trunk/arch/s390/kernel/asm-offsets.c +++ b/trunk/arch/s390/kernel/asm-offsets.c @@ -15,7 +15,7 @@ int main(void) { - DEFINE(__THREAD_info, offsetof(struct task_struct, stack),); + DEFINE(__THREAD_info, offsetof(struct task_struct, thread_info),); DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp),); DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info),); DEFINE(__THREAD_mm_segment, diff --git a/trunk/arch/s390/kernel/ipl.c b/trunk/arch/s390/kernel/ipl.c index 367caf92ea78..0ea048d350d8 100644 --- a/trunk/arch/s390/kernel/ipl.c +++ b/trunk/arch/s390/kernel/ipl.c @@ -816,23 +816,23 @@ static int __init ipl_register_fcp_files(void) { int rc; - rc = sysfs_create_group(&ipl_subsys.kobj, + rc = sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group); if (rc) goto out; - rc = sysfs_create_bin_file(&ipl_subsys.kobj, + rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr); if (rc) goto out_ipl_parm; - rc = sysfs_create_bin_file(&ipl_subsys.kobj, + rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj, &ipl_scp_data_attr); if (!rc) goto out; - sysfs_remove_bin_file(&ipl_subsys.kobj, &ipl_parameter_attr); + sysfs_remove_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr); out_ipl_parm: - sysfs_remove_group(&ipl_subsys.kobj, &ipl_fcp_attr_group); + sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group); out: return rc; } @@ -846,7 +846,7 @@ static int __init ipl_init(void) return rc; switch (ipl_info.type) { case IPL_TYPE_CCW: - rc = sysfs_create_group(&ipl_subsys.kobj, + rc = sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_ccw_attr_group); break; case IPL_TYPE_FCP: @@ -854,11 +854,11 @@ static int __init ipl_init(void) rc = ipl_register_fcp_files(); break; case IPL_TYPE_NSS: - rc = sysfs_create_group(&ipl_subsys.kobj, + rc = sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_nss_attr_group); break; default: - rc = sysfs_create_group(&ipl_subsys.kobj, + rc = sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_unknown_attr_group); break; } @@ -885,7 +885,7 @@ static int __init reipl_nss_init(void) if (!MACHINE_IS_VM) return 0; - rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_nss_attr_group); + rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_nss_attr_group); if (rc) return rc; strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1); @@ -900,7 +900,7 @@ static int __init reipl_ccw_init(void) reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL); if (!reipl_block_ccw) return -ENOMEM; - rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_ccw_attr_group); + rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_ccw_attr_group); if (rc) { free_page((unsigned long)reipl_block_ccw); return rc; @@ -938,7 +938,7 @@ static int __init reipl_fcp_init(void) reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL); if (!reipl_block_fcp) return -ENOMEM; - rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_fcp_attr_group); + rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_fcp_attr_group); if (rc) { free_page((unsigned long)reipl_block_fcp); return rc; @@ -990,7 +990,7 @@ static int __init dump_ccw_init(void) dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL); if (!dump_block_ccw) return -ENOMEM; - rc = sysfs_create_group(&dump_subsys.kobj, &dump_ccw_attr_group); + rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_ccw_attr_group); if (rc) { free_page((unsigned long)dump_block_ccw); return rc; @@ -1014,7 +1014,7 @@ static int __init dump_fcp_init(void) dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL); if (!dump_block_fcp) return -ENOMEM; - rc = sysfs_create_group(&dump_subsys.kobj, &dump_fcp_attr_group); + rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_fcp_attr_group); if (rc) { free_page((unsigned long)dump_block_fcp); return rc; diff --git a/trunk/arch/s390/kernel/smp.c b/trunk/arch/s390/kernel/smp.c index 09f028a3266b..b7977027a28f 100644 --- a/trunk/arch/s390/kernel/smp.c +++ b/trunk/arch/s390/kernel/smp.c @@ -789,12 +789,10 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: if (sysdev_create_file(s, &attr_capability)) return NOTIFY_BAD; break; case CPU_DEAD: - case CPU_DEAD_FROZEN: sysdev_remove_file(s, &attr_capability); break; } diff --git a/trunk/arch/s390/mm/fault.c b/trunk/arch/s390/mm/fault.c index d855cdbf8fb8..8b924b359774 100644 --- a/trunk/arch/s390/mm/fault.c +++ b/trunk/arch/s390/mm/fault.c @@ -253,10 +253,7 @@ static int signal_return(struct mm_struct *mm, struct pt_regs *regs, unsigned long address, unsigned long error_code) { u16 instruction; - int rc; -#ifdef CONFIG_COMPAT - int compat; -#endif + int rc, compat; pagefault_disable(); rc = __get_user(instruction, (u16 __user *) regs->psw.addr); diff --git a/trunk/arch/sh/Kconfig b/trunk/arch/sh/Kconfig index 038179ecf6a9..d74eb120a9c6 100644 --- a/trunk/arch/sh/Kconfig +++ b/trunk/arch/sh/Kconfig @@ -52,9 +52,6 @@ config GENERIC_IOMAP config GENERIC_TIME def_bool n -config GENERIC_CLOCKEVENTS - def_bool n - config SYS_SUPPORTS_APM_EMULATION bool @@ -439,11 +436,11 @@ endmenu menu "Timer and clock configuration" +if !GENERIC_TIME + config SH_TMU bool "TMU timer support" depends on CPU_SH3 || CPU_SH4 - select GENERIC_TIME - select GENERIC_CLOCKEVENTS default y help This enables the use of the TMU as the system timer. @@ -462,6 +459,8 @@ config SH_MTU2 help This enables the use of the MTU2 as the system timer. +endif + config SH_TIMER_IRQ int default "28" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785 @@ -469,6 +468,24 @@ config SH_TIMER_IRQ default "140" if CPU_SUBTYPE_SH7206 default "16" +config NO_IDLE_HZ + bool "Dynamic tick timer" + help + Select this option if you want to disable continuous timer ticks + and have them programmed to occur as required. This option saves + power as the system can remain in idle state for longer. + + By default dynamic tick is disabled during the boot, and can be + manually enabled with: + + echo 1 > /sys/devices/system/timer/timer0/dyn_tick + + Alternatively, if you want dynamic tick automatically enabled + during boot, pass "dyntick=enable" via the kernel command string. + + Please note that dynamic tick may affect the accuracy of + timekeeping on some platforms depending on the implementation. + config SH_PCLK_FREQ int "Peripheral clock frequency (in Hz)" default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343 @@ -492,8 +509,6 @@ config SH_CLK_MD help MD2 - MD0 pin setting. -source "kernel/time/Kconfig" - endmenu menu "CPU Frequency scaling" diff --git a/trunk/arch/sh/boards/landisk/setup.c b/trunk/arch/sh/boards/landisk/setup.c index 4058b4f50d44..a83a5d9587bb 100644 --- a/trunk/arch/sh/boards/landisk/setup.c +++ b/trunk/arch/sh/boards/landisk/setup.c @@ -93,7 +93,6 @@ static void __init landisk_setup(char **cmdline_p) */ struct sh_machine_vector mv_landisk __initmv = { .mv_name = "LANDISK", - .mv_nr_irqs = 72, .mv_setup = landisk_setup, .mv_init_irq = init_landisk_IRQ, }; diff --git a/trunk/arch/sh/boards/se/7751/setup.c b/trunk/arch/sh/boards/se/7751/setup.c index 52c7bfa57c2c..770defed9c4a 100644 --- a/trunk/arch/sh/boards/se/7751/setup.c +++ b/trunk/arch/sh/boards/se/7751/setup.c @@ -1,5 +1,5 @@ /* - * linux/arch/sh/boards/se/7751/setup.c + * linux/arch/sh/kernel/setup_7751se.c * * Copyright (C) 2000 Kazumoto Kojima * diff --git a/trunk/arch/sh/drivers/Makefile b/trunk/arch/sh/drivers/Makefile index e13f06bebd92..6cb92676c5fc 100644 --- a/trunk/arch/sh/drivers/Makefile +++ b/trunk/arch/sh/drivers/Makefile @@ -2,9 +2,8 @@ # Makefile for the Linux SuperH-specific device drivers. # -obj-y += dma/ - obj-$(CONFIG_PCI) += pci/ +obj-$(CONFIG_SH_DMA) += dma/ obj-$(CONFIG_SUPERHYWAY) += superhyway/ obj-$(CONFIG_PUSH_SWITCH) += push-switch.o obj-$(CONFIG_HEARTBEAT) += heartbeat.o diff --git a/trunk/arch/sh/drivers/dma/Kconfig b/trunk/arch/sh/drivers/dma/Kconfig index 99935f9daf4b..defc13c37d48 100644 --- a/trunk/arch/sh/drivers/dma/Kconfig +++ b/trunk/arch/sh/drivers/dma/Kconfig @@ -1,12 +1,12 @@ menu "DMA support" -config SH_DMA_API - bool - config SH_DMA - bool "SuperH on-chip DMA controller (DMAC) support" - select SH_DMA_API - default n + bool "DMA controller (DMAC) support" + help + Selecting this option will provide same API as PC's Direct Memory + Access Controller(8237A) for SuperH DMAC. + + If unsure, say N. config NR_ONCHIP_DMA_CHANNELS depends on SH_DMA @@ -53,12 +53,4 @@ config DMA_PAGE_OPS_CHANNEL in case channel 3 is unavailable. On the SH4, channels 1,2, and 3 are dual-address capable. -config SH_DMABRG - bool "SH7760 DMABRG support" - depends on CPU_SUBTYPE_SH7760 - help - The DMABRG does data transfers from main memory to Audio/USB units - of the SH7760. - Say Y if you want to use Audio/USB DMA on your SH7760 board. - endmenu diff --git a/trunk/arch/sh/drivers/dma/Makefile b/trunk/arch/sh/drivers/dma/Makefile index 1ac812d24488..db1295d32268 100644 --- a/trunk/arch/sh/drivers/dma/Makefile +++ b/trunk/arch/sh/drivers/dma/Makefile @@ -2,8 +2,8 @@ # Makefile for the SuperH DMA specific kernel interface routines under Linux. # -obj-$(CONFIG_SH_DMA_API) += dma-api.o dma-sysfs.o +obj-y += dma-api.o obj-$(CONFIG_ISA_DMA_API) += dma-isa.o +obj-$(CONFIG_SYSFS) += dma-sysfs.o obj-$(CONFIG_SH_DMA) += dma-sh.o obj-$(CONFIG_SH_DREAMCAST) += dma-pvr2.o dma-g2.o -obj-$(CONFIG_SH_DMABRG) += dmabrg.o diff --git a/trunk/arch/sh/drivers/dma/dmabrg.c b/trunk/arch/sh/drivers/dma/dmabrg.c deleted file mode 100644 index 9d0a29370f21..000000000000 --- a/trunk/arch/sh/drivers/dma/dmabrg.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * SH7760 DMABRG IRQ handling - * - * (c) 2007 MSC Vertriebsges.m.b.H, Manuel Lauss - * licensed under the GPLv2. - * - */ - -#include -#include -#include -#include -#include - -/* - * The DMABRG is a special DMA unit within the SH7760. It does transfers - * from USB-SRAM/Audio units to main memory (and also the LCDC; but that - * part is sensibly placed in the LCDC registers and requires no irqs) - * It has 3 IRQ lines which trigger 10 events, and works independently - * from the traditional SH DMAC (although it blocks usage of DMAC 0) - * - * BRGIRQID | component | dir | meaning | source - * ----------------------------------------------------- - * 0 | USB-DMA | ... | xfer done | DMABRGI1 - * 1 | USB-UAE | ... | USB addr err.| DMABRGI0 - * 2 | HAC0/SSI0 | play| all done | DMABRGI1 - * 3 | HAC0/SSI0 | play| half done | DMABRGI2 - * 4 | HAC0/SSI0 | rec | all done | DMABRGI1 - * 5 | HAC0/SSI0 | rec | half done | DMABRGI2 - * 6 | HAC1/SSI1 | play| all done | DMABRGI1 - * 7 | HAC1/SSI1 | play| half done | DMABRGI2 - * 8 | HAC1/SSI1 | rec | all done | DMABRGI1 - * 9 | HAC1/SSI1 | rec | half done | DMABRGI2 - * - * all can be enabled/disabled in the DMABRGCR register, - * as well as checked if they occured. - * - * DMABRGI0 services USB DMA Address errors, but it still must be - * enabled/acked in the DMABRGCR register. USB-DMA complete indicator - * is grouped together with the audio buffer end indicators, too bad... - * - * DMABRGCR: Bits 31-24: audio-dma ENABLE flags, - * Bits 23-16: audio-dma STATUS flags, - * Bits 9-8: USB error/xfer ENABLE, - * Bits 1-0: USB error/xfer STATUS. - * Ack an IRQ by writing 0 to the STATUS flag. - * Mask IRQ by writing 0 to ENABLE flag. - * - * Usage is almost like with any other IRQ: - * dmabrg_request_irq(BRGIRQID, handler, data) - * dmabrg_free_irq(BRGIRQID) - * - * handler prototype: void brgirqhandler(void *data) - */ - -#define DMARSRA 0xfe090000 -#define DMAOR 0xffa00040 -#define DMACHCR0 0xffa0000c -#define DMABRGCR 0xfe3c0000 - -#define DMAOR_BRG 0x0000c000 -#define DMAOR_DMEN 0x00000001 - -#define DMABRGI0 68 -#define DMABRGI1 69 -#define DMABRGI2 70 - -struct dmabrg_handler { - void (*handler)(void *); - void *data; -} *dmabrg_handlers; - -static inline void dmabrg_call_handler(int i) -{ - dmabrg_handlers[i].handler(dmabrg_handlers[i].data); -} - -/* - * main DMABRG irq handler. It acks irqs and then - * handles every set and unmasked bit sequentially. - * No locking and no validity checks; it should be - * as fast as possible (audio!) - */ -static irqreturn_t dmabrg_irq(int irq, void *data) -{ - unsigned long dcr; - unsigned int i; - - dcr = ctrl_inl(DMABRGCR); - ctrl_outl(dcr & ~0x00ff0003, DMABRGCR); /* ack all */ - dcr &= dcr >> 8; /* ignore masked */ - - /* USB stuff, get it out of the way first */ - if (dcr & 1) - dmabrg_call_handler(DMABRGIRQ_USBDMA); - if (dcr & 2) - dmabrg_call_handler(DMABRGIRQ_USBDMAERR); - - /* Audio */ - dcr >>= 16; - while (dcr) { - i = __ffs(dcr); - dcr &= dcr - 1; - dmabrg_call_handler(i + DMABRGIRQ_A0TXF); - } - return IRQ_HANDLED; -} - -static void dmabrg_disable_irq(unsigned int dmairq) -{ - unsigned long dcr; - dcr = ctrl_inl(DMABRGCR); - dcr &= ~(1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8)); - ctrl_outl(dcr, DMABRGCR); -} - -static void dmabrg_enable_irq(unsigned int dmairq) -{ - unsigned long dcr; - dcr = ctrl_inl(DMABRGCR); - dcr |= (1 << ((dmairq > 1) ? dmairq + 22 : dmairq + 8)); - ctrl_outl(dcr, DMABRGCR); -} - -int dmabrg_request_irq(unsigned int dmairq, void(*handler)(void*), - void *data) -{ - if ((dmairq > 9) || !handler) - return -ENOENT; - if (dmabrg_handlers[dmairq].handler) - return -EBUSY; - - dmabrg_handlers[dmairq].handler = handler; - dmabrg_handlers[dmairq].data = data; - - dmabrg_enable_irq(dmairq); - return 0; -} -EXPORT_SYMBOL_GPL(dmabrg_request_irq); - -void dmabrg_free_irq(unsigned int dmairq) -{ - if (likely(dmairq < 10)) { - dmabrg_disable_irq(dmairq); - dmabrg_handlers[dmairq].handler = NULL; - dmabrg_handlers[dmairq].data = NULL; - } -} -EXPORT_SYMBOL_GPL(dmabrg_free_irq); - -static int __init dmabrg_init(void) -{ - unsigned long or; - int ret; - - dmabrg_handlers = kzalloc(10 * sizeof(struct dmabrg_handler), - GFP_KERNEL); - if (!dmabrg_handlers) - return -ENOMEM; - -#ifdef CONFIG_SH_DMA - /* request DMAC channel 0 before anyone else can get it */ - ret = request_dma(0, "DMAC 0 (DMABRG)"); - if (ret < 0) - printk(KERN_INFO "DMABRG: DMAC ch0 not reserved!\n"); -#endif - - ctrl_outl(0, DMABRGCR); - ctrl_outl(0, DMACHCR0); - ctrl_outl(0x94000000, DMARSRA); /* enable DMABRG in DMAC 0 */ - - /* enable DMABRG mode, enable the DMAC */ - or = ctrl_inl(DMAOR); - ctrl_outl(or | DMAOR_BRG | DMAOR_DMEN, DMAOR); - - ret = request_irq(DMABRGI0, dmabrg_irq, IRQF_DISABLED, - "DMABRG USB address error", NULL); - if (ret) - goto out0; - - ret = request_irq(DMABRGI1, dmabrg_irq, IRQF_DISABLED, - "DMABRG Transfer End", NULL); - if (ret) - goto out1; - - ret = request_irq(DMABRGI2, dmabrg_irq, IRQF_DISABLED, - "DMABRG Transfer Half", NULL); - if (ret == 0) - return ret; - - free_irq(DMABRGI1, 0); -out1: free_irq(DMABRGI0, 0); -out0: kfree(dmabrg_handlers); - return ret; -} -subsys_initcall(dmabrg_init); diff --git a/trunk/arch/sh/kernel/cpu/sh2a/Makefile b/trunk/arch/sh/kernel/cpu/sh2a/Makefile index 965fa2572b23..350972ae9410 100644 --- a/trunk/arch/sh/kernel/cpu/sh2a/Makefile +++ b/trunk/arch/sh/kernel/cpu/sh2a/Makefile @@ -2,8 +2,9 @@ # Makefile for the Linux/SuperH SH-2A backends. # -obj-y := common.o probe.o opcode_helper.o +obj-y := common.o probe.o -common-y += $(addprefix ../sh2/, ex.o entry.o) +common-y += $(addprefix ../sh2/, ex.o) +common-y += $(addprefix ../sh2/, entry.o) obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o diff --git a/trunk/arch/sh/kernel/cpu/sh2a/opcode_helper.c b/trunk/arch/sh/kernel/cpu/sh2a/opcode_helper.c deleted file mode 100644 index 9704b7926d8b..000000000000 --- a/trunk/arch/sh/kernel/cpu/sh2a/opcode_helper.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * arch/sh/kernel/cpu/sh2a/opcode_helper.c - * - * Helper for the SH-2A 32-bit opcodes. - * - * Copyright (C) 2007 Paul Mundt - * - * 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. - */ -#include -#include - -/* - * Instructions on SH are generally fixed at 16-bits, however, SH-2A - * introduces some 32-bit instructions. Since there are no real - * constraints on their use (and they can be mixed and matched), we need - * to check the instruction encoding to work out if it's a true 32-bit - * instruction or not. - * - * Presently, 32-bit opcodes have only slight variations in what the - * actual encoding looks like in the first-half of the instruction, which - * makes it fairly straightforward to differentiate from the 16-bit ones. - * - * First 16-bits of encoding Used by - * - * 0011nnnnmmmm0001 mov.b, mov.w, mov.l, fmov.d, - * fmov.s, movu.b, movu.w - * - * 0011nnnn0iii1001 bclr.b, bld.b, bset.b, bst.b, band.b, - * bandnot.b, bldnot.b, bor.b, bornot.b, - * bxor.b - * - * 0000nnnniiii0000 movi20 - * 0000nnnniiii0001 movi20s - */ -unsigned int instruction_size(unsigned int insn) -{ - /* Look for the common cases */ - switch ((insn & 0xf00f)) { - case 0x0000: /* movi20 */ - case 0x0001: /* movi20s */ - case 0x3001: /* 32-bit mov/fmov/movu variants */ - return 4; - } - - /* And the special cases.. */ - switch ((insn & 0xf08f)) { - case 0x3009: /* 32-bit b*.b bit operations */ - return 4; - } - - return 2; -} diff --git a/trunk/arch/sh/kernel/cpu/sh2a/probe.c b/trunk/arch/sh/kernel/cpu/sh2a/probe.c index f455c3509789..426f6db01fc6 100644 --- a/trunk/arch/sh/kernel/cpu/sh2a/probe.c +++ b/trunk/arch/sh/kernel/cpu/sh2a/probe.c @@ -18,7 +18,6 @@ int __init detect_cpu_and_cache_system(void) { /* Just SH7206 for now .. */ current_cpu_data.type = CPU_SH7206; - current_cpu_data.flags |= CPU_HAS_OP32; current_cpu_data.dcache.ways = 4; current_cpu_data.dcache.way_incr = (1 << 11); diff --git a/trunk/arch/sh/kernel/cpu/sh3/entry.S b/trunk/arch/sh/kernel/cpu/sh3/entry.S index 832c0b4a1e6c..f3e827f29a46 100644 --- a/trunk/arch/sh/kernel/cpu/sh3/entry.S +++ b/trunk/arch/sh/kernel/cpu/sh3/entry.S @@ -1,5 +1,5 @@ /* - * arch/sh/kernel/cpu/sh3/entry.S + * arch/sh/kernel/entry.S * * Copyright (C) 1999, 2000, 2002 Niibe Yutaka * Copyright (C) 2003 - 2006 Paul Mundt diff --git a/trunk/arch/sh/kernel/cpu/sh3/ex.S b/trunk/arch/sh/kernel/cpu/sh3/ex.S index 2b2a9e02fb75..ba3082d640b5 100644 --- a/trunk/arch/sh/kernel/cpu/sh3/ex.S +++ b/trunk/arch/sh/kernel/cpu/sh3/ex.S @@ -1,7 +1,7 @@ /* * arch/sh/kernel/cpu/sh3/ex.S * - * The SH-3 and SH-4 exception vector table. + * The SH-3 exception vector table. * Copyright (C) 1999, 2000, 2002 Niibe Yutaka * Copyright (C) 2003 - 2006 Paul Mundt @@ -9,6 +9,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. + * */ #include @@ -35,12 +36,8 @@ ENTRY(exception_handling_table) .long exception_error ! address error load .long exception_error ! address error store /* 100 */ #endif -#if defined(CONFIG_SH_FPU) - .long do_fpu_error /* 120 */ -#else - .long exception_error /* 120 */ -#endif - .long exception_error /* 140 */ + .long exception_error ! fpu_exception /* 120 */ + .long exception_error /* 140 */ .long system_call ! Unconditional Trap /* 160 */ .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ @@ -58,4 +55,4 @@ ENTRY(user_break_point_trap) * away offsets can be manually inserted in to their appropriate * location via set_exception_table_{evt,vec}(). */ - .balign 4096,0,4096 + .balign 4096,0,4096 diff --git a/trunk/arch/sh/kernel/cpu/sh4/Makefile b/trunk/arch/sh/kernel/cpu/sh4/Makefile index 8add10bd8268..19ca68c71884 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/Makefile +++ b/trunk/arch/sh/kernel/cpu/sh4/Makefile @@ -2,10 +2,10 @@ # Makefile for the Linux/SuperH SH-4 backends. # -obj-y := probe.o common.o -common-y += $(addprefix ../sh3/, entry.o ex.o) +obj-y := ex.o probe.o common.o +common-y += $(addprefix ../sh3/, entry.o) -obj-$(CONFIG_SH_FPU) += fpu.o +obj-$(CONFIG_SH_FPU) += fpu.o obj-$(CONFIG_SH_STORE_QUEUES) += sq.o # CPU subtype setup diff --git a/trunk/arch/sh/kernel/cpu/sh4/ex.S b/trunk/arch/sh/kernel/cpu/sh4/ex.S new file mode 100644 index 000000000000..ac8ab57413cc --- /dev/null +++ b/trunk/arch/sh/kernel/cpu/sh4/ex.S @@ -0,0 +1,62 @@ +/* + * arch/sh/kernel/cpu/sh4/ex.S + * + * The SH-4 exception vector table. + + * Copyright (C) 1999, 2000, 2002 Niibe Yutaka + * Copyright (C) 2003 - 2006 Paul Mundt + * + * 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. + * + */ +#include + + .align 2 + .data + +ENTRY(exception_handling_table) + .long exception_error /* 000 */ + .long exception_error +#if defined(CONFIG_MMU) + .long tlb_miss_load /* 040 */ + .long tlb_miss_store + .long initial_page_write + .long tlb_protection_violation_load + .long tlb_protection_violation_store + .long address_error_load + .long address_error_store /* 100 */ +#else + .long exception_error ! tlb miss load /* 040 */ + .long exception_error ! tlb miss store + .long exception_error ! initial page write + .long exception_error ! tlb prot violation load + .long exception_error ! tlb prot violation store + .long exception_error ! address error load + .long exception_error ! address error store /* 100 */ +#endif +#if defined(CONFIG_SH_FPU) + .long do_fpu_error /* 120 */ +#else + .long exception_error /* 120 */ +#endif + .long exception_error /* 140 */ + .long system_call ! Unconditional Trap /* 160 */ + .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ + .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ +ENTRY(nmi_slot) +#if defined (CONFIG_KGDB_NMI) + .long debug_enter /* 1C0 */ ! Allow trap to debugger +#else + .long exception_none /* 1C0 */ ! Not implemented yet +#endif +ENTRY(user_break_point_trap) + .long break_point_trap /* 1E0 */ + + /* + * Pad the remainder of the table out, exceptions residing in far + * away offsets can be manually inserted in to their appropriate + * location via set_exception_table_{evt,vec}(). + */ + .balign 4096,0,4096 diff --git a/trunk/arch/sh/kernel/cpu/sh4/fpu.c b/trunk/arch/sh/kernel/cpu/sh4/fpu.c index d61dd599169f..7624677f6628 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/fpu.c +++ b/trunk/arch/sh/kernel/cpu/sh4/fpu.c @@ -16,7 +16,6 @@ #include #include #include -#include #include /* The PR (precision) bit in the FP Status Register must be clear when @@ -266,7 +265,7 @@ ieee_fpe_handler (struct pt_regs *regs) nextpc = regs->pr; finsn = *(unsigned short *) (regs->pc + 2); } else { - nextpc = regs->pc + instruction_size(insn); + nextpc = regs->pc + 2; finsn = insn; } diff --git a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh73180.c b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh73180.c index 6d5ba373a75e..2fa5cb2ae68d 100644 --- a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh73180.c +++ b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh73180.c @@ -1,5 +1,5 @@ /* - * arch/sh/kernel/cpu/sh4a/clock-sh73180.c + * arch/sh/kernel/cpu/sh4/clock-sh73180.c * * SH73180 support for the clock framework * diff --git a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index 7adc4f16e95a..1707a213f0cf 100644 --- a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7343.c @@ -1,5 +1,5 @@ /* - * arch/sh/kernel/cpu/sh4a/clock-sh7343.c + * arch/sh/kernel/cpu/sh4/clock-sh7343.c * * SH7343/SH7722 support for the clock framework * diff --git a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7770.c b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7770.c index 8e236062c721..c8694bac6477 100644 --- a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7770.c +++ b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7770.c @@ -1,5 +1,5 @@ /* - * arch/sh/kernel/cpu/sh4a/clock-sh7770.c + * arch/sh/kernel/cpu/sh4/clock-sh7770.c * * SH7770 support for the clock framework * diff --git a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7780.c b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7780.c index 01f3da619d3d..9e6a216750c8 100644 --- a/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7780.c +++ b/trunk/arch/sh/kernel/cpu/sh4a/clock-sh7780.c @@ -1,5 +1,5 @@ /* - * arch/sh/kernel/cpu/sh4a/clock-sh7780.c + * arch/sh/kernel/cpu/sh4/clock-sh7780.c * * SH7780 support for the clock framework * diff --git a/trunk/arch/sh/kernel/process.c b/trunk/arch/sh/kernel/process.c index 6b4f5748d0be..329b3f3051de 100644 --- a/trunk/arch/sh/kernel/process.c +++ b/trunk/arch/sh/kernel/process.c @@ -15,12 +15,9 @@ #include #include #include -#include -#include +#include #include #include -#include -#include #include static int hlt_counter; @@ -61,15 +58,12 @@ void cpu_idle(void) if (!idle) idle = default_idle; - tick_nohz_stop_sched_tick(); while (!need_resched()) idle(); - tick_nohz_restart_sched_tick(); preempt_enable_no_resched(); schedule(); preempt_disable(); - check_pgt_cache(); } } @@ -501,9 +495,9 @@ asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5, struct pt_regs *regs = RELOC_HIDE(&__regs, 0); /* Rewind */ - regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); + regs->pc -= 2; - if (notify_die(DIE_TRAP, "debug trap", regs, 0, regs->tra & 0xff, + if (notify_die(DIE_TRAP, regs, regs->tra & 0xff, SIGTRAP) == NOTIFY_STOP) return; @@ -520,9 +514,9 @@ asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5, struct pt_regs *regs = RELOC_HIDE(&__regs, 0); /* Rewind */ - regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); + regs->pc -= 2; - if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff, + if (notify_die(DIE_TRAP, regs, TRAPA_BUG_OPCODE & 0xff, SIGTRAP) == NOTIFY_STOP) return; diff --git a/trunk/arch/sh/kernel/setup.c b/trunk/arch/sh/kernel/setup.c index c27729135935..477d2a854fc4 100644 --- a/trunk/arch/sh/kernel/setup.c +++ b/trunk/arch/sh/kernel/setup.c @@ -431,7 +431,7 @@ const char *get_cpu_subtype(struct sh_cpuinfo *c) /* Symbolic CPU flags, keep in sync with asm/cpu-features.h */ static const char *cpu_flags[] = { "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr", - "ptea", "llsc", "l2", "op32", NULL + "ptea", "llsc", "l2", NULL }; static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c) diff --git a/trunk/arch/sh/kernel/sh_ksyms.c b/trunk/arch/sh/kernel/sh_ksyms.c index c1cfcb9f047c..fa91641c1f62 100644 --- a/trunk/arch/sh/kernel/sh_ksyms.c +++ b/trunk/arch/sh/kernel/sh_ksyms.c @@ -58,6 +58,8 @@ EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__ndelay); EXPORT_SYMBOL(__const_udelay); +EXPORT_SYMBOL(__div64_32); + #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) /* These symbols are generated by the compiler itself */ diff --git a/trunk/arch/sh/kernel/signal.c b/trunk/arch/sh/kernel/signal.c index b32c35a7c0a3..eb0191c374b6 100644 --- a/trunk/arch/sh/kernel/signal.c +++ b/trunk/arch/sh/kernel/signal.c @@ -23,7 +23,7 @@ #include #include #include -#include + #include #include #include @@ -500,9 +500,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, } /* fallthrough */ case -ERESTARTNOINTR: - regs->pc -= instruction_size( - ctrl_inw(regs->pc - 4)); - break; + regs->pc -= 2; } } else { /* gUSA handling */ @@ -518,8 +516,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, regs->regs[15] = regs->regs[1]; if (regs->pc < regs->regs[0]) /* Go to rewind point #1 */ - regs->pc = regs->regs[0] + offset - - instruction_size(ctrl_inw(regs->pc-4)); + regs->pc = regs->regs[0] + offset - 2; } #ifdef CONFIG_PREEMPT local_irq_restore(flags); @@ -603,9 +600,9 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) regs->regs[0] == -ERESTARTSYS || regs->regs[0] == -ERESTARTNOINTR) { regs->regs[0] = save_r0; - regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); + regs->pc -= 2; } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) { - regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); + regs->pc -= 2; regs->regs[3] = __NR_restart_syscall; } } diff --git a/trunk/arch/sh/kernel/stacktrace.c b/trunk/arch/sh/kernel/stacktrace.c index d41e561be20e..4bdd2f83535d 100644 --- a/trunk/arch/sh/kernel/stacktrace.c +++ b/trunk/arch/sh/kernel/stacktrace.c @@ -17,7 +17,7 @@ /* * Save stack-backtrace addresses into a stack_trace buffer. */ -void save_stack_trace(struct stack_trace *trace) +void save_stack_trace(struct stack_trace *trace, struct task_struct *task) { unsigned long *sp = (unsigned long *)current_stack_pointer; diff --git a/trunk/arch/sh/kernel/syscalls.S b/trunk/arch/sh/kernel/syscalls.S index 4357d1a6358f..38fc8cd3ea3a 100644 --- a/trunk/arch/sh/kernel/syscalls.S +++ b/trunk/arch/sh/kernel/syscalls.S @@ -354,4 +354,3 @@ ENTRY(sys_call_table) .long sys_move_pages .long sys_getcpu .long sys_epoll_pwait - .long sys_utimensat /* 320 */ diff --git a/trunk/arch/sh/kernel/time.c b/trunk/arch/sh/kernel/time.c index a3a67d151e52..d47e775962e9 100644 --- a/trunk/arch/sh/kernel/time.c +++ b/trunk/arch/sh/kernel/time.c @@ -3,7 +3,7 @@ * * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka * Copyright (C) 2000 Philipp Rumpf - * Copyright (C) 2002 - 2007 Paul Mundt + * Copyright (C) 2002 - 2006 Paul Mundt * Copyright (C) 2002 M. R. Brown * * Some code taken from i386 version. @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -39,14 +38,6 @@ static int null_rtc_set_time(const time_t secs) return 0; } -/* - * Null high precision timer functions for systems lacking one. - */ -static cycle_t null_hpt_read(void) -{ - return 0; -} - void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time; int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; @@ -110,7 +101,6 @@ int do_settimeofday(struct timespec *tv) EXPORT_SYMBOL(do_settimeofday); #endif /* !CONFIG_GENERIC_TIME */ -#ifndef CONFIG_GENERIC_CLOCKEVENTS /* last time the RTC clock got updated */ static long last_rtc_update; @@ -148,7 +138,6 @@ void handle_timer_tick(void) last_rtc_update = xtime.tv_sec - 600; } } -#endif /* !CONFIG_GENERIC_CLOCKEVENTS */ #ifdef CONFIG_PM int timer_suspend(struct sys_device *dev, pm_message_t state) @@ -179,58 +168,136 @@ static struct sysdev_class timer_sysclass = { .resume = timer_resume, }; -static int __init timer_init_sysfs(void) +#ifdef CONFIG_NO_IDLE_HZ +static int timer_dyn_tick_enable(void) { - int ret = sysdev_class_register(&timer_sysclass); - if (ret != 0) - return ret; + struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; + unsigned long flags; + int ret = -ENODEV; + + if (dyn_tick) { + spin_lock_irqsave(&dyn_tick->lock, flags); + ret = 0; + if (!(dyn_tick->state & DYN_TICK_ENABLED)) { + ret = dyn_tick->enable(); + + if (ret == 0) + dyn_tick->state |= DYN_TICK_ENABLED; + } + spin_unlock_irqrestore(&dyn_tick->lock, flags); + } - sys_timer->dev.cls = &timer_sysclass; - return sysdev_register(&sys_timer->dev); + return ret; } -device_initcall(timer_init_sysfs); -void (*board_time_init)(void); +static int timer_dyn_tick_disable(void) +{ + struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; + unsigned long flags; + int ret = -ENODEV; + + if (dyn_tick) { + spin_lock_irqsave(&dyn_tick->lock, flags); + ret = 0; + if (dyn_tick->state & DYN_TICK_ENABLED) { + ret = dyn_tick->disable(); + + if (ret == 0) + dyn_tick->state &= ~DYN_TICK_ENABLED; + } + spin_unlock_irqrestore(&dyn_tick->lock, flags); + } + + return ret; +} /* - * Shamelessly based on the MIPS and Sparc64 work. + * Reprogram the system timer for at least the calculated time interval. + * This function should be called from the idle thread with IRQs disabled, + * immediately before sleeping. */ -static unsigned long timer_ticks_per_nsec_quotient __read_mostly; -unsigned long sh_hpt_frequency = 0; - -#define NSEC_PER_CYC_SHIFT 10 - -struct clocksource clocksource_sh = { - .name = "SuperH", - .rating = 200, - .mask = CLOCKSOURCE_MASK(32), - .read = null_hpt_read, - .shift = 16, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static void __init init_sh_clocksource(void) +void timer_dyn_reprogram(void) { - if (!sh_hpt_frequency || clocksource_sh.read == null_hpt_read) + struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; + unsigned long next, seq, flags; + + if (!dyn_tick) return; - clocksource_sh.mult = clocksource_hz2mult(sh_hpt_frequency, - clocksource_sh.shift); + spin_lock_irqsave(&dyn_tick->lock, flags); + if (dyn_tick->state & DYN_TICK_ENABLED) { + next = next_timer_interrupt(); + do { + seq = read_seqbegin(&xtime_lock); + dyn_tick->reprogram(next - jiffies); + } while (read_seqretry(&xtime_lock, seq)); + } + spin_unlock_irqrestore(&dyn_tick->lock, flags); +} + +static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) +{ + return sprintf(buf, "%i\n", + (sys_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1); +} + +static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf, + size_t count) +{ + unsigned int enable = simple_strtoul(buf, NULL, 2); - timer_ticks_per_nsec_quotient = - clocksource_hz2mult(sh_hpt_frequency, NSEC_PER_CYC_SHIFT); + if (enable) + timer_dyn_tick_enable(); + else + timer_dyn_tick_disable(); - clocksource_register(&clocksource_sh); + return count; } +static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick); -#ifdef CONFIG_GENERIC_TIME -unsigned long long sched_clock(void) +/* + * dyntick=enable|disable + */ +static char dyntick_str[4] __initdata = ""; + +static int __init dyntick_setup(char *str) { - unsigned long long ticks = clocksource_sh.read(); - return (ticks * timer_ticks_per_nsec_quotient) >> NSEC_PER_CYC_SHIFT; + if (str) + strlcpy(dyntick_str, str, sizeof(dyntick_str)); + return 1; } + +__setup("dyntick=", dyntick_setup); +#endif + +static int __init timer_init_sysfs(void) +{ + int ret = sysdev_class_register(&timer_sysclass); + if (ret != 0) + return ret; + + sys_timer->dev.cls = &timer_sysclass; + ret = sysdev_register(&sys_timer->dev); + +#ifdef CONFIG_NO_IDLE_HZ + if (ret == 0 && sys_timer->dyn_tick) { + ret = sysdev_create_file(&sys_timer->dev, &attr_dyn_tick); + + /* + * Turn on dynamic tick after calibrate delay + * for correct bogomips + */ + if (ret == 0 && dyntick_str[0] == 'e') + ret = timer_dyn_tick_enable(); + } #endif + return ret; +} +device_initcall(timer_init_sysfs); + +void (*board_time_init)(void); + void __init time_init(void) { if (board_time_init) @@ -249,15 +316,10 @@ void __init time_init(void) sys_timer = get_sys_timer(); printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); - if (sys_timer->ops->read) - clocksource_sh.read = sys_timer->ops->read; - - init_sh_clocksource(); - - if (sh_hpt_frequency) - printk("Using %lu.%03lu MHz high precision timer.\n", - ((sh_hpt_frequency + 500) / 1000) / 1000, - ((sh_hpt_frequency + 500) / 1000) % 1000); +#ifdef CONFIG_NO_IDLE_HZ + if (sys_timer->dyn_tick) + spin_lock_init(&sys_timer->dyn_tick->lock); +#endif #if defined(CONFIG_SH_KGDB) /* diff --git a/trunk/arch/sh/kernel/timers/timer-tmu.c b/trunk/arch/sh/kernel/timers/timer-tmu.c index 2d997e2a5b6c..d9e3151c891e 100644 --- a/trunk/arch/sh/kernel/timers/timer-tmu.c +++ b/trunk/arch/sh/kernel/timers/timer-tmu.c @@ -1,7 +1,7 @@ /* * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support * - * Copyright (C) 2005 - 2007 Paul Mundt + * Copyright (C) 2005 Paul Mundt * * TMU handling code hacked out of arch/sh/kernel/time.c * @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -26,75 +25,56 @@ #include #define TMU_TOCR_INIT 0x00 -#define TMU_TCR_INIT 0x0020 +#define TMU0_TCR_INIT 0x0020 +#define TMU_TSTR_INIT 1 -static int tmu_timer_start(void) -{ - ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR); - return 0; -} +#define TMU0_TCR_CALIB 0x0000 -static void tmu0_timer_set_interval(unsigned long interval, unsigned int reload) +static unsigned long tmu_timer_get_offset(void) { - ctrl_outl(interval, TMU0_TCNT); + int count; + static int count_p = 0x7fffffff; /* for the first call after boot */ + static unsigned long jiffies_p = 0; /* - * TCNT reloads from TCOR on underflow, clear it if we don't - * intend to auto-reload + * cache volatile jiffies temporarily; we have IRQs turned off. */ - if (reload) - ctrl_outl(interval, TMU0_TCOR); - else - ctrl_outl(0, TMU0_TCOR); + unsigned long jiffies_t; - tmu_timer_start(); -} + /* timer count may underflow right here */ + count = ctrl_inl(TMU0_TCNT); /* read the latched count */ -static int tmu_timer_stop(void) -{ - ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR); - return 0; -} + jiffies_t = jiffies; -static cycle_t tmu_timer_read(void) -{ - return ~ctrl_inl(TMU1_TCNT); -} - -static int tmu_set_next_event(unsigned long cycles, - struct clock_event_device *evt) -{ - tmu0_timer_set_interval(cycles, 1); - return 0; -} + /* + * avoiding timer inconsistencies (they are rare, but they happen)... + * there is one kind of problem that must be avoided here: + * 1. the timer counter underflows + */ -static void tmu_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - ctrl_outl(ctrl_inl(TMU0_TCNT), TMU0_TCOR); - break; - case CLOCK_EVT_MODE_ONESHOT: - ctrl_outl(0, TMU0_TCOR); - break; - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - break; - } + if (jiffies_t == jiffies_p) { + if (count > count_p) { + /* the nutcase */ + if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */ + count -= LATCH; + } else { + printk("%s (): hardware timer problem?\n", + __FUNCTION__); + } + } + } else + jiffies_p = jiffies_t; + + count_p = count; + + count = ((LATCH-1) - count) * TICK_SIZE; + count = (count + LATCH/2) / LATCH; + + return count; } -static struct clock_event_device tmu0_clockevent = { - .name = "tmu0", - .shift = 32, - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = tmu_set_mode, - .set_next_event = tmu_set_next_event, -}; - static irqreturn_t tmu_timer_interrupt(int irq, void *dummy) { - struct clock_event_device *evt = &tmu0_clockevent; unsigned long timer_status; /* Clear UNF bit */ @@ -102,76 +82,72 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy) timer_status &= ~0x100; ctrl_outw(timer_status, TMU0_TCR); - evt->event_handler(evt); + /* + * Here we are in the timer irq handler. We just have irqs locally + * disabled but we don't know if the timer_bh is running on the other + * CPU. We need to avoid to SMP race with it. NOTE: we don' t need + * the irq version of write_lock because as just said we have irq + * locally disabled. -arca + */ + write_seqlock(&xtime_lock); + handle_timer_tick(); + write_sequnlock(&xtime_lock); return IRQ_HANDLED; } -static struct irqaction tmu0_irq = { - .name = "periodic timer", +static struct irqaction tmu_irq = { + .name = "timer", .handler = tmu_timer_interrupt, .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, .mask = CPU_MASK_NONE, }; -static void tmu0_clk_init(struct clk *clk) +static void tmu_clk_init(struct clk *clk) { - u8 divisor = TMU_TCR_INIT & 0x7; - ctrl_outw(TMU_TCR_INIT, TMU0_TCR); + u8 divisor = TMU0_TCR_INIT & 0x7; + ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); clk->rate = clk->parent->rate / (4 << (divisor << 1)); } -static void tmu0_clk_recalc(struct clk *clk) +static void tmu_clk_recalc(struct clk *clk) { u8 divisor = ctrl_inw(TMU0_TCR) & 0x7; clk->rate = clk->parent->rate / (4 << (divisor << 1)); } -static struct clk_ops tmu0_clk_ops = { - .init = tmu0_clk_init, - .recalc = tmu0_clk_recalc, +static struct clk_ops tmu_clk_ops = { + .init = tmu_clk_init, + .recalc = tmu_clk_recalc, }; static struct clk tmu0_clk = { .name = "tmu0_clk", - .ops = &tmu0_clk_ops, + .ops = &tmu_clk_ops, }; -static void tmu1_clk_init(struct clk *clk) +static int tmu_timer_start(void) { - u8 divisor = TMU_TCR_INIT & 0x7; - ctrl_outw(divisor, TMU1_TCR); - clk->rate = clk->parent->rate / (4 << (divisor << 1)); + ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); + return 0; } -static void tmu1_clk_recalc(struct clk *clk) +static int tmu_timer_stop(void) { - u8 divisor = ctrl_inw(TMU1_TCR) & 0x7; - clk->rate = clk->parent->rate / (4 << (divisor << 1)); + ctrl_outb(0, TMU_TSTR); + return 0; } -static struct clk_ops tmu1_clk_ops = { - .init = tmu1_clk_init, - .recalc = tmu1_clk_recalc, -}; - -static struct clk tmu1_clk = { - .name = "tmu1_clk", - .ops = &tmu1_clk_ops, -}; - static int tmu_timer_init(void) { unsigned long interval; - unsigned long frequency; - setup_irq(CONFIG_SH_TIMER_IRQ, &tmu0_irq); + setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq); tmu0_clk.parent = clk_get(NULL, "module_clk"); - tmu1_clk.parent = clk_get(NULL, "module_clk"); + /* Start TMU0 */ tmu_timer_stop(); - #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \ !defined(CONFIG_CPU_SUBTYPE_SH7760) && \ !defined(CONFIG_CPU_SUBTYPE_SH7785) @@ -179,29 +155,15 @@ static int tmu_timer_init(void) #endif clk_register(&tmu0_clk); - clk_register(&tmu1_clk); clk_enable(&tmu0_clk); - clk_enable(&tmu1_clk); - - frequency = clk_get_rate(&tmu0_clk); - interval = (frequency + HZ / 2) / HZ; - sh_hpt_frequency = clk_get_rate(&tmu1_clk); - ctrl_outl(~0, TMU1_TCNT); - ctrl_outl(~0, TMU1_TCOR); + interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ; + printk(KERN_INFO "Interval = %ld\n", interval); - tmu0_timer_set_interval(interval, 1); - - tmu0_clockevent.mult = div_sc(frequency, NSEC_PER_SEC, - tmu0_clockevent.shift); - tmu0_clockevent.max_delta_ns = - clockevent_delta2ns(-1, &tmu0_clockevent); - tmu0_clockevent.min_delta_ns = - clockevent_delta2ns(1, &tmu0_clockevent); - - tmu0_clockevent.cpumask = cpumask_of_cpu(0); + ctrl_outl(interval, TMU0_TCOR); + ctrl_outl(interval, TMU0_TCNT); - clockevents_register_device(&tmu0_clockevent); + tmu_timer_start(); return 0; } @@ -210,7 +172,9 @@ struct sys_timer_ops tmu_timer_ops = { .init = tmu_timer_init, .start = tmu_timer_start, .stop = tmu_timer_stop, - .read = tmu_timer_read, +#ifndef CONFIG_GENERIC_TIME + .get_offset = tmu_timer_get_offset, +#endif }; struct sys_timer tmu_timer = { diff --git a/trunk/arch/sh/kernel/traps.c b/trunk/arch/sh/kernel/traps.c index 3a197649cd83..7b40f0ff3dfc 100644 --- a/trunk/arch/sh/kernel/traps.c +++ b/trunk/arch/sh/kernel/traps.c @@ -20,10 +20,10 @@ #include #include #include -#include #include #include #include +#include #ifdef CONFIG_SH_KGDB #include @@ -76,6 +76,20 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top) } } +ATOMIC_NOTIFIER_HEAD(shdie_chain); + +int register_die_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&shdie_chain, nb); +} +EXPORT_SYMBOL(register_die_notifier); + +int unregister_die_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&shdie_chain, nb); +} +EXPORT_SYMBOL(unregister_die_notifier); + static DEFINE_SPINLOCK(die_lock); void die(const char * str, struct pt_regs * regs, long err) @@ -491,7 +505,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) simple: ret = handle_unaligned_ins(instruction,regs); if (ret==0) - regs->pc += instruction_size(instruction); + regs->pc += 2; return ret; } #endif /* CONFIG_CPU_SH2A */ @@ -668,7 +682,7 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, err = do_fpu_inst(inst, regs); if (!err) { - regs->pc += instruction_size(inst); + regs->pc += 2; return; } /* not a FPU inst. */ diff --git a/trunk/arch/sh/kernel/vsyscall/vsyscall.c b/trunk/arch/sh/kernel/vsyscall/vsyscall.c index e146bafcd14f..7b0f66f03319 100644 --- a/trunk/arch/sh/kernel/vsyscall/vsyscall.c +++ b/trunk/arch/sh/kernel/vsyscall/vsyscall.c @@ -1,5 +1,5 @@ /* - * arch/sh/kernel/vsyscall/vsyscall.c + * arch/sh/kernel/vsyscall.c * * Copyright (C) 2006 Paul Mundt * diff --git a/trunk/arch/sh/lib/delay.c b/trunk/arch/sh/lib/delay.c index f3ddd2133e6f..351714694d6d 100644 --- a/trunk/arch/sh/lib/delay.c +++ b/trunk/arch/sh/lib/delay.c @@ -24,10 +24,9 @@ inline void __const_udelay(unsigned long xloops) __asm__("dmulu.l %0, %2\n\t" "sts mach, %0" : "=r" (xloops) - : "0" (xloops), - "r" (HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) + : "0" (xloops), "r" (cpu_data[raw_smp_processor_id()].loops_per_jiffy) : "macl", "mach"); - __delay(xloops); + __delay(xloops * HZ); } void __udelay(unsigned long usecs) diff --git a/trunk/arch/sh/mm/Kconfig b/trunk/arch/sh/mm/Kconfig index 253346d7b316..12f3d394dc28 100644 --- a/trunk/arch/sh/mm/Kconfig +++ b/trunk/arch/sh/mm/Kconfig @@ -218,9 +218,6 @@ endmenu menu "Memory management options" -config QUICKLIST - def_bool y - config MMU bool "Support for memory management hardware" depends on !CPU_SH2 @@ -303,10 +300,6 @@ config NODES_SHIFT config ARCH_FLATMEM_ENABLE def_bool y -config MAX_ACTIVE_REGIONS - int - default "1" - config ARCH_POPULATES_NODE_MAP def_bool y diff --git a/trunk/arch/sh/mm/fault.c b/trunk/arch/sh/mm/fault.c index 9207da67ff8a..0ecc117cade4 100644 --- a/trunk/arch/sh/mm/fault.c +++ b/trunk/arch/sh/mm/fault.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/trunk/arch/sh/mm/init.c b/trunk/arch/sh/mm/init.c index 8fe223a890ed..4d030988b368 100644 --- a/trunk/arch/sh/mm/init.c +++ b/trunk/arch/sh/mm/init.c @@ -67,8 +67,6 @@ void show_mem(void) printk("%d slab pages\n", slab); printk("%d pages shared\n", shared); printk("%d pages swap cached\n", cached); - printk(KERN_INFO "Total of %ld pages in page table cache\n", - quicklist_total_size()); } #ifdef CONFIG_MMU diff --git a/trunk/arch/sparc/kernel/asm-offsets.c b/trunk/arch/sparc/kernel/asm-offsets.c index 6773ed76e414..29d7cfd1c970 100644 --- a/trunk/arch/sparc/kernel/asm-offsets.c +++ b/trunk/arch/sparc/kernel/asm-offsets.c @@ -28,7 +28,7 @@ int foo(void) DEFINE(AOFF_task_gid, offsetof(struct task_struct, gid)); DEFINE(AOFF_task_euid, offsetof(struct task_struct, euid)); DEFINE(AOFF_task_egid, offsetof(struct task_struct, egid)); - /* DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); */ + /* DEFINE(THREAD_INFO, offsetof(struct task_struct, thread_info)); */ DEFINE(ASIZ_task_uid, sizeof(current->uid)); DEFINE(ASIZ_task_gid, sizeof(current->gid)); DEFINE(ASIZ_task_euid, sizeof(current->euid)); diff --git a/trunk/arch/sparc64/kernel/pci.c b/trunk/arch/sparc64/kernel/pci.c index cf9a75112d0f..d85e1ed7c3e4 100644 --- a/trunk/arch/sparc64/kernel/pci.c +++ b/trunk/arch/sparc64/kernel/pci.c @@ -377,7 +377,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, const char *type; u32 class; - dev = alloc_pci_dev(); + dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); if (!dev) return NULL; diff --git a/trunk/arch/sparc64/kernel/pci_common.c b/trunk/arch/sparc64/kernel/pci_common.c index f974fefc3ebc..76faaa8135dd 100644 --- a/trunk/arch/sparc64/kernel/pci_common.c +++ b/trunk/arch/sparc64/kernel/pci_common.c @@ -14,200 +14,6 @@ #include #include "pci_impl.h" -#include "pci_sun4v.h" - -static int config_out_of_range(struct pci_pbm_info *pbm, - unsigned long bus, - unsigned long devfn, - unsigned long reg) -{ - if (bus < pbm->pci_first_busno || - bus > pbm->pci_last_busno) - return 1; - return 0; -} - -static void *sun4u_config_mkaddr(struct pci_pbm_info *pbm, - unsigned long bus, - unsigned long devfn, - unsigned long reg) -{ - unsigned long rbits = pbm->config_space_reg_bits; - - if (config_out_of_range(pbm, bus, devfn, reg)) - return NULL; - - reg = (reg & ((1 << rbits) - 1)); - devfn <<= rbits; - bus <<= rbits + 8; - - return (void *) (pbm->config_space | bus | devfn | reg); -} - -static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, - int where, int size, u32 *value) -{ - struct pci_pbm_info *pbm = bus_dev->sysdata; - unsigned char bus = bus_dev->number; - u32 *addr; - u16 tmp16; - u8 tmp8; - - if (bus_dev == pbm->pci_bus && devfn == 0x00) - return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, - size, value); - - switch (size) { - case 1: - *value = 0xff; - break; - case 2: - *value = 0xffff; - break; - case 4: - *value = 0xffffffff; - break; - } - - addr = sun4u_config_mkaddr(pbm, bus, devfn, where); - if (!addr) - return PCIBIOS_SUCCESSFUL; - - switch (size) { - case 1: - pci_config_read8((u8 *)addr, &tmp8); - *value = (u32) tmp8; - break; - - case 2: - if (where & 0x01) { - printk("pci_read_config_word: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_read16((u16 *)addr, &tmp16); - *value = (u32) tmp16; - break; - - case 4: - if (where & 0x03) { - printk("pci_read_config_dword: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_read32(addr, value); - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, - int where, int size, u32 value) -{ - struct pci_pbm_info *pbm = bus_dev->sysdata; - unsigned char bus = bus_dev->number; - u32 *addr; - - if (bus_dev == pbm->pci_bus && devfn == 0x00) - return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, - size, value); - addr = sun4u_config_mkaddr(pbm, bus, devfn, where); - if (!addr) - return PCIBIOS_SUCCESSFUL; - - switch (size) { - case 1: - pci_config_write8((u8 *)addr, value); - break; - - case 2: - if (where & 0x01) { - printk("pci_write_config_word: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_write16((u16 *)addr, value); - break; - - case 4: - if (where & 0x03) { - printk("pci_write_config_dword: misaligned reg [%x]\n", - where); - return PCIBIOS_SUCCESSFUL; - } - pci_config_write32(addr, value); - } - return PCIBIOS_SUCCESSFUL; -} - -struct pci_ops sun4u_pci_ops = { - .read = sun4u_read_pci_cfg, - .write = sun4u_write_pci_cfg, -}; - -static int sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, - int where, int size, u32 *value) -{ - struct pci_pbm_info *pbm = bus_dev->sysdata; - u32 devhandle = pbm->devhandle; - unsigned int bus = bus_dev->number; - unsigned int device = PCI_SLOT(devfn); - unsigned int func = PCI_FUNC(devfn); - unsigned long ret; - - if (bus_dev == pbm->pci_bus && devfn == 0x00) - return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, - size, value); - if (config_out_of_range(pbm, bus, devfn, where)) { - ret = ~0UL; - } else { - ret = pci_sun4v_config_get(devhandle, - HV_PCI_DEVICE_BUILD(bus, device, func), - where, size); - } - switch (size) { - case 1: - *value = ret & 0xff; - break; - case 2: - *value = ret & 0xffff; - break; - case 4: - *value = ret & 0xffffffff; - break; - }; - - - return PCIBIOS_SUCCESSFUL; -} - -static int sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, - int where, int size, u32 value) -{ - struct pci_pbm_info *pbm = bus_dev->sysdata; - u32 devhandle = pbm->devhandle; - unsigned int bus = bus_dev->number; - unsigned int device = PCI_SLOT(devfn); - unsigned int func = PCI_FUNC(devfn); - unsigned long ret; - - if (bus_dev == pbm->pci_bus && devfn == 0x00) - return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, - size, value); - if (config_out_of_range(pbm, bus, devfn, where)) { - /* Do nothing. */ - } else { - ret = pci_sun4v_config_put(devhandle, - HV_PCI_DEVICE_BUILD(bus, device, func), - where, size, value); - } - return PCIBIOS_SUCCESSFUL; -} - -struct pci_ops sun4v_pci_ops = { - .read = sun4v_read_pci_cfg, - .write = sun4v_write_pci_cfg, -}; void pci_get_pbm_props(struct pci_pbm_info *pbm) { diff --git a/trunk/arch/sparc64/kernel/pci_fire.c b/trunk/arch/sparc64/kernel/pci_fire.c index 9198c1a0f7a5..2e0eb4ee8f71 100644 --- a/trunk/arch/sparc64/kernel/pci_fire.c +++ b/trunk/arch/sparc64/kernel/pci_fire.c @@ -27,6 +27,138 @@ "i" (ASI_PHYS_BYPASS_EC_E) \ : "memory") +/* Fire config space address format is nearly identical to + * that of SCHIZO and PSYCHO, except that in order to accomodate + * PCI-E extended config space the encoding can handle 12 bits + * of register address: + * + * 32 28 27 20 19 15 14 12 11 2 1 0 + * ------------------------------------------------- + * |0 0 0 0 0| bus | device | function | reg | 0 0 | + * ------------------------------------------------- + */ +#define FIRE_CONFIG_BASE(PBM) ((PBM)->config_space) +#define FIRE_CONFIG_ENCODE(BUS, DEVFN, REG) \ + (((unsigned long)(BUS) << 20) | \ + ((unsigned long)(DEVFN) << 12) | \ + ((unsigned long)(REG))) + +static void *fire_pci_config_mkaddr(struct pci_pbm_info *pbm, + unsigned char bus, + unsigned int devfn, + int where) +{ + if (!pbm) + return NULL; + return (void *) + (FIRE_CONFIG_BASE(pbm) | + FIRE_CONFIG_ENCODE(bus, devfn, where)); +} + +/* FIRE PCI configuration space accessors. */ + +static int fire_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 *value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + u16 tmp16; + u8 tmp8; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, + size, value); + switch (size) { + case 1: + *value = 0xff; + break; + case 2: + *value = 0xffff; + break; + case 4: + *value = 0xffffffff; + break; + } + + addr = fire_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + pci_config_read8((u8 *)addr, &tmp8); + *value = tmp8; + break; + + case 2: + if (where & 0x01) { + printk("pci_read_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_read16((u16 *)addr, &tmp16); + *value = tmp16; + break; + + case 4: + if (where & 0x03) { + printk("pci_read_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + + pci_config_read32(addr, value); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int fire_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, + size, value); + addr = fire_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + pci_config_write8((u8 *)addr, value); + break; + + case 2: + if (where & 0x01) { + printk("pci_write_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_write16((u16 *)addr, value); + break; + + case 4: + if (where & 0x03) { + printk("pci_write_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + + pci_config_write32(addr, value); + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops pci_fire_ops = { + .read = fire_read_pci_cfg, + .write = fire_write_pci_cfg, +}; + static void pci_fire_scan_bus(struct pci_pbm_info *pbm) { pbm->pci_bus = pci_scan_one_pbm(pbm); @@ -182,8 +314,7 @@ static void pci_fire_pbm_init(struct pci_controller_info *p, pci_pbm_root = pbm; pbm->scan_bus = pci_fire_scan_bus; - pbm->pci_ops = &sun4u_pci_ops; - pbm->config_space_reg_bits = 12; + pbm->pci_ops = &pci_fire_ops; pbm->index = pci_num_pbms++; diff --git a/trunk/arch/sparc64/kernel/pci_impl.h b/trunk/arch/sparc64/kernel/pci_impl.h index f660c2b685eb..8e38023868aa 100644 --- a/trunk/arch/sparc64/kernel/pci_impl.h +++ b/trunk/arch/sparc64/kernel/pci_impl.h @@ -77,9 +77,6 @@ struct pci_pbm_info { /* Base of PCI Config space, can be per-PBM or shared. */ unsigned long config_space; - /* This will be 12 on PCI-E controllers, 8 elsewhere. */ - unsigned long config_space_reg_bits; - /* State of 66MHz capabilities on this PBM. */ int is_66mhz_capable; int all_devs_66mhz; @@ -159,7 +156,4 @@ extern void pci_config_write8(u8 *addr, u8 val); extern void pci_config_write16(u16 *addr, u16 val); extern void pci_config_write32(u32 *addr, u32 val); -extern struct pci_ops sun4u_pci_ops; -extern struct pci_ops sun4v_pci_ops; - #endif /* !(PCI_IMPL_H) */ diff --git a/trunk/arch/sparc64/kernel/pci_psycho.c b/trunk/arch/sparc64/kernel/pci_psycho.c index 598393a2df16..2edcb1dd13c3 100644 --- a/trunk/arch/sparc64/kernel/pci_psycho.c +++ b/trunk/arch/sparc64/kernel/pci_psycho.c @@ -94,6 +94,122 @@ static void *psycho_pci_config_mkaddr(struct pci_pbm_info *pbm, PSYCHO_CONFIG_ENCODE(bus, devfn, where)); } +static int psycho_out_of_range(struct pci_pbm_info *pbm, + unsigned char bus, + unsigned char devfn) +{ + return ((bus == pbm->pci_first_busno) && + PCI_SLOT(devfn) > 8); +} + +/* PSYCHO PCI configuration space accessors. */ + +static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 *value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + u16 tmp16; + u8 tmp8; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, + size, value); + + switch (size) { + case 1: + *value = 0xff; + break; + case 2: + *value = 0xffff; + break; + case 4: + *value = 0xffffffff; + break; + } + + addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + if (psycho_out_of_range(pbm, bus, devfn)) + return PCIBIOS_SUCCESSFUL; + switch (size) { + case 1: + pci_config_read8((u8 *)addr, &tmp8); + *value = (u32) tmp8; + break; + + case 2: + if (where & 0x01) { + printk("pci_read_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_read16((u16 *)addr, &tmp16); + *value = (u32) tmp16; + break; + + case 4: + if (where & 0x03) { + printk("pci_read_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_read32(addr, value); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, + size, value); + addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + if (psycho_out_of_range(pbm, bus, devfn)) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + pci_config_write8((u8 *)addr, value); + break; + + case 2: + if (where & 0x01) { + printk("pci_write_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_write16((u16 *)addr, value); + break; + + case 4: + if (where & 0x03) { + printk("pci_write_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_write32(addr, value); + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops psycho_ops = { + .read = psycho_read_pci_cfg, + .write = psycho_write_pci_cfg, +}; + /* PSYCHO error handling support. */ enum psycho_error_type { UE_ERR, CE_ERR, PCI_ERR @@ -973,8 +1089,7 @@ static void psycho_pbm_init(struct pci_controller_info *p, pci_pbm_root = pbm; pbm->scan_bus = psycho_scan_bus; - pbm->pci_ops = &sun4u_pci_ops; - pbm->config_space_reg_bits = 8; + pbm->pci_ops = &psycho_ops; pbm->index = pci_num_pbms++; diff --git a/trunk/arch/sparc64/kernel/pci_sabre.c b/trunk/arch/sparc64/kernel/pci_sabre.c index e2377796de89..4cefe6e83b24 100644 --- a/trunk/arch/sparc64/kernel/pci_sabre.c +++ b/trunk/arch/sparc64/kernel/pci_sabre.c @@ -205,9 +205,294 @@ #define SABRE_MEMSPACE 0x100000000UL #define SABRE_MEMSPACE_SIZE 0x07fffffffUL +/* UltraSparc-IIi Programmer's Manual, page 325, PCI + * configuration space address format: + * + * 32 24 23 16 15 11 10 8 7 2 1 0 + * --------------------------------------------------------- + * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 | + * --------------------------------------------------------- + */ +#define SABRE_CONFIG_BASE(PBM) \ + ((PBM)->config_space | (1UL << 24)) +#define SABRE_CONFIG_ENCODE(BUS, DEVFN, REG) \ + (((unsigned long)(BUS) << 16) | \ + ((unsigned long)(DEVFN) << 8) | \ + ((unsigned long)(REG))) + static int hummingbird_p; static struct pci_bus *sabre_root_bus; +static void *sabre_pci_config_mkaddr(struct pci_pbm_info *pbm, + unsigned char bus, + unsigned int devfn, + int where) +{ + if (!pbm) + return NULL; + return (void *) + (SABRE_CONFIG_BASE(pbm) | + SABRE_CONFIG_ENCODE(bus, devfn, where)); +} + +static int sabre_out_of_range(unsigned char devfn) +{ + if (hummingbird_p) + return 0; + + return (((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) || + ((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) > 1)) || + (PCI_SLOT(devfn) > 1)); +} + +static int __sabre_out_of_range(struct pci_pbm_info *pbm, + unsigned char bus, + unsigned char devfn) +{ + if (hummingbird_p) + return 0; + + return ((pbm->parent == 0) || + ((pbm == &pbm->parent->pbm_A) && + (bus == pbm->pci_first_busno) && + PCI_SLOT(devfn) > 8)); +} + +static int __sabre_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 *value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + u16 tmp16; + u8 tmp8; + + switch (size) { + case 1: + *value = 0xff; + break; + case 2: + *value = 0xffff; + break; + case 4: + *value = 0xffffffff; + break; + } + + addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + if (__sabre_out_of_range(pbm, bus, devfn)) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + pci_config_read8((u8 *) addr, &tmp8); + *value = tmp8; + break; + + case 2: + if (where & 0x01) { + printk("pci_read_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_read16((u16 *) addr, &tmp16); + *value = tmp16; + break; + + case 4: + if (where & 0x03) { + printk("pci_read_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_read32(addr, value); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *value) +{ + struct pci_pbm_info *pbm = bus->sysdata; + + if (bus == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus, devfn, where, + size, value); + + if (!bus->number && sabre_out_of_range(devfn)) { + switch (size) { + case 1: + *value = 0xff; + break; + case 2: + *value = 0xffff; + break; + case 4: + *value = 0xffffffff; + break; + } + return PCIBIOS_SUCCESSFUL; + } + + if (bus->number || PCI_SLOT(devfn)) + return __sabre_read_pci_cfg(bus, devfn, where, size, value); + + /* When accessing PCI config space of the PCI controller itself (bus + * 0, device slot 0, function 0) there are restrictions. Each + * register must be accessed as it's natural size. Thus, for example + * the Vendor ID must be accessed as a 16-bit quantity. + */ + + switch (size) { + case 1: + if (where < 8) { + u32 tmp32; + u16 tmp16; + + __sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32); + tmp16 = (u16) tmp32; + if (where & 1) + *value = tmp16 >> 8; + else + *value = tmp16 & 0xff; + } else + return __sabre_read_pci_cfg(bus, devfn, where, 1, value); + break; + + case 2: + if (where < 8) + return __sabre_read_pci_cfg(bus, devfn, where, 2, value); + else { + u32 tmp32; + u8 tmp8; + + __sabre_read_pci_cfg(bus, devfn, where, 1, &tmp32); + tmp8 = (u8) tmp32; + *value = tmp8; + __sabre_read_pci_cfg(bus, devfn, where + 1, 1, &tmp32); + tmp8 = (u8) tmp32; + *value |= tmp8 << 8; + } + break; + + case 4: { + u32 tmp32; + u16 tmp16; + + sabre_read_pci_cfg(bus, devfn, where, 2, &tmp32); + tmp16 = (u16) tmp32; + *value = tmp16; + sabre_read_pci_cfg(bus, devfn, where + 2, 2, &tmp32); + tmp16 = (u16) tmp32; + *value |= tmp16 << 16; + break; + } + } + return PCIBIOS_SUCCESSFUL; +} + +static int __sabre_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + + addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + if (__sabre_out_of_range(pbm, bus, devfn)) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + pci_config_write8((u8 *) addr, value); + break; + + case 2: + if (where & 0x01) { + printk("pci_write_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_write16((u16 *) addr, value); + break; + + case 4: + if (where & 0x03) { + printk("pci_write_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_write32(addr, value); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int sabre_write_pci_cfg(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + struct pci_pbm_info *pbm = bus->sysdata; + + if (bus == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus, devfn, where, + size, value); + + if (bus->number) + return __sabre_write_pci_cfg(bus, devfn, where, size, value); + + if (sabre_out_of_range(devfn)) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + if (where < 8) { + u32 tmp32; + u16 tmp16; + + __sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32); + tmp16 = (u16) tmp32; + if (where & 1) { + value &= 0x00ff; + value |= tmp16 << 8; + } else { + value &= 0xff00; + value |= tmp16; + } + tmp32 = (u32) tmp16; + return __sabre_write_pci_cfg(bus, devfn, where & ~1, 2, tmp32); + } else + return __sabre_write_pci_cfg(bus, devfn, where, 1, value); + break; + case 2: + if (where < 8) + return __sabre_write_pci_cfg(bus, devfn, where, 2, value); + else { + __sabre_write_pci_cfg(bus, devfn, where, 1, value & 0xff); + __sabre_write_pci_cfg(bus, devfn, where + 1, 1, value >> 8); + } + break; + case 4: + sabre_write_pci_cfg(bus, devfn, where, 2, value & 0xffff); + sabre_write_pci_cfg(bus, devfn, where + 2, 2, value >> 16); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops sabre_ops = { + .read = sabre_read_pci_cfg, + .write = sabre_write_pci_cfg, +}; + /* SABRE error handling support. */ static void sabre_check_iommu_error(struct pci_pbm_info *pbm, unsigned long afsr, @@ -725,8 +1010,7 @@ static void sabre_pbm_init(struct pci_controller_info *p, struct pci_pbm_info *p printk("%s: SABRE PCI Bus Module\n", pbm->name); pbm->scan_bus = sabre_scan_bus; - pbm->pci_ops = &sun4u_pci_ops; - pbm->config_space_reg_bits = 8; + pbm->pci_ops = &sabre_ops; pbm->index = pci_num_pbms++; diff --git a/trunk/arch/sparc64/kernel/pci_schizo.c b/trunk/arch/sparc64/kernel/pci_schizo.c index ae76898bbe2b..e375d72b8eed 100644 --- a/trunk/arch/sparc64/kernel/pci_schizo.c +++ b/trunk/arch/sparc64/kernel/pci_schizo.c @@ -104,6 +104,125 @@ static void *schizo_pci_config_mkaddr(struct pci_pbm_info *pbm, SCHIZO_CONFIG_ENCODE(bus, devfn, where)); } +/* Just make sure the bus number is in range. */ +static int schizo_out_of_range(struct pci_pbm_info *pbm, + unsigned char bus, + unsigned char devfn) +{ + if (bus < pbm->pci_first_busno || + bus > pbm->pci_last_busno) + return 1; + return 0; +} + +/* SCHIZO PCI configuration space accessors. */ + +static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 *value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + u16 tmp16; + u8 tmp8; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, + size, value); + switch (size) { + case 1: + *value = 0xff; + break; + case 2: + *value = 0xffff; + break; + case 4: + *value = 0xffffffff; + break; + } + + addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + if (schizo_out_of_range(pbm, bus, devfn)) + return PCIBIOS_SUCCESSFUL; + switch (size) { + case 1: + pci_config_read8((u8 *)addr, &tmp8); + *value = tmp8; + break; + + case 2: + if (where & 0x01) { + printk("pci_read_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_read16((u16 *)addr, &tmp16); + *value = tmp16; + break; + + case 4: + if (where & 0x03) { + printk("pci_read_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_read32(addr, value); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + unsigned char bus = bus_dev->number; + u32 *addr; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, + size, value); + addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where); + if (!addr) + return PCIBIOS_SUCCESSFUL; + + if (schizo_out_of_range(pbm, bus, devfn)) + return PCIBIOS_SUCCESSFUL; + + switch (size) { + case 1: + pci_config_write8((u8 *)addr, value); + break; + + case 2: + if (where & 0x01) { + printk("pci_write_config_word: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + pci_config_write16((u16 *)addr, value); + break; + + case 4: + if (where & 0x03) { + printk("pci_write_config_dword: misaligned reg [%x]\n", + where); + return PCIBIOS_SUCCESSFUL; + } + + pci_config_write32(addr, value); + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops schizo_ops = { + .read = schizo_read_pci_cfg, + .write = schizo_write_pci_cfg, +}; + /* SCHIZO error handling support. */ enum schizo_error_type { UE_ERR, CE_ERR, PCI_ERR, SAFARI_ERR @@ -1375,8 +1494,7 @@ static void schizo_pbm_init(struct pci_controller_info *p, pci_pbm_root = pbm; pbm->scan_bus = schizo_scan_bus; - pbm->pci_ops = &sun4u_pci_ops; - pbm->config_space_reg_bits = 8; + pbm->pci_ops = &schizo_ops; pbm->index = pci_num_pbms++; diff --git a/trunk/arch/sparc64/kernel/pci_sun4v.c b/trunk/arch/sparc64/kernel/pci_sun4v.c index 34df4047587a..0c76a8891a96 100644 --- a/trunk/arch/sparc64/kernel/pci_sun4v.c +++ b/trunk/arch/sparc64/kernel/pci_sun4v.c @@ -593,6 +593,89 @@ const struct pci_iommu_ops pci_sun4v_iommu_ops = { .dma_sync_sg_for_cpu = pci_4v_dma_sync_sg_for_cpu, }; +static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func) +{ + if (bus < pbm->pci_first_busno || + bus > pbm->pci_last_busno) + return 1; + return 0; +} + +static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 *value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + u32 devhandle = pbm->devhandle; + unsigned int bus = bus_dev->number; + unsigned int device = PCI_SLOT(devfn); + unsigned int func = PCI_FUNC(devfn); + unsigned long ret; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, + size, value); + if (pci_sun4v_out_of_range(pbm, bus, device, func)) { + ret = ~0UL; + } else { + ret = pci_sun4v_config_get(devhandle, + HV_PCI_DEVICE_BUILD(bus, device, func), + where, size); +#if 0 + printk("rcfg: [%x:%x:%x:%d]=[%lx]\n", + devhandle, HV_PCI_DEVICE_BUILD(bus, device, func), + where, size, ret); +#endif + } + switch (size) { + case 1: + *value = ret & 0xff; + break; + case 2: + *value = ret & 0xffff; + break; + case 4: + *value = ret & 0xffffffff; + break; + }; + + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, + int where, int size, u32 value) +{ + struct pci_pbm_info *pbm = bus_dev->sysdata; + u32 devhandle = pbm->devhandle; + unsigned int bus = bus_dev->number; + unsigned int device = PCI_SLOT(devfn); + unsigned int func = PCI_FUNC(devfn); + unsigned long ret; + + if (bus_dev == pbm->pci_bus && devfn == 0x00) + return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, + size, value); + if (pci_sun4v_out_of_range(pbm, bus, device, func)) { + /* Do nothing. */ + } else { + ret = pci_sun4v_config_put(devhandle, + HV_PCI_DEVICE_BUILD(bus, device, func), + where, size, value); +#if 0 + printk("wcfg: [%x:%x:%x:%d] v[%x] == [%lx]\n", + devhandle, HV_PCI_DEVICE_BUILD(bus, device, func), + where, size, value, ret); +#endif + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops pci_sun4v_ops = { + .read = pci_sun4v_read_pci_cfg, + .write = pci_sun4v_write_pci_cfg, +}; + + static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm) { struct property *prop; @@ -1155,8 +1238,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node pci_pbm_root = pbm; pbm->scan_bus = pci_sun4v_scan_bus; - pbm->pci_ops = &sun4v_pci_ops; - pbm->config_space_reg_bits = 12; + pbm->pci_ops = &pci_sun4v_ops; pbm->index = pci_num_pbms++; diff --git a/trunk/arch/sparc64/kernel/prom.c b/trunk/arch/sparc64/kernel/prom.c index b7976b14d0ba..c54d4d8af014 100644 --- a/trunk/arch/sparc64/kernel/prom.c +++ b/trunk/arch/sparc64/kernel/prom.c @@ -1636,21 +1636,10 @@ static struct device_node * __init create_node(phandle node, struct device_node static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp) { - struct device_node *ret = NULL, *prev_sibling = NULL; struct device_node *dp; - while (1) { - dp = create_node(node, parent); - if (!dp) - break; - - if (prev_sibling) - prev_sibling->sibling = dp; - - if (!ret) - ret = dp; - prev_sibling = dp; - + dp = create_node(node, parent); + if (dp) { *(*nextp) = dp; *nextp = &dp->allnext; @@ -1659,10 +1648,10 @@ static struct device_node * __init build_tree(struct device_node *parent, phandl dp->child = build_tree(dp, prom_getchild(node), nextp); - node = prom_getsibling(node); + dp->sibling = build_tree(parent, prom_getsibling(node), nextp); } - return ret; + return dp; } void __init prom_build_devicetree(void) diff --git a/trunk/arch/sparc64/kernel/traps.c b/trunk/arch/sparc64/kernel/traps.c index d0fde36395b4..dc652f210290 100644 --- a/trunk/arch/sparc64/kernel/traps.c +++ b/trunk/arch/sparc64/kernel/traps.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include diff --git a/trunk/arch/um/Kconfig b/trunk/arch/um/Kconfig index b9c0f307a8fa..354cc6b70530 100644 --- a/trunk/arch/um/Kconfig +++ b/trunk/arch/um/Kconfig @@ -320,7 +320,21 @@ source "crypto/Kconfig" source "lib/Kconfig" -source "drivers/scsi/Kconfig" +menu "SCSI support" +depends on BROKEN + +config SCSI + tristate "SCSI support" + +# This gives us free_dma, which scsi.c wants. +config GENERIC_ISA_DMA + bool + depends on SCSI + default y + +source "arch/um/Kconfig.scsi" + +endmenu source "drivers/md/Kconfig" diff --git a/trunk/arch/um/Kconfig.scsi b/trunk/arch/um/Kconfig.scsi new file mode 100644 index 000000000000..c291c942b1a8 --- /dev/null +++ b/trunk/arch/um/Kconfig.scsi @@ -0,0 +1,58 @@ +comment "SCSI support type (disk, tape, CD-ROM)" + depends on SCSI + +config BLK_DEV_SD + tristate "SCSI disk support" + depends on SCSI + +config SD_EXTRA_DEVS + int "Maximum number of SCSI disks that can be loaded as modules" + depends on BLK_DEV_SD + default "40" + +config CHR_DEV_ST + tristate "SCSI tape support" + depends on SCSI + +config BLK_DEV_SR + tristate "SCSI CD-ROM support" + depends on SCSI + +config BLK_DEV_SR_VENDOR + bool "Enable vendor-specific extensions (for SCSI CDROM)" + depends on BLK_DEV_SR + +config SR_EXTRA_DEVS + int "Maximum number of CDROM devices that can be loaded as modules" + depends on BLK_DEV_SR + default "2" + +config CHR_DEV_SG + tristate "SCSI generic support" + depends on SCSI + +comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs" + depends on SCSI + +#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then +config SCSI_DEBUG_QUEUES + bool "Enable extra checks in new queueing code" + depends on SCSI + +#fi +config SCSI_MULTI_LUN + bool "Probe all LUNs on each SCSI device" + depends on SCSI + +config SCSI_CONSTANTS + bool "Verbose SCSI error reporting (kernel size +=12K)" + depends on SCSI + +config SCSI_LOGGING + bool "SCSI logging facility" + depends on SCSI + +config SCSI_DEBUG + tristate "SCSI debugging host simulator (EXPERIMENTAL)" + depends on SCSI + diff --git a/trunk/arch/um/include/sysdep-i386/archsetjmp.h b/trunk/arch/um/include/sysdep-i386/archsetjmp.h index 0f312085ce1d..11bafab669e9 100644 --- a/trunk/arch/um/include/sysdep-i386/archsetjmp.h +++ b/trunk/arch/um/include/sysdep-i386/archsetjmp.h @@ -1,5 +1,5 @@ /* - * arch/um/include/sysdep-i386/archsetjmp.h + * arch/i386/include/klibc/archsetjmp.h */ #ifndef _KLIBC_ARCHSETJMP_H diff --git a/trunk/arch/um/include/sysdep-x86_64/archsetjmp.h b/trunk/arch/um/include/sysdep-x86_64/archsetjmp.h index 2af8f12ca161..9a5e1a6ec800 100644 --- a/trunk/arch/um/include/sysdep-x86_64/archsetjmp.h +++ b/trunk/arch/um/include/sysdep-x86_64/archsetjmp.h @@ -1,5 +1,5 @@ /* - * arch/um/include/sysdep-x86_64/archsetjmp.h + * arch/x86_64/include/klibc/archsetjmp.h */ #ifndef _KLIBC_ARCHSETJMP_H diff --git a/trunk/arch/um/kernel/skas/process.c b/trunk/arch/um/kernel/skas/process.c index a96ae1a0610e..ef36facd8fe9 100644 --- a/trunk/arch/um/kernel/skas/process.c +++ b/trunk/arch/um/kernel/skas/process.c @@ -178,23 +178,20 @@ int start_uml_skas(void) int external_pid_skas(struct task_struct *task) { - /* FIXME: Need to look up userspace_pid by cpu */ +#warning Need to look up userspace_pid by cpu return(userspace_pid[0]); } int thread_pid_skas(struct task_struct *task) { - /* FIXME: Need to look up userspace_pid by cpu */ +#warning Need to look up userspace_pid by cpu return(userspace_pid[0]); } void kill_off_processes_skas(void) { if(proc_mm) - /* - * FIXME: need to loop over userspace_pids in - * kill_off_processes_skas - */ +#warning need to loop over userspace_pids in kill_off_processes_skas os_kill_ptraced_process(userspace_pid[0], 1); else { struct task_struct *p; diff --git a/trunk/arch/um/os-Linux/process.c b/trunk/arch/um/os-Linux/process.c index 2d9d2ca39299..92a7b59120d6 100644 --- a/trunk/arch/um/os-Linux/process.c +++ b/trunk/arch/um/os-Linux/process.c @@ -239,7 +239,6 @@ int __init can_drop_memory(void) return ok; } -#ifdef UML_CONFIG_MODE_TT void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) { int flags = 0, pages; @@ -261,7 +260,6 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) "errno = %d\n", errno); } } -#endif void init_new_thread_signals(void) { diff --git a/trunk/arch/um/os-Linux/skas/mem.c b/trunk/arch/um/os-Linux/skas/mem.c index 5c8946320799..8e490fff3d47 100644 --- a/trunk/arch/um/os-Linux/skas/mem.c +++ b/trunk/arch/um/os-Linux/skas/mem.c @@ -68,7 +68,7 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) int err, pid = mm_idp->u.pid; if(proc_mm) - /* FIXME: Need to look up userspace_pid by cpu */ +#warning Need to look up userspace_pid by cpu pid = userspace_pid[0]; multi_count++; diff --git a/trunk/arch/um/os-Linux/skas/process.c b/trunk/arch/um/os-Linux/skas/process.c index 6a0e466d01e3..5c088a55396c 100644 --- a/trunk/arch/um/os-Linux/skas/process.c +++ b/trunk/arch/um/os-Linux/skas/process.c @@ -586,7 +586,7 @@ void switch_mm_skas(struct mm_id *mm_idp) { int err; - /* FIXME: need cpu pid in switch_mm_skas */ +#warning need cpu pid in switch_mm_skas if(proc_mm){ err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_idp->u.mm_fd); diff --git a/trunk/arch/v850/kernel/asm-offsets.c b/trunk/arch/v850/kernel/asm-offsets.c index cee5c3142d41..24f291369070 100644 --- a/trunk/arch/v850/kernel/asm-offsets.c +++ b/trunk/arch/v850/kernel/asm-offsets.c @@ -29,7 +29,7 @@ int main (void) DEFINE (TASK_PTRACE, offsetof (struct task_struct, ptrace)); DEFINE (TASK_BLOCKED, offsetof (struct task_struct, blocked)); DEFINE (TASK_THREAD, offsetof (struct task_struct, thread)); - DEFINE (TASK_THREAD_INFO, offsetof (struct task_struct, stack)); + DEFINE (TASK_THREAD_INFO, offsetof (struct task_struct, thread_info)); DEFINE (TASK_MM, offsetof (struct task_struct, mm)); DEFINE (TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm)); DEFINE (TASK_PID, offsetof (struct task_struct, pid)); diff --git a/trunk/arch/v850/kernel/entry.S b/trunk/arch/v850/kernel/entry.S index e4327a8d6bcd..8bc521ca081f 100644 --- a/trunk/arch/v850/kernel/entry.S +++ b/trunk/arch/v850/kernel/entry.S @@ -523,7 +523,7 @@ END(ret_from_trap) /* This the initial entry point for a new child thread, with an appropriate - stack in place that makes it look that the child is in the middle of an + stack in place that makes it look the the child is in the middle of an syscall. This function is actually `returned to' from switch_thread (copy_thread makes ret_from_fork the return address in each new thread's saved context). */ diff --git a/trunk/arch/x86_64/kernel/io_apic.c b/trunk/arch/x86_64/kernel/io_apic.c index d8bfe315471c..4d582589fa89 100644 --- a/trunk/arch/x86_64/kernel/io_apic.c +++ b/trunk/arch/x86_64/kernel/io_apic.c @@ -1413,7 +1413,7 @@ static void ack_apic_level(unsigned int irq) /* * We must acknowledge the irq before we move it or the acknowledge will - * not propagate properly. + * not propogate properly. */ ack_APIC_irq(); diff --git a/trunk/arch/x86_64/kernel/irq.c b/trunk/arch/x86_64/kernel/irq.c index 3eaceac32481..3bc30d2c13d3 100644 --- a/trunk/arch/x86_64/kernel/irq.c +++ b/trunk/arch/x86_64/kernel/irq.c @@ -32,7 +32,7 @@ atomic_t irq_err_count; */ static inline void stack_overflow_check(struct pt_regs *regs) { - u64 curbase = (u64)task_stack_page(current); + u64 curbase = (u64) current->thread_info; static unsigned long warned = -60*HZ; if (regs->rsp >= curbase && regs->rsp <= curbase + THREAD_SIZE && diff --git a/trunk/arch/x86_64/kernel/mce.c b/trunk/arch/x86_64/kernel/mce.c index a14375dd5425..442169640e45 100644 --- a/trunk/arch/x86_64/kernel/mce.c +++ b/trunk/arch/x86_64/kernel/mce.c @@ -720,11 +720,9 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: mce_create_device(cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: mce_remove_device(cpu); break; } diff --git a/trunk/arch/x86_64/kernel/mce_amd.c b/trunk/arch/x86_64/kernel/mce_amd.c index 03356e64f9c8..d0bd5d66e103 100644 --- a/trunk/arch/x86_64/kernel/mce_amd.c +++ b/trunk/arch/x86_64/kernel/mce_amd.c @@ -654,11 +654,9 @@ static int threshold_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: threshold_create_device(cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: threshold_remove_device(cpu); break; default: diff --git a/trunk/arch/x86_64/kernel/traps.c b/trunk/arch/x86_64/kernel/traps.c index d28f01379b9b..8c2ac41187c1 100644 --- a/trunk/arch/x86_64/kernel/traps.c +++ b/trunk/arch/x86_64/kernel/traps.c @@ -778,7 +778,6 @@ asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs) return; if (notify_die(DIE_NMI_POST, "nmi_post", regs, reason, 2, 0) == NOTIFY_STOP) - return; if (!do_nmi_callback(regs,cpu)) unknown_nmi_error(reason, regs); diff --git a/trunk/arch/x86_64/kernel/vsyscall.c b/trunk/arch/x86_64/kernel/vsyscall.c index 51d4c6fa88c8..dc32cef96195 100644 --- a/trunk/arch/x86_64/kernel/vsyscall.c +++ b/trunk/arch/x86_64/kernel/vsyscall.c @@ -327,7 +327,7 @@ static int __cpuinit cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg) { long cpu = (long)arg; - if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN) + if (action == CPU_ONLINE) smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 0, 1); return NOTIFY_DONE; } diff --git a/trunk/arch/xtensa/kernel/asm-offsets.c b/trunk/arch/xtensa/kernel/asm-offsets.c index 698079b3a336..b256cfbef344 100644 --- a/trunk/arch/xtensa/kernel/asm-offsets.c +++ b/trunk/arch/xtensa/kernel/asm-offsets.c @@ -70,7 +70,7 @@ int main(void) DEFINE(TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm)); DEFINE(TASK_PID, offsetof (struct task_struct, pid)); DEFINE(TASK_THREAD, offsetof (struct task_struct, thread)); - DEFINE(TASK_THREAD_INFO, offsetof (struct task_struct, stack)); + DEFINE(TASK_THREAD_INFO, offsetof (struct task_struct, thread_info)); DEFINE(TASK_STRUCT_SIZE, sizeof (struct task_struct)); BLANK(); diff --git a/trunk/arch/xtensa/kernel/pci-dma.c b/trunk/arch/xtensa/kernel/pci-dma.c index f5319d78c876..ca76f071666e 100644 --- a/trunk/arch/xtensa/kernel/pci-dma.c +++ b/trunk/arch/xtensa/kernel/pci-dma.c @@ -1,5 +1,5 @@ /* - * arch/xtensa/kernel/pci-dma.c + * arch/xtensa/pci-dma.c * * DMA coherent memory allocation. * diff --git a/trunk/block/as-iosched.c b/trunk/block/as-iosched.c index 109e91b91ffa..640aa839d63f 100644 --- a/trunk/block/as-iosched.c +++ b/trunk/block/as-iosched.c @@ -1306,7 +1306,7 @@ static void as_exit_queue(elevator_t *e) struct as_data *ad = e->elevator_data; del_timer_sync(&ad->antic_timer); - kblockd_flush_work(&ad->antic_work); + kblockd_flush(); BUG_ON(!list_empty(&ad->fifo_list[REQ_SYNC])); BUG_ON(!list_empty(&ad->fifo_list[REQ_ASYNC])); diff --git a/trunk/block/genhd.c b/trunk/block/genhd.c index 93a2cf654597..b5664440896c 100644 --- a/trunk/block/genhd.c +++ b/trunk/block/genhd.c @@ -213,59 +213,6 @@ struct gendisk *get_gendisk(dev_t dev, int *part) return kobj ? to_disk(kobj) : NULL; } -/* - * print a full list of all partitions - intended for places where the root - * filesystem can't be mounted and thus to give the victim some idea of what - * went wrong - */ -void __init printk_all_partitions(void) -{ - int n; - struct gendisk *sgp; - - mutex_lock(&block_subsys_lock); - /* For each block device... */ - list_for_each_entry(sgp, &block_subsys.list, kobj.entry) { - char buf[BDEVNAME_SIZE]; - /* - * Don't show empty devices or things that have been surpressed - */ - if (get_capacity(sgp) == 0 || - (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) - continue; - - /* - * Note, unlike /proc/partitions, I am showing the numbers in - * hex - the same format as the root= option takes. - */ - printk("%02x%02x %10llu %s", - sgp->major, sgp->first_minor, - (unsigned long long)get_capacity(sgp) >> 1, - disk_name(sgp, 0, buf)); - if (sgp->driverfs_dev != NULL && - sgp->driverfs_dev->driver != NULL) - printk(" driver: %s\n", - sgp->driverfs_dev->driver->name); - else - printk(" (driver?)\n"); - - /* now show the partitions */ - for (n = 0; n < sgp->minors - 1; ++n) { - if (sgp->part[n] == NULL) - continue; - if (sgp->part[n]->nr_sects == 0) - continue; - printk(" %02x%02x %10llu %s\n", - sgp->major, n + 1 + sgp->first_minor, - (unsigned long long)sgp->part[n]->nr_sects >> 1, - disk_name(sgp, n + 1, buf)); - } /* partition subloop */ - } /* Block device loop */ - - mutex_unlock(&block_subsys_lock); - return; -} - #ifdef CONFIG_PROC_FS /* iterator */ static void *part_start(struct seq_file *part, loff_t *pos) diff --git a/trunk/block/ll_rw_blk.c b/trunk/block/ll_rw_blk.c index 17e188973428..d99d402953a3 100644 --- a/trunk/block/ll_rw_blk.c +++ b/trunk/block/ll_rw_blk.c @@ -1704,7 +1704,7 @@ EXPORT_SYMBOL(blk_stop_queue); * on a queue, such as calling the unplug function after a timeout. * A block device may call blk_sync_queue to ensure that any * such activity is cancelled, thus allowing it to release resources - * that the callbacks might use. The caller must already have made sure + * the the callbacks might use. The caller must already have made sure * that its ->make_request_fn will not re-add plugging prior to calling * this function. * @@ -1712,6 +1712,7 @@ EXPORT_SYMBOL(blk_stop_queue); void blk_sync_queue(struct request_queue *q) { del_timer_sync(&q->unplug_timer); + kblockd_flush(); } EXPORT_SYMBOL(blk_sync_queue); @@ -3507,7 +3508,7 @@ static int blk_cpu_notify(struct notifier_block *self, unsigned long action, * If a CPU goes away, splice its entries to the current CPU * and trigger a run of the softirq */ - if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) { + if (action == CPU_DEAD) { int cpu = (unsigned long) hcpu; local_irq_disable(); @@ -3631,11 +3632,11 @@ int kblockd_schedule_work(struct work_struct *work) EXPORT_SYMBOL(kblockd_schedule_work); -void kblockd_flush_work(struct work_struct *work) +void kblockd_flush(void) { - cancel_work_sync(work); + flush_workqueue(kblockd_workqueue); } -EXPORT_SYMBOL(kblockd_flush_work); +EXPORT_SYMBOL(kblockd_flush); int __init blk_dev_init(void) { diff --git a/trunk/crypto/Kconfig b/trunk/crypto/Kconfig index 4ca0ab3448d9..620e14cabdc6 100644 --- a/trunk/crypto/Kconfig +++ b/trunk/crypto/Kconfig @@ -271,7 +271,7 @@ config CRYPTO_SERPENT Keys are allowed to be from 0 to 256 bits in length, in steps of 8 bits. Also includes the 'Tnepres' algorithm, a reversed - variant of Serpent for compatibility with old kerneli.org code. + variant of Serpent for compatibility with old kerneli code. See also: diff --git a/trunk/drivers/Makefile b/trunk/drivers/Makefile index adad2f3d438a..26ca9031ea49 100644 --- a/trunk/drivers/Makefile +++ b/trunk/drivers/Makefile @@ -36,7 +36,6 @@ obj-$(CONFIG_FC4) += fc4/ obj-$(CONFIG_SCSI) += scsi/ obj-$(CONFIG_ATA) += ata/ obj-$(CONFIG_FUSION) += message/ -obj-$(CONFIG_FIREWIRE) += firewire/ obj-$(CONFIG_IEEE1394) += ieee1394/ obj-y += cdrom/ obj-y += auxdisplay/ diff --git a/trunk/drivers/acpi/dispatcher/dsmethod.c b/trunk/drivers/acpi/dispatcher/dsmethod.c index 1cbe61905824..1683e5c5b94c 100644 --- a/trunk/drivers/acpi/dispatcher/dsmethod.c +++ b/trunk/drivers/acpi/dispatcher/dsmethod.c @@ -231,10 +231,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, * Obtain the method mutex if necessary. Do not acquire mutex for a * recursive call. */ - if (!walk_state || - !obj_desc->method.mutex->mutex.owner_thread || - (walk_state->thread != - obj_desc->method.mutex->mutex.owner_thread)) { + if (acpi_os_get_thread_id() != + obj_desc->method.mutex->mutex.owner_thread_id) { /* * Acquire the method mutex. This releases the interpreter if we * block (and reacquires it before it returns) @@ -248,14 +246,14 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, } /* Update the mutex and walk info and save the original sync_level */ + obj_desc->method.mutex->mutex.owner_thread_id = + acpi_os_get_thread_id(); if (walk_state) { obj_desc->method.mutex->mutex. original_sync_level = walk_state->thread->current_sync_level; - obj_desc->method.mutex->mutex.owner_thread = - walk_state->thread; walk_state->thread->current_sync_level = obj_desc->method.sync_level; } else { @@ -569,7 +567,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, acpi_os_release_mutex(method_desc->method.mutex->mutex. os_mutex); - method_desc->method.mutex->mutex.owner_thread = NULL; + method_desc->method.mutex->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED; } } diff --git a/trunk/drivers/acpi/dispatcher/dsopcode.c b/trunk/drivers/acpi/dispatcher/dsopcode.c index fc9da4879cbf..6c6104a7a247 100644 --- a/trunk/drivers/acpi/dispatcher/dsopcode.c +++ b/trunk/drivers/acpi/dispatcher/dsopcode.c @@ -866,7 +866,8 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) && (op->common.parent->common.aml_opcode != AML_VAR_PACKAGE_OP) - && (op->common.parent->common.aml_opcode != AML_NAME_OP))) { + && (op->common.parent->common.aml_opcode != + AML_NAME_OP))) { walk_state->result_obj = obj_desc; } } diff --git a/trunk/drivers/acpi/dispatcher/dsutils.c b/trunk/drivers/acpi/dispatcher/dsutils.c index 71503c036f7c..e4073e05a75c 100644 --- a/trunk/drivers/acpi/dispatcher/dsutils.c +++ b/trunk/drivers/acpi/dispatcher/dsutils.c @@ -556,9 +556,10 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, * indicate this to the interpreter, set the * object to the root */ - obj_desc = ACPI_CAST_PTR(union - acpi_operand_object, - acpi_gbl_root_node); + obj_desc = + ACPI_CAST_PTR(union + acpi_operand_object, + acpi_gbl_root_node); status = AE_OK; } else { /* diff --git a/trunk/drivers/acpi/dispatcher/dswstate.c b/trunk/drivers/acpi/dispatcher/dswstate.c index 5afcdd9c7449..16c8e38b51ef 100644 --- a/trunk/drivers/acpi/dispatcher/dswstate.c +++ b/trunk/drivers/acpi/dispatcher/dswstate.c @@ -630,9 +630,12 @@ struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread) * ******************************************************************************/ -struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object - *origin, union acpi_operand_object - *method_desc, struct acpi_thread_state +struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, + union acpi_parse_object + *origin, + union acpi_operand_object + *method_desc, + struct acpi_thread_state *thread) { struct acpi_walk_state *walk_state; diff --git a/trunk/drivers/acpi/ec.c b/trunk/drivers/acpi/ec.c index 82f496c07675..e08cf98f504f 100644 --- a/trunk/drivers/acpi/ec.c +++ b/trunk/drivers/acpi/ec.c @@ -147,10 +147,9 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event, return 0; } -static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, - unsigned count, int force_poll) +static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count) { - if (unlikely(force_poll) || acpi_ec_mode == EC_POLL) { + if (acpi_ec_mode == EC_POLL) { unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); while (time_before(jiffies, delay)) { if (acpi_ec_check_status(ec, event, 0)) @@ -174,15 +173,14 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, const u8 * wdata, unsigned wdata_len, - u8 * rdata, unsigned rdata_len, - int force_poll) + u8 * rdata, unsigned rdata_len) { int result = 0; unsigned count = atomic_read(&ec->event_count); acpi_ec_write_cmd(ec, command); for (; wdata_len > 0; --wdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count); if (result) { printk(KERN_ERR PREFIX "write_cmd timeout, command = %d\n", command); @@ -193,7 +191,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, } if (!rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count); if (result) { printk(KERN_ERR PREFIX "finish-write timeout, command = %d\n", command); @@ -204,7 +202,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, } for (; rdata_len > 0; --rdata_len) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count, force_poll); + result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count); if (result) { printk(KERN_ERR PREFIX "read timeout, command = %d\n", command); @@ -219,8 +217,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, const u8 * wdata, unsigned wdata_len, - u8 * rdata, unsigned rdata_len, - int force_poll) + u8 * rdata, unsigned rdata_len) { int status; u32 glk; @@ -243,7 +240,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, /* Make sure GPE is enabled before doing transaction */ acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0); + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); if (status) { printk(KERN_DEBUG PREFIX "input buffer is not empty, aborting transaction\n"); @@ -252,8 +249,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, status = acpi_ec_transaction_unlocked(ec, command, wdata, wdata_len, - rdata, rdata_len, - force_poll); + rdata, rdata_len); end: @@ -271,12 +267,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, int acpi_ec_burst_enable(struct acpi_ec *ec) { u8 d; - return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1, 0); + return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1); } int acpi_ec_burst_disable(struct acpi_ec *ec) { - return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0, 0); + return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0); } static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) @@ -285,7 +281,7 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) u8 d; result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ, - &address, 1, &d, 1, 0); + &address, 1, &d, 1); *data = d; return result; } @@ -294,7 +290,7 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) { u8 wdata[2] = { address, data }; return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE, - wdata, 2, NULL, 0, 0); + wdata, 2, NULL, 0); } /* @@ -353,15 +349,13 @@ EXPORT_SYMBOL(ec_write); int ec_transaction(u8 command, const u8 * wdata, unsigned wdata_len, - u8 * rdata, unsigned rdata_len, - int force_poll) + u8 * rdata, unsigned rdata_len) { if (!first_ec) return -ENODEV; return acpi_ec_transaction(first_ec, command, wdata, - wdata_len, rdata, rdata_len, - force_poll); + wdata_len, rdata, rdata_len); } EXPORT_SYMBOL(ec_transaction); @@ -380,7 +374,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) * bit to be cleared (and thus clearing the interrupt source). */ - result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1, 0); + result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1); if (result) return result; @@ -416,7 +410,6 @@ static u32 acpi_ec_gpe_handler(void *data) acpi_status status = AE_OK; u8 value; struct acpi_ec *ec = data; - atomic_inc(&ec->event_count); if (acpi_ec_mode == EC_INTR) { diff --git a/trunk/drivers/acpi/events/evgpe.c b/trunk/drivers/acpi/events/evgpe.c index e22f4a973c0f..635ba449ebc2 100644 --- a/trunk/drivers/acpi/events/evgpe.c +++ b/trunk/drivers/acpi/events/evgpe.c @@ -341,8 +341,9 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, /* A Non-NULL gpe_device means this is a GPE Block Device */ - obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *) - gpe_device); + obj_desc = + acpi_ns_get_attached_object((struct acpi_namespace_node *) + gpe_device); if (!obj_desc || !obj_desc->device.gpe_block) { return (NULL); } diff --git a/trunk/drivers/acpi/events/evgpeblk.c b/trunk/drivers/acpi/events/evgpeblk.c index 902c287b3a4f..ad5bc76edf46 100644 --- a/trunk/drivers/acpi/events/evgpeblk.c +++ b/trunk/drivers/acpi/events/evgpeblk.c @@ -1033,7 +1033,8 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) - && (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) { + && (gpe_event_info-> + flags & ACPI_GPE_TYPE_RUNTIME)) { gpe_enabled_count++; } diff --git a/trunk/drivers/acpi/events/evmisc.c b/trunk/drivers/acpi/events/evmisc.c index 21cb749d0c75..cae786ca8600 100644 --- a/trunk/drivers/acpi/events/evmisc.c +++ b/trunk/drivers/acpi/events/evmisc.c @@ -196,12 +196,15 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, notify_info->notify.value = (u16) notify_value; notify_info->notify.handler_obj = handler_obj; - status = - acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, - notify_info); + acpi_ex_exit_interpreter(); + + acpi_ev_notify_dispatch(notify_info); + + status = acpi_ex_enter_interpreter(); if (ACPI_FAILURE(status)) { - acpi_ut_delete_generic_state(notify_info); + return_ACPI_STATUS(status); } + } if (!handler_obj) { @@ -320,9 +323,8 @@ static u32 acpi_ev_global_lock_handler(void *context) acpi_gbl_global_lock_acquired = TRUE; /* Send a unit to the semaphore */ - if (ACPI_FAILURE - (acpi_os_signal_semaphore - (acpi_gbl_global_lock_semaphore, 1))) { + if (ACPI_FAILURE(acpi_os_signal_semaphore( + acpi_gbl_global_lock_semaphore, 1))) { ACPI_ERROR((AE_INFO, "Could not signal Global Lock semaphore")); } @@ -448,9 +450,7 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) } if (ACPI_FAILURE(status)) { - status = - acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, - timeout); + status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout); } if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); diff --git a/trunk/drivers/acpi/events/evregion.c b/trunk/drivers/acpi/events/evregion.c index e99f0c435a47..96b0e8431748 100644 --- a/trunk/drivers/acpi/events/evregion.c +++ b/trunk/drivers/acpi/events/evregion.c @@ -291,6 +291,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, u32 bit_width, acpi_integer * value) { acpi_status status; + acpi_status status2; acpi_adr_space_handler handler; acpi_adr_space_setup region_setup; union acpi_operand_object *handler_desc; @@ -344,7 +345,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * setup will potentially execute control methods * (e.g., _REG method for this region) */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = region_setup(region_obj, ACPI_REGION_ACTIVATE, handler_desc->address_space.context, @@ -352,7 +353,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, /* Re-enter the interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } /* Check for failure of the Region Setup */ @@ -405,7 +409,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * exit the interpreter because the handler *might* block -- we don't * know what it will do, so we can't hold the lock on the intepreter. */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); } /* Call the handler */ @@ -426,7 +430,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, * We just returned from a non-default handler, we must re-enter the * interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + return_ACPI_STATUS(status2); + } } return_ACPI_STATUS(status); diff --git a/trunk/drivers/acpi/events/evrgnini.c b/trunk/drivers/acpi/events/evrgnini.c index 400d90fca966..a4fa7e6822a3 100644 --- a/trunk/drivers/acpi/events/evrgnini.c +++ b/trunk/drivers/acpi/events/evrgnini.c @@ -228,8 +228,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, /* Install a handler for this PCI root bridge */ - status = - acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); + status = acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); if (ACPI_FAILURE(status)) { if (status == AE_SAME_HANDLER) { /* diff --git a/trunk/drivers/acpi/events/evxface.c b/trunk/drivers/acpi/events/evxface.c index 6d866a01f5f4..a3379bafa676 100644 --- a/trunk/drivers/acpi/events/evxface.c +++ b/trunk/drivers/acpi/events/evxface.c @@ -91,6 +91,7 @@ acpi_status acpi_install_exception_handler(acpi_exception_handler handler) ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) #endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_install_fixed_event_handler @@ -767,9 +768,11 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) return (AE_BAD_PARAMETER); } - /* Must lock interpreter to prevent race conditions */ + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return (status); + } - acpi_ex_enter_interpreter(); status = acpi_ev_acquire_global_lock(timeout); acpi_ex_exit_interpreter(); diff --git a/trunk/drivers/acpi/events/evxfevnt.c b/trunk/drivers/acpi/events/evxfevnt.c index 9cbd3414a574..17065e98807c 100644 --- a/trunk/drivers/acpi/events/evxfevnt.c +++ b/trunk/drivers/acpi/events/evxfevnt.c @@ -472,6 +472,7 @@ acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) } ACPI_EXPORT_SYMBOL(acpi_clear_gpe) + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -567,6 +568,7 @@ acpi_get_gpe_status(acpi_handle gpe_device, ACPI_EXPORT_SYMBOL(acpi_get_gpe_status) #endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_install_gpe_block diff --git a/trunk/drivers/acpi/executer/exconvrt.c b/trunk/drivers/acpi/executer/exconvrt.c index 79f2c0d42c06..d470e8b1f4ea 100644 --- a/trunk/drivers/acpi/executer/exconvrt.c +++ b/trunk/drivers/acpi/executer/exconvrt.c @@ -512,8 +512,9 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, * Create a new string object and string buffer * (-1 because of extra separator included in string_length from above) */ - return_desc = acpi_ut_create_string_object((acpi_size) - (string_length - 1)); + return_desc = + acpi_ut_create_string_object((acpi_size) + (string_length - 1)); if (!return_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } diff --git a/trunk/drivers/acpi/executer/excreate.c b/trunk/drivers/acpi/executer/excreate.c index 6e9a23e47fef..ae97812681a3 100644 --- a/trunk/drivers/acpi/executer/excreate.c +++ b/trunk/drivers/acpi/executer/excreate.c @@ -50,6 +50,7 @@ #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("excreate") + #ifndef ACPI_NO_METHOD_EXECUTION /******************************************************************************* * @@ -582,7 +583,10 @@ acpi_ex_create_method(u8 * aml_start, * Get the sync_level. If method is serialized, a mutex will be * created for this method when it is parsed. */ - if (method_flags & AML_METHOD_SERIALIZED) { + if (acpi_gbl_all_methods_serialized) { + obj_desc->method.sync_level = 0; + obj_desc->method.method_flags |= AML_METHOD_SERIALIZED; + } else if (method_flags & AML_METHOD_SERIALIZED) { /* * ACPI 1.0: sync_level = 0 * ACPI 2.0: sync_level = sync_level in method declaration diff --git a/trunk/drivers/acpi/executer/exdump.c b/trunk/drivers/acpi/executer/exdump.c index 51c9c29987c3..1a73c14df2c5 100644 --- a/trunk/drivers/acpi/executer/exdump.c +++ b/trunk/drivers/acpi/executer/exdump.c @@ -134,7 +134,7 @@ static struct acpi_exdump_info acpi_ex_dump_method[8] = { static struct acpi_exdump_info acpi_ex_dump_mutex[5] = { {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL}, {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"}, - {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread_id), "Owner Thread"}, {ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth), "Acquire Depth"}, {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.os_mutex), "OsMutex"} @@ -451,8 +451,9 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) ACPI_FUNCTION_NAME(ex_dump_operand) - if (!((ACPI_LV_EXEC & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { + if (! + ((ACPI_LV_EXEC & acpi_dbg_level) + && (_COMPONENT & acpi_dbg_layer))) { return; } @@ -843,8 +844,9 @@ void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags) ACPI_FUNCTION_ENTRY(); if (!flags) { - if (!((ACPI_LV_OBJECTS & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { + if (! + ((ACPI_LV_OBJECTS & acpi_dbg_level) + && (_COMPONENT & acpi_dbg_layer))) { return; } } @@ -1009,8 +1011,9 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags) } if (!flags) { - if (!((ACPI_LV_OBJECTS & acpi_dbg_level) - && (_COMPONENT & acpi_dbg_layer))) { + if (! + ((ACPI_LV_OBJECTS & acpi_dbg_level) + && (_COMPONENT & acpi_dbg_layer))) { return_VOID; } } diff --git a/trunk/drivers/acpi/executer/exmutex.c b/trunk/drivers/acpi/executer/exmutex.c index 6748e3ef0997..4eb883bda6ae 100644 --- a/trunk/drivers/acpi/executer/exmutex.c +++ b/trunk/drivers/acpi/executer/exmutex.c @@ -66,10 +66,9 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc, * ******************************************************************************/ -void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc) +void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc, + struct acpi_thread_state *thread) { - struct acpi_thread_state *thread = obj_desc->mutex.owner_thread; - if (!thread) { return; } @@ -174,16 +173,13 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, /* Support for multiple acquires by the owning thread */ - if (obj_desc->mutex.owner_thread) { - if (obj_desc->mutex.owner_thread->thread_id == - walk_state->thread->thread_id) { - /* - * The mutex is already owned by this thread, just increment the - * acquisition depth - */ - obj_desc->mutex.acquisition_depth++; - return_ACPI_STATUS(AE_OK); - } + if (obj_desc->mutex.owner_thread_id == acpi_os_get_thread_id()) { + /* + * The mutex is already owned by this thread, just increment the + * acquisition depth + */ + obj_desc->mutex.acquisition_depth++; + return_ACPI_STATUS(AE_OK); } /* Acquire the mutex, wait if necessary. Special case for Global Lock */ @@ -206,7 +202,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, /* Have the mutex: update mutex and walk info and save the sync_level */ - obj_desc->mutex.owner_thread = walk_state->thread; + obj_desc->mutex.owner_thread_id = acpi_os_get_thread_id(); obj_desc->mutex.acquisition_depth = 1; obj_desc->mutex.original_sync_level = walk_state->thread->current_sync_level; @@ -246,7 +242,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, /* The mutex must have been previously acquired in order to release it */ - if (!obj_desc->mutex.owner_thread) { + if (!obj_desc->mutex.owner_thread_id) { ACPI_ERROR((AE_INFO, "Cannot release Mutex [%4.4s], not acquired", acpi_ut_get_node_name(obj_desc->mutex.node))); @@ -266,15 +262,14 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, * The Mutex is owned, but this thread must be the owner. * Special case for Global Lock, any thread can release */ - if ((obj_desc->mutex.owner_thread->thread_id != + if ((obj_desc->mutex.owner_thread_id != walk_state->thread->thread_id) && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) { ACPI_ERROR((AE_INFO, "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", (unsigned long)walk_state->thread->thread_id, acpi_ut_get_node_name(obj_desc->mutex.node), - (unsigned long)obj_desc->mutex.owner_thread-> - thread_id)); + (unsigned long)obj_desc->mutex.owner_thread_id)); return_ACPI_STATUS(AE_AML_NOT_OWNER); } @@ -301,7 +296,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, /* Unlink the mutex from the owner's list */ - acpi_ex_unlink_mutex(obj_desc); + acpi_ex_unlink_mutex(obj_desc, walk_state->thread); /* Release the mutex, special case for Global Lock */ @@ -313,7 +308,7 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, /* Update the mutex and restore sync_level */ - obj_desc->mutex.owner_thread = NULL; + obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED; walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level; @@ -368,7 +363,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) /* Mark mutex unowned */ - obj_desc->mutex.owner_thread = NULL; + obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED; /* Update Thread sync_level (Last mutex is the important one) */ diff --git a/trunk/drivers/acpi/executer/exnames.c b/trunk/drivers/acpi/executer/exnames.c index 308eae52dc05..1ee4fb1175c6 100644 --- a/trunk/drivers/acpi/executer/exnames.c +++ b/trunk/drivers/acpi/executer/exnames.c @@ -177,7 +177,8 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string) ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Bytes from stream:\n")); - for (index = 0; (index < ACPI_NAME_SIZE) + for (index = 0; + (index < ACPI_NAME_SIZE) && (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) { char_buf[index] = *aml_address++; ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index])); diff --git a/trunk/drivers/acpi/executer/exprep.c b/trunk/drivers/acpi/executer/exprep.c index efe5d4b461a4..a6696621ff1b 100644 --- a/trunk/drivers/acpi/executer/exprep.c +++ b/trunk/drivers/acpi/executer/exprep.c @@ -242,7 +242,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, obj_desc->common_field.bit_length, 0xFFFFFFFF /* Temp until we pass region_length as parameter */ - ); + ); bit_length = byte_alignment * 8; #endif diff --git a/trunk/drivers/acpi/executer/exresop.c b/trunk/drivers/acpi/executer/exresop.c index 09d897b3f6d5..ba761862a599 100644 --- a/trunk/drivers/acpi/executer/exresop.c +++ b/trunk/drivers/acpi/executer/exresop.c @@ -354,7 +354,8 @@ acpi_ex_resolve_operands(u16 opcode, if ((opcode == AML_STORE_OP) && (ACPI_GET_OBJECT_TYPE(*stack_ptr) == ACPI_TYPE_LOCAL_REFERENCE) - && ((*stack_ptr)->reference.opcode == AML_INDEX_OP)) { + && ((*stack_ptr)->reference.opcode == + AML_INDEX_OP)) { goto next_operand; } break; diff --git a/trunk/drivers/acpi/executer/exsystem.c b/trunk/drivers/acpi/executer/exsystem.c index 9460baff3032..b2edf620ba89 100644 --- a/trunk/drivers/acpi/executer/exsystem.c +++ b/trunk/drivers/acpi/executer/exsystem.c @@ -66,6 +66,7 @@ ACPI_MODULE_NAME("exsystem") acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) { acpi_status status; + acpi_status status2; ACPI_FUNCTION_TRACE(ex_system_wait_semaphore); @@ -78,7 +79,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) /* We must wait, so unlock the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = acpi_os_wait_semaphore(semaphore, 1, timeout); @@ -88,7 +89,13 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) /* Reacquire the interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + + /* Report fatal error, could not acquire interpreter */ + + return_ACPI_STATUS(status2); + } } return_ACPI_STATUS(status); @@ -112,6 +119,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) { acpi_status status; + acpi_status status2; ACPI_FUNCTION_TRACE(ex_system_wait_mutex); @@ -124,7 +132,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) /* We must wait, so unlock the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); status = acpi_os_acquire_mutex(mutex, timeout); @@ -134,7 +142,13 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) /* Reacquire the interpreter */ - acpi_ex_reacquire_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status2)) { + + /* Report fatal error, could not acquire interpreter */ + + return_ACPI_STATUS(status2); + } } return_ACPI_STATUS(status); @@ -195,18 +209,20 @@ acpi_status acpi_ex_system_do_stall(u32 how_long) acpi_status acpi_ex_system_do_suspend(acpi_integer how_long) { + acpi_status status; + ACPI_FUNCTION_ENTRY(); /* Since this thread will sleep, we must release the interpreter */ - acpi_ex_relinquish_interpreter(); + acpi_ex_exit_interpreter(); acpi_os_sleep(how_long); /* And now we must get the interpreter again */ - acpi_ex_reacquire_interpreter(); - return (AE_OK); + status = acpi_ex_enter_interpreter(); + return (status); } /******************************************************************************* diff --git a/trunk/drivers/acpi/executer/exutils.c b/trunk/drivers/acpi/executer/exutils.c index 6b0aeccbb69b..aea461f3a48c 100644 --- a/trunk/drivers/acpi/executer/exutils.c +++ b/trunk/drivers/acpi/executer/exutils.c @@ -76,15 +76,14 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base); * * PARAMETERS: None * - * RETURN: None + * RETURN: Status * - * DESCRIPTION: Enter the interpreter execution region. Failure to enter - * the interpreter region is a fatal system error. Used in - * conjunction with exit_interpreter. + * DESCRIPTION: Enter the interpreter execution region. Failure to enter + * the interpreter region is a fatal system error * ******************************************************************************/ -void acpi_ex_enter_interpreter(void) +acpi_status acpi_ex_enter_interpreter(void) { acpi_status status; @@ -92,42 +91,10 @@ void acpi_ex_enter_interpreter(void) status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not acquire AML Interpreter mutex")); + ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex")); } - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_reacquire_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Reacquire the interpreter execution region from within the - * interpreter code. Failure to enter the interpreter region is a - * fatal system error. Used in conjuction with - * relinquish_interpreter - * - ******************************************************************************/ - -void acpi_ex_reacquire_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_reacquire_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter, - * since it was not actually released by acpi_ex_relinquish_interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_enter_interpreter(); - } - - return_VOID; + return_ACPI_STATUS(status); } /******************************************************************************* @@ -138,9 +105,17 @@ void acpi_ex_reacquire_interpreter(void) * * RETURN: None * - * DESCRIPTION: Exit the interpreter execution region. This is the top level - * routine used to exit the interpreter when all processing has - * been completed. + * DESCRIPTION: Exit the interpreter execution region + * + * Cases where the interpreter is unlocked: + * 1) Completion of the execution of a control method + * 2) Method blocked on a Sleep() AML opcode + * 3) Method blocked on an Acquire() AML opcode + * 4) Method blocked on a Wait() AML opcode + * 5) Method blocked to acquire the global lock + * 6) Method blocked to execute a serialized control method that is + * already executing + * 7) About to invoke a user-installed opregion handler * ******************************************************************************/ @@ -152,46 +127,7 @@ void acpi_ex_exit_interpreter(void) status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, - "Could not release AML Interpreter mutex")); - } - - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_relinquish_interpreter - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Exit the interpreter execution region, from within the - * interpreter - before attempting an operation that will possibly - * block the running thread. - * - * Cases where the interpreter is unlocked internally - * 1) Method to be blocked on a Sleep() AML opcode - * 2) Method to be blocked on an Acquire() AML opcode - * 3) Method to be blocked on a Wait() AML opcode - * 4) Method to be blocked to acquire the global lock - * 5) Method to be blocked waiting to execute a serialized control method - * that is currently executing - * 6) About to invoke a user-installed opregion handler - * - ******************************************************************************/ - -void acpi_ex_relinquish_interpreter(void) -{ - ACPI_FUNCTION_TRACE(ex_relinquish_interpreter); - - /* - * If the global serialized flag is set, do not release the interpreter. - * This forces the interpreter to be single threaded. - */ - if (!acpi_gbl_all_methods_serialized) { - acpi_ex_exit_interpreter(); + ACPI_ERROR((AE_INFO, "Could not release interpreter mutex")); } return_VOID; @@ -205,8 +141,8 @@ void acpi_ex_relinquish_interpreter(void) * * RETURN: none * - * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is - * 32-bit, as determined by the revision of the DSDT. + * DESCRIPTION: Truncate a number to 32-bits if the currently executing method + * belongs to a 32-bit ACPI table. * ******************************************************************************/ diff --git a/trunk/drivers/acpi/hardware/hwsleep.c b/trunk/drivers/acpi/hardware/hwsleep.c index 76c525dc590b..c84b1faba28c 100644 --- a/trunk/drivers/acpi/hardware/hwsleep.c +++ b/trunk/drivers/acpi/hardware/hwsleep.c @@ -152,6 +152,7 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) ACPI_EXPORT_SYMBOL(acpi_get_firmware_waking_vector) #endif + /******************************************************************************* * * FUNCTION: acpi_enter_sleep_state_prep diff --git a/trunk/drivers/acpi/namespace/nseval.c b/trunk/drivers/acpi/namespace/nseval.c index 97b2ac57c16b..26fd0dd6953d 100644 --- a/trunk/drivers/acpi/namespace/nseval.c +++ b/trunk/drivers/acpi/namespace/nseval.c @@ -75,7 +75,7 @@ ACPI_MODULE_NAME("nseval") * MUTEX: Locks interpreter * ******************************************************************************/ -acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) +acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) { acpi_status status; @@ -154,7 +154,11 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) * Execute the method via the interpreter. The interpreter is locked * here before calling into the AML parser */ - acpi_ex_enter_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + status = acpi_ps_execute_method(info); acpi_ex_exit_interpreter(); } else { @@ -178,7 +182,10 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) * resolution, we must lock it because we could access an opregion. * The opregion access code assumes that the interpreter is locked. */ - acpi_ex_enter_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } /* Function has a strange interface */ diff --git a/trunk/drivers/acpi/namespace/nsinit.c b/trunk/drivers/acpi/namespace/nsinit.c index 33db2241044e..c4ab615f77fe 100644 --- a/trunk/drivers/acpi/namespace/nsinit.c +++ b/trunk/drivers/acpi/namespace/nsinit.c @@ -214,7 +214,7 @@ acpi_ns_init_one_object(acpi_handle obj_handle, u32 level, void *context, void **return_value) { acpi_object_type type; - acpi_status status = AE_OK; + acpi_status status; struct acpi_init_walk_info *info = (struct acpi_init_walk_info *)context; struct acpi_namespace_node *node = @@ -268,7 +268,10 @@ acpi_ns_init_one_object(acpi_handle obj_handle, /* * Must lock the interpreter before executing AML code */ - acpi_ex_enter_interpreter(); + status = acpi_ex_enter_interpreter(); + if (ACPI_FAILURE(status)) { + return (status); + } /* * Each of these types can contain executable AML code within the diff --git a/trunk/drivers/acpi/namespace/nswalk.c b/trunk/drivers/acpi/namespace/nswalk.c index 280b8357c46c..94eb8f332d94 100644 --- a/trunk/drivers/acpi/namespace/nswalk.c +++ b/trunk/drivers/acpi/namespace/nswalk.c @@ -65,8 +65,10 @@ ACPI_MODULE_NAME("nswalk") * within Scope is returned. * ******************************************************************************/ -struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, struct acpi_namespace_node - *parent_node, struct acpi_namespace_node +struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, + struct acpi_namespace_node + *parent_node, + struct acpi_namespace_node *child_node) { struct acpi_namespace_node *next_node = NULL; diff --git a/trunk/drivers/acpi/namespace/nsxfeval.c b/trunk/drivers/acpi/namespace/nsxfeval.c index be4f2899de74..8904d0fae6a2 100644 --- a/trunk/drivers/acpi/namespace/nsxfeval.c +++ b/trunk/drivers/acpi/namespace/nsxfeval.c @@ -48,6 +48,7 @@ #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsxfeval") + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -72,8 +73,8 @@ ACPI_MODULE_NAME("nsxfeval") acpi_status acpi_evaluate_object_typed(acpi_handle handle, acpi_string pathname, - struct acpi_object_list *external_params, - struct acpi_buffer *return_buffer, + struct acpi_object_list * external_params, + struct acpi_buffer * return_buffer, acpi_object_type return_type) { acpi_status status; @@ -142,6 +143,7 @@ acpi_evaluate_object_typed(acpi_handle handle, ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed) #endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_evaluate_object @@ -168,6 +170,7 @@ acpi_evaluate_object(acpi_handle handle, struct acpi_buffer *return_buffer) { acpi_status status; + acpi_status status2; struct acpi_evaluate_info *info; acpi_size buffer_space_needed; u32 i; @@ -326,12 +329,14 @@ acpi_evaluate_object(acpi_handle handle, * Delete the internal return object. NOTE: Interpreter must be * locked to avoid race condition. */ - acpi_ex_enter_interpreter(); + status2 = acpi_ex_enter_interpreter(); + if (ACPI_SUCCESS(status2)) { - /* Remove one reference on the return object (should delete it) */ + /* Remove one reference on the return object (should delete it) */ - acpi_ut_remove_reference(info->return_object); - acpi_ex_exit_interpreter(); + acpi_ut_remove_reference(info->return_object); + acpi_ex_exit_interpreter(); + } } cleanup: diff --git a/trunk/drivers/acpi/osl.c b/trunk/drivers/acpi/osl.c index b998340e23d4..c2bed56915e1 100644 --- a/trunk/drivers/acpi/osl.c +++ b/trunk/drivers/acpi/osl.c @@ -71,7 +71,6 @@ static unsigned int acpi_irq_irq; static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; static struct workqueue_struct *kacpid_wq; -static struct workqueue_struct *kacpi_notify_wq; static void __init acpi_request_region (struct acpi_generic_address *addr, unsigned int length, char *desc) @@ -138,9 +137,8 @@ acpi_status acpi_os_initialize1(void) return AE_NULL_ENTRY; } kacpid_wq = create_singlethread_workqueue("kacpid"); - kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); BUG_ON(!kacpid_wq); - BUG_ON(!kacpi_notify_wq); + return AE_OK; } @@ -152,7 +150,6 @@ acpi_status acpi_os_terminate(void) } destroy_workqueue(kacpid_wq); - destroy_workqueue(kacpi_notify_wq); return AE_OK; } @@ -604,23 +601,6 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */ } static void acpi_os_execute_deferred(struct work_struct *work) -{ - struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); - if (!dpc) { - printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); - return; - } - - dpc->function(dpc->context); - kfree(dpc); - - /* Yield cpu to notify thread */ - cond_resched(); - - return; -} - -static void acpi_os_execute_notify(struct work_struct *work) { struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); @@ -657,12 +637,14 @@ acpi_status acpi_os_execute(acpi_execute_type type, acpi_status status = AE_OK; struct acpi_os_dpc *dpc; + ACPI_FUNCTION_TRACE("os_queue_for_execution"); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); if (!function) - return AE_BAD_PARAMETER; + return_ACPI_STATUS(AE_BAD_PARAMETER); /* * Allocate/initialize DPC structure. Note that this memory will be @@ -680,21 +662,14 @@ acpi_status acpi_os_execute(acpi_execute_type type, dpc->function = function; dpc->context = context; - if (type == OSL_NOTIFY_HANDLER) { - INIT_WORK(&dpc->work, acpi_os_execute_notify); - if (!queue_work(kacpi_notify_wq, &dpc->work)) { - status = AE_ERROR; - kfree(dpc); - } - } else { - INIT_WORK(&dpc->work, acpi_os_execute_deferred); - if (!queue_work(kacpid_wq, &dpc->work)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + INIT_WORK(&dpc->work, acpi_os_execute_deferred); + if (!queue_work(kacpid_wq, &dpc->work)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Call to queue_work() failed.\n")); - status = AE_ERROR; - kfree(dpc); - } + kfree(dpc); + status = AE_ERROR; } + return_ACPI_STATUS(status); } diff --git a/trunk/drivers/acpi/parser/psopcode.c b/trunk/drivers/acpi/parser/psopcode.c index 9296e86761d7..16d8b6cc3c22 100644 --- a/trunk/drivers/acpi/parser/psopcode.c +++ b/trunk/drivers/acpi/parser/psopcode.c @@ -185,453 +185,459 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { /* Index Name Parser Args Interpreter Args ObjectType Class Type Flags */ /* 00 */ ACPI_OP("Zero", ARGP_ZERO_OP, ARGI_ZERO_OP, ACPI_TYPE_INTEGER, - AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), + AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), /* 01 */ ACPI_OP("One", ARGP_ONE_OP, ARGI_ONE_OP, ACPI_TYPE_INTEGER, - AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), + AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), /* 02 */ ACPI_OP("Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP, - ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_SIMPLE, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_SIMPLE, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 03 */ ACPI_OP("Name", ARGP_NAME_OP, ARGI_NAME_OP, ACPI_TYPE_ANY, - AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 04 */ ACPI_OP("ByteConst", ARGP_BYTE_OP, ARGI_BYTE_OP, - ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_CONSTANT), + ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_CONSTANT), /* 05 */ ACPI_OP("WordConst", ARGP_WORD_OP, ARGI_WORD_OP, - ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_CONSTANT), + ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_CONSTANT), /* 06 */ ACPI_OP("DwordConst", ARGP_DWORD_OP, ARGI_DWORD_OP, - ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_CONSTANT), + ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_CONSTANT), /* 07 */ ACPI_OP("String", ARGP_STRING_OP, ARGI_STRING_OP, - ACPI_TYPE_STRING, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_CONSTANT), + ACPI_TYPE_STRING, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_CONSTANT), /* 08 */ ACPI_OP("Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP, - ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_NO_OBJ, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_NO_OBJ, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 09 */ ACPI_OP("Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP, - ACPI_TYPE_BUFFER, AML_CLASS_CREATE, - AML_TYPE_CREATE_OBJECT, - AML_HAS_ARGS | AML_DEFER | AML_CONSTANT), + ACPI_TYPE_BUFFER, AML_CLASS_CREATE, + AML_TYPE_CREATE_OBJECT, + AML_HAS_ARGS | AML_DEFER | AML_CONSTANT), /* 0A */ ACPI_OP("Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP, - ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, - AML_TYPE_CREATE_OBJECT, - AML_HAS_ARGS | AML_DEFER | AML_CONSTANT), + ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, + AML_TYPE_CREATE_OBJECT, + AML_HAS_ARGS | AML_DEFER | AML_CONSTANT), /* 0B */ ACPI_OP("Method", ARGP_METHOD_OP, ARGI_METHOD_OP, - ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_COMPLEX, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED | AML_DEFER), + ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_COMPLEX, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED | AML_DEFER), /* 0C */ ACPI_OP("Local0", ARGP_LOCAL0, ARGI_LOCAL0, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 0D */ ACPI_OP("Local1", ARGP_LOCAL1, ARGI_LOCAL1, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 0E */ ACPI_OP("Local2", ARGP_LOCAL2, ARGI_LOCAL2, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 0F */ ACPI_OP("Local3", ARGP_LOCAL3, ARGI_LOCAL3, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 10 */ ACPI_OP("Local4", ARGP_LOCAL4, ARGI_LOCAL4, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 11 */ ACPI_OP("Local5", ARGP_LOCAL5, ARGI_LOCAL5, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 12 */ ACPI_OP("Local6", ARGP_LOCAL6, ARGI_LOCAL6, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 13 */ ACPI_OP("Local7", ARGP_LOCAL7, ARGI_LOCAL7, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LOCAL_VARIABLE, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LOCAL_VARIABLE, 0), /* 14 */ ACPI_OP("Arg0", ARGP_ARG0, ARGI_ARG0, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), /* 15 */ ACPI_OP("Arg1", ARGP_ARG1, ARGI_ARG1, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), /* 16 */ ACPI_OP("Arg2", ARGP_ARG2, ARGI_ARG2, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), /* 17 */ ACPI_OP("Arg3", ARGP_ARG3, ARGI_ARG3, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), /* 18 */ ACPI_OP("Arg4", ARGP_ARG4, ARGI_ARG4, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), /* 19 */ ACPI_OP("Arg5", ARGP_ARG5, ARGI_ARG5, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), /* 1A */ ACPI_OP("Arg6", ARGP_ARG6, ARGI_ARG6, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_METHOD_ARGUMENT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_METHOD_ARGUMENT, 0), /* 1B */ ACPI_OP("Store", ARGP_STORE_OP, ARGI_STORE_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R), /* 1C */ ACPI_OP("RefOf", ARGP_REF_OF_OP, ARGI_REF_OF_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, - AML_FLAGS_EXEC_1A_0T_1R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, + AML_FLAGS_EXEC_1A_0T_1R), /* 1D */ ACPI_OP("Add", ARGP_ADD_OP, ARGI_ADD_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 1E */ ACPI_OP("Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), /* 1F */ ACPI_OP("Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 20 */ ACPI_OP("Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_1R, - AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_1R, + AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), /* 21 */ ACPI_OP("Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_1R, - AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_1R, + AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), /* 22 */ ACPI_OP("Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 23 */ ACPI_OP("Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_2T_1R, - AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_2T_1R, + AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT), /* 24 */ ACPI_OP("ShiftLeft", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 25 */ ACPI_OP("ShiftRight", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 26 */ ACPI_OP("And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 27 */ ACPI_OP("NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 28 */ ACPI_OP("Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 29 */ ACPI_OP("NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 2A */ ACPI_OP("XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT), /* 2B */ ACPI_OP("Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 2C */ ACPI_OP("FindSetLeftBit", ARGP_FIND_SET_LEFT_BIT_OP, - ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY, + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 2D */ ACPI_OP("FindSetRightBit", ARGP_FIND_SET_RIGHT_BIT_OP, - ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY, + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 2E */ ACPI_OP("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R), /* 2F */ ACPI_OP("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R), /* 30 */ ACPI_OP("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_1R, - AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_1R, + AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE), /* 31 */ ACPI_OP("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R), /* 32 */ ACPI_OP("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, - AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, + AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT), /* 33 */ ACPI_OP("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP, - ARGI_CREATE_DWORD_FIELD_OP, - ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, - AML_TYPE_CREATE_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | - AML_DEFER | AML_CREATE), + ARGI_CREATE_DWORD_FIELD_OP, + ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, + AML_TYPE_CREATE_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | + AML_DEFER | AML_CREATE), /* 34 */ ACPI_OP("CreateWordField", ARGP_CREATE_WORD_FIELD_OP, - ARGI_CREATE_WORD_FIELD_OP, - ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, - AML_TYPE_CREATE_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | - AML_DEFER | AML_CREATE), + ARGI_CREATE_WORD_FIELD_OP, + ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, + AML_TYPE_CREATE_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | + AML_DEFER | AML_CREATE), /* 35 */ ACPI_OP("CreateByteField", ARGP_CREATE_BYTE_FIELD_OP, - ARGI_CREATE_BYTE_FIELD_OP, - ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, - AML_TYPE_CREATE_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | - AML_DEFER | AML_CREATE), + ARGI_CREATE_BYTE_FIELD_OP, + ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, + AML_TYPE_CREATE_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | + AML_DEFER | AML_CREATE), /* 36 */ ACPI_OP("CreateBitField", ARGP_CREATE_BIT_FIELD_OP, - ARGI_CREATE_BIT_FIELD_OP, - ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, - AML_TYPE_CREATE_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | - AML_DEFER | AML_CREATE), + ARGI_CREATE_BIT_FIELD_OP, + ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, + AML_TYPE_CREATE_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | + AML_DEFER | AML_CREATE), /* 37 */ ACPI_OP("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_1R, - AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_1R, + AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE), /* 38 */ ACPI_OP("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, + AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | + AML_CONSTANT), /* 39 */ ACPI_OP("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, + AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | + AML_CONSTANT), /* 3A */ ACPI_OP("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, - AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, + AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT), /* 3B */ ACPI_OP("LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_0T_1R, + AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), /* 3C */ ACPI_OP("LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_0T_1R, + AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), /* 3D */ ACPI_OP("LLess", ARGP_LLESS_OP, ARGI_LLESS_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, + AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT), /* 3E */ ACPI_OP("If", ARGP_IF_OP, ARGI_IF_OP, ACPI_TYPE_ANY, - AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), + AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), /* 3F */ ACPI_OP("Else", ARGP_ELSE_OP, ARGI_ELSE_OP, ACPI_TYPE_ANY, - AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), + AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), /* 40 */ ACPI_OP("While", ARGP_WHILE_OP, ARGI_WHILE_OP, ACPI_TYPE_ANY, - AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), + AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS), /* 41 */ ACPI_OP("Noop", ARGP_NOOP_OP, ARGI_NOOP_OP, ACPI_TYPE_ANY, - AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), + AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), /* 42 */ ACPI_OP("Return", ARGP_RETURN_OP, ARGI_RETURN_OP, - ACPI_TYPE_ANY, AML_CLASS_CONTROL, - AML_TYPE_CONTROL, AML_HAS_ARGS), + ACPI_TYPE_ANY, AML_CLASS_CONTROL, + AML_TYPE_CONTROL, AML_HAS_ARGS), /* 43 */ ACPI_OP("Break", ARGP_BREAK_OP, ARGI_BREAK_OP, ACPI_TYPE_ANY, - AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), + AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), /* 44 */ ACPI_OP("BreakPoint", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP, - ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), + ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), /* 45 */ ACPI_OP("Ones", ARGP_ONES_OP, ARGI_ONES_OP, ACPI_TYPE_INTEGER, - AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), + AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT), /* Prefixed opcodes (Two-byte opcodes with a prefix op) */ /* 46 */ ACPI_OP("Mutex", ARGP_MUTEX_OP, ARGI_MUTEX_OP, ACPI_TYPE_MUTEX, - AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 47 */ ACPI_OP("Event", ARGP_EVENT_OP, ARGI_EVENT_OP, ACPI_TYPE_EVENT, - AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, - AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, + AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), /* 48 */ ACPI_OP("CondRefOf", ARGP_COND_REF_OF_OP, ARGI_COND_REF_OF_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), /* 49 */ ACPI_OP("CreateField", ARGP_CREATE_FIELD_OP, - ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, - AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | - AML_DEFER | AML_FIELD | AML_CREATE), + ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, + AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | + AML_DEFER | AML_FIELD | AML_CREATE), /* 4A */ ACPI_OP("Load", ARGP_LOAD_OP, ARGI_LOAD_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R, - AML_FLAGS_EXEC_1A_1T_0R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R, + AML_FLAGS_EXEC_1A_1T_0R), /* 4B */ ACPI_OP("Stall", ARGP_STALL_OP, ARGI_STALL_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, - AML_FLAGS_EXEC_1A_0T_0R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, + AML_FLAGS_EXEC_1A_0T_0R), /* 4C */ ACPI_OP("Sleep", ARGP_SLEEP_OP, ARGI_SLEEP_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, - AML_FLAGS_EXEC_1A_0T_0R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, + AML_FLAGS_EXEC_1A_0T_0R), /* 4D */ ACPI_OP("Acquire", ARGP_ACQUIRE_OP, ARGI_ACQUIRE_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R), /* 4E */ ACPI_OP("Signal", ARGP_SIGNAL_OP, ARGI_SIGNAL_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), /* 4F */ ACPI_OP("Wait", ARGP_WAIT_OP, ARGI_WAIT_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, - AML_FLAGS_EXEC_2A_0T_1R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, + AML_FLAGS_EXEC_2A_0T_1R), /* 50 */ ACPI_OP("Reset", ARGP_RESET_OP, ARGI_RESET_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, - AML_FLAGS_EXEC_1A_0T_0R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R, + AML_FLAGS_EXEC_1A_0T_0R), /* 51 */ ACPI_OP("Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), /* 52 */ ACPI_OP("FromBCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 53 */ ACPI_OP("ToBCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 54 */ ACPI_OP("Unload", ARGP_UNLOAD_OP, ARGI_UNLOAD_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R), /* 55 */ ACPI_OP("Revision", ARGP_REVISION_OP, ARGI_REVISION_OP, - ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, - AML_TYPE_CONSTANT, 0), + ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, + AML_TYPE_CONSTANT, 0), /* 56 */ ACPI_OP("Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_CONSTANT, 0), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_CONSTANT, 0), /* 57 */ ACPI_OP("Fatal", ARGP_FATAL_OP, ARGI_FATAL_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R, - AML_FLAGS_EXEC_3A_0T_0R), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R, + AML_FLAGS_EXEC_3A_0T_0R), /* 58 */ ACPI_OP("OperationRegion", ARGP_REGION_OP, ARGI_REGION_OP, - ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_COMPLEX, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED | AML_DEFER), + ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_COMPLEX, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED | AML_DEFER), /* 59 */ ACPI_OP("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY, - AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_FIELD), /* 5A */ ACPI_OP("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP, - ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_NO_OBJ, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_NO_OBJ, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 5B */ ACPI_OP("Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP, - ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_SIMPLE, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_SIMPLE, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 5C */ ACPI_OP("PowerResource", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP, - ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_SIMPLE, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_SIMPLE, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 5D */ ACPI_OP("ThermalZone", ARGP_THERMAL_ZONE_OP, - ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL, - AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL, + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 5E */ ACPI_OP("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP, - ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), + ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_FIELD), /* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP, - ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), + ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_FIELD), /* Internal opcodes that map to invalid AML opcodes */ /* 60 */ ACPI_OP("LNotEqual", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP, - ACPI_TYPE_ANY, AML_CLASS_INTERNAL, - AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_INTERNAL, + AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), /* 61 */ ACPI_OP("LLessEqual", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP, - ACPI_TYPE_ANY, AML_CLASS_INTERNAL, - AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_INTERNAL, + AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT), /* 62 */ ACPI_OP("LGreaterEqual", ARGP_LGREATEREQUAL_OP, - ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY, - AML_CLASS_INTERNAL, AML_TYPE_BOGUS, - AML_HAS_ARGS | AML_CONSTANT), + ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY, + AML_CLASS_INTERNAL, AML_TYPE_BOGUS, + AML_HAS_ARGS | AML_CONSTANT), /* 63 */ ACPI_OP("-NamePath-", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP, - ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE), + ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE), /* 64 */ ACPI_OP("-MethodCall-", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP, - ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL, - AML_TYPE_METHOD_CALL, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE), + ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL, + AML_TYPE_METHOD_CALL, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE), /* 65 */ ACPI_OP("-ByteList-", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP, - ACPI_TYPE_ANY, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, 0), + ACPI_TYPE_ANY, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, 0), /* 66 */ ACPI_OP("-ReservedField-", ARGP_RESERVEDFIELD_OP, - ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY, - AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), + ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY, + AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), /* 67 */ ACPI_OP("-NamedField-", ARGP_NAMEDFIELD_OP, ARGI_NAMEDFIELD_OP, - ACPI_TYPE_ANY, AML_CLASS_INTERNAL, - AML_TYPE_BOGUS, - AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), + ACPI_TYPE_ANY, AML_CLASS_INTERNAL, + AML_TYPE_BOGUS, + AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), /* 68 */ ACPI_OP("-AccessField-", ARGP_ACCESSFIELD_OP, - ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY, - AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), + ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY, + AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), /* 69 */ ACPI_OP("-StaticString", ARGP_STATICSTRING_OP, - ARGI_STATICSTRING_OP, ACPI_TYPE_ANY, - AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), + ARGI_STATICSTRING_OP, ACPI_TYPE_ANY, + AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0), /* 6A */ ACPI_OP("-Return Value-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, - AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN, - AML_HAS_ARGS | AML_HAS_RETVAL), + AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN, + AML_HAS_ARGS | AML_HAS_RETVAL), /* 6B */ ACPI_OP("-UNKNOWN_OP-", ARG_NONE, ARG_NONE, ACPI_TYPE_INVALID, - AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS), + AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS), /* 6C */ ACPI_OP("-ASCII_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, - AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS), + AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS), /* 6D */ ACPI_OP("-PREFIX_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY, - AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS), + AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS), /* ACPI 2.0 opcodes */ /* 6E */ ACPI_OP("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP, - ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, - AML_TYPE_LITERAL, AML_CONSTANT), + ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT, + AML_TYPE_LITERAL, AML_CONSTANT), /* 6F */ ACPI_OP("Package", /* Var */ ARGP_VAR_PACKAGE_OP, ARGI_VAR_PACKAGE_OP, ACPI_TYPE_PACKAGE, AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT, AML_HAS_ARGS | AML_DEFER), /* 70 */ ACPI_OP("ConcatenateResTemplate", ARGP_CONCAT_RES_OP, - ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), + ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY, + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), /* 71 */ ACPI_OP("Mod", ARGP_MOD_OP, ARGI_MOD_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), /* 72 */ ACPI_OP("CreateQWordField", ARGP_CREATE_QWORD_FIELD_OP, - ARGI_CREATE_QWORD_FIELD_OP, - ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, - AML_TYPE_CREATE_FIELD, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | - AML_DEFER | AML_CREATE), + ARGI_CREATE_QWORD_FIELD_OP, + ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, + AML_TYPE_CREATE_FIELD, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | + AML_DEFER | AML_CREATE), /* 73 */ ACPI_OP("ToBuffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 74 */ ACPI_OP("ToDecimalString", ARGP_TO_DEC_STR_OP, - ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY, + AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 75 */ ACPI_OP("ToHexString", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 76 */ ACPI_OP("ToInteger", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_1T_1R, - AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_1T_1R, + AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT), /* 77 */ ACPI_OP("ToString", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_2A_1T_1R, - AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_2A_1T_1R, + AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT), /* 78 */ ACPI_OP("CopyObject", ARGP_COPY_OP, ARGI_COPY_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R), /* 79 */ ACPI_OP("Mid", ARGP_MID_OP, ARGI_MID_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R, - AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT), + AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R, + AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT), /* 7A */ ACPI_OP("Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP, - ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), + ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0), /* 7B */ ACPI_OP("LoadTable", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP, - ACPI_TYPE_ANY, AML_CLASS_EXECUTE, - AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R), + ACPI_TYPE_ANY, AML_CLASS_EXECUTE, + AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R), /* 7C */ ACPI_OP("DataTableRegion", ARGP_DATA_REGION_OP, - ARGI_DATA_REGION_OP, ACPI_TYPE_REGION, - AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | - AML_NSNODE | AML_NAMED), + ARGI_DATA_REGION_OP, ACPI_TYPE_REGION, + AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE | AML_NAMED), /* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP, - ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, - AML_TYPE_NAMED_NO_OBJ, - AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE), + ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, + AML_TYPE_NAMED_NO_OBJ, + AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | + AML_NSNODE), /* ACPI 3.0 opcodes */ /* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY, - AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R, - AML_FLAGS_EXEC_0A_0T_1R) + AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R, + AML_FLAGS_EXEC_0A_0T_1R) /*! [End] no source code translation !*/ }; diff --git a/trunk/drivers/acpi/resources/rscalc.c b/trunk/drivers/acpi/resources/rscalc.c index 0dd2ce8a3475..8c6d3fdec38a 100644 --- a/trunk/drivers/acpi/resources/rscalc.c +++ b/trunk/drivers/acpi/resources/rscalc.c @@ -567,8 +567,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, (*sub_object_list)->string. length + 1); } else { - temp_size_needed += - acpi_ns_get_pathname_length((*sub_object_list)->reference.node); + temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node); } } else { /* diff --git a/trunk/drivers/acpi/resources/rscreate.c b/trunk/drivers/acpi/resources/rscreate.c index 50da494c3ee2..cc48ab05676c 100644 --- a/trunk/drivers/acpi/resources/rscreate.c +++ b/trunk/drivers/acpi/resources/rscreate.c @@ -267,19 +267,16 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, * If BIOS erroneously reversed the _PRT source_name and source_index, * then reverse them back. */ - if (ACPI_GET_OBJECT_TYPE(sub_object_list[3]) != - ACPI_TYPE_INTEGER) { + if (ACPI_GET_OBJECT_TYPE (sub_object_list[3]) != ACPI_TYPE_INTEGER) { if (acpi_gbl_enable_interpreter_slack) { source_name_index = 3; source_index_index = 2; - printk(KERN_WARNING - "ACPI: Handling Garbled _PRT entry\n"); + printk(KERN_WARNING "ACPI: Handling Garbled _PRT entry\n"); } else { ACPI_ERROR((AE_INFO, - "(PRT[%X].source_index) Need Integer, found %s", - index, - acpi_ut_get_object_type_name - (sub_object_list[3]))); + "(PRT[%X].source_index) Need Integer, found %s", + index, + acpi_ut_get_object_type_name(sub_object_list[3]))); return_ACPI_STATUS(AE_BAD_DATA); } } diff --git a/trunk/drivers/acpi/resources/rsdump.c b/trunk/drivers/acpi/resources/rsdump.c index 46da116a4030..de20a5d6decf 100644 --- a/trunk/drivers/acpi/resources/rsdump.c +++ b/trunk/drivers/acpi/resources/rsdump.c @@ -46,6 +46,7 @@ #define _COMPONENT ACPI_RESOURCES ACPI_MODULE_NAME("rsdump") + #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) /* Local prototypes */ static void acpi_rs_out_string(char *title, char *value); @@ -488,9 +489,10 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) /* * Optional resource_source for Address resources */ - acpi_rs_dump_resource_source(ACPI_CAST_PTR(struct - acpi_resource_source, - target)); + acpi_rs_dump_resource_source(ACPI_CAST_PTR + (struct + acpi_resource_source, + target)); break; default: diff --git a/trunk/drivers/acpi/resources/rsinfo.c b/trunk/drivers/acpi/resources/rsinfo.c index 2c2adb6292c1..7e3c335ab320 100644 --- a/trunk/drivers/acpi/resources/rsinfo.c +++ b/trunk/drivers/acpi/resources/rsinfo.c @@ -142,7 +142,7 @@ struct acpi_rsdump_info *acpi_gbl_dump_resource_dispatch[] = { }; #endif -#endif /* ACPI_FUTURE_USAGE */ +#endif /* ACPI_FUTURE_USAGE */ /* * Base sizes for external AML resource descriptors, indexed by internal type. * Includes size of the descriptor header (1 byte for small descriptors, diff --git a/trunk/drivers/acpi/resources/rslist.c b/trunk/drivers/acpi/resources/rslist.c index ca21e4660c79..a92755c8877d 100644 --- a/trunk/drivers/acpi/resources/rslist.c +++ b/trunk/drivers/acpi/resources/rslist.c @@ -153,9 +153,10 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, /* Perform the conversion */ - status = acpi_rs_convert_resource_to_aml(resource, ACPI_CAST_PTR(union - aml_resource, - aml), + status = acpi_rs_convert_resource_to_aml(resource, + ACPI_CAST_PTR(union + aml_resource, + aml), acpi_gbl_set_resource_dispatch [resource->type]); if (ACPI_FAILURE(status)) { diff --git a/trunk/drivers/acpi/resources/rsmisc.c b/trunk/drivers/acpi/resources/rsmisc.c index c7081afa893a..3b63b561b94e 100644 --- a/trunk/drivers/acpi/resources/rsmisc.c +++ b/trunk/drivers/acpi/resources/rsmisc.c @@ -46,6 +46,7 @@ #define _COMPONENT ACPI_RESOURCES ACPI_MODULE_NAME("rsmisc") + #define INIT_RESOURCE_TYPE(i) i->resource_offset #define INIT_RESOURCE_LENGTH(i) i->aml_offset #define INIT_TABLE_LENGTH(i) i->value @@ -428,7 +429,8 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, * Optional resource_source (Index and String) */ aml_length = - acpi_rs_set_resource_source(aml, (acpi_rs_length) + acpi_rs_set_resource_source(aml, + (acpi_rs_length) aml_length, source); acpi_rs_set_resource_length(aml_length, aml); break; diff --git a/trunk/drivers/acpi/resources/rsutils.c b/trunk/drivers/acpi/resources/rsutils.c index 11c0bd7b9cfd..2442a8f8df57 100644 --- a/trunk/drivers/acpi/resources/rsutils.c +++ b/trunk/drivers/acpi/resources/rsutils.c @@ -353,8 +353,10 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length, * * Zero the entire area of the buffer. */ - total_length = (u32) - ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + 1; + total_length = + (u32) + ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + + 1; total_length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(total_length); ACPI_MEMSET(resource_source->string_ptr, 0, total_length); diff --git a/trunk/drivers/acpi/resources/rsxface.c b/trunk/drivers/acpi/resources/rsxface.c index f63813a358c5..991f8901498c 100644 --- a/trunk/drivers/acpi/resources/rsxface.c +++ b/trunk/drivers/acpi/resources/rsxface.c @@ -217,6 +217,7 @@ acpi_get_current_resources(acpi_handle device_handle, } ACPI_EXPORT_SYMBOL(acpi_get_current_resources) + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -260,6 +261,7 @@ acpi_get_possible_resources(acpi_handle device_handle, ACPI_EXPORT_SYMBOL(acpi_get_possible_resources) #endif /* ACPI_FUTURE_USAGE */ + /******************************************************************************* * * FUNCTION: acpi_set_current_resources @@ -494,6 +496,7 @@ ACPI_EXPORT_SYMBOL(acpi_rs_match_vendor_resource) * each resource in the list. * ******************************************************************************/ + acpi_status acpi_walk_resources(acpi_handle device_handle, char *name, diff --git a/trunk/drivers/acpi/sleep/main.c b/trunk/drivers/acpi/sleep/main.c index bc7e16ec8393..f8c63410bcbf 100644 --- a/trunk/drivers/acpi/sleep/main.c +++ b/trunk/drivers/acpi/sleep/main.c @@ -29,6 +29,7 @@ static u32 acpi_suspend_states[] = { [PM_SUSPEND_ON] = ACPI_STATE_S0, [PM_SUSPEND_STANDBY] = ACPI_STATE_S1, [PM_SUSPEND_MEM] = ACPI_STATE_S3, + [PM_SUSPEND_DISK] = ACPI_STATE_S4, [PM_SUSPEND_MAX] = ACPI_STATE_S5 }; @@ -93,6 +94,14 @@ static int acpi_pm_enter(suspend_state_t pm_state) do_suspend_lowlevel(); break; + case PM_SUSPEND_DISK: + if (acpi_pm_ops.pm_disk_mode == PM_DISK_PLATFORM) + status = acpi_enter_sleep_state(acpi_state); + break; + case PM_SUSPEND_MAX: + acpi_power_off(); + break; + default: return -EINVAL; } @@ -148,13 +157,12 @@ int acpi_suspend(u32 acpi_state) suspend_state_t states[] = { [1] = PM_SUSPEND_STANDBY, [3] = PM_SUSPEND_MEM, + [4] = PM_SUSPEND_DISK, [5] = PM_SUSPEND_MAX }; if (acpi_state < 6 && states[acpi_state]) return pm_suspend(states[acpi_state]); - if (acpi_state == 4) - return hibernate(); return -EINVAL; } @@ -181,49 +189,6 @@ static struct pm_ops acpi_pm_ops = { .finish = acpi_pm_finish, }; -#ifdef CONFIG_SOFTWARE_SUSPEND -static int acpi_hibernation_prepare(void) -{ - return acpi_sleep_prepare(ACPI_STATE_S4); -} - -static int acpi_hibernation_enter(void) -{ - acpi_status status = AE_OK; - unsigned long flags = 0; - - ACPI_FLUSH_CPU_CACHE(); - - local_irq_save(flags); - acpi_enable_wakeup_device(ACPI_STATE_S4); - /* This shouldn't return. If it returns, we have a problem */ - status = acpi_enter_sleep_state(ACPI_STATE_S4); - local_irq_restore(flags); - - return ACPI_SUCCESS(status) ? 0 : -EFAULT; -} - -static void acpi_hibernation_finish(void) -{ - acpi_leave_sleep_state(ACPI_STATE_S4); - acpi_disable_wakeup_device(ACPI_STATE_S4); - - /* reset firmware waking vector */ - acpi_set_firmware_waking_vector((acpi_physical_address) 0); - - if (init_8259A_after_S1) { - printk("Broken toshiba laptop -> kicking interrupts\n"); - init_8259A(0); - } -} - -static struct hibernation_ops acpi_hibernation_ops = { - .prepare = acpi_hibernation_prepare, - .enter = acpi_hibernation_enter, - .finish = acpi_hibernation_finish, -}; -#endif /* CONFIG_SOFTWARE_SUSPEND */ - /* * Toshiba fails to preserve interrupts over S1, reinitialization * of 8259 is needed after S1 resume. @@ -262,17 +227,14 @@ int __init acpi_sleep_init(void) sleep_states[i] = 1; printk(" S%d", i); } + if (i == ACPI_STATE_S4) { + if (sleep_states[i]) + acpi_pm_ops.pm_disk_mode = PM_DISK_PLATFORM; + } } printk(")\n"); pm_set_ops(&acpi_pm_ops); - -#ifdef CONFIG_SOFTWARE_SUSPEND - if (sleep_states[ACPI_STATE_S4]) - hibernation_set_ops(&acpi_hibernation_ops); -#else - sleep_states[ACPI_STATE_S4] = 0; -#endif - return 0; } + diff --git a/trunk/drivers/acpi/sleep/proc.c b/trunk/drivers/acpi/sleep/proc.c index 61f1822cc350..5a76e5be61d5 100644 --- a/trunk/drivers/acpi/sleep/proc.c +++ b/trunk/drivers/acpi/sleep/proc.c @@ -60,7 +60,7 @@ acpi_system_write_sleep(struct file *file, state = simple_strtoul(str, NULL, 0); #ifdef CONFIG_SOFTWARE_SUSPEND if (state == 4) { - error = hibernate(); + error = pm_suspend(PM_SUSPEND_DISK); goto Done; } #endif @@ -349,7 +349,8 @@ acpi_system_write_alarm(struct file *file, end: return_VALUE(result ? result : count); } -#endif /* HAVE_ACPI_LEGACY_ALARM */ +#endif /* HAVE_ACPI_LEGACY_ALARM */ + extern struct list_head acpi_wakeup_device_list; extern spinlock_t acpi_device_lock; @@ -379,8 +380,8 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) dev->wakeup.state.enabled ? "enabled" : "disabled"); if (ldev) seq_printf(seq, "%s:%s", - ldev->bus ? ldev->bus->name : "no-bus", - ldev->bus_id); + ldev->bus ? ldev->bus->name : "no-bus", + ldev->bus_id); seq_printf(seq, "\n"); put_device(ldev); @@ -489,7 +490,7 @@ static u32 rtc_handler(void *context) return ACPI_INTERRUPT_HANDLED; } -#endif /* HAVE_ACPI_LEGACY_ALARM */ +#endif /* HAVE_ACPI_LEGACY_ALARM */ static int __init acpi_sleep_proc_init(void) { @@ -516,7 +517,7 @@ static int __init acpi_sleep_proc_init(void) entry->proc_fops = &acpi_system_alarm_fops; acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); -#endif /* HAVE_ACPI_LEGACY_ALARM */ +#endif /* HAVE_ACPI_LEGACY_ALARM */ /* 'wakeup device' [R/W] */ entry = diff --git a/trunk/drivers/acpi/tables/tbfadt.c b/trunk/drivers/acpi/tables/tbfadt.c index 1285e91474fb..1db833eb2417 100644 --- a/trunk/drivers/acpi/tables/tbfadt.c +++ b/trunk/drivers/acpi/tables/tbfadt.c @@ -334,8 +334,7 @@ static void acpi_tb_convert_fadt(void) (acpi_gbl_FADT.xpm1a_event_block.address + pm1_register_length)); /* Don't forget to copy space_id of the GAS */ - acpi_gbl_xpm1a_enable.space_id = - acpi_gbl_FADT.xpm1a_event_block.space_id; + acpi_gbl_xpm1a_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id; /* The PM1B register block is optional, ignore if not present */ @@ -345,8 +344,7 @@ static void acpi_tb_convert_fadt(void) (acpi_gbl_FADT.xpm1b_event_block. address + pm1_register_length)); /* Don't forget to copy space_id of the GAS */ - acpi_gbl_xpm1b_enable.space_id = - acpi_gbl_FADT.xpm1a_event_block.space_id; + acpi_gbl_xpm1b_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id; } diff --git a/trunk/drivers/acpi/tables/tbxface.c b/trunk/drivers/acpi/tables/tbxface.c index 5b302c4e293f..417ef5fa7666 100644 --- a/trunk/drivers/acpi/tables/tbxface.c +++ b/trunk/drivers/acpi/tables/tbxface.c @@ -201,7 +201,6 @@ acpi_status acpi_reallocate_root_table(void) return_ACPI_STATUS(AE_OK); } - /******************************************************************************* * * FUNCTION: acpi_load_table @@ -263,7 +262,7 @@ ACPI_EXPORT_SYMBOL(acpi_load_table) acpi_status acpi_get_table_header(char *signature, acpi_native_uint instance, - struct acpi_table_header * out_table_header) + struct acpi_table_header *out_table_header) { acpi_native_uint i; acpi_native_uint j; @@ -322,6 +321,7 @@ acpi_get_table_header(char *signature, ACPI_EXPORT_SYMBOL(acpi_get_table_header) + /****************************************************************************** * * FUNCTION: acpi_unload_table_id @@ -346,11 +346,11 @@ acpi_status acpi_unload_table_id(acpi_owner_id id) continue; } /* - * Delete all namespace objects owned by this table. Note that these - * objects can appear anywhere in the namespace by virtue of the AML - * "Scope" operator. Thus, we need to track ownership by an ID, not - * simply a position within the hierarchy - */ + * Delete all namespace objects owned by this table. Note that these + * objects can appear anywhere in the namespace by virtue of the AML + * "Scope" operator. Thus, we need to track ownership by an ID, not + * simply a position within the hierarchy + */ acpi_tb_delete_namespace_by_owner(i); status = acpi_tb_release_owner_id(i); acpi_tb_set_table_loaded_flag(i, FALSE); @@ -376,7 +376,7 @@ ACPI_EXPORT_SYMBOL(acpi_unload_table_id) *****************************************************************************/ acpi_status acpi_get_table(char *signature, - acpi_native_uint instance, struct acpi_table_header **out_table) + acpi_native_uint instance, struct acpi_table_header ** out_table) { acpi_native_uint i; acpi_native_uint j; diff --git a/trunk/drivers/acpi/thermal.c b/trunk/drivers/acpi/thermal.c index 1ada017d01ef..589b98b7b216 100644 --- a/trunk/drivers/acpi/thermal.c +++ b/trunk/drivers/acpi/thermal.c @@ -59,6 +59,8 @@ #define ACPI_THERMAL_NOTIFY_CRITICAL 0xF0 #define ACPI_THERMAL_NOTIFY_HOT 0xF1 #define ACPI_THERMAL_MODE_ACTIVE 0x00 +#define ACPI_THERMAL_MODE_PASSIVE 0x01 +#define ACPI_THERMAL_MODE_CRITICAL 0xff #define ACPI_THERMAL_PATH_POWEROFF "/sbin/poweroff" #define ACPI_THERMAL_MAX_ACTIVE 10 @@ -84,6 +86,9 @@ static int acpi_thermal_resume(struct acpi_device *device); static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); +static ssize_t acpi_thermal_write_trip_points(struct file *, + const char __user *, size_t, + loff_t *); static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file); static ssize_t acpi_thermal_write_cooling_mode(struct file *, const char __user *, size_t, @@ -162,6 +167,7 @@ struct acpi_thermal { unsigned long temperature; unsigned long last_temperature; unsigned long polling_frequency; + u8 cooling_mode; volatile u8 zombie; struct acpi_thermal_flags flags; struct acpi_thermal_state state; @@ -187,6 +193,7 @@ static const struct file_operations acpi_thermal_temp_fops = { static const struct file_operations acpi_thermal_trip_fops = { .open = acpi_thermal_trip_open_fs, .read = seq_read, + .write = acpi_thermal_write_trip_points, .llseek = seq_lseek, .release = single_release, }; @@ -290,6 +297,11 @@ static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode) if (ACPI_FAILURE(status)) return -ENODEV; + tz->cooling_mode = mode; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n", + mode ? "passive" : "active")); + return 0; } @@ -877,6 +889,67 @@ static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file) return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data); } +static ssize_t +acpi_thermal_write_trip_points(struct file *file, + const char __user * buffer, + size_t count, loff_t * ppos) +{ + struct seq_file *m = file->private_data; + struct acpi_thermal *tz = m->private; + + char *limit_string; + int num, critical, hot, passive; + int *active; + int i = 0; + + + limit_string = kzalloc(ACPI_THERMAL_MAX_LIMIT_STR_LEN, GFP_KERNEL); + if (!limit_string) + return -ENOMEM; + + active = kmalloc(ACPI_THERMAL_MAX_ACTIVE * sizeof(int), GFP_KERNEL); + if (!active) { + kfree(limit_string); + return -ENOMEM; + } + + if (!tz || (count > ACPI_THERMAL_MAX_LIMIT_STR_LEN - 1)) { + count = -EINVAL; + goto end; + } + + if (copy_from_user(limit_string, buffer, count)) { + count = -EFAULT; + goto end; + } + + limit_string[count] = '\0'; + + num = sscanf(limit_string, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", + &critical, &hot, &passive, + &active[0], &active[1], &active[2], &active[3], &active[4], + &active[5], &active[6], &active[7], &active[8], + &active[9]); + if (!(num >= 5 && num < (ACPI_THERMAL_MAX_ACTIVE + 3))) { + count = -EINVAL; + goto end; + } + + tz->trips.critical.temperature = CELSIUS_TO_KELVIN(critical); + tz->trips.hot.temperature = CELSIUS_TO_KELVIN(hot); + tz->trips.passive.temperature = CELSIUS_TO_KELVIN(passive); + for (i = 0; i < num - 3; i++) { + if (!(tz->trips.active[i].flags.valid)) + break; + tz->trips.active[i].temperature = CELSIUS_TO_KELVIN(active[i]); + } + + end: + kfree(active); + kfree(limit_string); + return count; +} + static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset) { struct acpi_thermal *tz = seq->private; @@ -885,10 +958,15 @@ static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset) if (!tz) goto end; - if (!tz->flags.cooling_mode) + if (!tz->flags.cooling_mode) { seq_puts(seq, "\n"); + } + + if (tz->cooling_mode == ACPI_THERMAL_MODE_CRITICAL) + seq_printf(seq, "cooling mode: critical\n"); else - seq_puts(seq, "0 - Active; 1 - Passive\n"); + seq_printf(seq, "cooling mode: %s\n", + tz->cooling_mode ? "passive" : "active"); end: return 0; @@ -1145,6 +1223,28 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz) result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE); if (!result) tz->flags.cooling_mode = 1; + else { + /* Oh,we have not _SCP method. + Generally show cooling_mode by _ACx, _PSV,spec 12.2 */ + tz->flags.cooling_mode = 0; + if (tz->trips.active[0].flags.valid + && tz->trips.passive.flags.valid) { + if (tz->trips.passive.temperature > + tz->trips.active[0].temperature) + tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE; + else + tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE; + } else if (!tz->trips.active[0].flags.valid + && tz->trips.passive.flags.valid) { + tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE; + } else if (tz->trips.active[0].flags.valid + && !tz->trips.passive.flags.valid) { + tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE; + } else { + /* _ACx and _PSV are optional, but _CRT is required */ + tz->cooling_mode = ACPI_THERMAL_MODE_CRITICAL; + } + } /* Get default polling frequency [_TZP] (optional) */ if (tzp) diff --git a/trunk/drivers/acpi/utilities/utalloc.c b/trunk/drivers/acpi/utilities/utalloc.c index 6e56d5f7c43a..55a764807499 100644 --- a/trunk/drivers/acpi/utilities/utalloc.c +++ b/trunk/drivers/acpi/utilities/utalloc.c @@ -107,6 +107,7 @@ acpi_status acpi_ut_create_caches(void) if (ACPI_FAILURE(status)) { return (status); } + #ifdef ACPI_DBG_TRACK_ALLOCATIONS /* Memory allocation lists */ diff --git a/trunk/drivers/acpi/utilities/utcache.c b/trunk/drivers/acpi/utilities/utcache.c index 285a0f531760..870f6edeb5f2 100644 --- a/trunk/drivers/acpi/utilities/utcache.c +++ b/trunk/drivers/acpi/utilities/utcache.c @@ -45,6 +45,7 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utcache") + #ifdef ACPI_USE_LOCAL_CACHE /******************************************************************************* * @@ -63,7 +64,7 @@ ACPI_MODULE_NAME("utcache") acpi_status acpi_os_create_cache(char *cache_name, u16 object_size, - u16 max_depth, struct acpi_memory_list ** return_cache) + u16 max_depth, struct acpi_memory_list **return_cache) { struct acpi_memory_list *cache; diff --git a/trunk/drivers/acpi/utilities/utcopy.c b/trunk/drivers/acpi/utilities/utcopy.c index 4c1e00874dff..84d529db0a66 100644 --- a/trunk/drivers/acpi/utilities/utcopy.c +++ b/trunk/drivers/acpi/utilities/utcopy.c @@ -814,9 +814,7 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type, /* * Create the object array */ - target_object->package.elements = - ACPI_ALLOCATE_ZEROED(((acpi_size) source_object->package. - count + 1) * sizeof(void *)); + target_object->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) source_object->package.count + 1) * sizeof(void *)); if (!target_object->package.elements) { status = AE_NO_MEMORY; goto error_exit; diff --git a/trunk/drivers/acpi/utilities/utdebug.c b/trunk/drivers/acpi/utilities/utdebug.c index c7e128e5369b..61ad4f2daee2 100644 --- a/trunk/drivers/acpi/utilities/utdebug.c +++ b/trunk/drivers/acpi/utilities/utdebug.c @@ -45,6 +45,7 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utdebug") + #ifdef ACPI_DEBUG_OUTPUT static acpi_thread_id acpi_gbl_prev_thread_id; static char *acpi_gbl_fn_entry_str = "----Entry"; @@ -180,8 +181,7 @@ acpi_ut_debug_print(u32 requested_debug_level, if (ACPI_LV_THREADS & acpi_dbg_level) { acpi_os_printf ("\n**** Context Switch from TID %lX to TID %lX ****\n\n", - (unsigned long)acpi_gbl_prev_thread_id, - (unsigned long)thread_id); + (unsigned long)acpi_gbl_prev_thread_id, (unsigned long)thread_id); } acpi_gbl_prev_thread_id = thread_id; diff --git a/trunk/drivers/acpi/utilities/utdelete.c b/trunk/drivers/acpi/utilities/utdelete.c index f777cebdc46d..673a0caa4073 100644 --- a/trunk/drivers/acpi/utilities/utdelete.c +++ b/trunk/drivers/acpi/utilities/utdelete.c @@ -170,7 +170,6 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) acpi_os_delete_mutex(object->mutex.os_mutex); acpi_gbl_global_lock_mutex = NULL; } else { - acpi_ex_unlink_mutex(object); acpi_os_delete_mutex(object->mutex.os_mutex); } break; diff --git a/trunk/drivers/acpi/utilities/utglobal.c b/trunk/drivers/acpi/utilities/utglobal.c index 1621655d6e2b..af33358a964b 100644 --- a/trunk/drivers/acpi/utilities/utglobal.c +++ b/trunk/drivers/acpi/utilities/utglobal.c @@ -55,10 +55,12 @@ ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) * Static global variable initialization. * ******************************************************************************/ + /* * We want the debug switches statically initialized so they * are already set when the debugger is entered. */ + /* Debug switch - level and trace mask */ u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT; @@ -733,5 +735,5 @@ void acpi_ut_init_globals(void) } ACPI_EXPORT_SYMBOL(acpi_dbg_level) - ACPI_EXPORT_SYMBOL(acpi_dbg_layer) - ACPI_EXPORT_SYMBOL(acpi_gpe_count) +ACPI_EXPORT_SYMBOL(acpi_dbg_layer) +ACPI_EXPORT_SYMBOL(acpi_gpe_count) diff --git a/trunk/drivers/acpi/utilities/utmisc.c b/trunk/drivers/acpi/utilities/utmisc.c index 2d19f71e9cfa..50133fffe420 100644 --- a/trunk/drivers/acpi/utilities/utmisc.c +++ b/trunk/drivers/acpi/utilities/utmisc.c @@ -802,8 +802,9 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) valid_digits++; - if (sign_of0x && ((valid_digits > 16) - || ((valid_digits > 8) && mode32))) { + if (sign_of0x + && ((valid_digits > 16) + || ((valid_digits > 8) && mode32))) { /* * This is to_integer operation case. * No any restrictions for string-to-integer conversion, @@ -1048,7 +1049,6 @@ acpi_ut_exception(char *module_name, acpi_os_vprintf(format, args); acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); } - EXPORT_SYMBOL(acpi_ut_exception); void ACPI_INTERNAL_VAR_XFACE diff --git a/trunk/drivers/acpi/utilities/utmutex.c b/trunk/drivers/acpi/utilities/utmutex.c index 4820bc86d1f5..cbad2ef5987d 100644 --- a/trunk/drivers/acpi/utilities/utmutex.c +++ b/trunk/drivers/acpi/utilities/utmutex.c @@ -244,7 +244,7 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %lX attempting to acquire Mutex [%s]\n", - (unsigned long)this_thread_id, + (unsigned long) this_thread_id, acpi_ut_get_mutex_name(mutex_id))); status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex, @@ -252,7 +252,7 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) if (ACPI_SUCCESS(status)) { ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %lX acquired Mutex [%s]\n", - (unsigned long)this_thread_id, + (unsigned long) this_thread_id, acpi_ut_get_mutex_name(mutex_id))); acpi_gbl_mutex_info[mutex_id].use_count++; @@ -260,7 +260,7 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) } else { ACPI_EXCEPTION((AE_INFO, status, "Thread %lX could not acquire Mutex [%X]", - (unsigned long)this_thread_id, mutex_id)); + (unsigned long) this_thread_id, mutex_id)); } return (status); @@ -287,7 +287,7 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) this_thread_id = acpi_os_get_thread_id(); ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %lX releasing Mutex [%s]\n", - (unsigned long)this_thread_id, + (unsigned long) this_thread_id, acpi_ut_get_mutex_name(mutex_id))); if (mutex_id > ACPI_MAX_MUTEX) { diff --git a/trunk/drivers/acpi/utilities/utresrc.c b/trunk/drivers/acpi/utilities/utresrc.c index cbbd3315a1e2..e8fe1ba6cc24 100644 --- a/trunk/drivers/acpi/utilities/utresrc.c +++ b/trunk/drivers/acpi/utilities/utresrc.c @@ -46,6 +46,7 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utresrc") + #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) /* * Strings used to decode resource descriptors. diff --git a/trunk/drivers/acpi/utilities/utxface.c b/trunk/drivers/acpi/utilities/utxface.c index e9a57806cd34..de3276f4f468 100644 --- a/trunk/drivers/acpi/utilities/utxface.c +++ b/trunk/drivers/acpi/utilities/utxface.c @@ -337,6 +337,7 @@ acpi_status acpi_terminate(void) } ACPI_EXPORT_SYMBOL(acpi_terminate) + #ifdef ACPI_FUTURE_USAGE /******************************************************************************* * @@ -469,6 +470,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function) ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler) #endif /* ACPI_FUTURE_USAGE */ + /***************************************************************************** * * FUNCTION: acpi_purge_cached_objects diff --git a/trunk/drivers/ata/Kconfig b/trunk/drivers/ata/Kconfig index f031b8732330..45dbdc14915f 100644 --- a/trunk/drivers/ata/Kconfig +++ b/trunk/drivers/ata/Kconfig @@ -3,7 +3,6 @@ # menu "Serial ATA (prod) and Parallel ATA (experimental) drivers" - depends on HAS_IOMEM config ATA tristate "ATA device support" @@ -436,7 +435,7 @@ config PATA_OPTIDMA help This option enables DMA/PIO support for the later OPTi controllers found on some old motherboards and in some - laptops. + latops If unsure, say N. diff --git a/trunk/drivers/ata/libata-acpi.c b/trunk/drivers/ata/libata-acpi.c index cb3eab6e379d..03a0acff6cfa 100644 --- a/trunk/drivers/ata/libata-acpi.c +++ b/trunk/drivers/ata/libata-acpi.c @@ -489,7 +489,8 @@ static void taskfile_load_raw(struct ata_port *ap, /* convert gtf to tf */ tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */ - tf.protocol = ATA_PROT_NODATA; + tf.protocol = atadev->class == ATA_DEV_ATAPI ? + ATA_PROT_ATAPI_NODATA : ATA_PROT_NODATA; tf.feature = gtf->tfa[0]; /* 0x1f1 */ tf.nsect = gtf->tfa[1]; /* 0x1f2 */ tf.lbal = gtf->tfa[2]; /* 0x1f3 */ diff --git a/trunk/drivers/ata/libata-core.c b/trunk/drivers/ata/libata-core.c index 4595d1f8cf60..a7950885d18e 100644 --- a/trunk/drivers/ata/libata-core.c +++ b/trunk/drivers/ata/libata-core.c @@ -895,7 +895,6 @@ static u64 ata_read_native_max_address(struct ata_device *dev) /** * ata_set_native_max_address_ext - LBA48 native max set * @dev: Device to query - * @new_sectors: new max sectors value to set for the device * * Perform an LBA48 size set max upon the device in question. Return the * actual LBA48 size or zero if the command fails. @@ -933,7 +932,6 @@ static u64 ata_set_native_max_address_ext(struct ata_device *dev, u64 new_sector /** * ata_set_native_max_address - LBA28 native max set * @dev: Device to query - * @new_sectors: new max sectors value to set for the device * * Perform an LBA28 size set max upon the device in question. Return the * actual LBA28 size or zero if the command fails. @@ -1318,7 +1316,7 @@ void ata_port_flush_task(struct ata_port *ap) spin_unlock_irqrestore(ap->lock, flags); DPRINTK("flush #1\n"); - cancel_work_sync(&ap->port_task.work); /* akpm: seems unneeded */ + flush_workqueue(ata_wq); /* * At this point, if a task is running, it's guaranteed to see @@ -1329,7 +1327,7 @@ void ata_port_flush_task(struct ata_port *ap) if (ata_msg_ctl(ap)) ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n", __FUNCTION__); - cancel_work_sync(&ap->port_task.work); + flush_workqueue(ata_wq); } spin_lock_irqsave(ap->lock, flags); @@ -6477,9 +6475,9 @@ void ata_port_detach(struct ata_port *ap) /* Flush hotplug task. The sequence is similar to * ata_port_flush_task(). */ - cancel_work_sync(&ap->hotplug_task.work); /* akpm: why? */ + flush_workqueue(ata_aux_wq); cancel_delayed_work(&ap->hotplug_task); - cancel_work_sync(&ap->hotplug_task.work); + flush_workqueue(ata_aux_wq); skip_eh: /* remove the associated SCSI host */ diff --git a/trunk/drivers/ata/pata_pcmcia.c b/trunk/drivers/ata/pata_pcmcia.c index 11245e331f77..75dc84797ff3 100644 --- a/trunk/drivers/ata/pata_pcmcia.c +++ b/trunk/drivers/ata/pata_pcmcia.c @@ -357,7 +357,6 @@ static struct pcmcia_device_id pcmcia_devices[] = { PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */ PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */ PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), - PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904), PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */ PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), diff --git a/trunk/drivers/ata/pata_qdi.c b/trunk/drivers/ata/pata_qdi.c index fb8c9e14b8d4..27685ce63ceb 100644 --- a/trunk/drivers/ata/pata_qdi.c +++ b/trunk/drivers/ata/pata_qdi.c @@ -375,7 +375,7 @@ static __init int qdi_init(void) res = inb(port + 3); if (res & 1) { /* Single channel mode */ - if (qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04) == 0) + if (qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04)) ct++; } else { /* Dual channel mode */ diff --git a/trunk/drivers/ata/pata_scc.c b/trunk/drivers/ata/pata_scc.c index 203f463ac39f..5df354d573e8 100644 --- a/trunk/drivers/ata/pata_scc.c +++ b/trunk/drivers/ata/pata_scc.c @@ -1142,14 +1142,14 @@ static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) static int printed_version; unsigned int board_idx = (unsigned int) ent->driver_data; const struct ata_port_info *ppi[] = { &scc_port_info[board_idx], NULL }; - struct ata_host *host; + struct device *dev = &pdev->dev; int rc; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - host = ata_host_alloc_pinfo(&pdev->dev, ppi, 1); + host = ata_port_alloc_pinfo(&pdev->dev, ppi, 1); if (!host) return -ENOMEM; diff --git a/trunk/drivers/ata/sata_nv.c b/trunk/drivers/ata/sata_nv.c index a097595d4dc7..e2e795e58236 100644 --- a/trunk/drivers/ata/sata_nv.c +++ b/trunk/drivers/ata/sata_nv.c @@ -257,8 +257,6 @@ static void nv_adma_port_stop(struct ata_port *ap); static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg); static int nv_adma_port_resume(struct ata_port *ap); #endif -static void nv_adma_freeze(struct ata_port *ap); -static void nv_adma_thaw(struct ata_port *ap); static void nv_adma_error_handler(struct ata_port *ap); static void nv_adma_host_stop(struct ata_host *host); static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc); @@ -446,8 +444,8 @@ static const struct ata_port_operations nv_adma_ops = { .bmdma_status = ata_bmdma_status, .qc_prep = nv_adma_qc_prep, .qc_issue = nv_adma_qc_issue, - .freeze = nv_adma_freeze, - .thaw = nv_adma_thaw, + .freeze = nv_ck804_freeze, + .thaw = nv_ck804_thaw, .error_handler = nv_adma_error_handler, .post_internal_cmd = nv_adma_post_internal_cmd, .data_xfer = ata_data_xfer, @@ -817,16 +815,8 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) u16 status; u32 gen_ctl; u32 notifier, notifier_error; - - /* if ADMA is disabled, use standard ata interrupt handler */ - if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) { - u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804) - >> (NV_INT_PORT_SHIFT * i); - handled += nv_host_intr(ap, irq_stat); - continue; - } - /* if in ATA register mode, check for standard interrupts */ + /* if in ATA register mode, use standard ata interrupt handler */ if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) { u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804) >> (NV_INT_PORT_SHIFT * i); @@ -836,6 +826,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) command is active, to prevent losing interrupts. */ irq_stat |= NV_INT_DEV; handled += nv_host_intr(ap, irq_stat); + continue; } notifier = readl(mmio + NV_ADMA_NOTIFIER); @@ -921,77 +912,22 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) return IRQ_RETVAL(handled); } -static void nv_adma_freeze(struct ata_port *ap) -{ - struct nv_adma_port_priv *pp = ap->private_data; - void __iomem *mmio = pp->ctl_block; - u16 tmp; - - nv_ck804_freeze(ap); - - if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) - return; - - /* clear any outstanding CK804 notifications */ - writeb( NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT), - ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804); - - /* Disable interrupt */ - tmp = readw(mmio + NV_ADMA_CTL); - writew( tmp & ~(NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN), - mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ -} - -static void nv_adma_thaw(struct ata_port *ap) -{ - struct nv_adma_port_priv *pp = ap->private_data; - void __iomem *mmio = pp->ctl_block; - u16 tmp; - - nv_ck804_thaw(ap); - - if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) - return; - - /* Enable interrupt */ - tmp = readw(mmio + NV_ADMA_CTL); - writew( tmp | (NV_ADMA_CTL_AIEN | NV_ADMA_CTL_HOTPLUG_IEN), - mmio + NV_ADMA_CTL); - readw( mmio + NV_ADMA_CTL ); /* flush posted write */ -} - static void nv_adma_irq_clear(struct ata_port *ap) { struct nv_adma_port_priv *pp = ap->private_data; void __iomem *mmio = pp->ctl_block; - u32 notifier_clears[2]; - - if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) { - ata_bmdma_irq_clear(ap); - return; - } - - /* clear any outstanding CK804 notifications */ - writeb( NV_INT_ALL << (ap->port_no * NV_INT_PORT_SHIFT), - ap->host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804); + u16 status = readw(mmio + NV_ADMA_STAT); + u32 notifier = readl(mmio + NV_ADMA_NOTIFIER); + u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR); + void __iomem *dma_stat_addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; /* clear ADMA status */ - writew(0xffff, mmio + NV_ADMA_STAT); - - /* clear notifiers - note both ports need to be written with - something even though we are only clearing on one */ - if (ap->port_no == 0) { - notifier_clears[0] = 0xFFFFFFFF; - notifier_clears[1] = 0; - } else { - notifier_clears[0] = 0; - notifier_clears[1] = 0xFFFFFFFF; - } - pp = ap->host->ports[0]->private_data; - writel(notifier_clears[0], pp->notifier_clear_block); - pp = ap->host->ports[1]->private_data; - writel(notifier_clears[1], pp->notifier_clear_block); + writew(status, mmio + NV_ADMA_STAT); + writel(notifier | notifier_error, + pp->notifier_clear_block); + + /** clear legacy status */ + iowrite8(ioread8(dma_stat_addr), dma_stat_addr); } static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc) diff --git a/trunk/drivers/ata/sata_promise.c b/trunk/drivers/ata/sata_promise.c index 3a7d9b5332af..f56549b90aa6 100644 --- a/trunk/drivers/ata/sata_promise.c +++ b/trunk/drivers/ata/sata_promise.c @@ -45,7 +45,7 @@ #include "sata_promise.h" #define DRV_NAME "sata_promise" -#define DRV_VERSION "2.07" +#define DRV_VERSION "2.05" enum { @@ -653,8 +653,6 @@ static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc, qc->err_mask |= ac_err_mask; pdc_reset_port(ap); - - ata_port_abort(ap); } static inline unsigned int pdc_host_intr( struct ata_port *ap, @@ -926,7 +924,6 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e struct ata_host *host; void __iomem *base; int n_ports, i, rc; - int is_sataii_tx4; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); @@ -965,23 +962,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e } host->iomap = pcim_iomap_table(pdev); - is_sataii_tx4 = 0; - if ((pi->flags & (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) == (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) { - is_sataii_tx4 = 1; - dev_printk(KERN_INFO, &pdev->dev, "applying SATAII TX4 port numbering workaround\n"); - } - for (i = 0; i < host->n_ports; i++) { - static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2}; - int ata_nr; - - ata_nr = i; - if (is_sataii_tx4) - ata_nr = sataii_tx4_port_remap[i]; - + for (i = 0; i < host->n_ports; i++) pdc_ata_setup_port(host->ports[i], - base + 0x200 + ata_nr * 0x80, - base + 0x400 + ata_nr * 0x100); - } + base + 0x200 + i * 0x80, + base + 0x400 + i * 0x100); /* initialize adapter */ pdc_host_init(host); diff --git a/trunk/drivers/ata/sata_via.c b/trunk/drivers/ata/sata_via.c index 939c9246fdd1..305ab7c68ca5 100644 --- a/trunk/drivers/ata/sata_via.c +++ b/trunk/drivers/ata/sata_via.c @@ -93,10 +93,6 @@ static struct pci_driver svia_pci_driver = { .name = DRV_NAME, .id_table = svia_pci_tbl, .probe = svia_init_one, -#ifdef CONFIG_PM - .suspend = ata_pci_device_suspend, - .resume = ata_pci_device_resume, -#endif .remove = ata_pci_remove_one, }; @@ -116,10 +112,6 @@ static struct scsi_host_template svia_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, -#ifdef CONFIG_PM - .suspend = ata_scsi_device_suspend, - .resume = ata_scsi_device_resume, -#endif }; static const struct ata_port_operations vt6420_sata_ops = { diff --git a/trunk/drivers/auxdisplay/Kconfig b/trunk/drivers/auxdisplay/Kconfig index 2e18a63ead36..0300e7f54cc4 100644 --- a/trunk/drivers/auxdisplay/Kconfig +++ b/trunk/drivers/auxdisplay/Kconfig @@ -6,7 +6,6 @@ # menu "Auxiliary Display support" - depends on PARPORT config KS0108 tristate "KS0108 LCD Controller" diff --git a/trunk/drivers/base/devres.c b/trunk/drivers/base/devres.c index e1c0730a3b99..e177c9533b6c 100644 --- a/trunk/drivers/base/devres.c +++ b/trunk/drivers/base/devres.c @@ -101,6 +101,19 @@ static void add_dr(struct device *dev, struct devres_node *node) list_add_tail(&node->entry, &dev->devres_head); } +/** + * devres_alloc - Allocate device resource data + * @release: Release function devres will be associated with + * @size: Allocation size + * @gfp: Allocation flags + * + * allocate devres of @size bytes. The allocated area is zeroed, then + * associated with @release. The returned pointer can be passed to + * other devres_*() functions. + * + * RETURNS: + * Pointer to allocated devres on success, NULL on failure. + */ #ifdef CONFIG_DEBUG_DEVRES void * __devres_alloc(dr_release_t release, size_t size, gfp_t gfp, const char *name) @@ -115,19 +128,6 @@ void * __devres_alloc(dr_release_t release, size_t size, gfp_t gfp, } EXPORT_SYMBOL_GPL(__devres_alloc); #else -/** - * devres_alloc - Allocate device resource data - * @release: Release function devres will be associated with - * @size: Allocation size - * @gfp: Allocation flags - * - * Allocate devres of @size bytes. The allocated area is zeroed, then - * associated with @release. The returned pointer can be passed to - * other devres_*() functions. - * - * RETURNS: - * Pointer to allocated devres on success, NULL on failure. - */ void * devres_alloc(dr_release_t release, size_t size, gfp_t gfp) { struct devres *dr; @@ -416,7 +416,7 @@ static int release_nodes(struct device *dev, struct list_head *first, } /** - * devres_release_all - Release all managed resources + * devres_release_all - Release all resources * @dev: Device to release resources for * * Release all resources associated with @dev. This function is @@ -600,7 +600,7 @@ static int devm_kzalloc_match(struct device *dev, void *res, void *data) } /** - * devm_kzalloc - Resource-managed kzalloc + * devm_kzalloc - Managed kzalloc * @dev: Device to allocate memory for * @size: Allocation size * @gfp: Allocation gfp flags @@ -628,7 +628,7 @@ void * devm_kzalloc(struct device *dev, size_t size, gfp_t gfp) EXPORT_SYMBOL_GPL(devm_kzalloc); /** - * devm_kfree - Resource-managed kfree + * devm_kfree - Managed kfree * @dev: Device this memory belongs to * @p: Memory to free * diff --git a/trunk/drivers/base/platform.c b/trunk/drivers/base/platform.c index 869ff8c00146..eb84d9d44645 100644 --- a/trunk/drivers/base/platform.c +++ b/trunk/drivers/base/platform.c @@ -360,7 +360,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister); * This function creates a simple platform device that requires minimal * resource and memory management. Canned release function freeing * memory allocated for the device allows drivers using such devices - * to be unloaded without waiting for the last reference to the device + * to be unloaded iwithout waiting for the last reference to the device * to be dropped. * * This interface is primarily intended for use with legacy drivers diff --git a/trunk/drivers/base/topology.c b/trunk/drivers/base/topology.c index 8d8cdfec6529..067a9e8bc377 100644 --- a/trunk/drivers/base/topology.c +++ b/trunk/drivers/base/topology.c @@ -126,13 +126,10 @@ static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_UP_PREPARE: - case CPU_UP_PREPARE_FROZEN: rc = topology_add_dev(cpu); break; case CPU_UP_CANCELED: - case CPU_UP_CANCELED_FROZEN: case CPU_DEAD: - case CPU_DEAD_FROZEN: topology_remove_dev(cpu); break; } diff --git a/trunk/drivers/block/Kconfig b/trunk/drivers/block/Kconfig index b4c8319138b2..17ee97f3a99b 100644 --- a/trunk/drivers/block/Kconfig +++ b/trunk/drivers/block/Kconfig @@ -444,6 +444,8 @@ config CDROM_PKTCDVD_WCACHE this option is dangerous unless the CD-RW media is known good, as we don't do deferred write error handling yet. +source "drivers/s390/block/Kconfig" + config ATA_OVER_ETH tristate "ATA over Ethernet support" depends on NET @@ -451,8 +453,6 @@ config ATA_OVER_ETH This driver provides Support for ATA over Ethernet block devices like the Coraid EtherDrive (R) Storage Blade. -source "drivers/s390/block/Kconfig" - endmenu endif diff --git a/trunk/drivers/block/loop.c b/trunk/drivers/block/loop.c index 18cdd8c77626..af6d7274a7cc 100644 --- a/trunk/drivers/block/loop.c +++ b/trunk/drivers/block/loop.c @@ -243,13 +243,17 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec, transfer_result = lo_do_transfer(lo, WRITE, page, offset, bvec->bv_page, bv_offs, size, IV); if (unlikely(transfer_result)) { + char *kaddr; + /* * The transfer failed, but we still write the data to * keep prepare/commit calls balanced. */ printk(KERN_ERR "loop: transfer error block %llu\n", (unsigned long long)index); - zero_user_page(page, offset, size, KM_USER0); + kaddr = kmap_atomic(page, KM_USER0); + memset(kaddr + offset, 0, size); + kunmap_atomic(kaddr, KM_USER0); } flush_dcache_page(page); ret = aops->commit_write(file, page, offset, diff --git a/trunk/drivers/block/nbd.c b/trunk/drivers/block/nbd.c index 069ae39a9cd9..090796bef78f 100644 --- a/trunk/drivers/block/nbd.c +++ b/trunk/drivers/block/nbd.c @@ -366,25 +366,20 @@ static struct disk_attribute pid_attr = { .show = pid_show, }; -static int nbd_do_it(struct nbd_device *lo) +static void nbd_do_it(struct nbd_device *lo) { struct request *req; - int ret; BUG_ON(lo->magic != LO_MAGIC); lo->pid = current->pid; - ret = sysfs_create_file(&lo->disk->kobj, &pid_attr.attr); - if (ret) { - printk(KERN_ERR "nbd: sysfs_create_file failed!"); - return ret; - } + sysfs_create_file(&lo->disk->kobj, &pid_attr.attr); while ((req = nbd_read_stat(lo)) != NULL) nbd_end_request(req); sysfs_remove_file(&lo->disk->kobj, &pid_attr.attr); - return 0; + return; } static void nbd_clear_que(struct nbd_device *lo) @@ -574,9 +569,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file, case NBD_DO_IT: if (!lo->file) return -EINVAL; - error = nbd_do_it(lo); - if (error) - return error; + nbd_do_it(lo); /* on return tidy up in case we have a signal */ /* Forcibly shutdown the socket causing all listeners * to error diff --git a/trunk/drivers/block/rd.c b/trunk/drivers/block/rd.c index a1512da32410..43d4ebcb3b44 100644 --- a/trunk/drivers/block/rd.c +++ b/trunk/drivers/block/rd.c @@ -151,7 +151,7 @@ static int ramdisk_commit_write(struct file *file, struct page *page, } /* - * ->writepage to the blockdev's mapping has to redirty the page so that the + * ->writepage to the the blockdev's mapping has to redirty the page so that the * VM doesn't go and steal it. We return AOP_WRITEPAGE_ACTIVATE so that the VM * won't try to (pointlessly) write the page again for a while. * diff --git a/trunk/drivers/char/Kconfig b/trunk/drivers/char/Kconfig index abcafac64738..2df42fdcdc91 100644 --- a/trunk/drivers/char/Kconfig +++ b/trunk/drivers/char/Kconfig @@ -6,7 +6,6 @@ menu "Character devices" config VT bool "Virtual terminal" if EMBEDDED - depends on !S390 select INPUT default y if !VIOCONS ---help--- @@ -82,7 +81,6 @@ config VT_HW_CONSOLE_BINDING config SERIAL_NONSTANDARD bool "Non-standard serial port support" - depends on HAS_IOMEM ---help--- Say Y here if you have any non-standard serial boards -- boards which aren't supported using the standard "dumb" serial driver. @@ -767,7 +765,7 @@ config NVRAM config RTC tristate "Enhanced Real Time Clock Support" - depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH && !S390 + depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH ---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 @@ -815,7 +813,7 @@ config SGI_IP27_RTC config GEN_RTC tristate "Generic /dev/rtc emulation" - depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV && !S390 + depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV ---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 @@ -860,7 +858,6 @@ config COBALT_LCD config DTLK tristate "Double Talk PC internal speech card support" - depends on ISA help This driver is for the DoubleTalk PC, a speech synthesizer manufactured by RC Systems (). It is also @@ -1046,7 +1043,7 @@ config HPET_MMAP config HANGCHECK_TIMER tristate "Hangcheck timer" - depends on X86 || IA64 || PPC64 || S390 + depends on X86 || IA64 || PPC64 help The hangcheck-timer module detects when the system has gone out to lunch past a certain margin. It can reboot the system @@ -1081,7 +1078,5 @@ config DEVPORT depends on ISA || PCI default y -source "drivers/s390/char/Kconfig" - endmenu diff --git a/trunk/drivers/char/drm/drm_dma.c b/trunk/drivers/char/drm/drm_dma.c index 32ed19c9ec1c..892db7096986 100644 --- a/trunk/drivers/char/drm/drm_dma.c +++ b/trunk/drivers/char/drm/drm_dma.c @@ -65,7 +65,7 @@ int drm_dma_setup(drm_device_t * dev) * \param dev DRM device. * * Free all pages associated with DMA buffers, the buffers and pages lists, and - * finally the drm_device::dma structure itself. + * finally the the drm_device::dma structure itself. */ void drm_dma_takedown(drm_device_t * dev) { diff --git a/trunk/drivers/char/drm/drm_vm.c b/trunk/drivers/char/drm/drm_vm.c index b5c5b9fa84c3..35540cfb43dd 100644 --- a/trunk/drivers/char/drm/drm_vm.c +++ b/trunk/drivers/char/drm/drm_vm.c @@ -157,7 +157,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, * \param address access address. * \return pointer to the page structure. * - * Get the mapping, find the real physical page to map, get the page, and + * Get the the mapping, find the real physical page to map, get the page, and * return it. */ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma, diff --git a/trunk/drivers/char/drm/r300_reg.h b/trunk/drivers/char/drm/r300_reg.h index ecda760ae8c0..a881f96c983e 100644 --- a/trunk/drivers/char/drm/r300_reg.h +++ b/trunk/drivers/char/drm/r300_reg.h @@ -293,7 +293,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0 # define R300_PVS_CNTL_1_POS_END_SHIFT 10 # define R300_PVS_CNTL_1_PROGRAM_END_SHIFT 20 -/* Addresses are relative to the vertex program parameters area. */ +/* Addresses are relative the the vertex program parameters area. */ #define R300_VAP_PVS_CNTL_2 0x22D4 # define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0 # define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT 16 diff --git a/trunk/drivers/char/genrtc.c b/trunk/drivers/char/genrtc.c index 9e1fc02967ff..49f914e79216 100644 --- a/trunk/drivers/char/genrtc.c +++ b/trunk/drivers/char/genrtc.c @@ -12,7 +12,7 @@ * * This driver allows use of the real time clock (built into * nearly all computers) from user space. It exports the /dev/rtc - * interface supporting various ioctl() and also the /proc/driver/rtc + * interface supporting various ioctl() and also the /proc/dev/rtc * pseudo-file for status information. * * The ioctls can be used to set the interrupt behaviour where @@ -377,7 +377,7 @@ static int gen_rtc_release(struct inode *inode, struct file *file) #ifdef CONFIG_PROC_FS /* - * Info exported via "/proc/driver/rtc". + * Info exported via "/proc/rtc". */ static int gen_rtc_proc_output(char *buf) diff --git a/trunk/drivers/char/hw_random/Kconfig b/trunk/drivers/char/hw_random/Kconfig index 7cda04b33534..5f3acd8e64b8 100644 --- a/trunk/drivers/char/hw_random/Kconfig +++ b/trunk/drivers/char/hw_random/Kconfig @@ -91,17 +91,3 @@ config HW_RANDOM_OMAP module will be called omap-rng. If unsure, say Y. - -config HW_RANDOM_PASEMI - tristate "PA Semi HW Random Number Generator support" - depends on HW_RANDOM && PPC_PASEMI - default HW_RANDOM - ---help--- - This driver provides kernel-side support for the Random Number - Generator hardware found on PA6T-1682M processor. - - To compile this driver as a module, choose M here: the - module will be called pasemi-rng. - - If unsure, say Y. - diff --git a/trunk/drivers/char/hw_random/Makefile b/trunk/drivers/char/hw_random/Makefile index c8b7300e2fb1..c41fa19454e3 100644 --- a/trunk/drivers/char/hw_random/Makefile +++ b/trunk/drivers/char/hw_random/Makefile @@ -10,4 +10,3 @@ obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o -obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o diff --git a/trunk/drivers/char/hw_random/pasemi-rng.c b/trunk/drivers/char/hw_random/pasemi-rng.c deleted file mode 100644 index fa6040b6c8f2..000000000000 --- a/trunk/drivers/char/hw_random/pasemi-rng.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2006-2007 PA Semi, Inc - * - * Maintained by: Olof Johansson - * - * Driver for the PWRficient onchip rng - * - * 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 the Free Software Foundation. - * - * 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 -#include -#include -#include -#include -#include - -#define SDCRNG_CTL_REG 0x00 -#define SDCRNG_CTL_FVLD_M 0x0000f000 -#define SDCRNG_CTL_FVLD_S 12 -#define SDCRNG_CTL_KSZ 0x00000800 -#define SDCRNG_CTL_RSRC_CRG 0x00000010 -#define SDCRNG_CTL_RSRC_RRG 0x00000000 -#define SDCRNG_CTL_CE 0x00000004 -#define SDCRNG_CTL_RE 0x00000002 -#define SDCRNG_CTL_DR 0x00000001 -#define SDCRNG_CTL_SELECT_RRG_RNG (SDCRNG_CTL_RE | SDCRNG_CTL_RSRC_RRG) -#define SDCRNG_CTL_SELECT_CRG_RNG (SDCRNG_CTL_CE | SDCRNG_CTL_RSRC_CRG) -#define SDCRNG_VAL_REG 0x20 - -#define MODULE_NAME "pasemi_rng" - -static int pasemi_rng_data_present(struct hwrng *rng) -{ - void __iomem *rng_regs = (void __iomem *)rng->priv; - - return (in_le32(rng_regs + SDCRNG_CTL_REG) - & SDCRNG_CTL_FVLD_M) ? 1 : 0; -} - -static int pasemi_rng_data_read(struct hwrng *rng, u32 *data) -{ - void __iomem *rng_regs = (void __iomem *)rng->priv; - *data = in_le32(rng_regs + SDCRNG_VAL_REG); - return 4; -} - -static int pasemi_rng_init(struct hwrng *rng) -{ - void __iomem *rng_regs = (void __iomem *)rng->priv; - u32 ctl; - - ctl = SDCRNG_CTL_DR | SDCRNG_CTL_SELECT_RRG_RNG | SDCRNG_CTL_KSZ; - out_le32(rng_regs + SDCRNG_CTL_REG, ctl); - out_le32(rng_regs + SDCRNG_CTL_REG, ctl & ~SDCRNG_CTL_DR); - - return 0; -} - -static void pasemi_rng_cleanup(struct hwrng *rng) -{ - void __iomem *rng_regs = (void __iomem *)rng->priv; - u32 ctl; - - ctl = SDCRNG_CTL_RE | SDCRNG_CTL_CE; - out_le32(rng_regs + SDCRNG_CTL_REG, - in_le32(rng_regs + SDCRNG_CTL_REG) & ~ctl); -} - -static struct hwrng pasemi_rng = { - .name = MODULE_NAME, - .init = pasemi_rng_init, - .cleanup = pasemi_rng_cleanup, - .data_present = pasemi_rng_data_present, - .data_read = pasemi_rng_data_read, -}; - -static int __devinit rng_probe(struct of_device *ofdev, - const struct of_device_id *match) -{ - void __iomem *rng_regs; - struct device_node *rng_np = ofdev->node; - struct resource res; - int err = 0; - - err = of_address_to_resource(rng_np, 0, &res); - if (err) - return -ENODEV; - - rng_regs = ioremap(res.start, 0x100); - - if (!rng_regs) - return -ENOMEM; - - pasemi_rng.priv = (unsigned long)rng_regs; - - printk(KERN_INFO "Registering PA Semi RNG\n"); - - err = hwrng_register(&pasemi_rng); - - if (err) - iounmap(rng_regs); - - return err; -} - -static int __devexit rng_remove(struct of_device *dev) -{ - void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; - - hwrng_unregister(&pasemi_rng); - iounmap(rng_regs); - - return 0; -} - -static struct of_device_id rng_match[] = { - { - .compatible = "1682m-rng", - }, - {}, -}; - -static struct of_platform_driver rng_driver = { - .name = "pasemi-rng", - .match_table = rng_match, - .probe = rng_probe, - .remove = rng_remove, -}; - -static int __init rng_init(void) -{ - return of_register_platform_driver(&rng_driver); -} -module_init(rng_init); - -static void __exit rng_exit(void) -{ - of_unregister_platform_driver(&rng_driver); -} -module_exit(rng_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Egor Martovetsky "); -MODULE_DESCRIPTION("H/W RNG driver for PA Semi processor"); diff --git a/trunk/drivers/char/ipmi/Kconfig b/trunk/drivers/char/ipmi/Kconfig index b894f67fdf14..a6dcb2918157 100644 --- a/trunk/drivers/char/ipmi/Kconfig +++ b/trunk/drivers/char/ipmi/Kconfig @@ -3,8 +3,6 @@ # menu "IPMI" - depends on HAS_IOMEM - config IPMI_HANDLER tristate 'IPMI top-level message handler' help diff --git a/trunk/drivers/char/mmtimer.c b/trunk/drivers/char/mmtimer.c index 6e55cfb9c65a..c09160383a53 100644 --- a/trunk/drivers/char/mmtimer.c +++ b/trunk/drivers/char/mmtimer.c @@ -705,13 +705,15 @@ static int __init mmtimer_init(void) maxn++; /* Allocate list of node ptrs to mmtimer_t's */ - timers = kzalloc(sizeof(mmtimer_t *)*maxn, GFP_KERNEL); + timers = kmalloc(sizeof(mmtimer_t *)*maxn, GFP_KERNEL); if (timers == NULL) { printk(KERN_ERR "%s: failed to allocate memory for device\n", MMTIMER_NAME); goto out3; } + memset(timers,0,(sizeof(mmtimer_t *)*maxn)); + /* Allocate mmtimer_t's for each online node */ for_each_online_node(node) { timers[node] = kmalloc_node(sizeof(mmtimer_t)*NUM_COMPARATORS, GFP_KERNEL, node); diff --git a/trunk/drivers/char/pcmcia/Kconfig b/trunk/drivers/char/pcmcia/Kconfig index f25facd97bb4..27c1179ee527 100644 --- a/trunk/drivers/char/pcmcia/Kconfig +++ b/trunk/drivers/char/pcmcia/Kconfig @@ -21,7 +21,6 @@ config SYNCLINK_CS config CARDMAN_4000 tristate "Omnikey Cardman 4000 support" depends on PCMCIA - select BITREVERSE help Enable support for the Omnikey Cardman 4000 PCMCIA Smartcard reader. diff --git a/trunk/drivers/char/pcmcia/cm4000_cs.c b/trunk/drivers/char/pcmcia/cm4000_cs.c index fee58e03dbe2..e91b43a014b0 100644 --- a/trunk/drivers/char/pcmcia/cm4000_cs.c +++ b/trunk/drivers/char/pcmcia/cm4000_cs.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -195,17 +194,41 @@ static inline unsigned char xinb(unsigned short port) } #endif -static inline unsigned char invert_revert(unsigned char ch) -{ - return bitrev8(~ch); -} +#define b_0000 15 +#define b_0001 14 +#define b_0010 13 +#define b_0011 12 +#define b_0100 11 +#define b_0101 10 +#define b_0110 9 +#define b_0111 8 +#define b_1000 7 +#define b_1001 6 +#define b_1010 5 +#define b_1011 4 +#define b_1100 3 +#define b_1101 2 +#define b_1110 1 +#define b_1111 0 + +static unsigned char irtab[16] = { + b_0000, b_1000, b_0100, b_1100, + b_0010, b_1010, b_0110, b_1110, + b_0001, b_1001, b_0101, b_1101, + b_0011, b_1011, b_0111, b_1111 +}; static void str_invert_revert(unsigned char *b, int len) { int i; for (i = 0; i < len; i++) - b[i] = invert_revert(b[i]); + b[i] = (irtab[b[i] & 0x0f] << 4) | irtab[b[i] >> 4]; +} + +static unsigned char invert_revert(unsigned char ch) +{ + return (irtab[ch & 0x0f] << 4) | irtab[ch >> 4]; } #define ATRLENCK(dev,pos) \ @@ -1091,7 +1114,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf, /* * wait for atr to become valid. * note: it is important to lock this code. if we dont, the monitor - * could be run between test_bit and the call to sleep on the + * could be run between test_bit and the the call the sleep on the * atr-queue. if *then* the monitor detects atr valid, it will wake up * any process on the atr-queue, *but* since we have been interrupted, * we do not yet sleep on this queue. this would result in a missed @@ -1858,11 +1881,8 @@ static int cm4000_probe(struct pcmcia_device *link) init_waitqueue_head(&dev->readq); ret = cm4000_config(link, i); - if (ret) { - dev_table[i] = NULL; - kfree(dev); + if (ret) return ret; - } class_device_create(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i); @@ -1887,7 +1907,7 @@ static void cm4000_detach(struct pcmcia_device *link) cm4000_release(link); dev_table[devno] = NULL; - kfree(dev); + kfree(dev); class_device_destroy(cmm_class, MKDEV(major, devno)); @@ -1936,14 +1956,12 @@ static int __init cmm_init(void) if (major < 0) { printk(KERN_WARNING MODULE_NAME ": could not get major number\n"); - class_destroy(cmm_class); return major; } rc = pcmcia_register_driver(&cm4000_driver); if (rc < 0) { unregister_chrdev(major, DEVICE_NAME); - class_destroy(cmm_class); return rc; } diff --git a/trunk/drivers/char/pcmcia/cm4040_cs.c b/trunk/drivers/char/pcmcia/cm4040_cs.c index af88181a17f4..f2e4ec4fd407 100644 --- a/trunk/drivers/char/pcmcia/cm4040_cs.c +++ b/trunk/drivers/char/pcmcia/cm4040_cs.c @@ -636,11 +636,8 @@ static int reader_probe(struct pcmcia_device *link) setup_timer(&dev->poll_timer, cm4040_do_poll, 0); ret = reader_config(link, i); - if (ret) { - dev_table[i] = NULL; - kfree(dev); + if (ret) return ret; - } class_device_create(cmx_class, NULL, MKDEV(major, i), NULL, "cmx%d", i); @@ -711,14 +708,12 @@ static int __init cm4040_init(void) if (major < 0) { printk(KERN_WARNING MODULE_NAME ": could not get major number\n"); - class_destroy(cmx_class); return major; } rc = pcmcia_register_driver(&reader_driver); if (rc < 0) { unregister_chrdev(major, DEVICE_NAME); - class_destroy(cmx_class); return rc; } diff --git a/trunk/drivers/char/tpm/Kconfig b/trunk/drivers/char/tpm/Kconfig index dc4e1ff7f56f..fe00c7dfb649 100644 --- a/trunk/drivers/char/tpm/Kconfig +++ b/trunk/drivers/char/tpm/Kconfig @@ -3,7 +3,6 @@ # menu "TPM devices" - depends on HAS_IOMEM config TCG_TPM tristate "TPM Hardware Support" @@ -34,7 +33,7 @@ config TCG_NSC tristate "National Semiconductor TPM Interface" depends on TCG_TPM && PNPACPI ---help--- - If you have a TPM security chip from National Semiconductor + If you have a TPM security chip from National Semicondutor say Yes and it will be accessible from within Linux. To compile this driver as a module, choose M here; the module will be called tpm_nsc. diff --git a/trunk/drivers/char/tty_io.c b/trunk/drivers/char/tty_io.c index fc662e4ce58a..7710a6a77d97 100644 --- a/trunk/drivers/char/tty_io.c +++ b/trunk/drivers/char/tty_io.c @@ -933,6 +933,13 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (ld == NULL) return -EINVAL; + /* + * No more input please, we are switching. The new ldisc + * will update this value in the ldisc open function + */ + + tty->receive_room = 0; + /* * Problem: What do we do if this blocks ? */ @@ -944,13 +951,6 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc) return 0; } - /* - * No more input please, we are switching. The new ldisc - * will update this value in the ldisc open function - */ - - tty->receive_room = 0; - o_ldisc = tty->ldisc; o_tty = tty->link; @@ -1573,11 +1573,11 @@ void no_tty(void) /** - * stop_tty - propagate flow control + * stop_tty - propogate flow control * @tty: tty to stop * * Perform flow control to the driver. For PTY/TTY pairs we - * must also propagate the TIOCKPKT status. May be called + * must also propogate the TIOCKPKT status. May be called * on an already stopped device and will not re-call the driver * method. * @@ -1607,11 +1607,11 @@ void stop_tty(struct tty_struct *tty) EXPORT_SYMBOL(stop_tty); /** - * start_tty - propagate flow control + * start_tty - propogate flow control * @tty: tty to start * * Start a tty that has been stopped if at all possible. Perform - * any neccessary wakeups and propagate the TIOCPKT status. If this + * any neccessary wakeups and propogate the TIOCPKT status. If this * is the tty was previous stopped and is being started then the * driver start method is invoked and the line discipline woken. * diff --git a/trunk/drivers/cpufreq/cpufreq.c b/trunk/drivers/cpufreq/cpufreq.c index eb37fba9b7ef..893dbaf386fb 100644 --- a/trunk/drivers/cpufreq/cpufreq.c +++ b/trunk/drivers/cpufreq/cpufreq.c @@ -1685,11 +1685,9 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, if (sys_dev) { switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: cpufreq_add_dev(sys_dev); break; case CPU_DOWN_PREPARE: - case CPU_DOWN_PREPARE_FROZEN: if (unlikely(lock_policy_rwsem_write(cpu))) BUG(); @@ -1701,7 +1699,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, __cpufreq_remove_dev(sys_dev); break; case CPU_DOWN_FAILED: - case CPU_DOWN_FAILED_FROZEN: cpufreq_add_dev(sys_dev); break; } diff --git a/trunk/drivers/cpufreq/cpufreq_stats.c b/trunk/drivers/cpufreq/cpufreq_stats.c index d2f0cbd8b8f3..d1c7cac9316c 100644 --- a/trunk/drivers/cpufreq/cpufreq_stats.c +++ b/trunk/drivers/cpufreq/cpufreq_stats.c @@ -313,11 +313,9 @@ static int cpufreq_stat_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: cpufreq_update_policy(cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: cpufreq_stats_free_table(cpu); break; } diff --git a/trunk/drivers/crypto/Kconfig b/trunk/drivers/crypto/Kconfig index e678a33ea672..f21fe66c9eef 100644 --- a/trunk/drivers/crypto/Kconfig +++ b/trunk/drivers/crypto/Kconfig @@ -51,31 +51,9 @@ config CRYPTO_DEV_GEODE default m help Say 'Y' here to use the AMD Geode LX processor on-board AES - engine for the CryptoAPI AES algorithm. + engine for the CryptoAPI AES alogrithm. To compile this driver as a module, choose M here: the module will be called geode-aes. -config ZCRYPT - tristate "Support for PCI-attached cryptographic adapters" - depends on S390 - select ZCRYPT_MONOLITHIC if ZCRYPT="y" - default "m" - help - Select this option if you want to use a PCI-attached cryptographic - adapter like: - + PCI Cryptographic Accelerator (PCICA) - + PCI Cryptographic Coprocessor (PCICC) - + PCI-X Cryptographic Coprocessor (PCIXCC) - + Crypto Express2 Coprocessor (CEX2C) - + Crypto Express2 Accelerator (CEX2A) - -config ZCRYPT_MONOLITHIC - bool "Monolithic zcrypt module" - depends on ZCRYPT="m" - help - Select this option if you want to have a single module z90crypt.ko - that contains all parts of the crypto device driver (ap bus, - request router and all the card drivers). - endmenu diff --git a/trunk/drivers/dma/Kconfig b/trunk/drivers/dma/Kconfig index 72be6c63edfc..30d021d1a07c 100644 --- a/trunk/drivers/dma/Kconfig +++ b/trunk/drivers/dma/Kconfig @@ -3,7 +3,6 @@ # menu "DMA Engine support" - depends on !S390 config DMA_ENGINE bool "Support for DMA engines" diff --git a/trunk/drivers/edac/Kconfig b/trunk/drivers/edac/Kconfig index 807c402df049..4f0898400c6d 100644 --- a/trunk/drivers/edac/Kconfig +++ b/trunk/drivers/edac/Kconfig @@ -7,7 +7,6 @@ # menu 'EDAC - error detection and reporting (RAS) (EXPERIMENTAL)' - depends on HAS_IOMEM config EDAC tristate "EDAC core system error reporting (EXPERIMENTAL)" diff --git a/trunk/drivers/firewire/Kconfig b/trunk/drivers/firewire/Kconfig deleted file mode 100644 index 5932c72f9e42..000000000000 --- a/trunk/drivers/firewire/Kconfig +++ /dev/null @@ -1,61 +0,0 @@ -# -*- shell-script -*- - -comment "An alternative FireWire stack is available with EXPERIMENTAL=y" - depends on EXPERIMENTAL=n - -config FIREWIRE - tristate "IEEE 1394 (FireWire) support (JUJU alternative stack, experimental)" - depends on EXPERIMENTAL - select CRC_ITU_T - help - IEEE 1394 describes a high performance serial bus, which is also - known as FireWire(tm) or i.Link(tm) and is used for connecting all - sorts of devices (most notably digital video cameras) to your - computer. - - If you have FireWire hardware and want to use it, say Y here. This - is the core support only, you will also need to select a driver for - your IEEE 1394 adapter. - - To compile this driver as a module, say M here: the module will be - called fw-core. - - This is the "JUJU" FireWire stack, an alternative implementation - designed for robustness and simplicity. You can build either this - stack, or the classic stack (the ieee1394 driver, ohci1394 etc.) - or both. - -config FIREWIRE_OHCI - tristate "Support for OHCI FireWire host controllers" - depends on PCI && FIREWIRE - help - Enable this driver if you have a FireWire controller based - on the OHCI specification. For all practical purposes, this - is the only chipset in use, so say Y here. - - To compile this driver as a module, say M here: The module will be - called fw-ohci. - - If you also build ohci1394 of the classic IEEE 1394 driver stack, - blacklist either ohci1394 or fw-ohci to let hotplug load the desired - driver. - -config FIREWIRE_SBP2 - tristate "Support for storage devices (SBP-2 protocol driver)" - depends on FIREWIRE && SCSI - help - This option enables you to use SBP-2 devices connected to a - FireWire bus. SBP-2 devices include storage devices like - harddisks and DVD drives, also some other FireWire devices - like scanners. - - To compile this driver as a module, say M here: The module will be - called fw-sbp2. - - You should also enable support for disks, CD-ROMs, etc. in the SCSI - configuration section. - - If you also build sbp2 of the classic IEEE 1394 driver stack, - blacklist either sbp2 or fw-sbp2 to let hotplug load the desired - driver. - diff --git a/trunk/drivers/firewire/Makefile b/trunk/drivers/firewire/Makefile deleted file mode 100644 index fc7d59d4bce0..000000000000 --- a/trunk/drivers/firewire/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for the Linux IEEE 1394 implementation -# - -fw-core-y += fw-card.o fw-topology.o fw-transaction.o fw-iso.o \ - fw-device.o fw-cdev.o - -obj-$(CONFIG_FIREWIRE) += fw-core.o -obj-$(CONFIG_FIREWIRE_OHCI) += fw-ohci.o -obj-$(CONFIG_FIREWIRE_SBP2) += fw-sbp2.o diff --git a/trunk/drivers/firewire/fw-card.c b/trunk/drivers/firewire/fw-card.c deleted file mode 100644 index 636151a64add..000000000000 --- a/trunk/drivers/firewire/fw-card.c +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Copyright (C) 2005-2007 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include -#include "fw-transaction.h" -#include "fw-topology.h" -#include "fw-device.h" - -int fw_compute_block_crc(u32 *block) -{ - __be32 be32_block[256]; - int i, length; - - length = (*block >> 16) & 0xff; - for (i = 0; i < length; i++) - be32_block[i] = cpu_to_be32(block[i + 1]); - *block |= crc_itu_t(0, (u8 *) be32_block, length * 4); - - return length; -} - -static DEFINE_MUTEX(card_mutex); -static LIST_HEAD(card_list); - -static LIST_HEAD(descriptor_list); -static int descriptor_count; - -#define BIB_CRC(v) ((v) << 0) -#define BIB_CRC_LENGTH(v) ((v) << 16) -#define BIB_INFO_LENGTH(v) ((v) << 24) - -#define BIB_LINK_SPEED(v) ((v) << 0) -#define BIB_GENERATION(v) ((v) << 4) -#define BIB_MAX_ROM(v) ((v) << 8) -#define BIB_MAX_RECEIVE(v) ((v) << 12) -#define BIB_CYC_CLK_ACC(v) ((v) << 16) -#define BIB_PMC ((1) << 27) -#define BIB_BMC ((1) << 28) -#define BIB_ISC ((1) << 29) -#define BIB_CMC ((1) << 30) -#define BIB_IMC ((1) << 31) - -static u32 * -generate_config_rom(struct fw_card *card, size_t *config_rom_length) -{ - struct fw_descriptor *desc; - static u32 config_rom[256]; - int i, j, length; - - /* - * Initialize contents of config rom buffer. On the OHCI - * controller, block reads to the config rom accesses the host - * memory, but quadlet read access the hardware bus info block - * registers. That's just crack, but it means we should make - * sure the contents of bus info block in host memory mathces - * the version stored in the OHCI registers. - */ - - memset(config_rom, 0, sizeof(config_rom)); - config_rom[0] = BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0); - config_rom[1] = 0x31333934; - - config_rom[2] = - BIB_LINK_SPEED(card->link_speed) | - BIB_GENERATION(card->config_rom_generation++ % 14 + 2) | - BIB_MAX_ROM(2) | - BIB_MAX_RECEIVE(card->max_receive) | - BIB_BMC | BIB_ISC | BIB_CMC | BIB_IMC; - config_rom[3] = card->guid >> 32; - config_rom[4] = card->guid; - - /* Generate root directory. */ - i = 5; - config_rom[i++] = 0; - config_rom[i++] = 0x0c0083c0; /* node capabilities */ - j = i + descriptor_count; - - /* Generate root directory entries for descriptors. */ - list_for_each_entry (desc, &descriptor_list, link) { - if (desc->immediate > 0) - config_rom[i++] = desc->immediate; - config_rom[i] = desc->key | (j - i); - i++; - j += desc->length; - } - - /* Update root directory length. */ - config_rom[5] = (i - 5 - 1) << 16; - - /* End of root directory, now copy in descriptors. */ - list_for_each_entry (desc, &descriptor_list, link) { - memcpy(&config_rom[i], desc->data, desc->length * 4); - i += desc->length; - } - - /* Calculate CRCs for all blocks in the config rom. This - * assumes that CRC length and info length are identical for - * the bus info block, which is always the case for this - * implementation. */ - for (i = 0; i < j; i += length + 1) - length = fw_compute_block_crc(config_rom + i); - - *config_rom_length = j; - - return config_rom; -} - -static void -update_config_roms(void) -{ - struct fw_card *card; - u32 *config_rom; - size_t length; - - list_for_each_entry (card, &card_list, link) { - config_rom = generate_config_rom(card, &length); - card->driver->set_config_rom(card, config_rom, length); - } -} - -int -fw_core_add_descriptor(struct fw_descriptor *desc) -{ - size_t i; - - /* - * Check descriptor is valid; the length of all blocks in the - * descriptor has to add up to exactly the length of the - * block. - */ - i = 0; - while (i < desc->length) - i += (desc->data[i] >> 16) + 1; - - if (i != desc->length) - return -EINVAL; - - mutex_lock(&card_mutex); - - list_add_tail(&desc->link, &descriptor_list); - descriptor_count++; - if (desc->immediate > 0) - descriptor_count++; - update_config_roms(); - - mutex_unlock(&card_mutex); - - return 0; -} -EXPORT_SYMBOL(fw_core_add_descriptor); - -void -fw_core_remove_descriptor(struct fw_descriptor *desc) -{ - mutex_lock(&card_mutex); - - list_del(&desc->link); - descriptor_count--; - if (desc->immediate > 0) - descriptor_count--; - update_config_roms(); - - mutex_unlock(&card_mutex); -} -EXPORT_SYMBOL(fw_core_remove_descriptor); - -static const char gap_count_table[] = { - 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 -}; - -struct bm_data { - struct fw_transaction t; - struct { - __be32 arg; - __be32 data; - } lock; - u32 old; - int rcode; - struct completion done; -}; - -static void -complete_bm_lock(struct fw_card *card, int rcode, - void *payload, size_t length, void *data) -{ - struct bm_data *bmd = data; - - if (rcode == RCODE_COMPLETE) - bmd->old = be32_to_cpu(*(__be32 *) payload); - bmd->rcode = rcode; - complete(&bmd->done); -} - -static void -fw_card_bm_work(struct work_struct *work) -{ - struct fw_card *card = container_of(work, struct fw_card, work.work); - struct fw_device *root; - struct bm_data bmd; - unsigned long flags; - int root_id, new_root_id, irm_id, gap_count, generation, grace; - int do_reset = 0; - - spin_lock_irqsave(&card->lock, flags); - - generation = card->generation; - root = card->root_node->data; - root_id = card->root_node->node_id; - grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 10)); - - if (card->bm_generation + 1 == generation || - (card->bm_generation != generation && grace)) { - /* - * This first step is to figure out who is IRM and - * then try to become bus manager. If the IRM is not - * well defined (e.g. does not have an active link - * layer or does not responds to our lock request, we - * will have to do a little vigilante bus management. - * In that case, we do a goto into the gap count logic - * so that when we do the reset, we still optimize the - * gap count. That could well save a reset in the - * next generation. - */ - - irm_id = card->irm_node->node_id; - if (!card->irm_node->link_on) { - new_root_id = card->local_node->node_id; - fw_notify("IRM has link off, making local node (%02x) root.\n", - new_root_id); - goto pick_me; - } - - bmd.lock.arg = cpu_to_be32(0x3f); - bmd.lock.data = cpu_to_be32(card->local_node->node_id); - - spin_unlock_irqrestore(&card->lock, flags); - - init_completion(&bmd.done); - fw_send_request(card, &bmd.t, TCODE_LOCK_COMPARE_SWAP, - irm_id, generation, - SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, - &bmd.lock, sizeof(bmd.lock), - complete_bm_lock, &bmd); - wait_for_completion(&bmd.done); - - if (bmd.rcode == RCODE_GENERATION) { - /* - * Another bus reset happened. Just return, - * the BM work has been rescheduled. - */ - return; - } - - if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f) - /* Somebody else is BM, let them do the work. */ - return; - - spin_lock_irqsave(&card->lock, flags); - if (bmd.rcode != RCODE_COMPLETE) { - /* - * The lock request failed, maybe the IRM - * isn't really IRM capable after all. Let's - * do a bus reset and pick the local node as - * root, and thus, IRM. - */ - new_root_id = card->local_node->node_id; - fw_notify("BM lock failed, making local node (%02x) root.\n", - new_root_id); - goto pick_me; - } - } else if (card->bm_generation != generation) { - /* - * OK, we weren't BM in the last generation, and it's - * less than 100ms since last bus reset. Reschedule - * this task 100ms from now. - */ - spin_unlock_irqrestore(&card->lock, flags); - schedule_delayed_work(&card->work, DIV_ROUND_UP(HZ, 10)); - return; - } - - /* - * We're bus manager for this generation, so next step is to - * make sure we have an active cycle master and do gap count - * optimization. - */ - card->bm_generation = generation; - - if (root == NULL) { - /* - * Either link_on is false, or we failed to read the - * config rom. In either case, pick another root. - */ - new_root_id = card->local_node->node_id; - } else if (atomic_read(&root->state) != FW_DEVICE_RUNNING) { - /* - * If we haven't probed this device yet, bail out now - * and let's try again once that's done. - */ - spin_unlock_irqrestore(&card->lock, flags); - return; - } else if (root->config_rom[2] & BIB_CMC) { - /* - * FIXME: I suppose we should set the cmstr bit in the - * STATE_CLEAR register of this node, as described in - * 1394-1995, 8.4.2.6. Also, send out a force root - * packet for this node. - */ - new_root_id = root_id; - } else { - /* - * Current root has an active link layer and we - * successfully read the config rom, but it's not - * cycle master capable. - */ - new_root_id = card->local_node->node_id; - } - - pick_me: - /* Now figure out what gap count to set. */ - if (card->topology_type == FW_TOPOLOGY_A && - card->root_node->max_hops < ARRAY_SIZE(gap_count_table)) - gap_count = gap_count_table[card->root_node->max_hops]; - else - gap_count = 63; - - /* - * Finally, figure out if we should do a reset or not. If we've - * done less that 5 resets with the same physical topology and we - * have either a new root or a new gap count setting, let's do it. - */ - - if (card->bm_retries++ < 5 && - (card->gap_count != gap_count || new_root_id != root_id)) - do_reset = 1; - - spin_unlock_irqrestore(&card->lock, flags); - - if (do_reset) { - fw_notify("phy config: card %d, new root=%x, gap_count=%d\n", - card->index, new_root_id, gap_count); - fw_send_phy_config(card, new_root_id, generation, gap_count); - fw_core_initiate_bus_reset(card, 1); - } -} - -static void -flush_timer_callback(unsigned long data) -{ - struct fw_card *card = (struct fw_card *)data; - - fw_flush_transactions(card); -} - -void -fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, - struct device *device) -{ - static atomic_t index = ATOMIC_INIT(-1); - - kref_init(&card->kref); - card->index = atomic_inc_return(&index); - card->driver = driver; - card->device = device; - card->current_tlabel = 0; - card->tlabel_mask = 0; - card->color = 0; - - INIT_LIST_HEAD(&card->transaction_list); - spin_lock_init(&card->lock); - setup_timer(&card->flush_timer, - flush_timer_callback, (unsigned long)card); - - card->local_node = NULL; - - INIT_DELAYED_WORK(&card->work, fw_card_bm_work); -} -EXPORT_SYMBOL(fw_card_initialize); - -int -fw_card_add(struct fw_card *card, - u32 max_receive, u32 link_speed, u64 guid) -{ - u32 *config_rom; - size_t length; - - card->max_receive = max_receive; - card->link_speed = link_speed; - card->guid = guid; - - /* Activate link_on bit and contender bit in our self ID packets.*/ - if (card->driver->update_phy_reg(card, 4, 0, - PHY_LINK_ACTIVE | PHY_CONTENDER) < 0) - return -EIO; - - /* - * The subsystem grabs a reference when the card is added and - * drops it when the driver calls fw_core_remove_card. - */ - fw_card_get(card); - - mutex_lock(&card_mutex); - config_rom = generate_config_rom(card, &length); - list_add_tail(&card->link, &card_list); - mutex_unlock(&card_mutex); - - return card->driver->enable(card, config_rom, length); -} -EXPORT_SYMBOL(fw_card_add); - - -/* - * The next few functions implements a dummy driver that use once a - * card driver shuts down an fw_card. This allows the driver to - * cleanly unload, as all IO to the card will be handled by the dummy - * driver instead of calling into the (possibly) unloaded module. The - * dummy driver just fails all IO. - */ - -static int -dummy_enable(struct fw_card *card, u32 *config_rom, size_t length) -{ - BUG(); - return -1; -} - -static int -dummy_update_phy_reg(struct fw_card *card, int address, - int clear_bits, int set_bits) -{ - return -ENODEV; -} - -static int -dummy_set_config_rom(struct fw_card *card, - u32 *config_rom, size_t length) -{ - /* - * We take the card out of card_list before setting the dummy - * driver, so this should never get called. - */ - BUG(); - return -1; -} - -static void -dummy_send_request(struct fw_card *card, struct fw_packet *packet) -{ - packet->callback(packet, card, -ENODEV); -} - -static void -dummy_send_response(struct fw_card *card, struct fw_packet *packet) -{ - packet->callback(packet, card, -ENODEV); -} - -static int -dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet) -{ - return -ENOENT; -} - -static int -dummy_enable_phys_dma(struct fw_card *card, - int node_id, int generation) -{ - return -ENODEV; -} - -static struct fw_card_driver dummy_driver = { - .name = "dummy", - .enable = dummy_enable, - .update_phy_reg = dummy_update_phy_reg, - .set_config_rom = dummy_set_config_rom, - .send_request = dummy_send_request, - .cancel_packet = dummy_cancel_packet, - .send_response = dummy_send_response, - .enable_phys_dma = dummy_enable_phys_dma, -}; - -void -fw_core_remove_card(struct fw_card *card) -{ - card->driver->update_phy_reg(card, 4, - PHY_LINK_ACTIVE | PHY_CONTENDER, 0); - fw_core_initiate_bus_reset(card, 1); - - mutex_lock(&card_mutex); - list_del(&card->link); - mutex_unlock(&card_mutex); - - /* Set up the dummy driver. */ - card->driver = &dummy_driver; - - fw_flush_transactions(card); - - fw_destroy_nodes(card); - - fw_card_put(card); -} -EXPORT_SYMBOL(fw_core_remove_card); - -struct fw_card * -fw_card_get(struct fw_card *card) -{ - kref_get(&card->kref); - - return card; -} -EXPORT_SYMBOL(fw_card_get); - -static void -release_card(struct kref *kref) -{ - struct fw_card *card = container_of(kref, struct fw_card, kref); - - kfree(card); -} - -/* - * An assumption for fw_card_put() is that the card driver allocates - * the fw_card struct with kalloc and that it has been shut down - * before the last ref is dropped. - */ -void -fw_card_put(struct fw_card *card) -{ - kref_put(&card->kref, release_card); -} -EXPORT_SYMBOL(fw_card_put); - -int -fw_core_initiate_bus_reset(struct fw_card *card, int short_reset) -{ - int reg = short_reset ? 5 : 1; - int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET; - - return card->driver->update_phy_reg(card, reg, 0, bit); -} -EXPORT_SYMBOL(fw_core_initiate_bus_reset); diff --git a/trunk/drivers/firewire/fw-cdev.c b/trunk/drivers/firewire/fw-cdev.c deleted file mode 100644 index 0fa5bd54c6a1..000000000000 --- a/trunk/drivers/firewire/fw-cdev.c +++ /dev/null @@ -1,961 +0,0 @@ -/* - * Char device for device raw access - * - * Copyright (C) 2005-2007 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "fw-transaction.h" -#include "fw-topology.h" -#include "fw-device.h" - -struct client; -struct client_resource { - struct list_head link; - void (*release)(struct client *client, struct client_resource *r); - u32 handle; -}; - -/* - * dequeue_event() just kfree()'s the event, so the event has to be - * the first field in the struct. - */ - -struct event { - struct { void *data; size_t size; } v[2]; - struct list_head link; -}; - -struct bus_reset { - struct event event; - struct fw_cdev_event_bus_reset reset; -}; - -struct response { - struct event event; - struct fw_transaction transaction; - struct client *client; - struct client_resource resource; - struct fw_cdev_event_response response; -}; - -struct iso_interrupt { - struct event event; - struct fw_cdev_event_iso_interrupt interrupt; -}; - -struct client { - u32 version; - struct fw_device *device; - spinlock_t lock; - u32 resource_handle; - struct list_head resource_list; - struct list_head event_list; - wait_queue_head_t wait; - u64 bus_reset_closure; - - struct fw_iso_context *iso_context; - u64 iso_closure; - struct fw_iso_buffer buffer; - unsigned long vm_start; - - struct list_head link; -}; - -static inline void __user * -u64_to_uptr(__u64 value) -{ - return (void __user *)(unsigned long)value; -} - -static inline __u64 -uptr_to_u64(void __user *ptr) -{ - return (__u64)(unsigned long)ptr; -} - -static int fw_device_op_open(struct inode *inode, struct file *file) -{ - struct fw_device *device; - struct client *client; - unsigned long flags; - - device = fw_device_from_devt(inode->i_rdev); - if (device == NULL) - return -ENODEV; - - client = kzalloc(sizeof(*client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - - client->device = fw_device_get(device); - INIT_LIST_HEAD(&client->event_list); - INIT_LIST_HEAD(&client->resource_list); - spin_lock_init(&client->lock); - init_waitqueue_head(&client->wait); - - file->private_data = client; - - spin_lock_irqsave(&device->card->lock, flags); - list_add_tail(&client->link, &device->client_list); - spin_unlock_irqrestore(&device->card->lock, flags); - - return 0; -} - -static void queue_event(struct client *client, struct event *event, - void *data0, size_t size0, void *data1, size_t size1) -{ - unsigned long flags; - - event->v[0].data = data0; - event->v[0].size = size0; - event->v[1].data = data1; - event->v[1].size = size1; - - spin_lock_irqsave(&client->lock, flags); - - list_add_tail(&event->link, &client->event_list); - wake_up_interruptible(&client->wait); - - spin_unlock_irqrestore(&client->lock, flags); -} - -static int -dequeue_event(struct client *client, char __user *buffer, size_t count) -{ - unsigned long flags; - struct event *event; - size_t size, total; - int i, retval; - - retval = wait_event_interruptible(client->wait, - !list_empty(&client->event_list) || - fw_device_is_shutdown(client->device)); - if (retval < 0) - return retval; - - if (list_empty(&client->event_list) && - fw_device_is_shutdown(client->device)) - return -ENODEV; - - spin_lock_irqsave(&client->lock, flags); - event = container_of(client->event_list.next, struct event, link); - list_del(&event->link); - spin_unlock_irqrestore(&client->lock, flags); - - total = 0; - for (i = 0; i < ARRAY_SIZE(event->v) && total < count; i++) { - size = min(event->v[i].size, count - total); - if (copy_to_user(buffer + total, event->v[i].data, size)) { - retval = -EFAULT; - goto out; - } - total += size; - } - retval = total; - - out: - kfree(event); - - return retval; -} - -static ssize_t -fw_device_op_read(struct file *file, - char __user *buffer, size_t count, loff_t *offset) -{ - struct client *client = file->private_data; - - return dequeue_event(client, buffer, count); -} - -static void -fill_bus_reset_event(struct fw_cdev_event_bus_reset *event, - struct client *client) -{ - struct fw_card *card = client->device->card; - - event->closure = client->bus_reset_closure; - event->type = FW_CDEV_EVENT_BUS_RESET; - event->node_id = client->device->node_id; - event->local_node_id = card->local_node->node_id; - event->bm_node_id = 0; /* FIXME: We don't track the BM. */ - event->irm_node_id = card->irm_node->node_id; - event->root_node_id = card->root_node->node_id; - event->generation = card->generation; -} - -static void -for_each_client(struct fw_device *device, - void (*callback)(struct client *client)) -{ - struct fw_card *card = device->card; - struct client *c; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - - list_for_each_entry(c, &device->client_list, link) - callback(c); - - spin_unlock_irqrestore(&card->lock, flags); -} - -static void -queue_bus_reset_event(struct client *client) -{ - struct bus_reset *bus_reset; - - bus_reset = kzalloc(sizeof(*bus_reset), GFP_ATOMIC); - if (bus_reset == NULL) { - fw_notify("Out of memory when allocating bus reset event\n"); - return; - } - - fill_bus_reset_event(&bus_reset->reset, client); - - queue_event(client, &bus_reset->event, - &bus_reset->reset, sizeof(bus_reset->reset), NULL, 0); -} - -void fw_device_cdev_update(struct fw_device *device) -{ - for_each_client(device, queue_bus_reset_event); -} - -static void wake_up_client(struct client *client) -{ - wake_up_interruptible(&client->wait); -} - -void fw_device_cdev_remove(struct fw_device *device) -{ - for_each_client(device, wake_up_client); -} - -static int ioctl_get_info(struct client *client, void *buffer) -{ - struct fw_cdev_get_info *get_info = buffer; - struct fw_cdev_event_bus_reset bus_reset; - - client->version = get_info->version; - get_info->version = FW_CDEV_VERSION; - - if (get_info->rom != 0) { - void __user *uptr = u64_to_uptr(get_info->rom); - size_t want = get_info->rom_length; - size_t have = client->device->config_rom_length * 4; - - if (copy_to_user(uptr, client->device->config_rom, - min(want, have))) - return -EFAULT; - } - get_info->rom_length = client->device->config_rom_length * 4; - - client->bus_reset_closure = get_info->bus_reset_closure; - if (get_info->bus_reset != 0) { - void __user *uptr = u64_to_uptr(get_info->bus_reset); - - fill_bus_reset_event(&bus_reset, client); - if (copy_to_user(uptr, &bus_reset, sizeof(bus_reset))) - return -EFAULT; - } - - get_info->card = client->device->card->index; - - return 0; -} - -static void -add_client_resource(struct client *client, struct client_resource *resource) -{ - unsigned long flags; - - spin_lock_irqsave(&client->lock, flags); - list_add_tail(&resource->link, &client->resource_list); - resource->handle = client->resource_handle++; - spin_unlock_irqrestore(&client->lock, flags); -} - -static int -release_client_resource(struct client *client, u32 handle, - struct client_resource **resource) -{ - struct client_resource *r; - unsigned long flags; - - spin_lock_irqsave(&client->lock, flags); - list_for_each_entry(r, &client->resource_list, link) { - if (r->handle == handle) { - list_del(&r->link); - break; - } - } - spin_unlock_irqrestore(&client->lock, flags); - - if (&r->link == &client->resource_list) - return -EINVAL; - - if (resource) - *resource = r; - else - r->release(client, r); - - return 0; -} - -static void -release_transaction(struct client *client, struct client_resource *resource) -{ - struct response *response = - container_of(resource, struct response, resource); - - fw_cancel_transaction(client->device->card, &response->transaction); -} - -static void -complete_transaction(struct fw_card *card, int rcode, - void *payload, size_t length, void *data) -{ - struct response *response = data; - struct client *client = response->client; - unsigned long flags; - - if (length < response->response.length) - response->response.length = length; - if (rcode == RCODE_COMPLETE) - memcpy(response->response.data, payload, - response->response.length); - - spin_lock_irqsave(&client->lock, flags); - list_del(&response->resource.link); - spin_unlock_irqrestore(&client->lock, flags); - - response->response.type = FW_CDEV_EVENT_RESPONSE; - response->response.rcode = rcode; - queue_event(client, &response->event, - &response->response, sizeof(response->response), - response->response.data, response->response.length); -} - -static ssize_t ioctl_send_request(struct client *client, void *buffer) -{ - struct fw_device *device = client->device; - struct fw_cdev_send_request *request = buffer; - struct response *response; - - /* What is the biggest size we'll accept, really? */ - if (request->length > 4096) - return -EINVAL; - - response = kmalloc(sizeof(*response) + request->length, GFP_KERNEL); - if (response == NULL) - return -ENOMEM; - - response->client = client; - response->response.length = request->length; - response->response.closure = request->closure; - - if (request->data && - copy_from_user(response->response.data, - u64_to_uptr(request->data), request->length)) { - kfree(response); - return -EFAULT; - } - - response->resource.release = release_transaction; - add_client_resource(client, &response->resource); - - fw_send_request(device->card, &response->transaction, - request->tcode & 0x1f, - device->node->node_id, - request->generation, - device->node->max_speed, - request->offset, - response->response.data, request->length, - complete_transaction, response); - - if (request->data) - return sizeof(request) + request->length; - else - return sizeof(request); -} - -struct address_handler { - struct fw_address_handler handler; - __u64 closure; - struct client *client; - struct client_resource resource; -}; - -struct request { - struct fw_request *request; - void *data; - size_t length; - struct client_resource resource; -}; - -struct request_event { - struct event event; - struct fw_cdev_event_request request; -}; - -static void -release_request(struct client *client, struct client_resource *resource) -{ - struct request *request = - container_of(resource, struct request, resource); - - fw_send_response(client->device->card, request->request, - RCODE_CONFLICT_ERROR); - kfree(request); -} - -static void -handle_request(struct fw_card *card, struct fw_request *r, - int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, - void *payload, size_t length, void *callback_data) -{ - struct address_handler *handler = callback_data; - struct request *request; - struct request_event *e; - struct client *client = handler->client; - - request = kmalloc(sizeof(*request), GFP_ATOMIC); - e = kmalloc(sizeof(*e), GFP_ATOMIC); - if (request == NULL || e == NULL) { - kfree(request); - kfree(e); - fw_send_response(card, r, RCODE_CONFLICT_ERROR); - return; - } - - request->request = r; - request->data = payload; - request->length = length; - - request->resource.release = release_request; - add_client_resource(client, &request->resource); - - e->request.type = FW_CDEV_EVENT_REQUEST; - e->request.tcode = tcode; - e->request.offset = offset; - e->request.length = length; - e->request.handle = request->resource.handle; - e->request.closure = handler->closure; - - queue_event(client, &e->event, - &e->request, sizeof(e->request), payload, length); -} - -static void -release_address_handler(struct client *client, - struct client_resource *resource) -{ - struct address_handler *handler = - container_of(resource, struct address_handler, resource); - - fw_core_remove_address_handler(&handler->handler); - kfree(handler); -} - -static int ioctl_allocate(struct client *client, void *buffer) -{ - struct fw_cdev_allocate *request = buffer; - struct address_handler *handler; - struct fw_address_region region; - - handler = kmalloc(sizeof(*handler), GFP_KERNEL); - if (handler == NULL) - return -ENOMEM; - - region.start = request->offset; - region.end = request->offset + request->length; - handler->handler.length = request->length; - handler->handler.address_callback = handle_request; - handler->handler.callback_data = handler; - handler->closure = request->closure; - handler->client = client; - - if (fw_core_add_address_handler(&handler->handler, ®ion) < 0) { - kfree(handler); - return -EBUSY; - } - - handler->resource.release = release_address_handler; - add_client_resource(client, &handler->resource); - request->handle = handler->resource.handle; - - return 0; -} - -static int ioctl_deallocate(struct client *client, void *buffer) -{ - struct fw_cdev_deallocate *request = buffer; - - return release_client_resource(client, request->handle, NULL); -} - -static int ioctl_send_response(struct client *client, void *buffer) -{ - struct fw_cdev_send_response *request = buffer; - struct client_resource *resource; - struct request *r; - - if (release_client_resource(client, request->handle, &resource) < 0) - return -EINVAL; - r = container_of(resource, struct request, resource); - if (request->length < r->length) - r->length = request->length; - if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) - return -EFAULT; - - fw_send_response(client->device->card, r->request, request->rcode); - kfree(r); - - return 0; -} - -static int ioctl_initiate_bus_reset(struct client *client, void *buffer) -{ - struct fw_cdev_initiate_bus_reset *request = buffer; - int short_reset; - - short_reset = (request->type == FW_CDEV_SHORT_RESET); - - return fw_core_initiate_bus_reset(client->device->card, short_reset); -} - -struct descriptor { - struct fw_descriptor d; - struct client_resource resource; - u32 data[0]; -}; - -static void release_descriptor(struct client *client, - struct client_resource *resource) -{ - struct descriptor *descriptor = - container_of(resource, struct descriptor, resource); - - fw_core_remove_descriptor(&descriptor->d); - kfree(descriptor); -} - -static int ioctl_add_descriptor(struct client *client, void *buffer) -{ - struct fw_cdev_add_descriptor *request = buffer; - struct descriptor *descriptor; - int retval; - - if (request->length > 256) - return -EINVAL; - - descriptor = - kmalloc(sizeof(*descriptor) + request->length * 4, GFP_KERNEL); - if (descriptor == NULL) - return -ENOMEM; - - if (copy_from_user(descriptor->data, - u64_to_uptr(request->data), request->length * 4)) { - kfree(descriptor); - return -EFAULT; - } - - descriptor->d.length = request->length; - descriptor->d.immediate = request->immediate; - descriptor->d.key = request->key; - descriptor->d.data = descriptor->data; - - retval = fw_core_add_descriptor(&descriptor->d); - if (retval < 0) { - kfree(descriptor); - return retval; - } - - descriptor->resource.release = release_descriptor; - add_client_resource(client, &descriptor->resource); - request->handle = descriptor->resource.handle; - - return 0; -} - -static int ioctl_remove_descriptor(struct client *client, void *buffer) -{ - struct fw_cdev_remove_descriptor *request = buffer; - - return release_client_resource(client, request->handle, NULL); -} - -static void -iso_callback(struct fw_iso_context *context, u32 cycle, - size_t header_length, void *header, void *data) -{ - struct client *client = data; - struct iso_interrupt *interrupt; - - interrupt = kzalloc(sizeof(*interrupt) + header_length, GFP_ATOMIC); - if (interrupt == NULL) - return; - - interrupt->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; - interrupt->interrupt.closure = client->iso_closure; - interrupt->interrupt.cycle = cycle; - interrupt->interrupt.header_length = header_length; - memcpy(interrupt->interrupt.header, header, header_length); - queue_event(client, &interrupt->event, - &interrupt->interrupt, - sizeof(interrupt->interrupt) + header_length, NULL, 0); -} - -static int ioctl_create_iso_context(struct client *client, void *buffer) -{ - struct fw_cdev_create_iso_context *request = buffer; - - if (request->channel > 63) - return -EINVAL; - - switch (request->type) { - case FW_ISO_CONTEXT_RECEIVE: - if (request->header_size < 4 || (request->header_size & 3)) - return -EINVAL; - - break; - - case FW_ISO_CONTEXT_TRANSMIT: - if (request->speed > SCODE_3200) - return -EINVAL; - - break; - - default: - return -EINVAL; - } - - client->iso_closure = request->closure; - client->iso_context = fw_iso_context_create(client->device->card, - request->type, - request->channel, - request->speed, - request->header_size, - iso_callback, client); - if (IS_ERR(client->iso_context)) - return PTR_ERR(client->iso_context); - - /* We only support one context at this time. */ - request->handle = 0; - - return 0; -} - -static int ioctl_queue_iso(struct client *client, void *buffer) -{ - struct fw_cdev_queue_iso *request = buffer; - struct fw_cdev_iso_packet __user *p, *end, *next; - struct fw_iso_context *ctx = client->iso_context; - unsigned long payload, buffer_end, header_length; - int count; - struct { - struct fw_iso_packet packet; - u8 header[256]; - } u; - - if (ctx == NULL || request->handle != 0) - return -EINVAL; - - /* - * If the user passes a non-NULL data pointer, has mmap()'ed - * the iso buffer, and the pointer points inside the buffer, - * we setup the payload pointers accordingly. Otherwise we - * set them both to 0, which will still let packets with - * payload_length == 0 through. In other words, if no packets - * use the indirect payload, the iso buffer need not be mapped - * and the request->data pointer is ignored. - */ - - payload = (unsigned long)request->data - client->vm_start; - buffer_end = client->buffer.page_count << PAGE_SHIFT; - if (request->data == 0 || client->buffer.pages == NULL || - payload >= buffer_end) { - payload = 0; - buffer_end = 0; - } - - if (!access_ok(VERIFY_READ, request->packets, request->size)) - return -EFAULT; - - p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(request->packets); - end = (void __user *)p + request->size; - count = 0; - while (p < end) { - if (__copy_from_user(&u.packet, p, sizeof(*p))) - return -EFAULT; - - if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) { - header_length = u.packet.header_length; - } else { - /* - * We require that header_length is a multiple of - * the fixed header size, ctx->header_size. - */ - if (ctx->header_size == 0) { - if (u.packet.header_length > 0) - return -EINVAL; - } else if (u.packet.header_length % ctx->header_size != 0) { - return -EINVAL; - } - header_length = 0; - } - - next = (struct fw_cdev_iso_packet __user *) - &p->header[header_length / 4]; - if (next > end) - return -EINVAL; - if (__copy_from_user - (u.packet.header, p->header, header_length)) - return -EFAULT; - if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT && - u.packet.header_length + u.packet.payload_length > 0) - return -EINVAL; - if (payload + u.packet.payload_length > buffer_end) - return -EINVAL; - - if (fw_iso_context_queue(ctx, &u.packet, - &client->buffer, payload)) - break; - - p = next; - payload += u.packet.payload_length; - count++; - } - - request->size -= uptr_to_u64(p) - request->packets; - request->packets = uptr_to_u64(p); - request->data = client->vm_start + payload; - - return count; -} - -static int ioctl_start_iso(struct client *client, void *buffer) -{ - struct fw_cdev_start_iso *request = buffer; - - if (request->handle != 0) - return -EINVAL; - if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE) { - if (request->tags == 0 || request->tags > 15) - return -EINVAL; - - if (request->sync > 15) - return -EINVAL; - } - - return fw_iso_context_start(client->iso_context, request->cycle, - request->sync, request->tags); -} - -static int ioctl_stop_iso(struct client *client, void *buffer) -{ - struct fw_cdev_stop_iso *request = buffer; - - if (request->handle != 0) - return -EINVAL; - - return fw_iso_context_stop(client->iso_context); -} - -static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { - ioctl_get_info, - ioctl_send_request, - ioctl_allocate, - ioctl_deallocate, - ioctl_send_response, - ioctl_initiate_bus_reset, - ioctl_add_descriptor, - ioctl_remove_descriptor, - ioctl_create_iso_context, - ioctl_queue_iso, - ioctl_start_iso, - ioctl_stop_iso, -}; - -static int -dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) -{ - char buffer[256]; - int retval; - - if (_IOC_TYPE(cmd) != '#' || - _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers)) - return -EINVAL; - - if (_IOC_DIR(cmd) & _IOC_WRITE) { - if (_IOC_SIZE(cmd) > sizeof(buffer) || - copy_from_user(buffer, arg, _IOC_SIZE(cmd))) - return -EFAULT; - } - - retval = ioctl_handlers[_IOC_NR(cmd)](client, buffer); - if (retval < 0) - return retval; - - if (_IOC_DIR(cmd) & _IOC_READ) { - if (_IOC_SIZE(cmd) > sizeof(buffer) || - copy_to_user(arg, buffer, _IOC_SIZE(cmd))) - return -EFAULT; - } - - return 0; -} - -static long -fw_device_op_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct client *client = file->private_data; - - return dispatch_ioctl(client, cmd, (void __user *) arg); -} - -#ifdef CONFIG_COMPAT -static long -fw_device_op_compat_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct client *client = file->private_data; - - return dispatch_ioctl(client, cmd, compat_ptr(arg)); -} -#endif - -static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct client *client = file->private_data; - enum dma_data_direction direction; - unsigned long size; - int page_count, retval; - - /* FIXME: We could support multiple buffers, but we don't. */ - if (client->buffer.pages != NULL) - return -EBUSY; - - if (!(vma->vm_flags & VM_SHARED)) - return -EINVAL; - - if (vma->vm_start & ~PAGE_MASK) - return -EINVAL; - - client->vm_start = vma->vm_start; - size = vma->vm_end - vma->vm_start; - page_count = size >> PAGE_SHIFT; - if (size & ~PAGE_MASK) - return -EINVAL; - - if (vma->vm_flags & VM_WRITE) - direction = DMA_TO_DEVICE; - else - direction = DMA_FROM_DEVICE; - - retval = fw_iso_buffer_init(&client->buffer, client->device->card, - page_count, direction); - if (retval < 0) - return retval; - - retval = fw_iso_buffer_map(&client->buffer, vma); - if (retval < 0) - fw_iso_buffer_destroy(&client->buffer, client->device->card); - - return retval; -} - -static int fw_device_op_release(struct inode *inode, struct file *file) -{ - struct client *client = file->private_data; - struct event *e, *next_e; - struct client_resource *r, *next_r; - unsigned long flags; - - if (client->buffer.pages) - fw_iso_buffer_destroy(&client->buffer, client->device->card); - - if (client->iso_context) - fw_iso_context_destroy(client->iso_context); - - list_for_each_entry_safe(r, next_r, &client->resource_list, link) - r->release(client, r); - - /* - * FIXME: We should wait for the async tasklets to stop - * running before freeing the memory. - */ - - list_for_each_entry_safe(e, next_e, &client->event_list, link) - kfree(e); - - spin_lock_irqsave(&client->device->card->lock, flags); - list_del(&client->link); - spin_unlock_irqrestore(&client->device->card->lock, flags); - - fw_device_put(client->device); - kfree(client); - - return 0; -} - -static unsigned int fw_device_op_poll(struct file *file, poll_table * pt) -{ - struct client *client = file->private_data; - unsigned int mask = 0; - - poll_wait(file, &client->wait, pt); - - if (fw_device_is_shutdown(client->device)) - mask |= POLLHUP | POLLERR; - if (!list_empty(&client->event_list)) - mask |= POLLIN | POLLRDNORM; - - return mask; -} - -const struct file_operations fw_device_ops = { - .owner = THIS_MODULE, - .open = fw_device_op_open, - .read = fw_device_op_read, - .unlocked_ioctl = fw_device_op_ioctl, - .poll = fw_device_op_poll, - .release = fw_device_op_release, - .mmap = fw_device_op_mmap, - -#ifdef CONFIG_COMPAT - .compat_ioctl = fw_device_op_compat_ioctl, -#endif -}; diff --git a/trunk/drivers/firewire/fw-device.c b/trunk/drivers/firewire/fw-device.c deleted file mode 100644 index c1ce465d9710..000000000000 --- a/trunk/drivers/firewire/fw-device.c +++ /dev/null @@ -1,813 +0,0 @@ -/* - * Device probing and sysfs code. - * - * Copyright (C) 2005-2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "fw-transaction.h" -#include "fw-topology.h" -#include "fw-device.h" - -void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 * p) -{ - ci->p = p + 1; - ci->end = ci->p + (p[0] >> 16); -} -EXPORT_SYMBOL(fw_csr_iterator_init); - -int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value) -{ - *key = *ci->p >> 24; - *value = *ci->p & 0xffffff; - - return ci->p++ < ci->end; -} -EXPORT_SYMBOL(fw_csr_iterator_next); - -static int is_fw_unit(struct device *dev); - -static int match_unit_directory(u32 * directory, const struct fw_device_id *id) -{ - struct fw_csr_iterator ci; - int key, value, match; - - match = 0; - fw_csr_iterator_init(&ci, directory); - while (fw_csr_iterator_next(&ci, &key, &value)) { - if (key == CSR_VENDOR && value == id->vendor) - match |= FW_MATCH_VENDOR; - if (key == CSR_MODEL && value == id->model) - match |= FW_MATCH_MODEL; - if (key == CSR_SPECIFIER_ID && value == id->specifier_id) - match |= FW_MATCH_SPECIFIER_ID; - if (key == CSR_VERSION && value == id->version) - match |= FW_MATCH_VERSION; - } - - return (match & id->match_flags) == id->match_flags; -} - -static int fw_unit_match(struct device *dev, struct device_driver *drv) -{ - struct fw_unit *unit = fw_unit(dev); - struct fw_driver *driver = fw_driver(drv); - int i; - - /* We only allow binding to fw_units. */ - if (!is_fw_unit(dev)) - return 0; - - for (i = 0; driver->id_table[i].match_flags != 0; i++) { - if (match_unit_directory(unit->directory, &driver->id_table[i])) - return 1; - } - - return 0; -} - -static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) -{ - struct fw_device *device = fw_device(unit->device.parent); - struct fw_csr_iterator ci; - - int key, value; - int vendor = 0; - int model = 0; - int specifier_id = 0; - int version = 0; - - fw_csr_iterator_init(&ci, &device->config_rom[5]); - while (fw_csr_iterator_next(&ci, &key, &value)) { - switch (key) { - case CSR_VENDOR: - vendor = value; - break; - case CSR_MODEL: - model = value; - break; - } - } - - fw_csr_iterator_init(&ci, unit->directory); - while (fw_csr_iterator_next(&ci, &key, &value)) { - switch (key) { - case CSR_SPECIFIER_ID: - specifier_id = value; - break; - case CSR_VERSION: - version = value; - break; - } - } - - return snprintf(buffer, buffer_size, - "ieee1394:ven%08Xmo%08Xsp%08Xver%08X", - vendor, model, specifier_id, version); -} - -static int -fw_unit_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) -{ - struct fw_unit *unit = fw_unit(dev); - char modalias[64]; - int length = 0; - int i = 0; - - get_modalias(unit, modalias, sizeof(modalias)); - - if (add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "MODALIAS=%s", modalias)) - return -ENOMEM; - - envp[i] = NULL; - - return 0; -} - -struct bus_type fw_bus_type = { - .name = "firewire", - .match = fw_unit_match, -}; -EXPORT_SYMBOL(fw_bus_type); - -struct fw_device *fw_device_get(struct fw_device *device) -{ - get_device(&device->device); - - return device; -} - -void fw_device_put(struct fw_device *device) -{ - put_device(&device->device); -} - -static void fw_device_release(struct device *dev) -{ - struct fw_device *device = fw_device(dev); - unsigned long flags; - - /* - * Take the card lock so we don't set this to NULL while a - * FW_NODE_UPDATED callback is being handled. - */ - spin_lock_irqsave(&device->card->lock, flags); - device->node->data = NULL; - spin_unlock_irqrestore(&device->card->lock, flags); - - fw_node_put(device->node); - fw_card_put(device->card); - kfree(device->config_rom); - kfree(device); -} - -int fw_device_enable_phys_dma(struct fw_device *device) -{ - return device->card->driver->enable_phys_dma(device->card, - device->node_id, - device->generation); -} -EXPORT_SYMBOL(fw_device_enable_phys_dma); - -struct config_rom_attribute { - struct device_attribute attr; - u32 key; -}; - -static ssize_t -show_immediate(struct device *dev, struct device_attribute *dattr, char *buf) -{ - struct config_rom_attribute *attr = - container_of(dattr, struct config_rom_attribute, attr); - struct fw_csr_iterator ci; - u32 *dir; - int key, value; - - if (is_fw_unit(dev)) - dir = fw_unit(dev)->directory; - else - dir = fw_device(dev)->config_rom + 5; - - fw_csr_iterator_init(&ci, dir); - while (fw_csr_iterator_next(&ci, &key, &value)) - if (attr->key == key) - return snprintf(buf, buf ? PAGE_SIZE : 0, - "0x%06x\n", value); - - return -ENOENT; -} - -#define IMMEDIATE_ATTR(name, key) \ - { __ATTR(name, S_IRUGO, show_immediate, NULL), key } - -static ssize_t -show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf) -{ - struct config_rom_attribute *attr = - container_of(dattr, struct config_rom_attribute, attr); - struct fw_csr_iterator ci; - u32 *dir, *block = NULL, *p, *end; - int length, key, value, last_key = 0; - char *b; - - if (is_fw_unit(dev)) - dir = fw_unit(dev)->directory; - else - dir = fw_device(dev)->config_rom + 5; - - fw_csr_iterator_init(&ci, dir); - while (fw_csr_iterator_next(&ci, &key, &value)) { - if (attr->key == last_key && - key == (CSR_DESCRIPTOR | CSR_LEAF)) - block = ci.p - 1 + value; - last_key = key; - } - - if (block == NULL) - return -ENOENT; - - length = min(block[0] >> 16, 256U); - if (length < 3) - return -ENOENT; - - if (block[1] != 0 || block[2] != 0) - /* Unknown encoding. */ - return -ENOENT; - - if (buf == NULL) - return length * 4; - - b = buf; - end = &block[length + 1]; - for (p = &block[3]; p < end; p++, b += 4) - * (u32 *) b = (__force u32) __cpu_to_be32(*p); - - /* Strip trailing whitespace and add newline. */ - while (b--, (isspace(*b) || *b == '\0') && b > buf); - strcpy(b + 1, "\n"); - - return b + 2 - buf; -} - -#define TEXT_LEAF_ATTR(name, key) \ - { __ATTR(name, S_IRUGO, show_text_leaf, NULL), key } - -static struct config_rom_attribute config_rom_attributes[] = { - IMMEDIATE_ATTR(vendor, CSR_VENDOR), - IMMEDIATE_ATTR(hardware_version, CSR_HARDWARE_VERSION), - IMMEDIATE_ATTR(specifier_id, CSR_SPECIFIER_ID), - IMMEDIATE_ATTR(version, CSR_VERSION), - IMMEDIATE_ATTR(model, CSR_MODEL), - TEXT_LEAF_ATTR(vendor_name, CSR_VENDOR), - TEXT_LEAF_ATTR(model_name, CSR_MODEL), - TEXT_LEAF_ATTR(hardware_version_name, CSR_HARDWARE_VERSION), -}; - -static void -init_fw_attribute_group(struct device *dev, - struct device_attribute *attrs, - struct fw_attribute_group *group) -{ - struct device_attribute *attr; - int i, j; - - for (j = 0; attrs[j].attr.name != NULL; j++) - group->attrs[j] = &attrs[j].attr; - - for (i = 0; i < ARRAY_SIZE(config_rom_attributes); i++) { - attr = &config_rom_attributes[i].attr; - if (attr->show(dev, attr, NULL) < 0) - continue; - group->attrs[j++] = &attr->attr; - } - - BUG_ON(j >= ARRAY_SIZE(group->attrs)); - group->attrs[j++] = NULL; - group->groups[0] = &group->group; - group->groups[1] = NULL; - group->group.attrs = group->attrs; - dev->groups = group->groups; -} - -static ssize_t -modalias_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fw_unit *unit = fw_unit(dev); - int length; - - length = get_modalias(unit, buf, PAGE_SIZE); - strcpy(buf + length, "\n"); - - return length + 1; -} - -static ssize_t -rom_index_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fw_device *device = fw_device(dev->parent); - struct fw_unit *unit = fw_unit(dev); - - return snprintf(buf, PAGE_SIZE, "%d\n", - (int)(unit->directory - device->config_rom)); -} - -static struct device_attribute fw_unit_attributes[] = { - __ATTR_RO(modalias), - __ATTR_RO(rom_index), - __ATTR_NULL, -}; - -static ssize_t -config_rom_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct fw_device *device = fw_device(dev); - - memcpy(buf, device->config_rom, device->config_rom_length * 4); - - return device->config_rom_length * 4; -} - -static ssize_t -guid_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct fw_device *device = fw_device(dev); - u64 guid; - - guid = ((u64)device->config_rom[3] << 32) | device->config_rom[4]; - - return snprintf(buf, PAGE_SIZE, "0x%016llx\n", - (unsigned long long)guid); -} - -static struct device_attribute fw_device_attributes[] = { - __ATTR_RO(config_rom), - __ATTR_RO(guid), - __ATTR_NULL, -}; - -struct read_quadlet_callback_data { - struct completion done; - int rcode; - u32 data; -}; - -static void -complete_transaction(struct fw_card *card, int rcode, - void *payload, size_t length, void *data) -{ - struct read_quadlet_callback_data *callback_data = data; - - if (rcode == RCODE_COMPLETE) - callback_data->data = be32_to_cpu(*(__be32 *)payload); - callback_data->rcode = rcode; - complete(&callback_data->done); -} - -static int read_rom(struct fw_device *device, int index, u32 * data) -{ - struct read_quadlet_callback_data callback_data; - struct fw_transaction t; - u64 offset; - - init_completion(&callback_data.done); - - offset = 0xfffff0000400ULL + index * 4; - fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST, - device->node_id, - device->generation, SCODE_100, - offset, NULL, 4, complete_transaction, &callback_data); - - wait_for_completion(&callback_data.done); - - *data = callback_data.data; - - return callback_data.rcode; -} - -static int read_bus_info_block(struct fw_device *device) -{ - static u32 rom[256]; - u32 stack[16], sp, key; - int i, end, length; - - /* First read the bus info block. */ - for (i = 0; i < 5; i++) { - if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) - return -1; - /* - * As per IEEE1212 7.2, during power-up, devices can - * reply with a 0 for the first quadlet of the config - * rom to indicate that they are booting (for example, - * if the firmware is on the disk of a external - * harddisk). In that case we just fail, and the - * retry mechanism will try again later. - */ - if (i == 0 && rom[i] == 0) - return -1; - } - - /* - * Now parse the config rom. The config rom is a recursive - * directory structure so we parse it using a stack of - * references to the blocks that make up the structure. We - * push a reference to the root directory on the stack to - * start things off. - */ - length = i; - sp = 0; - stack[sp++] = 0xc0000005; - while (sp > 0) { - /* - * Pop the next block reference of the stack. The - * lower 24 bits is the offset into the config rom, - * the upper 8 bits are the type of the reference the - * block. - */ - key = stack[--sp]; - i = key & 0xffffff; - if (i >= ARRAY_SIZE(rom)) - /* - * The reference points outside the standard - * config rom area, something's fishy. - */ - return -1; - - /* Read header quadlet for the block to get the length. */ - if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) - return -1; - end = i + (rom[i] >> 16) + 1; - i++; - if (end > ARRAY_SIZE(rom)) - /* - * This block extends outside standard config - * area (and the array we're reading it - * into). That's broken, so ignore this - * device. - */ - return -1; - - /* - * Now read in the block. If this is a directory - * block, check the entries as we read them to see if - * it references another block, and push it in that case. - */ - while (i < end) { - if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE) - return -1; - if ((key >> 30) == 3 && (rom[i] >> 30) > 1 && - sp < ARRAY_SIZE(stack)) - stack[sp++] = i + rom[i]; - i++; - } - if (length < i) - length = i; - } - - device->config_rom = kmalloc(length * 4, GFP_KERNEL); - if (device->config_rom == NULL) - return -1; - memcpy(device->config_rom, rom, length * 4); - device->config_rom_length = length; - - return 0; -} - -static void fw_unit_release(struct device *dev) -{ - struct fw_unit *unit = fw_unit(dev); - - kfree(unit); -} - -static struct device_type fw_unit_type = { - .uevent = fw_unit_uevent, - .release = fw_unit_release, -}; - -static int is_fw_unit(struct device *dev) -{ - return dev->type == &fw_unit_type; -} - -static void create_units(struct fw_device *device) -{ - struct fw_csr_iterator ci; - struct fw_unit *unit; - int key, value, i; - - i = 0; - fw_csr_iterator_init(&ci, &device->config_rom[5]); - while (fw_csr_iterator_next(&ci, &key, &value)) { - if (key != (CSR_UNIT | CSR_DIRECTORY)) - continue; - - /* - * Get the address of the unit directory and try to - * match the drivers id_tables against it. - */ - unit = kzalloc(sizeof(*unit), GFP_KERNEL); - if (unit == NULL) { - fw_error("failed to allocate memory for unit\n"); - continue; - } - - unit->directory = ci.p + value - 1; - unit->device.bus = &fw_bus_type; - unit->device.type = &fw_unit_type; - unit->device.parent = &device->device; - snprintf(unit->device.bus_id, sizeof(unit->device.bus_id), - "%s.%d", device->device.bus_id, i++); - - init_fw_attribute_group(&unit->device, - fw_unit_attributes, - &unit->attribute_group); - if (device_register(&unit->device) < 0) - goto skip_unit; - - continue; - - skip_unit: - kfree(unit); - } -} - -static int shutdown_unit(struct device *device, void *data) -{ - device_unregister(device); - - return 0; -} - -static DECLARE_RWSEM(idr_rwsem); -static DEFINE_IDR(fw_device_idr); -int fw_cdev_major; - -struct fw_device *fw_device_from_devt(dev_t devt) -{ - struct fw_device *device; - - down_read(&idr_rwsem); - device = idr_find(&fw_device_idr, MINOR(devt)); - up_read(&idr_rwsem); - - return device; -} - -static void fw_device_shutdown(struct work_struct *work) -{ - struct fw_device *device = - container_of(work, struct fw_device, work.work); - int minor = MINOR(device->device.devt); - - down_write(&idr_rwsem); - idr_remove(&fw_device_idr, minor); - up_write(&idr_rwsem); - - fw_device_cdev_remove(device); - device_for_each_child(&device->device, NULL, shutdown_unit); - device_unregister(&device->device); -} - -static struct device_type fw_device_type = { - .release = fw_device_release, -}; - -/* - * These defines control the retry behavior for reading the config - * rom. It shouldn't be necessary to tweak these; if the device - * doesn't respond to a config rom read within 10 seconds, it's not - * going to respond at all. As for the initial delay, a lot of - * devices will be able to respond within half a second after bus - * reset. On the other hand, it's not really worth being more - * aggressive than that, since it scales pretty well; if 10 devices - * are plugged in, they're all getting read within one second. - */ - -#define MAX_RETRIES 10 -#define RETRY_DELAY (3 * HZ) -#define INITIAL_DELAY (HZ / 2) - -static void fw_device_init(struct work_struct *work) -{ - struct fw_device *device = - container_of(work, struct fw_device, work.work); - int minor, err; - - /* - * All failure paths here set node->data to NULL, so that we - * don't try to do device_for_each_child() on a kfree()'d - * device. - */ - - if (read_bus_info_block(device) < 0) { - if (device->config_rom_retries < MAX_RETRIES) { - device->config_rom_retries++; - schedule_delayed_work(&device->work, RETRY_DELAY); - } else { - fw_notify("giving up on config rom for node id %x\n", - device->node_id); - if (device->node == device->card->root_node) - schedule_delayed_work(&device->card->work, 0); - fw_device_release(&device->device); - } - return; - } - - err = -ENOMEM; - down_write(&idr_rwsem); - if (idr_pre_get(&fw_device_idr, GFP_KERNEL)) - err = idr_get_new(&fw_device_idr, device, &minor); - up_write(&idr_rwsem); - if (err < 0) - goto error; - - device->device.bus = &fw_bus_type; - device->device.type = &fw_device_type; - device->device.parent = device->card->device; - device->device.devt = MKDEV(fw_cdev_major, minor); - snprintf(device->device.bus_id, sizeof(device->device.bus_id), - "fw%d", minor); - - init_fw_attribute_group(&device->device, - fw_device_attributes, - &device->attribute_group); - if (device_add(&device->device)) { - fw_error("Failed to add device.\n"); - goto error_with_cdev; - } - - create_units(device); - - /* - * Transition the device to running state. If it got pulled - * out from under us while we did the intialization work, we - * have to shut down the device again here. Normally, though, - * fw_node_event will be responsible for shutting it down when - * necessary. We have to use the atomic cmpxchg here to avoid - * racing with the FW_NODE_DESTROYED case in - * fw_node_event(). - */ - if (atomic_cmpxchg(&device->state, - FW_DEVICE_INITIALIZING, - FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) - fw_device_shutdown(&device->work.work); - else - fw_notify("created new fw device %s (%d config rom retries)\n", - device->device.bus_id, device->config_rom_retries); - - /* - * Reschedule the IRM work if we just finished reading the - * root node config rom. If this races with a bus reset we - * just end up running the IRM work a couple of extra times - - * pretty harmless. - */ - if (device->node == device->card->root_node) - schedule_delayed_work(&device->card->work, 0); - - return; - - error_with_cdev: - down_write(&idr_rwsem); - idr_remove(&fw_device_idr, minor); - up_write(&idr_rwsem); - error: - put_device(&device->device); -} - -static int update_unit(struct device *dev, void *data) -{ - struct fw_unit *unit = fw_unit(dev); - struct fw_driver *driver = (struct fw_driver *)dev->driver; - - if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) { - down(&dev->sem); - driver->update(unit); - up(&dev->sem); - } - - return 0; -} - -static void fw_device_update(struct work_struct *work) -{ - struct fw_device *device = - container_of(work, struct fw_device, work.work); - - fw_device_cdev_update(device); - device_for_each_child(&device->device, NULL, update_unit); -} - -void fw_node_event(struct fw_card *card, struct fw_node *node, int event) -{ - struct fw_device *device; - - switch (event) { - case FW_NODE_CREATED: - case FW_NODE_LINK_ON: - if (!node->link_on) - break; - - device = kzalloc(sizeof(*device), GFP_ATOMIC); - if (device == NULL) - break; - - /* - * Do minimal intialization of the device here, the - * rest will happen in fw_device_init(). We need the - * card and node so we can read the config rom and we - * need to do device_initialize() now so - * device_for_each_child() in FW_NODE_UPDATED is - * doesn't freak out. - */ - device_initialize(&device->device); - atomic_set(&device->state, FW_DEVICE_INITIALIZING); - device->card = fw_card_get(card); - device->node = fw_node_get(node); - device->node_id = node->node_id; - device->generation = card->generation; - INIT_LIST_HEAD(&device->client_list); - - /* - * Set the node data to point back to this device so - * FW_NODE_UPDATED callbacks can update the node_id - * and generation for the device. - */ - node->data = device; - - /* - * Many devices are slow to respond after bus resets, - * especially if they are bus powered and go through - * power-up after getting plugged in. We schedule the - * first config rom scan half a second after bus reset. - */ - INIT_DELAYED_WORK(&device->work, fw_device_init); - schedule_delayed_work(&device->work, INITIAL_DELAY); - break; - - case FW_NODE_UPDATED: - if (!node->link_on || node->data == NULL) - break; - - device = node->data; - device->node_id = node->node_id; - device->generation = card->generation; - if (atomic_read(&device->state) == FW_DEVICE_RUNNING) { - PREPARE_DELAYED_WORK(&device->work, fw_device_update); - schedule_delayed_work(&device->work, 0); - } - break; - - case FW_NODE_DESTROYED: - case FW_NODE_LINK_OFF: - if (!node->data) - break; - - /* - * Destroy the device associated with the node. There - * are two cases here: either the device is fully - * initialized (FW_DEVICE_RUNNING) or we're in the - * process of reading its config rom - * (FW_DEVICE_INITIALIZING). If it is fully - * initialized we can reuse device->work to schedule a - * full fw_device_shutdown(). If not, there's work - * scheduled to read it's config rom, and we just put - * the device in shutdown state to have that code fail - * to create the device. - */ - device = node->data; - if (atomic_xchg(&device->state, - FW_DEVICE_SHUTDOWN) == FW_DEVICE_RUNNING) { - PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown); - schedule_delayed_work(&device->work, 0); - } - break; - } -} diff --git a/trunk/drivers/firewire/fw-device.h b/trunk/drivers/firewire/fw-device.h deleted file mode 100644 index 0ba9d64ccf4c..000000000000 --- a/trunk/drivers/firewire/fw-device.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2005-2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __fw_device_h -#define __fw_device_h - -#include -#include -#include - -enum fw_device_state { - FW_DEVICE_INITIALIZING, - FW_DEVICE_RUNNING, - FW_DEVICE_SHUTDOWN, -}; - -struct fw_attribute_group { - struct attribute_group *groups[2]; - struct attribute_group group; - struct attribute *attrs[11]; -}; - -struct fw_device { - atomic_t state; - struct fw_node *node; - int node_id; - int generation; - struct fw_card *card; - struct device device; - struct list_head link; - struct list_head client_list; - u32 *config_rom; - size_t config_rom_length; - int config_rom_retries; - struct delayed_work work; - struct fw_attribute_group attribute_group; -}; - -static inline struct fw_device * -fw_device(struct device *dev) -{ - return container_of(dev, struct fw_device, device); -} - -static inline int -fw_device_is_shutdown(struct fw_device *device) -{ - return atomic_read(&device->state) == FW_DEVICE_SHUTDOWN; -} - -struct fw_device *fw_device_get(struct fw_device *device); -void fw_device_put(struct fw_device *device); -int fw_device_enable_phys_dma(struct fw_device *device); - -void fw_device_cdev_update(struct fw_device *device); -void fw_device_cdev_remove(struct fw_device *device); - -struct fw_device *fw_device_from_devt(dev_t devt); -extern int fw_cdev_major; - -struct fw_unit { - struct device device; - u32 *directory; - struct fw_attribute_group attribute_group; -}; - -static inline struct fw_unit * -fw_unit(struct device *dev) -{ - return container_of(dev, struct fw_unit, device); -} - -#define CSR_OFFSET 0x40 -#define CSR_LEAF 0x80 -#define CSR_DIRECTORY 0xc0 - -#define CSR_DESCRIPTOR 0x01 -#define CSR_VENDOR 0x03 -#define CSR_HARDWARE_VERSION 0x04 -#define CSR_NODE_CAPABILITIES 0x0c -#define CSR_UNIT 0x11 -#define CSR_SPECIFIER_ID 0x12 -#define CSR_VERSION 0x13 -#define CSR_DEPENDENT_INFO 0x14 -#define CSR_MODEL 0x17 -#define CSR_INSTANCE 0x18 - -#define SBP2_COMMAND_SET_SPECIFIER 0x38 -#define SBP2_COMMAND_SET 0x39 -#define SBP2_COMMAND_SET_REVISION 0x3b -#define SBP2_FIRMWARE_REVISION 0x3c - -struct fw_csr_iterator { - u32 *p; - u32 *end; -}; - -void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 *p); -int fw_csr_iterator_next(struct fw_csr_iterator *ci, - int *key, int *value); - -#define FW_MATCH_VENDOR 0x0001 -#define FW_MATCH_MODEL 0x0002 -#define FW_MATCH_SPECIFIER_ID 0x0004 -#define FW_MATCH_VERSION 0x0008 - -struct fw_device_id { - u32 match_flags; - u32 vendor; - u32 model; - u32 specifier_id; - u32 version; - void *driver_data; -}; - -struct fw_driver { - struct device_driver driver; - /* Called when the parent device sits through a bus reset. */ - void (*update) (struct fw_unit *unit); - const struct fw_device_id *id_table; -}; - -static inline struct fw_driver * -fw_driver(struct device_driver *drv) -{ - return container_of(drv, struct fw_driver, driver); -} - -extern const struct file_operations fw_device_ops; - -#endif /* __fw_device_h */ diff --git a/trunk/drivers/firewire/fw-iso.c b/trunk/drivers/firewire/fw-iso.c deleted file mode 100644 index 2b640e9be6de..000000000000 --- a/trunk/drivers/firewire/fw-iso.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Isochronous IO functionality - * - * Copyright (C) 2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include - -#include "fw-transaction.h" -#include "fw-topology.h" -#include "fw-device.h" - -int -fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, - int page_count, enum dma_data_direction direction) -{ - int i, j, retval = -ENOMEM; - dma_addr_t address; - - buffer->page_count = page_count; - buffer->direction = direction; - - buffer->pages = kmalloc(page_count * sizeof(buffer->pages[0]), - GFP_KERNEL); - if (buffer->pages == NULL) - goto out; - - for (i = 0; i < buffer->page_count; i++) { - buffer->pages[i] = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); - if (buffer->pages[i] == NULL) - goto out_pages; - - address = dma_map_page(card->device, buffer->pages[i], - 0, PAGE_SIZE, direction); - if (dma_mapping_error(address)) { - __free_page(buffer->pages[i]); - goto out_pages; - } - set_page_private(buffer->pages[i], address); - } - - return 0; - - out_pages: - for (j = 0; j < i; j++) { - address = page_private(buffer->pages[j]); - dma_unmap_page(card->device, address, - PAGE_SIZE, DMA_TO_DEVICE); - __free_page(buffer->pages[j]); - } - kfree(buffer->pages); - out: - buffer->pages = NULL; - return retval; -} - -int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma) -{ - unsigned long uaddr; - int i, retval; - - uaddr = vma->vm_start; - for (i = 0; i < buffer->page_count; i++) { - retval = vm_insert_page(vma, uaddr, buffer->pages[i]); - if (retval) - return retval; - uaddr += PAGE_SIZE; - } - - return 0; -} - -void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, - struct fw_card *card) -{ - int i; - dma_addr_t address; - - for (i = 0; i < buffer->page_count; i++) { - address = page_private(buffer->pages[i]); - dma_unmap_page(card->device, address, - PAGE_SIZE, DMA_TO_DEVICE); - __free_page(buffer->pages[i]); - } - - kfree(buffer->pages); - buffer->pages = NULL; -} - -struct fw_iso_context * -fw_iso_context_create(struct fw_card *card, int type, - int channel, int speed, size_t header_size, - fw_iso_callback_t callback, void *callback_data) -{ - struct fw_iso_context *ctx; - - ctx = card->driver->allocate_iso_context(card, type, header_size); - if (IS_ERR(ctx)) - return ctx; - - ctx->card = card; - ctx->type = type; - ctx->channel = channel; - ctx->speed = speed; - ctx->header_size = header_size; - ctx->callback = callback; - ctx->callback_data = callback_data; - - return ctx; -} -EXPORT_SYMBOL(fw_iso_context_create); - -void fw_iso_context_destroy(struct fw_iso_context *ctx) -{ - struct fw_card *card = ctx->card; - - card->driver->free_iso_context(ctx); -} -EXPORT_SYMBOL(fw_iso_context_destroy); - -int -fw_iso_context_start(struct fw_iso_context *ctx, int cycle, int sync, int tags) -{ - return ctx->card->driver->start_iso(ctx, cycle, sync, tags); -} -EXPORT_SYMBOL(fw_iso_context_start); - -int -fw_iso_context_queue(struct fw_iso_context *ctx, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload) -{ - struct fw_card *card = ctx->card; - - return card->driver->queue_iso(ctx, packet, buffer, payload); -} -EXPORT_SYMBOL(fw_iso_context_queue); - -int -fw_iso_context_stop(struct fw_iso_context *ctx) -{ - return ctx->card->driver->stop_iso(ctx); -} -EXPORT_SYMBOL(fw_iso_context_stop); diff --git a/trunk/drivers/firewire/fw-ohci.c b/trunk/drivers/firewire/fw-ohci.c deleted file mode 100644 index 1f5c70461b8b..000000000000 --- a/trunk/drivers/firewire/fw-ohci.c +++ /dev/null @@ -1,1943 +0,0 @@ -/* - * Driver for OHCI 1394 controllers - * - * Copyright (C) 2003-2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "fw-transaction.h" -#include "fw-ohci.h" - -#define DESCRIPTOR_OUTPUT_MORE 0 -#define DESCRIPTOR_OUTPUT_LAST (1 << 12) -#define DESCRIPTOR_INPUT_MORE (2 << 12) -#define DESCRIPTOR_INPUT_LAST (3 << 12) -#define DESCRIPTOR_STATUS (1 << 11) -#define DESCRIPTOR_KEY_IMMEDIATE (2 << 8) -#define DESCRIPTOR_PING (1 << 7) -#define DESCRIPTOR_YY (1 << 6) -#define DESCRIPTOR_NO_IRQ (0 << 4) -#define DESCRIPTOR_IRQ_ERROR (1 << 4) -#define DESCRIPTOR_IRQ_ALWAYS (3 << 4) -#define DESCRIPTOR_BRANCH_ALWAYS (3 << 2) -#define DESCRIPTOR_WAIT (3 << 0) - -struct descriptor { - __le16 req_count; - __le16 control; - __le32 data_address; - __le32 branch_address; - __le16 res_count; - __le16 transfer_status; -} __attribute__((aligned(16))); - -struct db_descriptor { - __le16 first_size; - __le16 control; - __le16 second_req_count; - __le16 first_req_count; - __le32 branch_address; - __le16 second_res_count; - __le16 first_res_count; - __le32 reserved0; - __le32 first_buffer; - __le32 second_buffer; - __le32 reserved1; -} __attribute__((aligned(16))); - -#define CONTROL_SET(regs) (regs) -#define CONTROL_CLEAR(regs) ((regs) + 4) -#define COMMAND_PTR(regs) ((regs) + 12) -#define CONTEXT_MATCH(regs) ((regs) + 16) - -struct ar_buffer { - struct descriptor descriptor; - struct ar_buffer *next; - __le32 data[0]; -}; - -struct ar_context { - struct fw_ohci *ohci; - struct ar_buffer *current_buffer; - struct ar_buffer *last_buffer; - void *pointer; - u32 regs; - struct tasklet_struct tasklet; -}; - -struct context; - -typedef int (*descriptor_callback_t)(struct context *ctx, - struct descriptor *d, - struct descriptor *last); -struct context { - struct fw_ohci *ohci; - u32 regs; - - struct descriptor *buffer; - dma_addr_t buffer_bus; - size_t buffer_size; - struct descriptor *head_descriptor; - struct descriptor *tail_descriptor; - struct descriptor *tail_descriptor_last; - struct descriptor *prev_descriptor; - - descriptor_callback_t callback; - - struct tasklet_struct tasklet; -}; - -#define IT_HEADER_SY(v) ((v) << 0) -#define IT_HEADER_TCODE(v) ((v) << 4) -#define IT_HEADER_CHANNEL(v) ((v) << 8) -#define IT_HEADER_TAG(v) ((v) << 14) -#define IT_HEADER_SPEED(v) ((v) << 16) -#define IT_HEADER_DATA_LENGTH(v) ((v) << 16) - -struct iso_context { - struct fw_iso_context base; - struct context context; - void *header; - size_t header_length; -}; - -#define CONFIG_ROM_SIZE 1024 - -struct fw_ohci { - struct fw_card card; - - u32 version; - __iomem char *registers; - dma_addr_t self_id_bus; - __le32 *self_id_cpu; - struct tasklet_struct bus_reset_tasklet; - int node_id; - int generation; - int request_generation; - u32 bus_seconds; - - /* - * Spinlock for accessing fw_ohci data. Never call out of - * this driver with this lock held. - */ - spinlock_t lock; - u32 self_id_buffer[512]; - - /* Config rom buffers */ - __be32 *config_rom; - dma_addr_t config_rom_bus; - __be32 *next_config_rom; - dma_addr_t next_config_rom_bus; - u32 next_header; - - struct ar_context ar_request_ctx; - struct ar_context ar_response_ctx; - struct context at_request_ctx; - struct context at_response_ctx; - - u32 it_context_mask; - struct iso_context *it_context_list; - u32 ir_context_mask; - struct iso_context *ir_context_list; -}; - -static inline struct fw_ohci *fw_ohci(struct fw_card *card) -{ - return container_of(card, struct fw_ohci, card); -} - -#define IT_CONTEXT_CYCLE_MATCH_ENABLE 0x80000000 -#define IR_CONTEXT_BUFFER_FILL 0x80000000 -#define IR_CONTEXT_ISOCH_HEADER 0x40000000 -#define IR_CONTEXT_CYCLE_MATCH_ENABLE 0x20000000 -#define IR_CONTEXT_MULTI_CHANNEL_MODE 0x10000000 -#define IR_CONTEXT_DUAL_BUFFER_MODE 0x08000000 - -#define CONTEXT_RUN 0x8000 -#define CONTEXT_WAKE 0x1000 -#define CONTEXT_DEAD 0x0800 -#define CONTEXT_ACTIVE 0x0400 - -#define OHCI1394_MAX_AT_REQ_RETRIES 0x2 -#define OHCI1394_MAX_AT_RESP_RETRIES 0x2 -#define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8 - -#define FW_OHCI_MAJOR 240 -#define OHCI1394_REGISTER_SIZE 0x800 -#define OHCI_LOOP_COUNT 500 -#define OHCI1394_PCI_HCI_Control 0x40 -#define SELF_ID_BUF_SIZE 0x800 -#define OHCI_TCODE_PHY_PACKET 0x0e -#define OHCI_VERSION_1_1 0x010010 -#define ISO_BUFFER_SIZE (64 * 1024) -#define AT_BUFFER_SIZE 4096 - -static char ohci_driver_name[] = KBUILD_MODNAME; - -static inline void reg_write(const struct fw_ohci *ohci, int offset, u32 data) -{ - writel(data, ohci->registers + offset); -} - -static inline u32 reg_read(const struct fw_ohci *ohci, int offset) -{ - return readl(ohci->registers + offset); -} - -static inline void flush_writes(const struct fw_ohci *ohci) -{ - /* Do a dummy read to flush writes. */ - reg_read(ohci, OHCI1394_Version); -} - -static int -ohci_update_phy_reg(struct fw_card *card, int addr, - int clear_bits, int set_bits) -{ - struct fw_ohci *ohci = fw_ohci(card); - u32 val, old; - - reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr)); - msleep(2); - val = reg_read(ohci, OHCI1394_PhyControl); - if ((val & OHCI1394_PhyControl_ReadDone) == 0) { - fw_error("failed to set phy reg bits.\n"); - return -EBUSY; - } - - old = OHCI1394_PhyControl_ReadData(val); - old = (old & ~clear_bits) | set_bits; - reg_write(ohci, OHCI1394_PhyControl, - OHCI1394_PhyControl_Write(addr, old)); - - return 0; -} - -static int ar_context_add_page(struct ar_context *ctx) -{ - struct device *dev = ctx->ohci->card.device; - struct ar_buffer *ab; - dma_addr_t ab_bus; - size_t offset; - - ab = (struct ar_buffer *) __get_free_page(GFP_ATOMIC); - if (ab == NULL) - return -ENOMEM; - - ab_bus = dma_map_single(dev, ab, PAGE_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(ab_bus)) { - free_page((unsigned long) ab); - return -ENOMEM; - } - - memset(&ab->descriptor, 0, sizeof(ab->descriptor)); - ab->descriptor.control = cpu_to_le16(DESCRIPTOR_INPUT_MORE | - DESCRIPTOR_STATUS | - DESCRIPTOR_BRANCH_ALWAYS); - offset = offsetof(struct ar_buffer, data); - ab->descriptor.req_count = cpu_to_le16(PAGE_SIZE - offset); - ab->descriptor.data_address = cpu_to_le32(ab_bus + offset); - ab->descriptor.res_count = cpu_to_le16(PAGE_SIZE - offset); - ab->descriptor.branch_address = 0; - - dma_sync_single_for_device(dev, ab_bus, PAGE_SIZE, DMA_BIDIRECTIONAL); - - ctx->last_buffer->descriptor.branch_address = ab_bus | 1; - ctx->last_buffer->next = ab; - ctx->last_buffer = ab; - - reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); - flush_writes(ctx->ohci); - - return 0; -} - -static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) -{ - struct fw_ohci *ohci = ctx->ohci; - struct fw_packet p; - u32 status, length, tcode; - - p.header[0] = le32_to_cpu(buffer[0]); - p.header[1] = le32_to_cpu(buffer[1]); - p.header[2] = le32_to_cpu(buffer[2]); - - tcode = (p.header[0] >> 4) & 0x0f; - switch (tcode) { - case TCODE_WRITE_QUADLET_REQUEST: - case TCODE_READ_QUADLET_RESPONSE: - p.header[3] = (__force __u32) buffer[3]; - p.header_length = 16; - p.payload_length = 0; - break; - - case TCODE_READ_BLOCK_REQUEST : - p.header[3] = le32_to_cpu(buffer[3]); - p.header_length = 16; - p.payload_length = 0; - break; - - case TCODE_WRITE_BLOCK_REQUEST: - case TCODE_READ_BLOCK_RESPONSE: - case TCODE_LOCK_REQUEST: - case TCODE_LOCK_RESPONSE: - p.header[3] = le32_to_cpu(buffer[3]); - p.header_length = 16; - p.payload_length = p.header[3] >> 16; - break; - - case TCODE_WRITE_RESPONSE: - case TCODE_READ_QUADLET_REQUEST: - case OHCI_TCODE_PHY_PACKET: - p.header_length = 12; - p.payload_length = 0; - break; - } - - p.payload = (void *) buffer + p.header_length; - - /* FIXME: What to do about evt_* errors? */ - length = (p.header_length + p.payload_length + 3) / 4; - status = le32_to_cpu(buffer[length]); - - p.ack = ((status >> 16) & 0x1f) - 16; - p.speed = (status >> 21) & 0x7; - p.timestamp = status & 0xffff; - p.generation = ohci->request_generation; - - /* - * The OHCI bus reset handler synthesizes a phy packet with - * the new generation number when a bus reset happens (see - * section 8.4.2.3). This helps us determine when a request - * was received and make sure we send the response in the same - * generation. We only need this for requests; for responses - * we use the unique tlabel for finding the matching - * request. - */ - - if (p.ack + 16 == 0x09) - ohci->request_generation = (buffer[2] >> 16) & 0xff; - else if (ctx == &ohci->ar_request_ctx) - fw_core_handle_request(&ohci->card, &p); - else - fw_core_handle_response(&ohci->card, &p); - - return buffer + length + 1; -} - -static void ar_context_tasklet(unsigned long data) -{ - struct ar_context *ctx = (struct ar_context *)data; - struct fw_ohci *ohci = ctx->ohci; - struct ar_buffer *ab; - struct descriptor *d; - void *buffer, *end; - - ab = ctx->current_buffer; - d = &ab->descriptor; - - if (d->res_count == 0) { - size_t size, rest, offset; - - /* - * This descriptor is finished and we may have a - * packet split across this and the next buffer. We - * reuse the page for reassembling the split packet. - */ - - offset = offsetof(struct ar_buffer, data); - dma_unmap_single(ohci->card.device, - ab->descriptor.data_address - offset, - PAGE_SIZE, DMA_BIDIRECTIONAL); - - buffer = ab; - ab = ab->next; - d = &ab->descriptor; - size = buffer + PAGE_SIZE - ctx->pointer; - rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count); - memmove(buffer, ctx->pointer, size); - memcpy(buffer + size, ab->data, rest); - ctx->current_buffer = ab; - ctx->pointer = (void *) ab->data + rest; - end = buffer + size + rest; - - while (buffer < end) - buffer = handle_ar_packet(ctx, buffer); - - free_page((unsigned long)buffer); - ar_context_add_page(ctx); - } else { - buffer = ctx->pointer; - ctx->pointer = end = - (void *) ab + PAGE_SIZE - le16_to_cpu(d->res_count); - - while (buffer < end) - buffer = handle_ar_packet(ctx, buffer); - } -} - -static int -ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci, u32 regs) -{ - struct ar_buffer ab; - - ctx->regs = regs; - ctx->ohci = ohci; - ctx->last_buffer = &ab; - tasklet_init(&ctx->tasklet, ar_context_tasklet, (unsigned long)ctx); - - ar_context_add_page(ctx); - ar_context_add_page(ctx); - ctx->current_buffer = ab.next; - ctx->pointer = ctx->current_buffer->data; - - reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ab.descriptor.branch_address); - reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN); - flush_writes(ctx->ohci); - - return 0; -} - -static void context_tasklet(unsigned long data) -{ - struct context *ctx = (struct context *) data; - struct fw_ohci *ohci = ctx->ohci; - struct descriptor *d, *last; - u32 address; - int z; - - dma_sync_single_for_cpu(ohci->card.device, ctx->buffer_bus, - ctx->buffer_size, DMA_TO_DEVICE); - - d = ctx->tail_descriptor; - last = ctx->tail_descriptor_last; - - while (last->branch_address != 0) { - address = le32_to_cpu(last->branch_address); - z = address & 0xf; - d = ctx->buffer + (address - ctx->buffer_bus) / sizeof(*d); - last = (z == 2) ? d : d + z - 1; - - if (!ctx->callback(ctx, d, last)) - break; - - ctx->tail_descriptor = d; - ctx->tail_descriptor_last = last; - } -} - -static int -context_init(struct context *ctx, struct fw_ohci *ohci, - size_t buffer_size, u32 regs, - descriptor_callback_t callback) -{ - ctx->ohci = ohci; - ctx->regs = regs; - ctx->buffer_size = buffer_size; - ctx->buffer = kmalloc(buffer_size, GFP_KERNEL); - if (ctx->buffer == NULL) - return -ENOMEM; - - tasklet_init(&ctx->tasklet, context_tasklet, (unsigned long)ctx); - ctx->callback = callback; - - ctx->buffer_bus = - dma_map_single(ohci->card.device, ctx->buffer, - buffer_size, DMA_TO_DEVICE); - if (dma_mapping_error(ctx->buffer_bus)) { - kfree(ctx->buffer); - return -ENOMEM; - } - - ctx->head_descriptor = ctx->buffer; - ctx->prev_descriptor = ctx->buffer; - ctx->tail_descriptor = ctx->buffer; - ctx->tail_descriptor_last = ctx->buffer; - - /* - * We put a dummy descriptor in the buffer that has a NULL - * branch address and looks like it's been sent. That way we - * have a descriptor to append DMA programs to. Also, the - * ring buffer invariant is that it always has at least one - * element so that head == tail means buffer full. - */ - - memset(ctx->head_descriptor, 0, sizeof(*ctx->head_descriptor)); - ctx->head_descriptor->control = cpu_to_le16(DESCRIPTOR_OUTPUT_LAST); - ctx->head_descriptor->transfer_status = cpu_to_le16(0x8011); - ctx->head_descriptor++; - - return 0; -} - -static void -context_release(struct context *ctx) -{ - struct fw_card *card = &ctx->ohci->card; - - dma_unmap_single(card->device, ctx->buffer_bus, - ctx->buffer_size, DMA_TO_DEVICE); - kfree(ctx->buffer); -} - -static struct descriptor * -context_get_descriptors(struct context *ctx, int z, dma_addr_t *d_bus) -{ - struct descriptor *d, *tail, *end; - - d = ctx->head_descriptor; - tail = ctx->tail_descriptor; - end = ctx->buffer + ctx->buffer_size / sizeof(*d); - - if (d + z <= tail) { - goto has_space; - } else if (d > tail && d + z <= end) { - goto has_space; - } else if (d > tail && ctx->buffer + z <= tail) { - d = ctx->buffer; - goto has_space; - } - - return NULL; - - has_space: - memset(d, 0, z * sizeof(*d)); - *d_bus = ctx->buffer_bus + (d - ctx->buffer) * sizeof(*d); - - return d; -} - -static void context_run(struct context *ctx, u32 extra) -{ - struct fw_ohci *ohci = ctx->ohci; - - reg_write(ohci, COMMAND_PTR(ctx->regs), - le32_to_cpu(ctx->tail_descriptor_last->branch_address)); - reg_write(ohci, CONTROL_CLEAR(ctx->regs), ~0); - reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN | extra); - flush_writes(ohci); -} - -static void context_append(struct context *ctx, - struct descriptor *d, int z, int extra) -{ - dma_addr_t d_bus; - - d_bus = ctx->buffer_bus + (d - ctx->buffer) * sizeof(*d); - - ctx->head_descriptor = d + z + extra; - ctx->prev_descriptor->branch_address = cpu_to_le32(d_bus | z); - ctx->prev_descriptor = z == 2 ? d : d + z - 1; - - dma_sync_single_for_device(ctx->ohci->card.device, ctx->buffer_bus, - ctx->buffer_size, DMA_TO_DEVICE); - - reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); - flush_writes(ctx->ohci); -} - -static void context_stop(struct context *ctx) -{ - u32 reg; - int i; - - reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN); - flush_writes(ctx->ohci); - - for (i = 0; i < 10; i++) { - reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs)); - if ((reg & CONTEXT_ACTIVE) == 0) - break; - - fw_notify("context_stop: still active (0x%08x)\n", reg); - msleep(1); - } -} - -struct driver_data { - struct fw_packet *packet; -}; - -/* - * This function apppends a packet to the DMA queue for transmission. - * Must always be called with the ochi->lock held to ensure proper - * generation handling and locking around packet queue manipulation. - */ -static int -at_context_queue_packet(struct context *ctx, struct fw_packet *packet) -{ - struct fw_ohci *ohci = ctx->ohci; - dma_addr_t d_bus, payload_bus; - struct driver_data *driver_data; - struct descriptor *d, *last; - __le32 *header; - int z, tcode; - u32 reg; - - d = context_get_descriptors(ctx, 4, &d_bus); - if (d == NULL) { - packet->ack = RCODE_SEND_ERROR; - return -1; - } - - d[0].control = cpu_to_le16(DESCRIPTOR_KEY_IMMEDIATE); - d[0].res_count = cpu_to_le16(packet->timestamp); - - /* - * The DMA format for asyncronous link packets is different - * from the IEEE1394 layout, so shift the fields around - * accordingly. If header_length is 8, it's a PHY packet, to - * which we need to prepend an extra quadlet. - */ - - header = (__le32 *) &d[1]; - if (packet->header_length > 8) { - header[0] = cpu_to_le32((packet->header[0] & 0xffff) | - (packet->speed << 16)); - header[1] = cpu_to_le32((packet->header[1] & 0xffff) | - (packet->header[0] & 0xffff0000)); - header[2] = cpu_to_le32(packet->header[2]); - - tcode = (packet->header[0] >> 4) & 0x0f; - if (TCODE_IS_BLOCK_PACKET(tcode)) - header[3] = cpu_to_le32(packet->header[3]); - else - header[3] = (__force __le32) packet->header[3]; - - d[0].req_count = cpu_to_le16(packet->header_length); - } else { - header[0] = cpu_to_le32((OHCI1394_phy_tcode << 4) | - (packet->speed << 16)); - header[1] = cpu_to_le32(packet->header[0]); - header[2] = cpu_to_le32(packet->header[1]); - d[0].req_count = cpu_to_le16(12); - } - - driver_data = (struct driver_data *) &d[3]; - driver_data->packet = packet; - packet->driver_data = driver_data; - - if (packet->payload_length > 0) { - payload_bus = - dma_map_single(ohci->card.device, packet->payload, - packet->payload_length, DMA_TO_DEVICE); - if (dma_mapping_error(payload_bus)) { - packet->ack = RCODE_SEND_ERROR; - return -1; - } - - d[2].req_count = cpu_to_le16(packet->payload_length); - d[2].data_address = cpu_to_le32(payload_bus); - last = &d[2]; - z = 3; - } else { - last = &d[0]; - z = 2; - } - - last->control |= cpu_to_le16(DESCRIPTOR_OUTPUT_LAST | - DESCRIPTOR_IRQ_ALWAYS | - DESCRIPTOR_BRANCH_ALWAYS); - - /* FIXME: Document how the locking works. */ - if (ohci->generation != packet->generation) { - packet->ack = RCODE_GENERATION; - return -1; - } - - context_append(ctx, d, z, 4 - z); - - /* If the context isn't already running, start it up. */ - reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs)); - if ((reg & CONTEXT_RUN) == 0) - context_run(ctx, 0); - - return 0; -} - -static int handle_at_packet(struct context *context, - struct descriptor *d, - struct descriptor *last) -{ - struct driver_data *driver_data; - struct fw_packet *packet; - struct fw_ohci *ohci = context->ohci; - dma_addr_t payload_bus; - int evt; - - if (last->transfer_status == 0) - /* This descriptor isn't done yet, stop iteration. */ - return 0; - - driver_data = (struct driver_data *) &d[3]; - packet = driver_data->packet; - if (packet == NULL) - /* This packet was cancelled, just continue. */ - return 1; - - payload_bus = le32_to_cpu(last->data_address); - if (payload_bus != 0) - dma_unmap_single(ohci->card.device, payload_bus, - packet->payload_length, DMA_TO_DEVICE); - - evt = le16_to_cpu(last->transfer_status) & 0x1f; - packet->timestamp = le16_to_cpu(last->res_count); - - switch (evt) { - case OHCI1394_evt_timeout: - /* Async response transmit timed out. */ - packet->ack = RCODE_CANCELLED; - break; - - case OHCI1394_evt_flushed: - /* - * The packet was flushed should give same error as - * when we try to use a stale generation count. - */ - packet->ack = RCODE_GENERATION; - break; - - case OHCI1394_evt_missing_ack: - /* - * Using a valid (current) generation count, but the - * node is not on the bus or not sending acks. - */ - packet->ack = RCODE_NO_ACK; - break; - - case ACK_COMPLETE + 0x10: - case ACK_PENDING + 0x10: - case ACK_BUSY_X + 0x10: - case ACK_BUSY_A + 0x10: - case ACK_BUSY_B + 0x10: - case ACK_DATA_ERROR + 0x10: - case ACK_TYPE_ERROR + 0x10: - packet->ack = evt - 0x10; - break; - - default: - packet->ack = RCODE_SEND_ERROR; - break; - } - - packet->callback(packet, &ohci->card, packet->ack); - - return 1; -} - -#define HEADER_GET_DESTINATION(q) (((q) >> 16) & 0xffff) -#define HEADER_GET_TCODE(q) (((q) >> 4) & 0x0f) -#define HEADER_GET_OFFSET_HIGH(q) (((q) >> 0) & 0xffff) -#define HEADER_GET_DATA_LENGTH(q) (((q) >> 16) & 0xffff) -#define HEADER_GET_EXTENDED_TCODE(q) (((q) >> 0) & 0xffff) - -static void -handle_local_rom(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) -{ - struct fw_packet response; - int tcode, length, i; - - tcode = HEADER_GET_TCODE(packet->header[0]); - if (TCODE_IS_BLOCK_PACKET(tcode)) - length = HEADER_GET_DATA_LENGTH(packet->header[3]); - else - length = 4; - - i = csr - CSR_CONFIG_ROM; - if (i + length > CONFIG_ROM_SIZE) { - fw_fill_response(&response, packet->header, - RCODE_ADDRESS_ERROR, NULL, 0); - } else if (!TCODE_IS_READ_REQUEST(tcode)) { - fw_fill_response(&response, packet->header, - RCODE_TYPE_ERROR, NULL, 0); - } else { - fw_fill_response(&response, packet->header, RCODE_COMPLETE, - (void *) ohci->config_rom + i, length); - } - - fw_core_handle_response(&ohci->card, &response); -} - -static void -handle_local_lock(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) -{ - struct fw_packet response; - int tcode, length, ext_tcode, sel; - __be32 *payload, lock_old; - u32 lock_arg, lock_data; - - tcode = HEADER_GET_TCODE(packet->header[0]); - length = HEADER_GET_DATA_LENGTH(packet->header[3]); - payload = packet->payload; - ext_tcode = HEADER_GET_EXTENDED_TCODE(packet->header[3]); - - if (tcode == TCODE_LOCK_REQUEST && - ext_tcode == EXTCODE_COMPARE_SWAP && length == 8) { - lock_arg = be32_to_cpu(payload[0]); - lock_data = be32_to_cpu(payload[1]); - } else if (tcode == TCODE_READ_QUADLET_REQUEST) { - lock_arg = 0; - lock_data = 0; - } else { - fw_fill_response(&response, packet->header, - RCODE_TYPE_ERROR, NULL, 0); - goto out; - } - - sel = (csr - CSR_BUS_MANAGER_ID) / 4; - reg_write(ohci, OHCI1394_CSRData, lock_data); - reg_write(ohci, OHCI1394_CSRCompareData, lock_arg); - reg_write(ohci, OHCI1394_CSRControl, sel); - - if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000) - lock_old = cpu_to_be32(reg_read(ohci, OHCI1394_CSRData)); - else - fw_notify("swap not done yet\n"); - - fw_fill_response(&response, packet->header, - RCODE_COMPLETE, &lock_old, sizeof(lock_old)); - out: - fw_core_handle_response(&ohci->card, &response); -} - -static void -handle_local_request(struct context *ctx, struct fw_packet *packet) -{ - u64 offset; - u32 csr; - - if (ctx == &ctx->ohci->at_request_ctx) { - packet->ack = ACK_PENDING; - packet->callback(packet, &ctx->ohci->card, packet->ack); - } - - offset = - ((unsigned long long) - HEADER_GET_OFFSET_HIGH(packet->header[1]) << 32) | - packet->header[2]; - csr = offset - CSR_REGISTER_BASE; - - /* Handle config rom reads. */ - if (csr >= CSR_CONFIG_ROM && csr < CSR_CONFIG_ROM_END) - handle_local_rom(ctx->ohci, packet, csr); - else switch (csr) { - case CSR_BUS_MANAGER_ID: - case CSR_BANDWIDTH_AVAILABLE: - case CSR_CHANNELS_AVAILABLE_HI: - case CSR_CHANNELS_AVAILABLE_LO: - handle_local_lock(ctx->ohci, packet, csr); - break; - default: - if (ctx == &ctx->ohci->at_request_ctx) - fw_core_handle_request(&ctx->ohci->card, packet); - else - fw_core_handle_response(&ctx->ohci->card, packet); - break; - } - - if (ctx == &ctx->ohci->at_response_ctx) { - packet->ack = ACK_COMPLETE; - packet->callback(packet, &ctx->ohci->card, packet->ack); - } -} - -static void -at_context_transmit(struct context *ctx, struct fw_packet *packet) -{ - unsigned long flags; - int retval; - - spin_lock_irqsave(&ctx->ohci->lock, flags); - - if (HEADER_GET_DESTINATION(packet->header[0]) == ctx->ohci->node_id && - ctx->ohci->generation == packet->generation) { - spin_unlock_irqrestore(&ctx->ohci->lock, flags); - handle_local_request(ctx, packet); - return; - } - - retval = at_context_queue_packet(ctx, packet); - spin_unlock_irqrestore(&ctx->ohci->lock, flags); - - if (retval < 0) - packet->callback(packet, &ctx->ohci->card, packet->ack); - -} - -static void bus_reset_tasklet(unsigned long data) -{ - struct fw_ohci *ohci = (struct fw_ohci *)data; - int self_id_count, i, j, reg; - int generation, new_generation; - unsigned long flags; - - reg = reg_read(ohci, OHCI1394_NodeID); - if (!(reg & OHCI1394_NodeID_idValid)) { - fw_error("node ID not valid, new bus reset in progress\n"); - return; - } - ohci->node_id = reg & 0xffff; - - /* - * The count in the SelfIDCount register is the number of - * bytes in the self ID receive buffer. Since we also receive - * the inverted quadlets and a header quadlet, we shift one - * bit extra to get the actual number of self IDs. - */ - - self_id_count = (reg_read(ohci, OHCI1394_SelfIDCount) >> 3) & 0x3ff; - generation = (le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff; - - for (i = 1, j = 0; j < self_id_count; i += 2, j++) { - if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) - fw_error("inconsistent self IDs\n"); - ohci->self_id_buffer[j] = le32_to_cpu(ohci->self_id_cpu[i]); - } - - /* - * Check the consistency of the self IDs we just read. The - * problem we face is that a new bus reset can start while we - * read out the self IDs from the DMA buffer. If this happens, - * the DMA buffer will be overwritten with new self IDs and we - * will read out inconsistent data. The OHCI specification - * (section 11.2) recommends a technique similar to - * linux/seqlock.h, where we remember the generation of the - * self IDs in the buffer before reading them out and compare - * it to the current generation after reading them out. If - * the two generations match we know we have a consistent set - * of self IDs. - */ - - new_generation = (reg_read(ohci, OHCI1394_SelfIDCount) >> 16) & 0xff; - if (new_generation != generation) { - fw_notify("recursive bus reset detected, " - "discarding self ids\n"); - return; - } - - /* FIXME: Document how the locking works. */ - spin_lock_irqsave(&ohci->lock, flags); - - ohci->generation = generation; - context_stop(&ohci->at_request_ctx); - context_stop(&ohci->at_response_ctx); - reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); - - /* - * This next bit is unrelated to the AT context stuff but we - * have to do it under the spinlock also. If a new config rom - * was set up before this reset, the old one is now no longer - * in use and we can free it. Update the config rom pointers - * to point to the current config rom and clear the - * next_config_rom pointer so a new udpate can take place. - */ - - if (ohci->next_config_rom != NULL) { - dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, - ohci->config_rom, ohci->config_rom_bus); - ohci->config_rom = ohci->next_config_rom; - ohci->config_rom_bus = ohci->next_config_rom_bus; - ohci->next_config_rom = NULL; - - /* - * Restore config_rom image and manually update - * config_rom registers. Writing the header quadlet - * will indicate that the config rom is ready, so we - * do that last. - */ - reg_write(ohci, OHCI1394_BusOptions, - be32_to_cpu(ohci->config_rom[2])); - ohci->config_rom[0] = cpu_to_be32(ohci->next_header); - reg_write(ohci, OHCI1394_ConfigROMhdr, ohci->next_header); - } - - spin_unlock_irqrestore(&ohci->lock, flags); - - fw_core_handle_bus_reset(&ohci->card, ohci->node_id, generation, - self_id_count, ohci->self_id_buffer); -} - -static irqreturn_t irq_handler(int irq, void *data) -{ - struct fw_ohci *ohci = data; - u32 event, iso_event, cycle_time; - int i; - - event = reg_read(ohci, OHCI1394_IntEventClear); - - if (!event) - return IRQ_NONE; - - reg_write(ohci, OHCI1394_IntEventClear, event); - - if (event & OHCI1394_selfIDComplete) - tasklet_schedule(&ohci->bus_reset_tasklet); - - if (event & OHCI1394_RQPkt) - tasklet_schedule(&ohci->ar_request_ctx.tasklet); - - if (event & OHCI1394_RSPkt) - tasklet_schedule(&ohci->ar_response_ctx.tasklet); - - if (event & OHCI1394_reqTxComplete) - tasklet_schedule(&ohci->at_request_ctx.tasklet); - - if (event & OHCI1394_respTxComplete) - tasklet_schedule(&ohci->at_response_ctx.tasklet); - - iso_event = reg_read(ohci, OHCI1394_IsoRecvIntEventClear); - reg_write(ohci, OHCI1394_IsoRecvIntEventClear, iso_event); - - while (iso_event) { - i = ffs(iso_event) - 1; - tasklet_schedule(&ohci->ir_context_list[i].context.tasklet); - iso_event &= ~(1 << i); - } - - iso_event = reg_read(ohci, OHCI1394_IsoXmitIntEventClear); - reg_write(ohci, OHCI1394_IsoXmitIntEventClear, iso_event); - - while (iso_event) { - i = ffs(iso_event) - 1; - tasklet_schedule(&ohci->it_context_list[i].context.tasklet); - iso_event &= ~(1 << i); - } - - if (event & OHCI1394_cycle64Seconds) { - cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer); - if ((cycle_time & 0x80000000) == 0) - ohci->bus_seconds++; - } - - return IRQ_HANDLED; -} - -static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) -{ - struct fw_ohci *ohci = fw_ohci(card); - struct pci_dev *dev = to_pci_dev(card->device); - - /* - * When the link is not yet enabled, the atomic config rom - * update mechanism described below in ohci_set_config_rom() - * is not active. We have to update ConfigRomHeader and - * BusOptions manually, and the write to ConfigROMmap takes - * effect immediately. We tie this to the enabling of the - * link, so we have a valid config rom before enabling - the - * OHCI requires that ConfigROMhdr and BusOptions have valid - * values before enabling. - * - * However, when the ConfigROMmap is written, some controllers - * always read back quadlets 0 and 2 from the config rom to - * the ConfigRomHeader and BusOptions registers on bus reset. - * They shouldn't do that in this initial case where the link - * isn't enabled. This means we have to use the same - * workaround here, setting the bus header to 0 and then write - * the right values in the bus reset tasklet. - */ - - ohci->next_config_rom = - dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE, - &ohci->next_config_rom_bus, GFP_KERNEL); - if (ohci->next_config_rom == NULL) - return -ENOMEM; - - memset(ohci->next_config_rom, 0, CONFIG_ROM_SIZE); - fw_memcpy_to_be32(ohci->next_config_rom, config_rom, length * 4); - - ohci->next_header = config_rom[0]; - ohci->next_config_rom[0] = 0; - reg_write(ohci, OHCI1394_ConfigROMhdr, 0); - reg_write(ohci, OHCI1394_BusOptions, config_rom[2]); - reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus); - - reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000); - - if (request_irq(dev->irq, irq_handler, - IRQF_SHARED, ohci_driver_name, ohci)) { - fw_error("Failed to allocate shared interrupt %d.\n", - dev->irq); - dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, - ohci->config_rom, ohci->config_rom_bus); - return -EIO; - } - - reg_write(ohci, OHCI1394_HCControlSet, - OHCI1394_HCControl_linkEnable | - OHCI1394_HCControl_BIBimageValid); - flush_writes(ohci); - - /* - * We are ready to go, initiate bus reset to finish the - * initialization. - */ - - fw_core_initiate_bus_reset(&ohci->card, 1); - - return 0; -} - -static int -ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length) -{ - struct fw_ohci *ohci; - unsigned long flags; - int retval = 0; - __be32 *next_config_rom; - dma_addr_t next_config_rom_bus; - - ohci = fw_ohci(card); - - /* - * When the OHCI controller is enabled, the config rom update - * mechanism is a bit tricky, but easy enough to use. See - * section 5.5.6 in the OHCI specification. - * - * The OHCI controller caches the new config rom address in a - * shadow register (ConfigROMmapNext) and needs a bus reset - * for the changes to take place. When the bus reset is - * detected, the controller loads the new values for the - * ConfigRomHeader and BusOptions registers from the specified - * config rom and loads ConfigROMmap from the ConfigROMmapNext - * shadow register. All automatically and atomically. - * - * Now, there's a twist to this story. The automatic load of - * ConfigRomHeader and BusOptions doesn't honor the - * noByteSwapData bit, so with a be32 config rom, the - * controller will load be32 values in to these registers - * during the atomic update, even on litte endian - * architectures. The workaround we use is to put a 0 in the - * header quadlet; 0 is endian agnostic and means that the - * config rom isn't ready yet. In the bus reset tasklet we - * then set up the real values for the two registers. - * - * We use ohci->lock to avoid racing with the code that sets - * ohci->next_config_rom to NULL (see bus_reset_tasklet). - */ - - next_config_rom = - dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE, - &next_config_rom_bus, GFP_KERNEL); - if (next_config_rom == NULL) - return -ENOMEM; - - spin_lock_irqsave(&ohci->lock, flags); - - if (ohci->next_config_rom == NULL) { - ohci->next_config_rom = next_config_rom; - ohci->next_config_rom_bus = next_config_rom_bus; - - memset(ohci->next_config_rom, 0, CONFIG_ROM_SIZE); - fw_memcpy_to_be32(ohci->next_config_rom, config_rom, - length * 4); - - ohci->next_header = config_rom[0]; - ohci->next_config_rom[0] = 0; - - reg_write(ohci, OHCI1394_ConfigROMmap, - ohci->next_config_rom_bus); - } else { - dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, - next_config_rom, next_config_rom_bus); - retval = -EBUSY; - } - - spin_unlock_irqrestore(&ohci->lock, flags); - - /* - * Now initiate a bus reset to have the changes take - * effect. We clean up the old config rom memory and DMA - * mappings in the bus reset tasklet, since the OHCI - * controller could need to access it before the bus reset - * takes effect. - */ - if (retval == 0) - fw_core_initiate_bus_reset(&ohci->card, 1); - - return retval; -} - -static void ohci_send_request(struct fw_card *card, struct fw_packet *packet) -{ - struct fw_ohci *ohci = fw_ohci(card); - - at_context_transmit(&ohci->at_request_ctx, packet); -} - -static void ohci_send_response(struct fw_card *card, struct fw_packet *packet) -{ - struct fw_ohci *ohci = fw_ohci(card); - - at_context_transmit(&ohci->at_response_ctx, packet); -} - -static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) -{ - struct fw_ohci *ohci = fw_ohci(card); - struct context *ctx = &ohci->at_request_ctx; - struct driver_data *driver_data = packet->driver_data; - int retval = -ENOENT; - - tasklet_disable(&ctx->tasklet); - - if (packet->ack != 0) - goto out; - - driver_data->packet = NULL; - packet->ack = RCODE_CANCELLED; - packet->callback(packet, &ohci->card, packet->ack); - retval = 0; - - out: - tasklet_enable(&ctx->tasklet); - - return retval; -} - -static int -ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) -{ - struct fw_ohci *ohci = fw_ohci(card); - unsigned long flags; - int n, retval = 0; - - /* - * FIXME: Make sure this bitmask is cleared when we clear the busReset - * interrupt bit. Clear physReqResourceAllBuses on bus reset. - */ - - spin_lock_irqsave(&ohci->lock, flags); - - if (ohci->generation != generation) { - retval = -ESTALE; - goto out; - } - - /* - * Note, if the node ID contains a non-local bus ID, physical DMA is - * enabled for _all_ nodes on remote buses. - */ - - n = (node_id & 0xffc0) == LOCAL_BUS ? node_id & 0x3f : 63; - if (n < 32) - reg_write(ohci, OHCI1394_PhyReqFilterLoSet, 1 << n); - else - reg_write(ohci, OHCI1394_PhyReqFilterHiSet, 1 << (n - 32)); - - flush_writes(ohci); - out: - spin_unlock_irqrestore(&ohci->lock, flags); - return retval; -} - -static u64 -ohci_get_bus_time(struct fw_card *card) -{ - struct fw_ohci *ohci = fw_ohci(card); - u32 cycle_time; - u64 bus_time; - - cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer); - bus_time = ((u64) ohci->bus_seconds << 32) | cycle_time; - - return bus_time; -} - -static int handle_ir_dualbuffer_packet(struct context *context, - struct descriptor *d, - struct descriptor *last) -{ - struct iso_context *ctx = - container_of(context, struct iso_context, context); - struct db_descriptor *db = (struct db_descriptor *) d; - __le32 *ir_header; - size_t header_length; - void *p, *end; - int i; - - if (db->first_res_count > 0 && db->second_res_count > 0) - /* This descriptor isn't done yet, stop iteration. */ - return 0; - - header_length = le16_to_cpu(db->first_req_count) - - le16_to_cpu(db->first_res_count); - - i = ctx->header_length; - p = db + 1; - end = p + header_length; - while (p < end && i + ctx->base.header_size <= PAGE_SIZE) { - /* - * The iso header is byteswapped to little endian by - * the controller, but the remaining header quadlets - * are big endian. We want to present all the headers - * as big endian, so we have to swap the first - * quadlet. - */ - *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); - memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4); - i += ctx->base.header_size; - p += ctx->base.header_size + 4; - } - - ctx->header_length = i; - - if (le16_to_cpu(db->control) & DESCRIPTOR_IRQ_ALWAYS) { - ir_header = (__le32 *) (db + 1); - ctx->base.callback(&ctx->base, - le32_to_cpu(ir_header[0]) & 0xffff, - ctx->header_length, ctx->header, - ctx->base.callback_data); - ctx->header_length = 0; - } - - return 1; -} - -static int handle_it_packet(struct context *context, - struct descriptor *d, - struct descriptor *last) -{ - struct iso_context *ctx = - container_of(context, struct iso_context, context); - - if (last->transfer_status == 0) - /* This descriptor isn't done yet, stop iteration. */ - return 0; - - if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) - ctx->base.callback(&ctx->base, le16_to_cpu(last->res_count), - 0, NULL, ctx->base.callback_data); - - return 1; -} - -static struct fw_iso_context * -ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) -{ - struct fw_ohci *ohci = fw_ohci(card); - struct iso_context *ctx, *list; - descriptor_callback_t callback; - u32 *mask, regs; - unsigned long flags; - int index, retval = -ENOMEM; - - if (type == FW_ISO_CONTEXT_TRANSMIT) { - mask = &ohci->it_context_mask; - list = ohci->it_context_list; - callback = handle_it_packet; - } else { - mask = &ohci->ir_context_mask; - list = ohci->ir_context_list; - callback = handle_ir_dualbuffer_packet; - } - - /* FIXME: We need a fallback for pre 1.1 OHCI. */ - if (callback == handle_ir_dualbuffer_packet && - ohci->version < OHCI_VERSION_1_1) - return ERR_PTR(-EINVAL); - - spin_lock_irqsave(&ohci->lock, flags); - index = ffs(*mask) - 1; - if (index >= 0) - *mask &= ~(1 << index); - spin_unlock_irqrestore(&ohci->lock, flags); - - if (index < 0) - return ERR_PTR(-EBUSY); - - if (type == FW_ISO_CONTEXT_TRANSMIT) - regs = OHCI1394_IsoXmitContextBase(index); - else - regs = OHCI1394_IsoRcvContextBase(index); - - ctx = &list[index]; - memset(ctx, 0, sizeof(*ctx)); - ctx->header_length = 0; - ctx->header = (void *) __get_free_page(GFP_KERNEL); - if (ctx->header == NULL) - goto out; - - retval = context_init(&ctx->context, ohci, ISO_BUFFER_SIZE, - regs, callback); - if (retval < 0) - goto out_with_header; - - return &ctx->base; - - out_with_header: - free_page((unsigned long)ctx->header); - out: - spin_lock_irqsave(&ohci->lock, flags); - *mask |= 1 << index; - spin_unlock_irqrestore(&ohci->lock, flags); - - return ERR_PTR(retval); -} - -static int ohci_start_iso(struct fw_iso_context *base, - s32 cycle, u32 sync, u32 tags) -{ - struct iso_context *ctx = container_of(base, struct iso_context, base); - struct fw_ohci *ohci = ctx->context.ohci; - u32 control, match; - int index; - - if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) { - index = ctx - ohci->it_context_list; - match = 0; - if (cycle >= 0) - match = IT_CONTEXT_CYCLE_MATCH_ENABLE | - (cycle & 0x7fff) << 16; - - reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 1 << index); - reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << index); - context_run(&ctx->context, match); - } else { - index = ctx - ohci->ir_context_list; - control = IR_CONTEXT_DUAL_BUFFER_MODE | IR_CONTEXT_ISOCH_HEADER; - match = (tags << 28) | (sync << 8) | ctx->base.channel; - if (cycle >= 0) { - match |= (cycle & 0x07fff) << 12; - control |= IR_CONTEXT_CYCLE_MATCH_ENABLE; - } - - reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index); - reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index); - reg_write(ohci, CONTEXT_MATCH(ctx->context.regs), match); - context_run(&ctx->context, control); - } - - return 0; -} - -static int ohci_stop_iso(struct fw_iso_context *base) -{ - struct fw_ohci *ohci = fw_ohci(base->card); - struct iso_context *ctx = container_of(base, struct iso_context, base); - int index; - - if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) { - index = ctx - ohci->it_context_list; - reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 1 << index); - } else { - index = ctx - ohci->ir_context_list; - reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 1 << index); - } - flush_writes(ohci); - context_stop(&ctx->context); - - return 0; -} - -static void ohci_free_iso_context(struct fw_iso_context *base) -{ - struct fw_ohci *ohci = fw_ohci(base->card); - struct iso_context *ctx = container_of(base, struct iso_context, base); - unsigned long flags; - int index; - - ohci_stop_iso(base); - context_release(&ctx->context); - free_page((unsigned long)ctx->header); - - spin_lock_irqsave(&ohci->lock, flags); - - if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) { - index = ctx - ohci->it_context_list; - ohci->it_context_mask |= 1 << index; - } else { - index = ctx - ohci->ir_context_list; - ohci->ir_context_mask |= 1 << index; - } - - spin_unlock_irqrestore(&ohci->lock, flags); -} - -static int -ohci_queue_iso_transmit(struct fw_iso_context *base, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload) -{ - struct iso_context *ctx = container_of(base, struct iso_context, base); - struct descriptor *d, *last, *pd; - struct fw_iso_packet *p; - __le32 *header; - dma_addr_t d_bus, page_bus; - u32 z, header_z, payload_z, irq; - u32 payload_index, payload_end_index, next_page_index; - int page, end_page, i, length, offset; - - /* - * FIXME: Cycle lost behavior should be configurable: lose - * packet, retransmit or terminate.. - */ - - p = packet; - payload_index = payload; - - if (p->skip) - z = 1; - else - z = 2; - if (p->header_length > 0) - z++; - - /* Determine the first page the payload isn't contained in. */ - end_page = PAGE_ALIGN(payload_index + p->payload_length) >> PAGE_SHIFT; - if (p->payload_length > 0) - payload_z = end_page - (payload_index >> PAGE_SHIFT); - else - payload_z = 0; - - z += payload_z; - - /* Get header size in number of descriptors. */ - header_z = DIV_ROUND_UP(p->header_length, sizeof(*d)); - - d = context_get_descriptors(&ctx->context, z + header_z, &d_bus); - if (d == NULL) - return -ENOMEM; - - if (!p->skip) { - d[0].control = cpu_to_le16(DESCRIPTOR_KEY_IMMEDIATE); - d[0].req_count = cpu_to_le16(8); - - header = (__le32 *) &d[1]; - header[0] = cpu_to_le32(IT_HEADER_SY(p->sy) | - IT_HEADER_TAG(p->tag) | - IT_HEADER_TCODE(TCODE_STREAM_DATA) | - IT_HEADER_CHANNEL(ctx->base.channel) | - IT_HEADER_SPEED(ctx->base.speed)); - header[1] = - cpu_to_le32(IT_HEADER_DATA_LENGTH(p->header_length + - p->payload_length)); - } - - if (p->header_length > 0) { - d[2].req_count = cpu_to_le16(p->header_length); - d[2].data_address = cpu_to_le32(d_bus + z * sizeof(*d)); - memcpy(&d[z], p->header, p->header_length); - } - - pd = d + z - payload_z; - payload_end_index = payload_index + p->payload_length; - for (i = 0; i < payload_z; i++) { - page = payload_index >> PAGE_SHIFT; - offset = payload_index & ~PAGE_MASK; - next_page_index = (page + 1) << PAGE_SHIFT; - length = - min(next_page_index, payload_end_index) - payload_index; - pd[i].req_count = cpu_to_le16(length); - - page_bus = page_private(buffer->pages[page]); - pd[i].data_address = cpu_to_le32(page_bus + offset); - - payload_index += length; - } - - if (p->interrupt) - irq = DESCRIPTOR_IRQ_ALWAYS; - else - irq = DESCRIPTOR_NO_IRQ; - - last = z == 2 ? d : d + z - 1; - last->control |= cpu_to_le16(DESCRIPTOR_OUTPUT_LAST | - DESCRIPTOR_STATUS | - DESCRIPTOR_BRANCH_ALWAYS | - irq); - - context_append(&ctx->context, d, z, header_z); - - return 0; -} - -static int -ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload) -{ - struct iso_context *ctx = container_of(base, struct iso_context, base); - struct db_descriptor *db = NULL; - struct descriptor *d; - struct fw_iso_packet *p; - dma_addr_t d_bus, page_bus; - u32 z, header_z, length, rest; - int page, offset, packet_count, header_size; - - /* - * FIXME: Cycle lost behavior should be configurable: lose - * packet, retransmit or terminate.. - */ - - if (packet->skip) { - d = context_get_descriptors(&ctx->context, 2, &d_bus); - if (d == NULL) - return -ENOMEM; - - db = (struct db_descriptor *) d; - db->control = cpu_to_le16(DESCRIPTOR_STATUS | - DESCRIPTOR_BRANCH_ALWAYS | - DESCRIPTOR_WAIT); - db->first_size = cpu_to_le16(ctx->base.header_size + 4); - context_append(&ctx->context, d, 2, 0); - } - - p = packet; - z = 2; - - /* - * The OHCI controller puts the status word in the header - * buffer too, so we need 4 extra bytes per packet. - */ - packet_count = p->header_length / ctx->base.header_size; - header_size = packet_count * (ctx->base.header_size + 4); - - /* Get header size in number of descriptors. */ - header_z = DIV_ROUND_UP(header_size, sizeof(*d)); - page = payload >> PAGE_SHIFT; - offset = payload & ~PAGE_MASK; - rest = p->payload_length; - - /* FIXME: OHCI 1.0 doesn't support dual buffer receive */ - /* FIXME: make packet-per-buffer/dual-buffer a context option */ - while (rest > 0) { - d = context_get_descriptors(&ctx->context, - z + header_z, &d_bus); - if (d == NULL) - return -ENOMEM; - - db = (struct db_descriptor *) d; - db->control = cpu_to_le16(DESCRIPTOR_STATUS | - DESCRIPTOR_BRANCH_ALWAYS); - db->first_size = cpu_to_le16(ctx->base.header_size + 4); - db->first_req_count = cpu_to_le16(header_size); - db->first_res_count = db->first_req_count; - db->first_buffer = cpu_to_le32(d_bus + sizeof(*db)); - - if (offset + rest < PAGE_SIZE) - length = rest; - else - length = PAGE_SIZE - offset; - - db->second_req_count = cpu_to_le16(length); - db->second_res_count = db->second_req_count; - page_bus = page_private(buffer->pages[page]); - db->second_buffer = cpu_to_le32(page_bus + offset); - - if (p->interrupt && length == rest) - db->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS); - - context_append(&ctx->context, d, z, header_z); - offset = (offset + length) & ~PAGE_MASK; - rest -= length; - page++; - } - - return 0; -} - -static int -ohci_queue_iso(struct fw_iso_context *base, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload) -{ - struct iso_context *ctx = container_of(base, struct iso_context, base); - - if (base->type == FW_ISO_CONTEXT_TRANSMIT) - return ohci_queue_iso_transmit(base, packet, buffer, payload); - else if (ctx->context.ohci->version >= OHCI_VERSION_1_1) - return ohci_queue_iso_receive_dualbuffer(base, packet, - buffer, payload); - else - /* FIXME: Implement fallback for OHCI 1.0 controllers. */ - return -EINVAL; -} - -static const struct fw_card_driver ohci_driver = { - .name = ohci_driver_name, - .enable = ohci_enable, - .update_phy_reg = ohci_update_phy_reg, - .set_config_rom = ohci_set_config_rom, - .send_request = ohci_send_request, - .send_response = ohci_send_response, - .cancel_packet = ohci_cancel_packet, - .enable_phys_dma = ohci_enable_phys_dma, - .get_bus_time = ohci_get_bus_time, - - .allocate_iso_context = ohci_allocate_iso_context, - .free_iso_context = ohci_free_iso_context, - .queue_iso = ohci_queue_iso, - .start_iso = ohci_start_iso, - .stop_iso = ohci_stop_iso, -}; - -static int software_reset(struct fw_ohci *ohci) -{ - int i; - - reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset); - - for (i = 0; i < OHCI_LOOP_COUNT; i++) { - if ((reg_read(ohci, OHCI1394_HCControlSet) & - OHCI1394_HCControl_softReset) == 0) - return 0; - msleep(1); - } - - return -EBUSY; -} - -static int __devinit -pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) -{ - struct fw_ohci *ohci; - u32 bus_options, max_receive, link_speed; - u64 guid; - int err; - size_t size; - - ohci = kzalloc(sizeof(*ohci), GFP_KERNEL); - if (ohci == NULL) { - fw_error("Could not malloc fw_ohci data.\n"); - return -ENOMEM; - } - - fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev); - - err = pci_enable_device(dev); - if (err) { - fw_error("Failed to enable OHCI hardware.\n"); - goto fail_put_card; - } - - pci_set_master(dev); - pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0); - pci_set_drvdata(dev, ohci); - - spin_lock_init(&ohci->lock); - - tasklet_init(&ohci->bus_reset_tasklet, - bus_reset_tasklet, (unsigned long)ohci); - - err = pci_request_region(dev, 0, ohci_driver_name); - if (err) { - fw_error("MMIO resource unavailable\n"); - goto fail_disable; - } - - ohci->registers = pci_iomap(dev, 0, OHCI1394_REGISTER_SIZE); - if (ohci->registers == NULL) { - fw_error("Failed to remap registers\n"); - err = -ENXIO; - goto fail_iomem; - } - - if (software_reset(ohci)) { - fw_error("Failed to reset ohci card.\n"); - err = -EBUSY; - goto fail_registers; - } - - /* - * Now enable LPS, which we need in order to start accessing - * most of the registers. In fact, on some cards (ALI M5251), - * accessing registers in the SClk domain without LPS enabled - * will lock up the machine. Wait 50msec to make sure we have - * full link enabled. - */ - reg_write(ohci, OHCI1394_HCControlSet, - OHCI1394_HCControl_LPS | - OHCI1394_HCControl_postedWriteEnable); - flush_writes(ohci); - msleep(50); - - reg_write(ohci, OHCI1394_HCControlClear, - OHCI1394_HCControl_noByteSwapData); - - reg_write(ohci, OHCI1394_LinkControlSet, - OHCI1394_LinkControl_rcvSelfID | - OHCI1394_LinkControl_cycleTimerEnable | - OHCI1394_LinkControl_cycleMaster); - - ar_context_init(&ohci->ar_request_ctx, ohci, - OHCI1394_AsReqRcvContextControlSet); - - ar_context_init(&ohci->ar_response_ctx, ohci, - OHCI1394_AsRspRcvContextControlSet); - - context_init(&ohci->at_request_ctx, ohci, AT_BUFFER_SIZE, - OHCI1394_AsReqTrContextControlSet, handle_at_packet); - - context_init(&ohci->at_response_ctx, ohci, AT_BUFFER_SIZE, - OHCI1394_AsRspTrContextControlSet, handle_at_packet); - - reg_write(ohci, OHCI1394_ATRetries, - OHCI1394_MAX_AT_REQ_RETRIES | - (OHCI1394_MAX_AT_RESP_RETRIES << 4) | - (OHCI1394_MAX_PHYS_RESP_RETRIES << 8)); - - reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0); - ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet); - reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0); - size = sizeof(struct iso_context) * hweight32(ohci->it_context_mask); - ohci->it_context_list = kzalloc(size, GFP_KERNEL); - - reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0); - ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet); - reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0); - size = sizeof(struct iso_context) * hweight32(ohci->ir_context_mask); - ohci->ir_context_list = kzalloc(size, GFP_KERNEL); - - if (ohci->it_context_list == NULL || ohci->ir_context_list == NULL) { - fw_error("Out of memory for it/ir contexts.\n"); - err = -ENOMEM; - goto fail_registers; - } - - /* self-id dma buffer allocation */ - ohci->self_id_cpu = dma_alloc_coherent(ohci->card.device, - SELF_ID_BUF_SIZE, - &ohci->self_id_bus, - GFP_KERNEL); - if (ohci->self_id_cpu == NULL) { - fw_error("Out of memory for self ID buffer.\n"); - err = -ENOMEM; - goto fail_registers; - } - - reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus); - reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000); - reg_write(ohci, OHCI1394_IntEventClear, ~0); - reg_write(ohci, OHCI1394_IntMaskClear, ~0); - reg_write(ohci, OHCI1394_IntMaskSet, - OHCI1394_selfIDComplete | - OHCI1394_RQPkt | OHCI1394_RSPkt | - OHCI1394_reqTxComplete | OHCI1394_respTxComplete | - OHCI1394_isochRx | OHCI1394_isochTx | - OHCI1394_masterIntEnable | - OHCI1394_cycle64Seconds); - - bus_options = reg_read(ohci, OHCI1394_BusOptions); - max_receive = (bus_options >> 12) & 0xf; - link_speed = bus_options & 0x7; - guid = ((u64) reg_read(ohci, OHCI1394_GUIDHi) << 32) | - reg_read(ohci, OHCI1394_GUIDLo); - - err = fw_card_add(&ohci->card, max_receive, link_speed, guid); - if (err < 0) - goto fail_self_id; - - ohci->version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; - fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n", - dev->dev.bus_id, ohci->version >> 16, ohci->version & 0xff); - - return 0; - - fail_self_id: - dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE, - ohci->self_id_cpu, ohci->self_id_bus); - fail_registers: - kfree(ohci->it_context_list); - kfree(ohci->ir_context_list); - pci_iounmap(dev, ohci->registers); - fail_iomem: - pci_release_region(dev, 0); - fail_disable: - pci_disable_device(dev); - fail_put_card: - fw_card_put(&ohci->card); - - return err; -} - -static void pci_remove(struct pci_dev *dev) -{ - struct fw_ohci *ohci; - - ohci = pci_get_drvdata(dev); - reg_write(ohci, OHCI1394_IntMaskClear, ~0); - flush_writes(ohci); - fw_core_remove_card(&ohci->card); - - /* - * FIXME: Fail all pending packets here, now that the upper - * layers can't queue any more. - */ - - software_reset(ohci); - free_irq(dev->irq, ohci); - dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE, - ohci->self_id_cpu, ohci->self_id_bus); - kfree(ohci->it_context_list); - kfree(ohci->ir_context_list); - pci_iounmap(dev, ohci->registers); - pci_release_region(dev, 0); - pci_disable_device(dev); - fw_card_put(&ohci->card); - - fw_notify("Removed fw-ohci device.\n"); -} - -static struct pci_device_id pci_table[] = { - { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_FIREWIRE_OHCI, ~0) }, - { } -}; - -MODULE_DEVICE_TABLE(pci, pci_table); - -static struct pci_driver fw_ohci_pci_driver = { - .name = ohci_driver_name, - .id_table = pci_table, - .probe = pci_probe, - .remove = pci_remove, -}; - -MODULE_AUTHOR("Kristian Hoegsberg "); -MODULE_DESCRIPTION("Driver for PCI OHCI IEEE1394 controllers"); -MODULE_LICENSE("GPL"); - -/* Provide a module alias so root-on-sbp2 initrds don't break. */ -#ifndef CONFIG_IEEE1394_OHCI1394_MODULE -MODULE_ALIAS("ohci1394"); -#endif - -static int __init fw_ohci_init(void) -{ - return pci_register_driver(&fw_ohci_pci_driver); -} - -static void __exit fw_ohci_cleanup(void) -{ - pci_unregister_driver(&fw_ohci_pci_driver); -} - -module_init(fw_ohci_init); -module_exit(fw_ohci_cleanup); diff --git a/trunk/drivers/firewire/fw-ohci.h b/trunk/drivers/firewire/fw-ohci.h deleted file mode 100644 index fa15706397d7..000000000000 --- a/trunk/drivers/firewire/fw-ohci.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef __fw_ohci_h -#define __fw_ohci_h - -/* OHCI register map */ - -#define OHCI1394_Version 0x000 -#define OHCI1394_GUID_ROM 0x004 -#define OHCI1394_ATRetries 0x008 -#define OHCI1394_CSRData 0x00C -#define OHCI1394_CSRCompareData 0x010 -#define OHCI1394_CSRControl 0x014 -#define OHCI1394_ConfigROMhdr 0x018 -#define OHCI1394_BusID 0x01C -#define OHCI1394_BusOptions 0x020 -#define OHCI1394_GUIDHi 0x024 -#define OHCI1394_GUIDLo 0x028 -#define OHCI1394_ConfigROMmap 0x034 -#define OHCI1394_PostedWriteAddressLo 0x038 -#define OHCI1394_PostedWriteAddressHi 0x03C -#define OHCI1394_VendorID 0x040 -#define OHCI1394_HCControlSet 0x050 -#define OHCI1394_HCControlClear 0x054 -#define OHCI1394_HCControl_BIBimageValid 0x80000000 -#define OHCI1394_HCControl_noByteSwapData 0x40000000 -#define OHCI1394_HCControl_programPhyEnable 0x00800000 -#define OHCI1394_HCControl_aPhyEnhanceEnable 0x00400000 -#define OHCI1394_HCControl_LPS 0x00080000 -#define OHCI1394_HCControl_postedWriteEnable 0x00040000 -#define OHCI1394_HCControl_linkEnable 0x00020000 -#define OHCI1394_HCControl_softReset 0x00010000 -#define OHCI1394_SelfIDBuffer 0x064 -#define OHCI1394_SelfIDCount 0x068 -#define OHCI1394_IRMultiChanMaskHiSet 0x070 -#define OHCI1394_IRMultiChanMaskHiClear 0x074 -#define OHCI1394_IRMultiChanMaskLoSet 0x078 -#define OHCI1394_IRMultiChanMaskLoClear 0x07C -#define OHCI1394_IntEventSet 0x080 -#define OHCI1394_IntEventClear 0x084 -#define OHCI1394_IntMaskSet 0x088 -#define OHCI1394_IntMaskClear 0x08C -#define OHCI1394_IsoXmitIntEventSet 0x090 -#define OHCI1394_IsoXmitIntEventClear 0x094 -#define OHCI1394_IsoXmitIntMaskSet 0x098 -#define OHCI1394_IsoXmitIntMaskClear 0x09C -#define OHCI1394_IsoRecvIntEventSet 0x0A0 -#define OHCI1394_IsoRecvIntEventClear 0x0A4 -#define OHCI1394_IsoRecvIntMaskSet 0x0A8 -#define OHCI1394_IsoRecvIntMaskClear 0x0AC -#define OHCI1394_InitialBandwidthAvailable 0x0B0 -#define OHCI1394_InitialChannelsAvailableHi 0x0B4 -#define OHCI1394_InitialChannelsAvailableLo 0x0B8 -#define OHCI1394_FairnessControl 0x0DC -#define OHCI1394_LinkControlSet 0x0E0 -#define OHCI1394_LinkControlClear 0x0E4 -#define OHCI1394_LinkControl_rcvSelfID (1 << 9) -#define OHCI1394_LinkControl_rcvPhyPkt (1 << 10) -#define OHCI1394_LinkControl_cycleTimerEnable (1 << 20) -#define OHCI1394_LinkControl_cycleMaster (1 << 21) -#define OHCI1394_LinkControl_cycleSource (1 << 22) -#define OHCI1394_NodeID 0x0E8 -#define OHCI1394_NodeID_idValid 0x80000000 -#define OHCI1394_PhyControl 0x0EC -#define OHCI1394_PhyControl_Read(addr) (((addr) << 8) | 0x00008000) -#define OHCI1394_PhyControl_ReadDone 0x80000000 -#define OHCI1394_PhyControl_ReadData(r) (((r) & 0x00ff0000) >> 16) -#define OHCI1394_PhyControl_Write(addr, data) (((addr) << 8) | (data) | 0x00004000) -#define OHCI1394_PhyControl_WriteDone 0x00004000 -#define OHCI1394_IsochronousCycleTimer 0x0F0 -#define OHCI1394_AsReqFilterHiSet 0x100 -#define OHCI1394_AsReqFilterHiClear 0x104 -#define OHCI1394_AsReqFilterLoSet 0x108 -#define OHCI1394_AsReqFilterLoClear 0x10C -#define OHCI1394_PhyReqFilterHiSet 0x110 -#define OHCI1394_PhyReqFilterHiClear 0x114 -#define OHCI1394_PhyReqFilterLoSet 0x118 -#define OHCI1394_PhyReqFilterLoClear 0x11C -#define OHCI1394_PhyUpperBound 0x120 - -#define OHCI1394_AsReqTrContextBase 0x180 -#define OHCI1394_AsReqTrContextControlSet 0x180 -#define OHCI1394_AsReqTrContextControlClear 0x184 -#define OHCI1394_AsReqTrCommandPtr 0x18C - -#define OHCI1394_AsRspTrContextBase 0x1A0 -#define OHCI1394_AsRspTrContextControlSet 0x1A0 -#define OHCI1394_AsRspTrContextControlClear 0x1A4 -#define OHCI1394_AsRspTrCommandPtr 0x1AC - -#define OHCI1394_AsReqRcvContextBase 0x1C0 -#define OHCI1394_AsReqRcvContextControlSet 0x1C0 -#define OHCI1394_AsReqRcvContextControlClear 0x1C4 -#define OHCI1394_AsReqRcvCommandPtr 0x1CC - -#define OHCI1394_AsRspRcvContextBase 0x1E0 -#define OHCI1394_AsRspRcvContextControlSet 0x1E0 -#define OHCI1394_AsRspRcvContextControlClear 0x1E4 -#define OHCI1394_AsRspRcvCommandPtr 0x1EC - -/* Isochronous transmit registers */ -#define OHCI1394_IsoXmitContextBase(n) (0x200 + 16 * (n)) -#define OHCI1394_IsoXmitContextControlSet(n) (0x200 + 16 * (n)) -#define OHCI1394_IsoXmitContextControlClear(n) (0x204 + 16 * (n)) -#define OHCI1394_IsoXmitCommandPtr(n) (0x20C + 16 * (n)) - -/* Isochronous receive registers */ -#define OHCI1394_IsoRcvContextBase(n) (0x400 + 32 * (n)) -#define OHCI1394_IsoRcvContextControlSet(n) (0x400 + 32 * (n)) -#define OHCI1394_IsoRcvContextControlClear(n) (0x404 + 32 * (n)) -#define OHCI1394_IsoRcvCommandPtr(n) (0x40C + 32 * (n)) -#define OHCI1394_IsoRcvContextMatch(n) (0x410 + 32 * (n)) - -/* Interrupts Mask/Events */ -#define OHCI1394_reqTxComplete 0x00000001 -#define OHCI1394_respTxComplete 0x00000002 -#define OHCI1394_ARRQ 0x00000004 -#define OHCI1394_ARRS 0x00000008 -#define OHCI1394_RQPkt 0x00000010 -#define OHCI1394_RSPkt 0x00000020 -#define OHCI1394_isochTx 0x00000040 -#define OHCI1394_isochRx 0x00000080 -#define OHCI1394_postedWriteErr 0x00000100 -#define OHCI1394_lockRespErr 0x00000200 -#define OHCI1394_selfIDComplete 0x00010000 -#define OHCI1394_busReset 0x00020000 -#define OHCI1394_phy 0x00080000 -#define OHCI1394_cycleSynch 0x00100000 -#define OHCI1394_cycle64Seconds 0x00200000 -#define OHCI1394_cycleLost 0x00400000 -#define OHCI1394_cycleInconsistent 0x00800000 -#define OHCI1394_unrecoverableError 0x01000000 -#define OHCI1394_cycleTooLong 0x02000000 -#define OHCI1394_phyRegRcvd 0x04000000 -#define OHCI1394_masterIntEnable 0x80000000 - -#define OHCI1394_evt_no_status 0x0 -#define OHCI1394_evt_long_packet 0x2 -#define OHCI1394_evt_missing_ack 0x3 -#define OHCI1394_evt_underrun 0x4 -#define OHCI1394_evt_overrun 0x5 -#define OHCI1394_evt_descriptor_read 0x6 -#define OHCI1394_evt_data_read 0x7 -#define OHCI1394_evt_data_write 0x8 -#define OHCI1394_evt_bus_reset 0x9 -#define OHCI1394_evt_timeout 0xa -#define OHCI1394_evt_tcode_err 0xb -#define OHCI1394_evt_reserved_b 0xc -#define OHCI1394_evt_reserved_c 0xd -#define OHCI1394_evt_unknown 0xe -#define OHCI1394_evt_flushed 0xf - -#define OHCI1394_phy_tcode 0xe - -#endif /* __fw_ohci_h */ diff --git a/trunk/drivers/firewire/fw-sbp2.c b/trunk/drivers/firewire/fw-sbp2.c deleted file mode 100644 index 68300414e5f4..000000000000 --- a/trunk/drivers/firewire/fw-sbp2.c +++ /dev/null @@ -1,1147 +0,0 @@ -/* - * SBP2 driver (SCSI over IEEE1394) - * - * Copyright (C) 2005-2007 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * The basic structure of this driver is based on the old storage driver, - * drivers/ieee1394/sbp2.c, originally written by - * James Goodwin - * with later contributions and ongoing maintenance from - * Ben Collins , - * Stefan Richter - * and many others. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "fw-transaction.h" -#include "fw-topology.h" -#include "fw-device.h" - -/* I don't know why the SCSI stack doesn't define something like this... */ -typedef void (*scsi_done_fn_t)(struct scsi_cmnd *); - -static const char sbp2_driver_name[] = "sbp2"; - -struct sbp2_device { - struct kref kref; - struct fw_unit *unit; - struct fw_address_handler address_handler; - struct list_head orb_list; - u64 management_agent_address; - u64 command_block_agent_address; - u32 workarounds; - int login_id; - - /* - * We cache these addresses and only update them once we've - * logged in or reconnected to the sbp2 device. That way, any - * IO to the device will automatically fail and get retried if - * it happens in a window where the device is not ready to - * handle it (e.g. after a bus reset but before we reconnect). - */ - int node_id; - int address_high; - int generation; - - int retries; - struct delayed_work work; -}; - -#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 -#define SBP2_MAX_SECTORS 255 /* Max sectors supported */ -#define SBP2_ORB_TIMEOUT 2000 /* Timeout in ms */ - -#define SBP2_ORB_NULL 0x80000000 - -#define SBP2_DIRECTION_TO_MEDIA 0x0 -#define SBP2_DIRECTION_FROM_MEDIA 0x1 - -/* Unit directory keys */ -#define SBP2_COMMAND_SET_SPECIFIER 0x38 -#define SBP2_COMMAND_SET 0x39 -#define SBP2_COMMAND_SET_REVISION 0x3b -#define SBP2_FIRMWARE_REVISION 0x3c - -/* Flags for detected oddities and brokeness */ -#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1 -#define SBP2_WORKAROUND_INQUIRY_36 0x2 -#define SBP2_WORKAROUND_MODE_SENSE_8 0x4 -#define SBP2_WORKAROUND_FIX_CAPACITY 0x8 -#define SBP2_WORKAROUND_OVERRIDE 0x100 - -/* Management orb opcodes */ -#define SBP2_LOGIN_REQUEST 0x0 -#define SBP2_QUERY_LOGINS_REQUEST 0x1 -#define SBP2_RECONNECT_REQUEST 0x3 -#define SBP2_SET_PASSWORD_REQUEST 0x4 -#define SBP2_LOGOUT_REQUEST 0x7 -#define SBP2_ABORT_TASK_REQUEST 0xb -#define SBP2_ABORT_TASK_SET 0xc -#define SBP2_LOGICAL_UNIT_RESET 0xe -#define SBP2_TARGET_RESET_REQUEST 0xf - -/* Offsets for command block agent registers */ -#define SBP2_AGENT_STATE 0x00 -#define SBP2_AGENT_RESET 0x04 -#define SBP2_ORB_POINTER 0x08 -#define SBP2_DOORBELL 0x10 -#define SBP2_UNSOLICITED_STATUS_ENABLE 0x14 - -/* Status write response codes */ -#define SBP2_STATUS_REQUEST_COMPLETE 0x0 -#define SBP2_STATUS_TRANSPORT_FAILURE 0x1 -#define SBP2_STATUS_ILLEGAL_REQUEST 0x2 -#define SBP2_STATUS_VENDOR_DEPENDENT 0x3 - -#define STATUS_GET_ORB_HIGH(v) ((v).status & 0xffff) -#define STATUS_GET_SBP_STATUS(v) (((v).status >> 16) & 0xff) -#define STATUS_GET_LEN(v) (((v).status >> 24) & 0x07) -#define STATUS_GET_DEAD(v) (((v).status >> 27) & 0x01) -#define STATUS_GET_RESPONSE(v) (((v).status >> 28) & 0x03) -#define STATUS_GET_SOURCE(v) (((v).status >> 30) & 0x03) -#define STATUS_GET_ORB_LOW(v) ((v).orb_low) -#define STATUS_GET_DATA(v) ((v).data) - -struct sbp2_status { - u32 status; - u32 orb_low; - u8 data[24]; -}; - -struct sbp2_pointer { - u32 high; - u32 low; -}; - -struct sbp2_orb { - struct fw_transaction t; - dma_addr_t request_bus; - int rcode; - struct sbp2_pointer pointer; - void (*callback)(struct sbp2_orb * orb, struct sbp2_status * status); - struct list_head link; -}; - -#define MANAGEMENT_ORB_LUN(v) ((v)) -#define MANAGEMENT_ORB_FUNCTION(v) ((v) << 16) -#define MANAGEMENT_ORB_RECONNECT(v) ((v) << 20) -#define MANAGEMENT_ORB_EXCLUSIVE ((1) << 28) -#define MANAGEMENT_ORB_REQUEST_FORMAT(v) ((v) << 29) -#define MANAGEMENT_ORB_NOTIFY ((1) << 31) - -#define MANAGEMENT_ORB_RESPONSE_LENGTH(v) ((v)) -#define MANAGEMENT_ORB_PASSWORD_LENGTH(v) ((v) << 16) - -struct sbp2_management_orb { - struct sbp2_orb base; - struct { - struct sbp2_pointer password; - struct sbp2_pointer response; - u32 misc; - u32 length; - struct sbp2_pointer status_fifo; - } request; - __be32 response[4]; - dma_addr_t response_bus; - struct completion done; - struct sbp2_status status; -}; - -#define LOGIN_RESPONSE_GET_LOGIN_ID(v) ((v).misc & 0xffff) -#define LOGIN_RESPONSE_GET_LENGTH(v) (((v).misc >> 16) & 0xffff) - -struct sbp2_login_response { - u32 misc; - struct sbp2_pointer command_block_agent; - u32 reconnect_hold; -}; -#define COMMAND_ORB_DATA_SIZE(v) ((v)) -#define COMMAND_ORB_PAGE_SIZE(v) ((v) << 16) -#define COMMAND_ORB_PAGE_TABLE_PRESENT ((1) << 19) -#define COMMAND_ORB_MAX_PAYLOAD(v) ((v) << 20) -#define COMMAND_ORB_SPEED(v) ((v) << 24) -#define COMMAND_ORB_DIRECTION(v) ((v) << 27) -#define COMMAND_ORB_REQUEST_FORMAT(v) ((v) << 29) -#define COMMAND_ORB_NOTIFY ((1) << 31) - -struct sbp2_command_orb { - struct sbp2_orb base; - struct { - struct sbp2_pointer next; - struct sbp2_pointer data_descriptor; - u32 misc; - u8 command_block[12]; - } request; - struct scsi_cmnd *cmd; - scsi_done_fn_t done; - struct fw_unit *unit; - - struct sbp2_pointer page_table[SG_ALL]; - dma_addr_t page_table_bus; - dma_addr_t request_buffer_bus; -}; - -/* - * List of devices with known bugs. - * - * The firmware_revision field, masked with 0xffff00, is the best - * indicator for the type of bridge chip of a device. It yields a few - * false positives but this did not break correctly behaving devices - * so far. We use ~0 as a wildcard, since the 24 bit values we get - * from the config rom can never match that. - */ -static const struct { - u32 firmware_revision; - u32 model; - unsigned workarounds; -} sbp2_workarounds_table[] = { - /* DViCO Momobay CX-1 with TSB42AA9 bridge */ { - .firmware_revision = 0x002800, - .model = 0x001010, - .workarounds = SBP2_WORKAROUND_INQUIRY_36 | - SBP2_WORKAROUND_MODE_SENSE_8, - }, - /* Initio bridges, actually only needed for some older ones */ { - .firmware_revision = 0x000200, - .model = ~0, - .workarounds = SBP2_WORKAROUND_INQUIRY_36, - }, - /* Symbios bridge */ { - .firmware_revision = 0xa0b800, - .model = ~0, - .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS, - }, - - /* - * There are iPods (2nd gen, 3rd gen) with model_id == 0, but - * these iPods do not feature the read_capacity bug according - * to one report. Read_capacity behaviour as well as model_id - * could change due to Apple-supplied firmware updates though. - */ - - /* iPod 4th generation. */ { - .firmware_revision = 0x0a2700, - .model = 0x000021, - .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, - }, - /* iPod mini */ { - .firmware_revision = 0x0a2700, - .model = 0x000023, - .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, - }, - /* iPod Photo */ { - .firmware_revision = 0x0a2700, - .model = 0x00007e, - .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, - } -}; - -static void -sbp2_status_write(struct fw_card *card, struct fw_request *request, - int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, - void *payload, size_t length, void *callback_data) -{ - struct sbp2_device *sd = callback_data; - struct sbp2_orb *orb; - struct sbp2_status status; - size_t header_size; - unsigned long flags; - - if (tcode != TCODE_WRITE_BLOCK_REQUEST || - length == 0 || length > sizeof(status)) { - fw_send_response(card, request, RCODE_TYPE_ERROR); - return; - } - - header_size = min(length, 2 * sizeof(u32)); - fw_memcpy_from_be32(&status, payload, header_size); - if (length > header_size) - memcpy(status.data, payload + 8, length - header_size); - if (STATUS_GET_SOURCE(status) == 2 || STATUS_GET_SOURCE(status) == 3) { - fw_notify("non-orb related status write, not handled\n"); - fw_send_response(card, request, RCODE_COMPLETE); - return; - } - - /* Lookup the orb corresponding to this status write. */ - spin_lock_irqsave(&card->lock, flags); - list_for_each_entry(orb, &sd->orb_list, link) { - if (STATUS_GET_ORB_HIGH(status) == 0 && - STATUS_GET_ORB_LOW(status) == orb->request_bus && - orb->rcode == RCODE_COMPLETE) { - list_del(&orb->link); - break; - } - } - spin_unlock_irqrestore(&card->lock, flags); - - if (&orb->link != &sd->orb_list) - orb->callback(orb, &status); - else - fw_error("status write for unknown orb\n"); - - fw_send_response(card, request, RCODE_COMPLETE); -} - -static void -complete_transaction(struct fw_card *card, int rcode, - void *payload, size_t length, void *data) -{ - struct sbp2_orb *orb = data; - unsigned long flags; - - orb->rcode = rcode; - if (rcode != RCODE_COMPLETE) { - spin_lock_irqsave(&card->lock, flags); - list_del(&orb->link); - spin_unlock_irqrestore(&card->lock, flags); - orb->callback(orb, NULL); - } -} - -static void -sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit, - int node_id, int generation, u64 offset) -{ - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_device *sd = unit->device.driver_data; - unsigned long flags; - - orb->pointer.high = 0; - orb->pointer.low = orb->request_bus; - fw_memcpy_to_be32(&orb->pointer, &orb->pointer, sizeof(orb->pointer)); - - spin_lock_irqsave(&device->card->lock, flags); - list_add_tail(&orb->link, &sd->orb_list); - spin_unlock_irqrestore(&device->card->lock, flags); - - fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST, - node_id, generation, - device->node->max_speed, offset, - &orb->pointer, sizeof(orb->pointer), - complete_transaction, orb); -} - -static int sbp2_cancel_orbs(struct fw_unit *unit) -{ - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_device *sd = unit->device.driver_data; - struct sbp2_orb *orb, *next; - struct list_head list; - unsigned long flags; - int retval = -ENOENT; - - INIT_LIST_HEAD(&list); - spin_lock_irqsave(&device->card->lock, flags); - list_splice_init(&sd->orb_list, &list); - spin_unlock_irqrestore(&device->card->lock, flags); - - list_for_each_entry_safe(orb, next, &list, link) { - retval = 0; - if (fw_cancel_transaction(device->card, &orb->t) == 0) - continue; - - orb->rcode = RCODE_CANCELLED; - orb->callback(orb, NULL); - } - - return retval; -} - -static void -complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) -{ - struct sbp2_management_orb *orb = - (struct sbp2_management_orb *)base_orb; - - if (status) - memcpy(&orb->status, status, sizeof(*status)); - complete(&orb->done); -} - -static int -sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, - int function, int lun, void *response) -{ - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_device *sd = unit->device.driver_data; - struct sbp2_management_orb *orb; - int retval = -ENOMEM; - - orb = kzalloc(sizeof(*orb), GFP_ATOMIC); - if (orb == NULL) - return -ENOMEM; - - /* - * The sbp2 device is going to send a block read request to - * read out the request from host memory, so map it for dma. - */ - orb->base.request_bus = - dma_map_single(device->card->device, &orb->request, - sizeof(orb->request), DMA_TO_DEVICE); - if (dma_mapping_error(orb->base.request_bus)) - goto out; - - orb->response_bus = - dma_map_single(device->card->device, &orb->response, - sizeof(orb->response), DMA_FROM_DEVICE); - if (dma_mapping_error(orb->response_bus)) - goto out; - - orb->request.response.high = 0; - orb->request.response.low = orb->response_bus; - - orb->request.misc = - MANAGEMENT_ORB_NOTIFY | - MANAGEMENT_ORB_FUNCTION(function) | - MANAGEMENT_ORB_LUN(lun); - orb->request.length = - MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response)); - - orb->request.status_fifo.high = sd->address_handler.offset >> 32; - orb->request.status_fifo.low = sd->address_handler.offset; - - /* - * FIXME: Yeah, ok this isn't elegant, we hardwire exclusive - * login and 1 second reconnect time. The reconnect setting - * is probably fine, but the exclusive login should be an option. - */ - if (function == SBP2_LOGIN_REQUEST) { - orb->request.misc |= - MANAGEMENT_ORB_EXCLUSIVE | - MANAGEMENT_ORB_RECONNECT(0); - } - - fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request)); - - init_completion(&orb->done); - orb->base.callback = complete_management_orb; - - sbp2_send_orb(&orb->base, unit, - node_id, generation, sd->management_agent_address); - - wait_for_completion_timeout(&orb->done, - msecs_to_jiffies(SBP2_ORB_TIMEOUT)); - - retval = -EIO; - if (sbp2_cancel_orbs(unit) == 0) { - fw_error("orb reply timed out, rcode=0x%02x\n", - orb->base.rcode); - goto out; - } - - if (orb->base.rcode != RCODE_COMPLETE) { - fw_error("management write failed, rcode 0x%02x\n", - orb->base.rcode); - goto out; - } - - if (STATUS_GET_RESPONSE(orb->status) != 0 || - STATUS_GET_SBP_STATUS(orb->status) != 0) { - fw_error("error status: %d:%d\n", - STATUS_GET_RESPONSE(orb->status), - STATUS_GET_SBP_STATUS(orb->status)); - goto out; - } - - retval = 0; - out: - dma_unmap_single(device->card->device, orb->base.request_bus, - sizeof(orb->request), DMA_TO_DEVICE); - dma_unmap_single(device->card->device, orb->response_bus, - sizeof(orb->response), DMA_FROM_DEVICE); - - if (response) - fw_memcpy_from_be32(response, - orb->response, sizeof(orb->response)); - kfree(orb); - - return retval; -} - -static void -complete_agent_reset_write(struct fw_card *card, int rcode, - void *payload, size_t length, void *data) -{ - struct fw_transaction *t = data; - - kfree(t); -} - -static int sbp2_agent_reset(struct fw_unit *unit) -{ - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_device *sd = unit->device.driver_data; - struct fw_transaction *t; - static u32 zero; - - t = kzalloc(sizeof(*t), GFP_ATOMIC); - if (t == NULL) - return -ENOMEM; - - fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST, - sd->node_id, sd->generation, SCODE_400, - sd->command_block_agent_address + SBP2_AGENT_RESET, - &zero, sizeof(zero), complete_agent_reset_write, t); - - return 0; -} - -static void sbp2_reconnect(struct work_struct *work); -static struct scsi_host_template scsi_driver_template; - -static void -release_sbp2_device(struct kref *kref) -{ - struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref); - struct Scsi_Host *host = - container_of((void *)sd, struct Scsi_Host, hostdata[0]); - - sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation, - SBP2_LOGOUT_REQUEST, sd->login_id, NULL); - - scsi_remove_host(host); - fw_core_remove_address_handler(&sd->address_handler); - fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id); - put_device(&sd->unit->device); - scsi_host_put(host); -} - -static void sbp2_login(struct work_struct *work) -{ - struct sbp2_device *sd = - container_of(work, struct sbp2_device, work.work); - struct Scsi_Host *host = - container_of((void *)sd, struct Scsi_Host, hostdata[0]); - struct fw_unit *unit = sd->unit; - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_login_response response; - int generation, node_id, local_node_id, lun, retval; - - /* FIXME: Make this work for multi-lun devices. */ - lun = 0; - - generation = device->card->generation; - node_id = device->node->node_id; - local_node_id = device->card->local_node->node_id; - - if (sbp2_send_management_orb(unit, node_id, generation, - SBP2_LOGIN_REQUEST, lun, &response) < 0) { - if (sd->retries++ < 5) { - schedule_delayed_work(&sd->work, DIV_ROUND_UP(HZ, 5)); - } else { - fw_error("failed to login to %s\n", - unit->device.bus_id); - kref_put(&sd->kref, release_sbp2_device); - } - return; - } - - sd->generation = generation; - sd->node_id = node_id; - sd->address_high = local_node_id << 16; - - /* Get command block agent offset and login id. */ - sd->command_block_agent_address = - ((u64) (response.command_block_agent.high & 0xffff) << 32) | - response.command_block_agent.low; - sd->login_id = LOGIN_RESPONSE_GET_LOGIN_ID(response); - - fw_notify("logged in to sbp2 unit %s (%d retries)\n", - unit->device.bus_id, sd->retries); - fw_notify(" - management_agent_address: 0x%012llx\n", - (unsigned long long) sd->management_agent_address); - fw_notify(" - command_block_agent_address: 0x%012llx\n", - (unsigned long long) sd->command_block_agent_address); - fw_notify(" - status write address: 0x%012llx\n", - (unsigned long long) sd->address_handler.offset); - -#if 0 - /* FIXME: The linux1394 sbp2 does this last step. */ - sbp2_set_busy_timeout(scsi_id); -#endif - - PREPARE_DELAYED_WORK(&sd->work, sbp2_reconnect); - sbp2_agent_reset(unit); - - /* FIXME: Loop over luns here. */ - lun = 0; - retval = scsi_add_device(host, 0, 0, lun); - if (retval < 0) { - sbp2_send_management_orb(unit, sd->node_id, sd->generation, - SBP2_LOGOUT_REQUEST, sd->login_id, - NULL); - /* - * Set this back to sbp2_login so we fall back and - * retry login on bus reset. - */ - PREPARE_DELAYED_WORK(&sd->work, sbp2_login); - } - kref_put(&sd->kref, release_sbp2_device); -} - -static int sbp2_probe(struct device *dev) -{ - struct fw_unit *unit = fw_unit(dev); - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_device *sd; - struct fw_csr_iterator ci; - struct Scsi_Host *host; - int i, key, value, err; - u32 model, firmware_revision; - - err = -ENOMEM; - host = scsi_host_alloc(&scsi_driver_template, sizeof(*sd)); - if (host == NULL) - goto fail; - - sd = (struct sbp2_device *) host->hostdata; - unit->device.driver_data = sd; - sd->unit = unit; - INIT_LIST_HEAD(&sd->orb_list); - kref_init(&sd->kref); - - sd->address_handler.length = 0x100; - sd->address_handler.address_callback = sbp2_status_write; - sd->address_handler.callback_data = sd; - - err = fw_core_add_address_handler(&sd->address_handler, - &fw_high_memory_region); - if (err < 0) - goto fail_host; - - err = fw_device_enable_phys_dma(device); - if (err < 0) - goto fail_address_handler; - - err = scsi_add_host(host, &unit->device); - if (err < 0) - goto fail_address_handler; - - /* - * Scan unit directory to get management agent address, - * firmware revison and model. Initialize firmware_revision - * and model to values that wont match anything in our table. - */ - firmware_revision = 0xff000000; - model = 0xff000000; - fw_csr_iterator_init(&ci, unit->directory); - while (fw_csr_iterator_next(&ci, &key, &value)) { - switch (key) { - case CSR_DEPENDENT_INFO | CSR_OFFSET: - sd->management_agent_address = - 0xfffff0000000ULL + 4 * value; - break; - case SBP2_FIRMWARE_REVISION: - firmware_revision = value; - break; - case CSR_MODEL: - model = value; - break; - } - } - - for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) { - if (sbp2_workarounds_table[i].firmware_revision != - (firmware_revision & 0xffffff00)) - continue; - if (sbp2_workarounds_table[i].model != model && - sbp2_workarounds_table[i].model != ~0) - continue; - sd->workarounds |= sbp2_workarounds_table[i].workarounds; - break; - } - - if (sd->workarounds) - fw_notify("Workarounds for node %s: 0x%x " - "(firmware_revision 0x%06x, model_id 0x%06x)\n", - unit->device.bus_id, - sd->workarounds, firmware_revision, model); - - get_device(&unit->device); - - /* - * We schedule work to do the login so we can easily - * reschedule retries. Always get the ref before scheduling - * work. - */ - INIT_DELAYED_WORK(&sd->work, sbp2_login); - if (schedule_delayed_work(&sd->work, 0)) - kref_get(&sd->kref); - - return 0; - - fail_address_handler: - fw_core_remove_address_handler(&sd->address_handler); - fail_host: - scsi_host_put(host); - fail: - return err; -} - -static int sbp2_remove(struct device *dev) -{ - struct fw_unit *unit = fw_unit(dev); - struct sbp2_device *sd = unit->device.driver_data; - - kref_put(&sd->kref, release_sbp2_device); - - return 0; -} - -static void sbp2_reconnect(struct work_struct *work) -{ - struct sbp2_device *sd = - container_of(work, struct sbp2_device, work.work); - struct fw_unit *unit = sd->unit; - struct fw_device *device = fw_device(unit->device.parent); - int generation, node_id, local_node_id; - - generation = device->card->generation; - node_id = device->node->node_id; - local_node_id = device->card->local_node->node_id; - - if (sbp2_send_management_orb(unit, node_id, generation, - SBP2_RECONNECT_REQUEST, - sd->login_id, NULL) < 0) { - if (sd->retries++ >= 5) { - fw_error("failed to reconnect to %s\n", - unit->device.bus_id); - /* Fall back and try to log in again. */ - sd->retries = 0; - PREPARE_DELAYED_WORK(&sd->work, sbp2_login); - } - schedule_delayed_work(&sd->work, DIV_ROUND_UP(HZ, 5)); - return; - } - - sd->generation = generation; - sd->node_id = node_id; - sd->address_high = local_node_id << 16; - - fw_notify("reconnected to unit %s (%d retries)\n", - unit->device.bus_id, sd->retries); - sbp2_agent_reset(unit); - sbp2_cancel_orbs(unit); - kref_put(&sd->kref, release_sbp2_device); -} - -static void sbp2_update(struct fw_unit *unit) -{ - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_device *sd = unit->device.driver_data; - - sd->retries = 0; - fw_device_enable_phys_dma(device); - if (schedule_delayed_work(&sd->work, 0)) - kref_get(&sd->kref); -} - -#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e -#define SBP2_SW_VERSION_ENTRY 0x00010483 - -static const struct fw_device_id sbp2_id_table[] = { - { - .match_flags = FW_MATCH_SPECIFIER_ID | FW_MATCH_VERSION, - .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY, - .version = SBP2_SW_VERSION_ENTRY, - }, - { } -}; - -static struct fw_driver sbp2_driver = { - .driver = { - .owner = THIS_MODULE, - .name = sbp2_driver_name, - .bus = &fw_bus_type, - .probe = sbp2_probe, - .remove = sbp2_remove, - }, - .update = sbp2_update, - .id_table = sbp2_id_table, -}; - -static unsigned int -sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data) -{ - int sam_status; - - sense_data[0] = 0x70; - sense_data[1] = 0x0; - sense_data[2] = sbp2_status[1]; - sense_data[3] = sbp2_status[4]; - sense_data[4] = sbp2_status[5]; - sense_data[5] = sbp2_status[6]; - sense_data[6] = sbp2_status[7]; - sense_data[7] = 10; - sense_data[8] = sbp2_status[8]; - sense_data[9] = sbp2_status[9]; - sense_data[10] = sbp2_status[10]; - sense_data[11] = sbp2_status[11]; - sense_data[12] = sbp2_status[2]; - sense_data[13] = sbp2_status[3]; - sense_data[14] = sbp2_status[12]; - sense_data[15] = sbp2_status[13]; - - sam_status = sbp2_status[0] & 0x3f; - - switch (sam_status) { - case SAM_STAT_GOOD: - case SAM_STAT_CHECK_CONDITION: - case SAM_STAT_CONDITION_MET: - case SAM_STAT_BUSY: - case SAM_STAT_RESERVATION_CONFLICT: - case SAM_STAT_COMMAND_TERMINATED: - return DID_OK << 16 | sam_status; - - default: - return DID_ERROR << 16; - } -} - -static void -complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) -{ - struct sbp2_command_orb *orb = (struct sbp2_command_orb *)base_orb; - struct fw_unit *unit = orb->unit; - struct fw_device *device = fw_device(unit->device.parent); - struct scatterlist *sg; - int result; - - if (status != NULL) { - if (STATUS_GET_DEAD(*status)) - sbp2_agent_reset(unit); - - switch (STATUS_GET_RESPONSE(*status)) { - case SBP2_STATUS_REQUEST_COMPLETE: - result = DID_OK << 16; - break; - case SBP2_STATUS_TRANSPORT_FAILURE: - result = DID_BUS_BUSY << 16; - break; - case SBP2_STATUS_ILLEGAL_REQUEST: - case SBP2_STATUS_VENDOR_DEPENDENT: - default: - result = DID_ERROR << 16; - break; - } - - if (result == DID_OK << 16 && STATUS_GET_LEN(*status) > 1) - result = sbp2_status_to_sense_data(STATUS_GET_DATA(*status), - orb->cmd->sense_buffer); - } else { - /* - * If the orb completes with status == NULL, something - * went wrong, typically a bus reset happened mid-orb - * or when sending the write (less likely). - */ - result = DID_BUS_BUSY << 16; - } - - dma_unmap_single(device->card->device, orb->base.request_bus, - sizeof(orb->request), DMA_TO_DEVICE); - - if (orb->cmd->use_sg > 0) { - sg = (struct scatterlist *)orb->cmd->request_buffer; - dma_unmap_sg(device->card->device, sg, orb->cmd->use_sg, - orb->cmd->sc_data_direction); - } - - if (orb->page_table_bus != 0) - dma_unmap_single(device->card->device, orb->page_table_bus, - sizeof(orb->page_table_bus), DMA_TO_DEVICE); - - if (orb->request_buffer_bus != 0) - dma_unmap_single(device->card->device, orb->request_buffer_bus, - sizeof(orb->request_buffer_bus), - DMA_FROM_DEVICE); - - orb->cmd->result = result; - orb->done(orb->cmd); - kfree(orb); -} - -static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) -{ - struct sbp2_device *sd = - (struct sbp2_device *)orb->cmd->device->host->hostdata; - struct fw_unit *unit = sd->unit; - struct fw_device *device = fw_device(unit->device.parent); - struct scatterlist *sg; - int sg_len, l, i, j, count; - size_t size; - dma_addr_t sg_addr; - - sg = (struct scatterlist *)orb->cmd->request_buffer; - count = dma_map_sg(device->card->device, sg, orb->cmd->use_sg, - orb->cmd->sc_data_direction); - if (count == 0) - goto fail; - - /* - * Handle the special case where there is only one element in - * the scatter list by converting it to an immediate block - * request. This is also a workaround for broken devices such - * as the second generation iPod which doesn't support page - * tables. - */ - if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) { - orb->request.data_descriptor.high = sd->address_high; - orb->request.data_descriptor.low = sg_dma_address(sg); - orb->request.misc |= - COMMAND_ORB_DATA_SIZE(sg_dma_len(sg)); - return 0; - } - - /* - * Convert the scatterlist to an sbp2 page table. If any - * scatterlist entries are too big for sbp2, we split them as we - * go. Even if we ask the block I/O layer to not give us sg - * elements larger than 65535 bytes, some IOMMUs may merge sg elements - * during DMA mapping, and Linux currently doesn't prevent this. - */ - for (i = 0, j = 0; i < count; i++) { - sg_len = sg_dma_len(sg + i); - sg_addr = sg_dma_address(sg + i); - while (sg_len) { - l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH); - orb->page_table[j].low = sg_addr; - orb->page_table[j].high = (l << 16); - sg_addr += l; - sg_len -= l; - j++; - } - } - - size = sizeof(orb->page_table[0]) * j; - - /* - * The data_descriptor pointer is the one case where we need - * to fill in the node ID part of the address. All other - * pointers assume that the data referenced reside on the - * initiator (i.e. us), but data_descriptor can refer to data - * on other nodes so we need to put our ID in descriptor.high. - */ - - orb->page_table_bus = - dma_map_single(device->card->device, orb->page_table, - size, DMA_TO_DEVICE); - if (dma_mapping_error(orb->page_table_bus)) - goto fail_page_table; - orb->request.data_descriptor.high = sd->address_high; - orb->request.data_descriptor.low = orb->page_table_bus; - orb->request.misc |= - COMMAND_ORB_PAGE_TABLE_PRESENT | - COMMAND_ORB_DATA_SIZE(j); - - fw_memcpy_to_be32(orb->page_table, orb->page_table, size); - - return 0; - - fail_page_table: - dma_unmap_sg(device->card->device, sg, orb->cmd->use_sg, - orb->cmd->sc_data_direction); - fail: - return -ENOMEM; -} - -/* SCSI stack integration */ - -static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) -{ - struct sbp2_device *sd = - (struct sbp2_device *)cmd->device->host->hostdata; - struct fw_unit *unit = sd->unit; - struct fw_device *device = fw_device(unit->device.parent); - struct sbp2_command_orb *orb; - - /* - * Bidirectional commands are not yet implemented, and unknown - * transfer direction not handled. - */ - if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) { - fw_error("Cannot handle DMA_BIDIRECTIONAL - rejecting command"); - cmd->result = DID_ERROR << 16; - done(cmd); - return 0; - } - - orb = kzalloc(sizeof(*orb), GFP_ATOMIC); - if (orb == NULL) { - fw_notify("failed to alloc orb\n"); - goto fail_alloc; - } - - /* Initialize rcode to something not RCODE_COMPLETE. */ - orb->base.rcode = -1; - orb->base.request_bus = - dma_map_single(device->card->device, &orb->request, - sizeof(orb->request), DMA_TO_DEVICE); - if (dma_mapping_error(orb->base.request_bus)) - goto fail_mapping; - - orb->unit = unit; - orb->done = done; - orb->cmd = cmd; - - orb->request.next.high = SBP2_ORB_NULL; - orb->request.next.low = 0x0; - /* - * At speed 100 we can do 512 bytes per packet, at speed 200, - * 1024 bytes per packet etc. The SBP-2 max_payload field - * specifies the max payload size as 2 ^ (max_payload + 2), so - * if we set this to max_speed + 7, we get the right value. - */ - orb->request.misc = - COMMAND_ORB_MAX_PAYLOAD(device->node->max_speed + 7) | - COMMAND_ORB_SPEED(device->node->max_speed) | - COMMAND_ORB_NOTIFY; - - if (cmd->sc_data_direction == DMA_FROM_DEVICE) - orb->request.misc |= - COMMAND_ORB_DIRECTION(SBP2_DIRECTION_FROM_MEDIA); - else if (cmd->sc_data_direction == DMA_TO_DEVICE) - orb->request.misc |= - COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA); - - if (cmd->use_sg && sbp2_command_orb_map_scatterlist(orb) < 0) - goto fail_map_payload; - - fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request)); - - memset(orb->request.command_block, - 0, sizeof(orb->request.command_block)); - memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd)); - - orb->base.callback = complete_command_orb; - - sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation, - sd->command_block_agent_address + SBP2_ORB_POINTER); - - return 0; - - fail_map_payload: - dma_unmap_single(device->card->device, orb->base.request_bus, - sizeof(orb->request), DMA_TO_DEVICE); - fail_mapping: - kfree(orb); - fail_alloc: - return SCSI_MLQUEUE_HOST_BUSY; -} - -static int sbp2_scsi_slave_alloc(struct scsi_device *sdev) -{ - struct sbp2_device *sd = (struct sbp2_device *)sdev->host->hostdata; - - sdev->allow_restart = 1; - - if (sd->workarounds & SBP2_WORKAROUND_INQUIRY_36) - sdev->inquiry_len = 36; - return 0; -} - -static int sbp2_scsi_slave_configure(struct scsi_device *sdev) -{ - struct sbp2_device *sd = (struct sbp2_device *)sdev->host->hostdata; - struct fw_unit *unit = sd->unit; - - sdev->use_10_for_rw = 1; - - if (sdev->type == TYPE_ROM) - sdev->use_10_for_ms = 1; - if (sdev->type == TYPE_DISK && - sd->workarounds & SBP2_WORKAROUND_MODE_SENSE_8) - sdev->skip_ms_page_8 = 1; - if (sd->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) { - fw_notify("setting fix_capacity for %s\n", unit->device.bus_id); - sdev->fix_capacity = 1; - } - - return 0; -} - -/* - * Called by scsi stack when something has really gone wrong. Usually - * called when a command has timed-out for some reason. - */ -static int sbp2_scsi_abort(struct scsi_cmnd *cmd) -{ - struct sbp2_device *sd = - (struct sbp2_device *)cmd->device->host->hostdata; - struct fw_unit *unit = sd->unit; - - fw_notify("sbp2_scsi_abort\n"); - sbp2_agent_reset(unit); - sbp2_cancel_orbs(unit); - - return SUCCESS; -} - -static struct scsi_host_template scsi_driver_template = { - .module = THIS_MODULE, - .name = "SBP-2 IEEE-1394", - .proc_name = (char *)sbp2_driver_name, - .queuecommand = sbp2_scsi_queuecommand, - .slave_alloc = sbp2_scsi_slave_alloc, - .slave_configure = sbp2_scsi_slave_configure, - .eh_abort_handler = sbp2_scsi_abort, - .this_id = -1, - .sg_tablesize = SG_ALL, - .use_clustering = ENABLE_CLUSTERING, - .cmd_per_lun = 1, - .can_queue = 1, -}; - -MODULE_AUTHOR("Kristian Hoegsberg "); -MODULE_DESCRIPTION("SCSI over IEEE1394"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table); - -/* Provide a module alias so root-on-sbp2 initrds don't break. */ -#ifndef CONFIG_IEEE1394_SBP2_MODULE -MODULE_ALIAS("sbp2"); -#endif - -static int __init sbp2_init(void) -{ - return driver_register(&sbp2_driver.driver); -} - -static void __exit sbp2_cleanup(void) -{ - driver_unregister(&sbp2_driver.driver); -} - -module_init(sbp2_init); -module_exit(sbp2_cleanup); diff --git a/trunk/drivers/firewire/fw-topology.c b/trunk/drivers/firewire/fw-topology.c deleted file mode 100644 index 7aebb8ae0efa..000000000000 --- a/trunk/drivers/firewire/fw-topology.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Incremental bus scan, based on bus topology - * - * Copyright (C) 2004-2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include "fw-transaction.h" -#include "fw-topology.h" - -#define SELF_ID_PHY_ID(q) (((q) >> 24) & 0x3f) -#define SELF_ID_EXTENDED(q) (((q) >> 23) & 0x01) -#define SELF_ID_LINK_ON(q) (((q) >> 22) & 0x01) -#define SELF_ID_GAP_COUNT(q) (((q) >> 16) & 0x3f) -#define SELF_ID_PHY_SPEED(q) (((q) >> 14) & 0x03) -#define SELF_ID_CONTENDER(q) (((q) >> 11) & 0x01) -#define SELF_ID_PHY_INITIATOR(q) (((q) >> 1) & 0x01) -#define SELF_ID_MORE_PACKETS(q) (((q) >> 0) & 0x01) - -#define SELF_ID_EXT_SEQUENCE(q) (((q) >> 20) & 0x07) - -static u32 *count_ports(u32 *sid, int *total_port_count, int *child_port_count) -{ - u32 q; - int port_type, shift, seq; - - *total_port_count = 0; - *child_port_count = 0; - - shift = 6; - q = *sid; - seq = 0; - - while (1) { - port_type = (q >> shift) & 0x03; - switch (port_type) { - case SELFID_PORT_CHILD: - (*child_port_count)++; - case SELFID_PORT_PARENT: - case SELFID_PORT_NCONN: - (*total_port_count)++; - case SELFID_PORT_NONE: - break; - } - - shift -= 2; - if (shift == 0) { - if (!SELF_ID_MORE_PACKETS(q)) - return sid + 1; - - shift = 16; - sid++; - q = *sid; - - /* - * Check that the extra packets actually are - * extended self ID packets and that the - * sequence numbers in the extended self ID - * packets increase as expected. - */ - - if (!SELF_ID_EXTENDED(q) || - seq != SELF_ID_EXT_SEQUENCE(q)) - return NULL; - - seq++; - } - } -} - -static int get_port_type(u32 *sid, int port_index) -{ - int index, shift; - - index = (port_index + 5) / 8; - shift = 16 - ((port_index + 5) & 7) * 2; - return (sid[index] >> shift) & 0x03; -} - -static struct fw_node *fw_node_create(u32 sid, int port_count, int color) -{ - struct fw_node *node; - - node = kzalloc(sizeof(*node) + port_count * sizeof(node->ports[0]), - GFP_ATOMIC); - if (node == NULL) - return NULL; - - node->color = color; - node->node_id = LOCAL_BUS | SELF_ID_PHY_ID(sid); - node->link_on = SELF_ID_LINK_ON(sid); - node->phy_speed = SELF_ID_PHY_SPEED(sid); - node->port_count = port_count; - - atomic_set(&node->ref_count, 1); - INIT_LIST_HEAD(&node->link); - - return node; -} - -/* - * Compute the maximum hop count for this node and it's children. The - * maximum hop count is the maximum number of connections between any - * two nodes in the subtree rooted at this node. We need this for - * setting the gap count. As we build the tree bottom up in - * build_tree() below, this is fairly easy to do: for each node we - * maintain the max hop count and the max depth, ie the number of hops - * to the furthest leaf. Computing the max hop count breaks down into - * two cases: either the path goes through this node, in which case - * the hop count is the sum of the two biggest child depths plus 2. - * Or it could be the case that the max hop path is entirely - * containted in a child tree, in which case the max hop count is just - * the max hop count of this child. - */ -static void update_hop_count(struct fw_node *node) -{ - int depths[2] = { -1, -1 }; - int max_child_hops = 0; - int i; - - for (i = 0; i < node->port_count; i++) { - if (node->ports[i].node == NULL) - continue; - - if (node->ports[i].node->max_hops > max_child_hops) - max_child_hops = node->ports[i].node->max_hops; - - if (node->ports[i].node->max_depth > depths[0]) { - depths[1] = depths[0]; - depths[0] = node->ports[i].node->max_depth; - } else if (node->ports[i].node->max_depth > depths[1]) - depths[1] = node->ports[i].node->max_depth; - } - - node->max_depth = depths[0] + 1; - node->max_hops = max(max_child_hops, depths[0] + depths[1] + 2); -} - - -/** - * build_tree - Build the tree representation of the topology - * @self_ids: array of self IDs to create the tree from - * @self_id_count: the length of the self_ids array - * @local_id: the node ID of the local node - * - * This function builds the tree representation of the topology given - * by the self IDs from the latest bus reset. During the construction - * of the tree, the function checks that the self IDs are valid and - * internally consistent. On succcess this funtions returns the - * fw_node corresponding to the local card otherwise NULL. - */ -static struct fw_node *build_tree(struct fw_card *card, - u32 *sid, int self_id_count) -{ - struct fw_node *node, *child, *local_node, *irm_node; - struct list_head stack, *h; - u32 *next_sid, *end, q; - int i, port_count, child_port_count, phy_id, parent_count, stack_depth; - int gap_count, topology_type; - - local_node = NULL; - node = NULL; - INIT_LIST_HEAD(&stack); - stack_depth = 0; - end = sid + self_id_count; - phy_id = 0; - irm_node = NULL; - gap_count = SELF_ID_GAP_COUNT(*sid); - topology_type = 0; - - while (sid < end) { - next_sid = count_ports(sid, &port_count, &child_port_count); - - if (next_sid == NULL) { - fw_error("Inconsistent extended self IDs.\n"); - return NULL; - } - - q = *sid; - if (phy_id != SELF_ID_PHY_ID(q)) { - fw_error("PHY ID mismatch in self ID: %d != %d.\n", - phy_id, SELF_ID_PHY_ID(q)); - return NULL; - } - - if (child_port_count > stack_depth) { - fw_error("Topology stack underflow\n"); - return NULL; - } - - /* - * Seek back from the top of our stack to find the - * start of the child nodes for this node. - */ - for (i = 0, h = &stack; i < child_port_count; i++) - h = h->prev; - child = fw_node(h); - - node = fw_node_create(q, port_count, card->color); - if (node == NULL) { - fw_error("Out of memory while building topology."); - return NULL; - } - - if (phy_id == (card->node_id & 0x3f)) - local_node = node; - - if (SELF_ID_CONTENDER(q)) - irm_node = node; - - if (node->phy_speed == SCODE_BETA) - topology_type |= FW_TOPOLOGY_B; - else - topology_type |= FW_TOPOLOGY_A; - - parent_count = 0; - - for (i = 0; i < port_count; i++) { - switch (get_port_type(sid, i)) { - case SELFID_PORT_PARENT: - /* - * Who's your daddy? We dont know the - * parent node at this time, so we - * temporarily abuse node->color for - * remembering the entry in the - * node->ports array where the parent - * node should be. Later, when we - * handle the parent node, we fix up - * the reference. - */ - parent_count++; - node->color = i; - break; - - case SELFID_PORT_CHILD: - node->ports[i].node = child; - /* - * Fix up parent reference for this - * child node. - */ - child->ports[child->color].node = node; - child->color = card->color; - child = fw_node(child->link.next); - break; - } - } - - /* - * Check that the node reports exactly one parent - * port, except for the root, which of course should - * have no parents. - */ - if ((next_sid == end && parent_count != 0) || - (next_sid < end && parent_count != 1)) { - fw_error("Parent port inconsistency for node %d: " - "parent_count=%d\n", phy_id, parent_count); - return NULL; - } - - /* Pop the child nodes off the stack and push the new node. */ - __list_del(h->prev, &stack); - list_add_tail(&node->link, &stack); - stack_depth += 1 - child_port_count; - - /* - * If all PHYs does not report the same gap count - * setting, we fall back to 63 which will force a gap - * count reconfiguration and a reset. - */ - if (SELF_ID_GAP_COUNT(q) != gap_count) - gap_count = 63; - - update_hop_count(node); - - sid = next_sid; - phy_id++; - } - - card->root_node = node; - card->irm_node = irm_node; - card->gap_count = gap_count; - card->topology_type = topology_type; - - return local_node; -} - -typedef void (*fw_node_callback_t)(struct fw_card * card, - struct fw_node * node, - struct fw_node * parent); - -static void -for_each_fw_node(struct fw_card *card, struct fw_node *root, - fw_node_callback_t callback) -{ - struct list_head list; - struct fw_node *node, *next, *child, *parent; - int i; - - INIT_LIST_HEAD(&list); - - fw_node_get(root); - list_add_tail(&root->link, &list); - parent = NULL; - list_for_each_entry(node, &list, link) { - node->color = card->color; - - for (i = 0; i < node->port_count; i++) { - child = node->ports[i].node; - if (!child) - continue; - if (child->color == card->color) - parent = child; - else { - fw_node_get(child); - list_add_tail(&child->link, &list); - } - } - - callback(card, node, parent); - } - - list_for_each_entry_safe(node, next, &list, link) - fw_node_put(node); -} - -static void -report_lost_node(struct fw_card *card, - struct fw_node *node, struct fw_node *parent) -{ - fw_node_event(card, node, FW_NODE_DESTROYED); - fw_node_put(node); -} - -static void -report_found_node(struct fw_card *card, - struct fw_node *node, struct fw_node *parent) -{ - int b_path = (node->phy_speed == SCODE_BETA); - - if (parent != NULL) { - /* min() macro doesn't work here with gcc 3.4 */ - node->max_speed = parent->max_speed < node->phy_speed ? - parent->max_speed : node->phy_speed; - node->b_path = parent->b_path && b_path; - } else { - node->max_speed = node->phy_speed; - node->b_path = b_path; - } - - fw_node_event(card, node, FW_NODE_CREATED); -} - -void fw_destroy_nodes(struct fw_card *card) -{ - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - card->color++; - if (card->local_node != NULL) - for_each_fw_node(card, card->local_node, report_lost_node); - spin_unlock_irqrestore(&card->lock, flags); -} - -static void move_tree(struct fw_node *node0, struct fw_node *node1, int port) -{ - struct fw_node *tree; - int i; - - tree = node1->ports[port].node; - node0->ports[port].node = tree; - for (i = 0; i < tree->port_count; i++) { - if (tree->ports[i].node == node1) { - tree->ports[i].node = node0; - break; - } - } -} - -/** - * update_tree - compare the old topology tree for card with the new - * one specified by root. Queue the nodes and mark them as either - * found, lost or updated. Update the nodes in the card topology tree - * as we go. - */ -static void -update_tree(struct fw_card *card, struct fw_node *root) -{ - struct list_head list0, list1; - struct fw_node *node0, *node1; - int i, event; - - INIT_LIST_HEAD(&list0); - list_add_tail(&card->local_node->link, &list0); - INIT_LIST_HEAD(&list1); - list_add_tail(&root->link, &list1); - - node0 = fw_node(list0.next); - node1 = fw_node(list1.next); - - while (&node0->link != &list0) { - - /* assert(node0->port_count == node1->port_count); */ - if (node0->link_on && !node1->link_on) - event = FW_NODE_LINK_OFF; - else if (!node0->link_on && node1->link_on) - event = FW_NODE_LINK_ON; - else - event = FW_NODE_UPDATED; - - node0->node_id = node1->node_id; - node0->color = card->color; - node0->link_on = node1->link_on; - node0->initiated_reset = node1->initiated_reset; - node0->max_hops = node1->max_hops; - node1->color = card->color; - fw_node_event(card, node0, event); - - if (card->root_node == node1) - card->root_node = node0; - if (card->irm_node == node1) - card->irm_node = node0; - - for (i = 0; i < node0->port_count; i++) { - if (node0->ports[i].node && node1->ports[i].node) { - /* - * This port didn't change, queue the - * connected node for further - * investigation. - */ - if (node0->ports[i].node->color == card->color) - continue; - list_add_tail(&node0->ports[i].node->link, - &list0); - list_add_tail(&node1->ports[i].node->link, - &list1); - } else if (node0->ports[i].node) { - /* - * The nodes connected here were - * unplugged; unref the lost nodes and - * queue FW_NODE_LOST callbacks for - * them. - */ - - for_each_fw_node(card, node0->ports[i].node, - report_lost_node); - node0->ports[i].node = NULL; - } else if (node1->ports[i].node) { - /* - * One or more node were connected to - * this port. Move the new nodes into - * the tree and queue FW_NODE_CREATED - * callbacks for them. - */ - move_tree(node0, node1, i); - for_each_fw_node(card, node0->ports[i].node, - report_found_node); - } - } - - node0 = fw_node(node0->link.next); - node1 = fw_node(node1->link.next); - } -} - -static void -update_topology_map(struct fw_card *card, u32 *self_ids, int self_id_count) -{ - int node_count; - - card->topology_map[1]++; - node_count = (card->root_node->node_id & 0x3f) + 1; - card->topology_map[2] = (node_count << 16) | self_id_count; - card->topology_map[0] = (self_id_count + 2) << 16; - memcpy(&card->topology_map[3], self_ids, self_id_count * 4); - fw_compute_block_crc(card->topology_map); -} - -void -fw_core_handle_bus_reset(struct fw_card *card, - int node_id, int generation, - int self_id_count, u32 * self_ids) -{ - struct fw_node *local_node; - unsigned long flags; - - fw_flush_transactions(card); - - spin_lock_irqsave(&card->lock, flags); - - /* - * If the new topology has a different self_id_count the topology - * changed, either nodes were added or removed. In that case we - * reset the IRM reset counter. - */ - if (card->self_id_count != self_id_count) - card->bm_retries = 0; - - card->node_id = node_id; - card->generation = generation; - card->reset_jiffies = jiffies; - schedule_delayed_work(&card->work, 0); - - local_node = build_tree(card, self_ids, self_id_count); - - update_topology_map(card, self_ids, self_id_count); - - card->color++; - - if (local_node == NULL) { - fw_error("topology build failed\n"); - /* FIXME: We need to issue a bus reset in this case. */ - } else if (card->local_node == NULL) { - card->local_node = local_node; - for_each_fw_node(card, local_node, report_found_node); - } else { - update_tree(card, local_node); - } - - spin_unlock_irqrestore(&card->lock, flags); -} -EXPORT_SYMBOL(fw_core_handle_bus_reset); diff --git a/trunk/drivers/firewire/fw-topology.h b/trunk/drivers/firewire/fw-topology.h deleted file mode 100644 index 363b6cbcd0b3..000000000000 --- a/trunk/drivers/firewire/fw-topology.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2003-2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __fw_topology_h -#define __fw_topology_h - -enum { - FW_TOPOLOGY_A = 0x01, - FW_TOPOLOGY_B = 0x02, - FW_TOPOLOGY_MIXED = 0x03, -}; - -enum { - FW_NODE_CREATED = 0x00, - FW_NODE_UPDATED = 0x01, - FW_NODE_DESTROYED = 0x02, - FW_NODE_LINK_ON = 0x03, - FW_NODE_LINK_OFF = 0x04, -}; - -struct fw_port { - struct fw_node *node; - unsigned speed : 3; /* S100, S200, ... S3200 */ -}; - -struct fw_node { - u16 node_id; - u8 color; - u8 port_count; - unsigned link_on : 1; - unsigned initiated_reset : 1; - unsigned b_path : 1; - u8 phy_speed : 3; /* As in the self ID packet. */ - u8 max_speed : 5; /* Minimum of all phy-speeds and port speeds on - * the path from the local node to this node. */ - u8 max_depth : 4; /* Maximum depth to any leaf node */ - u8 max_hops : 4; /* Max hops in this sub tree */ - atomic_t ref_count; - - /* For serializing node topology into a list. */ - struct list_head link; - - /* Upper layer specific data. */ - void *data; - - struct fw_port ports[0]; -}; - -static inline struct fw_node * -fw_node(struct list_head *l) -{ - return list_entry(l, struct fw_node, link); -} - -static inline struct fw_node * -fw_node_get(struct fw_node *node) -{ - atomic_inc(&node->ref_count); - - return node; -} - -static inline void -fw_node_put(struct fw_node *node) -{ - if (atomic_dec_and_test(&node->ref_count)) - kfree(node); -} - -void -fw_destroy_nodes(struct fw_card *card); - -int -fw_compute_block_crc(u32 *block); - - -#endif /* __fw_topology_h */ diff --git a/trunk/drivers/firewire/fw-transaction.c b/trunk/drivers/firewire/fw-transaction.c deleted file mode 100644 index 80d0121463d0..000000000000 --- a/trunk/drivers/firewire/fw-transaction.c +++ /dev/null @@ -1,910 +0,0 @@ -/* - * Core IEEE1394 transaction logic - * - * Copyright (C) 2004-2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "fw-transaction.h" -#include "fw-topology.h" -#include "fw-device.h" - -#define HEADER_PRI(pri) ((pri) << 0) -#define HEADER_TCODE(tcode) ((tcode) << 4) -#define HEADER_RETRY(retry) ((retry) << 8) -#define HEADER_TLABEL(tlabel) ((tlabel) << 10) -#define HEADER_DESTINATION(destination) ((destination) << 16) -#define HEADER_SOURCE(source) ((source) << 16) -#define HEADER_RCODE(rcode) ((rcode) << 12) -#define HEADER_OFFSET_HIGH(offset_high) ((offset_high) << 0) -#define HEADER_DATA_LENGTH(length) ((length) << 16) -#define HEADER_EXTENDED_TCODE(tcode) ((tcode) << 0) - -#define HEADER_GET_TCODE(q) (((q) >> 4) & 0x0f) -#define HEADER_GET_TLABEL(q) (((q) >> 10) & 0x3f) -#define HEADER_GET_RCODE(q) (((q) >> 12) & 0x0f) -#define HEADER_GET_DESTINATION(q) (((q) >> 16) & 0xffff) -#define HEADER_GET_SOURCE(q) (((q) >> 16) & 0xffff) -#define HEADER_GET_OFFSET_HIGH(q) (((q) >> 0) & 0xffff) -#define HEADER_GET_DATA_LENGTH(q) (((q) >> 16) & 0xffff) -#define HEADER_GET_EXTENDED_TCODE(q) (((q) >> 0) & 0xffff) - -#define PHY_CONFIG_GAP_COUNT(gap_count) (((gap_count) << 16) | (1 << 22)) -#define PHY_CONFIG_ROOT_ID(node_id) ((((node_id) & 0x3f) << 24) | (1 << 23)) -#define PHY_IDENTIFIER(id) ((id) << 30) - -static int -close_transaction(struct fw_transaction *transaction, - struct fw_card *card, int rcode, - u32 *payload, size_t length) -{ - struct fw_transaction *t; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - list_for_each_entry(t, &card->transaction_list, link) { - if (t == transaction) { - list_del(&t->link); - card->tlabel_mask &= ~(1 << t->tlabel); - break; - } - } - spin_unlock_irqrestore(&card->lock, flags); - - if (&t->link != &card->transaction_list) { - t->callback(card, rcode, payload, length, t->callback_data); - return 0; - } - - return -ENOENT; -} - -/* - * Only valid for transactions that are potentially pending (ie have - * been sent). - */ -int -fw_cancel_transaction(struct fw_card *card, - struct fw_transaction *transaction) -{ - /* - * Cancel the packet transmission if it's still queued. That - * will call the packet transmission callback which cancels - * the transaction. - */ - - if (card->driver->cancel_packet(card, &transaction->packet) == 0) - return 0; - - /* - * If the request packet has already been sent, we need to see - * if the transaction is still pending and remove it in that case. - */ - - return close_transaction(transaction, card, RCODE_CANCELLED, NULL, 0); -} -EXPORT_SYMBOL(fw_cancel_transaction); - -static void -transmit_complete_callback(struct fw_packet *packet, - struct fw_card *card, int status) -{ - struct fw_transaction *t = - container_of(packet, struct fw_transaction, packet); - - switch (status) { - case ACK_COMPLETE: - close_transaction(t, card, RCODE_COMPLETE, NULL, 0); - break; - case ACK_PENDING: - t->timestamp = packet->timestamp; - break; - case ACK_BUSY_X: - case ACK_BUSY_A: - case ACK_BUSY_B: - close_transaction(t, card, RCODE_BUSY, NULL, 0); - break; - case ACK_DATA_ERROR: - close_transaction(t, card, RCODE_DATA_ERROR, NULL, 0); - break; - case ACK_TYPE_ERROR: - close_transaction(t, card, RCODE_TYPE_ERROR, NULL, 0); - break; - default: - /* - * In this case the ack is really a juju specific - * rcode, so just forward that to the callback. - */ - close_transaction(t, card, status, NULL, 0); - break; - } -} - -static void -fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, - int node_id, int source_id, int generation, int speed, - unsigned long long offset, void *payload, size_t length) -{ - int ext_tcode; - - if (tcode > 0x10) { - ext_tcode = tcode - 0x10; - tcode = TCODE_LOCK_REQUEST; - } else - ext_tcode = 0; - - packet->header[0] = - HEADER_RETRY(RETRY_X) | - HEADER_TLABEL(tlabel) | - HEADER_TCODE(tcode) | - HEADER_DESTINATION(node_id); - packet->header[1] = - HEADER_OFFSET_HIGH(offset >> 32) | HEADER_SOURCE(source_id); - packet->header[2] = - offset; - - switch (tcode) { - case TCODE_WRITE_QUADLET_REQUEST: - packet->header[3] = *(u32 *)payload; - packet->header_length = 16; - packet->payload_length = 0; - break; - - case TCODE_LOCK_REQUEST: - case TCODE_WRITE_BLOCK_REQUEST: - packet->header[3] = - HEADER_DATA_LENGTH(length) | - HEADER_EXTENDED_TCODE(ext_tcode); - packet->header_length = 16; - packet->payload = payload; - packet->payload_length = length; - break; - - case TCODE_READ_QUADLET_REQUEST: - packet->header_length = 12; - packet->payload_length = 0; - break; - - case TCODE_READ_BLOCK_REQUEST: - packet->header[3] = - HEADER_DATA_LENGTH(length) | - HEADER_EXTENDED_TCODE(ext_tcode); - packet->header_length = 16; - packet->payload_length = 0; - break; - } - - packet->speed = speed; - packet->generation = generation; - packet->ack = 0; -} - -/** - * This function provides low-level access to the IEEE1394 transaction - * logic. Most C programs would use either fw_read(), fw_write() or - * fw_lock() instead - those function are convenience wrappers for - * this function. The fw_send_request() function is primarily - * provided as a flexible, one-stop entry point for languages bindings - * and protocol bindings. - * - * FIXME: Document this function further, in particular the possible - * values for rcode in the callback. In short, we map ACK_COMPLETE to - * RCODE_COMPLETE, internal errors set errno and set rcode to - * RCODE_SEND_ERROR (which is out of range for standard ieee1394 - * rcodes). All other rcodes are forwarded unchanged. For all - * errors, payload is NULL, length is 0. - * - * Can not expect the callback to be called before the function - * returns, though this does happen in some cases (ACK_COMPLETE and - * errors). - * - * The payload is only used for write requests and must not be freed - * until the callback has been called. - * - * @param card the card from which to send the request - * @param tcode the tcode for this transaction. Do not use - * TCODE_LOCK_REQUEST directly, insted use TCODE_LOCK_MASK_SWAP - * etc. to specify tcode and ext_tcode. - * @param node_id the destination node ID (bus ID and PHY ID concatenated) - * @param generation the generation for which node_id is valid - * @param speed the speed to use for sending the request - * @param offset the 48 bit offset on the destination node - * @param payload the data payload for the request subaction - * @param length the length in bytes of the data to read - * @param callback function to be called when the transaction is completed - * @param callback_data pointer to arbitrary data, which will be - * passed to the callback - */ -void -fw_send_request(struct fw_card *card, struct fw_transaction *t, - int tcode, int node_id, int generation, int speed, - unsigned long long offset, - void *payload, size_t length, - fw_transaction_callback_t callback, void *callback_data) -{ - unsigned long flags; - int tlabel, source; - - /* - * Bump the flush timer up 100ms first of all so we - * don't race with a flush timer callback. - */ - - mod_timer(&card->flush_timer, jiffies + DIV_ROUND_UP(HZ, 10)); - - /* - * Allocate tlabel from the bitmap and put the transaction on - * the list while holding the card spinlock. - */ - - spin_lock_irqsave(&card->lock, flags); - - source = card->node_id; - tlabel = card->current_tlabel; - if (card->tlabel_mask & (1 << tlabel)) { - spin_unlock_irqrestore(&card->lock, flags); - callback(card, RCODE_SEND_ERROR, NULL, 0, callback_data); - return; - } - - card->current_tlabel = (card->current_tlabel + 1) & 0x1f; - card->tlabel_mask |= (1 << tlabel); - - list_add_tail(&t->link, &card->transaction_list); - - spin_unlock_irqrestore(&card->lock, flags); - - /* Initialize rest of transaction, fill out packet and send it. */ - t->node_id = node_id; - t->tlabel = tlabel; - t->callback = callback; - t->callback_data = callback_data; - - fw_fill_request(&t->packet, tcode, t->tlabel, - node_id, source, generation, - speed, offset, payload, length); - t->packet.callback = transmit_complete_callback; - - card->driver->send_request(card, &t->packet); -} -EXPORT_SYMBOL(fw_send_request); - -static void -transmit_phy_packet_callback(struct fw_packet *packet, - struct fw_card *card, int status) -{ - kfree(packet); -} - -static void send_phy_packet(struct fw_card *card, u32 data, int generation) -{ - struct fw_packet *packet; - - packet = kzalloc(sizeof(*packet), GFP_ATOMIC); - if (packet == NULL) - return; - - packet->header[0] = data; - packet->header[1] = ~data; - packet->header_length = 8; - packet->payload_length = 0; - packet->speed = SCODE_100; - packet->generation = generation; - packet->callback = transmit_phy_packet_callback; - - card->driver->send_request(card, packet); -} - -void fw_send_phy_config(struct fw_card *card, - int node_id, int generation, int gap_count) -{ - u32 q; - - q = PHY_IDENTIFIER(PHY_PACKET_CONFIG) | - PHY_CONFIG_ROOT_ID(node_id) | - PHY_CONFIG_GAP_COUNT(gap_count); - - send_phy_packet(card, q, generation); -} - -void fw_flush_transactions(struct fw_card *card) -{ - struct fw_transaction *t, *next; - struct list_head list; - unsigned long flags; - - INIT_LIST_HEAD(&list); - spin_lock_irqsave(&card->lock, flags); - list_splice_init(&card->transaction_list, &list); - card->tlabel_mask = 0; - spin_unlock_irqrestore(&card->lock, flags); - - list_for_each_entry_safe(t, next, &list, link) { - card->driver->cancel_packet(card, &t->packet); - - /* - * At this point cancel_packet will never call the - * transaction callback, since we just took all the - * transactions out of the list. So do it here. - */ - t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data); - } -} - -static struct fw_address_handler * -lookup_overlapping_address_handler(struct list_head *list, - unsigned long long offset, size_t length) -{ - struct fw_address_handler *handler; - - list_for_each_entry(handler, list, link) { - if (handler->offset < offset + length && - offset < handler->offset + handler->length) - return handler; - } - - return NULL; -} - -static struct fw_address_handler * -lookup_enclosing_address_handler(struct list_head *list, - unsigned long long offset, size_t length) -{ - struct fw_address_handler *handler; - - list_for_each_entry(handler, list, link) { - if (handler->offset <= offset && - offset + length <= handler->offset + handler->length) - return handler; - } - - return NULL; -} - -static DEFINE_SPINLOCK(address_handler_lock); -static LIST_HEAD(address_handler_list); - -const struct fw_address_region fw_low_memory_region = - { .start = 0x000000000000ULL, .end = 0x000100000000ULL, }; -const struct fw_address_region fw_high_memory_region = - { .start = 0x000100000000ULL, .end = 0xffffe0000000ULL, }; -const struct fw_address_region fw_private_region = - { .start = 0xffffe0000000ULL, .end = 0xfffff0000000ULL, }; -const struct fw_address_region fw_csr_region = - { .start = 0xfffff0000000ULL, .end = 0xfffff0000800ULL, }; -const struct fw_address_region fw_unit_space_region = - { .start = 0xfffff0000900ULL, .end = 0x1000000000000ULL, }; -EXPORT_SYMBOL(fw_low_memory_region); -EXPORT_SYMBOL(fw_high_memory_region); -EXPORT_SYMBOL(fw_private_region); -EXPORT_SYMBOL(fw_csr_region); -EXPORT_SYMBOL(fw_unit_space_region); - -/** - * Allocate a range of addresses in the node space of the OHCI - * controller. When a request is received that falls within the - * specified address range, the specified callback is invoked. The - * parameters passed to the callback give the details of the - * particular request - */ -int -fw_core_add_address_handler(struct fw_address_handler *handler, - const struct fw_address_region *region) -{ - struct fw_address_handler *other; - unsigned long flags; - int ret = -EBUSY; - - spin_lock_irqsave(&address_handler_lock, flags); - - handler->offset = region->start; - while (handler->offset + handler->length <= region->end) { - other = - lookup_overlapping_address_handler(&address_handler_list, - handler->offset, - handler->length); - if (other != NULL) { - handler->offset += other->length; - } else { - list_add_tail(&handler->link, &address_handler_list); - ret = 0; - break; - } - } - - spin_unlock_irqrestore(&address_handler_lock, flags); - - return ret; -} -EXPORT_SYMBOL(fw_core_add_address_handler); - -/** - * Deallocate a range of addresses allocated with fw_allocate. This - * will call the associated callback one last time with a the special - * tcode TCODE_DEALLOCATE, to let the client destroy the registered - * callback data. For convenience, the callback parameters offset and - * length are set to the start and the length respectively for the - * deallocated region, payload is set to NULL. - */ -void fw_core_remove_address_handler(struct fw_address_handler *handler) -{ - unsigned long flags; - - spin_lock_irqsave(&address_handler_lock, flags); - list_del(&handler->link); - spin_unlock_irqrestore(&address_handler_lock, flags); -} -EXPORT_SYMBOL(fw_core_remove_address_handler); - -struct fw_request { - struct fw_packet response; - u32 request_header[4]; - int ack; - u32 length; - u32 data[0]; -}; - -static void -free_response_callback(struct fw_packet *packet, - struct fw_card *card, int status) -{ - struct fw_request *request; - - request = container_of(packet, struct fw_request, response); - kfree(request); -} - -void -fw_fill_response(struct fw_packet *response, u32 *request_header, - int rcode, void *payload, size_t length) -{ - int tcode, tlabel, extended_tcode, source, destination; - - tcode = HEADER_GET_TCODE(request_header[0]); - tlabel = HEADER_GET_TLABEL(request_header[0]); - source = HEADER_GET_DESTINATION(request_header[0]); - destination = HEADER_GET_SOURCE(request_header[1]); - extended_tcode = HEADER_GET_EXTENDED_TCODE(request_header[3]); - - response->header[0] = - HEADER_RETRY(RETRY_1) | - HEADER_TLABEL(tlabel) | - HEADER_DESTINATION(destination); - response->header[1] = - HEADER_SOURCE(source) | - HEADER_RCODE(rcode); - response->header[2] = 0; - - switch (tcode) { - case TCODE_WRITE_QUADLET_REQUEST: - case TCODE_WRITE_BLOCK_REQUEST: - response->header[0] |= HEADER_TCODE(TCODE_WRITE_RESPONSE); - response->header_length = 12; - response->payload_length = 0; - break; - - case TCODE_READ_QUADLET_REQUEST: - response->header[0] |= - HEADER_TCODE(TCODE_READ_QUADLET_RESPONSE); - if (payload != NULL) - response->header[3] = *(u32 *)payload; - else - response->header[3] = 0; - response->header_length = 16; - response->payload_length = 0; - break; - - case TCODE_READ_BLOCK_REQUEST: - case TCODE_LOCK_REQUEST: - response->header[0] |= HEADER_TCODE(tcode + 2); - response->header[3] = - HEADER_DATA_LENGTH(length) | - HEADER_EXTENDED_TCODE(extended_tcode); - response->header_length = 16; - response->payload = payload; - response->payload_length = length; - break; - - default: - BUG(); - return; - } -} -EXPORT_SYMBOL(fw_fill_response); - -static struct fw_request * -allocate_request(struct fw_packet *p) -{ - struct fw_request *request; - u32 *data, length; - int request_tcode, t; - - request_tcode = HEADER_GET_TCODE(p->header[0]); - switch (request_tcode) { - case TCODE_WRITE_QUADLET_REQUEST: - data = &p->header[3]; - length = 4; - break; - - case TCODE_WRITE_BLOCK_REQUEST: - case TCODE_LOCK_REQUEST: - data = p->payload; - length = HEADER_GET_DATA_LENGTH(p->header[3]); - break; - - case TCODE_READ_QUADLET_REQUEST: - data = NULL; - length = 4; - break; - - case TCODE_READ_BLOCK_REQUEST: - data = NULL; - length = HEADER_GET_DATA_LENGTH(p->header[3]); - break; - - default: - BUG(); - return NULL; - } - - request = kmalloc(sizeof(*request) + length, GFP_ATOMIC); - if (request == NULL) - return NULL; - - t = (p->timestamp & 0x1fff) + 4000; - if (t >= 8000) - t = (p->timestamp & ~0x1fff) + 0x2000 + t - 8000; - else - t = (p->timestamp & ~0x1fff) + t; - - request->response.speed = p->speed; - request->response.timestamp = t; - request->response.generation = p->generation; - request->response.ack = 0; - request->response.callback = free_response_callback; - request->ack = p->ack; - request->length = length; - if (data) - memcpy(request->data, data, length); - - memcpy(request->request_header, p->header, sizeof(p->header)); - - return request; -} - -void -fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) -{ - /* - * Broadcast packets are reported as ACK_COMPLETE, so this - * check is sufficient to ensure we don't send response to - * broadcast packets or posted writes. - */ - if (request->ack != ACK_PENDING) - return; - - if (rcode == RCODE_COMPLETE) - fw_fill_response(&request->response, request->request_header, - rcode, request->data, request->length); - else - fw_fill_response(&request->response, request->request_header, - rcode, NULL, 0); - - card->driver->send_response(card, &request->response); -} -EXPORT_SYMBOL(fw_send_response); - -void -fw_core_handle_request(struct fw_card *card, struct fw_packet *p) -{ - struct fw_address_handler *handler; - struct fw_request *request; - unsigned long long offset; - unsigned long flags; - int tcode, destination, source; - - if (p->payload_length > 2048) { - /* FIXME: send error response. */ - return; - } - - if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE) - return; - - request = allocate_request(p); - if (request == NULL) { - /* FIXME: send statically allocated busy packet. */ - return; - } - - offset = - ((unsigned long long) - HEADER_GET_OFFSET_HIGH(p->header[1]) << 32) | p->header[2]; - tcode = HEADER_GET_TCODE(p->header[0]); - destination = HEADER_GET_DESTINATION(p->header[0]); - source = HEADER_GET_SOURCE(p->header[0]); - - spin_lock_irqsave(&address_handler_lock, flags); - handler = lookup_enclosing_address_handler(&address_handler_list, - offset, request->length); - spin_unlock_irqrestore(&address_handler_lock, flags); - - /* - * FIXME: lookup the fw_node corresponding to the sender of - * this request and pass that to the address handler instead - * of the node ID. We may also want to move the address - * allocations to fw_node so we only do this callback if the - * upper layers registered it for this node. - */ - - if (handler == NULL) - fw_send_response(card, request, RCODE_ADDRESS_ERROR); - else - handler->address_callback(card, request, - tcode, destination, source, - p->generation, p->speed, offset, - request->data, request->length, - handler->callback_data); -} -EXPORT_SYMBOL(fw_core_handle_request); - -void -fw_core_handle_response(struct fw_card *card, struct fw_packet *p) -{ - struct fw_transaction *t; - unsigned long flags; - u32 *data; - size_t data_length; - int tcode, tlabel, destination, source, rcode; - - tcode = HEADER_GET_TCODE(p->header[0]); - tlabel = HEADER_GET_TLABEL(p->header[0]); - destination = HEADER_GET_DESTINATION(p->header[0]); - source = HEADER_GET_SOURCE(p->header[1]); - rcode = HEADER_GET_RCODE(p->header[1]); - - spin_lock_irqsave(&card->lock, flags); - list_for_each_entry(t, &card->transaction_list, link) { - if (t->node_id == source && t->tlabel == tlabel) { - list_del(&t->link); - card->tlabel_mask &= ~(1 << t->tlabel); - break; - } - } - spin_unlock_irqrestore(&card->lock, flags); - - if (&t->link == &card->transaction_list) { - fw_notify("Unsolicited response (source %x, tlabel %x)\n", - source, tlabel); - return; - } - - /* - * FIXME: sanity check packet, is length correct, does tcodes - * and addresses match. - */ - - switch (tcode) { - case TCODE_READ_QUADLET_RESPONSE: - data = (u32 *) &p->header[3]; - data_length = 4; - break; - - case TCODE_WRITE_RESPONSE: - data = NULL; - data_length = 0; - break; - - case TCODE_READ_BLOCK_RESPONSE: - case TCODE_LOCK_RESPONSE: - data = p->payload; - data_length = HEADER_GET_DATA_LENGTH(p->header[3]); - break; - - default: - /* Should never happen, this is just to shut up gcc. */ - data = NULL; - data_length = 0; - break; - } - - t->callback(card, rcode, data, data_length, t->callback_data); -} -EXPORT_SYMBOL(fw_core_handle_response); - -const struct fw_address_region topology_map_region = - { .start = 0xfffff0001000ull, .end = 0xfffff0001400ull, }; - -static void -handle_topology_map(struct fw_card *card, struct fw_request *request, - int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, - void *payload, size_t length, void *callback_data) -{ - int i, start, end; - u32 *map; - - if (!TCODE_IS_READ_REQUEST(tcode)) { - fw_send_response(card, request, RCODE_TYPE_ERROR); - return; - } - - if ((offset & 3) > 0 || (length & 3) > 0) { - fw_send_response(card, request, RCODE_ADDRESS_ERROR); - return; - } - - start = (offset - topology_map_region.start) / 4; - end = start + length / 4; - map = payload; - - for (i = 0; i < length / 4; i++) - map[i] = cpu_to_be32(card->topology_map[start + i]); - - fw_send_response(card, request, RCODE_COMPLETE); -} - -static struct fw_address_handler topology_map = { - .length = 0x200, - .address_callback = handle_topology_map, -}; - -const struct fw_address_region registers_region = - { .start = 0xfffff0000000ull, .end = 0xfffff0000400ull, }; - -static void -handle_registers(struct fw_card *card, struct fw_request *request, - int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, - void *payload, size_t length, void *callback_data) -{ - int reg = offset - CSR_REGISTER_BASE; - unsigned long long bus_time; - __be32 *data = payload; - - switch (reg) { - case CSR_CYCLE_TIME: - case CSR_BUS_TIME: - if (!TCODE_IS_READ_REQUEST(tcode) || length != 4) { - fw_send_response(card, request, RCODE_TYPE_ERROR); - break; - } - - bus_time = card->driver->get_bus_time(card); - if (reg == CSR_CYCLE_TIME) - *data = cpu_to_be32(bus_time); - else - *data = cpu_to_be32(bus_time >> 25); - fw_send_response(card, request, RCODE_COMPLETE); - break; - - case CSR_BUS_MANAGER_ID: - case CSR_BANDWIDTH_AVAILABLE: - case CSR_CHANNELS_AVAILABLE_HI: - case CSR_CHANNELS_AVAILABLE_LO: - /* - * FIXME: these are handled by the OHCI hardware and - * the stack never sees these request. If we add - * support for a new type of controller that doesn't - * handle this in hardware we need to deal with these - * transactions. - */ - BUG(); - break; - - case CSR_BUSY_TIMEOUT: - /* FIXME: Implement this. */ - default: - fw_send_response(card, request, RCODE_ADDRESS_ERROR); - break; - } -} - -static struct fw_address_handler registers = { - .length = 0x400, - .address_callback = handle_registers, -}; - -MODULE_AUTHOR("Kristian Hoegsberg "); -MODULE_DESCRIPTION("Core IEEE1394 transaction logic"); -MODULE_LICENSE("GPL"); - -static const u32 vendor_textual_descriptor[] = { - /* textual descriptor leaf () */ - 0x00060000, - 0x00000000, - 0x00000000, - 0x4c696e75, /* L i n u */ - 0x78204669, /* x F i */ - 0x72657769, /* r e w i */ - 0x72650000, /* r e */ -}; - -static const u32 model_textual_descriptor[] = { - /* model descriptor leaf () */ - 0x00030000, - 0x00000000, - 0x00000000, - 0x4a756a75, /* J u j u */ -}; - -static struct fw_descriptor vendor_id_descriptor = { - .length = ARRAY_SIZE(vendor_textual_descriptor), - .immediate = 0x03d00d1e, - .key = 0x81000000, - .data = vendor_textual_descriptor, -}; - -static struct fw_descriptor model_id_descriptor = { - .length = ARRAY_SIZE(model_textual_descriptor), - .immediate = 0x17000001, - .key = 0x81000000, - .data = model_textual_descriptor, -}; - -static int __init fw_core_init(void) -{ - int retval; - - retval = bus_register(&fw_bus_type); - if (retval < 0) - return retval; - - fw_cdev_major = register_chrdev(0, "firewire", &fw_device_ops); - if (fw_cdev_major < 0) { - bus_unregister(&fw_bus_type); - return fw_cdev_major; - } - - retval = fw_core_add_address_handler(&topology_map, - &topology_map_region); - BUG_ON(retval < 0); - - retval = fw_core_add_address_handler(®isters, - ®isters_region); - BUG_ON(retval < 0); - - /* Add the vendor textual descriptor. */ - retval = fw_core_add_descriptor(&vendor_id_descriptor); - BUG_ON(retval < 0); - retval = fw_core_add_descriptor(&model_id_descriptor); - BUG_ON(retval < 0); - - return 0; -} - -static void __exit fw_core_cleanup(void) -{ - unregister_chrdev(fw_cdev_major, "firewire"); - bus_unregister(&fw_bus_type); -} - -module_init(fw_core_init); -module_exit(fw_core_cleanup); diff --git a/trunk/drivers/firewire/fw-transaction.h b/trunk/drivers/firewire/fw-transaction.h deleted file mode 100644 index acdc3be38c61..000000000000 --- a/trunk/drivers/firewire/fw-transaction.h +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (C) 2003-2006 Kristian Hoegsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __fw_transaction_h -#define __fw_transaction_h - -#include -#include -#include -#include -#include -#include -#include - -#define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4) -#define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0) -#define TCODE_IS_REQUEST(tcode) (((tcode) & 2) == 0) -#define TCODE_IS_RESPONSE(tcode) (((tcode) & 2) != 0) -#define TCODE_HAS_REQUEST_DATA(tcode) (((tcode) & 12) != 4) -#define TCODE_HAS_RESPONSE_DATA(tcode) (((tcode) & 12) != 0) - -#define LOCAL_BUS 0xffc0 - -#define SELFID_PORT_CHILD 0x3 -#define SELFID_PORT_PARENT 0x2 -#define SELFID_PORT_NCONN 0x1 -#define SELFID_PORT_NONE 0x0 - -#define PHY_PACKET_CONFIG 0x0 -#define PHY_PACKET_LINK_ON 0x1 -#define PHY_PACKET_SELF_ID 0x2 - -/* Bit fields _within_ the PHY registers. */ -#define PHY_LINK_ACTIVE 0x80 -#define PHY_CONTENDER 0x40 -#define PHY_BUS_RESET 0x40 -#define PHY_BUS_SHORT_RESET 0x40 - -#define CSR_REGISTER_BASE 0xfffff0000000ULL - -/* register offsets relative to CSR_REGISTER_BASE */ -#define CSR_STATE_CLEAR 0x0 -#define CSR_STATE_SET 0x4 -#define CSR_NODE_IDS 0x8 -#define CSR_RESET_START 0xc -#define CSR_SPLIT_TIMEOUT_HI 0x18 -#define CSR_SPLIT_TIMEOUT_LO 0x1c -#define CSR_CYCLE_TIME 0x200 -#define CSR_BUS_TIME 0x204 -#define CSR_BUSY_TIMEOUT 0x210 -#define CSR_BUS_MANAGER_ID 0x21c -#define CSR_BANDWIDTH_AVAILABLE 0x220 -#define CSR_CHANNELS_AVAILABLE 0x224 -#define CSR_CHANNELS_AVAILABLE_HI 0x224 -#define CSR_CHANNELS_AVAILABLE_LO 0x228 -#define CSR_BROADCAST_CHANNEL 0x234 -#define CSR_CONFIG_ROM 0x400 -#define CSR_CONFIG_ROM_END 0x800 -#define CSR_FCP_COMMAND 0xB00 -#define CSR_FCP_RESPONSE 0xD00 -#define CSR_FCP_END 0xF00 -#define CSR_TOPOLOGY_MAP 0x1000 -#define CSR_TOPOLOGY_MAP_END 0x1400 -#define CSR_SPEED_MAP 0x2000 -#define CSR_SPEED_MAP_END 0x3000 - -#define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args) -#define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args) -#define fw_debug(s, args...) printk(KERN_DEBUG KBUILD_MODNAME ": " s, ## args) - -static inline void -fw_memcpy_from_be32(void *_dst, void *_src, size_t size) -{ - u32 *dst = _dst; - u32 *src = _src; - int i; - - for (i = 0; i < size / 4; i++) - dst[i] = cpu_to_be32(src[i]); -} - -static inline void -fw_memcpy_to_be32(void *_dst, void *_src, size_t size) -{ - fw_memcpy_from_be32(_dst, _src, size); -} - -struct fw_card; -struct fw_packet; -struct fw_node; -struct fw_request; - -struct fw_descriptor { - struct list_head link; - size_t length; - u32 immediate; - u32 key; - const u32 *data; -}; - -int fw_core_add_descriptor(struct fw_descriptor *desc); -void fw_core_remove_descriptor(struct fw_descriptor *desc); - -typedef void (*fw_packet_callback_t)(struct fw_packet *packet, - struct fw_card *card, int status); - -typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode, - void *data, - size_t length, - void *callback_data); - -typedef void (*fw_address_callback_t)(struct fw_card *card, - struct fw_request *request, - int tcode, int destination, int source, - int generation, int speed, - unsigned long long offset, - void *data, size_t length, - void *callback_data); - -typedef void (*fw_bus_reset_callback_t)(struct fw_card *handle, - int node_id, int generation, - u32 *self_ids, - int self_id_count, - void *callback_data); - -struct fw_packet { - int speed; - int generation; - u32 header[4]; - size_t header_length; - void *payload; - size_t payload_length; - u32 timestamp; - - /* - * This callback is called when the packet transmission has - * completed; for successful transmission, the status code is - * the ack received from the destination, otherwise it's a - * negative errno: ENOMEM, ESTALE, ETIMEDOUT, ENODEV, EIO. - * The callback can be called from tasklet context and thus - * must never block. - */ - fw_packet_callback_t callback; - int ack; - struct list_head link; - void *driver_data; -}; - -struct fw_transaction { - int node_id; /* The generation is implied; it is always the current. */ - int tlabel; - int timestamp; - struct list_head link; - - struct fw_packet packet; - - /* - * The data passed to the callback is valid only during the - * callback. - */ - fw_transaction_callback_t callback; - void *callback_data; -}; - -static inline struct fw_packet * -fw_packet(struct list_head *l) -{ - return list_entry(l, struct fw_packet, link); -} - -struct fw_address_handler { - u64 offset; - size_t length; - fw_address_callback_t address_callback; - void *callback_data; - struct list_head link; -}; - - -struct fw_address_region { - u64 start; - u64 end; -}; - -extern const struct fw_address_region fw_low_memory_region; -extern const struct fw_address_region fw_high_memory_region; -extern const struct fw_address_region fw_private_region; -extern const struct fw_address_region fw_csr_region; -extern const struct fw_address_region fw_unit_space_region; - -int fw_core_add_address_handler(struct fw_address_handler *handler, - const struct fw_address_region *region); -void fw_core_remove_address_handler(struct fw_address_handler *handler); -void fw_fill_response(struct fw_packet *response, u32 *request_header, - int rcode, void *payload, size_t length); -void fw_send_response(struct fw_card *card, - struct fw_request *request, int rcode); - -extern struct bus_type fw_bus_type; - -struct fw_card { - const struct fw_card_driver *driver; - struct device *device; - struct kref kref; - - int node_id; - int generation; - /* This is the generation used for timestamping incoming requests. */ - int request_generation; - int current_tlabel, tlabel_mask; - struct list_head transaction_list; - struct timer_list flush_timer; - unsigned long reset_jiffies; - - unsigned long long guid; - int max_receive; - int link_speed; - int config_rom_generation; - - /* - * We need to store up to 4 self ID for a maximum of 63 - * devices plus 3 words for the topology map header. - */ - int self_id_count; - u32 topology_map[252 + 3]; - - spinlock_t lock; /* Take this lock when handling the lists in - * this struct. */ - struct fw_node *local_node; - struct fw_node *root_node; - struct fw_node *irm_node; - int color; - int gap_count; - int topology_type; - - int index; - - struct list_head link; - - /* Work struct for BM duties. */ - struct delayed_work work; - int bm_retries; - int bm_generation; -}; - -struct fw_card *fw_card_get(struct fw_card *card); -void fw_card_put(struct fw_card *card); - -/* - * The iso packet format allows for an immediate header/payload part - * stored in 'header' immediately after the packet info plus an - * indirect payload part that is pointer to by the 'payload' field. - * Applications can use one or the other or both to implement simple - * low-bandwidth streaming (e.g. audio) or more advanced - * scatter-gather streaming (e.g. assembling video frame automatically). - */ - -struct fw_iso_packet { - u16 payload_length; /* Length of indirect payload. */ - u32 interrupt : 1; /* Generate interrupt on this packet */ - u32 skip : 1; /* Set to not send packet at all. */ - u32 tag : 2; - u32 sy : 4; - u32 header_length : 8; /* Length of immediate header. */ - u32 header[0]; -}; - -#define FW_ISO_CONTEXT_TRANSMIT 0 -#define FW_ISO_CONTEXT_RECEIVE 1 - -#define FW_ISO_CONTEXT_MATCH_TAG0 1 -#define FW_ISO_CONTEXT_MATCH_TAG1 2 -#define FW_ISO_CONTEXT_MATCH_TAG2 4 -#define FW_ISO_CONTEXT_MATCH_TAG3 8 -#define FW_ISO_CONTEXT_MATCH_ALL_TAGS 15 - -struct fw_iso_context; - -typedef void (*fw_iso_callback_t)(struct fw_iso_context *context, - u32 cycle, - size_t header_length, - void *header, - void *data); - -/* - * An iso buffer is just a set of pages mapped for DMA in the - * specified direction. Since the pages are to be used for DMA, they - * are not mapped into the kernel virtual address space. We store the - * DMA address in the page private. The helper function - * fw_iso_buffer_map() will map the pages into a given vma. - */ - -struct fw_iso_buffer { - enum dma_data_direction direction; - struct page **pages; - int page_count; -}; - -struct fw_iso_context { - struct fw_card *card; - int type; - int channel; - int speed; - size_t header_size; - fw_iso_callback_t callback; - void *callback_data; -}; - -int -fw_iso_buffer_init(struct fw_iso_buffer *buffer, - struct fw_card *card, - int page_count, - enum dma_data_direction direction); -int -fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); -void -fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); - -struct fw_iso_context * -fw_iso_context_create(struct fw_card *card, int type, - int channel, int speed, size_t header_size, - fw_iso_callback_t callback, void *callback_data); - -void -fw_iso_context_destroy(struct fw_iso_context *ctx); - -int -fw_iso_context_queue(struct fw_iso_context *ctx, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload); - -int -fw_iso_context_start(struct fw_iso_context *ctx, - int cycle, int sync, int tags); - -int -fw_iso_context_stop(struct fw_iso_context *ctx); - -struct fw_card_driver { - const char *name; - - /* - * Enable the given card with the given initial config rom. - * This function is expected to activate the card, and either - * enable the PHY or set the link_on bit and initiate a bus - * reset. - */ - int (*enable)(struct fw_card *card, u32 *config_rom, size_t length); - - int (*update_phy_reg)(struct fw_card *card, int address, - int clear_bits, int set_bits); - - /* - * Update the config rom for an enabled card. This function - * should change the config rom that is presented on the bus - * an initiate a bus reset. - */ - int (*set_config_rom)(struct fw_card *card, - u32 *config_rom, size_t length); - - void (*send_request)(struct fw_card *card, struct fw_packet *packet); - void (*send_response)(struct fw_card *card, struct fw_packet *packet); - /* Calling cancel is valid once a packet has been submitted. */ - int (*cancel_packet)(struct fw_card *card, struct fw_packet *packet); - - /* - * Allow the specified node ID to do direct DMA out and in of - * host memory. The card will disable this for all node when - * a bus reset happens, so driver need to reenable this after - * bus reset. Returns 0 on success, -ENODEV if the card - * doesn't support this, -ESTALE if the generation doesn't - * match. - */ - int (*enable_phys_dma)(struct fw_card *card, - int node_id, int generation); - - u64 (*get_bus_time)(struct fw_card *card); - - struct fw_iso_context * - (*allocate_iso_context)(struct fw_card *card, - int type, size_t header_size); - void (*free_iso_context)(struct fw_iso_context *ctx); - - int (*start_iso)(struct fw_iso_context *ctx, - s32 cycle, u32 sync, u32 tags); - - int (*queue_iso)(struct fw_iso_context *ctx, - struct fw_iso_packet *packet, - struct fw_iso_buffer *buffer, - unsigned long payload); - - int (*stop_iso)(struct fw_iso_context *ctx); -}; - -int -fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); - -void -fw_send_request(struct fw_card *card, struct fw_transaction *t, - int tcode, int node_id, int generation, int speed, - unsigned long long offset, - void *data, size_t length, - fw_transaction_callback_t callback, void *callback_data); - -int fw_cancel_transaction(struct fw_card *card, - struct fw_transaction *transaction); - -void fw_flush_transactions(struct fw_card *card); - -void fw_send_phy_config(struct fw_card *card, - int node_id, int generation, int gap_count); - -/* - * Called by the topology code to inform the device code of node - * activity; found, lost, or updated nodes. - */ -void -fw_node_event(struct fw_card *card, struct fw_node *node, int event); - -/* API used by card level drivers */ - -void -fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, - struct device *device); -int -fw_card_add(struct fw_card *card, - u32 max_receive, u32 link_speed, u64 guid); - -void -fw_core_remove_card(struct fw_card *card); - -void -fw_core_handle_bus_reset(struct fw_card *card, - int node_id, int generation, - int self_id_count, u32 *self_ids); -void -fw_core_handle_request(struct fw_card *card, struct fw_packet *request); - -void -fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); - -#endif /* __fw_transaction_h */ diff --git a/trunk/drivers/hwmon/Kconfig b/trunk/drivers/hwmon/Kconfig index 4d1cb5b855d1..3ba3a5221c41 100644 --- a/trunk/drivers/hwmon/Kconfig +++ b/trunk/drivers/hwmon/Kconfig @@ -4,7 +4,6 @@ menuconfig HWMON tristate "Hardware Monitoring support" - depends on HAS_IOMEM default y help Hardware monitoring devices let you monitor the hardware health diff --git a/trunk/drivers/hwmon/ams/ams-input.c b/trunk/drivers/hwmon/ams/ams-input.c index ca7095d96ad0..18210164e307 100644 --- a/trunk/drivers/hwmon/ams/ams-input.c +++ b/trunk/drivers/hwmon/ams/ams-input.c @@ -87,7 +87,7 @@ static void ams_input_enable(void) ams_info.idev->id.vendor = 0; ams_info.idev->open = ams_input_open; ams_info.idev->close = ams_input_close; - ams_info.idev->dev.parent = &ams_info.of_dev->dev; + ams_info.idev->cdev.dev = &ams_info.of_dev->dev; input_set_abs_params(ams_info.idev, ABS_X, -50, 50, 3, 0); input_set_abs_params(ams_info.idev, ABS_Y, -50, 50, 3, 0); diff --git a/trunk/drivers/hwmon/applesmc.c b/trunk/drivers/hwmon/applesmc.c index 0c160675b3ac..b51c104a28a2 100644 --- a/trunk/drivers/hwmon/applesmc.c +++ b/trunk/drivers/hwmon/applesmc.c @@ -1100,7 +1100,7 @@ static int applesmc_create_accelerometer(void) /* initialize the input class */ applesmc_idev->name = "applesmc"; applesmc_idev->id.bustype = BUS_HOST; - applesmc_idev->dev.parent = &pdev->dev; + applesmc_idev->cdev.dev = &pdev->dev; applesmc_idev->evbit[0] = BIT(EV_ABS); applesmc_idev->open = applesmc_idev_open; applesmc_idev->close = applesmc_idev_close; diff --git a/trunk/drivers/hwmon/coretemp.c b/trunk/drivers/hwmon/coretemp.c index 75e3911810a3..03b1f650d1c4 100644 --- a/trunk/drivers/hwmon/coretemp.c +++ b/trunk/drivers/hwmon/coretemp.c @@ -309,11 +309,9 @@ static int coretemp_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: coretemp_device_add(cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: coretemp_device_remove(cpu); break; } diff --git a/trunk/drivers/hwmon/hdaps.c b/trunk/drivers/hwmon/hdaps.c index e0cf5e6fe5bc..f82fa2d23f95 100644 --- a/trunk/drivers/hwmon/hdaps.c +++ b/trunk/drivers/hwmon/hdaps.c @@ -574,7 +574,7 @@ static int __init hdaps_init(void) /* initialize the input class */ hdaps_idev->name = "hdaps"; - hdaps_idev->dev.parent = &pdev->dev; + hdaps_idev->cdev.dev = &pdev->dev; hdaps_idev->evbit[0] = BIT(EV_ABS); input_set_abs_params(hdaps_idev, ABS_X, -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT); diff --git a/trunk/drivers/i2c/Kconfig b/trunk/drivers/i2c/Kconfig index 96867347bcbf..434a61b415a3 100644 --- a/trunk/drivers/i2c/Kconfig +++ b/trunk/drivers/i2c/Kconfig @@ -4,7 +4,6 @@ menuconfig I2C tristate "I2C support" - depends on HAS_IOMEM ---help--- I2C (pronounce: I-square-C) is a slow serial bus protocol used in many micro controller applications and developed by Philips. SMBus, diff --git a/trunk/drivers/i2c/busses/i2c-at91.c b/trunk/drivers/i2c/busses/i2c-at91.c index 9c8b6d5eaec9..f35156c58922 100644 --- a/trunk/drivers/i2c/busses/i2c-at91.c +++ b/trunk/drivers/i2c/busses/i2c-at91.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -227,14 +226,13 @@ static int __devinit at91_i2c_probe(struct platform_device *pdev) adapter->algo = &at91_algorithm; adapter->class = I2C_CLASS_HWMON; adapter->dev.parent = &pdev->dev; - /* adapter->id == 0 ... only one TWI controller for now */ platform_set_drvdata(pdev, adapter); clk_enable(twi_clk); /* enable peripheral clock */ at91_twi_hwinit(); /* initialize TWI controller */ - rc = i2c_add_numbered_adapter(adapter); + rc = i2c_add_adapter(adapter); if (rc) { dev_err(&pdev->dev, "Adapter %s registration failed\n", adapter->name); @@ -297,9 +295,6 @@ static int at91_i2c_resume(struct platform_device *pdev) #define at91_i2c_resume NULL #endif -/* work with "modprobe at91_i2c" from hotplugging or coldplugging */ -MODULE_ALIAS("at91_i2c"); - static struct platform_driver at91_i2c_driver = { .probe = at91_i2c_probe, .remove = __devexit_p(at91_i2c_remove), diff --git a/trunk/drivers/i2c/busses/i2c-pxa.c b/trunk/drivers/i2c/busses/i2c-pxa.c index 8a0a99b93641..873544ab598e 100644 --- a/trunk/drivers/i2c/busses/i2c-pxa.c +++ b/trunk/drivers/i2c/busses/i2c-pxa.c @@ -548,7 +548,7 @@ static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c) */ icr = readl(_ICR(i2c)); icr &= ~(ICR_STOP | ICR_ACKNAK); - writel(icr, _ICR(i2c)); + writel(icr, _IRC(i2c)); } /* diff --git a/trunk/drivers/i2c/chips/tps65010.c b/trunk/drivers/i2c/chips/tps65010.c index 3c3f2ebf3fc9..7ed92dc3d833 100644 --- a/trunk/drivers/i2c/chips/tps65010.c +++ b/trunk/drivers/i2c/chips/tps65010.c @@ -354,7 +354,7 @@ static void tps65010_interrupt(struct tps65010 *tps) * also needs to get error handling and probably * an #ifdef CONFIG_SOFTWARE_SUSPEND */ - hibernate(); + pm_suspend(PM_SUSPEND_DISK); #endif poll = 1; } diff --git a/trunk/drivers/ide/Kconfig b/trunk/drivers/ide/Kconfig index 9040809d2c25..5bdf64b77913 100644 --- a/trunk/drivers/ide/Kconfig +++ b/trunk/drivers/ide/Kconfig @@ -7,7 +7,6 @@ if BLOCK menu "ATA/ATAPI/MFM/RLL support" - depends on HAS_IOMEM config IDE tristate "ATA/ATAPI/MFM/RLL support" @@ -292,17 +291,6 @@ config IDE_TASK_IOCTL If you are unsure, say N here. -config IDE_PROC_FS - bool "legacy /proc/ide/ support" - depends on IDE && PROC_FS - default y - help - This option enables support for the various files in - /proc/ide. In Linux 2.6 this has been superseded by - files in sysfs but many legacy applications rely on this. - - If unsure say Y. - comment "IDE chipset support/bugfixes" config IDE_GENERIC @@ -372,9 +360,6 @@ config IDEPCI_SHARE_IRQ It is safe to say Y to this question, in most cases. If unsure, say N. -config IDEPCI_PCIBUS_ORDER - def_bool PCI && BLK_DEV_IDE=y && BLK_DEV_IDEPCI - config BLK_DEV_OFFBOARD bool "Boot off-board chipsets first support" depends on PCI && BLK_DEV_IDEPCI diff --git a/trunk/drivers/ide/Makefile b/trunk/drivers/ide/Makefile index 75dc6969e0a7..d9f029e8ff74 100644 --- a/trunk/drivers/ide/Makefile +++ b/trunk/drivers/ide/Makefile @@ -20,7 +20,7 @@ ide-core-$(CONFIG_BLK_DEV_CMD640) += pci/cmd640.o # Core IDE code - must come before legacy ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o -ide-core-$(CONFIG_IDE_PROC_FS) += ide-proc.o +ide-core-$(CONFIG_PROC_FS) += ide-proc.o ide-core-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o diff --git a/trunk/drivers/ide/arm/bast-ide.c b/trunk/drivers/ide/arm/bast-ide.c index f7449d04114a..9d474e5fd8dc 100644 --- a/trunk/drivers/ide/arm/bast-ide.c +++ b/trunk/drivers/ide/arm/bast-ide.c @@ -45,7 +45,7 @@ bastide_register(unsigned int base, unsigned int aux, int irq, hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20); hw.irq = irq; - ide_register_hw(&hw, 0, hwif); + ide_register_hw(&hw, hwif); return 0; } diff --git a/trunk/drivers/ide/arm/icside.c b/trunk/drivers/ide/arm/icside.c index 1fe0457243db..e2953fc1fafb 100644 --- a/trunk/drivers/ide/arm/icside.c +++ b/trunk/drivers/ide/arm/icside.c @@ -342,7 +342,7 @@ static int icside_dma_check(ide_drive_t *drive) * Enable DMA on any drive that has multiword DMA */ if (id->field_valid & 2) { - xfer_mode = ide_max_dma_mode(drive); + xfer_mode = ide_dma_speed(drive, 0); goto out; } @@ -591,8 +591,7 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec) state->hwif[0] = hwif; probe_hwif_init(hwif); - - ide_proc_register_port(hwif); + create_proc_ide_interfaces(); return 0; } @@ -680,9 +679,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) probe_hwif_init(hwif); probe_hwif_init(mate); - - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + create_proc_ide_interfaces(); return 0; diff --git a/trunk/drivers/ide/arm/ide_arm.c b/trunk/drivers/ide/arm/ide_arm.c index a3d6744e870a..23488c4d1fcd 100644 --- a/trunk/drivers/ide/arm/ide_arm.c +++ b/trunk/drivers/ide/arm/ide_arm.c @@ -38,6 +38,6 @@ void __init ide_arm_init(void) memset(&hw, 0, sizeof(hw)); ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206); hw.irq = IDE_ARM_IRQ; - ide_register_hw(&hw, 1, NULL); + ide_register_hw(&hw, NULL); } } diff --git a/trunk/drivers/ide/arm/rapide.c b/trunk/drivers/ide/arm/rapide.c index 890ea3fac3c6..9c6c49fdd2b1 100644 --- a/trunk/drivers/ide/arm/rapide.c +++ b/trunk/drivers/ide/arm/rapide.c @@ -76,7 +76,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id) hwif->gendev.parent = &ec->dev; hwif->noprobe = 0; probe_hwif_init(hwif); - ide_proc_register_port(hwif); + create_proc_ide_interfaces(); ecard_set_drvdata(ec, hwif); goto out; } diff --git a/trunk/drivers/ide/cris/ide-cris.c b/trunk/drivers/ide/cris/ide-cris.c index c04cb25a01ff..5e8efc89255a 100644 --- a/trunk/drivers/ide/cris/ide-cris.c +++ b/trunk/drivers/ide/cris/ide-cris.c @@ -796,7 +796,7 @@ init_e100_ide (void) ide_offsets, 0, 0, cris_ide_ack_intr, ide_default_irq(0)); - ide_register_hw(&hw, 1, &hwif); + ide_register_hw(&hw, &hwif); hwif->mmio = 1; hwif->chipset = ide_etrax100; hwif->tuneproc = &tune_cris_ide; @@ -1004,7 +1004,7 @@ static int cris_ide_build_dmatable (ide_drive_t *drive) static int cris_config_drive_for_dma (ide_drive_t *drive) { - u8 speed = ide_max_dma_mode(drive); + u8 speed = ide_dma_speed(drive, 1); if (!speed) return 0; diff --git a/trunk/drivers/ide/h8300/ide-h8300.c b/trunk/drivers/ide/h8300/ide-h8300.c index 6d26ad7360d5..88750a300337 100644 --- a/trunk/drivers/ide/h8300/ide-h8300.c +++ b/trunk/drivers/ide/h8300/ide-h8300.c @@ -101,7 +101,7 @@ void __init h8300_ide_init(void) hw_setup(&hw); /* register if */ - idx = ide_register_hw(&hw, 1, &hwif); + idx = ide_register_hw(&hw, &hwif); if (idx == -1) { printk(KERN_ERR "ide-h8300: IDE I/F register failed\n"); return; diff --git a/trunk/drivers/ide/ide-cd.c b/trunk/drivers/ide/ide-cd.c index 252ab8295edf..638becda81c6 100644 --- a/trunk/drivers/ide/ide-cd.c +++ b/trunk/drivers/ide/ide-cd.c @@ -3059,14 +3059,10 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) return nslots; } -#ifdef CONFIG_IDE_PROC_FS static void ide_cdrom_add_settings(ide_drive_t *drive) { - ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); + ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); } -#else -static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; } -#endif /* * standard prep_rq_fn that builds 10 byte cmds @@ -3278,7 +3274,7 @@ int ide_cdrom_setup (ide_drive_t *drive) return 0; } -#ifdef CONFIG_IDE_PROC_FS +#ifdef CONFIG_PROC_FS static sector_t ide_cdrom_capacity (ide_drive_t *drive) { @@ -3295,7 +3291,7 @@ static void ide_cd_remove(ide_drive_t *drive) { struct cdrom_info *info = drive->driver_data; - ide_proc_unregister_driver(drive, info->driver); + ide_unregister_subdriver(drive, info->driver); del_gendisk(info->disk); @@ -3325,7 +3321,7 @@ static void ide_cd_release(struct kref *kref) static int ide_cd_probe(ide_drive_t *); -#ifdef CONFIG_IDE_PROC_FS +#ifdef CONFIG_PROC_FS static int proc_idecd_read_capacity (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -3340,6 +3336,8 @@ static ide_proc_entry_t idecd_proc[] = { { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL }, { NULL, 0, NULL, NULL } }; +#else +# define idecd_proc NULL #endif static ide_driver_t ide_cdrom_driver = { @@ -3357,9 +3355,7 @@ static ide_driver_t ide_cdrom_driver = { .end_request = ide_end_request, .error = __ide_error, .abort = __ide_abort, -#ifdef CONFIG_IDE_PROC_FS .proc = idecd_proc, -#endif }; static int idecd_open(struct inode * inode, struct file * file) @@ -3521,7 +3517,7 @@ static int ide_cd_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_proc_register_driver(drive, &ide_cdrom_driver); + ide_register_subdriver(drive, &ide_cdrom_driver); kref_init(&info->kref); @@ -3538,7 +3534,7 @@ static int ide_cd_probe(ide_drive_t *drive) g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE; if (ide_cdrom_setup(drive)) { struct cdrom_device_info *devinfo = &info->devinfo; - ide_proc_unregister_driver(drive, &ide_cdrom_driver); + ide_unregister_subdriver(drive, &ide_cdrom_driver); kfree(info->buffer); kfree(info->toc); kfree(info->changer_info); diff --git a/trunk/drivers/ide/ide-disk.c b/trunk/drivers/ide/ide-disk.c index 7fff773f2df7..37aa6ddd9702 100644 --- a/trunk/drivers/ide/ide-disk.c +++ b/trunk/drivers/ide/ide-disk.c @@ -559,7 +559,8 @@ static sector_t idedisk_capacity (ide_drive_t *drive) return drive->capacity64 - drive->sect0; } -#ifdef CONFIG_IDE_PROC_FS +#ifdef CONFIG_PROC_FS + static int smart_enable(ide_drive_t *drive) { ide_task_t args; @@ -677,7 +678,12 @@ static ide_proc_entry_t idedisk_proc[] = { { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL }, { NULL, 0, NULL, NULL } }; -#endif /* CONFIG_IDE_PROC_FS */ + +#else + +#define idedisk_proc NULL + +#endif /* CONFIG_PROC_FS */ static void idedisk_prepare_flush(request_queue_t *q, struct request *rq) { @@ -731,9 +737,6 @@ static int set_multcount(ide_drive_t *drive, int arg) { struct request rq; - if (arg < 0 || arg > drive->id->max_multsect) - return -EINVAL; - if (drive->special.b.set_multmode) return -EBUSY; ide_init_drive_cmd (&rq); @@ -746,9 +749,6 @@ static int set_multcount(ide_drive_t *drive, int arg) static int set_nowerr(ide_drive_t *drive, int arg) { - if (arg < 0 || arg > 1) - return -EINVAL; - if (ide_spin_wait_hwgroup(drive)) return -EBUSY; drive->nowerr = arg; @@ -800,9 +800,6 @@ static int write_cache(ide_drive_t *drive, int arg) ide_task_t args; int err = 1; - if (arg < 0 || arg > 1) - return -EINVAL; - if (ide_id_has_flush_cache(drive->id)) { memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? @@ -838,9 +835,6 @@ static int set_acoustic (ide_drive_t *drive, int arg) { ide_task_t args; - if (arg < 0 || arg > 254) - return -EINVAL; - memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM; @@ -861,9 +855,6 @@ static int set_acoustic (ide_drive_t *drive, int arg) */ static int set_lba_addressing(ide_drive_t *drive, int arg) { - if (arg < 0 || arg > 2) - return -EINVAL; - drive->addressing = 0; if (HWIF(drive)->no_lba48) @@ -875,27 +866,23 @@ static int set_lba_addressing(ide_drive_t *drive, int arg) return 0; } -#ifdef CONFIG_IDE_PROC_FS static void idedisk_add_settings(ide_drive_t *drive) { struct hd_driveid *id = drive->id; - ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); - ide_add_setting(drive, "bswap", SETTING_READ, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL); - ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, id->max_multsect, 1, 1, &drive->mult_count, set_multcount); - ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); - ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL); - ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache); - ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic); - ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL); - ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); + ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); + ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); + ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); + ide_add_setting(drive, "address", SETTING_RW, HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, TYPE_INTA, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); + ide_add_setting(drive, "bswap", SETTING_READ, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL); + ide_add_setting(drive, "multcount", id ? SETTING_RW : SETTING_READ, HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, TYPE_BYTE, 0, id ? id->max_multsect : 0, 1, 1, &drive->mult_count, set_multcount); + ide_add_setting(drive, "nowerr", SETTING_RW, HDIO_GET_NOWERR, HDIO_SET_NOWERR, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); + ide_add_setting(drive, "lun", SETTING_RW, -1, -1, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL); + ide_add_setting(drive, "wcache", SETTING_RW, HDIO_GET_WCACHE, HDIO_SET_WCACHE, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache); + ide_add_setting(drive, "acoustic", SETTING_RW, HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic); + ide_add_setting(drive, "failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL); + ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); } -#else -static inline void idedisk_add_settings(ide_drive_t *drive) { ; } -#endif static void idedisk_setup (ide_drive_t *drive) { @@ -1014,7 +1001,7 @@ static void ide_disk_remove(ide_drive_t *drive) struct ide_disk_obj *idkp = drive->driver_data; struct gendisk *g = idkp->disk; - ide_proc_unregister_driver(drive, idkp->driver); + ide_unregister_subdriver(drive, idkp->driver); del_gendisk(g); @@ -1079,9 +1066,7 @@ static ide_driver_t idedisk_driver = { .end_request = ide_end_request, .error = __ide_error, .abort = __ide_abort, -#ifdef CONFIG_IDE_PROC_FS .proc = idedisk_proc, -#endif }; static int idedisk_open(struct inode *inode, struct file *filp) @@ -1155,49 +1140,9 @@ static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo) static int idedisk_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - unsigned long flags; struct block_device *bdev = inode->i_bdev; struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); - ide_drive_t *drive = idkp->drive; - int err, (*setfunc)(ide_drive_t *, int); - u8 *val; - - switch (cmd) { - case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val; - case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val; - case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val; - case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val; - case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val; - case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val; - case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val; - case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val; - case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val; - case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val; - } - - return generic_ide_ioctl(drive, file, bdev, cmd, arg); - -read_val: - down(&ide_setting_sem); - spin_lock_irqsave(&ide_lock, flags); - err = *val; - spin_unlock_irqrestore(&ide_lock, flags); - up(&ide_setting_sem); - return err >= 0 ? put_user(err, (long __user *)arg) : err; - -set_val: - if (bdev != bdev->bd_contains) - err = -EINVAL; - else { - if (!capable(CAP_SYS_ADMIN)) - err = -EACCES; - else { - down(&ide_setting_sem); - err = setfunc(drive, arg); - up(&ide_setting_sem); - } - } - return err; + return generic_ide_ioctl(idkp->drive, file, bdev, cmd, arg); } static int idedisk_media_changed(struct gendisk *disk) @@ -1257,7 +1202,7 @@ static int ide_disk_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_proc_register_driver(drive, &idedisk_driver); + ide_register_subdriver(drive, &idedisk_driver); kref_init(&idkp->kref); diff --git a/trunk/drivers/ide/ide-dma.c b/trunk/drivers/ide/ide-dma.c index 5fe85191d49c..fd213088b06b 100644 --- a/trunk/drivers/ide/ide-dma.c +++ b/trunk/drivers/ide/ide-dma.c @@ -705,100 +705,6 @@ int ide_use_dma(ide_drive_t *drive) EXPORT_SYMBOL_GPL(ide_use_dma); -static const u8 xfer_mode_bases[] = { - XFER_UDMA_0, - XFER_MW_DMA_0, - XFER_SW_DMA_0, -}; - -static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = drive->hwif; - unsigned int mask = 0; - - switch(base) { - case XFER_UDMA_0: - if ((id->field_valid & 4) == 0) - break; - - mask = id->dma_ultra & hwif->ultra_mask; - - if (hwif->udma_filter) - mask &= hwif->udma_filter(drive); - - if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) - mask &= 0x07; - break; - case XFER_MW_DMA_0: - mask = id->dma_mword & hwif->mwdma_mask; - break; - case XFER_SW_DMA_0: - mask = id->dma_1word & hwif->swdma_mask; - break; - default: - BUG(); - break; - } - - return mask; -} - -/** - * ide_max_dma_mode - compute DMA speed - * @drive: IDE device - * - * Checks the drive capabilities and returns the speed to use - * for the DMA transfer. Returns 0 if the drive is incapable - * of DMA transfers. - */ - -u8 ide_max_dma_mode(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - unsigned int mask; - int x, i; - u8 mode = 0; - - if (drive->media != ide_disk && hwif->atapi_dma == 0) - return 0; - - for (i = 0; i < ARRAY_SIZE(xfer_mode_bases); i++) { - mask = ide_get_mode_mask(drive, xfer_mode_bases[i]); - x = fls(mask) - 1; - if (x >= 0) { - mode = xfer_mode_bases[i] + x; - break; - } - } - - printk(KERN_DEBUG "%s: selected mode 0x%x\n", drive->name, mode); - - return mode; -} - -EXPORT_SYMBOL_GPL(ide_max_dma_mode); - -int ide_tune_dma(ide_drive_t *drive) -{ - u8 speed; - - /* TODO: use only ide_max_dma_mode() */ - if (!ide_use_dma(drive)) - return 0; - - speed = ide_max_dma_mode(drive); - - if (!speed) - return 0; - - drive->hwif->speedproc(drive, speed); - - return ide_dma_enable(drive); -} - -EXPORT_SYMBOL_GPL(ide_tune_dma); - void ide_dma_verbose(ide_drive_t *drive) { struct hd_driveid *id = drive->id; diff --git a/trunk/drivers/ide/ide-floppy.c b/trunk/drivers/ide/ide-floppy.c index f429be88c4f9..57cd21c5b2c1 100644 --- a/trunk/drivers/ide/ide-floppy.c +++ b/trunk/drivers/ide/ide-floppy.c @@ -1811,22 +1811,18 @@ static int idefloppy_identify_device (ide_drive_t *drive,struct hd_driveid *id) return 0; } -#ifdef CONFIG_IDE_PROC_FS static void idefloppy_add_settings(ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; /* - * drive setting name read/write data type min max mul_factor div_factor data pointer set function + * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function */ - ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL); + ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); + ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); + ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); + ide_add_setting(drive, "ticks", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL); } -#else -static inline void idefloppy_add_settings(ide_drive_t *drive) { ; } -#endif /* * Driver initialization. @@ -1877,7 +1873,7 @@ static void ide_floppy_remove(ide_drive_t *drive) idefloppy_floppy_t *floppy = drive->driver_data; struct gendisk *g = floppy->disk; - ide_proc_unregister_driver(drive, floppy->driver); + ide_unregister_subdriver(drive, floppy->driver); del_gendisk(g); @@ -1896,7 +1892,8 @@ static void ide_floppy_release(struct kref *kref) kfree(floppy); } -#ifdef CONFIG_IDE_PROC_FS +#ifdef CONFIG_PROC_FS + static int proc_idefloppy_read_capacity (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -1912,7 +1909,12 @@ static ide_proc_entry_t idefloppy_proc[] = { { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, { NULL, 0, NULL, NULL } }; -#endif /* CONFIG_IDE_PROC_FS */ + +#else + +#define idefloppy_proc NULL + +#endif /* CONFIG_PROC_FS */ static int ide_floppy_probe(ide_drive_t *); @@ -1931,9 +1933,7 @@ static ide_driver_t idefloppy_driver = { .end_request = idefloppy_do_end_request, .error = __ide_error, .abort = __ide_abort, -#ifdef CONFIG_IDE_PROC_FS .proc = idefloppy_proc, -#endif }; static int idefloppy_open(struct inode *inode, struct file *filp) @@ -2159,7 +2159,7 @@ static int ide_floppy_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_proc_register_driver(drive, &idefloppy_driver); + ide_register_subdriver(drive, &idefloppy_driver); kref_init(&floppy->kref); diff --git a/trunk/drivers/ide/ide-generic.c b/trunk/drivers/ide/ide-generic.c index 0f72b98d727f..99fd56151131 100644 --- a/trunk/drivers/ide/ide-generic.c +++ b/trunk/drivers/ide/ide-generic.c @@ -22,6 +22,8 @@ static int __init ide_generic_init(void) if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) ide_release_lock(); /* for atari only */ + create_proc_ide_interfaces(); + return 0; } diff --git a/trunk/drivers/ide/ide-io.c b/trunk/drivers/ide/ide-io.c index 8e568143d90d..8670112f1d39 100644 --- a/trunk/drivers/ide/ide-io.c +++ b/trunk/drivers/ide/ide-io.c @@ -172,6 +172,15 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * memset(args, 0, sizeof(*args)); + if (drive->media != ide_disk) { + /* + * skip idedisk_pm_restore_pio and idedisk_pm_idle for ATAPI + * devices + */ + if (pm->pm_step == idedisk_pm_restore_pio) + pm->pm_step = ide_pm_restore_dma; + } + switch (pm->pm_step) { case ide_pm_flush_cache: /* Suspend step 1 (flush cache) */ if (drive->media != ide_disk) @@ -198,13 +207,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */ if (drive->hwif->tuneproc != NULL) drive->hwif->tuneproc(drive, 255); - /* - * skip idedisk_pm_idle for ATAPI devices - */ - if (drive->media != ide_disk) - pm->pm_step = ide_pm_restore_dma; - else - ide_complete_power_step(drive, rq, 0, 0); + ide_complete_power_step(drive, rq, 0, 0); return ide_stopped; case idedisk_pm_idle: /* Resume step 2 (idle) */ diff --git a/trunk/drivers/ide/ide-iops.c b/trunk/drivers/ide/ide-iops.c index f0be5f665a0e..3caa176b3155 100644 --- a/trunk/drivers/ide/ide-iops.c +++ b/trunk/drivers/ide/ide-iops.c @@ -571,54 +571,51 @@ EXPORT_SYMBOL(ide_wait_stat); */ u8 eighty_ninty_three (ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; - struct hd_driveid *id = drive->id; - - if (hwif->udma_four == 0) - goto no_80w; + if(HWIF(drive)->udma_four == 0) + return 0; /* Check for SATA but only if we are ATA5 or higher */ - if (id->hw_config == 0 && (id->major_rev_num & 0x7FE0)) + if (drive->id->hw_config == 0 && (drive->id->major_rev_num & 0x7FE0)) return 1; - + if (!(drive->id->hw_config & 0x6000)) + return 0; +#ifndef CONFIG_IDEDMA_IVB + if(!(drive->id->hw_config & 0x4000)) + return 0; +#endif /* CONFIG_IDEDMA_IVB */ /* * FIXME: * - change master/slave IDENTIFY order * - force bit13 (80c cable present) check * (unless the slave device is pre-ATA3) */ -#ifndef CONFIG_IDEDMA_IVB - if (id->hw_config & 0x4000) -#else - if (id->hw_config & 0x6000) -#endif - return 1; - -no_80w: - if (drive->udma33_warned == 1) - return 0; - - printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, " - "limiting max speed to UDMA33\n", - drive->name, hwif->udma_four ? "drive" : "host"); - - drive->udma33_warned = 1; - - return 0; + return 1; } +EXPORT_SYMBOL(eighty_ninty_three); + int ide_ata66_check (ide_drive_t *drive, ide_task_t *args) { if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) && (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) { - if (eighty_ninty_three(drive) == 0) { - printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot " - "be set\n", drive->name); +#ifndef CONFIG_IDEDMA_IVB + if ((drive->id->hw_config & 0x6000) == 0) { +#else /* !CONFIG_IDEDMA_IVB */ + if (((drive->id->hw_config & 0x2000) == 0) || + ((drive->id->hw_config & 0x4000) == 0)) { +#endif /* CONFIG_IDEDMA_IVB */ + printk("%s: Speed warnings UDMA 3/4/5 is not " + "functional.\n", drive->name); + return 1; + } + if (!HWIF(drive)->udma_four) { + printk("%s: Speed warnings UDMA 3/4/5 is not " + "functional.\n", + HWIF(drive)->name); return 1; } } - return 0; } diff --git a/trunk/drivers/ide/ide-lib.c b/trunk/drivers/ide/ide-lib.c index 3be3c69383f2..68719314df3f 100644 --- a/trunk/drivers/ide/ide-lib.c +++ b/trunk/drivers/ide/ide-lib.c @@ -69,41 +69,123 @@ char *ide_xfer_verbose (u8 xfer_rate) EXPORT_SYMBOL(ide_xfer_verbose); /** - * ide_rate_filter - filter transfer mode - * @drive: IDE device + * ide_dma_speed - compute DMA speed + * @drive: drive + * @mode: modes available + * + * Checks the drive capabilities and returns the speed to use + * for the DMA transfer. Returns 0 if the drive is incapable + * of DMA transfers. + */ + +u8 ide_dma_speed(ide_drive_t *drive, u8 mode) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + u8 ultra_mask, mwdma_mask, swdma_mask; + u8 speed = 0; + + if (drive->media != ide_disk && hwif->atapi_dma == 0) + return 0; + + /* Capable of UltraDMA modes? */ + ultra_mask = id->dma_ultra & hwif->ultra_mask; + + if (!(id->field_valid & 4)) + mode = 0; /* fallback to MW/SW DMA if no UltraDMA */ + + switch (mode) { + case 4: + if (ultra_mask & 0x40) { + speed = XFER_UDMA_6; + break; + } + case 3: + if (ultra_mask & 0x20) { + speed = XFER_UDMA_5; + break; + } + case 2: + if (ultra_mask & 0x10) { + speed = XFER_UDMA_4; + break; + } + if (ultra_mask & 0x08) { + speed = XFER_UDMA_3; + break; + } + case 1: + if (ultra_mask & 0x04) { + speed = XFER_UDMA_2; + break; + } + if (ultra_mask & 0x02) { + speed = XFER_UDMA_1; + break; + } + if (ultra_mask & 0x01) { + speed = XFER_UDMA_0; + break; + } + case 0: + mwdma_mask = id->dma_mword & hwif->mwdma_mask; + + if (mwdma_mask & 0x04) { + speed = XFER_MW_DMA_2; + break; + } + if (mwdma_mask & 0x02) { + speed = XFER_MW_DMA_1; + break; + } + if (mwdma_mask & 0x01) { + speed = XFER_MW_DMA_0; + break; + } + + swdma_mask = id->dma_1word & hwif->swdma_mask; + + if (swdma_mask & 0x04) { + speed = XFER_SW_DMA_2; + break; + } + if (swdma_mask & 0x02) { + speed = XFER_SW_DMA_1; + break; + } + if (swdma_mask & 0x01) { + speed = XFER_SW_DMA_0; + break; + } + } + + return speed; +} +EXPORT_SYMBOL(ide_dma_speed); + + +/** + * ide_rate_filter - return best speed for mode + * @mode: modes available * @speed: desired speed * - * Given the available transfer modes this function returns + * Given the available DMA/UDMA mode this function returns * the best available speed at or below the speed requested. - * - * FIXME: filter also PIO/SWDMA/MWDMA modes */ -u8 ide_rate_filter(ide_drive_t *drive, u8 speed) +u8 ide_rate_filter (u8 mode, u8 speed) { #ifdef CONFIG_BLK_DEV_IDEDMA - ide_hwif_t *hwif = drive->hwif; - u8 mask = hwif->ultra_mask, mode = XFER_MW_DMA_2; - - if (hwif->udma_filter) - mask = hwif->udma_filter(drive); - - /* - * TODO: speed > XFER_UDMA_2 extra check is needed to avoid false - * cable warning from eighty_ninty_three(), moving ide_rate_filter() - * calls from ->speedproc to core code will make this hack go away - */ - if (speed > XFER_UDMA_2) { - if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) - mask &= 0x07; - } - - if (mask) - mode = fls(mask) - 1 + XFER_UDMA_0; + static u8 speed_max[] = { + XFER_MW_DMA_2, XFER_UDMA_2, XFER_UDMA_4, + XFER_UDMA_5, XFER_UDMA_6 + }; // printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); - return min(speed, mode); + /* So that we remember to update this if new modes appear */ + BUG_ON(mode > 4); + return min(speed, speed_max[mode]); #else /* !CONFIG_BLK_DEV_IDEDMA */ return min(speed, (u8)XFER_PIO_4); #endif /* CONFIG_BLK_DEV_IDEDMA */ diff --git a/trunk/drivers/ide/ide-pnp.c b/trunk/drivers/ide/ide-pnp.c index 2b8009c50e91..98410ca044cf 100644 --- a/trunk/drivers/ide/ide-pnp.c +++ b/trunk/drivers/ide/ide-pnp.c @@ -42,7 +42,7 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id hw.irq = pnp_irq(dev, 0); hw.dma = NO_DMA; - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, &hwif); if (index != -1) { printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index); diff --git a/trunk/drivers/ide/ide-probe.c b/trunk/drivers/ide/ide-probe.c index 3cebed77f55d..8f15c23aa70d 100644 --- a/trunk/drivers/ide/ide-probe.c +++ b/trunk/drivers/ide/ide-probe.c @@ -1427,9 +1427,6 @@ int ideprobe_init (void) } } } - for (index = 0; index < MAX_HWIFS; ++index) - if (probe[index]) - ide_proc_register_port(&ide_hwifs[index]); return 0; } diff --git a/trunk/drivers/ide/ide-proc.c b/trunk/drivers/ide/ide-proc.c index d50bd996ff22..a9e0b30fb1f2 100644 --- a/trunk/drivers/ide/ide-proc.c +++ b/trunk/drivers/ide/ide-proc.c @@ -3,8 +3,6 @@ * * Copyright (C) 1997-1998 Mark Lord * Copyright (C) 2003 Red Hat - * - * Some code was moved here from ide.c, see it for original copyrights. */ /* @@ -39,8 +37,6 @@ #include -static struct proc_dir_entry *proc_ide_root; - static int proc_ide_read_imodel (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -125,265 +121,6 @@ static int proc_ide_read_identify PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } -/** - * __ide_add_setting - add an ide setting option - * @drive: drive to use - * @name: setting name - * @rw: true if the function is read write - * @data_type: type of data - * @min: range minimum - * @max: range maximum - * @mul_factor: multiplication scale - * @div_factor: divison scale - * @data: private data field - * @set: setting - * @auto_remove: setting auto removal flag - * - * Removes the setting named from the device if it is present. - * The function takes the settings_lock to protect against - * parallel changes. This function must not be called from IRQ - * context. Returns 0 on success or -1 on failure. - * - * BUGS: This code is seriously over-engineered. There is also - * magic about how the driver specific features are setup. If - * a driver is attached we assume the driver settings are auto - * remove. - */ - -static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove) -{ - ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; - - down(&ide_setting_sem); - while ((*p) && strcmp((*p)->name, name) < 0) - p = &((*p)->next); - if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL) - goto abort; - if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL) - goto abort; - strcpy(setting->name, name); - setting->rw = rw; - setting->data_type = data_type; - setting->min = min; - setting->max = max; - setting->mul_factor = mul_factor; - setting->div_factor = div_factor; - setting->data = data; - setting->set = set; - - setting->next = *p; - if (auto_remove) - setting->auto_remove = 1; - *p = setting; - up(&ide_setting_sem); - return 0; -abort: - up(&ide_setting_sem); - kfree(setting); - return -1; -} - -int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) -{ - return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1); -} - -EXPORT_SYMBOL(ide_add_setting); - -/** - * __ide_remove_setting - remove an ide setting option - * @drive: drive to use - * @name: setting name - * - * Removes the setting named from the device if it is present. - * The caller must hold the setting semaphore. - */ - -static void __ide_remove_setting (ide_drive_t *drive, char *name) -{ - ide_settings_t **p, *setting; - - p = (ide_settings_t **) &drive->settings; - - while ((*p) && strcmp((*p)->name, name)) - p = &((*p)->next); - if ((setting = (*p)) == NULL) - return; - - (*p) = setting->next; - - kfree(setting->name); - kfree(setting); -} - -/** - * auto_remove_settings - remove driver specific settings - * @drive: drive - * - * Automatically remove all the driver specific settings for this - * drive. This function may not be called from IRQ context. The - * caller must hold ide_setting_sem. - */ - -static void auto_remove_settings (ide_drive_t *drive) -{ - ide_settings_t *setting; -repeat: - setting = drive->settings; - while (setting) { - if (setting->auto_remove) { - __ide_remove_setting(drive, setting->name); - goto repeat; - } - setting = setting->next; - } -} - -/** - * ide_find_setting_by_name - find a drive specific setting - * @drive: drive to scan - * @name: setting name - * - * Scan's the device setting table for a matching entry and returns - * this or NULL if no entry is found. The caller must hold the - * setting semaphore - */ - -static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name) -{ - ide_settings_t *setting = drive->settings; - - while (setting) { - if (strcmp(setting->name, name) == 0) - break; - setting = setting->next; - } - return setting; -} - -/** - * ide_read_setting - read an IDE setting - * @drive: drive to read from - * @setting: drive setting - * - * Read a drive setting and return the value. The caller - * must hold the ide_setting_sem when making this call. - * - * BUGS: the data return and error are the same return value - * so an error -EINVAL and true return of the same value cannot - * be told apart - */ - -static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting) -{ - int val = -EINVAL; - unsigned long flags; - - if ((setting->rw & SETTING_READ)) { - spin_lock_irqsave(&ide_lock, flags); - switch(setting->data_type) { - case TYPE_BYTE: - val = *((u8 *) setting->data); - break; - case TYPE_SHORT: - val = *((u16 *) setting->data); - break; - case TYPE_INT: - val = *((u32 *) setting->data); - break; - } - spin_unlock_irqrestore(&ide_lock, flags); - } - return val; -} - -/** - * ide_write_setting - read an IDE setting - * @drive: drive to read from - * @setting: drive setting - * @val: value - * - * Write a drive setting if it is possible. The caller - * must hold the ide_setting_sem when making this call. - * - * BUGS: the data return and error are the same return value - * so an error -EINVAL and true return of the same value cannot - * be told apart - * - * FIXME: This should be changed to enqueue a special request - * to the driver to change settings, and then wait on a sema for completion. - * The current scheme of polling is kludgy, though safe enough. - */ - -static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val) -{ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - if (setting->set) - return setting->set(drive, val); - if (!(setting->rw & SETTING_WRITE)) - return -EPERM; - if (val < setting->min || val > setting->max) - return -EINVAL; - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - switch (setting->data_type) { - case TYPE_BYTE: - *((u8 *) setting->data) = val; - break; - case TYPE_SHORT: - *((u16 *) setting->data) = val; - break; - case TYPE_INT: - *((u32 *) setting->data) = val; - break; - } - spin_unlock_irq(&ide_lock); - return 0; -} - -static int set_xfer_rate (ide_drive_t *drive, int arg) -{ - int err; - - if (arg < 0 || arg > 70) - return -EINVAL; - - err = ide_wait_cmd(drive, - WIN_SETFEATURES, (u8) arg, - SETFEATURES_XFER, 0, NULL); - - if (!err && arg) { - ide_set_xfer_rate(drive, (u8) arg); - ide_driveid_update(drive); - } - return err; -} - -/** - * ide_add_generic_settings - generic ide settings - * @drive: drive being configured - * - * Add the generic parts of the system settings to the /proc files. - * The caller must not be holding the ide_setting_sem. - */ - -void ide_add_generic_settings (ide_drive_t *drive) -{ -/* - * drive setting name read/write access data type min max mul_factor div_factor data pointer set function - */ - __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); - __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); - __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); - __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); - __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); - __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); - __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); - __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); - __ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); -} - static void proc_ide_settings_warn(void) { static int warned = 0; @@ -662,7 +399,7 @@ static ide_proc_entry_t generic_drive_entries[] = { { NULL, 0, NULL, NULL } }; -static void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data) +void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data) { struct proc_dir_entry *ent; @@ -678,7 +415,7 @@ static void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p } } -static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p) +void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p) { if (!dir || !p) return; @@ -688,51 +425,6 @@ static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t } } -void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) -{ - ide_add_proc_entries(drive->proc, driver->proc, drive); -} - -EXPORT_SYMBOL(ide_proc_register_driver); - -/** - * ide_proc_unregister_driver - remove driver specific data - * @drive: drive - * @driver: driver - * - * Clean up the driver specific /proc files and IDE settings - * for a given drive. - * - * Takes ide_setting_sem and ide_lock. - * Caller must hold none of the locks. - */ - -void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) -{ - unsigned long flags; - - ide_remove_proc_entries(drive->proc, driver->proc); - - down(&ide_setting_sem); - spin_lock_irqsave(&ide_lock, flags); - /* - * ide_setting_sem protects the settings list - * ide_lock protects the use of settings - * - * so we need to hold both, ide_settings_sem because we want to - * modify the settings list, and ide_lock because we cannot take - * a setting out that is being used. - * - * OTOH both ide_{read,write}_setting are only ever used under - * ide_setting_sem. - */ - auto_remove_settings(drive); - spin_unlock_irqrestore(&ide_lock, flags); - up(&ide_setting_sem); -} - -EXPORT_SYMBOL(ide_proc_unregister_driver); - static void create_proc_ide_drives(ide_hwif_t *hwif) { int d; @@ -785,24 +477,26 @@ static ide_proc_entry_t hwif_entries[] = { { NULL, 0, NULL, NULL } }; -void ide_proc_register_port(ide_hwif_t *hwif) +void create_proc_ide_interfaces(void) { - if (!hwif->present) - return; - - if (!hwif->proc) { - hwif->proc = proc_mkdir(hwif->name, proc_ide_root); + int h; - if (!hwif->proc) - return; + for (h = 0; h < MAX_HWIFS; h++) { + ide_hwif_t *hwif = &ide_hwifs[h]; - ide_add_proc_entries(hwif->proc, hwif_entries, hwif); + if (!hwif->present) + continue; + if (!hwif->proc) { + hwif->proc = proc_mkdir(hwif->name, proc_ide_root); + if (!hwif->proc) + return; + ide_add_proc_entries(hwif->proc, hwif_entries, hwif); + } + create_proc_ide_drives(hwif); } - - create_proc_ide_drives(hwif); } -EXPORT_SYMBOL_GPL(ide_proc_register_port); +EXPORT_SYMBOL(create_proc_ide_interfaces); #ifdef CONFIG_BLK_DEV_IDEPCI void ide_pci_create_host_proc(const char *name, get_info_t *get_info) @@ -813,7 +507,7 @@ void ide_pci_create_host_proc(const char *name, get_info_t *get_info) EXPORT_SYMBOL_GPL(ide_pci_create_host_proc); #endif -void ide_proc_unregister_port(ide_hwif_t *hwif) +void destroy_proc_ide_interface(ide_hwif_t *hwif) { if (hwif->proc) { destroy_proc_ide_drives(hwif); @@ -860,11 +554,11 @@ void proc_ide_create(void) { struct proc_dir_entry *entry; - proc_ide_root = proc_mkdir("ide", NULL); - if (!proc_ide_root) return; + create_proc_ide_interfaces(); + entry = create_proc_entry("drivers", 0, proc_ide_root); if (entry) entry->proc_fops = &ide_drivers_operations; diff --git a/trunk/drivers/ide/ide-tape.c b/trunk/drivers/ide/ide-tape.c index e82bfa5e0ab8..4e59239fef75 100644 --- a/trunk/drivers/ide/ide-tape.c +++ b/trunk/drivers/ide/ide-tape.c @@ -4561,33 +4561,28 @@ static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive) printk(KERN_INFO "ide-tape: Adjusted block size - %d\n", tape->tape_block_size); #endif /* IDETAPE_DEBUG_INFO */ } - -#ifdef CONFIG_IDE_PROC_FS static void idetape_add_settings (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; /* - * drive setting name read/write data type min max mul_factor div_factor data pointer set function + * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function */ - ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL); - ide_add_setting(drive, "pipeline_min", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); - ide_add_setting(drive, "pipeline", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); - ide_add_setting(drive, "pipeline_max", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); - ide_add_setting(drive, "pipeline_used", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL); - ide_add_setting(drive, "pipeline_pending", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL); - ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL); - ide_add_setting(drive, "stage", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1024, &tape->stage_size, NULL); - ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_frequency, NULL); - ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); - ide_add_setting(drive, "pipeline_head_speed_c",SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed, NULL); - ide_add_setting(drive, "pipeline_head_speed_u",SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->uncontrolled_pipeline_head_speed,NULL); - ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); - ide_add_setting(drive, "debug_level", SETTING_RW, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); + ide_add_setting(drive, "buffer", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL); + ide_add_setting(drive, "pipeline_min", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); + ide_add_setting(drive, "pipeline", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); + ide_add_setting(drive, "pipeline_max", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); + ide_add_setting(drive, "pipeline_used",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL); + ide_add_setting(drive, "pipeline_pending",SETTING_READ,-1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL); + ide_add_setting(drive, "speed", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL); + ide_add_setting(drive, "stage", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1024, &tape->stage_size, NULL); + ide_add_setting(drive, "tdsc", SETTING_RW, -1, -1, TYPE_INT, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_frequency, NULL); + ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); + ide_add_setting(drive, "pipeline_head_speed_c",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed, NULL); + ide_add_setting(drive, "pipeline_head_speed_u",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->uncontrolled_pipeline_head_speed, NULL); + ide_add_setting(drive, "avg_speed", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); + ide_add_setting(drive, "debug_level",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); } -#else -static inline void idetape_add_settings(ide_drive_t *drive) { ; } -#endif /* * ide_setup is called to: @@ -4708,7 +4703,7 @@ static void ide_tape_remove(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - ide_proc_unregister_driver(drive, tape->driver); + ide_unregister_subdriver(drive, tape->driver); ide_unregister_region(tape->disk); @@ -4735,7 +4730,8 @@ static void ide_tape_release(struct kref *kref) kfree(tape); } -#ifdef CONFIG_IDE_PROC_FS +#ifdef CONFIG_PROC_FS + static int proc_idetape_read_name (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -4753,6 +4749,11 @@ static ide_proc_entry_t idetape_proc[] = { { "name", S_IFREG|S_IRUGO, proc_idetape_read_name, NULL }, { NULL, 0, NULL, NULL } }; + +#else + +#define idetape_proc NULL + #endif static int ide_tape_probe(ide_drive_t *); @@ -4772,9 +4773,7 @@ static ide_driver_t idetape_driver = { .end_request = idetape_end_request, .error = __ide_error, .abort = __ide_abort, -#ifdef CONFIG_IDE_PROC_FS .proc = idetape_proc, -#endif }; /* @@ -4865,7 +4864,7 @@ static int ide_tape_probe(ide_drive_t *drive) ide_init_disk(g, drive); - ide_proc_register_driver(drive, &idetape_driver); + ide_register_subdriver(drive, &idetape_driver); kref_init(&tape->kref); diff --git a/trunk/drivers/ide/ide.c b/trunk/drivers/ide/ide.c index f2b547ff7722..ae5bf2be6f52 100644 --- a/trunk/drivers/ide/ide.c +++ b/trunk/drivers/ide/ide.c @@ -168,11 +168,12 @@ static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, static int idebus_parameter; /* holds the "idebus=" parameter */ static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ +static int initializing; /* set while initializing built-in drivers */ DECLARE_MUTEX(ide_cfg_sem); __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock); -#ifdef CONFIG_IDEPCI_PCIBUS_ORDER +#ifdef CONFIG_BLK_DEV_IDEPCI static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ #endif @@ -215,6 +216,9 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index) hwif->bus_state = BUSSTATE_ON; hwif->atapi_dma = 0; /* disable all atapi dma */ + hwif->ultra_mask = 0x80; /* disable all ultra */ + hwif->mwdma_mask = 0x80; /* disable all mwdma */ + hwif->swdma_mask = 0x80; /* disable all swdma */ init_completion(&hwif->gendev_rel_comp); @@ -301,7 +305,9 @@ static void __init init_ide_data (void) #endif } #ifdef CONFIG_IDE_ARM + initializing = 1; ide_arm_init(); + initializing = 0; #endif } @@ -347,6 +353,10 @@ static int ide_system_bus_speed(void) return system_bus_speed; } +#ifdef CONFIG_PROC_FS +struct proc_dir_entry *proc_ide_root; +#endif + static struct resource* hwif_request_region(ide_hwif_t *hwif, unsigned long addr, int num) { @@ -470,7 +480,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) hwif->tuneproc = tmp_hwif->tuneproc; hwif->speedproc = tmp_hwif->speedproc; - hwif->udma_filter = tmp_hwif->udma_filter; hwif->selectproc = tmp_hwif->selectproc; hwif->reset_poll = tmp_hwif->reset_poll; hwif->pre_reset = tmp_hwif->pre_reset; @@ -590,7 +599,7 @@ void ide_unregister(unsigned int index) spin_unlock_irq(&ide_lock); - ide_proc_unregister_port(hwif); + destroy_proc_ide_interface(hwif); hwgroup = hwif->hwgroup; /* @@ -742,7 +751,6 @@ void ide_setup_ports ( hw_regs_t *hw, /** * ide_register_hw_with_fixup - register IDE interface * @hw: hardware registers - * @initializing: set while initializing built-in drivers * @hwifp: pointer to returned hwif * @fixup: fixup function * @@ -752,9 +760,7 @@ void ide_setup_ports ( hw_regs_t *hw, * Returns -1 on error. */ -int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing, - ide_hwif_t **hwifp, - void(*fixup)(ide_hwif_t *hwif)) +int ide_register_hw_with_fixup(hw_regs_t *hw, ide_hwif_t **hwifp, void(*fixup)(ide_hwif_t *hwif)) { int index, retry = 1; ide_hwif_t *hwif; @@ -795,7 +801,7 @@ int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing, if (!initializing) { probe_hwif_init_with_fixup(hwif, fixup); - ide_proc_register_port(hwif); + create_proc_ide_interfaces(); } if (hwifp) @@ -806,9 +812,9 @@ int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing, EXPORT_SYMBOL(ide_register_hw_with_fixup); -int ide_register_hw(hw_regs_t *hw, int initializing, ide_hwif_t **hwifp) +int ide_register_hw(hw_regs_t *hw, ide_hwif_t **hwifp) { - return ide_register_hw_with_fixup(hw, initializing, hwifp, NULL); + return ide_register_hw_with_fixup(hw, hwifp, NULL); } EXPORT_SYMBOL(ide_register_hw); @@ -819,7 +825,205 @@ EXPORT_SYMBOL(ide_register_hw); DECLARE_MUTEX(ide_setting_sem); -EXPORT_SYMBOL_GPL(ide_setting_sem); +/** + * __ide_add_setting - add an ide setting option + * @drive: drive to use + * @name: setting name + * @rw: true if the function is read write + * @read_ioctl: function to call on read + * @write_ioctl: function to call on write + * @data_type: type of data + * @min: range minimum + * @max: range maximum + * @mul_factor: multiplication scale + * @div_factor: divison scale + * @data: private data field + * @set: setting + * @auto_remove: setting auto removal flag + * + * Removes the setting named from the device if it is present. + * The function takes the settings_lock to protect against + * parallel changes. This function must not be called from IRQ + * context. Returns 0 on success or -1 on failure. + * + * BUGS: This code is seriously over-engineered. There is also + * magic about how the driver specific features are setup. If + * a driver is attached we assume the driver settings are auto + * remove. + */ + +static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove) +{ + ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; + + down(&ide_setting_sem); + while ((*p) && strcmp((*p)->name, name) < 0) + p = &((*p)->next); + if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL) + goto abort; + if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL) + goto abort; + strcpy(setting->name, name); + setting->rw = rw; + setting->read_ioctl = read_ioctl; + setting->write_ioctl = write_ioctl; + setting->data_type = data_type; + setting->min = min; + setting->max = max; + setting->mul_factor = mul_factor; + setting->div_factor = div_factor; + setting->data = data; + setting->set = set; + + setting->next = *p; + if (auto_remove) + setting->auto_remove = 1; + *p = setting; + up(&ide_setting_sem); + return 0; +abort: + up(&ide_setting_sem); + kfree(setting); + return -1; +} + +int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) +{ + return __ide_add_setting(drive, name, rw, read_ioctl, write_ioctl, data_type, min, max, mul_factor, div_factor, data, set, 1); +} + +EXPORT_SYMBOL(ide_add_setting); + +/** + * __ide_remove_setting - remove an ide setting option + * @drive: drive to use + * @name: setting name + * + * Removes the setting named from the device if it is present. + * The caller must hold the setting semaphore. + */ + +static void __ide_remove_setting (ide_drive_t *drive, char *name) +{ + ide_settings_t **p, *setting; + + p = (ide_settings_t **) &drive->settings; + + while ((*p) && strcmp((*p)->name, name)) + p = &((*p)->next); + if ((setting = (*p)) == NULL) + return; + + (*p) = setting->next; + + kfree(setting->name); + kfree(setting); +} + +/** + * ide_find_setting_by_ioctl - find a drive specific ioctl + * @drive: drive to scan + * @cmd: ioctl command to handle + * + * Scan's the device setting table for a matching entry and returns + * this or NULL if no entry is found. The caller must hold the + * setting semaphore + */ + +static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd) +{ + ide_settings_t *setting = drive->settings; + + while (setting) { + if (setting->read_ioctl == cmd || setting->write_ioctl == cmd) + break; + setting = setting->next; + } + + return setting; +} + +/** + * ide_find_setting_by_name - find a drive specific setting + * @drive: drive to scan + * @name: setting name + * + * Scan's the device setting table for a matching entry and returns + * this or NULL if no entry is found. The caller must hold the + * setting semaphore + */ + +ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name) +{ + ide_settings_t *setting = drive->settings; + + while (setting) { + if (strcmp(setting->name, name) == 0) + break; + setting = setting->next; + } + return setting; +} + +/** + * auto_remove_settings - remove driver specific settings + * @drive: drive + * + * Automatically remove all the driver specific settings for this + * drive. This function may not be called from IRQ context. The + * caller must hold ide_setting_sem. + */ + +static void auto_remove_settings (ide_drive_t *drive) +{ + ide_settings_t *setting; +repeat: + setting = drive->settings; + while (setting) { + if (setting->auto_remove) { + __ide_remove_setting(drive, setting->name); + goto repeat; + } + setting = setting->next; + } +} + +/** + * ide_read_setting - read an IDE setting + * @drive: drive to read from + * @setting: drive setting + * + * Read a drive setting and return the value. The caller + * must hold the ide_setting_sem when making this call. + * + * BUGS: the data return and error are the same return value + * so an error -EINVAL and true return of the same value cannot + * be told apart + */ + +int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting) +{ + int val = -EINVAL; + unsigned long flags; + + if ((setting->rw & SETTING_READ)) { + spin_lock_irqsave(&ide_lock, flags); + switch(setting->data_type) { + case TYPE_BYTE: + val = *((u8 *) setting->data); + break; + case TYPE_SHORT: + val = *((u16 *) setting->data); + break; + case TYPE_INT: + case TYPE_INTA: + val = *((u32 *) setting->data); + break; + } + spin_unlock_irqrestore(&ide_lock, flags); + } + return val; +} /** * ide_spin_wait_hwgroup - wait for group @@ -854,14 +1058,61 @@ int ide_spin_wait_hwgroup (ide_drive_t *drive) EXPORT_SYMBOL(ide_spin_wait_hwgroup); -int set_io_32bit(ide_drive_t *drive, int arg) +/** + * ide_write_setting - read an IDE setting + * @drive: drive to read from + * @setting: drive setting + * @val: value + * + * Write a drive setting if it is possible. The caller + * must hold the ide_setting_sem when making this call. + * + * BUGS: the data return and error are the same return value + * so an error -EINVAL and true return of the same value cannot + * be told apart + * + * FIXME: This should be changed to enqueue a special request + * to the driver to change settings, and then wait on a sema for completion. + * The current scheme of polling is kludgy, though safe enough. + */ + +int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) { - if (drive->no_io_32bit) - return -EPERM; + int i; + u32 *p; - if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (!(setting->rw & SETTING_WRITE)) + return -EPERM; + if (val < setting->min || val > setting->max) return -EINVAL; + if (setting->set) + return setting->set(drive, val); + if (ide_spin_wait_hwgroup(drive)) + return -EBUSY; + switch (setting->data_type) { + case TYPE_BYTE: + *((u8 *) setting->data) = val; + break; + case TYPE_SHORT: + *((u16 *) setting->data) = val; + break; + case TYPE_INT: + *((u32 *) setting->data) = val; + break; + case TYPE_INTA: + p = (u32 *) setting->data; + for (i = 0; i < 1 << PARTN_BITS; i++, p++) + *p = val; + break; + } + spin_unlock_irq(&ide_lock); + return 0; +} +static int set_io_32bit(ide_drive_t *drive, int arg) +{ drive->io_32bit = arg; #ifdef CONFIG_BLK_DEV_DTC2278 if (HWIF(drive)->chipset == ide_dtc2278) @@ -870,28 +1121,12 @@ int set_io_32bit(ide_drive_t *drive, int arg) return 0; } -static int set_ksettings(ide_drive_t *drive, int arg) -{ - if (arg < 0 || arg > 1) - return -EINVAL; - - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - drive->keep_settings = arg; - spin_unlock_irq(&ide_lock); - - return 0; -} - -int set_using_dma(ide_drive_t *drive, int arg) +static int set_using_dma (ide_drive_t *drive, int arg) { #ifdef CONFIG_BLK_DEV_IDEDMA ide_hwif_t *hwif = drive->hwif; int err = -EPERM; - if (arg < 0 || arg > 1) - return -EINVAL; - if (!drive->id || !(drive->id->capability & 1)) goto out; @@ -924,20 +1159,14 @@ int set_using_dma(ide_drive_t *drive, int arg) out: return err; #else - if (arg < 0 || arg > 1) - return -EINVAL; - return -EPERM; #endif } -int set_pio_mode(ide_drive_t *drive, int arg) +static int set_pio_mode (ide_drive_t *drive, int arg) { struct request rq; - if (arg < 0 || arg > 255) - return -EINVAL; - if (!HWIF(drive)->tuneproc) return -ENOSYS; if (drive->special.b.set_tune) @@ -949,20 +1178,42 @@ int set_pio_mode(ide_drive_t *drive, int arg) return 0; } -static int set_unmaskirq(ide_drive_t *drive, int arg) +static int set_xfer_rate (ide_drive_t *drive, int arg) { - if (drive->no_unmask) - return -EPERM; + int err = ide_wait_cmd(drive, + WIN_SETFEATURES, (u8) arg, + SETFEATURES_XFER, 0, NULL); - if (arg < 0 || arg > 1) - return -EINVAL; + if (!err && arg) { + ide_set_xfer_rate(drive, (u8) arg); + ide_driveid_update(drive); + } + return err; +} - if (ide_spin_wait_hwgroup(drive)) - return -EBUSY; - drive->unmask = arg; - spin_unlock_irq(&ide_lock); +/** + * ide_add_generic_settings - generic ide settings + * @drive: drive being configured + * + * Add the generic parts of the system settings to the /proc files and + * ioctls for this IDE device. The caller must not be holding the + * ide_setting_sem. + */ - return 0; +void ide_add_generic_settings (ide_drive_t *drive) +{ +/* + * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function + */ + __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); + __ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); + __ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); + __ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); + __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); + __ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); + __ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); + __ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); + __ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); } /** @@ -1034,23 +1285,27 @@ static int generic_ide_resume(struct device *dev) int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, unsigned int cmd, unsigned long arg) { - unsigned long flags; + ide_settings_t *setting; ide_driver_t *drv; + int err = 0; void __user *p = (void __user *)arg; - int err = 0, (*setfunc)(ide_drive_t *, int); - u8 *val; - switch (cmd) { - case HDIO_GET_32BIT: val = &drive->io_32bit; goto read_val; - case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val; - case HDIO_GET_UNMASKINTR: val = &drive->unmask; goto read_val; - case HDIO_GET_DMA: val = &drive->using_dma; goto read_val; - case HDIO_SET_32BIT: setfunc = set_io_32bit; goto set_val; - case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings; goto set_val; - case HDIO_SET_PIO_MODE: setfunc = set_pio_mode; goto set_val; - case HDIO_SET_UNMASKINTR: setfunc = set_unmaskirq; goto set_val; - case HDIO_SET_DMA: setfunc = set_using_dma; goto set_val; + down(&ide_setting_sem); + if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) { + if (cmd == setting->read_ioctl) { + err = ide_read_setting(drive, setting); + up(&ide_setting_sem); + return err >= 0 ? put_user(err, (long __user *)arg) : err; + } else { + if (bdev != bdev->bd_contains) + err = -EINVAL; + else + err = ide_write_setting(drive, setting, arg); + up(&ide_setting_sem); + return err; + } } + up(&ide_setting_sem); switch (cmd) { case HDIO_OBSOLETE_IDENTITY: @@ -1104,7 +1359,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device ide_init_hwif_ports(&hw, (unsigned long) args[0], (unsigned long) args[1], NULL); hw.irq = args[2]; - if (ide_register_hw(&hw, 0, NULL) == -1) + if (ide_register_hw(&hw, NULL) == -1) return -EIO; return 0; } @@ -1179,28 +1434,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device default: return -EINVAL; } - -read_val: - down(&ide_setting_sem); - spin_lock_irqsave(&ide_lock, flags); - err = *val; - spin_unlock_irqrestore(&ide_lock, flags); - up(&ide_setting_sem); - return err >= 0 ? put_user(err, (long __user *)arg) : err; - -set_val: - if (bdev != bdev->bd_contains) - err = -EINVAL; - else { - if (!capable(CAP_SYS_ADMIN)) - err = -EACCES; - else { - down(&ide_setting_sem); - err = setfunc(drive, arg); - up(&ide_setting_sem); - } - } - return err; } EXPORT_SYMBOL(generic_ide_ioctl); @@ -1333,13 +1566,13 @@ static int __init ide_setup(char *s) return 1; } -#ifdef CONFIG_IDEPCI_PCIBUS_ORDER +#ifdef CONFIG_BLK_DEV_IDEPCI if (!strcmp(s, "ide=reverse")) { ide_scan_direction = 1; printk(" : Enabled support for IDE inverse scan order.\n"); return 1; } -#endif +#endif /* CONFIG_BLK_DEV_IDEPCI */ #ifdef CONFIG_BLK_DEV_IDEACPI if (!strcmp(s, "ide=noacpi")) { @@ -1599,9 +1832,9 @@ extern void __init h8300_ide_init(void); */ static void __init probe_for_hwifs (void) { -#ifdef CONFIG_IDEPCI_PCIBUS_ORDER +#ifdef CONFIG_BLK_DEV_IDEPCI ide_scan_pcibus(ide_scan_direction); -#endif +#endif /* CONFIG_BLK_DEV_IDEPCI */ #ifdef CONFIG_ETRAX_IDE { @@ -1659,6 +1892,54 @@ static void __init probe_for_hwifs (void) #endif } +void ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) +{ +#ifdef CONFIG_PROC_FS + ide_add_proc_entries(drive->proc, driver->proc, drive); +#endif +} + +EXPORT_SYMBOL(ide_register_subdriver); + +/** + * ide_unregister_subdriver - disconnect drive from driver + * @drive: drive to unplug + * @driver: driver + * + * Disconnect a drive from the driver it was attached to and then + * clean up the various proc files and other objects attached to it. + * + * Takes ide_setting_sem and ide_lock. + * Caller must hold none of the locks. + */ + +void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver) +{ + unsigned long flags; + +#ifdef CONFIG_PROC_FS + ide_remove_proc_entries(drive->proc, driver->proc); +#endif + down(&ide_setting_sem); + spin_lock_irqsave(&ide_lock, flags); + /* + * ide_setting_sem protects the settings list + * ide_lock protects the use of settings + * + * so we need to hold both, ide_settings_sem because we want to + * modify the settings list, and ide_lock because we cannot take + * a setting out that is being used. + * + * OTOH both ide_{read,write}_setting are only ever used under + * ide_setting_sem. + */ + auto_remove_settings(drive); + spin_unlock_irqrestore(&ide_lock, flags); + up(&ide_setting_sem); +} + +EXPORT_SYMBOL(ide_unregister_subdriver); + /* * Probe module */ @@ -1790,7 +2071,9 @@ static int __init ide_init(void) init_ide_data(); - proc_ide_create(); +#ifdef CONFIG_PROC_FS + proc_ide_root = proc_mkdir("ide", NULL); +#endif #ifdef CONFIG_BLK_DEV_ALI14XX if (probe_ali14xx) @@ -1813,9 +2096,14 @@ static int __init ide_init(void) (void)qd65xx_init(); #endif + initializing = 1; /* Probe for special PCI and other "known" interface chipsets. */ probe_for_hwifs(); + initializing = 0; +#ifdef CONFIG_PROC_FS + proc_ide_create(); +#endif return 0; } @@ -1855,7 +2143,9 @@ void __exit cleanup_module (void) pnpide_exit(); #endif +#ifdef CONFIG_PROC_FS proc_ide_destroy(); +#endif bus_unregister(&ide_bus_type); } diff --git a/trunk/drivers/ide/legacy/ali14xx.c b/trunk/drivers/ide/legacy/ali14xx.c index df17ed68c0bc..91961aa03047 100644 --- a/trunk/drivers/ide/legacy/ali14xx.c +++ b/trunk/drivers/ide/legacy/ali14xx.c @@ -223,8 +223,7 @@ static int __init ali14xx_probe(void) probe_hwif_init(hwif); probe_hwif_init(mate); - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + create_proc_ide_interfaces(); return 0; } diff --git a/trunk/drivers/ide/legacy/buddha.c b/trunk/drivers/ide/legacy/buddha.c index 101aee1711c4..1ed224a01f79 100644 --- a/trunk/drivers/ide/legacy/buddha.c +++ b/trunk/drivers/ide/legacy/buddha.c @@ -213,7 +213,7 @@ void __init buddha_init(void) IRQ_AMIGA_PORTS); } - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, &hwif); if (index != -1) { hwif->mmio = 1; printk("ide%d: ", index); diff --git a/trunk/drivers/ide/legacy/dtc2278.c b/trunk/drivers/ide/legacy/dtc2278.c index 36a3f0ac6162..0219ffa64db6 100644 --- a/trunk/drivers/ide/legacy/dtc2278.c +++ b/trunk/drivers/ide/legacy/dtc2278.c @@ -138,8 +138,7 @@ static int __init dtc2278_probe(void) probe_hwif_init(hwif); probe_hwif_init(mate); - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + create_proc_ide_interfaces(); return 0; } diff --git a/trunk/drivers/ide/legacy/falconide.c b/trunk/drivers/ide/legacy/falconide.c index e1e9d9d6893f..a9f2cd5bb81e 100644 --- a/trunk/drivers/ide/legacy/falconide.c +++ b/trunk/drivers/ide/legacy/falconide.c @@ -70,7 +70,7 @@ void __init falconide_init(void) 0, 0, NULL, // falconide_iops, IRQ_MFP_IDE); - index = ide_register_hw(&hw, 1, NULL); + index = ide_register_hw(&hw, NULL); if (index != -1) printk("ide%d: Falcon IDE interface\n", index); diff --git a/trunk/drivers/ide/legacy/gayle.c b/trunk/drivers/ide/legacy/gayle.c index 0830a021bbb6..dcfadbbf55d8 100644 --- a/trunk/drivers/ide/legacy/gayle.c +++ b/trunk/drivers/ide/legacy/gayle.c @@ -165,7 +165,7 @@ void __init gayle_init(void) // &gayle_iops, IRQ_AMIGA_PORTS); - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, &hwif); if (index != -1) { hwif->mmio = 1; switch (i) { diff --git a/trunk/drivers/ide/legacy/ht6560b.c b/trunk/drivers/ide/legacy/ht6560b.c index c8f353b1296f..a2832643c522 100644 --- a/trunk/drivers/ide/legacy/ht6560b.c +++ b/trunk/drivers/ide/legacy/ht6560b.c @@ -357,8 +357,7 @@ int __init ht6560b_init(void) probe_hwif_init(hwif); probe_hwif_init(mate); - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + create_proc_ide_interfaces(); return 0; diff --git a/trunk/drivers/ide/legacy/ide-cs.c b/trunk/drivers/ide/legacy/ide-cs.c index 2f3977f195b7..c6522a64d7ec 100644 --- a/trunk/drivers/ide/legacy/ide-cs.c +++ b/trunk/drivers/ide/legacy/ide-cs.c @@ -153,7 +153,7 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq hw.irq = irq; hw.chipset = ide_pci; hw.dev = &handle->dev; - return ide_register_hw_with_fixup(&hw, 0, NULL, ide_undecoded_slave); + return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave); } /*====================================================================== diff --git a/trunk/drivers/ide/legacy/macide.c b/trunk/drivers/ide/legacy/macide.c index c211fc78345d..4c0079ad52ac 100644 --- a/trunk/drivers/ide/legacy/macide.c +++ b/trunk/drivers/ide/legacy/macide.c @@ -102,21 +102,21 @@ void macide_init(void) 0, 0, macide_ack_intr, // quadra_ide_iops, IRQ_NUBUS_F); - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, &hwif); break; case MAC_IDE_PB: ide_setup_ports(&hw, IDE_BASE, macide_offsets, 0, 0, macide_ack_intr, // macide_pb_iops, IRQ_NUBUS_C); - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, &hwif); break; case MAC_IDE_BABOON: ide_setup_ports(&hw, BABOON_BASE, macide_offsets, 0, 0, NULL, // macide_baboon_iops, IRQ_BABOON_1); - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, &hwif); if (index == -1) break; if (macintosh_config->ident == MAC_MODEL_PB190) { diff --git a/trunk/drivers/ide/legacy/q40ide.c b/trunk/drivers/ide/legacy/q40ide.c index e628a983ce33..74f08124eabb 100644 --- a/trunk/drivers/ide/legacy/q40ide.c +++ b/trunk/drivers/ide/legacy/q40ide.c @@ -142,7 +142,7 @@ void q40ide_init(void) 0, NULL, // m68kide_iops, q40ide_default_irq(pcide_bases[i])); - index = ide_register_hw(&hw, 1, &hwif); + index = ide_register_hw(&hw, &hwif); // **FIXME** if (index != -1) hwif->mmio = 1; diff --git a/trunk/drivers/ide/legacy/qd65xx.c b/trunk/drivers/ide/legacy/qd65xx.c index d1414a75b523..2fb8f50f1293 100644 --- a/trunk/drivers/ide/legacy/qd65xx.c +++ b/trunk/drivers/ide/legacy/qd65xx.c @@ -427,7 +427,7 @@ static int __init qd_probe(int base) qd_setup(hwif, base, config, QD6500_DEF_DATA, QD6500_DEF_DATA, &qd6500_tune_drive); - ide_proc_register_port(hwif); + create_proc_ide_interfaces(); return 1; } @@ -459,7 +459,7 @@ static int __init qd_probe(int base) &qd6580_tune_drive); qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); - ide_proc_register_port(hwif); + create_proc_ide_interfaces(); return 1; } else { @@ -479,8 +479,7 @@ static int __init qd_probe(int base) &qd6580_tune_drive); qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT); - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + create_proc_ide_interfaces(); return 0; /* no other qd65xx possible */ } diff --git a/trunk/drivers/ide/legacy/umc8672.c b/trunk/drivers/ide/legacy/umc8672.c index ddc403a0bd82..ca7974455578 100644 --- a/trunk/drivers/ide/legacy/umc8672.c +++ b/trunk/drivers/ide/legacy/umc8672.c @@ -160,8 +160,7 @@ static int __init umc8672_probe(void) probe_hwif_init(hwif); probe_hwif_init(mate); - ide_proc_register_port(hwif); - ide_proc_register_port(mate); + create_proc_ide_interfaces(); return 0; } diff --git a/trunk/drivers/ide/mips/au1xxx-ide.c b/trunk/drivers/ide/mips/au1xxx-ide.c index ca95e990862e..d54d9fe92a7d 100644 --- a/trunk/drivers/ide/mips/au1xxx-ide.c +++ b/trunk/drivers/ide/mips/au1xxx-ide.c @@ -760,9 +760,6 @@ static int au_ide_probe(struct device *dev) #endif probe_hwif_init(hwif); - - ide_proc_register_port(hwif); - dev_set_drvdata(dev, hwif); printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode ); diff --git a/trunk/drivers/ide/mips/swarm.c b/trunk/drivers/ide/mips/swarm.c index 6e935d7c63fd..81fa06851b27 100644 --- a/trunk/drivers/ide/mips/swarm.c +++ b/trunk/drivers/ide/mips/swarm.c @@ -129,9 +129,6 @@ static int __devinit swarm_ide_probe(struct device *dev) hwif->irq = hwif->hw.irq; probe_hwif_init(hwif); - - ide_proc_register_port(hwif); - dev_set_drvdata(dev, hwif); return 0; diff --git a/trunk/drivers/ide/pci/aec62xx.c b/trunk/drivers/ide/pci/aec62xx.c index b173bc66ce1e..73bdf64dbbfc 100644 --- a/trunk/drivers/ide/pci/aec62xx.c +++ b/trunk/drivers/ide/pci/aec62xx.c @@ -87,12 +87,38 @@ static u8 pci_bus_clock_list_ultra (u8 speed, struct chipset_bus_clock_list_entr return chipset_table->ultra_settings; } +static u8 aec62xx_ratemask (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u8 mode; + + switch(hwif->pci_dev->device) { + case PCI_DEVICE_ID_ARTOP_ATP865: + case PCI_DEVICE_ID_ARTOP_ATP865R: + mode = (inb(hwif->channel ? + hwif->mate->dma_status : + hwif->dma_status) & 0x10) ? 4 : 3; + break; + case PCI_DEVICE_ID_ARTOP_ATP860: + case PCI_DEVICE_ID_ARTOP_ATP860R: + mode = 2; + break; + case PCI_DEVICE_ID_ARTOP_ATP850UF: + default: + return 1; + } + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + static int aec6210_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u16 d_conf = 0; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(aec62xx_ratemask(drive), xferspeed); u8 ultra = 0, ultra_conf = 0; u8 tmp0 = 0, tmp1 = 0, tmp2 = 0; unsigned long flags; @@ -119,7 +145,7 @@ static int aec6260_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(aec62xx_ratemask(drive), xferspeed); u8 unit = (drive->select.b.unit & 0x01); u8 tmp1 = 0, tmp2 = 0; u8 ultra = 0, drive_conf = 0, ultra_conf = 0; @@ -155,6 +181,17 @@ static int aec62xx_tune_chipset (ide_drive_t *drive, u8 speed) } } +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, aec62xx_ratemask(drive)); + + if (!(speed)) + return 0; + + (void) aec62xx_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio) { pio = ide_get_best_pio_mode(drive, pio, 4, NULL); @@ -163,7 +200,7 @@ static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio) static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive) { - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) @@ -224,13 +261,11 @@ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const ch static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; - hwif->autodma = 0; hwif->tuneproc = &aec62xx_tune_drive; hwif->speedproc = &aec62xx_tune_chipset; - if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) + if (hwif->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) hwif->serialized = hwif->channel; if (hwif->mate) @@ -242,15 +277,7 @@ static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif) return; } - hwif->ultra_mask = hwif->cds->udma_mask; - - /* atp865 and atp865r */ - if (hwif->ultra_mask == 0x3f) { - /* check bit 0x10 of DMA status register */ - if (inb(pci_resource_start(dev, 4) + 2) & 0x10) - hwif->ultra_mask = 0x7f; /* udma0-6 */ - } - + hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; hwif->ide_dma_check = &aec62xx_config_drive_xfer_rate; @@ -317,7 +344,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, .bootable = OFF_BOARD, - .udma_mask = 0x07, /* udma0-2 */ },{ /* 1 */ .name = "AEC6260", .init_setup = init_setup_aec62xx, @@ -327,7 +353,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { .channels = 2, .autodma = NOAUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x1f, /* udma0-4 */ },{ /* 2 */ .name = "AEC6260R", .init_setup = init_setup_aec62xx, @@ -338,7 +363,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, .bootable = NEVER_BOARD, - .udma_mask = 0x1f, /* udma0-4 */ },{ /* 3 */ .name = "AEC6X80", .init_setup = init_setup_aec6x80, @@ -348,7 +372,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x3f, /* udma0-5 */ },{ /* 4 */ .name = "AEC6X80R", .init_setup = init_setup_aec6x80, @@ -359,7 +382,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, .bootable = OFF_BOARD, - .udma_mask = 0x3f, /* udma0-5 */ } }; diff --git a/trunk/drivers/ide/pci/alim15x3.c b/trunk/drivers/ide/pci/alim15x3.c index 428efdae0c7b..946a12746cb5 100644 --- a/trunk/drivers/ide/pci/alim15x3.c +++ b/trunk/drivers/ide/pci/alim15x3.c @@ -50,7 +50,7 @@ static u8 m5229_revision; static u8 chip_is_1543c_e; static struct pci_dev *isa_dev; -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) +#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) #include #include @@ -278,7 +278,7 @@ static int ali_get_info (char *buffer, char **addr, off_t offset, int count) return p-buffer; /* => must be less than 4k! */ } -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ +#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ /** * ali15x3_tune_pio - set up chipset for PIO mode @@ -378,31 +378,74 @@ static void ali15x3_tune_drive (ide_drive_t *drive, u8 pio) } /** - * ali_udma_filter - compute UDMA mask - * @drive: IDE device + * ali15x3_can_ultra - check for ultra DMA support + * @drive: drive to do the check * - * Return available UDMA modes. - * - * The actual rules for the ALi are: + * Check the drive and controller revisions. Return 0 if UDMA is + * not available, or 1 if UDMA can be used. The actual rules for + * the ALi are * No UDMA on revisions <= 0x20 * Disk only for revisions < 0xC2 * Not WDC drives for revisions < 0xC2 * * FIXME: WDC ifdef needs to die */ - -static u8 ali_udma_filter(ide_drive_t *drive) + +static u8 ali15x3_can_ultra (ide_drive_t *drive) { - if (m5229_revision > 0x20 && m5229_revision < 0xC2) { - if (drive->media != ide_disk) - return 0; #ifndef CONFIG_WDC_ALI15X3 - if (chip_is_1543c_e && strstr(drive->id->model, "WDC ")) - return 0; -#endif + struct hd_driveid *id = drive->id; +#endif /* CONFIG_WDC_ALI15X3 */ + + if (m5229_revision <= 0x20) { + return 0; + } else if ((m5229_revision < 0xC2) && +#ifndef CONFIG_WDC_ALI15X3 + ((chip_is_1543c_e && strstr(id->model, "WDC ")) || + (drive->media!=ide_disk))) { +#else /* CONFIG_WDC_ALI15X3 */ + (drive->media!=ide_disk)) { +#endif /* CONFIG_WDC_ALI15X3 */ + return 0; + } else { + return 1; + } +} + +/** + * ali15x3_ratemask - generate DMA mode list + * @drive: drive to compute against + * + * Generate a list of the available DMA modes for the drive. + * FIXME: this function contains lots of bogus masking we can dump + * + * Return the highest available mode (UDMA33, UDMA66, UDMA100,..) + */ + +static u8 ali15x3_ratemask (ide_drive_t *drive) +{ + u8 mode = 0, can_ultra = ali15x3_can_ultra(drive); + + if (m5229_revision > 0xC4 && can_ultra) { + mode = 4; + } else if (m5229_revision == 0xC4 && can_ultra) { + mode = 3; + } else if (m5229_revision >= 0xC2 && can_ultra) { + mode = 2; + } else if (can_ultra) { + return 1; + } else { + return 0; } - return drive->hwif->ultra_mask; + /* + * If the drive sees no suitable cable then UDMA 33 + * is the highest permitted mode + */ + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; } /** @@ -418,7 +461,7 @@ static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(ali15x3_ratemask(drive), xferspeed); u8 speed1 = speed; u8 unit = (drive->select.b.unit & 0x01); u8 tmpbyte = 0x00; @@ -468,7 +511,7 @@ static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_max_dma_mode(drive); + u8 speed = ide_dma_speed(drive, ali15x3_ratemask(drive)); if (!(speed)) return 0; @@ -566,13 +609,13 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) +#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) if (!ali_proc) { ali_proc = 1; bmide_dev = dev; ide_pci_create_host_proc("ali", ali_get_info); } -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ +#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ local_irq_save(flags); @@ -728,7 +771,6 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif) hwif->autodma = 0; hwif->tuneproc = &ali15x3_tune_drive; hwif->speedproc = &ali15x3_tune_chipset; - hwif->udma_filter = &ali_udma_filter; /* don't use LBA48 DMA on ALi devices before rev 0xC5 */ hwif->no_lba48_dma = (m5229_revision <= 0xC4) ? 1 : 0; @@ -741,17 +783,8 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif) hwif->atapi_dma = 1; - if (m5229_revision <= 0x20) - hwif->ultra_mask = 0x00; /* no udma */ - else if (m5229_revision < 0xC2) - hwif->ultra_mask = 0x07; /* udma0-2 */ - else if (m5229_revision == 0xC2 || m5229_revision == 0xC3) - hwif->ultra_mask = 0x1f; /* udma0-4 */ - else if (m5229_revision == 0xC4) - hwif->ultra_mask = 0x3f; /* udma0-5 */ - else - hwif->ultra_mask = 0x7f; /* udma0-6 */ - + if (m5229_revision > 0x20) + hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; diff --git a/trunk/drivers/ide/pci/amd74xx.c b/trunk/drivers/ide/pci/amd74xx.c index becb1a5648b0..7989bdd842a2 100644 --- a/trunk/drivers/ide/pci/amd74xx.c +++ b/trunk/drivers/ide/pci/amd74xx.c @@ -92,7 +92,7 @@ static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3 * AMD /proc entry. */ -#ifdef CONFIG_IDE_PROC_FS +#ifdef CONFIG_PROC_FS #include #include @@ -402,14 +402,14 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch * Register /proc/ide/amd74xx entry */ -#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_IDE_PROC_FS) +#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS) if (!amd74xx_proc) { amd_base = pci_resource_start(dev, 4); bmide_dev = dev; ide_pci_create_host_proc("amd74xx", amd74xx_get_info); amd74xx_proc = 1; } -#endif /* DISPLAY_AMD_TIMINGS && CONFIG_IDE_PROC_FS */ +#endif /* DISPLAY_AMD_TIMINGS && CONFIG_PROC_FS */ return dev->irq; } diff --git a/trunk/drivers/ide/pci/atiixp.c b/trunk/drivers/ide/pci/atiixp.c index 0e52ad722a72..2d48af32e3f4 100644 --- a/trunk/drivers/ide/pci/atiixp.c +++ b/trunk/drivers/ide/pci/atiixp.c @@ -48,6 +48,22 @@ static int save_mdma_mode[4]; static DEFINE_SPINLOCK(atiixp_lock); +/** + * atiixp_ratemask - compute rate mask for ATIIXP IDE + * @drive: IDE drive to compute for + * + * Returns the available modes for the ATIIXP IDE controller. + */ + +static u8 atiixp_ratemask(ide_drive_t *drive) +{ + u8 mode = 3; + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + /** * atiixp_dma_2_pio - return the PIO mode matching DMA * @xfer_rate: transfer speed @@ -173,7 +189,7 @@ static int atiixp_speedproc(ide_drive_t *drive, u8 xferspeed) u16 tmp16; u8 speed, pio; - speed = ide_rate_filter(drive, xferspeed); + speed = ide_rate_filter(atiixp_ratemask(drive), xferspeed); spin_lock_irqsave(&atiixp_lock, flags); @@ -206,6 +222,26 @@ static int atiixp_speedproc(ide_drive_t *drive, u8 xferspeed) return ide_config_drive_speed(drive, speed); } +/** + * atiixp_config_drive_for_dma - configure drive for DMA + * @drive: IDE drive to configure + * + * Set up a ATIIXP interface channel for the best available speed. + * We prefer UDMA if it is available and then MWDMA. If DMA is + * not available we switch to PIO and return 0. + */ + +static int atiixp_config_drive_for_dma(ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, atiixp_ratemask(drive)); + + if (!speed) + return 0; + + (void) atiixp_speedproc(drive, speed); + return ide_dma_enable(drive); +} + /** * atiixp_dma_check - set up an IDE device * @drive: IDE drive to configure @@ -220,7 +256,7 @@ static int atiixp_dma_check(ide_drive_t *drive) drive->init_speed = 0; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && atiixp_config_drive_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) { diff --git a/trunk/drivers/ide/pci/cmd64x.c b/trunk/drivers/ide/pci/cmd64x.c index 61ea96b5555c..77f51ab6d439 100644 --- a/trunk/drivers/ide/pci/cmd64x.c +++ b/trunk/drivers/ide/pci/cmd64x.c @@ -74,7 +74,7 @@ #define UDIDETCR1 0x7B #define DTPR1 0x7C -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) +#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) #include #include @@ -165,7 +165,7 @@ static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count) return p-buffer; /* => must be less than 4k! */ } -#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ +#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */ static u8 quantize_timing(int timing, int quant) { @@ -292,6 +292,55 @@ static void cmd64x_tune_drive (ide_drive_t *drive, u8 pio) (void) ide_config_drive_speed(drive, XFER_PIO_0 + pio); } +static u8 cmd64x_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 mode = 0; + + switch(dev->device) { + case PCI_DEVICE_ID_CMD_649: + mode = 3; + break; + case PCI_DEVICE_ID_CMD_648: + mode = 2; + break; + case PCI_DEVICE_ID_CMD_643: + return 0; + + case PCI_DEVICE_ID_CMD_646: + { + unsigned int class_rev = 0; + pci_read_config_dword(dev, + PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + /* + * UltraDMA only supported on PCI646U and PCI646U2, which + * correspond to revisions 0x03, 0x05 and 0x07 respectively. + * Actually, although the CMD tech support people won't + * tell me the details, the 0x03 revision cannot support + * UDMA correctly without hardware modifications, and even + * then it only works with Quantum disks due to some + * hold time assumptions in the 646U part which are fixed + * in the 646U2. + * + * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. + */ + switch(class_rev) { + case 0x07: + case 0x05: + return 1; + case 0x03: + case 0x01: + default: + return 0; + } + } + } + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + static int cmd64x_tune_chipset (ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = HWIF(drive); @@ -299,7 +348,7 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 speed) u8 unit = drive->dn & 0x01; u8 regU = 0, pciU = hwif->channel ? UDIDETCR1 : UDIDETCR0; - speed = ide_rate_filter(drive, speed); + speed = ide_rate_filter(cmd64x_ratemask(drive), speed); if (speed >= XFER_SW_DMA_0) { (void) pci_read_config_byte(dev, pciU, ®U); @@ -354,7 +403,7 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 speed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_max_dma_mode(drive); + u8 speed = ide_dma_speed(drive, cmd64x_ratemask(drive)); if (!speed) return 0; @@ -548,7 +597,7 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha (void) pci_write_config_byte(dev, UDIDETCR0, 0xf0); #endif /* CONFIG_PPC */ -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) +#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) cmd_devs[n_cmd_devs++] = dev; @@ -556,7 +605,7 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha cmd64x_proc = 1; ide_pci_create_host_proc("cmd64x", cmd64x_get_info); } -#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_IDE_PROC_FS */ +#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ return 0; } @@ -595,25 +644,16 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif) hwif->atapi_dma = 1; - hwif->ultra_mask = hwif->cds->udma_mask; - - /* - * UltraDMA only supported on PCI646U and PCI646U2, which - * correspond to revisions 0x03, 0x05 and 0x07 respectively. - * Actually, although the CMD tech support people won't - * tell me the details, the 0x03 revision cannot support - * UDMA correctly without hardware modifications, and even - * then it only works with Quantum disks due to some - * hold time assumptions in the 646U part which are fixed - * in the 646U2. - * - * So we only do UltraDMA on revision 0x05 and 0x07 chipsets. - */ - if (dev->device == PCI_DEVICE_ID_CMD_646 && class_rev < 5) - hwif->ultra_mask = 0x00; - + hwif->ultra_mask = 0x3f; hwif->mwdma_mask = 0x07; + if (dev->device == PCI_DEVICE_ID_CMD_643) + hwif->ultra_mask = 0x80; + if (dev->device == PCI_DEVICE_ID_CMD_646) + hwif->ultra_mask = (class_rev > 0x04) ? 0x07 : 0x80; + if (dev->device == PCI_DEVICE_ID_CMD_648) + hwif->ultra_mask = 0x1f; + hwif->ide_dma_check = &cmd64x_config_drive_for_dma; if (!(hwif->udma_four)) hwif->udma_four = ata66_cmd64x(hwif); @@ -676,7 +716,6 @@ static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}}, .bootable = ON_BOARD, - .udma_mask = 0x00, /* no udma */ },{ /* 1 */ .name = "CMD646", .init_setup = init_setup_cmd646, @@ -686,7 +725,6 @@ static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, .bootable = ON_BOARD, - .udma_mask = 0x07, /* udma0-2 */ },{ /* 2 */ .name = "CMD648", .init_setup = init_setup_cmd64x, @@ -696,7 +734,6 @@ static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, .bootable = ON_BOARD, - .udma_mask = 0x1f, /* udma0-4 */ },{ /* 3 */ .name = "CMD649", .init_setup = init_setup_cmd64x, @@ -706,7 +743,6 @@ static ide_pci_device_t cmd64x_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}}, .bootable = ON_BOARD, - .udma_mask = 0x3f, /* udma0-5 */ } }; diff --git a/trunk/drivers/ide/pci/cs5520.c b/trunk/drivers/ide/pci/cs5520.c index 3b88a3a56116..400859a839f7 100644 --- a/trunk/drivers/ide/pci/cs5520.c +++ b/trunk/drivers/ide/pci/cs5520.c @@ -213,7 +213,6 @@ static ide_pci_device_t cyrix_chipsets[] __devinitdata = { static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_hwif_t *hwif = NULL, *mate = NULL; ata_index_t index; ide_pci_device_t *d = &cyrix_chipsets[id->driver_data]; @@ -240,21 +239,10 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic ide_pci_setup_ports(dev, d, 14, &index); - if ((index.b.low & 0xf0) != 0xf0) - hwif = &ide_hwifs[index.b.low]; - if ((index.b.high & 0xf0) != 0xf0) - mate = &ide_hwifs[index.b.high]; - - if (hwif) - probe_hwif_init(hwif); - if (mate) - probe_hwif_init(mate); - - if (hwif) - ide_proc_register_port(hwif); - if (mate) - ide_proc_register_port(mate); - + if((index.b.low & 0xf0) != 0xf0) + probe_hwif_init(&ide_hwifs[index.b.low]); + if((index.b.high & 0xf0) != 0xf0) + probe_hwif_init(&ide_hwifs[index.b.high]); return 0; } diff --git a/trunk/drivers/ide/pci/cs5535.c b/trunk/drivers/ide/pci/cs5535.c index 41925c47ef05..45f43efbf92c 100644 --- a/trunk/drivers/ide/pci/cs5535.c +++ b/trunk/drivers/ide/pci/cs5535.c @@ -127,6 +127,20 @@ static void cs5535_set_speed(ide_drive_t *drive, u8 speed) } } +static u8 cs5535_ratemask(ide_drive_t *drive) +{ + /* eighty93 will return 1 if it's 80core and capable of + exceeding udma2, 0 otherwise. we need ratemask to set + the max speed and if we can > udma2 then we return 2 + which selects speed_max as udma4 which is the 5535's max + speed, and 1 selects udma2 which is the max for 40c */ + if (!eighty_ninty_three(drive)) + return 1; + + return 2; +} + + /**** * cs5535_set_drive - Configure the drive to the new speed * @drive: Drive to set up @@ -137,7 +151,7 @@ static void cs5535_set_speed(ide_drive_t *drive, u8 speed) */ static int cs5535_set_drive(ide_drive_t *drive, u8 speed) { - speed = ide_rate_filter(drive, speed); + speed = ide_rate_filter(cs5535_ratemask(drive), speed); ide_config_drive_speed(drive, speed); cs5535_set_speed(drive, speed); @@ -164,13 +178,28 @@ static void cs5535_tuneproc(ide_drive_t *drive, u8 xferspeed) cs5535_set_speed(drive, xferspeed); } +static int cs5535_config_drive_for_dma(ide_drive_t *drive) +{ + u8 speed; + + speed = ide_dma_speed(drive, cs5535_ratemask(drive)); + + /* If no DMA speed was available then let dma_check hit pio */ + if (!speed) { + return 0; + } + + cs5535_set_drive(drive, speed); + return ide_dma_enable(drive); +} + static int cs5535_dma_check(ide_drive_t *drive) { u8 speed; drive->init_speed = 0; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && cs5535_config_drive_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) { diff --git a/trunk/drivers/ide/pci/delkin_cb.c b/trunk/drivers/ide/pci/delkin_cb.c index 46f4a888c037..dd7ec37fdeab 100644 --- a/trunk/drivers/ide/pci/delkin_cb.c +++ b/trunk/drivers/ide/pci/delkin_cb.c @@ -80,7 +80,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) hw.irq = dev->irq; hw.chipset = ide_pci; /* this enables IRQ sharing */ - rc = ide_register_hw_with_fixup(&hw, 0, &hwif, ide_undecoded_slave); + rc = ide_register_hw_with_fixup(&hw, &hwif, ide_undecoded_slave); if (rc < 0) { printk(KERN_ERR "delkin_cb: ide_register_hw failed (%d)\n", rc); pci_disable_device(dev); diff --git a/trunk/drivers/ide/pci/hpt34x.c b/trunk/drivers/ide/pci/hpt34x.c index 2c24c3de8846..924eaa3a5708 100644 --- a/trunk/drivers/ide/pci/hpt34x.c +++ b/trunk/drivers/ide/pci/hpt34x.c @@ -43,10 +43,15 @@ #define HPT343_DEBUG_DRIVE_INFO 0 +static u8 hpt34x_ratemask (ide_drive_t *drive) +{ + return 1; +} + static int hpt34x_tune_chipset (ide_drive_t *drive, u8 xferspeed) { struct pci_dev *dev = HWIF(drive)->pci_dev; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(hpt34x_ratemask(drive), xferspeed); u32 reg1= 0, tmp1 = 0, reg2 = 0, tmp2 = 0; u8 hi_speed, lo_speed; @@ -84,11 +89,29 @@ static void hpt34x_tune_drive (ide_drive_t *drive, u8 pio) (void) hpt34x_tune_chipset(drive, (XFER_PIO_0 + pio)); } +/* + * This allows the configuration of ide_pci chipset registers + * for cards that learn about the drive's UDMA, DMA, PIO capabilities + * after the drive is reported by the OS. Initially for designed for + * HPT343 UDMA chipset by HighPoint|Triones Technologies, Inc. + */ + +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, hpt34x_ratemask(drive)); + + if (!(speed)) + return 0; + + (void) hpt34x_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + static int hpt34x_config_drive_xfer_rate (ide_drive_t *drive) { drive->init_speed = 0; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) #ifndef CONFIG_HPT34X_AUTODMA return -1; #else diff --git a/trunk/drivers/ide/pci/hpt366.c b/trunk/drivers/ide/pci/hpt366.c index fcbc5605b38e..cf9d344d19f8 100644 --- a/trunk/drivers/ide/pci/hpt366.c +++ b/trunk/drivers/ide/pci/hpt366.c @@ -514,31 +514,43 @@ static int check_in_drive_list(ide_drive_t *drive, const char **list) return 0; } +static u8 hpt3xx_ratemask(ide_drive_t *drive) +{ + struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev); + u8 mode = info->max_mode; + + if (!eighty_ninty_three(drive) && mode) + mode = min(mode, (u8)1); + return mode; +} + /* * Note for the future; the SATA hpt37x we must set * either PIO or UDMA modes 0,4,5 */ - -static u8 hpt3xx_udma_filter(ide_drive_t *drive) + +static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed) { struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev); u8 chip_type = info->chip_type; - u8 mode = info->max_mode; - u8 mask; + u8 mode = hpt3xx_ratemask(drive); + + if (drive->media != ide_disk) + return min(speed, (u8)XFER_PIO_4); switch (mode) { case 0x04: - mask = 0x7f; + speed = min_t(u8, speed, XFER_UDMA_6); break; case 0x03: - mask = 0x3f; + speed = min_t(u8, speed, XFER_UDMA_5); if (chip_type >= HPT374) break; if (!check_in_drive_list(drive, bad_ata100_5)) goto check_bad_ata33; /* fall thru */ case 0x02: - mask = 0x1f; + speed = min_t(u8, speed, XFER_UDMA_4); /* * CHECK ME, Does this need to be changed to HPT374 ?? @@ -549,13 +561,13 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive) !check_in_drive_list(drive, bad_ata66_4)) goto check_bad_ata33; - mask = 0x0f; + speed = min_t(u8, speed, XFER_UDMA_3); if (HPT366_ALLOW_ATA66_3 && !check_in_drive_list(drive, bad_ata66_3)) goto check_bad_ata33; /* fall thru */ case 0x01: - mask = 0x07; + speed = min_t(u8, speed, XFER_UDMA_2); check_bad_ata33: if (chip_type >= HPT370A) @@ -565,10 +577,10 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive) /* fall thru */ case 0x00: default: - mask = 0x00; + speed = min_t(u8, speed, XFER_MW_DMA_2); break; } - return mask; + return speed; } static u32 get_speed_setting(u8 speed, struct hpt_info *info) @@ -596,19 +608,12 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = pci_get_drvdata(dev); - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = hpt3xx_ratefilter(drive, xferspeed); u8 itr_addr = drive->dn ? 0x44 : 0x40; + u32 itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 : + (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff); + u32 new_itr = get_speed_setting(speed, info); u32 old_itr = 0; - u32 itr_mask, new_itr; - - /* TODO: move this to ide_rate_filter() [ check ->atapi_dma ] */ - if (drive->media != ide_disk) - speed = min_t(u8, speed, XFER_PIO_4); - - itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 : - (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff); - - new_itr = get_speed_setting(speed, info); /* * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well) @@ -628,19 +633,12 @@ static int hpt37x_tune_chipset(ide_drive_t *drive, u8 xferspeed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = pci_get_drvdata(dev); - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = hpt3xx_ratefilter(drive, xferspeed); u8 itr_addr = 0x40 + (drive->dn * 4); + u32 itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 : + (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff); + u32 new_itr = get_speed_setting(speed, info); u32 old_itr = 0; - u32 itr_mask, new_itr; - - /* TODO: move this to ide_rate_filter() [ check ->atapi_dma ] */ - if (drive->media != ide_disk) - speed = min_t(u8, speed, XFER_PIO_4); - - itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 : - (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff); - - new_itr = get_speed_setting(speed, info); pci_read_config_dword(dev, itr_addr, &old_itr); new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); @@ -669,6 +667,24 @@ static void hpt3xx_tune_drive(ide_drive_t *drive, u8 pio) (void) hpt3xx_tune_chipset (drive, XFER_PIO_0 + pio); } +/* + * This allows the configuration of ide_pci chipset registers + * for cards that learn about the drive's UDMA, DMA, PIO capabilities + * after the drive is reported by the OS. Initially designed for + * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc. + * + */ +static int config_chipset_for_dma(ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive)); + + if (!speed) + return 0; + + (void) hpt3xx_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + static int hpt3xx_quirkproc(ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -723,7 +739,7 @@ static int hpt366_config_drive_xfer_rate(ide_drive_t *drive) { drive->init_speed = 0; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) @@ -1255,7 +1271,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->intrproc = &hpt3xx_intrproc; hwif->maskproc = &hpt3xx_maskproc; hwif->busproc = &hpt3xx_busproc; - hwif->udma_filter = &hpt3xx_udma_filter; /* * HPT3xxN chips have some complications: diff --git a/trunk/drivers/ide/pci/it8213.c b/trunk/drivers/ide/pci/it8213.c index c04a02687b95..424f00bb160d 100644 --- a/trunk/drivers/ide/pci/it8213.c +++ b/trunk/drivers/ide/pci/it8213.c @@ -17,6 +17,22 @@ #include +/* + * it8213_ratemask - Compute available modes + * @drive: IDE drive + * + * Compute the available speeds for the devices on the interface. This + * is all modes to ATA133 clipped by drive cable setup. + */ + +static u8 it8213_ratemask (ide_drive_t *drive) +{ + u8 mode = 4; + if (!eighty_ninty_three(drive)) + mode = min_t(u8, mode, 1); + return mode; +} + /** * it8213_dma_2_pio - return the PIO mode matching DMA * @xfer_rate: transfer speed @@ -129,7 +145,7 @@ static int it8213_tune_chipset (ide_drive_t *drive, u8 xferspeed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 maslave = 0x40; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(it8213_ratemask(drive), xferspeed); int a_speed = 3 << (drive->dn * 4); int u_flag = 1 << drive->dn; int v_flag = 0x01 << drive->dn; @@ -197,6 +213,25 @@ static int it8213_tune_chipset (ide_drive_t *drive, u8 xferspeed) return ide_config_drive_speed(drive, speed); } +/* + * config_chipset_for_dma - configure for DMA + * @drive: drive to configure + * + * Called by the IDE layer when it wants the timings set up. + */ + +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, it8213_ratemask(drive)); + + if (!speed) + return 0; + + it8213_tune_chipset(drive, speed); + + return ide_dma_enable(drive); +} + /** * it8213_configure_drive_for_dma - set up for DMA transfers * @drive: drive we are going to set up @@ -211,7 +246,7 @@ static int it8213_config_drive_for_dma (ide_drive_t *drive) { u8 pio; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) return 0; pio = ide_get_best_pio_mode(drive, 255, 4, NULL); diff --git a/trunk/drivers/ide/pci/it821x.c b/trunk/drivers/ide/pci/it821x.c index 442f658c6ae7..4e1254813ee0 100644 --- a/trunk/drivers/ide/pci/it821x.c +++ b/trunk/drivers/ide/pci/it821x.c @@ -228,6 +228,22 @@ static void it821x_clock_strategy(ide_drive_t *drive) } } +/** + * it821x_ratemask - Compute available modes + * @drive: IDE drive + * + * Compute the available speeds for the devices on the interface. This + * is all modes to ATA133 clipped by drive cable setup. + */ + +static u8 it821x_ratemask (ide_drive_t *drive) +{ + u8 mode = 4; + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + /** * it821x_tunepio - tune a drive * @drive: drive to tune @@ -422,7 +438,7 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed) ide_hwif_t *hwif = drive->hwif; struct it821x_dev *itdev = ide_get_hwifdata(hwif); - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(it821x_ratemask(drive), xferspeed); switch (speed) { case XFER_PIO_4: @@ -472,7 +488,7 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_max_dma_mode(drive); + u8 speed = ide_dma_speed(drive, it821x_ratemask(drive)); if (speed == 0) return 0; diff --git a/trunk/drivers/ide/pci/jmicron.c b/trunk/drivers/ide/pci/jmicron.c index 76ed25147229..be4fc96c29e0 100644 --- a/trunk/drivers/ide/pci/jmicron.c +++ b/trunk/drivers/ide/pci/jmicron.c @@ -21,6 +21,22 @@ typedef enum { PORT_SATA = 2, } port_type; +/** + * jmicron_ratemask - Compute available modes + * @drive: IDE drive + * + * Compute the available speeds for the devices on the interface. This + * is all modes to ATA133 clipped by drive cable setup. + */ + +static u8 jmicron_ratemask(ide_drive_t *drive) +{ + u8 mode = 4; + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + /** * ata66_jmicron - Cable check * @hwif: IDE port @@ -113,11 +129,31 @@ static void config_jmicron_chipset_for_pio (ide_drive_t *drive, byte set_speed) static int jmicron_tune_chipset (ide_drive_t *drive, byte xferspeed) { - u8 speed = ide_rate_filter(drive, xferspeed); + + u8 speed = ide_rate_filter(jmicron_ratemask(drive), xferspeed); return ide_config_drive_speed(drive, speed); } +/** + * config_chipset_for_dma - configure for DMA + * @drive: drive to configure + * + * As the JMicron snoops for timings all we actually need to do is + * make sure we don't set an invalid mode. + */ + +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, jmicron_ratemask(drive)); + + if (!speed) + return 0; + + jmicron_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + /** * jmicron_configure_drive_for_dma - set up for DMA transfers * @drive: drive we are going to set up @@ -128,7 +164,7 @@ static int jmicron_tune_chipset (ide_drive_t *drive, byte xferspeed) static int jmicron_config_drive_for_dma (ide_drive_t *drive) { - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) return 0; config_jmicron_chipset_for_pio(drive, 1); diff --git a/trunk/drivers/ide/pci/pdc202xx_new.c b/trunk/drivers/ide/pci/pdc202xx_new.c index 65b1e124edf7..2cdd629c653d 100644 --- a/trunk/drivers/ide/pci/pdc202xx_new.c +++ b/trunk/drivers/ide/pci/pdc202xx_new.c @@ -37,6 +37,8 @@ #include #endif +#define PDC202_DEBUG_CABLE 0 + #undef DEBUG #ifdef DEBUG @@ -80,6 +82,16 @@ static u8 max_dma_rate(struct pci_dev *pdev) return mode; } +static u8 pdcnew_ratemask(ide_drive_t *drive) +{ + u8 mode = max_dma_rate(HWIF(drive)->pci_dev); + + if (!eighty_ninty_three(drive)) + mode = min_t(u8, mode, 1); + + return mode; +} + /** * get_indexed_reg - Get indexed register * @hwif: for the port address @@ -152,7 +164,7 @@ static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed) u8 adj = (drive->dn & 1) ? 0x08 : 0x00; int err; - speed = ide_rate_filter(drive, speed); + speed = ide_rate_filter(pdcnew_ratemask(drive), speed); /* * Issue SETFEATURES_XFER to the drive first. PDC202xx hardware will @@ -232,8 +244,17 @@ static int config_chipset_for_dma(ide_drive_t *drive) { struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); + u8 ultra_66 = (id->dma_ultra & 0x0078) ? 1 : 0; + u8 cable = pdcnew_cable_detect(hwif); u8 speed; + if (ultra_66 && cable) { + printk(KERN_WARNING "Warning: %s channel " + "requires an 80-pin cable for operation.\n", + hwif->channel ? "Secondary" : "Primary"); + printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); + } + if (id->capability & 4) { /* * Set IORDY_EN & PREFETCH_EN (this seems to have @@ -246,7 +267,7 @@ static int config_chipset_for_dma(ide_drive_t *drive) set_indexed_reg(hwif, 0x13 + adj, tmp | 0x03); } - speed = ide_max_dma_mode(drive); + speed = ide_dma_speed(drive, pdcnew_ratemask(drive)); if (!speed) return 0; @@ -522,8 +543,7 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) hwif->drives[0].autotune = hwif->drives[1].autotune = 1; hwif->atapi_dma = 1; - - hwif->ultra_mask = hwif->cds->udma_mask; + hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; hwif->err_stops_fifo = 1; @@ -536,6 +556,11 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; + +#if PDC202_DEBUG_CABLE + printk(KERN_DEBUG "%s: %s-pin cable\n", + hwif->name, hwif->udma_four ? "80" : "40"); +#endif /* PDC202_DEBUG_CABLE */ } static int __devinit init_setup_pdcnew(struct pci_dev *dev, ide_pci_device_t *d) @@ -594,7 +619,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x3f, /* udma0-5 */ },{ /* 1 */ .name = "PDC20269", .init_setup = init_setup_pdcnew, @@ -603,7 +627,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x7f, /* udma0-6*/ },{ /* 2 */ .name = "PDC20270", .init_setup = init_setup_pdc20270, @@ -612,7 +635,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x3f, /* udma0-5 */ },{ /* 3 */ .name = "PDC20271", .init_setup = init_setup_pdcnew, @@ -621,7 +643,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x7f, /* udma0-6*/ },{ /* 4 */ .name = "PDC20275", .init_setup = init_setup_pdcnew, @@ -630,7 +651,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x7f, /* udma0-6*/ },{ /* 5 */ .name = "PDC20276", .init_setup = init_setup_pdc20276, @@ -639,7 +659,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x7f, /* udma0-6*/ },{ /* 6 */ .name = "PDC20277", .init_setup = init_setup_pdcnew, @@ -648,7 +667,6 @@ static ide_pci_device_t pdcnew_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - .udma_mask = 0x7f, /* udma0-6*/ } }; diff --git a/trunk/drivers/ide/pci/pdc202xx_old.c b/trunk/drivers/ide/pci/pdc202xx_old.c index 7146fe3f6ba7..a7a639fe1eaf 100644 --- a/trunk/drivers/ide/pci/pdc202xx_old.c +++ b/trunk/drivers/ide/pci/pdc202xx_old.c @@ -46,6 +46,7 @@ #include #include +#define PDC202_DEBUG_CABLE 0 #define PDC202XX_DEBUG_DRIVE_INFO 0 static const char *pdc_quirk_drives[] = { @@ -100,12 +101,35 @@ static const char *pdc_quirk_drives[] = { #define MC1 0x02 /* DMA"C" timing */ #define MC0 0x01 /* DMA"C" timing */ +static u8 pdc202xx_ratemask (ide_drive_t *drive) +{ + u8 mode; + + switch(HWIF(drive)->pci_dev->device) { + case PCI_DEVICE_ID_PROMISE_20267: + case PCI_DEVICE_ID_PROMISE_20265: + mode = 3; + break; + case PCI_DEVICE_ID_PROMISE_20263: + case PCI_DEVICE_ID_PROMISE_20262: + mode = 2; + break; + case PCI_DEVICE_ID_PROMISE_20246: + return 1; + default: + return 0; + } + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 drive_pci = 0x60 + (drive->dn << 2); - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(pdc202xx_ratemask(drive), xferspeed); u32 drive_conf; u8 AP, BP, CP, DP; @@ -237,7 +261,20 @@ static int config_chipset_for_dma (ide_drive_t *drive) u32 drive_conf = 0; u8 drive_pci = 0x60 + (drive->dn << 2); u8 test1 = 0, test2 = 0, speed = -1; - u8 AP = 0; + u8 AP = 0, cable = 0; + + u8 ultra_66 = ((id->dma_ultra & 0x0010) || + (id->dma_ultra & 0x0008)) ? 1 : 0; + + if (dev->device != PCI_DEVICE_ID_PROMISE_20246) + cable = pdc202xx_old_cable_detect(hwif); + else + ultra_66 = 0; + + if (ultra_66 && cable) { + printk(KERN_WARNING "Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary"); + printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); + } if (dev->device != PCI_DEVICE_ID_PROMISE_20246) pdc_old_disable_66MHz_clock(drive->hwif); @@ -271,7 +308,7 @@ static int config_chipset_for_dma (ide_drive_t *drive) if (drive->media == ide_disk) /* PREFETCH_EN */ pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN); - speed = ide_max_dma_mode(drive); + speed = ide_dma_speed(drive, pdc202xx_ratemask(drive)); if (!(speed)) { /* restore original pci-config space */ @@ -441,7 +478,7 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) hwif->drives[0].autotune = hwif->drives[1].autotune = 1; - hwif->ultra_mask = hwif->cds->udma_mask; + hwif->ultra_mask = 0x3f; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; hwif->atapi_dma = 1; @@ -463,6 +500,10 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif) if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; +#if PDC202_DEBUG_CABLE + printk(KERN_DEBUG "%s: %s-pin cable\n", + hwif->name, hwif->udma_four ? "80" : "40"); +#endif /* PDC202_DEBUG_CABLE */ } static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase) @@ -546,7 +587,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 16, - .udma_mask = 0x07, /* udma0-2 */ },{ /* 1 */ .name = "PDC20262", .init_setup = init_setup_pdc202ata4, @@ -557,7 +597,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 48, - .udma_mask = 0x1f, /* udma0-4 */ },{ /* 2 */ .name = "PDC20263", .init_setup = init_setup_pdc202ata4, @@ -568,7 +607,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 48, - .udma_mask = 0x1f, /* udma0-4 */ },{ /* 3 */ .name = "PDC20265", .init_setup = init_setup_pdc20265, @@ -579,7 +617,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 48, - .udma_mask = 0x3f, /* udma0-5 */ },{ /* 4 */ .name = "PDC20267", .init_setup = init_setup_pdc202xx, @@ -590,7 +627,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = { .autodma = AUTODMA, .bootable = OFF_BOARD, .extra = 48, - .udma_mask = 0x3f, /* udma0-5 */ } }; diff --git a/trunk/drivers/ide/pci/piix.c b/trunk/drivers/ide/pci/piix.c index 8b219dd63024..061d300ab8be 100644 --- a/trunk/drivers/ide/pci/piix.c +++ b/trunk/drivers/ide/pci/piix.c @@ -105,6 +105,68 @@ static int no_piix_dma; +/** + * piix_ratemask - compute rate mask for PIIX IDE + * @drive: IDE drive to compute for + * + * Returns the available modes for the PIIX IDE controller. + */ + +static u8 piix_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 mode; + + switch(dev->device) { + case PCI_DEVICE_ID_INTEL_82801EB_1: + mode = 3; + break; + /* UDMA 100 capable */ + case PCI_DEVICE_ID_INTEL_82801BA_8: + case PCI_DEVICE_ID_INTEL_82801BA_9: + case PCI_DEVICE_ID_INTEL_82801CA_10: + case PCI_DEVICE_ID_INTEL_82801CA_11: + case PCI_DEVICE_ID_INTEL_82801E_11: + case PCI_DEVICE_ID_INTEL_82801DB_1: + case PCI_DEVICE_ID_INTEL_82801DB_10: + case PCI_DEVICE_ID_INTEL_82801DB_11: + case PCI_DEVICE_ID_INTEL_82801EB_11: + case PCI_DEVICE_ID_INTEL_ESB_2: + case PCI_DEVICE_ID_INTEL_ICH6_19: + case PCI_DEVICE_ID_INTEL_ICH7_21: + case PCI_DEVICE_ID_INTEL_ESB2_18: + case PCI_DEVICE_ID_INTEL_ICH8_6: + mode = 3; + break; + /* UDMA 66 capable */ + case PCI_DEVICE_ID_INTEL_82801AA_1: + case PCI_DEVICE_ID_INTEL_82372FB_1: + mode = 2; + break; + /* UDMA 33 capable */ + case PCI_DEVICE_ID_INTEL_82371AB: + case PCI_DEVICE_ID_INTEL_82443MX_1: + case PCI_DEVICE_ID_INTEL_82451NX: + case PCI_DEVICE_ID_INTEL_82801AB_1: + return 1; + /* Non UDMA capable (MWDMA2) */ + case PCI_DEVICE_ID_INTEL_82371SB_1: + case PCI_DEVICE_ID_INTEL_82371FB_1: + case PCI_DEVICE_ID_INTEL_82371FB_0: + case PCI_DEVICE_ID_INTEL_82371MX: + default: + return 0; + } + + /* + * If we are UDMA66 capable fall back to UDMA33 + * if the drive cannot see an 80pin cable. + */ + if (!eighty_ninty_three(drive)) + mode = min_t(u8, mode, 1); + return mode; +} + /** * piix_dma_2_pio - return the PIO mode matching DMA * @xfer_rate: transfer speed @@ -239,7 +301,7 @@ static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 maslave = hwif->channel ? 0x42 : 0x40; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(piix_ratemask(drive), xferspeed); int a_speed = 3 << (drive->dn * 4); int u_flag = 1 << drive->dn; int v_flag = 0x01 << drive->dn; @@ -303,6 +365,30 @@ static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed) return ide_config_drive_speed(drive, speed); } +/** + * piix_config_drive_for_dma - configure drive for DMA + * @drive: IDE drive to configure + * + * Set up a PIIX interface channel for the best available speed. + * We prefer UDMA if it is available and then MWDMA. If DMA is + * not available we switch to PIO and return 0. + */ + +static int piix_config_drive_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, piix_ratemask(drive)); + + /* + * If no DMA speed was available or the chipset has DMA bugs + * then disable DMA and use PIO + */ + if (!speed) + return 0; + + (void) piix_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + /** * piix_config_drive_xfer_rate - set up an IDE device * @drive: IDE drive to configure @@ -315,7 +401,7 @@ static int piix_config_drive_xfer_rate (ide_drive_t *drive) { drive->init_speed = 0; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && piix_config_drive_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) @@ -438,14 +524,26 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) hwif->ide_dma_clear_irq = &piix_dma_clear_irq; hwif->atapi_dma = 1; - - hwif->ultra_mask = hwif->cds->udma_mask; + hwif->ultra_mask = 0x3f; hwif->mwdma_mask = 0x06; hwif->swdma_mask = 0x04; - if (hwif->ultra_mask & 0x78) { - if (!hwif->udma_four) - hwif->udma_four = piix_cable_detect(hwif); + switch(hwif->pci_dev->device) { + case PCI_DEVICE_ID_INTEL_82371FB_0: + case PCI_DEVICE_ID_INTEL_82371FB_1: + case PCI_DEVICE_ID_INTEL_82371SB_1: + hwif->ultra_mask = 0x80; + break; + case PCI_DEVICE_ID_INTEL_82371AB: + case PCI_DEVICE_ID_INTEL_82443MX_1: + case PCI_DEVICE_ID_INTEL_82451NX: + case PCI_DEVICE_ID_INTEL_82801AB_1: + hwif->ultra_mask = 0x07; + break; + default: + if (!hwif->udma_four) + hwif->udma_four = piix_cable_detect(hwif); + break; } if (no_piix_dma) @@ -459,7 +557,7 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) hwif->drives[0].autodma = hwif->autodma; } -#define DECLARE_PIIX_DEV(name_str, udma) \ +#define DECLARE_PIIX_DEV(name_str) \ { \ .name = name_str, \ .init_chipset = init_chipset_piix, \ @@ -468,12 +566,11 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) .autodma = AUTODMA, \ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ .bootable = ON_BOARD, \ - .udma_mask = udma, \ } static ide_pci_device_t piix_pci_info[] __devinitdata = { - /* 0 */ DECLARE_PIIX_DEV("PIIXa", 0x00), /* no udma */ - /* 1 */ DECLARE_PIIX_DEV("PIIXb", 0x00), /* no udma */ + /* 0 */ DECLARE_PIIX_DEV("PIIXa"), + /* 1 */ DECLARE_PIIX_DEV("PIIXb"), /* 2 */ { /* @@ -490,28 +587,28 @@ static ide_pci_device_t piix_pci_info[] __devinitdata = { .flags = IDEPCI_FLAG_ISA_PORTS }, - /* 3 */ DECLARE_PIIX_DEV("PIIX3", 0x00), /* no udma */ - /* 4 */ DECLARE_PIIX_DEV("PIIX4", 0x07), /* udma0-2 */ - /* 5 */ DECLARE_PIIX_DEV("ICH0", 0x07), /* udma0-2 */ - /* 6 */ DECLARE_PIIX_DEV("PIIX4", 0x07), /* udma0-2 */ - /* 7 */ DECLARE_PIIX_DEV("ICH", 0x1f), /* udma0-4 */ - /* 8 */ DECLARE_PIIX_DEV("PIIX4", 0x1f), /* udma0-4 */ - /* 9 */ DECLARE_PIIX_DEV("PIIX4", 0x07), /* udma0-2 */ - /* 10 */ DECLARE_PIIX_DEV("ICH2", 0x3f), /* udma0-5 */ - /* 11 */ DECLARE_PIIX_DEV("ICH2M", 0x3f), /* udma0-5 */ - /* 12 */ DECLARE_PIIX_DEV("ICH3M", 0x3f), /* udma0-5 */ - /* 13 */ DECLARE_PIIX_DEV("ICH3", 0x3f), /* udma0-5 */ - /* 14 */ DECLARE_PIIX_DEV("ICH4", 0x3f), /* udma0-5 */ - /* 15 */ DECLARE_PIIX_DEV("ICH5", 0x3f), /* udma0-5 */ - /* 16 */ DECLARE_PIIX_DEV("C-ICH", 0x3f), /* udma0-5 */ - /* 17 */ DECLARE_PIIX_DEV("ICH4", 0x3f), /* udma0-5 */ - /* 18 */ DECLARE_PIIX_DEV("ICH5-SATA", 0x3f), /* udma0-5 */ - /* 19 */ DECLARE_PIIX_DEV("ICH5", 0x3f), /* udma0-5 */ - /* 20 */ DECLARE_PIIX_DEV("ICH6", 0x3f), /* udma0-5 */ - /* 21 */ DECLARE_PIIX_DEV("ICH7", 0x3f), /* udma0-5 */ - /* 22 */ DECLARE_PIIX_DEV("ICH4", 0x3f), /* udma0-5 */ - /* 23 */ DECLARE_PIIX_DEV("ESB2", 0x3f), /* udma0-5 */ - /* 24 */ DECLARE_PIIX_DEV("ICH8M", 0x3f), /* udma0-5 */ + /* 3 */ DECLARE_PIIX_DEV("PIIX3"), + /* 4 */ DECLARE_PIIX_DEV("PIIX4"), + /* 5 */ DECLARE_PIIX_DEV("ICH0"), + /* 6 */ DECLARE_PIIX_DEV("PIIX4"), + /* 7 */ DECLARE_PIIX_DEV("ICH"), + /* 8 */ DECLARE_PIIX_DEV("PIIX4"), + /* 9 */ DECLARE_PIIX_DEV("PIIX4"), + /* 10 */ DECLARE_PIIX_DEV("ICH2"), + /* 11 */ DECLARE_PIIX_DEV("ICH2M"), + /* 12 */ DECLARE_PIIX_DEV("ICH3M"), + /* 13 */ DECLARE_PIIX_DEV("ICH3"), + /* 14 */ DECLARE_PIIX_DEV("ICH4"), + /* 15 */ DECLARE_PIIX_DEV("ICH5"), + /* 16 */ DECLARE_PIIX_DEV("C-ICH"), + /* 17 */ DECLARE_PIIX_DEV("ICH4"), + /* 18 */ DECLARE_PIIX_DEV("ICH5-SATA"), + /* 19 */ DECLARE_PIIX_DEV("ICH5"), + /* 20 */ DECLARE_PIIX_DEV("ICH6"), + /* 21 */ DECLARE_PIIX_DEV("ICH7"), + /* 22 */ DECLARE_PIIX_DEV("ICH4"), + /* 23 */ DECLARE_PIIX_DEV("ESB2"), + /* 24 */ DECLARE_PIIX_DEV("ICH8M"), }; /** diff --git a/trunk/drivers/ide/pci/scc_pata.c b/trunk/drivers/ide/pci/scc_pata.c index cbf936325355..f84bf791f72e 100644 --- a/trunk/drivers/ide/pci/scc_pata.c +++ b/trunk/drivers/ide/pci/scc_pata.c @@ -189,6 +189,23 @@ scc_ide_outsl(unsigned long port, void *addr, u32 count) } } +/** + * scc_ratemask - Compute available modes + * @drive: IDE drive + * + * Compute the available speeds for the devices on the interface. + * Enforce UDMA33 as a limit if there is no 80pin cable present. + */ + +static u8 scc_ratemask(ide_drive_t *drive) +{ + u8 mode = 4; + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + /** * scc_tuneproc - tune a drive PIO mode * @drive: drive to tune @@ -256,7 +273,7 @@ static void scc_tuneproc(ide_drive_t *drive, byte mode_wanted) static int scc_tune_chipset(ide_drive_t *drive, byte xferspeed) { ide_hwif_t *hwif = HWIF(drive); - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(scc_ratemask(drive), xferspeed); struct scc_ports *ports = ide_get_hwifdata(hwif); unsigned long ctl_base = ports->ctl; unsigned long cckctrl_port = ctl_base + 0xff0; @@ -330,7 +347,7 @@ static int scc_tune_chipset(ide_drive_t *drive, byte xferspeed) static int scc_config_chipset_for_dma(ide_drive_t *drive) { - u8 speed = ide_max_dma_mode(drive); + u8 speed = ide_dma_speed(drive, scc_ratemask(drive)); if (!speed) return 0; diff --git a/trunk/drivers/ide/pci/serverworks.c b/trunk/drivers/ide/pci/serverworks.c index 2fa6d92d16cc..dbcd37a0c652 100644 --- a/trunk/drivers/ide/pci/serverworks.c +++ b/trunk/drivers/ide/pci/serverworks.c @@ -65,16 +65,16 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list) return 0; } -static u8 svwks_udma_filter(ide_drive_t *drive) +static u8 svwks_ratemask (ide_drive_t *drive) { struct pci_dev *dev = HWIF(drive)->pci_dev; - u8 mask = 0; + u8 mode = 0; if (!svwks_revision) pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision); if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) - return 0x1f; + return 2; if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { u32 reg = 0; if (isa_dev) @@ -86,31 +86,25 @@ static u8 svwks_udma_filter(ide_drive_t *drive) if(drive->media == ide_disk) return 0; /* Check the OSB4 DMA33 enable bit */ - return ((reg & 0x00004000) == 0x00004000) ? 0x07 : 0; + return ((reg & 0x00004000) == 0x00004000) ? 1 : 0; } else if (svwks_revision < SVWKS_CSB5_REVISION_NEW) { - return 0x07; + return 1; } else if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) { - u8 btr = 0, mode; + u8 btr = 0; pci_read_config_byte(dev, 0x5A, &btr); mode = btr & 0x3; - + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); /* If someone decides to do UDMA133 on CSB5 the same issue will bite so be inclusive */ if (mode > 2 && check_in_drive_lists(drive, svwks_bad_ata100)) mode = 2; - - switch(mode) { - case 2: mask = 0x1f; break; - case 1: mask = 0x07; break; - default: mask = 0x00; break; - } } if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) && (!(PCI_FUNC(dev->devfn) & 1))) - mask = 0x1f; - - return mask; + mode = 2; + return mode; } static u8 svwks_csb_check (struct pci_dev *dev) @@ -147,7 +141,7 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) if (xferspeed == 255) /* PIO auto-tuning */ speed = XFER_PIO_0 + pio; else - speed = ide_rate_filter(drive, xferspeed); + speed = ide_rate_filter(svwks_ratemask(drive), xferspeed); /* If we are about to put a disk into UDMA mode we screwed up. Our code assumes we never _ever_ do this on an OSB4 */ @@ -310,7 +304,7 @@ static void svwks_tune_drive (ide_drive_t *drive, u8 pio) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_max_dma_mode(drive); + u8 speed = ide_dma_speed(drive, svwks_ratemask(drive)); if (!(speed)) speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); @@ -506,7 +500,6 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif) hwif->tuneproc = &svwks_tune_drive; hwif->speedproc = &svwks_tune_chipset; - hwif->udma_filter = &svwks_udma_filter; hwif->atapi_dma = 1; diff --git a/trunk/drivers/ide/pci/sgiioc4.c b/trunk/drivers/ide/pci/sgiioc4.c index d3185e29a38e..fd09b295a69d 100644 --- a/trunk/drivers/ide/pci/sgiioc4.c +++ b/trunk/drivers/ide/pci/sgiioc4.c @@ -692,7 +692,7 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) return -EIO; /* Create /proc/ide entries */ - ide_proc_register_port(hwif); + create_proc_ide_interfaces(); return 0; } diff --git a/trunk/drivers/ide/pci/siimage.c b/trunk/drivers/ide/pci/siimage.c index d09e74c2996e..c0188de3cc66 100644 --- a/trunk/drivers/ide/pci/siimage.c +++ b/trunk/drivers/ide/pci/siimage.c @@ -122,41 +122,45 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r) } /** - * sil_udma_filter - compute UDMA mask - * @drive: IDE device - * - * Compute the available UDMA speeds for the device on the interface. + * siimage_ratemask - Compute available modes + * @drive: IDE drive * + * Compute the available speeds for the devices on the interface. * For the CMD680 this depends on the clocking mode (scsc), for the - * SI3112 SATA controller life is a bit simpler. + * SI3312 SATA controller life is a bit simpler. Enforce UDMA33 + * as a limit if there is no 80pin cable present. */ - -static u8 sil_udma_filter(ide_drive_t *drive) + +static byte siimage_ratemask (ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = HWIF(drive); + u8 mode = 0, scsc = 0; unsigned long base = (unsigned long) hwif->hwif_data; - u8 mask = 0, scsc = 0; if (hwif->mmio) scsc = hwif->INB(base + 0x4A); else pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc); - if (is_sata(hwif)) { - mask = strstr(drive->id->model, "Maxtor") ? 0x3f : 0x7f; - goto out; + if(is_sata(hwif)) + { + if(strstr(drive->id->model, "Maxtor")) + return 3; + return 4; } - + if ((scsc & 0x30) == 0x10) /* 133 */ - mask = 0x7f; + mode = 4; else if ((scsc & 0x30) == 0x20) /* 2xPCI */ - mask = 0x7f; + mode = 4; else if ((scsc & 0x30) == 0x00) /* 100 */ - mask = 0x3f; + mode = 3; else /* Disabled ? */ BUG(); -out: - return mask; + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; } /** @@ -302,7 +306,7 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed) ide_hwif_t *hwif = HWIF(drive); u16 ultra = 0, multi = 0; u8 mode = 0, unit = drive->select.b.unit; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(siimage_ratemask(drive), xferspeed); unsigned long base = (unsigned long)hwif->hwif_data; u8 scsc = 0, addr_mask = ((hwif->channel) ? ((hwif->mmio) ? 0xF4 : 0x84) : @@ -385,7 +389,7 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_max_dma_mode(drive); + u8 speed = ide_dma_speed(drive, siimage_ratemask(drive)); if (!speed) return 0; @@ -827,7 +831,7 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif) /* * Now set up the hw. We have to do this ourselves as - * the MMIO layout isnt the same as the standard port + * the MMIO layout isnt the same as the the standard port * based I/O */ @@ -985,7 +989,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) hwif->tuneproc = &siimage_tuneproc; hwif->reset_poll = &siimage_reset_poll; hwif->pre_reset = &siimage_pre_reset; - hwif->udma_filter = &sil_udma_filter; if(is_sata(hwif)) { static int first = 1; diff --git a/trunk/drivers/ide/pci/sis5513.c b/trunk/drivers/ide/pci/sis5513.c index 2bde1b92784a..2ba0669f36a1 100644 --- a/trunk/drivers/ide/pci/sis5513.c +++ b/trunk/drivers/ide/pci/sis5513.c @@ -191,7 +191,7 @@ static char* chipset_capability[] = { "ATA 133 (1st gen)", "ATA 133 (2nd gen)" }; -#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_IDE_PROC_FS) +#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) #include #include @@ -426,7 +426,17 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) return len > count ? count : len; } -#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ +#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static u8 sis5513_ratemask (ide_drive_t *drive) +{ + u8 rates[] = { 0, 0, 1, 2, 3, 3, 4, 4 }; + u8 mode = rates[chipset_family]; + + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} /* * Configuration functions @@ -553,7 +563,7 @@ static int sis5513_tune_chipset (ide_drive_t *drive, u8 xferspeed) u8 drive_pci, reg, speed; u32 regdw; - speed = ide_rate_filter(drive, xferspeed); + speed = ide_rate_filter(sis5513_ratemask(drive), xferspeed); /* See config_art_rwp_pio for drive pci config registers */ drive_pci = 0x40; @@ -638,13 +648,32 @@ static void sis5513_tune_drive (ide_drive_t *drive, u8 pio) (void) config_chipset_for_pio(drive, pio); } +/* + * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four)) + */ +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, sis5513_ratemask(drive)); + +#ifdef DEBUG + printk("SIS5513: config_chipset_for_dma, drive %d, ultra %x\n", + drive->dn, drive->id->dma_ultra); +#endif + + if (!(speed)) + return 0; + + sis5513_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + static int sis5513_config_xfer_rate(ide_drive_t *drive) { config_art_rwp_pio(drive, 5); drive->init_speed = 0; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) @@ -797,7 +826,7 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c break; } -#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_IDE_PROC_FS) +#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) if (!sis_proc) { sis_proc = 1; bmide_dev = dev; @@ -829,8 +858,6 @@ static unsigned int __devinit ata66_sis5513 (ide_hwif_t *hwif) static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif) { - u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f }; - hwif->autodma = 0; if (!hwif->irq) @@ -846,8 +873,7 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif) } hwif->atapi_dma = 1; - - hwif->ultra_mask = udma_rates[chipset_family]; + hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; diff --git a/trunk/drivers/ide/pci/slc90e66.c b/trunk/drivers/ide/pci/slc90e66.c index c40f291f91e0..852ccb36da1d 100644 --- a/trunk/drivers/ide/pci/slc90e66.c +++ b/trunk/drivers/ide/pci/slc90e66.c @@ -21,6 +21,15 @@ #include +static u8 slc90e66_ratemask (ide_drive_t *drive) +{ + u8 mode = 2; + + if (!eighty_ninty_three(drive)) + mode = min_t(u8, mode, 1); + return mode; +} + static u8 slc90e66_dma_2_pio (u8 xfer_rate) { switch(xfer_rate) { case XFER_UDMA_4: @@ -113,7 +122,7 @@ static int slc90e66_tune_chipset (ide_drive_t *drive, u8 xferspeed) ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 maslave = hwif->channel ? 0x42 : 0x40; - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(slc90e66_ratemask(drive), xferspeed); int sitre = 0, a_speed = 7 << (drive->dn * 4); int u_speed = 0, u_flag = 1 << drive->dn; u16 reg4042, reg44, reg48, reg4a; @@ -160,11 +169,22 @@ static int slc90e66_tune_chipset (ide_drive_t *drive, u8 xferspeed) return ide_config_drive_speed(drive, speed); } +static int slc90e66_config_drive_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, slc90e66_ratemask(drive)); + + if (!speed) + return 0; + + (void) slc90e66_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive) { drive->init_speed = 0; - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) diff --git a/trunk/drivers/ide/pci/tc86c001.c b/trunk/drivers/ide/pci/tc86c001.c index cee619bb2eaf..0b6d81d6ce48 100644 --- a/trunk/drivers/ide/pci/tc86c001.c +++ b/trunk/drivers/ide/pci/tc86c001.c @@ -13,13 +13,18 @@ #include #include +static inline u8 tc86c001_ratemask(ide_drive_t *drive) +{ + return eighty_ninty_three(drive) ? 2 : 1; +} + static int tc86c001_tune_chipset(ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = HWIF(drive); unsigned long scr_port = hwif->config_data + (drive->dn ? 0x02 : 0x00); u16 mode, scr = hwif->INW(scr_port); - speed = ide_rate_filter(drive, speed); + speed = ide_rate_filter(tc86c001_ratemask(drive), speed); switch (speed) { case XFER_UDMA_4: mode = 0x00c0; break; @@ -167,9 +172,20 @@ static int tc86c001_busproc(ide_drive_t *drive, int state) return 0; } +static int config_chipset_for_dma(ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, tc86c001_ratemask(drive)); + + if (!speed) + return 0; + + (void) tc86c001_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + static int tc86c001_config_drive_xfer_rate(ide_drive_t *drive) { - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) return 0; if (ide_use_fast_pio(drive)) diff --git a/trunk/drivers/ide/pci/triflex.c b/trunk/drivers/ide/pci/triflex.c index 35e8c612638f..5e06179c3469 100644 --- a/trunk/drivers/ide/pci/triflex.c +++ b/trunk/drivers/ide/pci/triflex.c @@ -48,7 +48,7 @@ static int triflex_tune_chipset(ide_drive_t *drive, u8 xferspeed) u16 timing = 0; u32 triflex_timings = 0; u8 unit = (drive->select.b.unit & 0x01); - u8 speed = ide_rate_filter(drive, xferspeed); + u8 speed = ide_rate_filter(0, xferspeed); pci_read_config_dword(dev, channel_offset, &triflex_timings); @@ -100,9 +100,20 @@ static void triflex_tune_drive(ide_drive_t *drive, u8 pio) (void) triflex_tune_chipset(drive, (XFER_PIO_0 + use_pio)); } +static int triflex_config_drive_for_dma(ide_drive_t *drive) +{ + int speed = ide_dma_speed(drive, 0); /* No ultra speeds */ + + if (!speed) + return 0; + + (void) triflex_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + static int triflex_config_drive_xfer_rate(ide_drive_t *drive) { - if (ide_tune_dma(drive)) + if (ide_use_dma(drive) && triflex_config_drive_for_dma(drive)) return 0; triflex_tune_drive(drive, 255); diff --git a/trunk/drivers/ide/ppc/pmac.c b/trunk/drivers/ide/ppc/pmac.c index 45fc36f0f219..a49ebe44babd 100644 --- a/trunk/drivers/ide/ppc/pmac.c +++ b/trunk/drivers/ide/ppc/pmac.c @@ -1276,8 +1276,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) /* We probe the hwif now */ probe_hwif_init(hwif); - ide_proc_register_port(hwif); - return 0; } diff --git a/trunk/drivers/ide/setup-pci.c b/trunk/drivers/ide/setup-pci.c index 67035ba4bf5e..118fb3205ca8 100644 --- a/trunk/drivers/ide/setup-pci.c +++ b/trunk/drivers/ide/setup-pci.c @@ -702,7 +702,6 @@ static int do_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d, int ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d) { - ide_hwif_t *hwif = NULL, *mate = NULL; ata_index_t index_list; int ret; @@ -711,19 +710,11 @@ int ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d) goto out; if ((index_list.b.low & 0xf0) != 0xf0) - hwif = &ide_hwifs[index_list.b.low]; + probe_hwif_init_with_fixup(&ide_hwifs[index_list.b.low], d->fixup); if ((index_list.b.high & 0xf0) != 0xf0) - mate = &ide_hwifs[index_list.b.high]; + probe_hwif_init_with_fixup(&ide_hwifs[index_list.b.high], d->fixup); - if (hwif) - probe_hwif_init_with_fixup(hwif, d->fixup); - if (mate) - probe_hwif_init_with_fixup(mate, d->fixup); - - if (hwif) - ide_proc_register_port(hwif); - if (mate) - ide_proc_register_port(mate); + create_proc_ide_interfaces(); out: return ret; } @@ -757,22 +748,13 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2, } } - for (i = 0; i < 2; i++) { - u8 idx[2] = { index_list[i].b.low, index_list[i].b.high }; - int j; - - for (j = 0; j < 2; j++) { - if ((idx[j] & 0xf0) != 0xf0) - ide_proc_register_port(ide_hwifs + idx[j]); - } - } + create_proc_ide_interfaces(); out: return ret; } EXPORT_SYMBOL_GPL(ide_setup_pci_devices); -#ifdef CONFIG_IDEPCI_PCIBUS_ORDER /* * Module interfaces */ @@ -879,4 +861,3 @@ void __init ide_scan_pcibus (int scan_direction) __pci_register_driver(d, d->driver.owner, d->driver.mod_name); } } -#endif diff --git a/trunk/drivers/ieee1394/Kconfig b/trunk/drivers/ieee1394/Kconfig index 8012b3b0ce75..61d7809a5a26 100644 --- a/trunk/drivers/ieee1394/Kconfig +++ b/trunk/drivers/ieee1394/Kconfig @@ -1,7 +1,4 @@ menu "IEEE 1394 (FireWire) support" - depends on PCI || BROKEN - -source "drivers/firewire/Kconfig" config IEEE1394 tristate "IEEE 1394 (FireWire) support" diff --git a/trunk/drivers/ieee1394/nodemgr.c b/trunk/drivers/ieee1394/nodemgr.c index 835937e38529..6a1a0572275e 100644 --- a/trunk/drivers/ieee1394/nodemgr.c +++ b/trunk/drivers/ieee1394/nodemgr.c @@ -1702,7 +1702,7 @@ static int nodemgr_host_thread(void *__hi) generation = get_hpsb_generation(host); /* If we get a reset before we are done waiting, then - * start the waiting over again */ + * start the the waiting over again */ if (generation != g) g = generation, i = 0; } diff --git a/trunk/drivers/infiniband/Kconfig b/trunk/drivers/infiniband/Kconfig index 994decc7bcf2..66b36de9fa6f 100644 --- a/trunk/drivers/infiniband/Kconfig +++ b/trunk/drivers/infiniband/Kconfig @@ -1,5 +1,4 @@ menu "InfiniBand support" - depends on HAS_IOMEM config INFINIBAND depends on PCI || BROKEN @@ -30,11 +29,6 @@ config INFINIBAND_USER_ACCESS libibverbs, libibcm and a hardware driver library from . -config INFINIBAND_USER_MEM - bool - depends on INFINIBAND_USER_ACCESS != n - default y - config INFINIBAND_ADDR_TRANS bool depends on INFINIBAND && INET @@ -46,8 +40,6 @@ source "drivers/infiniband/hw/ehca/Kconfig" source "drivers/infiniband/hw/amso1100/Kconfig" source "drivers/infiniband/hw/cxgb3/Kconfig" -source "drivers/infiniband/hw/mlx4/Kconfig" - source "drivers/infiniband/ulp/ipoib/Kconfig" source "drivers/infiniband/ulp/srp/Kconfig" diff --git a/trunk/drivers/infiniband/Makefile b/trunk/drivers/infiniband/Makefile index 75f325e40b54..da2066c4f22c 100644 --- a/trunk/drivers/infiniband/Makefile +++ b/trunk/drivers/infiniband/Makefile @@ -4,7 +4,6 @@ obj-$(CONFIG_INFINIBAND_IPATH) += hw/ipath/ obj-$(CONFIG_INFINIBAND_EHCA) += hw/ehca/ obj-$(CONFIG_INFINIBAND_AMSO1100) += hw/amso1100/ obj-$(CONFIG_INFINIBAND_CXGB3) += hw/cxgb3/ -obj-$(CONFIG_MLX4_INFINIBAND) += hw/mlx4/ obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/ obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/ obj-$(CONFIG_INFINIBAND_ISER) += ulp/iser/ diff --git a/trunk/drivers/infiniband/core/Makefile b/trunk/drivers/infiniband/core/Makefile index cb1ab3ea4998..189e5d4b9b17 100644 --- a/trunk/drivers/infiniband/core/Makefile +++ b/trunk/drivers/infiniband/core/Makefile @@ -9,7 +9,6 @@ obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o \ ib_core-y := packer.o ud_header.o verbs.o sysfs.o \ device.o fmr_pool.o cache.o -ib_core-$(CONFIG_INFINIBAND_USER_MEM) += umem.o ib_mad-y := mad.o smi.o agent.o mad_rmpp.o @@ -29,4 +28,5 @@ ib_umad-y := user_mad.o ib_ucm-y := ucm.o -ib_uverbs-y := uverbs_main.o uverbs_cmd.o uverbs_marshall.o +ib_uverbs-y := uverbs_main.o uverbs_cmd.o uverbs_mem.o \ + uverbs_marshall.o diff --git a/trunk/drivers/infiniband/core/device.c b/trunk/drivers/infiniband/core/device.c index 592c90aa3183..7fabb425b033 100644 --- a/trunk/drivers/infiniband/core/device.c +++ b/trunk/drivers/infiniband/core/device.c @@ -613,8 +613,6 @@ static void __exit ib_core_cleanup(void) { ib_cache_cleanup(); ib_sysfs_cleanup(); - /* Make sure that any pending umem accounting work is done. */ - flush_scheduled_work(); } module_init(ib_core_init); diff --git a/trunk/drivers/infiniband/core/uverbs.h b/trunk/drivers/infiniband/core/uverbs.h index c33546f9e961..102a59c033ff 100644 --- a/trunk/drivers/infiniband/core/uverbs.h +++ b/trunk/drivers/infiniband/core/uverbs.h @@ -45,7 +45,6 @@ #include #include -#include #include /* @@ -164,6 +163,11 @@ void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr); void ib_uverbs_event_handler(struct ib_event_handler *handler, struct ib_event *event); +int ib_umem_get(struct ib_device *dev, struct ib_umem *mem, + void *addr, size_t size, int write); +void ib_umem_release(struct ib_device *dev, struct ib_umem *umem); +void ib_umem_release_on_close(struct ib_device *dev, struct ib_umem *umem); + #define IB_UVERBS_DECLARE_CMD(name) \ ssize_t ib_uverbs_##name(struct ib_uverbs_file *file, \ const char __user *buf, int in_len, \ diff --git a/trunk/drivers/infiniband/core/uverbs_cmd.c b/trunk/drivers/infiniband/core/uverbs_cmd.c index 01d70084aebe..bab66769be14 100644 --- a/trunk/drivers/infiniband/core/uverbs_cmd.c +++ b/trunk/drivers/infiniband/core/uverbs_cmd.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005, 2006, 2007 Cisco Systems. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. * Copyright (c) 2005 PathScale, Inc. All rights reserved. * Copyright (c) 2006 Mellanox Technologies. All rights reserved. * @@ -295,7 +295,6 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, INIT_LIST_HEAD(&ucontext->qp_list); INIT_LIST_HEAD(&ucontext->srq_list); INIT_LIST_HEAD(&ucontext->ah_list); - ucontext->closing = 0; resp.num_comp_vectors = file->device->num_comp_vectors; @@ -574,7 +573,7 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, struct ib_uverbs_reg_mr cmd; struct ib_uverbs_reg_mr_resp resp; struct ib_udata udata; - struct ib_uobject *uobj; + struct ib_umem_object *obj; struct ib_pd *pd; struct ib_mr *mr; int ret; @@ -600,21 +599,35 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, !(cmd.access_flags & IB_ACCESS_LOCAL_WRITE)) return -EINVAL; - uobj = kmalloc(sizeof *uobj, GFP_KERNEL); - if (!uobj) + obj = kmalloc(sizeof *obj, GFP_KERNEL); + if (!obj) return -ENOMEM; - init_uobj(uobj, 0, file->ucontext, &mr_lock_key); - down_write(&uobj->mutex); + init_uobj(&obj->uobject, 0, file->ucontext, &mr_lock_key); + down_write(&obj->uobject.mutex); + + /* + * We ask for writable memory if any access flags other than + * "remote read" are set. "Local write" and "remote write" + * obviously require write access. "Remote atomic" can do + * things like fetch and add, which will modify memory, and + * "MW bind" can change permissions by binding a window. + */ + ret = ib_umem_get(file->device->ib_dev, &obj->umem, + (void *) (unsigned long) cmd.start, cmd.length, + !!(cmd.access_flags & ~IB_ACCESS_REMOTE_READ)); + if (ret) + goto err_free; + + obj->umem.virt_base = cmd.hca_va; pd = idr_read_pd(cmd.pd_handle, file->ucontext); if (!pd) { ret = -EINVAL; - goto err_free; + goto err_release; } - mr = pd->device->reg_user_mr(pd, cmd.start, cmd.length, cmd.hca_va, - cmd.access_flags, &udata); + mr = pd->device->reg_user_mr(pd, &obj->umem, cmd.access_flags, &udata); if (IS_ERR(mr)) { ret = PTR_ERR(mr); goto err_put; @@ -622,19 +635,19 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, mr->device = pd->device; mr->pd = pd; - mr->uobject = uobj; + mr->uobject = &obj->uobject; atomic_inc(&pd->usecnt); atomic_set(&mr->usecnt, 0); - uobj->object = mr; - ret = idr_add_uobj(&ib_uverbs_mr_idr, uobj); + obj->uobject.object = mr; + ret = idr_add_uobj(&ib_uverbs_mr_idr, &obj->uobject); if (ret) goto err_unreg; memset(&resp, 0, sizeof resp); resp.lkey = mr->lkey; resp.rkey = mr->rkey; - resp.mr_handle = uobj->id; + resp.mr_handle = obj->uobject.id; if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { @@ -645,17 +658,17 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, put_pd_read(pd); mutex_lock(&file->mutex); - list_add_tail(&uobj->list, &file->ucontext->mr_list); + list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); mutex_unlock(&file->mutex); - uobj->live = 1; + obj->uobject.live = 1; - up_write(&uobj->mutex); + up_write(&obj->uobject.mutex); return in_len; err_copy: - idr_remove_uobj(&ib_uverbs_mr_idr, uobj); + idr_remove_uobj(&ib_uverbs_mr_idr, &obj->uobject); err_unreg: ib_dereg_mr(mr); @@ -663,8 +676,11 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, err_put: put_pd_read(pd); +err_release: + ib_umem_release(file->device->ib_dev, &obj->umem); + err_free: - put_uobj_write(uobj); + put_uobj_write(&obj->uobject); return ret; } @@ -675,6 +691,7 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, struct ib_uverbs_dereg_mr cmd; struct ib_mr *mr; struct ib_uobject *uobj; + struct ib_umem_object *memobj; int ret = -EINVAL; if (copy_from_user(&cmd, buf, sizeof cmd)) @@ -684,7 +701,8 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, if (!uobj) return -EINVAL; - mr = uobj->object; + memobj = container_of(uobj, struct ib_umem_object, uobject); + mr = uobj->object; ret = ib_dereg_mr(mr); if (!ret) @@ -701,6 +719,8 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, list_del(&uobj->list); mutex_unlock(&file->mutex); + ib_umem_release(file->device->ib_dev, &memobj->umem); + put_uobj(uobj); return in_len; diff --git a/trunk/drivers/infiniband/core/uverbs_main.c b/trunk/drivers/infiniband/core/uverbs_main.c index 14d7ccd89195..d44e54799651 100644 --- a/trunk/drivers/infiniband/core/uverbs_main.c +++ b/trunk/drivers/infiniband/core/uverbs_main.c @@ -183,8 +183,6 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, if (!context) return 0; - context->closing = 1; - list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) { struct ib_ah *ah = uobj->object; @@ -232,10 +230,16 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) { struct ib_mr *mr = uobj->object; + struct ib_device *mrdev = mr->device; + struct ib_umem_object *memobj; idr_remove_uobj(&ib_uverbs_mr_idr, uobj); ib_dereg_mr(mr); - kfree(uobj); + + memobj = container_of(uobj, struct ib_umem_object, uobject); + ib_umem_release_on_close(mrdev, &memobj->umem); + + kfree(memobj); } list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) { @@ -902,6 +906,7 @@ static void __exit ib_uverbs_cleanup(void) unregister_filesystem(&uverbs_event_fs); class_destroy(uverbs_class); unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES); + flush_scheduled_work(); idr_destroy(&ib_uverbs_pd_idr); idr_destroy(&ib_uverbs_mr_idr); idr_destroy(&ib_uverbs_mw_idr); diff --git a/trunk/drivers/infiniband/core/umem.c b/trunk/drivers/infiniband/core/uverbs_mem.c similarity index 59% rename from trunk/drivers/infiniband/core/umem.c rename to trunk/drivers/infiniband/core/uverbs_mem.c index f32ca5fbb26b..c95fe952abd5 100644 --- a/trunk/drivers/infiniband/core/umem.c +++ b/trunk/drivers/infiniband/core/uverbs_mem.c @@ -39,6 +39,13 @@ #include "uverbs.h" +struct ib_umem_account_work { + struct work_struct work; + struct mm_struct *mm; + unsigned long diff; +}; + + static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int dirty) { struct ib_umem_chunk *chunk, *tmp; @@ -57,56 +64,35 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d } } -/** - * ib_umem_get - Pin and DMA map userspace memory. - * @context: userspace context to pin memory for - * @addr: userspace virtual address to start at - * @size: length of region to pin - * @access: IB_ACCESS_xxx flags for memory being pinned - */ -struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, - size_t size, int access) +int ib_umem_get(struct ib_device *dev, struct ib_umem *mem, + void *addr, size_t size, int write) { - struct ib_umem *umem; struct page **page_list; struct ib_umem_chunk *chunk; unsigned long locked; unsigned long lock_limit; unsigned long cur_base; unsigned long npages; - int ret; + int ret = 0; int off; int i; if (!can_do_mlock()) - return ERR_PTR(-EPERM); + return -EPERM; - umem = kmalloc(sizeof *umem, GFP_KERNEL); - if (!umem) - return ERR_PTR(-ENOMEM); - - umem->context = context; - umem->length = size; - umem->offset = addr & ~PAGE_MASK; - umem->page_size = PAGE_SIZE; - /* - * We ask for writable memory if any access flags other than - * "remote read" are set. "Local write" and "remote write" - * obviously require write access. "Remote atomic" can do - * things like fetch and add, which will modify memory, and - * "MW bind" can change permissions by binding a window. - */ - umem->writable = !!(access & ~IB_ACCESS_REMOTE_READ); + page_list = (struct page **) __get_free_page(GFP_KERNEL); + if (!page_list) + return -ENOMEM; - INIT_LIST_HEAD(&umem->chunk_list); + mem->user_base = (unsigned long) addr; + mem->length = size; + mem->offset = (unsigned long) addr & ~PAGE_MASK; + mem->page_size = PAGE_SIZE; + mem->writable = write; - page_list = (struct page **) __get_free_page(GFP_KERNEL); - if (!page_list) { - kfree(umem); - return ERR_PTR(-ENOMEM); - } + INIT_LIST_HEAD(&mem->chunk_list); - npages = PAGE_ALIGN(size + umem->offset) >> PAGE_SHIFT; + npages = PAGE_ALIGN(size + mem->offset) >> PAGE_SHIFT; down_write(¤t->mm->mmap_sem); @@ -118,13 +104,13 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, goto out; } - cur_base = addr & PAGE_MASK; + cur_base = (unsigned long) addr & PAGE_MASK; while (npages) { ret = get_user_pages(current, current->mm, cur_base, min_t(int, npages, PAGE_SIZE / sizeof (struct page *)), - 1, !umem->writable, page_list, NULL); + 1, !write, page_list, NULL); if (ret < 0) goto out; @@ -150,7 +136,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, chunk->page_list[i].length = PAGE_SIZE; } - chunk->nmap = ib_dma_map_sg(context->device, + chunk->nmap = ib_dma_map_sg(dev, &chunk->page_list[0], chunk->nents, DMA_BIDIRECTIONAL); @@ -165,94 +151,75 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, ret -= chunk->nents; off += chunk->nents; - list_add_tail(&chunk->list, &umem->chunk_list); + list_add_tail(&chunk->list, &mem->chunk_list); } ret = 0; } out: - if (ret < 0) { - __ib_umem_release(context->device, umem, 0); - kfree(umem); - } else + if (ret < 0) + __ib_umem_release(dev, mem, 0); + else current->mm->locked_vm = locked; up_write(¤t->mm->mmap_sem); free_page((unsigned long) page_list); - return ret < 0 ? ERR_PTR(ret) : umem; + return ret; } -EXPORT_SYMBOL(ib_umem_get); -static void ib_umem_account(struct work_struct *work) +void ib_umem_release(struct ib_device *dev, struct ib_umem *umem) { - struct ib_umem *umem = container_of(work, struct ib_umem, work); + __ib_umem_release(dev, umem, 1); - down_write(&umem->mm->mmap_sem); - umem->mm->locked_vm -= umem->diff; - up_write(&umem->mm->mmap_sem); - mmput(umem->mm); - kfree(umem); + down_write(¤t->mm->mmap_sem); + current->mm->locked_vm -= + PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT; + up_write(¤t->mm->mmap_sem); } -/** - * ib_umem_release - release memory pinned with ib_umem_get - * @umem: umem struct to release - */ -void ib_umem_release(struct ib_umem *umem) +static void ib_umem_account(struct work_struct *_work) { - struct ib_ucontext *context = umem->context; + struct ib_umem_account_work *work = + container_of(_work, struct ib_umem_account_work, work); + + down_write(&work->mm->mmap_sem); + work->mm->locked_vm -= work->diff; + up_write(&work->mm->mmap_sem); + mmput(work->mm); + kfree(work); +} + +void ib_umem_release_on_close(struct ib_device *dev, struct ib_umem *umem) +{ + struct ib_umem_account_work *work; struct mm_struct *mm; - unsigned long diff; - __ib_umem_release(umem->context->device, umem, 1); + __ib_umem_release(dev, umem, 1); mm = get_task_mm(current); if (!mm) return; - diff = PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT; - /* * We may be called with the mm's mmap_sem already held. This * can happen when a userspace munmap() is the call that drops * the last reference to our file and calls our release * method. If there are memory regions to destroy, we'll end - * up here and not be able to take the mmap_sem. In that case - * we defer the vm_locked accounting to the system workqueue. + * up here and not be able to take the mmap_sem. Therefore we + * defer the vm_locked accounting to the system workqueue. */ - if (context->closing && !down_write_trylock(&mm->mmap_sem)) { - INIT_WORK(&umem->work, ib_umem_account); - umem->mm = mm; - umem->diff = diff; - schedule_work(&umem->work); + work = kmalloc(sizeof *work, GFP_KERNEL); + if (!work) { + mmput(mm); return; - } else - down_write(&mm->mmap_sem); - - current->mm->locked_vm -= diff; - up_write(&mm->mmap_sem); - mmput(mm); - kfree(umem); -} -EXPORT_SYMBOL(ib_umem_release); - -int ib_umem_page_count(struct ib_umem *umem) -{ - struct ib_umem_chunk *chunk; - int shift; - int i; - int n; - - shift = ilog2(umem->page_size); + } - n = 0; - list_for_each_entry(chunk, &umem->chunk_list, list) - for (i = 0; i < chunk->nmap; ++i) - n += sg_dma_len(&chunk->page_list[i]) >> shift; + INIT_WORK(&work->work, ib_umem_account); + work->mm = mm; + work->diff = PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT; - return n; + schedule_work(&work->work); } -EXPORT_SYMBOL(ib_umem_page_count); diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_provider.c b/trunk/drivers/infiniband/hw/amso1100/c2_provider.c index 997cf1530762..109166223c09 100644 --- a/trunk/drivers/infiniband/hw/amso1100/c2_provider.c +++ b/trunk/drivers/infiniband/hw/amso1100/c2_provider.c @@ -56,7 +56,6 @@ #include #include -#include #include #include "c2.h" #include "c2_provider.h" @@ -397,7 +396,6 @@ static struct ib_mr *c2_reg_phys_mr(struct ib_pd *ib_pd, } mr->pd = to_c2pd(ib_pd); - mr->umem = NULL; pr_debug("%s - page shift %d, pbl_depth %d, total_len %u, " "*iova_start %llx, first pa %llx, last pa %llx\n", __FUNCTION__, page_shift, pbl_depth, total_len, @@ -430,8 +428,8 @@ static struct ib_mr *c2_get_dma_mr(struct ib_pd *pd, int acc) return c2_reg_phys_mr(pd, &bl, 1, acc, &kva); } -static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt, int acc, struct ib_udata *udata) +static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, + int acc, struct ib_udata *udata) { u64 *pages; u64 kva = 0; @@ -443,23 +441,15 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, struct c2_mr *c2mr; pr_debug("%s:%u\n", __FUNCTION__, __LINE__); + shift = ffs(region->page_size) - 1; c2mr = kmalloc(sizeof(*c2mr), GFP_KERNEL); if (!c2mr) return ERR_PTR(-ENOMEM); c2mr->pd = c2pd; - c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc); - if (IS_ERR(c2mr->umem)) { - err = PTR_ERR(c2mr->umem); - kfree(c2mr); - return ERR_PTR(err); - } - - shift = ffs(c2mr->umem->page_size) - 1; - n = 0; - list_for_each_entry(chunk, &c2mr->umem->chunk_list, list) + list_for_each_entry(chunk, ®ion->chunk_list, list) n += chunk->nents; pages = kmalloc(n * sizeof(u64), GFP_KERNEL); @@ -469,34 +459,35 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, } i = 0; - list_for_each_entry(chunk, &c2mr->umem->chunk_list, list) { + list_for_each_entry(chunk, ®ion->chunk_list, list) { for (j = 0; j < chunk->nmap; ++j) { len = sg_dma_len(&chunk->page_list[j]) >> shift; for (k = 0; k < len; ++k) { pages[i++] = sg_dma_address(&chunk->page_list[j]) + - (c2mr->umem->page_size * k); + (region->page_size * k); } } } - kva = virt; + kva = (u64)region->virt_base; err = c2_nsmr_register_phys_kern(to_c2dev(pd->device), pages, - c2mr->umem->page_size, + region->page_size, i, - length, - c2mr->umem->offset, + region->length, + region->offset, &kva, c2_convert_access(acc), c2mr); kfree(pages); - if (err) - goto err; + if (err) { + kfree(c2mr); + return ERR_PTR(err); + } return &c2mr->ibmr; err: - ib_umem_release(c2mr->umem); kfree(c2mr); return ERR_PTR(err); } @@ -511,11 +502,8 @@ static int c2_dereg_mr(struct ib_mr *ib_mr) err = c2_stag_dealloc(to_c2dev(ib_mr->device), ib_mr->lkey); if (err) pr_debug("c2_stag_dealloc failed: %d\n", err); - else { - if (mr->umem) - ib_umem_release(mr->umem); + else kfree(mr); - } return err; } diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_provider.h b/trunk/drivers/infiniband/hw/amso1100/c2_provider.h index 1076df2ee96a..fc906223220f 100644 --- a/trunk/drivers/infiniband/hw/amso1100/c2_provider.h +++ b/trunk/drivers/infiniband/hw/amso1100/c2_provider.h @@ -73,7 +73,6 @@ struct c2_pd { struct c2_mr { struct ib_mr ibmr; struct c2_pd *pd; - struct ib_umem *umem; }; struct c2_av; diff --git a/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.c b/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.c index e7c2c3948037..a891493fd340 100644 --- a/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include "cxio_hal.h" @@ -444,8 +443,6 @@ static int iwch_dereg_mr(struct ib_mr *ib_mr) remove_handle(rhp, &rhp->mmidr, mmid); if (mhp->kva) kfree((void *) (unsigned long) mhp->kva); - if (mhp->umem) - ib_umem_release(mhp->umem); PDBG("%s mmid 0x%x ptr %p\n", __FUNCTION__, mmid, mhp); kfree(mhp); return 0; @@ -580,8 +577,8 @@ static int iwch_reregister_phys_mem(struct ib_mr *mr, } -static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt, int acc, struct ib_udata *udata) +static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, + int acc, struct ib_udata *udata) { __be64 *pages; int shift, n, len; @@ -594,6 +591,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, struct iwch_reg_user_mr_resp uresp; PDBG("%s ib_pd %p\n", __FUNCTION__, pd); + shift = ffs(region->page_size) - 1; php = to_iwch_pd(pd); rhp = php->rhp; @@ -601,17 +599,8 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, if (!mhp) return ERR_PTR(-ENOMEM); - mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc); - if (IS_ERR(mhp->umem)) { - err = PTR_ERR(mhp->umem); - kfree(mhp); - return ERR_PTR(err); - } - - shift = ffs(mhp->umem->page_size) - 1; - n = 0; - list_for_each_entry(chunk, &mhp->umem->chunk_list, list) + list_for_each_entry(chunk, ®ion->chunk_list, list) n += chunk->nents; pages = kmalloc(n * sizeof(u64), GFP_KERNEL); @@ -622,13 +611,13 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, i = n = 0; - list_for_each_entry(chunk, &mhp->umem->chunk_list, list) + list_for_each_entry(chunk, ®ion->chunk_list, list) for (j = 0; j < chunk->nmap; ++j) { len = sg_dma_len(&chunk->page_list[j]) >> shift; for (k = 0; k < len; ++k) { pages[i++] = cpu_to_be64(sg_dma_address( &chunk->page_list[j]) + - mhp->umem->page_size * k); + region->page_size * k); } } @@ -636,9 +625,9 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, mhp->attr.pdid = php->pdid; mhp->attr.zbva = 0; mhp->attr.perms = iwch_ib_to_tpt_access(acc); - mhp->attr.va_fbo = virt; + mhp->attr.va_fbo = region->virt_base; mhp->attr.page_size = shift - 12; - mhp->attr.len = (u32) length; + mhp->attr.len = (u32) region->length; mhp->attr.pbl_size = i; err = iwch_register_mem(rhp, php, mhp, shift, pages); kfree(pages); @@ -661,7 +650,6 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, return &mhp->ibmr; err: - ib_umem_release(mhp->umem); kfree(mhp); return ERR_PTR(err); } diff --git a/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.h b/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.h index 48833f3f3bd0..93bcc56756bd 100644 --- a/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.h +++ b/trunk/drivers/infiniband/hw/cxgb3/iwch_provider.h @@ -73,7 +73,6 @@ struct tpt_attributes { struct iwch_mr { struct ib_mr ibmr; - struct ib_umem *umem; struct iwch_dev *rhp; u64 kva; struct tpt_attributes attr; diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h b/trunk/drivers/infiniband/hw/ehca/ehca_classes.h index f64d42b08674..10fb8fbafa0c 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/trunk/drivers/infiniband/hw/ehca/ehca_classes.h @@ -176,7 +176,6 @@ struct ehca_mr { struct ib_mr ib_mr; /* must always be first in ehca_mr */ struct ib_fmr ib_fmr; /* must always be first in ehca_mr */ } ib; - struct ib_umem *umem; spinlock_t mrlock; enum ehca_mr_flag flags; diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_irq.c b/trunk/drivers/infiniband/hw/ehca/ehca_irq.c index 82dda2faf4d0..f284be1c9166 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_irq.c @@ -745,7 +745,6 @@ static int comp_pool_callback(struct notifier_block *nfb, switch (action) { case CPU_UP_PREPARE: - case CPU_UP_PREPARE_FROZEN: ehca_gen_dbg("CPU: %x (CPU_PREPARE)", cpu); if(!create_comp_task(pool, cpu)) { ehca_gen_err("Can't create comp_task for cpu: %x", cpu); @@ -753,29 +752,24 @@ static int comp_pool_callback(struct notifier_block *nfb, } break; case CPU_UP_CANCELED: - case CPU_UP_CANCELED_FROZEN: ehca_gen_dbg("CPU: %x (CPU_CANCELED)", cpu); cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); kthread_bind(cct->task, any_online_cpu(cpu_online_map)); destroy_comp_task(pool, cpu); break; case CPU_ONLINE: - case CPU_ONLINE_FROZEN: ehca_gen_dbg("CPU: %x (CPU_ONLINE)", cpu); cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); kthread_bind(cct->task, cpu); wake_up_process(cct->task); break; case CPU_DOWN_PREPARE: - case CPU_DOWN_PREPARE_FROZEN: ehca_gen_dbg("CPU: %x (CPU_DOWN_PREPARE)", cpu); break; case CPU_DOWN_FAILED: - case CPU_DOWN_FAILED_FROZEN: ehca_gen_dbg("CPU: %x (CPU_DOWN_FAILED)", cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: ehca_gen_dbg("CPU: %x (CPU_DEAD)", cpu); destroy_comp_task(pool, cpu); take_over_work(pool, cpu); diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h b/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h index 37e7fe0908cf..e14b029332c8 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h +++ b/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h @@ -78,7 +78,8 @@ struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd, int num_phys_buf, int mr_access_flags, u64 *iova_start); -struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt, +struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, + struct ib_umem *region, int mr_access_flags, struct ib_udata *udata); int ehca_rereg_phys_mr(struct ib_mr *mr, diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c b/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c index 84c5bb498563..d22ab563633f 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c @@ -39,8 +39,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include - #include #include "ehca_iverbs.h" @@ -240,8 +238,10 @@ struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd, /*----------------------------------------------------------------------*/ -struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt, - int mr_access_flags, struct ib_udata *udata) +struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, + struct ib_umem *region, + int mr_access_flags, + struct ib_udata *udata) { struct ib_mr *ib_mr; struct ehca_mr *e_mr; @@ -257,7 +257,11 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt ehca_gen_err("bad pd=%p", pd); return ERR_PTR(-EFAULT); } - + if (!region) { + ehca_err(pd->device, "bad input values: region=%p", region); + ib_mr = ERR_PTR(-EINVAL); + goto reg_user_mr_exit0; + } if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) && !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) || ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) && @@ -271,10 +275,17 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt ib_mr = ERR_PTR(-EINVAL); goto reg_user_mr_exit0; } + if (region->page_size != PAGE_SIZE) { + ehca_err(pd->device, "page size not supported, " + "region->page_size=%x", region->page_size); + ib_mr = ERR_PTR(-EINVAL); + goto reg_user_mr_exit0; + } - if (length == 0 || virt + length < virt) { + if ((region->length == 0) || + ((region->virt_base + region->length) < region->virt_base)) { ehca_err(pd->device, "bad input values: length=%lx " - "virt_base=%lx", length, virt); + "virt_base=%lx", region->length, region->virt_base); ib_mr = ERR_PTR(-EINVAL); goto reg_user_mr_exit0; } @@ -286,55 +297,40 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, u64 virt goto reg_user_mr_exit0; } - e_mr->umem = ib_umem_get(pd->uobject->context, start, length, - mr_access_flags); - if (IS_ERR(e_mr->umem)) { - ib_mr = (void *) e_mr->umem; - goto reg_user_mr_exit1; - } - - if (e_mr->umem->page_size != PAGE_SIZE) { - ehca_err(pd->device, "page size not supported, " - "e_mr->umem->page_size=%x", e_mr->umem->page_size); - ib_mr = ERR_PTR(-EINVAL); - goto reg_user_mr_exit2; - } - /* determine number of MR pages */ - num_pages_mr = (((virt % PAGE_SIZE) + length + PAGE_SIZE - 1) / - PAGE_SIZE); - num_pages_4k = (((virt % EHCA_PAGESIZE) + length + EHCA_PAGESIZE - 1) / - EHCA_PAGESIZE); + num_pages_mr = (((region->virt_base % PAGE_SIZE) + region->length + + PAGE_SIZE - 1) / PAGE_SIZE); + num_pages_4k = (((region->virt_base % EHCA_PAGESIZE) + region->length + + EHCA_PAGESIZE - 1) / EHCA_PAGESIZE); /* register MR on HCA */ pginfo.type = EHCA_MR_PGI_USER; pginfo.num_pages = num_pages_mr; pginfo.num_4k = num_pages_4k; - pginfo.region = e_mr->umem; - pginfo.next_4k = e_mr->umem->offset / EHCA_PAGESIZE; + pginfo.region = region; + pginfo.next_4k = region->offset / EHCA_PAGESIZE; pginfo.next_chunk = list_prepare_entry(pginfo.next_chunk, - (&e_mr->umem->chunk_list), + (®ion->chunk_list), list); - ret = ehca_reg_mr(shca, e_mr, (u64*) virt, length, mr_access_flags, e_pd, - &pginfo, &e_mr->ib.ib_mr.lkey, &e_mr->ib.ib_mr.rkey); + ret = ehca_reg_mr(shca, e_mr, (u64*)region->virt_base, + region->length, mr_access_flags, e_pd, &pginfo, + &e_mr->ib.ib_mr.lkey, &e_mr->ib.ib_mr.rkey); if (ret) { ib_mr = ERR_PTR(ret); - goto reg_user_mr_exit2; + goto reg_user_mr_exit1; } /* successful registration of all pages */ return &e_mr->ib.ib_mr; -reg_user_mr_exit2: - ib_umem_release(e_mr->umem); reg_user_mr_exit1: ehca_mr_delete(e_mr); reg_user_mr_exit0: if (IS_ERR(ib_mr)) - ehca_err(pd->device, "rc=%lx pd=%p mr_access_flags=%x" + ehca_err(pd->device, "rc=%lx pd=%p region=%p mr_access_flags=%x" " udata=%p", - PTR_ERR(ib_mr), pd, mr_access_flags, udata); + PTR_ERR(ib_mr), pd, region, mr_access_flags, udata); return ib_mr; } /* end ehca_reg_user_mr() */ @@ -600,9 +596,6 @@ int ehca_dereg_mr(struct ib_mr *mr) goto dereg_mr_exit0; } - if (e_mr->umem) - ib_umem_release(e_mr->umem); - /* successful deregistration */ ehca_mr_delete(e_mr); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_mr.c b/trunk/drivers/infiniband/hw/ipath/ipath_mr.c index bdeef8d4f279..31e70732e369 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_mr.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_mr.c @@ -31,7 +31,6 @@ * SOFTWARE. */ -#include #include #include @@ -148,7 +147,6 @@ struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd, mr->mr.offset = 0; mr->mr.access_flags = acc; mr->mr.max_segs = num_phys_buf; - mr->umem = NULL; m = 0; n = 0; @@ -172,56 +170,46 @@ struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd, /** * ipath_reg_user_mr - register a userspace memory region * @pd: protection domain for this memory region - * @start: starting userspace address - * @length: length of region to register - * @virt_addr: virtual address to use (from HCA's point of view) + * @region: the user memory region * @mr_access_flags: access flags for this memory region * @udata: unused by the InfiniPath driver * * Returns the memory region on success, otherwise returns an errno. */ -struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt_addr, int mr_access_flags, - struct ib_udata *udata) +struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, + int mr_access_flags, struct ib_udata *udata) { struct ipath_mr *mr; - struct ib_umem *umem; struct ib_umem_chunk *chunk; int n, m, i; struct ib_mr *ret; - if (length == 0) { + if (region->length == 0) { ret = ERR_PTR(-EINVAL); goto bail; } - umem = ib_umem_get(pd->uobject->context, start, length, mr_access_flags); - if (IS_ERR(umem)) - return (void *) umem; - n = 0; - list_for_each_entry(chunk, &umem->chunk_list, list) + list_for_each_entry(chunk, ®ion->chunk_list, list) n += chunk->nents; mr = alloc_mr(n, &to_idev(pd->device)->lk_table); if (!mr) { ret = ERR_PTR(-ENOMEM); - ib_umem_release(umem); goto bail; } mr->mr.pd = pd; - mr->mr.user_base = start; - mr->mr.iova = virt_addr; - mr->mr.length = length; - mr->mr.offset = umem->offset; + mr->mr.user_base = region->user_base; + mr->mr.iova = region->virt_base; + mr->mr.length = region->length; + mr->mr.offset = region->offset; mr->mr.access_flags = mr_access_flags; mr->mr.max_segs = n; - mr->umem = umem; m = 0; n = 0; - list_for_each_entry(chunk, &umem->chunk_list, list) { + list_for_each_entry(chunk, ®ion->chunk_list, list) { for (i = 0; i < chunk->nents; i++) { void *vaddr; @@ -231,7 +219,7 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, goto bail; } mr->mr.map[m]->segs[n].vaddr = vaddr; - mr->mr.map[m]->segs[n].length = umem->page_size; + mr->mr.map[m]->segs[n].length = region->page_size; n++; if (n == IPATH_SEGSZ) { m++; @@ -265,10 +253,6 @@ int ipath_dereg_mr(struct ib_mr *ibmr) i--; kfree(mr->mr.map[i]); } - - if (mr->umem) - ib_umem_release(mr->umem); - kfree(mr); return 0; } diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h index 088b837ebea8..7064fc222727 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h +++ b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h @@ -251,7 +251,6 @@ struct ipath_sge { /* Memory region */ struct ipath_mr { struct ib_mr ibmr; - struct ib_umem *umem; struct ipath_mregion mr; /* must be last */ }; @@ -752,8 +751,8 @@ struct ib_mr *ipath_reg_phys_mr(struct ib_pd *pd, struct ib_phys_buf *buffer_list, int num_phys_buf, int acc, u64 *iova_start); -struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt_addr, int mr_access_flags, +struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, + int mr_access_flags, struct ib_udata *udata); int ipath_dereg_mr(struct ib_mr *ibmr); diff --git a/trunk/drivers/infiniband/hw/mlx4/Kconfig b/trunk/drivers/infiniband/hw/mlx4/Kconfig deleted file mode 100644 index b8912cdb9663..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -config MLX4_INFINIBAND - tristate "Mellanox ConnectX HCA support" - depends on INFINIBAND - select MLX4_CORE - ---help--- - This driver provides low-level InfiniBand support for - Mellanox ConnectX PCI Express host channel adapters (HCAs). - This is required to use InfiniBand protocols such as - IP-over-IB or SRP with these devices. diff --git a/trunk/drivers/infiniband/hw/mlx4/Makefile b/trunk/drivers/infiniband/hw/mlx4/Makefile deleted file mode 100644 index 70f09c7826da..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_MLX4_INFINIBAND) += mlx4_ib.o - -mlx4_ib-y := ah.o cq.o doorbell.o mad.o main.o mr.o qp.o srq.o diff --git a/trunk/drivers/infiniband/hw/mlx4/ah.c b/trunk/drivers/infiniband/hw/mlx4/ah.c deleted file mode 100644 index c75ac9463e20..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/ah.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "mlx4_ib.h" - -struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) -{ - struct mlx4_dev *dev = to_mdev(pd->device)->dev; - struct mlx4_ib_ah *ah; - - ah = kmalloc(sizeof *ah, GFP_ATOMIC); - if (!ah) - return ERR_PTR(-ENOMEM); - - memset(&ah->av, 0, sizeof ah->av); - - ah->av.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24)); - ah->av.g_slid = ah_attr->src_path_bits; - ah->av.dlid = cpu_to_be16(ah_attr->dlid); - if (ah_attr->static_rate) { - ah->av.stat_rate = ah_attr->static_rate + MLX4_STAT_RATE_OFFSET; - while (ah->av.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET && - !(1 << ah->av.stat_rate & dev->caps.stat_rate_support)) - --ah->av.stat_rate; - } - ah->av.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28); - if (ah_attr->ah_flags & IB_AH_GRH) { - ah->av.g_slid |= 0x80; - ah->av.gid_index = ah_attr->grh.sgid_index; - ah->av.hop_limit = ah_attr->grh.hop_limit; - ah->av.sl_tclass_flowlabel |= - cpu_to_be32((ah_attr->grh.traffic_class << 20) | - ah_attr->grh.flow_label); - memcpy(ah->av.dgid, ah_attr->grh.dgid.raw, 16); - } - - return &ah->ibah; -} - -int mlx4_ib_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr) -{ - struct mlx4_ib_ah *ah = to_mah(ibah); - - memset(ah_attr, 0, sizeof *ah_attr); - ah_attr->dlid = be16_to_cpu(ah->av.dlid); - ah_attr->sl = be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 28; - ah_attr->port_num = be32_to_cpu(ah->av.port_pd) >> 24; - if (ah->av.stat_rate) - ah_attr->static_rate = ah->av.stat_rate - MLX4_STAT_RATE_OFFSET; - ah_attr->src_path_bits = ah->av.g_slid & 0x7F; - - if (mlx4_ib_ah_grh_present(ah)) { - ah_attr->ah_flags = IB_AH_GRH; - - ah_attr->grh.traffic_class = - be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 20; - ah_attr->grh.flow_label = - be32_to_cpu(ah->av.sl_tclass_flowlabel) & 0xfffff; - ah_attr->grh.hop_limit = ah->av.hop_limit; - ah_attr->grh.sgid_index = ah->av.gid_index; - memcpy(ah_attr->grh.dgid.raw, ah->av.dgid, 16); - } - - return 0; -} - -int mlx4_ib_destroy_ah(struct ib_ah *ah) -{ - kfree(to_mah(ah)); - return 0; -} diff --git a/trunk/drivers/infiniband/hw/mlx4/cq.c b/trunk/drivers/infiniband/hw/mlx4/cq.c deleted file mode 100644 index b2a290c6703a..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/cq.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include "mlx4_ib.h" -#include "user.h" - -static void mlx4_ib_cq_comp(struct mlx4_cq *cq) -{ - struct ib_cq *ibcq = &to_mibcq(cq)->ibcq; - ibcq->comp_handler(ibcq, ibcq->cq_context); -} - -static void mlx4_ib_cq_event(struct mlx4_cq *cq, enum mlx4_event type) -{ - struct ib_event event; - struct ib_cq *ibcq; - - if (type != MLX4_EVENT_TYPE_CQ_ERROR) { - printk(KERN_WARNING "mlx4_ib: Unexpected event type %d " - "on CQ %06x\n", type, cq->cqn); - return; - } - - ibcq = &to_mibcq(cq)->ibcq; - if (ibcq->event_handler) { - event.device = ibcq->device; - event.event = IB_EVENT_CQ_ERR; - event.element.cq = ibcq; - ibcq->event_handler(&event, ibcq->cq_context); - } -} - -static void *get_cqe_from_buf(struct mlx4_ib_cq_buf *buf, int n) -{ - int offset = n * sizeof (struct mlx4_cqe); - - if (buf->buf.nbufs == 1) - return buf->buf.u.direct.buf + offset; - else - return buf->buf.u.page_list[offset >> PAGE_SHIFT].buf + - (offset & (PAGE_SIZE - 1)); -} - -static void *get_cqe(struct mlx4_ib_cq *cq, int n) -{ - return get_cqe_from_buf(&cq->buf, n); -} - -static void *get_sw_cqe(struct mlx4_ib_cq *cq, int n) -{ - struct mlx4_cqe *cqe = get_cqe(cq, n & cq->ibcq.cqe); - - return (!!(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK) ^ - !!(n & (cq->ibcq.cqe + 1))) ? NULL : cqe; -} - -static struct mlx4_cqe *next_cqe_sw(struct mlx4_ib_cq *cq) -{ - return get_sw_cqe(cq, cq->mcq.cons_index); -} - -struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector, - struct ib_ucontext *context, - struct ib_udata *udata) -{ - struct mlx4_ib_dev *dev = to_mdev(ibdev); - struct mlx4_ib_cq *cq; - struct mlx4_uar *uar; - int buf_size; - int err; - - if (entries < 1 || entries > dev->dev->caps.max_cqes) - return ERR_PTR(-EINVAL); - - cq = kmalloc(sizeof *cq, GFP_KERNEL); - if (!cq) - return ERR_PTR(-ENOMEM); - - entries = roundup_pow_of_two(entries + 1); - cq->ibcq.cqe = entries - 1; - buf_size = entries * sizeof (struct mlx4_cqe); - spin_lock_init(&cq->lock); - - if (context) { - struct mlx4_ib_create_cq ucmd; - - if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { - err = -EFAULT; - goto err_cq; - } - - cq->umem = ib_umem_get(context, ucmd.buf_addr, buf_size, - IB_ACCESS_LOCAL_WRITE); - if (IS_ERR(cq->umem)) { - err = PTR_ERR(cq->umem); - goto err_cq; - } - - err = mlx4_mtt_init(dev->dev, ib_umem_page_count(cq->umem), - ilog2(cq->umem->page_size), &cq->buf.mtt); - if (err) - goto err_buf; - - err = mlx4_ib_umem_write_mtt(dev, &cq->buf.mtt, cq->umem); - if (err) - goto err_mtt; - - err = mlx4_ib_db_map_user(to_mucontext(context), ucmd.db_addr, - &cq->db); - if (err) - goto err_mtt; - - uar = &to_mucontext(context)->uar; - } else { - err = mlx4_ib_db_alloc(dev, &cq->db, 1); - if (err) - goto err_cq; - - cq->mcq.set_ci_db = cq->db.db; - cq->mcq.arm_db = cq->db.db + 1; - *cq->mcq.set_ci_db = 0; - *cq->mcq.arm_db = 0; - - if (mlx4_buf_alloc(dev->dev, buf_size, PAGE_SIZE * 2, &cq->buf.buf)) { - err = -ENOMEM; - goto err_db; - } - - err = mlx4_mtt_init(dev->dev, cq->buf.buf.npages, cq->buf.buf.page_shift, - &cq->buf.mtt); - if (err) - goto err_buf; - - err = mlx4_buf_write_mtt(dev->dev, &cq->buf.mtt, &cq->buf.buf); - if (err) - goto err_mtt; - - uar = &dev->priv_uar; - } - - err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar, - cq->db.dma, &cq->mcq); - if (err) - goto err_dbmap; - - cq->mcq.comp = mlx4_ib_cq_comp; - cq->mcq.event = mlx4_ib_cq_event; - - if (context) - if (ib_copy_to_udata(udata, &cq->mcq.cqn, sizeof (__u32))) { - err = -EFAULT; - goto err_dbmap; - } - - return &cq->ibcq; - -err_dbmap: - if (context) - mlx4_ib_db_unmap_user(to_mucontext(context), &cq->db); - -err_mtt: - mlx4_mtt_cleanup(dev->dev, &cq->buf.mtt); - -err_buf: - if (context) - ib_umem_release(cq->umem); - else - mlx4_buf_free(dev->dev, entries * sizeof (struct mlx4_cqe), - &cq->buf.buf); - -err_db: - if (!context) - mlx4_ib_db_free(dev, &cq->db); - -err_cq: - kfree(cq); - - return ERR_PTR(err); -} - -int mlx4_ib_destroy_cq(struct ib_cq *cq) -{ - struct mlx4_ib_dev *dev = to_mdev(cq->device); - struct mlx4_ib_cq *mcq = to_mcq(cq); - - mlx4_cq_free(dev->dev, &mcq->mcq); - mlx4_mtt_cleanup(dev->dev, &mcq->buf.mtt); - - if (cq->uobject) { - mlx4_ib_db_unmap_user(to_mucontext(cq->uobject->context), &mcq->db); - ib_umem_release(mcq->umem); - } else { - mlx4_buf_free(dev->dev, (cq->cqe + 1) * sizeof (struct mlx4_cqe), - &mcq->buf.buf); - mlx4_ib_db_free(dev, &mcq->db); - } - - kfree(mcq); - - return 0; -} - -static void dump_cqe(void *cqe) -{ - __be32 *buf = cqe; - - printk(KERN_DEBUG "CQE contents %08x %08x %08x %08x %08x %08x %08x %08x\n", - be32_to_cpu(buf[0]), be32_to_cpu(buf[1]), be32_to_cpu(buf[2]), - be32_to_cpu(buf[3]), be32_to_cpu(buf[4]), be32_to_cpu(buf[5]), - be32_to_cpu(buf[6]), be32_to_cpu(buf[7])); -} - -static void mlx4_ib_handle_error_cqe(struct mlx4_err_cqe *cqe, - struct ib_wc *wc) -{ - if (cqe->syndrome == MLX4_CQE_SYNDROME_LOCAL_QP_OP_ERR) { - printk(KERN_DEBUG "local QP operation err " - "(QPN %06x, WQE index %x, vendor syndrome %02x, " - "opcode = %02x)\n", - be32_to_cpu(cqe->my_qpn), be16_to_cpu(cqe->wqe_index), - cqe->vendor_err_syndrome, - cqe->owner_sr_opcode & ~MLX4_CQE_OWNER_MASK); - dump_cqe(cqe); - } - - switch (cqe->syndrome) { - case MLX4_CQE_SYNDROME_LOCAL_LENGTH_ERR: - wc->status = IB_WC_LOC_LEN_ERR; - break; - case MLX4_CQE_SYNDROME_LOCAL_QP_OP_ERR: - wc->status = IB_WC_LOC_QP_OP_ERR; - break; - case MLX4_CQE_SYNDROME_LOCAL_PROT_ERR: - wc->status = IB_WC_LOC_PROT_ERR; - break; - case MLX4_CQE_SYNDROME_WR_FLUSH_ERR: - wc->status = IB_WC_WR_FLUSH_ERR; - break; - case MLX4_CQE_SYNDROME_MW_BIND_ERR: - wc->status = IB_WC_MW_BIND_ERR; - break; - case MLX4_CQE_SYNDROME_BAD_RESP_ERR: - wc->status = IB_WC_BAD_RESP_ERR; - break; - case MLX4_CQE_SYNDROME_LOCAL_ACCESS_ERR: - wc->status = IB_WC_LOC_ACCESS_ERR; - break; - case MLX4_CQE_SYNDROME_REMOTE_INVAL_REQ_ERR: - wc->status = IB_WC_REM_INV_REQ_ERR; - break; - case MLX4_CQE_SYNDROME_REMOTE_ACCESS_ERR: - wc->status = IB_WC_REM_ACCESS_ERR; - break; - case MLX4_CQE_SYNDROME_REMOTE_OP_ERR: - wc->status = IB_WC_REM_OP_ERR; - break; - case MLX4_CQE_SYNDROME_TRANSPORT_RETRY_EXC_ERR: - wc->status = IB_WC_RETRY_EXC_ERR; - break; - case MLX4_CQE_SYNDROME_RNR_RETRY_EXC_ERR: - wc->status = IB_WC_RNR_RETRY_EXC_ERR; - break; - case MLX4_CQE_SYNDROME_REMOTE_ABORTED_ERR: - wc->status = IB_WC_REM_ABORT_ERR; - break; - default: - wc->status = IB_WC_GENERAL_ERR; - break; - } - - wc->vendor_err = cqe->vendor_err_syndrome; -} - -static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq, - struct mlx4_ib_qp **cur_qp, - struct ib_wc *wc) -{ - struct mlx4_cqe *cqe; - struct mlx4_qp *mqp; - struct mlx4_ib_wq *wq; - struct mlx4_ib_srq *srq; - int is_send; - int is_error; - u16 wqe_ctr; - - cqe = next_cqe_sw(cq); - if (!cqe) - return -EAGAIN; - - ++cq->mcq.cons_index; - - /* - * Make sure we read CQ entry contents after we've checked the - * ownership bit. - */ - rmb(); - - is_send = cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK; - is_error = (cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) == - MLX4_CQE_OPCODE_ERROR; - - if (!*cur_qp || - (be32_to_cpu(cqe->my_qpn) & 0xffffff) != (*cur_qp)->mqp.qpn) { - /* - * We do not have to take the QP table lock here, - * because CQs will be locked while QPs are removed - * from the table. - */ - mqp = __mlx4_qp_lookup(to_mdev(cq->ibcq.device)->dev, - be32_to_cpu(cqe->my_qpn)); - if (unlikely(!mqp)) { - printk(KERN_WARNING "CQ %06x with entry for unknown QPN %06x\n", - cq->mcq.cqn, be32_to_cpu(cqe->my_qpn) & 0xffffff); - return -EINVAL; - } - - *cur_qp = to_mibqp(mqp); - } - - wc->qp = &(*cur_qp)->ibqp; - - if (is_send) { - wq = &(*cur_qp)->sq; - wqe_ctr = be16_to_cpu(cqe->wqe_index); - wq->tail += wqe_ctr - (u16) wq->tail; - wc->wr_id = wq->wrid[wq->tail & (wq->max - 1)]; - ++wq->tail; - } else if ((*cur_qp)->ibqp.srq) { - srq = to_msrq((*cur_qp)->ibqp.srq); - wqe_ctr = be16_to_cpu(cqe->wqe_index); - wc->wr_id = srq->wrid[wqe_ctr]; - mlx4_ib_free_srq_wqe(srq, wqe_ctr); - } else { - wq = &(*cur_qp)->rq; - wc->wr_id = wq->wrid[wq->tail & (wq->max - 1)]; - ++wq->tail; - } - - if (unlikely(is_error)) { - mlx4_ib_handle_error_cqe((struct mlx4_err_cqe *) cqe, wc); - return 0; - } - - wc->status = IB_WC_SUCCESS; - - if (is_send) { - wc->wc_flags = 0; - switch (cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) { - case MLX4_OPCODE_RDMA_WRITE_IMM: - wc->wc_flags |= IB_WC_WITH_IMM; - case MLX4_OPCODE_RDMA_WRITE: - wc->opcode = IB_WC_RDMA_WRITE; - break; - case MLX4_OPCODE_SEND_IMM: - wc->wc_flags |= IB_WC_WITH_IMM; - case MLX4_OPCODE_SEND: - wc->opcode = IB_WC_SEND; - break; - case MLX4_OPCODE_RDMA_READ: - wc->opcode = IB_WC_SEND; - wc->byte_len = be32_to_cpu(cqe->byte_cnt); - break; - case MLX4_OPCODE_ATOMIC_CS: - wc->opcode = IB_WC_COMP_SWAP; - wc->byte_len = 8; - break; - case MLX4_OPCODE_ATOMIC_FA: - wc->opcode = IB_WC_FETCH_ADD; - wc->byte_len = 8; - break; - case MLX4_OPCODE_BIND_MW: - wc->opcode = IB_WC_BIND_MW; - break; - } - } else { - wc->byte_len = be32_to_cpu(cqe->byte_cnt); - - switch (cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) { - case MLX4_RECV_OPCODE_RDMA_WRITE_IMM: - wc->opcode = IB_WC_RECV_RDMA_WITH_IMM; - wc->wc_flags = IB_WC_WITH_IMM; - wc->imm_data = cqe->immed_rss_invalid; - break; - case MLX4_RECV_OPCODE_SEND: - wc->opcode = IB_WC_RECV; - wc->wc_flags = 0; - break; - case MLX4_RECV_OPCODE_SEND_IMM: - wc->opcode = IB_WC_RECV; - wc->wc_flags = IB_WC_WITH_IMM; - wc->imm_data = cqe->immed_rss_invalid; - break; - } - - wc->slid = be16_to_cpu(cqe->rlid); - wc->sl = cqe->sl >> 4; - wc->src_qp = be32_to_cpu(cqe->g_mlpath_rqpn) & 0xffffff; - wc->dlid_path_bits = (be32_to_cpu(cqe->g_mlpath_rqpn) >> 24) & 0x7f; - wc->wc_flags |= be32_to_cpu(cqe->g_mlpath_rqpn) & 0x80000000 ? - IB_WC_GRH : 0; - wc->pkey_index = be32_to_cpu(cqe->immed_rss_invalid) >> 16; - } - - return 0; -} - -int mlx4_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) -{ - struct mlx4_ib_cq *cq = to_mcq(ibcq); - struct mlx4_ib_qp *cur_qp = NULL; - unsigned long flags; - int npolled; - int err = 0; - - spin_lock_irqsave(&cq->lock, flags); - - for (npolled = 0; npolled < num_entries; ++npolled) { - err = mlx4_ib_poll_one(cq, &cur_qp, wc + npolled); - if (err) - break; - } - - if (npolled) - mlx4_cq_set_ci(&cq->mcq); - - spin_unlock_irqrestore(&cq->lock, flags); - - if (err == 0 || err == -EAGAIN) - return npolled; - else - return err; -} - -int mlx4_ib_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags) -{ - mlx4_cq_arm(&to_mcq(ibcq)->mcq, - (flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED ? - MLX4_CQ_DB_REQ_NOT_SOL : MLX4_CQ_DB_REQ_NOT, - to_mdev(ibcq->device)->uar_map, - MLX4_GET_DOORBELL_LOCK(&to_mdev(ibcq->device)->uar_lock)); - - return 0; -} - -void __mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq) -{ - u32 prod_index; - int nfreed = 0; - struct mlx4_cqe *cqe; - - /* - * First we need to find the current producer index, so we - * know where to start cleaning from. It doesn't matter if HW - * adds new entries after this loop -- the QP we're worried - * about is already in RESET, so the new entries won't come - * from our QP and therefore don't need to be checked. - */ - for (prod_index = cq->mcq.cons_index; get_sw_cqe(cq, prod_index); ++prod_index) - if (prod_index == cq->mcq.cons_index + cq->ibcq.cqe) - break; - - /* - * Now sweep backwards through the CQ, removing CQ entries - * that match our QP by copying older entries on top of them. - */ - while ((int) --prod_index - (int) cq->mcq.cons_index >= 0) { - cqe = get_cqe(cq, prod_index & cq->ibcq.cqe); - if ((be32_to_cpu(cqe->my_qpn) & 0xffffff) == qpn) { - if (srq && !(cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK)) - mlx4_ib_free_srq_wqe(srq, be16_to_cpu(cqe->wqe_index)); - ++nfreed; - } else if (nfreed) - memcpy(get_cqe(cq, (prod_index + nfreed) & cq->ibcq.cqe), - cqe, sizeof *cqe); - } - - if (nfreed) { - cq->mcq.cons_index += nfreed; - /* - * Make sure update of buffer contents is done before - * updating consumer index. - */ - wmb(); - mlx4_cq_set_ci(&cq->mcq); - } -} - -void mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq) -{ - spin_lock_irq(&cq->lock); - __mlx4_ib_cq_clean(cq, qpn, srq); - spin_unlock_irq(&cq->lock); -} diff --git a/trunk/drivers/infiniband/hw/mlx4/doorbell.c b/trunk/drivers/infiniband/hw/mlx4/doorbell.c deleted file mode 100644 index 1c36087aef14..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/doorbell.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include "mlx4_ib.h" - -struct mlx4_ib_db_pgdir { - struct list_head list; - DECLARE_BITMAP(order0, MLX4_IB_DB_PER_PAGE); - DECLARE_BITMAP(order1, MLX4_IB_DB_PER_PAGE / 2); - unsigned long *bits[2]; - __be32 *db_page; - dma_addr_t db_dma; -}; - -static struct mlx4_ib_db_pgdir *mlx4_ib_alloc_db_pgdir(struct mlx4_ib_dev *dev) -{ - struct mlx4_ib_db_pgdir *pgdir; - - pgdir = kzalloc(sizeof *pgdir, GFP_KERNEL); - if (!pgdir) - return NULL; - - bitmap_fill(pgdir->order1, MLX4_IB_DB_PER_PAGE / 2); - pgdir->bits[0] = pgdir->order0; - pgdir->bits[1] = pgdir->order1; - pgdir->db_page = dma_alloc_coherent(dev->ib_dev.dma_device, - PAGE_SIZE, &pgdir->db_dma, - GFP_KERNEL); - if (!pgdir->db_page) { - kfree(pgdir); - return NULL; - } - - return pgdir; -} - -static int mlx4_ib_alloc_db_from_pgdir(struct mlx4_ib_db_pgdir *pgdir, - struct mlx4_ib_db *db, int order) -{ - int o; - int i; - - for (o = order; o <= 1; ++o) { - i = find_first_bit(pgdir->bits[o], MLX4_IB_DB_PER_PAGE >> o); - if (i < MLX4_IB_DB_PER_PAGE >> o) - goto found; - } - - return -ENOMEM; - -found: - clear_bit(i, pgdir->bits[o]); - - i <<= o; - - if (o > order) - set_bit(i ^ 1, pgdir->bits[order]); - - db->u.pgdir = pgdir; - db->index = i; - db->db = pgdir->db_page + db->index; - db->dma = pgdir->db_dma + db->index * 4; - db->order = order; - - return 0; -} - -int mlx4_ib_db_alloc(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db, int order) -{ - struct mlx4_ib_db_pgdir *pgdir; - int ret = 0; - - mutex_lock(&dev->pgdir_mutex); - - list_for_each_entry(pgdir, &dev->pgdir_list, list) - if (!mlx4_ib_alloc_db_from_pgdir(pgdir, db, order)) - goto out; - - pgdir = mlx4_ib_alloc_db_pgdir(dev); - if (!pgdir) { - ret = -ENOMEM; - goto out; - } - - list_add(&pgdir->list, &dev->pgdir_list); - - /* This should never fail -- we just allocated an empty page: */ - WARN_ON(mlx4_ib_alloc_db_from_pgdir(pgdir, db, order)); - -out: - mutex_unlock(&dev->pgdir_mutex); - - return ret; -} - -void mlx4_ib_db_free(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db) -{ - int o; - int i; - - mutex_lock(&dev->pgdir_mutex); - - o = db->order; - i = db->index; - - if (db->order == 0 && test_bit(i ^ 1, db->u.pgdir->order0)) { - clear_bit(i ^ 1, db->u.pgdir->order0); - ++o; - } - - i >>= o; - set_bit(i, db->u.pgdir->bits[o]); - - if (bitmap_full(db->u.pgdir->order1, MLX4_IB_DB_PER_PAGE / 2)) { - dma_free_coherent(dev->ib_dev.dma_device, PAGE_SIZE, - db->u.pgdir->db_page, db->u.pgdir->db_dma); - list_del(&db->u.pgdir->list); - kfree(db->u.pgdir); - } - - mutex_unlock(&dev->pgdir_mutex); -} - -struct mlx4_ib_user_db_page { - struct list_head list; - struct ib_umem *umem; - unsigned long user_virt; - int refcnt; -}; - -int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt, - struct mlx4_ib_db *db) -{ - struct mlx4_ib_user_db_page *page; - struct ib_umem_chunk *chunk; - int err = 0; - - mutex_lock(&context->db_page_mutex); - - list_for_each_entry(page, &context->db_page_list, list) - if (page->user_virt == (virt & PAGE_MASK)) - goto found; - - page = kmalloc(sizeof *page, GFP_KERNEL); - if (!page) { - err = -ENOMEM; - goto out; - } - - page->user_virt = (virt & PAGE_MASK); - page->refcnt = 0; - page->umem = ib_umem_get(&context->ibucontext, virt & PAGE_MASK, - PAGE_SIZE, 0); - if (IS_ERR(page->umem)) { - err = PTR_ERR(page->umem); - kfree(page); - goto out; - } - - list_add(&page->list, &context->db_page_list); - -found: - chunk = list_entry(page->umem->chunk_list.next, struct ib_umem_chunk, list); - db->dma = sg_dma_address(chunk->page_list) + (virt & ~PAGE_MASK); - db->u.user_page = page; - ++page->refcnt; - -out: - mutex_unlock(&context->db_page_mutex); - - return err; -} - -void mlx4_ib_db_unmap_user(struct mlx4_ib_ucontext *context, struct mlx4_ib_db *db) -{ - mutex_lock(&context->db_page_mutex); - - if (!--db->u.user_page->refcnt) { - list_del(&db->u.user_page->list); - ib_umem_release(db->u.user_page->umem); - kfree(db->u.user_page); - } - - mutex_unlock(&context->db_page_mutex); -} diff --git a/trunk/drivers/infiniband/hw/mlx4/mad.c b/trunk/drivers/infiniband/hw/mlx4/mad.c deleted file mode 100644 index 333091787c5f..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/mad.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include - -#include "mlx4_ib.h" - -enum { - MLX4_IB_VENDOR_CLASS1 = 0x9, - MLX4_IB_VENDOR_CLASS2 = 0xa -}; - -int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey, - int port, struct ib_wc *in_wc, struct ib_grh *in_grh, - void *in_mad, void *response_mad) -{ - struct mlx4_cmd_mailbox *inmailbox, *outmailbox; - void *inbox; - int err; - u32 in_modifier = port; - u8 op_modifier = 0; - - inmailbox = mlx4_alloc_cmd_mailbox(dev->dev); - if (IS_ERR(inmailbox)) - return PTR_ERR(inmailbox); - inbox = inmailbox->buf; - - outmailbox = mlx4_alloc_cmd_mailbox(dev->dev); - if (IS_ERR(outmailbox)) { - mlx4_free_cmd_mailbox(dev->dev, inmailbox); - return PTR_ERR(outmailbox); - } - - memcpy(inbox, in_mad, 256); - - /* - * Key check traps can't be generated unless we have in_wc to - * tell us where to send the trap. - */ - if (ignore_mkey || !in_wc) - op_modifier |= 0x1; - if (ignore_bkey || !in_wc) - op_modifier |= 0x2; - - if (in_wc) { - struct { - __be32 my_qpn; - u32 reserved1; - __be32 rqpn; - u8 sl; - u8 g_path; - u16 reserved2[2]; - __be16 pkey; - u32 reserved3[11]; - u8 grh[40]; - } *ext_info; - - memset(inbox + 256, 0, 256); - ext_info = inbox + 256; - - ext_info->my_qpn = cpu_to_be32(in_wc->qp->qp_num); - ext_info->rqpn = cpu_to_be32(in_wc->src_qp); - ext_info->sl = in_wc->sl << 4; - ext_info->g_path = in_wc->dlid_path_bits | - (in_wc->wc_flags & IB_WC_GRH ? 0x80 : 0); - ext_info->pkey = cpu_to_be16(in_wc->pkey_index); - - if (in_grh) - memcpy(ext_info->grh, in_grh, 40); - - op_modifier |= 0x4; - - in_modifier |= in_wc->slid << 16; - } - - err = mlx4_cmd_box(dev->dev, inmailbox->dma, outmailbox->dma, - in_modifier, op_modifier, - MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C); - - if (!err); - memcpy(response_mad, outmailbox->buf, 256); - - mlx4_free_cmd_mailbox(dev->dev, inmailbox); - mlx4_free_cmd_mailbox(dev->dev, outmailbox); - - return err; -} - -static void update_sm_ah(struct mlx4_ib_dev *dev, u8 port_num, u16 lid, u8 sl) -{ - struct ib_ah *new_ah; - struct ib_ah_attr ah_attr; - - if (!dev->send_agent[port_num - 1][0]) - return; - - memset(&ah_attr, 0, sizeof ah_attr); - ah_attr.dlid = lid; - ah_attr.sl = sl; - ah_attr.port_num = port_num; - - new_ah = ib_create_ah(dev->send_agent[port_num - 1][0]->qp->pd, - &ah_attr); - if (IS_ERR(new_ah)) - return; - - spin_lock(&dev->sm_lock); - if (dev->sm_ah[port_num - 1]) - ib_destroy_ah(dev->sm_ah[port_num - 1]); - dev->sm_ah[port_num - 1] = new_ah; - spin_unlock(&dev->sm_lock); -} - -/* - * Snoop SM MADs for port info and P_Key table sets, so we can - * synthesize LID change and P_Key change events. - */ -static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad) -{ - struct ib_event event; - - if ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || - mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) && - mad->mad_hdr.method == IB_MGMT_METHOD_SET) { - if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) { - struct ib_port_info *pinfo = - (struct ib_port_info *) ((struct ib_smp *) mad)->data; - - update_sm_ah(to_mdev(ibdev), port_num, - be16_to_cpu(pinfo->sm_lid), - pinfo->neighbormtu_mastersmsl & 0xf); - - event.device = ibdev; - event.element.port_num = port_num; - - if(pinfo->clientrereg_resv_subnetto & 0x80) - event.event = IB_EVENT_CLIENT_REREGISTER; - else - event.event = IB_EVENT_LID_CHANGE; - - ib_dispatch_event(&event); - } - - if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PKEY_TABLE) { - event.device = ibdev; - event.event = IB_EVENT_PKEY_CHANGE; - event.element.port_num = port_num; - ib_dispatch_event(&event); - } - } -} - -static void node_desc_override(struct ib_device *dev, - struct ib_mad *mad) -{ - if ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || - mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) && - mad->mad_hdr.method == IB_MGMT_METHOD_GET_RESP && - mad->mad_hdr.attr_id == IB_SMP_ATTR_NODE_DESC) { - spin_lock(&to_mdev(dev)->sm_lock); - memcpy(((struct ib_smp *) mad)->data, dev->node_desc, 64); - spin_unlock(&to_mdev(dev)->sm_lock); - } -} - -static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *mad) -{ - int qpn = mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED; - struct ib_mad_send_buf *send_buf; - struct ib_mad_agent *agent = dev->send_agent[port_num - 1][qpn]; - int ret; - - if (agent) { - send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR, - IB_MGMT_MAD_DATA, GFP_ATOMIC); - /* - * We rely here on the fact that MLX QPs don't use the - * address handle after the send is posted (this is - * wrong following the IB spec strictly, but we know - * it's OK for our devices). - */ - spin_lock(&dev->sm_lock); - memcpy(send_buf->mad, mad, sizeof *mad); - if ((send_buf->ah = dev->sm_ah[port_num - 1])) - ret = ib_post_send_mad(send_buf, NULL); - else - ret = -EINVAL; - spin_unlock(&dev->sm_lock); - - if (ret) - ib_free_send_mad(send_buf); - } -} - -int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, - struct ib_wc *in_wc, struct ib_grh *in_grh, - struct ib_mad *in_mad, struct ib_mad *out_mad) -{ - u16 slid; - int err; - - slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); - - if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP && slid == 0) { - forward_trap(to_mdev(ibdev), port_num, in_mad); - return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED; - } - - if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || - in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) { - if (in_mad->mad_hdr.method != IB_MGMT_METHOD_GET && - in_mad->mad_hdr.method != IB_MGMT_METHOD_SET && - in_mad->mad_hdr.method != IB_MGMT_METHOD_TRAP_REPRESS) - return IB_MAD_RESULT_SUCCESS; - - /* - * Don't process SMInfo queries or vendor-specific - * MADs -- the SMA can't handle them. - */ - if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO || - ((in_mad->mad_hdr.attr_id & IB_SMP_ATTR_VENDOR_MASK) == - IB_SMP_ATTR_VENDOR_MASK)) - return IB_MAD_RESULT_SUCCESS; - } else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT || - in_mad->mad_hdr.mgmt_class == MLX4_IB_VENDOR_CLASS1 || - in_mad->mad_hdr.mgmt_class == MLX4_IB_VENDOR_CLASS2) { - if (in_mad->mad_hdr.method != IB_MGMT_METHOD_GET && - in_mad->mad_hdr.method != IB_MGMT_METHOD_SET) - return IB_MAD_RESULT_SUCCESS; - } else - return IB_MAD_RESULT_SUCCESS; - - err = mlx4_MAD_IFC(to_mdev(ibdev), - mad_flags & IB_MAD_IGNORE_MKEY, - mad_flags & IB_MAD_IGNORE_BKEY, - port_num, in_wc, in_grh, in_mad, out_mad); - if (err) - return IB_MAD_RESULT_FAILURE; - - if (!out_mad->mad_hdr.status) { - smp_snoop(ibdev, port_num, in_mad); - node_desc_override(ibdev, out_mad); - } - - /* set return bit in status of directed route responses */ - if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) - out_mad->mad_hdr.status |= cpu_to_be16(1 << 15); - - if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP_REPRESS) - /* no response for trap repress */ - return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED; - - return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; -} - -static void send_handler(struct ib_mad_agent *agent, - struct ib_mad_send_wc *mad_send_wc) -{ - ib_free_send_mad(mad_send_wc->send_buf); -} - -int mlx4_ib_mad_init(struct mlx4_ib_dev *dev) -{ - struct ib_mad_agent *agent; - int p, q; - int ret; - - for (p = 0; p < dev->dev->caps.num_ports; ++p) - for (q = 0; q <= 1; ++q) { - agent = ib_register_mad_agent(&dev->ib_dev, p + 1, - q ? IB_QPT_GSI : IB_QPT_SMI, - NULL, 0, send_handler, - NULL, NULL); - if (IS_ERR(agent)) { - ret = PTR_ERR(agent); - goto err; - } - dev->send_agent[p][q] = agent; - } - - return 0; - -err: - for (p = 0; p < dev->dev->caps.num_ports; ++p) - for (q = 0; q <= 1; ++q) - if (dev->send_agent[p][q]) - ib_unregister_mad_agent(dev->send_agent[p][q]); - - return ret; -} - -void mlx4_ib_mad_cleanup(struct mlx4_ib_dev *dev) -{ - struct ib_mad_agent *agent; - int p, q; - - for (p = 0; p < dev->dev->caps.num_ports; ++p) { - for (q = 0; q <= 1; ++q) { - agent = dev->send_agent[p][q]; - dev->send_agent[p][q] = NULL; - ib_unregister_mad_agent(agent); - } - - if (dev->sm_ah[p]) - ib_destroy_ah(dev->sm_ah[p]); - } -} diff --git a/trunk/drivers/infiniband/hw/mlx4/main.c b/trunk/drivers/infiniband/hw/mlx4/main.c deleted file mode 100644 index 688ecb4c39f3..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/main.c +++ /dev/null @@ -1,651 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include - -#include -#include - -#include -#include - -#include "mlx4_ib.h" -#include "user.h" - -#define DRV_NAME "mlx4_ib" -#define DRV_VERSION "0.01" -#define DRV_RELDATE "May 1, 2006" - -MODULE_AUTHOR("Roland Dreier"); -MODULE_DESCRIPTION("Mellanox ConnectX HCA InfiniBand driver"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION(DRV_VERSION); - -static const char mlx4_ib_version[] __devinitdata = - DRV_NAME ": Mellanox ConnectX InfiniBand driver v" - DRV_VERSION " (" DRV_RELDATE ")\n"; - -static void init_query_mad(struct ib_smp *mad) -{ - mad->base_version = 1; - mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; - mad->class_version = 1; - mad->method = IB_MGMT_METHOD_GET; -} - -static int mlx4_ib_query_device(struct ib_device *ibdev, - struct ib_device_attr *props) -{ - struct mlx4_ib_dev *dev = to_mdev(ibdev); - struct ib_smp *in_mad = NULL; - struct ib_smp *out_mad = NULL; - int err = -ENOMEM; - - in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); - out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); - if (!in_mad || !out_mad) - goto out; - - init_query_mad(in_mad); - in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; - - err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad, out_mad); - if (err) - goto out; - - memset(props, 0, sizeof *props); - - props->fw_ver = dev->dev->caps.fw_ver; - props->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT | - IB_DEVICE_PORT_ACTIVE_EVENT | - IB_DEVICE_SYS_IMAGE_GUID | - IB_DEVICE_RC_RNR_NAK_GEN; - if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BAD_PKEY_CNTR) - props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR; - if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BAD_QKEY_CNTR) - props->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR; - if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_APM) - props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG; - if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UD_AV_PORT) - props->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE; - - props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) & - 0xffffff; - props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); - props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32)); - memcpy(&props->sys_image_guid, out_mad->data + 4, 8); - - props->max_mr_size = ~0ull; - props->page_size_cap = dev->dev->caps.page_size_cap; - props->max_qp = dev->dev->caps.num_qps - dev->dev->caps.reserved_qps; - props->max_qp_wr = dev->dev->caps.max_wqes; - props->max_sge = min(dev->dev->caps.max_sq_sg, - dev->dev->caps.max_rq_sg); - props->max_cq = dev->dev->caps.num_cqs - dev->dev->caps.reserved_cqs; - props->max_cqe = dev->dev->caps.max_cqes; - props->max_mr = dev->dev->caps.num_mpts - dev->dev->caps.reserved_mrws; - props->max_pd = dev->dev->caps.num_pds - dev->dev->caps.reserved_pds; - props->max_qp_rd_atom = dev->dev->caps.max_qp_dest_rdma; - props->max_qp_init_rd_atom = dev->dev->caps.max_qp_init_rdma; - props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp; - props->max_srq = dev->dev->caps.num_srqs - dev->dev->caps.reserved_srqs; - props->max_srq_wr = dev->dev->caps.max_srq_wqes; - props->max_srq_sge = dev->dev->caps.max_srq_sge; - props->local_ca_ack_delay = dev->dev->caps.local_ca_ack_delay; - props->atomic_cap = dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_ATOMIC ? - IB_ATOMIC_HCA : IB_ATOMIC_NONE; - props->max_pkeys = dev->dev->caps.pkey_table_len; - props->max_mcast_grp = dev->dev->caps.num_mgms + dev->dev->caps.num_amgms; - props->max_mcast_qp_attach = dev->dev->caps.num_qp_per_mgm; - props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * - props->max_mcast_grp; - props->max_map_per_fmr = (1 << (32 - ilog2(dev->dev->caps.num_mpts))) - 1; - -out: - kfree(in_mad); - kfree(out_mad); - - return err; -} - -static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port, - struct ib_port_attr *props) -{ - struct ib_smp *in_mad = NULL; - struct ib_smp *out_mad = NULL; - int err = -ENOMEM; - - in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); - out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); - if (!in_mad || !out_mad) - goto out; - - memset(props, 0, sizeof *props); - - init_query_mad(in_mad); - in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; - in_mad->attr_mod = cpu_to_be32(port); - - err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); - if (err) - goto out; - - props->lid = be16_to_cpup((__be16 *) (out_mad->data + 16)); - props->lmc = out_mad->data[34] & 0x7; - props->sm_lid = be16_to_cpup((__be16 *) (out_mad->data + 18)); - props->sm_sl = out_mad->data[36] & 0xf; - props->state = out_mad->data[32] & 0xf; - props->phys_state = out_mad->data[33] >> 4; - props->port_cap_flags = be32_to_cpup((__be32 *) (out_mad->data + 20)); - props->gid_tbl_len = to_mdev(ibdev)->dev->caps.gid_table_len; - props->max_msg_sz = 0x80000000; - props->pkey_tbl_len = to_mdev(ibdev)->dev->caps.pkey_table_len; - props->bad_pkey_cntr = be16_to_cpup((__be16 *) (out_mad->data + 46)); - props->qkey_viol_cntr = be16_to_cpup((__be16 *) (out_mad->data + 48)); - props->active_width = out_mad->data[31] & 0xf; - props->active_speed = out_mad->data[35] >> 4; - props->max_mtu = out_mad->data[41] & 0xf; - props->active_mtu = out_mad->data[36] >> 4; - props->subnet_timeout = out_mad->data[51] & 0x1f; - props->max_vl_num = out_mad->data[37] >> 4; - props->init_type_reply = out_mad->data[41] >> 4; - -out: - kfree(in_mad); - kfree(out_mad); - - return err; -} - -static int mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index, - union ib_gid *gid) -{ - struct ib_smp *in_mad = NULL; - struct ib_smp *out_mad = NULL; - int err = -ENOMEM; - - in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); - out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); - if (!in_mad || !out_mad) - goto out; - - init_query_mad(in_mad); - in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; - in_mad->attr_mod = cpu_to_be32(port); - - err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); - if (err) - goto out; - - memcpy(gid->raw, out_mad->data + 8, 8); - - init_query_mad(in_mad); - in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; - in_mad->attr_mod = cpu_to_be32(index / 8); - - err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); - if (err) - goto out; - - memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8); - -out: - kfree(in_mad); - kfree(out_mad); - return err; -} - -static int mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index, - u16 *pkey) -{ - struct ib_smp *in_mad = NULL; - struct ib_smp *out_mad = NULL; - int err = -ENOMEM; - - in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); - out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); - if (!in_mad || !out_mad) - goto out; - - init_query_mad(in_mad); - in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; - in_mad->attr_mod = cpu_to_be32(index / 32); - - err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); - if (err) - goto out; - - *pkey = be16_to_cpu(((__be16 *) out_mad->data)[index % 32]); - -out: - kfree(in_mad); - kfree(out_mad); - return err; -} - -static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask, - struct ib_device_modify *props) -{ - if (mask & ~IB_DEVICE_MODIFY_NODE_DESC) - return -EOPNOTSUPP; - - if (mask & IB_DEVICE_MODIFY_NODE_DESC) { - spin_lock(&to_mdev(ibdev)->sm_lock); - memcpy(ibdev->node_desc, props->node_desc, 64); - spin_unlock(&to_mdev(ibdev)->sm_lock); - } - - return 0; -} - -static int mlx4_SET_PORT(struct mlx4_ib_dev *dev, u8 port, int reset_qkey_viols, - u32 cap_mask) -{ - struct mlx4_cmd_mailbox *mailbox; - int err; - - mailbox = mlx4_alloc_cmd_mailbox(dev->dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - - memset(mailbox->buf, 0, 256); - *(u8 *) mailbox->buf = !!reset_qkey_viols << 6; - ((__be32 *) mailbox->buf)[2] = cpu_to_be32(cap_mask); - - err = mlx4_cmd(dev->dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT, - MLX4_CMD_TIME_CLASS_B); - - mlx4_free_cmd_mailbox(dev->dev, mailbox); - return err; -} - -static int mlx4_ib_modify_port(struct ib_device *ibdev, u8 port, int mask, - struct ib_port_modify *props) -{ - struct ib_port_attr attr; - u32 cap_mask; - int err; - - mutex_lock(&to_mdev(ibdev)->cap_mask_mutex); - - err = mlx4_ib_query_port(ibdev, port, &attr); - if (err) - goto out; - - cap_mask = (attr.port_cap_flags | props->set_port_cap_mask) & - ~props->clr_port_cap_mask; - - err = mlx4_SET_PORT(to_mdev(ibdev), port, - !!(mask & IB_PORT_RESET_QKEY_CNTR), - cap_mask); - -out: - mutex_unlock(&to_mdev(ibdev)->cap_mask_mutex); - return err; -} - -static struct ib_ucontext *mlx4_ib_alloc_ucontext(struct ib_device *ibdev, - struct ib_udata *udata) -{ - struct mlx4_ib_dev *dev = to_mdev(ibdev); - struct mlx4_ib_ucontext *context; - struct mlx4_ib_alloc_ucontext_resp resp; - int err; - - resp.qp_tab_size = dev->dev->caps.num_qps; - resp.bf_reg_size = dev->dev->caps.bf_reg_size; - resp.bf_regs_per_page = dev->dev->caps.bf_regs_per_page; - - context = kmalloc(sizeof *context, GFP_KERNEL); - if (!context) - return ERR_PTR(-ENOMEM); - - err = mlx4_uar_alloc(to_mdev(ibdev)->dev, &context->uar); - if (err) { - kfree(context); - return ERR_PTR(err); - } - - INIT_LIST_HEAD(&context->db_page_list); - mutex_init(&context->db_page_mutex); - - err = ib_copy_to_udata(udata, &resp, sizeof resp); - if (err) { - mlx4_uar_free(to_mdev(ibdev)->dev, &context->uar); - kfree(context); - return ERR_PTR(-EFAULT); - } - - return &context->ibucontext; -} - -static int mlx4_ib_dealloc_ucontext(struct ib_ucontext *ibcontext) -{ - struct mlx4_ib_ucontext *context = to_mucontext(ibcontext); - - mlx4_uar_free(to_mdev(ibcontext->device)->dev, &context->uar); - kfree(context); - - return 0; -} - -static int mlx4_ib_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) -{ - struct mlx4_ib_dev *dev = to_mdev(context->device); - - if (vma->vm_end - vma->vm_start != PAGE_SIZE) - return -EINVAL; - - if (vma->vm_pgoff == 0) { - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - if (io_remap_pfn_range(vma, vma->vm_start, - to_mucontext(context)->uar.pfn, - PAGE_SIZE, vma->vm_page_prot)) - return -EAGAIN; - } else if (vma->vm_pgoff == 1 && dev->dev->caps.bf_reg_size != 0) { - /* FIXME want pgprot_writecombine() for BlueFlame pages */ - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - if (io_remap_pfn_range(vma, vma->vm_start, - to_mucontext(context)->uar.pfn + - dev->dev->caps.num_uars, - PAGE_SIZE, vma->vm_page_prot)) - return -EAGAIN; - } else - return -EINVAL; - - return 0; -} - -static struct ib_pd *mlx4_ib_alloc_pd(struct ib_device *ibdev, - struct ib_ucontext *context, - struct ib_udata *udata) -{ - struct mlx4_ib_pd *pd; - int err; - - pd = kmalloc(sizeof *pd, GFP_KERNEL); - if (!pd) - return ERR_PTR(-ENOMEM); - - err = mlx4_pd_alloc(to_mdev(ibdev)->dev, &pd->pdn); - if (err) { - kfree(pd); - return ERR_PTR(err); - } - - if (context) - if (ib_copy_to_udata(udata, &pd->pdn, sizeof (__u32))) { - mlx4_pd_free(to_mdev(ibdev)->dev, pd->pdn); - kfree(pd); - return ERR_PTR(-EFAULT); - } - - return &pd->ibpd; -} - -static int mlx4_ib_dealloc_pd(struct ib_pd *pd) -{ - mlx4_pd_free(to_mdev(pd->device)->dev, to_mpd(pd)->pdn); - kfree(pd); - - return 0; -} - -static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - return mlx4_multicast_attach(to_mdev(ibqp->device)->dev, - &to_mqp(ibqp)->mqp, gid->raw); -} - -static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - return mlx4_multicast_detach(to_mdev(ibqp->device)->dev, - &to_mqp(ibqp)->mqp, gid->raw); -} - -static int init_node_data(struct mlx4_ib_dev *dev) -{ - struct ib_smp *in_mad = NULL; - struct ib_smp *out_mad = NULL; - int err = -ENOMEM; - - in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); - out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); - if (!in_mad || !out_mad) - goto out; - - init_query_mad(in_mad); - in_mad->attr_id = IB_SMP_ATTR_NODE_DESC; - - err = mlx4_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); - if (err) - goto out; - - memcpy(dev->ib_dev.node_desc, out_mad->data, 64); - - in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; - - err = mlx4_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); - if (err) - goto out; - - memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8); - -out: - kfree(in_mad); - kfree(out_mad); - return err; -} - -static void *mlx4_ib_add(struct mlx4_dev *dev) -{ - struct mlx4_ib_dev *ibdev; - - ibdev = (struct mlx4_ib_dev *) ib_alloc_device(sizeof *ibdev); - if (!ibdev) { - dev_err(&dev->pdev->dev, "Device struct alloc failed\n"); - return NULL; - } - - if (mlx4_pd_alloc(dev, &ibdev->priv_pdn)) - goto err_dealloc; - - if (mlx4_uar_alloc(dev, &ibdev->priv_uar)) - goto err_pd; - - ibdev->uar_map = ioremap(ibdev->priv_uar.pfn << PAGE_SHIFT, PAGE_SIZE); - if (!ibdev->uar_map) - goto err_uar; - - INIT_LIST_HEAD(&ibdev->pgdir_list); - mutex_init(&ibdev->pgdir_mutex); - - ibdev->dev = dev; - - strlcpy(ibdev->ib_dev.name, "mlx4_%d", IB_DEVICE_NAME_MAX); - ibdev->ib_dev.owner = THIS_MODULE; - ibdev->ib_dev.node_type = RDMA_NODE_IB_CA; - ibdev->ib_dev.phys_port_cnt = dev->caps.num_ports; - ibdev->ib_dev.num_comp_vectors = 1; - ibdev->ib_dev.dma_device = &dev->pdev->dev; - - ibdev->ib_dev.uverbs_abi_ver = MLX4_IB_UVERBS_ABI_VERSION; - ibdev->ib_dev.uverbs_cmd_mask = - (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | - (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | - (1ull << IB_USER_VERBS_CMD_QUERY_PORT) | - (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | - (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | - (1ull << IB_USER_VERBS_CMD_REG_MR) | - (1ull << IB_USER_VERBS_CMD_DEREG_MR) | - (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | - (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | - (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) | - (1ull << IB_USER_VERBS_CMD_CREATE_QP) | - (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | - (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | - (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) | - (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) | - (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) | - (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) | - (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ); - - ibdev->ib_dev.query_device = mlx4_ib_query_device; - ibdev->ib_dev.query_port = mlx4_ib_query_port; - ibdev->ib_dev.query_gid = mlx4_ib_query_gid; - ibdev->ib_dev.query_pkey = mlx4_ib_query_pkey; - ibdev->ib_dev.modify_device = mlx4_ib_modify_device; - ibdev->ib_dev.modify_port = mlx4_ib_modify_port; - ibdev->ib_dev.alloc_ucontext = mlx4_ib_alloc_ucontext; - ibdev->ib_dev.dealloc_ucontext = mlx4_ib_dealloc_ucontext; - ibdev->ib_dev.mmap = mlx4_ib_mmap; - ibdev->ib_dev.alloc_pd = mlx4_ib_alloc_pd; - ibdev->ib_dev.dealloc_pd = mlx4_ib_dealloc_pd; - ibdev->ib_dev.create_ah = mlx4_ib_create_ah; - ibdev->ib_dev.query_ah = mlx4_ib_query_ah; - ibdev->ib_dev.destroy_ah = mlx4_ib_destroy_ah; - ibdev->ib_dev.create_srq = mlx4_ib_create_srq; - ibdev->ib_dev.modify_srq = mlx4_ib_modify_srq; - ibdev->ib_dev.destroy_srq = mlx4_ib_destroy_srq; - ibdev->ib_dev.post_srq_recv = mlx4_ib_post_srq_recv; - ibdev->ib_dev.create_qp = mlx4_ib_create_qp; - ibdev->ib_dev.modify_qp = mlx4_ib_modify_qp; - ibdev->ib_dev.destroy_qp = mlx4_ib_destroy_qp; - ibdev->ib_dev.post_send = mlx4_ib_post_send; - ibdev->ib_dev.post_recv = mlx4_ib_post_recv; - ibdev->ib_dev.create_cq = mlx4_ib_create_cq; - ibdev->ib_dev.destroy_cq = mlx4_ib_destroy_cq; - ibdev->ib_dev.poll_cq = mlx4_ib_poll_cq; - ibdev->ib_dev.req_notify_cq = mlx4_ib_arm_cq; - ibdev->ib_dev.get_dma_mr = mlx4_ib_get_dma_mr; - ibdev->ib_dev.reg_user_mr = mlx4_ib_reg_user_mr; - ibdev->ib_dev.dereg_mr = mlx4_ib_dereg_mr; - ibdev->ib_dev.attach_mcast = mlx4_ib_mcg_attach; - ibdev->ib_dev.detach_mcast = mlx4_ib_mcg_detach; - ibdev->ib_dev.process_mad = mlx4_ib_process_mad; - - if (init_node_data(ibdev)) - goto err_map; - - spin_lock_init(&ibdev->sm_lock); - mutex_init(&ibdev->cap_mask_mutex); - - if (ib_register_device(&ibdev->ib_dev)) - goto err_map; - - if (mlx4_ib_mad_init(ibdev)) - goto err_reg; - - return ibdev; - -err_reg: - ib_unregister_device(&ibdev->ib_dev); - -err_map: - iounmap(ibdev->uar_map); - -err_uar: - mlx4_uar_free(dev, &ibdev->priv_uar); - -err_pd: - mlx4_pd_free(dev, ibdev->priv_pdn); - -err_dealloc: - ib_dealloc_device(&ibdev->ib_dev); - - return NULL; -} - -static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) -{ - struct mlx4_ib_dev *ibdev = ibdev_ptr; - int p; - - for (p = 1; p <= dev->caps.num_ports; ++p) - mlx4_CLOSE_PORT(dev, p); - - mlx4_ib_mad_cleanup(ibdev); - ib_unregister_device(&ibdev->ib_dev); - iounmap(ibdev->uar_map); - mlx4_uar_free(dev, &ibdev->priv_uar); - mlx4_pd_free(dev, ibdev->priv_pdn); - ib_dealloc_device(&ibdev->ib_dev); -} - -static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, - enum mlx4_dev_event event, int subtype, - int port) -{ - struct ib_event ibev; - - switch (event) { - case MLX4_EVENT_TYPE_PORT_CHANGE: - ibev.event = subtype == MLX4_PORT_CHANGE_SUBTYPE_ACTIVE ? - IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR; - break; - - case MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR: - ibev.event = IB_EVENT_DEVICE_FATAL; - break; - - default: - return; - } - - ibev.device = ibdev_ptr; - ibev.element.port_num = port; - - ib_dispatch_event(&ibev); -} - -static struct mlx4_interface mlx4_ib_interface = { - .add = mlx4_ib_add, - .remove = mlx4_ib_remove, - .event = mlx4_ib_event -}; - -static int __init mlx4_ib_init(void) -{ - return mlx4_register_interface(&mlx4_ib_interface); -} - -static void __exit mlx4_ib_cleanup(void) -{ - mlx4_unregister_interface(&mlx4_ib_interface); -} - -module_init(mlx4_ib_init); -module_exit(mlx4_ib_cleanup); diff --git a/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h b/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h deleted file mode 100644 index 93dac71f3230..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef MLX4_IB_H -#define MLX4_IB_H - -#include -#include - -#include -#include - -#include -#include - -enum { - MLX4_IB_DB_PER_PAGE = PAGE_SIZE / 4 -}; - -struct mlx4_ib_db_pgdir; -struct mlx4_ib_user_db_page; - -struct mlx4_ib_db { - __be32 *db; - union { - struct mlx4_ib_db_pgdir *pgdir; - struct mlx4_ib_user_db_page *user_page; - } u; - dma_addr_t dma; - int index; - int order; -}; - -struct mlx4_ib_ucontext { - struct ib_ucontext ibucontext; - struct mlx4_uar uar; - struct list_head db_page_list; - struct mutex db_page_mutex; -}; - -struct mlx4_ib_pd { - struct ib_pd ibpd; - u32 pdn; -}; - -struct mlx4_ib_cq_buf { - struct mlx4_buf buf; - struct mlx4_mtt mtt; -}; - -struct mlx4_ib_cq { - struct ib_cq ibcq; - struct mlx4_cq mcq; - struct mlx4_ib_cq_buf buf; - struct mlx4_ib_db db; - spinlock_t lock; - struct ib_umem *umem; -}; - -struct mlx4_ib_mr { - struct ib_mr ibmr; - struct mlx4_mr mmr; - struct ib_umem *umem; -}; - -struct mlx4_ib_wq { - u64 *wrid; - spinlock_t lock; - int max; - int max_gs; - int offset; - int wqe_shift; - unsigned head; - unsigned tail; -}; - -struct mlx4_ib_qp { - struct ib_qp ibqp; - struct mlx4_qp mqp; - struct mlx4_buf buf; - - struct mlx4_ib_db db; - struct mlx4_ib_wq rq; - - u32 doorbell_qpn; - __be32 sq_signal_bits; - struct mlx4_ib_wq sq; - - struct ib_umem *umem; - struct mlx4_mtt mtt; - int buf_size; - struct mutex mutex; - u8 port; - u8 alt_port; - u8 atomic_rd_en; - u8 resp_depth; - u8 state; -}; - -struct mlx4_ib_srq { - struct ib_srq ibsrq; - struct mlx4_srq msrq; - struct mlx4_buf buf; - struct mlx4_ib_db db; - u64 *wrid; - spinlock_t lock; - int head; - int tail; - u16 wqe_ctr; - struct ib_umem *umem; - struct mlx4_mtt mtt; - struct mutex mutex; -}; - -struct mlx4_ib_ah { - struct ib_ah ibah; - struct mlx4_av av; -}; - -struct mlx4_ib_dev { - struct ib_device ib_dev; - struct mlx4_dev *dev; - void __iomem *uar_map; - - struct list_head pgdir_list; - struct mutex pgdir_mutex; - - struct mlx4_uar priv_uar; - u32 priv_pdn; - MLX4_DECLARE_DOORBELL_LOCK(uar_lock); - - struct ib_mad_agent *send_agent[MLX4_MAX_PORTS][2]; - struct ib_ah *sm_ah[MLX4_MAX_PORTS]; - spinlock_t sm_lock; - - struct mutex cap_mask_mutex; -}; - -static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev) -{ - return container_of(ibdev, struct mlx4_ib_dev, ib_dev); -} - -static inline struct mlx4_ib_ucontext *to_mucontext(struct ib_ucontext *ibucontext) -{ - return container_of(ibucontext, struct mlx4_ib_ucontext, ibucontext); -} - -static inline struct mlx4_ib_pd *to_mpd(struct ib_pd *ibpd) -{ - return container_of(ibpd, struct mlx4_ib_pd, ibpd); -} - -static inline struct mlx4_ib_cq *to_mcq(struct ib_cq *ibcq) -{ - return container_of(ibcq, struct mlx4_ib_cq, ibcq); -} - -static inline struct mlx4_ib_cq *to_mibcq(struct mlx4_cq *mcq) -{ - return container_of(mcq, struct mlx4_ib_cq, mcq); -} - -static inline struct mlx4_ib_mr *to_mmr(struct ib_mr *ibmr) -{ - return container_of(ibmr, struct mlx4_ib_mr, ibmr); -} - -static inline struct mlx4_ib_qp *to_mqp(struct ib_qp *ibqp) -{ - return container_of(ibqp, struct mlx4_ib_qp, ibqp); -} - -static inline struct mlx4_ib_qp *to_mibqp(struct mlx4_qp *mqp) -{ - return container_of(mqp, struct mlx4_ib_qp, mqp); -} - -static inline struct mlx4_ib_srq *to_msrq(struct ib_srq *ibsrq) -{ - return container_of(ibsrq, struct mlx4_ib_srq, ibsrq); -} - -static inline struct mlx4_ib_srq *to_mibsrq(struct mlx4_srq *msrq) -{ - return container_of(msrq, struct mlx4_ib_srq, msrq); -} - -static inline struct mlx4_ib_ah *to_mah(struct ib_ah *ibah) -{ - return container_of(ibah, struct mlx4_ib_ah, ibah); -} - -int mlx4_ib_db_alloc(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db, int order); -void mlx4_ib_db_free(struct mlx4_ib_dev *dev, struct mlx4_ib_db *db); -int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt, - struct mlx4_ib_db *db); -void mlx4_ib_db_unmap_user(struct mlx4_ib_ucontext *context, struct mlx4_ib_db *db); - -struct ib_mr *mlx4_ib_get_dma_mr(struct ib_pd *pd, int acc); -int mlx4_ib_umem_write_mtt(struct mlx4_ib_dev *dev, struct mlx4_mtt *mtt, - struct ib_umem *umem); -struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt_addr, int access_flags, - struct ib_udata *udata); -int mlx4_ib_dereg_mr(struct ib_mr *mr); - -struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector, - struct ib_ucontext *context, - struct ib_udata *udata); -int mlx4_ib_destroy_cq(struct ib_cq *cq); -int mlx4_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc); -int mlx4_ib_arm_cq(struct ib_cq *cq, enum ib_cq_notify_flags flags); -void __mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq); -void mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq); - -struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr); -int mlx4_ib_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr); -int mlx4_ib_destroy_ah(struct ib_ah *ah); - -struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd, - struct ib_srq_init_attr *init_attr, - struct ib_udata *udata); -int mlx4_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, - enum ib_srq_attr_mask attr_mask, struct ib_udata *udata); -int mlx4_ib_destroy_srq(struct ib_srq *srq); -void mlx4_ib_free_srq_wqe(struct mlx4_ib_srq *srq, int wqe_index); -int mlx4_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, - struct ib_recv_wr **bad_wr); - -struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd, - struct ib_qp_init_attr *init_attr, - struct ib_udata *udata); -int mlx4_ib_destroy_qp(struct ib_qp *qp); -int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, - int attr_mask, struct ib_udata *udata); -int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, - struct ib_send_wr **bad_wr); -int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr, - struct ib_recv_wr **bad_wr); - -int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey, - int port, struct ib_wc *in_wc, struct ib_grh *in_grh, - void *in_mad, void *response_mad); -int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, - struct ib_wc *in_wc, struct ib_grh *in_grh, - struct ib_mad *in_mad, struct ib_mad *out_mad); -int mlx4_ib_mad_init(struct mlx4_ib_dev *dev); -void mlx4_ib_mad_cleanup(struct mlx4_ib_dev *dev); - -static inline int mlx4_ib_ah_grh_present(struct mlx4_ib_ah *ah) -{ - return !!(ah->av.g_slid & 0x80); -} - -#endif /* MLX4_IB_H */ diff --git a/trunk/drivers/infiniband/hw/mlx4/mr.c b/trunk/drivers/infiniband/hw/mlx4/mr.c deleted file mode 100644 index 85ae906f1d12..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/mr.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "mlx4_ib.h" - -static u32 convert_access(int acc) -{ - return (acc & IB_ACCESS_REMOTE_ATOMIC ? MLX4_PERM_ATOMIC : 0) | - (acc & IB_ACCESS_REMOTE_WRITE ? MLX4_PERM_REMOTE_WRITE : 0) | - (acc & IB_ACCESS_REMOTE_READ ? MLX4_PERM_REMOTE_READ : 0) | - (acc & IB_ACCESS_LOCAL_WRITE ? MLX4_PERM_LOCAL_WRITE : 0) | - MLX4_PERM_LOCAL_READ; -} - -struct ib_mr *mlx4_ib_get_dma_mr(struct ib_pd *pd, int acc) -{ - struct mlx4_ib_mr *mr; - int err; - - mr = kmalloc(sizeof *mr, GFP_KERNEL); - if (!mr) - return ERR_PTR(-ENOMEM); - - err = mlx4_mr_alloc(to_mdev(pd->device)->dev, to_mpd(pd)->pdn, 0, - ~0ull, convert_access(acc), 0, 0, &mr->mmr); - if (err) - goto err_free; - - err = mlx4_mr_enable(to_mdev(pd->device)->dev, &mr->mmr); - if (err) - goto err_mr; - - mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; - mr->umem = NULL; - - return &mr->ibmr; - -err_mr: - mlx4_mr_free(to_mdev(pd->device)->dev, &mr->mmr); - -err_free: - kfree(mr); - - return ERR_PTR(err); -} - -int mlx4_ib_umem_write_mtt(struct mlx4_ib_dev *dev, struct mlx4_mtt *mtt, - struct ib_umem *umem) -{ - u64 *pages; - struct ib_umem_chunk *chunk; - int i, j, k; - int n; - int len; - int err = 0; - - pages = (u64 *) __get_free_page(GFP_KERNEL); - if (!pages) - return -ENOMEM; - - i = n = 0; - - list_for_each_entry(chunk, &umem->chunk_list, list) - for (j = 0; j < chunk->nmap; ++j) { - len = sg_dma_len(&chunk->page_list[j]) >> mtt->page_shift; - for (k = 0; k < len; ++k) { - pages[i++] = sg_dma_address(&chunk->page_list[j]) + - umem->page_size * k; - /* - * Be friendly to WRITE_MTT firmware - * command, and pass it chunks of - * appropriate size. - */ - if (i == PAGE_SIZE / sizeof (u64) - 2) { - err = mlx4_write_mtt(dev->dev, mtt, n, - i, pages); - if (err) - goto out; - n += i; - i = 0; - } - } - } - - if (i) - err = mlx4_write_mtt(dev->dev, mtt, n, i, pages); - -out: - free_page((unsigned long) pages); - return err; -} - -struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt_addr, int access_flags, - struct ib_udata *udata) -{ - struct mlx4_ib_dev *dev = to_mdev(pd->device); - struct mlx4_ib_mr *mr; - int shift; - int err; - int n; - - mr = kmalloc(sizeof *mr, GFP_KERNEL); - if (!mr) - return ERR_PTR(-ENOMEM); - - mr->umem = ib_umem_get(pd->uobject->context, start, length, access_flags); - if (IS_ERR(mr->umem)) { - err = PTR_ERR(mr->umem); - goto err_free; - } - - n = ib_umem_page_count(mr->umem); - shift = ilog2(mr->umem->page_size); - - err = mlx4_mr_alloc(dev->dev, to_mpd(pd)->pdn, virt_addr, length, - convert_access(access_flags), n, shift, &mr->mmr); - if (err) - goto err_umem; - - err = mlx4_ib_umem_write_mtt(dev, &mr->mmr.mtt, mr->umem); - if (err) - goto err_mr; - - err = mlx4_mr_enable(dev->dev, &mr->mmr); - if (err) - goto err_mr; - - mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; - - return &mr->ibmr; - -err_mr: - mlx4_mr_free(to_mdev(pd->device)->dev, &mr->mmr); - -err_umem: - ib_umem_release(mr->umem); - -err_free: - kfree(mr); - - return ERR_PTR(err); -} - -int mlx4_ib_dereg_mr(struct ib_mr *ibmr) -{ - struct mlx4_ib_mr *mr = to_mmr(ibmr); - - mlx4_mr_free(to_mdev(ibmr->device)->dev, &mr->mmr); - if (mr->umem) - ib_umem_release(mr->umem); - kfree(mr); - - return 0; -} diff --git a/trunk/drivers/infiniband/hw/mlx4/qp.c b/trunk/drivers/infiniband/hw/mlx4/qp.c deleted file mode 100644 index 5cd706908450..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/qp.c +++ /dev/null @@ -1,1294 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include - -#include "mlx4_ib.h" -#include "user.h" - -enum { - MLX4_IB_ACK_REQ_FREQ = 8, -}; - -enum { - MLX4_IB_DEFAULT_SCHED_QUEUE = 0x83, - MLX4_IB_DEFAULT_QP0_SCHED_QUEUE = 0x3f -}; - -enum { - /* - * Largest possible UD header: send with GRH and immediate data. - */ - MLX4_IB_UD_HEADER_SIZE = 72 -}; - -struct mlx4_ib_sqp { - struct mlx4_ib_qp qp; - int pkey_index; - u32 qkey; - u32 send_psn; - struct ib_ud_header ud_header; - u8 header_buf[MLX4_IB_UD_HEADER_SIZE]; -}; - -static const __be32 mlx4_ib_opcode[] = { - [IB_WR_SEND] = __constant_cpu_to_be32(MLX4_OPCODE_SEND), - [IB_WR_SEND_WITH_IMM] = __constant_cpu_to_be32(MLX4_OPCODE_SEND_IMM), - [IB_WR_RDMA_WRITE] = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_WRITE), - [IB_WR_RDMA_WRITE_WITH_IMM] = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_WRITE_IMM), - [IB_WR_RDMA_READ] = __constant_cpu_to_be32(MLX4_OPCODE_RDMA_READ), - [IB_WR_ATOMIC_CMP_AND_SWP] = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_CS), - [IB_WR_ATOMIC_FETCH_AND_ADD] = __constant_cpu_to_be32(MLX4_OPCODE_ATOMIC_FA), -}; - -static struct mlx4_ib_sqp *to_msqp(struct mlx4_ib_qp *mqp) -{ - return container_of(mqp, struct mlx4_ib_sqp, qp); -} - -static int is_sqp(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp) -{ - return qp->mqp.qpn >= dev->dev->caps.sqp_start && - qp->mqp.qpn <= dev->dev->caps.sqp_start + 3; -} - -static int is_qp0(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp) -{ - return qp->mqp.qpn >= dev->dev->caps.sqp_start && - qp->mqp.qpn <= dev->dev->caps.sqp_start + 1; -} - -static void *get_wqe(struct mlx4_ib_qp *qp, int offset) -{ - if (qp->buf.nbufs == 1) - return qp->buf.u.direct.buf + offset; - else - return qp->buf.u.page_list[offset >> PAGE_SHIFT].buf + - (offset & (PAGE_SIZE - 1)); -} - -static void *get_recv_wqe(struct mlx4_ib_qp *qp, int n) -{ - return get_wqe(qp, qp->rq.offset + (n << qp->rq.wqe_shift)); -} - -static void *get_send_wqe(struct mlx4_ib_qp *qp, int n) -{ - return get_wqe(qp, qp->sq.offset + (n << qp->sq.wqe_shift)); -} - -static void mlx4_ib_qp_event(struct mlx4_qp *qp, enum mlx4_event type) -{ - struct ib_event event; - struct ib_qp *ibqp = &to_mibqp(qp)->ibqp; - - if (type == MLX4_EVENT_TYPE_PATH_MIG) - to_mibqp(qp)->port = to_mibqp(qp)->alt_port; - - if (ibqp->event_handler) { - event.device = ibqp->device; - event.element.qp = ibqp; - switch (type) { - case MLX4_EVENT_TYPE_PATH_MIG: - event.event = IB_EVENT_PATH_MIG; - break; - case MLX4_EVENT_TYPE_COMM_EST: - event.event = IB_EVENT_COMM_EST; - break; - case MLX4_EVENT_TYPE_SQ_DRAINED: - event.event = IB_EVENT_SQ_DRAINED; - break; - case MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE: - event.event = IB_EVENT_QP_LAST_WQE_REACHED; - break; - case MLX4_EVENT_TYPE_WQ_CATAS_ERROR: - event.event = IB_EVENT_QP_FATAL; - break; - case MLX4_EVENT_TYPE_PATH_MIG_FAILED: - event.event = IB_EVENT_PATH_MIG_ERR; - break; - case MLX4_EVENT_TYPE_WQ_INVAL_REQ_ERROR: - event.event = IB_EVENT_QP_REQ_ERR; - break; - case MLX4_EVENT_TYPE_WQ_ACCESS_ERROR: - event.event = IB_EVENT_QP_ACCESS_ERR; - break; - default: - printk(KERN_WARNING "mlx4_ib: Unexpected event type %d " - "on QP %06x\n", type, qp->qpn); - return; - } - - ibqp->event_handler(&event, ibqp->qp_context); - } -} - -static int send_wqe_overhead(enum ib_qp_type type) -{ - /* - * UD WQEs must have a datagram segment. - * RC and UC WQEs might have a remote address segment. - * MLX WQEs need two extra inline data segments (for the UD - * header and space for the ICRC). - */ - switch (type) { - case IB_QPT_UD: - return sizeof (struct mlx4_wqe_ctrl_seg) + - sizeof (struct mlx4_wqe_datagram_seg); - case IB_QPT_UC: - return sizeof (struct mlx4_wqe_ctrl_seg) + - sizeof (struct mlx4_wqe_raddr_seg); - case IB_QPT_RC: - return sizeof (struct mlx4_wqe_ctrl_seg) + - sizeof (struct mlx4_wqe_atomic_seg) + - sizeof (struct mlx4_wqe_raddr_seg); - case IB_QPT_SMI: - case IB_QPT_GSI: - return sizeof (struct mlx4_wqe_ctrl_seg) + - ALIGN(MLX4_IB_UD_HEADER_SIZE + - sizeof (struct mlx4_wqe_inline_seg), - sizeof (struct mlx4_wqe_data_seg)) + - ALIGN(4 + - sizeof (struct mlx4_wqe_inline_seg), - sizeof (struct mlx4_wqe_data_seg)); - default: - return sizeof (struct mlx4_wqe_ctrl_seg); - } -} - -static int set_qp_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap, - enum ib_qp_type type, struct mlx4_ib_qp *qp) -{ - /* Sanity check QP size before proceeding */ - if (cap->max_send_wr > dev->dev->caps.max_wqes || - cap->max_recv_wr > dev->dev->caps.max_wqes || - cap->max_send_sge > dev->dev->caps.max_sq_sg || - cap->max_recv_sge > dev->dev->caps.max_rq_sg || - cap->max_inline_data + send_wqe_overhead(type) + - sizeof (struct mlx4_wqe_inline_seg) > dev->dev->caps.max_sq_desc_sz) - return -EINVAL; - - /* - * For MLX transport we need 2 extra S/G entries: - * one for the header and one for the checksum at the end - */ - if ((type == IB_QPT_SMI || type == IB_QPT_GSI) && - cap->max_send_sge + 2 > dev->dev->caps.max_sq_sg) - return -EINVAL; - - qp->rq.max = cap->max_recv_wr ? roundup_pow_of_two(cap->max_recv_wr) : 0; - qp->sq.max = cap->max_send_wr ? roundup_pow_of_two(cap->max_send_wr) : 0; - - qp->rq.wqe_shift = ilog2(roundup_pow_of_two(cap->max_recv_sge * - sizeof (struct mlx4_wqe_data_seg))); - qp->rq.max_gs = (1 << qp->rq.wqe_shift) / sizeof (struct mlx4_wqe_data_seg); - - qp->sq.wqe_shift = ilog2(roundup_pow_of_two(max(cap->max_send_sge * - sizeof (struct mlx4_wqe_data_seg), - cap->max_inline_data + - sizeof (struct mlx4_wqe_inline_seg)) + - send_wqe_overhead(type))); - qp->sq.max_gs = ((1 << qp->sq.wqe_shift) - send_wqe_overhead(type)) / - sizeof (struct mlx4_wqe_data_seg); - - qp->buf_size = (qp->rq.max << qp->rq.wqe_shift) + - (qp->sq.max << qp->sq.wqe_shift); - if (qp->rq.wqe_shift > qp->sq.wqe_shift) { - qp->rq.offset = 0; - qp->sq.offset = qp->rq.max << qp->rq.wqe_shift; - } else { - qp->rq.offset = qp->sq.max << qp->sq.wqe_shift; - qp->sq.offset = 0; - } - - cap->max_send_wr = qp->sq.max; - cap->max_recv_wr = qp->rq.max; - cap->max_send_sge = qp->sq.max_gs; - cap->max_recv_sge = qp->rq.max_gs; - cap->max_inline_data = (1 << qp->sq.wqe_shift) - send_wqe_overhead(type) - - sizeof (struct mlx4_wqe_inline_seg); - - return 0; -} - -static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, - struct ib_qp_init_attr *init_attr, - struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp) -{ - struct mlx4_wqe_ctrl_seg *ctrl; - int err; - int i; - - mutex_init(&qp->mutex); - spin_lock_init(&qp->sq.lock); - spin_lock_init(&qp->rq.lock); - - qp->state = IB_QPS_RESET; - qp->atomic_rd_en = 0; - qp->resp_depth = 0; - - qp->rq.head = 0; - qp->rq.tail = 0; - qp->sq.head = 0; - qp->sq.tail = 0; - - err = set_qp_size(dev, &init_attr->cap, init_attr->qp_type, qp); - if (err) - goto err; - - if (pd->uobject) { - struct mlx4_ib_create_qp ucmd; - - if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { - err = -EFAULT; - goto err; - } - - qp->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr, - qp->buf_size, 0); - if (IS_ERR(qp->umem)) { - err = PTR_ERR(qp->umem); - goto err; - } - - err = mlx4_mtt_init(dev->dev, ib_umem_page_count(qp->umem), - ilog2(qp->umem->page_size), &qp->mtt); - if (err) - goto err_buf; - - err = mlx4_ib_umem_write_mtt(dev, &qp->mtt, qp->umem); - if (err) - goto err_mtt; - - err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context), - ucmd.db_addr, &qp->db); - if (err) - goto err_mtt; - } else { - err = mlx4_ib_db_alloc(dev, &qp->db, 0); - if (err) - goto err; - - *qp->db.db = 0; - - if (mlx4_buf_alloc(dev->dev, qp->buf_size, PAGE_SIZE * 2, &qp->buf)) { - err = -ENOMEM; - goto err_db; - } - - err = mlx4_mtt_init(dev->dev, qp->buf.npages, qp->buf.page_shift, - &qp->mtt); - if (err) - goto err_buf; - - err = mlx4_buf_write_mtt(dev->dev, &qp->mtt, &qp->buf); - if (err) - goto err_mtt; - - for (i = 0; i < qp->sq.max; ++i) { - ctrl = get_send_wqe(qp, i); - ctrl->owner_opcode = cpu_to_be32(1 << 31); - } - - qp->sq.wrid = kmalloc(qp->sq.max * sizeof (u64), GFP_KERNEL); - qp->rq.wrid = kmalloc(qp->rq.max * sizeof (u64), GFP_KERNEL); - - if (!qp->sq.wrid || !qp->rq.wrid) { - err = -ENOMEM; - goto err_wrid; - } - - /* We don't support inline sends for kernel QPs (yet) */ - init_attr->cap.max_inline_data = 0; - } - - err = mlx4_qp_alloc(dev->dev, sqpn, &qp->mqp); - if (err) - goto err_wrid; - - /* - * Hardware wants QPN written in big-endian order (after - * shifting) for send doorbell. Precompute this value to save - * a little bit when posting sends. - */ - qp->doorbell_qpn = swab32(qp->mqp.qpn << 8); - - if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) - qp->sq_signal_bits = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE); - else - qp->sq_signal_bits = 0; - - qp->mqp.event = mlx4_ib_qp_event; - - return 0; - -err_wrid: - if (pd->uobject) - mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &qp->db); - else { - kfree(qp->sq.wrid); - kfree(qp->rq.wrid); - } - -err_mtt: - mlx4_mtt_cleanup(dev->dev, &qp->mtt); - -err_buf: - if (pd->uobject) - ib_umem_release(qp->umem); - else - mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf); - -err_db: - if (!pd->uobject) - mlx4_ib_db_free(dev, &qp->db); - -err: - return err; -} - -static enum mlx4_qp_state to_mlx4_state(enum ib_qp_state state) -{ - switch (state) { - case IB_QPS_RESET: return MLX4_QP_STATE_RST; - case IB_QPS_INIT: return MLX4_QP_STATE_INIT; - case IB_QPS_RTR: return MLX4_QP_STATE_RTR; - case IB_QPS_RTS: return MLX4_QP_STATE_RTS; - case IB_QPS_SQD: return MLX4_QP_STATE_SQD; - case IB_QPS_SQE: return MLX4_QP_STATE_SQER; - case IB_QPS_ERR: return MLX4_QP_STATE_ERR; - default: return -1; - } -} - -static void mlx4_ib_lock_cqs(struct mlx4_ib_cq *send_cq, struct mlx4_ib_cq *recv_cq) -{ - if (send_cq == recv_cq) - spin_lock_irq(&send_cq->lock); - else if (send_cq->mcq.cqn < recv_cq->mcq.cqn) { - spin_lock_irq(&send_cq->lock); - spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING); - } else { - spin_lock_irq(&recv_cq->lock); - spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING); - } -} - -static void mlx4_ib_unlock_cqs(struct mlx4_ib_cq *send_cq, struct mlx4_ib_cq *recv_cq) -{ - if (send_cq == recv_cq) - spin_unlock_irq(&send_cq->lock); - else if (send_cq->mcq.cqn < recv_cq->mcq.cqn) { - spin_unlock(&recv_cq->lock); - spin_unlock_irq(&send_cq->lock); - } else { - spin_unlock(&send_cq->lock); - spin_unlock_irq(&recv_cq->lock); - } -} - -static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, - int is_user) -{ - struct mlx4_ib_cq *send_cq, *recv_cq; - - if (qp->state != IB_QPS_RESET) - if (mlx4_qp_modify(dev->dev, NULL, to_mlx4_state(qp->state), - MLX4_QP_STATE_RST, NULL, 0, 0, &qp->mqp)) - printk(KERN_WARNING "mlx4_ib: modify QP %06x to RESET failed.\n", - qp->mqp.qpn); - - send_cq = to_mcq(qp->ibqp.send_cq); - recv_cq = to_mcq(qp->ibqp.recv_cq); - - mlx4_ib_lock_cqs(send_cq, recv_cq); - - if (!is_user) { - __mlx4_ib_cq_clean(recv_cq, qp->mqp.qpn, - qp->ibqp.srq ? to_msrq(qp->ibqp.srq): NULL); - if (send_cq != recv_cq) - __mlx4_ib_cq_clean(send_cq, qp->mqp.qpn, NULL); - } - - mlx4_qp_remove(dev->dev, &qp->mqp); - - mlx4_ib_unlock_cqs(send_cq, recv_cq); - - mlx4_qp_free(dev->dev, &qp->mqp); - mlx4_mtt_cleanup(dev->dev, &qp->mtt); - - if (is_user) { - mlx4_ib_db_unmap_user(to_mucontext(qp->ibqp.uobject->context), - &qp->db); - ib_umem_release(qp->umem); - } else { - kfree(qp->sq.wrid); - kfree(qp->rq.wrid); - mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf); - mlx4_ib_db_free(dev, &qp->db); - } -} - -struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd, - struct ib_qp_init_attr *init_attr, - struct ib_udata *udata) -{ - struct mlx4_ib_dev *dev = to_mdev(pd->device); - struct mlx4_ib_sqp *sqp; - struct mlx4_ib_qp *qp; - int err; - - switch (init_attr->qp_type) { - case IB_QPT_RC: - case IB_QPT_UC: - case IB_QPT_UD: - { - qp = kmalloc(sizeof *qp, GFP_KERNEL); - if (!qp) - return ERR_PTR(-ENOMEM); - - err = create_qp_common(dev, pd, init_attr, udata, 0, qp); - if (err) { - kfree(qp); - return ERR_PTR(err); - } - - qp->ibqp.qp_num = qp->mqp.qpn; - - break; - } - case IB_QPT_SMI: - case IB_QPT_GSI: - { - /* Userspace is not allowed to create special QPs: */ - if (pd->uobject) - return ERR_PTR(-EINVAL); - - sqp = kmalloc(sizeof *sqp, GFP_KERNEL); - if (!sqp) - return ERR_PTR(-ENOMEM); - - qp = &sqp->qp; - - err = create_qp_common(dev, pd, init_attr, udata, - dev->dev->caps.sqp_start + - (init_attr->qp_type == IB_QPT_SMI ? 0 : 2) + - init_attr->port_num - 1, - qp); - if (err) { - kfree(sqp); - return ERR_PTR(err); - } - - qp->port = init_attr->port_num; - qp->ibqp.qp_num = init_attr->qp_type == IB_QPT_SMI ? 0 : 1; - - break; - } - default: - /* Don't support raw QPs */ - return ERR_PTR(-EINVAL); - } - - return &qp->ibqp; -} - -int mlx4_ib_destroy_qp(struct ib_qp *qp) -{ - struct mlx4_ib_dev *dev = to_mdev(qp->device); - struct mlx4_ib_qp *mqp = to_mqp(qp); - - if (is_qp0(dev, mqp)) - mlx4_CLOSE_PORT(dev->dev, mqp->port); - - destroy_qp_common(dev, mqp, !!qp->pd->uobject); - - if (is_sqp(dev, mqp)) - kfree(to_msqp(mqp)); - else - kfree(mqp); - - return 0; -} - -static void init_port(struct mlx4_ib_dev *dev, int port) -{ - struct mlx4_init_port_param param; - int err; - - memset(¶m, 0, sizeof param); - - param.port_width_cap = dev->dev->caps.port_width_cap; - param.vl_cap = dev->dev->caps.vl_cap; - param.mtu = ib_mtu_enum_to_int(dev->dev->caps.mtu_cap); - param.max_gid = dev->dev->caps.gid_table_len; - param.max_pkey = dev->dev->caps.pkey_table_len; - - err = mlx4_INIT_PORT(dev->dev, ¶m, port); - if (err) - printk(KERN_WARNING "INIT_PORT failed, return code %d.\n", err); -} - -static int to_mlx4_st(enum ib_qp_type type) -{ - switch (type) { - case IB_QPT_RC: return MLX4_QP_ST_RC; - case IB_QPT_UC: return MLX4_QP_ST_UC; - case IB_QPT_UD: return MLX4_QP_ST_UD; - case IB_QPT_SMI: - case IB_QPT_GSI: return MLX4_QP_ST_MLX; - default: return -1; - } -} - -static __be32 to_mlx4_access_flags(struct mlx4_ib_qp *qp, struct ib_qp_attr *attr, - int attr_mask) -{ - u8 dest_rd_atomic; - u32 access_flags; - u32 hw_access_flags = 0; - - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) - dest_rd_atomic = attr->max_dest_rd_atomic; - else - dest_rd_atomic = qp->resp_depth; - - if (attr_mask & IB_QP_ACCESS_FLAGS) - access_flags = attr->qp_access_flags; - else - access_flags = qp->atomic_rd_en; - - if (!dest_rd_atomic) - access_flags &= IB_ACCESS_REMOTE_WRITE; - - if (access_flags & IB_ACCESS_REMOTE_READ) - hw_access_flags |= MLX4_QP_BIT_RRE; - if (access_flags & IB_ACCESS_REMOTE_ATOMIC) - hw_access_flags |= MLX4_QP_BIT_RAE; - if (access_flags & IB_ACCESS_REMOTE_WRITE) - hw_access_flags |= MLX4_QP_BIT_RWE; - - return cpu_to_be32(hw_access_flags); -} - -static void store_sqp_attrs(struct mlx4_ib_sqp *sqp, struct ib_qp_attr *attr, - int attr_mask) -{ - if (attr_mask & IB_QP_PKEY_INDEX) - sqp->pkey_index = attr->pkey_index; - if (attr_mask & IB_QP_QKEY) - sqp->qkey = attr->qkey; - if (attr_mask & IB_QP_SQ_PSN) - sqp->send_psn = attr->sq_psn; -} - -static void mlx4_set_sched(struct mlx4_qp_path *path, u8 port) -{ - path->sched_queue = (path->sched_queue & 0xbf) | ((port - 1) << 6); -} - -static int mlx4_set_path(struct mlx4_ib_dev *dev, struct ib_ah_attr *ah, - struct mlx4_qp_path *path, u8 port) -{ - path->grh_mylmc = ah->src_path_bits & 0x7f; - path->rlid = cpu_to_be16(ah->dlid); - if (ah->static_rate) { - path->static_rate = ah->static_rate + MLX4_STAT_RATE_OFFSET; - while (path->static_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET && - !(1 << path->static_rate & dev->dev->caps.stat_rate_support)) - --path->static_rate; - } else - path->static_rate = 0; - path->counter_index = 0xff; - - if (ah->ah_flags & IB_AH_GRH) { - if (ah->grh.sgid_index >= dev->dev->caps.gid_table_len) { - printk(KERN_ERR "sgid_index (%u) too large. max is %d\n", - ah->grh.sgid_index, dev->dev->caps.gid_table_len - 1); - return -1; - } - - path->grh_mylmc |= 1 << 7; - path->mgid_index = ah->grh.sgid_index; - path->hop_limit = ah->grh.hop_limit; - path->tclass_flowlabel = - cpu_to_be32((ah->grh.traffic_class << 20) | - (ah->grh.flow_label)); - memcpy(path->rgid, ah->grh.dgid.raw, 16); - } - - path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE | - ((port - 1) << 6) | ((ah->sl & 0xf) << 2); - - return 0; -} - -int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, - int attr_mask, struct ib_udata *udata) -{ - struct mlx4_ib_dev *dev = to_mdev(ibqp->device); - struct mlx4_ib_qp *qp = to_mqp(ibqp); - struct mlx4_qp_context *context; - enum mlx4_qp_optpar optpar = 0; - enum ib_qp_state cur_state, new_state; - int sqd_event; - int err = -EINVAL; - - context = kzalloc(sizeof *context, GFP_KERNEL); - if (!context) - return -ENOMEM; - - mutex_lock(&qp->mutex); - - cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state; - new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state; - - if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask)) - goto out; - - if ((attr_mask & IB_QP_PKEY_INDEX) && - attr->pkey_index >= dev->dev->caps.pkey_table_len) { - goto out; - } - - if ((attr_mask & IB_QP_PORT) && - (attr->port_num == 0 || attr->port_num > dev->dev->caps.num_ports)) { - goto out; - } - - if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && - attr->max_rd_atomic > dev->dev->caps.max_qp_init_rdma) { - goto out; - } - - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC && - attr->max_dest_rd_atomic > 1 << dev->dev->caps.max_qp_dest_rdma) { - goto out; - } - - context->flags = cpu_to_be32((to_mlx4_state(new_state) << 28) | - (to_mlx4_st(ibqp->qp_type) << 16)); - context->flags |= cpu_to_be32(1 << 8); /* DE? */ - - if (!(attr_mask & IB_QP_PATH_MIG_STATE)) - context->flags |= cpu_to_be32(MLX4_QP_PM_MIGRATED << 11); - else { - optpar |= MLX4_QP_OPTPAR_PM_STATE; - switch (attr->path_mig_state) { - case IB_MIG_MIGRATED: - context->flags |= cpu_to_be32(MLX4_QP_PM_MIGRATED << 11); - break; - case IB_MIG_REARM: - context->flags |= cpu_to_be32(MLX4_QP_PM_REARM << 11); - break; - case IB_MIG_ARMED: - context->flags |= cpu_to_be32(MLX4_QP_PM_ARMED << 11); - break; - } - } - - if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI || - ibqp->qp_type == IB_QPT_UD) - context->mtu_msgmax = (IB_MTU_4096 << 5) | 11; - else if (attr_mask & IB_QP_PATH_MTU) { - if (attr->path_mtu < IB_MTU_256 || attr->path_mtu > IB_MTU_4096) { - printk(KERN_ERR "path MTU (%u) is invalid\n", - attr->path_mtu); - return -EINVAL; - } - context->mtu_msgmax = (attr->path_mtu << 5) | 31; - } - - if (qp->rq.max) - context->rq_size_stride = ilog2(qp->rq.max) << 3; - context->rq_size_stride |= qp->rq.wqe_shift - 4; - - if (qp->sq.max) - context->sq_size_stride = ilog2(qp->sq.max) << 3; - context->sq_size_stride |= qp->sq.wqe_shift - 4; - - if (qp->ibqp.uobject) - context->usr_page = cpu_to_be32(to_mucontext(ibqp->uobject->context)->uar.index); - else - context->usr_page = cpu_to_be32(dev->priv_uar.index); - - if (attr_mask & IB_QP_DEST_QPN) - context->remote_qpn = cpu_to_be32(attr->dest_qp_num); - - if (attr_mask & IB_QP_PORT) { - if (cur_state == IB_QPS_SQD && new_state == IB_QPS_SQD && - !(attr_mask & IB_QP_AV)) { - mlx4_set_sched(&context->pri_path, attr->port_num); - optpar |= MLX4_QP_OPTPAR_SCHED_QUEUE; - } - } - - if (attr_mask & IB_QP_PKEY_INDEX) { - context->pri_path.pkey_index = attr->pkey_index; - optpar |= MLX4_QP_OPTPAR_PKEY_INDEX; - } - - if (attr_mask & IB_QP_RNR_RETRY) { - context->params1 |= cpu_to_be32(attr->rnr_retry << 13); - optpar |= MLX4_QP_OPTPAR_RNR_RETRY; - } - - if (attr_mask & IB_QP_AV) { - if (mlx4_set_path(dev, &attr->ah_attr, &context->pri_path, - attr_mask & IB_QP_PORT ? attr->port_num : qp->port)) { - err = -EINVAL; - goto out; - } - - optpar |= (MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH | - MLX4_QP_OPTPAR_SCHED_QUEUE); - } - - if (attr_mask & IB_QP_TIMEOUT) { - context->pri_path.ackto = attr->timeout << 3; - optpar |= MLX4_QP_OPTPAR_ACK_TIMEOUT; - } - - if (attr_mask & IB_QP_ALT_PATH) { - if (attr->alt_pkey_index >= dev->dev->caps.pkey_table_len) - return -EINVAL; - - if (attr->alt_port_num == 0 || - attr->alt_port_num > dev->dev->caps.num_ports) - return -EINVAL; - - if (mlx4_set_path(dev, &attr->alt_ah_attr, &context->alt_path, - attr->alt_port_num)) - return -EINVAL; - - context->alt_path.pkey_index = attr->alt_pkey_index; - context->alt_path.ackto = attr->alt_timeout << 3; - optpar |= MLX4_QP_OPTPAR_ALT_ADDR_PATH; - } - - context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pdn); - context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28); - if (attr_mask & IB_QP_RETRY_CNT) { - context->params1 |= cpu_to_be32(attr->retry_cnt << 16); - optpar |= MLX4_QP_OPTPAR_RETRY_COUNT; - } - - if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) { - if (attr->max_rd_atomic) - context->params1 |= - cpu_to_be32(fls(attr->max_rd_atomic - 1) << 21); - optpar |= MLX4_QP_OPTPAR_SRA_MAX; - } - - if (attr_mask & IB_QP_SQ_PSN) - context->next_send_psn = cpu_to_be32(attr->sq_psn); - - context->cqn_send = cpu_to_be32(to_mcq(ibqp->send_cq)->mcq.cqn); - - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { - if (attr->max_dest_rd_atomic) - context->params2 |= - cpu_to_be32(fls(attr->max_dest_rd_atomic - 1) << 21); - optpar |= MLX4_QP_OPTPAR_RRA_MAX; - } - - if (attr_mask & (IB_QP_ACCESS_FLAGS | IB_QP_MAX_DEST_RD_ATOMIC)) { - context->params2 |= to_mlx4_access_flags(qp, attr, attr_mask); - optpar |= MLX4_QP_OPTPAR_RWE | MLX4_QP_OPTPAR_RRE | MLX4_QP_OPTPAR_RAE; - } - - if (ibqp->srq) - context->params2 |= cpu_to_be32(MLX4_QP_BIT_RIC); - - if (attr_mask & IB_QP_MIN_RNR_TIMER) { - context->rnr_nextrecvpsn |= cpu_to_be32(attr->min_rnr_timer << 24); - optpar |= MLX4_QP_OPTPAR_RNR_TIMEOUT; - } - if (attr_mask & IB_QP_RQ_PSN) - context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn); - - context->cqn_recv = cpu_to_be32(to_mcq(ibqp->recv_cq)->mcq.cqn); - - if (attr_mask & IB_QP_QKEY) { - context->qkey = cpu_to_be32(attr->qkey); - optpar |= MLX4_QP_OPTPAR_Q_KEY; - } - - if (ibqp->srq) - context->srqn = cpu_to_be32(1 << 24 | to_msrq(ibqp->srq)->msrq.srqn); - - if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) - context->db_rec_addr = cpu_to_be64(qp->db.dma); - - if (cur_state == IB_QPS_INIT && - new_state == IB_QPS_RTR && - (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI || - ibqp->qp_type == IB_QPT_UD)) { - context->pri_path.sched_queue = (qp->port - 1) << 6; - if (is_qp0(dev, qp)) - context->pri_path.sched_queue |= MLX4_IB_DEFAULT_QP0_SCHED_QUEUE; - else - context->pri_path.sched_queue |= MLX4_IB_DEFAULT_SCHED_QUEUE; - } - - if (cur_state == IB_QPS_RTS && new_state == IB_QPS_SQD && - attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY && attr->en_sqd_async_notify) - sqd_event = 1; - else - sqd_event = 0; - - err = mlx4_qp_modify(dev->dev, &qp->mtt, to_mlx4_state(cur_state), - to_mlx4_state(new_state), context, optpar, - sqd_event, &qp->mqp); - if (err) - goto out; - - qp->state = new_state; - - if (attr_mask & IB_QP_ACCESS_FLAGS) - qp->atomic_rd_en = attr->qp_access_flags; - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) - qp->resp_depth = attr->max_dest_rd_atomic; - if (attr_mask & IB_QP_PORT) - qp->port = attr->port_num; - if (attr_mask & IB_QP_ALT_PATH) - qp->alt_port = attr->alt_port_num; - - if (is_sqp(dev, qp)) - store_sqp_attrs(to_msqp(qp), attr, attr_mask); - - /* - * If we moved QP0 to RTR, bring the IB link up; if we moved - * QP0 to RESET or ERROR, bring the link back down. - */ - if (is_qp0(dev, qp)) { - if (cur_state != IB_QPS_RTR && new_state == IB_QPS_RTR) - init_port(dev, qp->port); - - if (cur_state != IB_QPS_RESET && cur_state != IB_QPS_ERR && - (new_state == IB_QPS_RESET || new_state == IB_QPS_ERR)) - mlx4_CLOSE_PORT(dev->dev, qp->port); - } - - /* - * If we moved a kernel QP to RESET, clean up all old CQ - * entries and reinitialize the QP. - */ - if (new_state == IB_QPS_RESET && !ibqp->uobject) { - mlx4_ib_cq_clean(to_mcq(ibqp->recv_cq), qp->mqp.qpn, - ibqp->srq ? to_msrq(ibqp->srq): NULL); - if (ibqp->send_cq != ibqp->recv_cq) - mlx4_ib_cq_clean(to_mcq(ibqp->send_cq), qp->mqp.qpn, NULL); - - qp->rq.head = 0; - qp->rq.tail = 0; - qp->sq.head = 0; - qp->sq.tail = 0; - *qp->db.db = 0; - } - -out: - mutex_unlock(&qp->mutex); - kfree(context); - return err; -} - -static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, - void *wqe) -{ - struct ib_device *ib_dev = &to_mdev(sqp->qp.ibqp.device)->ib_dev; - struct mlx4_wqe_mlx_seg *mlx = wqe; - struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx; - struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah); - u16 pkey; - int send_size; - int header_size; - int i; - - send_size = 0; - for (i = 0; i < wr->num_sge; ++i) - send_size += wr->sg_list[i].length; - - ib_ud_header_init(send_size, mlx4_ib_ah_grh_present(ah), &sqp->ud_header); - - sqp->ud_header.lrh.service_level = - be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 28; - sqp->ud_header.lrh.destination_lid = ah->av.dlid; - sqp->ud_header.lrh.source_lid = cpu_to_be16(ah->av.g_slid & 0x7f); - if (mlx4_ib_ah_grh_present(ah)) { - sqp->ud_header.grh.traffic_class = - (be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 20) & 0xff; - sqp->ud_header.grh.flow_label = - ah->av.sl_tclass_flowlabel & cpu_to_be32(0xfffff); - ib_get_cached_gid(ib_dev, be32_to_cpu(ah->av.port_pd) >> 24, - ah->av.gid_index, &sqp->ud_header.grh.source_gid); - memcpy(sqp->ud_header.grh.destination_gid.raw, - ah->av.dgid, 16); - } - - mlx->flags &= cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE); - mlx->flags |= cpu_to_be32((!sqp->qp.ibqp.qp_num ? MLX4_WQE_MLX_VL15 : 0) | - (sqp->ud_header.lrh.destination_lid == - IB_LID_PERMISSIVE ? MLX4_WQE_MLX_SLR : 0) | - (sqp->ud_header.lrh.service_level << 8)); - mlx->rlid = sqp->ud_header.lrh.destination_lid; - - switch (wr->opcode) { - case IB_WR_SEND: - sqp->ud_header.bth.opcode = IB_OPCODE_UD_SEND_ONLY; - sqp->ud_header.immediate_present = 0; - break; - case IB_WR_SEND_WITH_IMM: - sqp->ud_header.bth.opcode = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE; - sqp->ud_header.immediate_present = 1; - sqp->ud_header.immediate_data = wr->imm_data; - break; - default: - return -EINVAL; - } - - sqp->ud_header.lrh.virtual_lane = !sqp->qp.ibqp.qp_num ? 15 : 0; - if (sqp->ud_header.lrh.destination_lid == IB_LID_PERMISSIVE) - sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE; - sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED); - if (!sqp->qp.ibqp.qp_num) - ib_get_cached_pkey(ib_dev, sqp->qp.port, sqp->pkey_index, &pkey); - else - ib_get_cached_pkey(ib_dev, sqp->qp.port, wr->wr.ud.pkey_index, &pkey); - sqp->ud_header.bth.pkey = cpu_to_be16(pkey); - sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->wr.ud.remote_qpn); - sqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1)); - sqp->ud_header.deth.qkey = cpu_to_be32(wr->wr.ud.remote_qkey & 0x80000000 ? - sqp->qkey : wr->wr.ud.remote_qkey); - sqp->ud_header.deth.source_qpn = cpu_to_be32(sqp->qp.ibqp.qp_num); - - header_size = ib_ud_header_pack(&sqp->ud_header, sqp->header_buf); - - if (0) { - printk(KERN_ERR "built UD header of size %d:\n", header_size); - for (i = 0; i < header_size / 4; ++i) { - if (i % 8 == 0) - printk(" [%02x] ", i * 4); - printk(" %08x", - be32_to_cpu(((__be32 *) sqp->header_buf)[i])); - if ((i + 1) % 8 == 0) - printk("\n"); - } - printk("\n"); - } - - inl->byte_count = cpu_to_be32(1 << 31 | header_size); - memcpy(inl + 1, sqp->header_buf, header_size); - - return ALIGN(sizeof (struct mlx4_wqe_inline_seg) + header_size, 16); -} - -static int mlx4_wq_overflow(struct mlx4_ib_wq *wq, int nreq, struct ib_cq *ib_cq) -{ - unsigned cur; - struct mlx4_ib_cq *cq; - - cur = wq->head - wq->tail; - if (likely(cur + nreq < wq->max)) - return 0; - - cq = to_mcq(ib_cq); - spin_lock(&cq->lock); - cur = wq->head - wq->tail; - spin_unlock(&cq->lock); - - return cur + nreq >= wq->max; -} - -int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, - struct ib_send_wr **bad_wr) -{ - struct mlx4_ib_qp *qp = to_mqp(ibqp); - void *wqe; - struct mlx4_wqe_ctrl_seg *ctrl; - unsigned long flags; - int nreq; - int err = 0; - int ind; - int size; - int i; - - spin_lock_irqsave(&qp->rq.lock, flags); - - ind = qp->sq.head; - - for (nreq = 0; wr; ++nreq, wr = wr->next) { - if (mlx4_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)) { - err = -ENOMEM; - *bad_wr = wr; - goto out; - } - - if (unlikely(wr->num_sge > qp->sq.max_gs)) { - err = -EINVAL; - *bad_wr = wr; - goto out; - } - - ctrl = wqe = get_send_wqe(qp, ind & (qp->sq.max - 1)); - qp->sq.wrid[ind & (qp->sq.max - 1)] = wr->wr_id; - - ctrl->srcrb_flags = - (wr->send_flags & IB_SEND_SIGNALED ? - cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE) : 0) | - (wr->send_flags & IB_SEND_SOLICITED ? - cpu_to_be32(MLX4_WQE_CTRL_SOLICITED) : 0) | - qp->sq_signal_bits; - - if (wr->opcode == IB_WR_SEND_WITH_IMM || - wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) - ctrl->imm = wr->imm_data; - else - ctrl->imm = 0; - - wqe += sizeof *ctrl; - size = sizeof *ctrl / 16; - - switch (ibqp->qp_type) { - case IB_QPT_RC: - case IB_QPT_UC: - switch (wr->opcode) { - case IB_WR_ATOMIC_CMP_AND_SWP: - case IB_WR_ATOMIC_FETCH_AND_ADD: - ((struct mlx4_wqe_raddr_seg *) wqe)->raddr = - cpu_to_be64(wr->wr.atomic.remote_addr); - ((struct mlx4_wqe_raddr_seg *) wqe)->rkey = - cpu_to_be32(wr->wr.atomic.rkey); - ((struct mlx4_wqe_raddr_seg *) wqe)->reserved = 0; - - wqe += sizeof (struct mlx4_wqe_raddr_seg); - - if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP) { - ((struct mlx4_wqe_atomic_seg *) wqe)->swap_add = - cpu_to_be64(wr->wr.atomic.swap); - ((struct mlx4_wqe_atomic_seg *) wqe)->compare = - cpu_to_be64(wr->wr.atomic.compare_add); - } else { - ((struct mlx4_wqe_atomic_seg *) wqe)->swap_add = - cpu_to_be64(wr->wr.atomic.compare_add); - ((struct mlx4_wqe_atomic_seg *) wqe)->compare = 0; - } - - wqe += sizeof (struct mlx4_wqe_atomic_seg); - size += (sizeof (struct mlx4_wqe_raddr_seg) + - sizeof (struct mlx4_wqe_atomic_seg)) / 16; - - break; - - case IB_WR_RDMA_READ: - case IB_WR_RDMA_WRITE: - case IB_WR_RDMA_WRITE_WITH_IMM: - ((struct mlx4_wqe_raddr_seg *) wqe)->raddr = - cpu_to_be64(wr->wr.rdma.remote_addr); - ((struct mlx4_wqe_raddr_seg *) wqe)->rkey = - cpu_to_be32(wr->wr.rdma.rkey); - ((struct mlx4_wqe_raddr_seg *) wqe)->reserved = 0; - - wqe += sizeof (struct mlx4_wqe_raddr_seg); - size += sizeof (struct mlx4_wqe_raddr_seg) / 16; - - break; - - default: - /* No extra segments required for sends */ - break; - } - break; - - case IB_QPT_UD: - memcpy(((struct mlx4_wqe_datagram_seg *) wqe)->av, - &to_mah(wr->wr.ud.ah)->av, sizeof (struct mlx4_av)); - ((struct mlx4_wqe_datagram_seg *) wqe)->dqpn = - cpu_to_be32(wr->wr.ud.remote_qpn); - ((struct mlx4_wqe_datagram_seg *) wqe)->qkey = - cpu_to_be32(wr->wr.ud.remote_qkey); - - wqe += sizeof (struct mlx4_wqe_datagram_seg); - size += sizeof (struct mlx4_wqe_datagram_seg) / 16; - break; - - case IB_QPT_SMI: - case IB_QPT_GSI: - err = build_mlx_header(to_msqp(qp), wr, ctrl); - if (err < 0) { - *bad_wr = wr; - goto out; - } - wqe += err; - size += err / 16; - - err = 0; - break; - - default: - break; - } - - for (i = 0; i < wr->num_sge; ++i) { - ((struct mlx4_wqe_data_seg *) wqe)->byte_count = - cpu_to_be32(wr->sg_list[i].length); - ((struct mlx4_wqe_data_seg *) wqe)->lkey = - cpu_to_be32(wr->sg_list[i].lkey); - ((struct mlx4_wqe_data_seg *) wqe)->addr = - cpu_to_be64(wr->sg_list[i].addr); - - wqe += sizeof (struct mlx4_wqe_data_seg); - size += sizeof (struct mlx4_wqe_data_seg) / 16; - } - - /* Add one more inline data segment for ICRC for MLX sends */ - if (qp->ibqp.qp_type == IB_QPT_SMI || qp->ibqp.qp_type == IB_QPT_GSI) { - ((struct mlx4_wqe_inline_seg *) wqe)->byte_count = - cpu_to_be32((1 << 31) | 4); - ((u32 *) wqe)[1] = 0; - wqe += sizeof (struct mlx4_wqe_data_seg); - size += sizeof (struct mlx4_wqe_data_seg) / 16; - } - - ctrl->fence_size = (wr->send_flags & IB_SEND_FENCE ? - MLX4_WQE_CTRL_FENCE : 0) | size; - - /* - * Make sure descriptor is fully written before - * setting ownership bit (because HW can start - * executing as soon as we do). - */ - wmb(); - - if (wr->opcode < 0 || wr->opcode > ARRAY_SIZE(mlx4_ib_opcode)) { - err = -EINVAL; - goto out; - } - - ctrl->owner_opcode = mlx4_ib_opcode[wr->opcode] | - (ind & qp->sq.max ? cpu_to_be32(1 << 31) : 0); - - ++ind; - } - -out: - if (likely(nreq)) { - qp->sq.head += nreq; - - /* - * Make sure that descriptors are written before - * doorbell record. - */ - wmb(); - - writel(qp->doorbell_qpn, - to_mdev(ibqp->device)->uar_map + MLX4_SEND_DOORBELL); - - /* - * Make sure doorbells don't leak out of SQ spinlock - * and reach the HCA out of order. - */ - mmiowb(); - } - - spin_unlock_irqrestore(&qp->rq.lock, flags); - - return err; -} - -int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr, - struct ib_recv_wr **bad_wr) -{ - struct mlx4_ib_qp *qp = to_mqp(ibqp); - struct mlx4_wqe_data_seg *scat; - unsigned long flags; - int err = 0; - int nreq; - int ind; - int i; - - spin_lock_irqsave(&qp->rq.lock, flags); - - ind = qp->rq.head & (qp->rq.max - 1); - - for (nreq = 0; wr; ++nreq, wr = wr->next) { - if (mlx4_wq_overflow(&qp->rq, nreq, qp->ibqp.send_cq)) { - err = -ENOMEM; - *bad_wr = wr; - goto out; - } - - if (unlikely(wr->num_sge > qp->rq.max_gs)) { - err = -EINVAL; - *bad_wr = wr; - goto out; - } - - scat = get_recv_wqe(qp, ind); - - for (i = 0; i < wr->num_sge; ++i) { - scat[i].byte_count = cpu_to_be32(wr->sg_list[i].length); - scat[i].lkey = cpu_to_be32(wr->sg_list[i].lkey); - scat[i].addr = cpu_to_be64(wr->sg_list[i].addr); - } - - if (i < qp->rq.max_gs) { - scat[i].byte_count = 0; - scat[i].lkey = cpu_to_be32(MLX4_INVALID_LKEY); - scat[i].addr = 0; - } - - qp->rq.wrid[ind] = wr->wr_id; - - ind = (ind + 1) & (qp->rq.max - 1); - } - -out: - if (likely(nreq)) { - qp->rq.head += nreq; - - /* - * Make sure that descriptors are written before - * doorbell record. - */ - wmb(); - - *qp->db.db = cpu_to_be32(qp->rq.head & 0xffff); - } - - spin_unlock_irqrestore(&qp->rq.lock, flags); - - return err; -} diff --git a/trunk/drivers/infiniband/hw/mlx4/srq.c b/trunk/drivers/infiniband/hw/mlx4/srq.c deleted file mode 100644 index 42ab4a801d6a..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/srq.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include "mlx4_ib.h" -#include "user.h" - -static void *get_wqe(struct mlx4_ib_srq *srq, int n) -{ - int offset = n << srq->msrq.wqe_shift; - - if (srq->buf.nbufs == 1) - return srq->buf.u.direct.buf + offset; - else - return srq->buf.u.page_list[offset >> PAGE_SHIFT].buf + - (offset & (PAGE_SIZE - 1)); -} - -static void mlx4_ib_srq_event(struct mlx4_srq *srq, enum mlx4_event type) -{ - struct ib_event event; - struct ib_srq *ibsrq = &to_mibsrq(srq)->ibsrq; - - if (ibsrq->event_handler) { - event.device = ibsrq->device; - event.element.srq = ibsrq; - switch (type) { - case MLX4_EVENT_TYPE_SRQ_LIMIT: - event.event = IB_EVENT_SRQ_LIMIT_REACHED; - break; - case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR: - event.event = IB_EVENT_SRQ_ERR; - break; - default: - printk(KERN_WARNING "mlx4_ib: Unexpected event type %d " - "on SRQ %06x\n", type, srq->srqn); - return; - } - - ibsrq->event_handler(&event, ibsrq->srq_context); - } -} - -struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd, - struct ib_srq_init_attr *init_attr, - struct ib_udata *udata) -{ - struct mlx4_ib_dev *dev = to_mdev(pd->device); - struct mlx4_ib_srq *srq; - struct mlx4_wqe_srq_next_seg *next; - int desc_size; - int buf_size; - int err; - int i; - - /* Sanity check SRQ size before proceeding */ - if (init_attr->attr.max_wr >= dev->dev->caps.max_srq_wqes || - init_attr->attr.max_sge > dev->dev->caps.max_srq_sge) - return ERR_PTR(-EINVAL); - - srq = kmalloc(sizeof *srq, GFP_KERNEL); - if (!srq) - return ERR_PTR(-ENOMEM); - - mutex_init(&srq->mutex); - spin_lock_init(&srq->lock); - srq->msrq.max = roundup_pow_of_two(init_attr->attr.max_wr + 1); - srq->msrq.max_gs = init_attr->attr.max_sge; - - desc_size = max(32UL, - roundup_pow_of_two(sizeof (struct mlx4_wqe_srq_next_seg) + - srq->msrq.max_gs * - sizeof (struct mlx4_wqe_data_seg))); - srq->msrq.wqe_shift = ilog2(desc_size); - - buf_size = srq->msrq.max * desc_size; - - if (pd->uobject) { - struct mlx4_ib_create_srq ucmd; - - if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { - err = -EFAULT; - goto err_srq; - } - - srq->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr, - buf_size, 0); - if (IS_ERR(srq->umem)) { - err = PTR_ERR(srq->umem); - goto err_srq; - } - - err = mlx4_mtt_init(dev->dev, ib_umem_page_count(srq->umem), - ilog2(srq->umem->page_size), &srq->mtt); - if (err) - goto err_buf; - - err = mlx4_ib_umem_write_mtt(dev, &srq->mtt, srq->umem); - if (err) - goto err_mtt; - - err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context), - ucmd.db_addr, &srq->db); - if (err) - goto err_mtt; - } else { - err = mlx4_ib_db_alloc(dev, &srq->db, 0); - if (err) - goto err_srq; - - *srq->db.db = 0; - - if (mlx4_buf_alloc(dev->dev, buf_size, PAGE_SIZE * 2, &srq->buf)) { - err = -ENOMEM; - goto err_db; - } - - srq->head = 0; - srq->tail = srq->msrq.max - 1; - srq->wqe_ctr = 0; - - for (i = 0; i < srq->msrq.max; ++i) { - next = get_wqe(srq, i); - next->next_wqe_index = - cpu_to_be16((i + 1) & (srq->msrq.max - 1)); - } - - err = mlx4_mtt_init(dev->dev, srq->buf.npages, srq->buf.page_shift, - &srq->mtt); - if (err) - goto err_buf; - - err = mlx4_buf_write_mtt(dev->dev, &srq->mtt, &srq->buf); - if (err) - goto err_mtt; - - srq->wrid = kmalloc(srq->msrq.max * sizeof (u64), GFP_KERNEL); - if (!srq->wrid) { - err = -ENOMEM; - goto err_mtt; - } - } - - err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, &srq->mtt, - srq->db.dma, &srq->msrq); - if (err) - goto err_wrid; - - srq->msrq.event = mlx4_ib_srq_event; - - if (pd->uobject) - if (ib_copy_to_udata(udata, &srq->msrq.srqn, sizeof (__u32))) { - err = -EFAULT; - goto err_wrid; - } - - init_attr->attr.max_wr = srq->msrq.max - 1; - - return &srq->ibsrq; - -err_wrid: - if (pd->uobject) - mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &srq->db); - else - kfree(srq->wrid); - -err_mtt: - mlx4_mtt_cleanup(dev->dev, &srq->mtt); - -err_buf: - if (pd->uobject) - ib_umem_release(srq->umem); - else - mlx4_buf_free(dev->dev, buf_size, &srq->buf); - -err_db: - if (!pd->uobject) - mlx4_ib_db_free(dev, &srq->db); - -err_srq: - kfree(srq); - - return ERR_PTR(err); -} - -int mlx4_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, - enum ib_srq_attr_mask attr_mask, struct ib_udata *udata) -{ - struct mlx4_ib_dev *dev = to_mdev(ibsrq->device); - struct mlx4_ib_srq *srq = to_msrq(ibsrq); - int ret; - - /* We don't support resizing SRQs (yet?) */ - if (attr_mask & IB_SRQ_MAX_WR) - return -EINVAL; - - if (attr_mask & IB_SRQ_LIMIT) { - if (attr->srq_limit >= srq->msrq.max) - return -EINVAL; - - mutex_lock(&srq->mutex); - ret = mlx4_srq_arm(dev->dev, &srq->msrq, attr->srq_limit); - mutex_unlock(&srq->mutex); - - if (ret) - return ret; - } - - return 0; -} - -int mlx4_ib_destroy_srq(struct ib_srq *srq) -{ - struct mlx4_ib_dev *dev = to_mdev(srq->device); - struct mlx4_ib_srq *msrq = to_msrq(srq); - - mlx4_srq_free(dev->dev, &msrq->msrq); - mlx4_mtt_cleanup(dev->dev, &msrq->mtt); - - if (srq->uobject) { - mlx4_ib_db_unmap_user(to_mucontext(srq->uobject->context), &msrq->db); - ib_umem_release(msrq->umem); - } else { - kfree(msrq->wrid); - mlx4_buf_free(dev->dev, msrq->msrq.max << msrq->msrq.wqe_shift, - &msrq->buf); - mlx4_ib_db_free(dev, &msrq->db); - } - - kfree(msrq); - - return 0; -} - -void mlx4_ib_free_srq_wqe(struct mlx4_ib_srq *srq, int wqe_index) -{ - struct mlx4_wqe_srq_next_seg *next; - - /* always called with interrupts disabled. */ - spin_lock(&srq->lock); - - next = get_wqe(srq, srq->tail); - next->next_wqe_index = cpu_to_be16(wqe_index); - srq->tail = wqe_index; - - spin_unlock(&srq->lock); -} - -int mlx4_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, - struct ib_recv_wr **bad_wr) -{ - struct mlx4_ib_srq *srq = to_msrq(ibsrq); - struct mlx4_wqe_srq_next_seg *next; - struct mlx4_wqe_data_seg *scat; - unsigned long flags; - int err = 0; - int nreq; - int i; - - spin_lock_irqsave(&srq->lock, flags); - - for (nreq = 0; wr; ++nreq, wr = wr->next) { - if (unlikely(wr->num_sge > srq->msrq.max_gs)) { - err = -EINVAL; - *bad_wr = wr; - break; - } - - srq->wrid[srq->head] = wr->wr_id; - - next = get_wqe(srq, srq->head); - srq->head = be16_to_cpu(next->next_wqe_index); - scat = (struct mlx4_wqe_data_seg *) (next + 1); - - for (i = 0; i < wr->num_sge; ++i) { - scat[i].byte_count = cpu_to_be32(wr->sg_list[i].length); - scat[i].lkey = cpu_to_be32(wr->sg_list[i].lkey); - scat[i].addr = cpu_to_be64(wr->sg_list[i].addr); - } - - if (i < srq->msrq.max_gs) { - scat[i].byte_count = 0; - scat[i].lkey = cpu_to_be32(MLX4_INVALID_LKEY); - scat[i].addr = 0; - } - } - - if (likely(nreq)) { - srq->wqe_ctr += nreq; - - /* - * Make sure that descriptors are written before - * doorbell record. - */ - wmb(); - - *srq->db.db = cpu_to_be32(srq->wqe_ctr); - } - - spin_unlock_irqrestore(&srq->lock, flags); - - return err; -} diff --git a/trunk/drivers/infiniband/hw/mlx4/user.h b/trunk/drivers/infiniband/hw/mlx4/user.h deleted file mode 100644 index 5b8eddc9fa83..000000000000 --- a/trunk/drivers/infiniband/hw/mlx4/user.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef MLX4_IB_USER_H -#define MLX4_IB_USER_H - -#include - -/* - * Increment this value if any changes that break userspace ABI - * compatibility are made. - */ -#define MLX4_IB_UVERBS_ABI_VERSION 1 - -/* - * Make sure that all structs defined in this file remain laid out so - * that they pack the same way on 32-bit and 64-bit architectures (to - * avoid incompatibility between 32-bit userspace and 64-bit kernels). - * In particular do not use pointer types -- pass pointers in __u64 - * instead. - */ - -struct mlx4_ib_alloc_ucontext_resp { - __u32 qp_tab_size; - __u16 bf_reg_size; - __u16 bf_regs_per_page; -}; - -struct mlx4_ib_alloc_pd_resp { - __u32 pdn; - __u32 reserved; -}; - -struct mlx4_ib_create_cq { - __u64 buf_addr; - __u64 db_addr; -}; - -struct mlx4_ib_create_cq_resp { - __u32 cqn; - __u32 reserved; -}; - -struct mlx4_ib_resize_cq { - __u64 buf_addr; -}; - -struct mlx4_ib_create_srq { - __u64 buf_addr; - __u64 db_addr; -}; - -struct mlx4_ib_create_srq_resp { - __u32 srqn; - __u32 reserved; -}; - -struct mlx4_ib_create_qp { - __u64 buf_addr; - __u64 db_addr; -}; - -#endif /* MLX4_IB_USER_H */ diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_provider.c b/trunk/drivers/infiniband/hw/mthca/mthca_provider.c index 6bcde1cb9688..1c05486c3c68 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_provider.c @@ -37,7 +37,6 @@ */ #include -#include #include #include @@ -909,8 +908,6 @@ static struct ib_mr *mthca_get_dma_mr(struct ib_pd *pd, int acc) return ERR_PTR(err); } - mr->umem = NULL; - return &mr->ibmr; } @@ -1006,13 +1003,11 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd *pd, } kfree(page_list); - mr->umem = NULL; - return &mr->ibmr; } -static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, - u64 virt, int acc, struct ib_udata *udata) +static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, + int acc, struct ib_udata *udata) { struct mthca_dev *dev = to_mdev(pd->device); struct ib_umem_chunk *chunk; @@ -1023,26 +1018,20 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, int err = 0; int write_mtt_size; + shift = ffs(region->page_size) - 1; + mr = kmalloc(sizeof *mr, GFP_KERNEL); if (!mr) return ERR_PTR(-ENOMEM); - mr->umem = ib_umem_get(pd->uobject->context, start, length, acc); - if (IS_ERR(mr->umem)) { - err = PTR_ERR(mr->umem); - goto err; - } - - shift = ffs(mr->umem->page_size) - 1; - n = 0; - list_for_each_entry(chunk, &mr->umem->chunk_list, list) + list_for_each_entry(chunk, ®ion->chunk_list, list) n += chunk->nents; mr->mtt = mthca_alloc_mtt(dev, n); if (IS_ERR(mr->mtt)) { err = PTR_ERR(mr->mtt); - goto err_umem; + goto err; } pages = (u64 *) __get_free_page(GFP_KERNEL); @@ -1055,12 +1044,12 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, write_mtt_size = min(mthca_write_mtt_size(dev), (int) (PAGE_SIZE / sizeof *pages)); - list_for_each_entry(chunk, &mr->umem->chunk_list, list) + list_for_each_entry(chunk, ®ion->chunk_list, list) for (j = 0; j < chunk->nmap; ++j) { len = sg_dma_len(&chunk->page_list[j]) >> shift; for (k = 0; k < len; ++k) { pages[i++] = sg_dma_address(&chunk->page_list[j]) + - mr->umem->page_size * k; + region->page_size * k; /* * Be friendly to write_mtt and pass it chunks * of appropriate size. @@ -1082,8 +1071,8 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, if (err) goto err_mtt; - err = mthca_mr_alloc(dev, to_mpd(pd)->pd_num, shift, virt, length, - convert_access(acc), mr); + err = mthca_mr_alloc(dev, to_mpd(pd)->pd_num, shift, region->virt_base, + region->length, convert_access(acc), mr); if (err) goto err_mtt; @@ -1093,9 +1082,6 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, err_mtt: mthca_free_mtt(dev, mr->mtt); -err_umem: - ib_umem_release(mr->umem); - err: kfree(mr); return ERR_PTR(err); @@ -1104,12 +1090,8 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, static int mthca_dereg_mr(struct ib_mr *mr) { struct mthca_mr *mmr = to_mmr(mr); - mthca_free_mr(to_mdev(mr->device), mmr); - if (mmr->umem) - ib_umem_release(mmr->umem); kfree(mmr); - return 0; } diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_provider.h b/trunk/drivers/infiniband/hw/mthca/mthca_provider.h index 262616c8ebb6..1d266ac2e094 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_provider.h +++ b/trunk/drivers/infiniband/hw/mthca/mthca_provider.h @@ -73,7 +73,6 @@ struct mthca_mtt; struct mthca_mr { struct ib_mr ibmr; - struct ib_umem *umem; struct mthca_mtt *mtt; }; diff --git a/trunk/drivers/input/Kconfig b/trunk/drivers/input/Kconfig index f814fb3a469d..0e9b69535ad6 100644 --- a/trunk/drivers/input/Kconfig +++ b/trunk/drivers/input/Kconfig @@ -3,7 +3,6 @@ # menu "Input device support" - depends on !S390 config INPUT tristate "Generic input layer (needed for keyboard, mouse, ...)" if EMBEDDED diff --git a/trunk/drivers/isdn/Kconfig b/trunk/drivers/isdn/Kconfig index d42fe89cddf6..c90afeea54aa 100644 --- a/trunk/drivers/isdn/Kconfig +++ b/trunk/drivers/isdn/Kconfig @@ -3,7 +3,6 @@ # menu "ISDN subsystem" - depends on !S390 config ISDN tristate "ISDN support" diff --git a/trunk/drivers/isdn/capi/Kconfig b/trunk/drivers/isdn/capi/Kconfig index c92f9d764fce..c921d6c522f5 100644 --- a/trunk/drivers/isdn/capi/Kconfig +++ b/trunk/drivers/isdn/capi/Kconfig @@ -17,7 +17,7 @@ config CAPI_TRACE help If you say Y here, the kernelcapi driver can make verbose traces of CAPI messages. This feature can be enabled/disabled via IOCTL for - every controller (default disabled). + every controler (default disabled). This will increase the size of the kernelcapi module by 20 KB. If unsure, say Y. diff --git a/trunk/drivers/isdn/hardware/eicon/divasync.h b/trunk/drivers/isdn/hardware/eicon/divasync.h index 85784a7ffb25..af3eb9e795b5 100644 --- a/trunk/drivers/isdn/hardware/eicon/divasync.h +++ b/trunk/drivers/isdn/hardware/eicon/divasync.h @@ -216,7 +216,7 @@ typedef struct #define SERIAL_HOOK_RING 0x85 #define SERIAL_HOOK_DETACH 0x8f unsigned char Flags; /* function refinements */ - /* parameters passed by the ATTACH request */ + /* parameters passed by the the ATTACH request */ SERIAL_INT_CB InterruptHandler; /* called on each interrupt */ SERIAL_DPC_CB DeferredHandler; /* called on hook state changes */ void *HandlerContext; /* context for both handlers */ diff --git a/trunk/drivers/isdn/hisax/hfc_usb.c b/trunk/drivers/isdn/hisax/hfc_usb.c index 1f18f1993387..99e70d4103b6 100644 --- a/trunk/drivers/isdn/hisax/hfc_usb.c +++ b/trunk/drivers/isdn/hisax/hfc_usb.c @@ -1217,11 +1217,11 @@ usb_init(hfcusb_data * hfc) /* aux = output, reset off */ write_usb(hfc, HFCUSB_CIRM, 0x10); - /* set USB_SIZE to match the wMaxPacketSize for INT or BULK transfers */ + /* set USB_SIZE to match the the wMaxPacketSize for INT or BULK transfers */ write_usb(hfc, HFCUSB_USB_SIZE, (hfc->packet_size / 8) | ((hfc->packet_size / 8) << 4)); - /* set USB_SIZE_I to match the wMaxPacketSize for ISO transfers */ + /* set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers */ write_usb(hfc, HFCUSB_USB_SIZE_I, hfc->iso_packet_size); /* enable PCM/GCI master mode */ diff --git a/trunk/drivers/kvm/Kconfig b/trunk/drivers/kvm/Kconfig index e8e37d826478..703cc88d1ef9 100644 --- a/trunk/drivers/kvm/Kconfig +++ b/trunk/drivers/kvm/Kconfig @@ -2,7 +2,6 @@ # KVM configuration # menu "Virtualization" - depends on X86 config KVM tristate "Kernel-based Virtual Machine (KVM) support" diff --git a/trunk/drivers/kvm/kvm_main.c b/trunk/drivers/kvm/kvm_main.c index 0d892600ff00..c8b8cfa332bb 100644 --- a/trunk/drivers/kvm/kvm_main.c +++ b/trunk/drivers/kvm/kvm_main.c @@ -2889,9 +2889,7 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, switch (val) { case CPU_DOWN_PREPARE: - case CPU_DOWN_PREPARE_FROZEN: case CPU_UP_CANCELED: - case CPU_UP_CANCELED_FROZEN: printk(KERN_INFO "kvm: disabling virtualization on CPU%d\n", cpu); decache_vcpus_on_cpu(cpu); @@ -2899,7 +2897,6 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, NULL, 0, 1); break; case CPU_ONLINE: - case CPU_ONLINE_FROZEN: printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n", cpu); smp_call_function_single(cpu, kvm_arch_ops->hardware_enable, diff --git a/trunk/drivers/leds/Kconfig b/trunk/drivers/leds/Kconfig index 87d2046f866c..80acd08f0e97 100644 --- a/trunk/drivers/leds/Kconfig +++ b/trunk/drivers/leds/Kconfig @@ -1,6 +1,5 @@ menu "LED devices" - depends on HAS_IOMEM config NEW_LEDS bool "LED Support" diff --git a/trunk/drivers/leds/leds-h1940.c b/trunk/drivers/leds/leds-h1940.c index 677c99325be5..1d49d2ade557 100644 --- a/trunk/drivers/leds/leds-h1940.c +++ b/trunk/drivers/leds/leds-h1940.c @@ -1,5 +1,5 @@ /* - * drivers/leds/leds-h1940.c + * drivers/leds/h1940-leds.c * Copyright (c) Arnaud Patard * * This file is subject to the terms and conditions of the GNU General Public diff --git a/trunk/drivers/macintosh/Kconfig b/trunk/drivers/macintosh/Kconfig index 58926da0ae18..a32c91e27b3c 100644 --- a/trunk/drivers/macintosh/Kconfig +++ b/trunk/drivers/macintosh/Kconfig @@ -237,7 +237,7 @@ config PMAC_RACKMETER tristate "Support for Apple XServe front panel LEDs" depends on PPC_PMAC help - This driver provides some support to control the front panel + This driver procides some support to control the front panel blue LEDs "vu-meter" of the XServer macs. endif # MACINTOSH_DRIVERS diff --git a/trunk/drivers/macintosh/mediabay.c b/trunk/drivers/macintosh/mediabay.c index c803d2bba65d..0acf2f7fd9d7 100644 --- a/trunk/drivers/macintosh/mediabay.c +++ b/trunk/drivers/macintosh/mediabay.c @@ -563,7 +563,7 @@ static void media_bay_step(int i) ide_init_hwif_ports(&hw, (unsigned long) bay->cd_base, (unsigned long) 0, NULL); hw.irq = bay->cd_irq; hw.chipset = ide_pmac; - bay->cd_index = ide_register_hw(&hw, 0, NULL); + bay->cd_index = ide_register_hw(&hw, NULL); pmu_resume(); } if (bay->cd_index == -1) { diff --git a/trunk/drivers/mca/mca-bus.c b/trunk/drivers/mca/mca-bus.c index 67b8e9453b19..da862e4632dd 100644 --- a/trunk/drivers/mca/mca-bus.c +++ b/trunk/drivers/mca/mca-bus.c @@ -47,25 +47,19 @@ static int mca_bus_match (struct device *dev, struct device_driver *drv) { struct mca_device *mca_dev = to_mca_device (dev); struct mca_driver *mca_drv = to_mca_driver (drv); - const unsigned short *mca_ids = mca_drv->id_table; - int i = 0; - - if (mca_ids) { - for(i = 0; mca_ids[i]; i++) { - if (mca_ids[i] == mca_dev->pos_id) { - mca_dev->index = i; - return 1; - } + const short *mca_ids = mca_drv->id_table; + int i; + + if (!mca_ids) + return 0; + + for(i = 0; mca_ids[i]; i++) { + if (mca_ids[i] == mca_dev->pos_id) { + mca_dev->index = i; + return 1; } } - /* If the integrated id is present, treat it as though it were an - * additional id in the id_table (it can't be because by definition, - * integrated id's overflow a short */ - if (mca_drv->integrated_id && mca_dev->pos_id == - mca_drv->integrated_id) { - mca_dev->index = i; - return 1; - } + return 0; } diff --git a/trunk/drivers/mca/mca-driver.c b/trunk/drivers/mca/mca-driver.c index 32cd39bcc715..2223466b3d8a 100644 --- a/trunk/drivers/mca/mca-driver.c +++ b/trunk/drivers/mca/mca-driver.c @@ -36,25 +36,12 @@ int mca_register_driver(struct mca_driver *mca_drv) mca_drv->driver.bus = &mca_bus_type; if ((r = driver_register(&mca_drv->driver)) < 0) return r; - mca_drv->integrated_id = 0; } return 0; } EXPORT_SYMBOL(mca_register_driver); -int mca_register_driver_integrated(struct mca_driver *mca_driver, - int integrated_id) -{ - int r = mca_register_driver(mca_driver); - - if (!r) - mca_driver->integrated_id = integrated_id; - - return r; -} -EXPORT_SYMBOL(mca_register_driver_integrated); - void mca_unregister_driver(struct mca_driver *mca_drv) { if (MCA_bus) diff --git a/trunk/drivers/md/Kconfig b/trunk/drivers/md/Kconfig index 7df934d69134..4540ade6b6b5 100644 --- a/trunk/drivers/md/Kconfig +++ b/trunk/drivers/md/Kconfig @@ -262,15 +262,6 @@ config DM_MULTIPATH_EMC ---help--- Multipath support for EMC CX/AX series hardware. -config DM_DELAY - tristate "I/O delaying target (EXPERIMENTAL)" - depends on BLK_DEV_DM && EXPERIMENTAL - ---help--- - A target that delays reads and/or writes and can send - them to different devices. Useful for testing. - - If unsure, say N. - endmenu endif diff --git a/trunk/drivers/md/Makefile b/trunk/drivers/md/Makefile index 38754084eac7..34957a68d921 100644 --- a/trunk/drivers/md/Makefile +++ b/trunk/drivers/md/Makefile @@ -31,7 +31,6 @@ obj-$(CONFIG_MD_FAULTY) += faulty.o obj-$(CONFIG_BLK_DEV_MD) += md-mod.o obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o obj-$(CONFIG_DM_CRYPT) += dm-crypt.o -obj-$(CONFIG_DM_DELAY) += dm-delay.o obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o diff --git a/trunk/drivers/md/dm-bio-list.h b/trunk/drivers/md/dm-bio-list.h index c6be88826fae..da4349649f7f 100644 --- a/trunk/drivers/md/dm-bio-list.h +++ b/trunk/drivers/md/dm-bio-list.h @@ -8,43 +8,17 @@ #define DM_BIO_LIST_H #include -#include struct bio_list { struct bio *head; struct bio *tail; }; -static inline int bio_list_empty(const struct bio_list *bl) -{ - return bl->head == NULL; -} - -#define BIO_LIST_INIT { .head = NULL, .tail = NULL } - -#define BIO_LIST(bl) \ - struct bio_list bl = BIO_LIST_INIT - static inline void bio_list_init(struct bio_list *bl) { bl->head = bl->tail = NULL; } -#define bio_list_for_each(bio, bl) \ - for (bio = (bl)->head; bio && ({ prefetch(bio->bi_next); 1; }); \ - bio = bio->bi_next) - -static inline unsigned bio_list_size(const struct bio_list *bl) -{ - unsigned sz = 0; - struct bio *bio; - - bio_list_for_each(bio, bl) - sz++; - - return sz; -} - static inline void bio_list_add(struct bio_list *bl, struct bio *bio) { bio->bi_next = NULL; diff --git a/trunk/drivers/md/dm-crypt.c b/trunk/drivers/md/dm-crypt.c index 7b0fcfc9eaa5..d8121234c347 100644 --- a/trunk/drivers/md/dm-crypt.c +++ b/trunk/drivers/md/dm-crypt.c @@ -33,6 +33,7 @@ struct crypt_io { struct dm_target *target; struct bio *base_bio; + struct bio *first_clone; struct work_struct work; atomic_t pending; int error; @@ -106,8 +107,6 @@ struct crypt_config { static struct kmem_cache *_crypt_io_pool; -static void clone_init(struct crypt_io *, struct bio *); - /* * Different IV generation algorithms: * @@ -121,9 +120,6 @@ static void clone_init(struct crypt_io *, struct bio *); * benbi: the 64-bit "big-endian 'narrow block'-count", starting at 1 * (needed for LRW-32-AES and possible other narrow block modes) * - * null: the initial vector is always zero. Provides compatibility with - * obsolete loop_fish2 devices. Do not use for new devices. - * * plumb: unimplemented, see: * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454 */ @@ -260,13 +256,6 @@ static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector) return 0; } -static int crypt_iv_null_gen(struct crypt_config *cc, u8 *iv, sector_t sector) -{ - memset(iv, 0, cc->iv_size); - - return 0; -} - static struct crypt_iv_operations crypt_iv_plain_ops = { .generator = crypt_iv_plain_gen }; @@ -283,10 +272,6 @@ static struct crypt_iv_operations crypt_iv_benbi_ops = { .generator = crypt_iv_benbi_gen }; -static struct crypt_iv_operations crypt_iv_null_ops = { - .generator = crypt_iv_null_gen -}; - static int crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, struct scatterlist *in, unsigned int length, @@ -393,21 +378,36 @@ static int crypt_convert(struct crypt_config *cc, * This should never violate the device limitations * May return a smaller bio when running out of pages */ -static struct bio *crypt_alloc_buffer(struct crypt_io *io, unsigned int size) +static struct bio * +crypt_alloc_buffer(struct crypt_config *cc, unsigned int size, + struct bio *base_bio, unsigned int *bio_vec_idx) { - struct crypt_config *cc = io->target->private; struct bio *clone; unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM; unsigned int i; - clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, cc->bs); + if (base_bio) { + clone = bio_alloc_bioset(GFP_NOIO, base_bio->bi_max_vecs, cc->bs); + __bio_clone(clone, base_bio); + } else + clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, cc->bs); + if (!clone) return NULL; - clone_init(io, clone); + clone->bi_destructor = dm_crypt_bio_destructor; - for (i = 0; i < nr_iovecs; i++) { + /* if the last bio was not complete, continue where that one ended */ + clone->bi_idx = *bio_vec_idx; + clone->bi_vcnt = *bio_vec_idx; + clone->bi_size = 0; + clone->bi_flags &= ~(1 << BIO_SEG_VALID); + + /* clone->bi_idx pages have already been allocated */ + size -= clone->bi_idx * PAGE_SIZE; + + for (i = clone->bi_idx; i < nr_iovecs; i++) { struct bio_vec *bv = bio_iovec_idx(clone, i); bv->bv_page = mempool_alloc(cc->page_pool, gfp_mask); @@ -419,7 +419,7 @@ static struct bio *crypt_alloc_buffer(struct crypt_io *io, unsigned int size) * return a partially allocated bio, the caller will then try * to allocate additional bios while submitting this partial bio */ - if (i == (MIN_BIO_PAGES - 1)) + if ((i - clone->bi_idx) == (MIN_BIO_PAGES - 1)) gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT; bv->bv_offset = 0; @@ -438,6 +438,12 @@ static struct bio *crypt_alloc_buffer(struct crypt_io *io, unsigned int size) return NULL; } + /* + * Remember the last bio_vec allocated to be able + * to correctly continue after the splitting. + */ + *bio_vec_idx = clone->bi_vcnt; + return clone; } @@ -489,6 +495,9 @@ static void dec_pending(struct crypt_io *io, int error) if (!atomic_dec_and_test(&io->pending)) return; + if (io->first_clone) + bio_put(io->first_clone); + bio_endio(io->base_bio, io->base_bio->bi_size, io->error); mempool_free(io, cc->io_pool); @@ -553,7 +562,6 @@ static void clone_init(struct crypt_io *io, struct bio *clone) clone->bi_end_io = crypt_endio; clone->bi_bdev = cc->dev->bdev; clone->bi_rw = io->base_bio->bi_rw; - clone->bi_destructor = dm_crypt_bio_destructor; } static void process_read(struct crypt_io *io) @@ -577,6 +585,7 @@ static void process_read(struct crypt_io *io) } clone_init(io, clone); + clone->bi_destructor = dm_crypt_bio_destructor; clone->bi_idx = 0; clone->bi_vcnt = bio_segments(base_bio); clone->bi_size = base_bio->bi_size; @@ -595,6 +604,7 @@ static void process_write(struct crypt_io *io) struct convert_context ctx; unsigned remaining = base_bio->bi_size; sector_t sector = base_bio->bi_sector - io->target->begin; + unsigned bvec_idx = 0; atomic_inc(&io->pending); @@ -605,14 +615,14 @@ static void process_write(struct crypt_io *io) * so repeat the whole process until all the data can be handled. */ while (remaining) { - clone = crypt_alloc_buffer(io, remaining); + clone = crypt_alloc_buffer(cc, base_bio->bi_size, + io->first_clone, &bvec_idx); if (unlikely(!clone)) { dec_pending(io, -ENOMEM); return; } ctx.bio_out = clone; - ctx.idx_out = 0; if (unlikely(crypt_convert(cc, &ctx) < 0)) { crypt_free_buffer_pages(cc, clone, clone->bi_size); @@ -621,26 +631,31 @@ static void process_write(struct crypt_io *io) return; } - /* crypt_convert should have filled the clone bio */ - BUG_ON(ctx.idx_out < clone->bi_vcnt); - + clone_init(io, clone); clone->bi_sector = cc->start + sector; + + if (!io->first_clone) { + /* + * hold a reference to the first clone, because it + * holds the bio_vec array and that can't be freed + * before all other clones are released + */ + bio_get(clone); + io->first_clone = clone; + } + remaining -= clone->bi_size; sector += bio_sectors(clone); - /* Grab another reference to the io struct - * before we kick off the request */ + /* prevent bio_put of first_clone */ if (remaining) atomic_inc(&io->pending); generic_make_request(clone); - /* Do not reference clone after this - it - * may be gone already. */ - /* out of memory -> run queues */ if (remaining) - congestion_wait(WRITE, HZ/100); + congestion_wait(bio_data_dir(clone), HZ/100); } } @@ -817,8 +832,6 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) cc->iv_gen_ops = &crypt_iv_essiv_ops; else if (strcmp(ivmode, "benbi") == 0) cc->iv_gen_ops = &crypt_iv_benbi_ops; - else if (strcmp(ivmode, "null") == 0) - cc->iv_gen_ops = &crypt_iv_null_ops; else { ti->error = "Invalid IV mode"; goto bad2; @@ -941,12 +954,10 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, struct crypt_config *cc = ti->private; struct crypt_io *io; - if (bio_barrier(bio)) - return -EOPNOTSUPP; - io = mempool_alloc(cc->io_pool, GFP_NOIO); io->target = ti; io->base_bio = bio; + io->first_clone = NULL; io->error = io->post_process = 0; atomic_set(&io->pending, 0); kcryptd_queue_io(io); @@ -1046,7 +1057,7 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv) static struct target_type crypt_target = { .name = "crypt", - .version= {1, 5, 0}, + .version= {1, 3, 0}, .module = THIS_MODULE, .ctr = crypt_ctr, .dtr = crypt_dtr, diff --git a/trunk/drivers/md/dm-delay.c b/trunk/drivers/md/dm-delay.c deleted file mode 100644 index 52c7cf9e5803..000000000000 --- a/trunk/drivers/md/dm-delay.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (C) 2005-2007 Red Hat GmbH - * - * A target that delays reads and/or writes and can send - * them to different devices. - * - * This file is released under the GPL. - */ - -#include -#include -#include -#include -#include - -#include "dm.h" -#include "dm-bio-list.h" - -#define DM_MSG_PREFIX "delay" - -struct delay_c { - struct timer_list delay_timer; - struct semaphore timer_lock; - struct work_struct flush_expired_bios; - struct list_head delayed_bios; - atomic_t may_delay; - mempool_t *delayed_pool; - - struct dm_dev *dev_read; - sector_t start_read; - unsigned read_delay; - unsigned reads; - - struct dm_dev *dev_write; - sector_t start_write; - unsigned write_delay; - unsigned writes; -}; - -struct delay_info { - struct delay_c *context; - struct list_head list; - struct bio *bio; - unsigned long expires; -}; - -static DEFINE_MUTEX(delayed_bios_lock); - -static struct workqueue_struct *kdelayd_wq; -static struct kmem_cache *delayed_cache; - -static void handle_delayed_timer(unsigned long data) -{ - struct delay_c *dc = (struct delay_c *)data; - - queue_work(kdelayd_wq, &dc->flush_expired_bios); -} - -static void queue_timeout(struct delay_c *dc, unsigned long expires) -{ - down(&dc->timer_lock); - - if (!timer_pending(&dc->delay_timer) || expires < dc->delay_timer.expires) - mod_timer(&dc->delay_timer, expires); - - up(&dc->timer_lock); -} - -static void flush_bios(struct bio *bio) -{ - struct bio *n; - - while (bio) { - n = bio->bi_next; - bio->bi_next = NULL; - generic_make_request(bio); - bio = n; - } -} - -static struct bio *flush_delayed_bios(struct delay_c *dc, int flush_all) -{ - struct delay_info *delayed, *next; - unsigned long next_expires = 0; - int start_timer = 0; - BIO_LIST(flush_bios); - - mutex_lock(&delayed_bios_lock); - list_for_each_entry_safe(delayed, next, &dc->delayed_bios, list) { - if (flush_all || time_after_eq(jiffies, delayed->expires)) { - list_del(&delayed->list); - bio_list_add(&flush_bios, delayed->bio); - if ((bio_data_dir(delayed->bio) == WRITE)) - delayed->context->writes--; - else - delayed->context->reads--; - mempool_free(delayed, dc->delayed_pool); - continue; - } - - if (!start_timer) { - start_timer = 1; - next_expires = delayed->expires; - } else - next_expires = min(next_expires, delayed->expires); - } - - mutex_unlock(&delayed_bios_lock); - - if (start_timer) - queue_timeout(dc, next_expires); - - return bio_list_get(&flush_bios); -} - -static void flush_expired_bios(struct work_struct *work) -{ - struct delay_c *dc; - - dc = container_of(work, struct delay_c, flush_expired_bios); - flush_bios(flush_delayed_bios(dc, 0)); -} - -/* - * Mapping parameters: - * [ ] - * - * With separate write parameters, the first set is only used for reads. - * Delays are specified in milliseconds. - */ -static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) -{ - struct delay_c *dc; - unsigned long long tmpll; - - if (argc != 3 && argc != 6) { - ti->error = "requires exactly 3 or 6 arguments"; - return -EINVAL; - } - - dc = kmalloc(sizeof(*dc), GFP_KERNEL); - if (!dc) { - ti->error = "Cannot allocate context"; - return -ENOMEM; - } - - dc->reads = dc->writes = 0; - - if (sscanf(argv[1], "%llu", &tmpll) != 1) { - ti->error = "Invalid device sector"; - goto bad; - } - dc->start_read = tmpll; - - if (sscanf(argv[2], "%u", &dc->read_delay) != 1) { - ti->error = "Invalid delay"; - goto bad; - } - - if (dm_get_device(ti, argv[0], dc->start_read, ti->len, - dm_table_get_mode(ti->table), &dc->dev_read)) { - ti->error = "Device lookup failed"; - goto bad; - } - - if (argc == 3) { - dc->dev_write = NULL; - goto out; - } - - if (sscanf(argv[4], "%llu", &tmpll) != 1) { - ti->error = "Invalid write device sector"; - goto bad; - } - dc->start_write = tmpll; - - if (sscanf(argv[5], "%u", &dc->write_delay) != 1) { - ti->error = "Invalid write delay"; - goto bad; - } - - if (dm_get_device(ti, argv[3], dc->start_write, ti->len, - dm_table_get_mode(ti->table), &dc->dev_write)) { - ti->error = "Write device lookup failed"; - dm_put_device(ti, dc->dev_read); - goto bad; - } - -out: - dc->delayed_pool = mempool_create_slab_pool(128, delayed_cache); - if (!dc->delayed_pool) { - DMERR("Couldn't create delayed bio pool."); - goto bad; - } - - init_timer(&dc->delay_timer); - dc->delay_timer.function = handle_delayed_timer; - dc->delay_timer.data = (unsigned long)dc; - - INIT_WORK(&dc->flush_expired_bios, flush_expired_bios); - INIT_LIST_HEAD(&dc->delayed_bios); - init_MUTEX(&dc->timer_lock); - atomic_set(&dc->may_delay, 1); - - ti->private = dc; - return 0; - -bad: - kfree(dc); - return -EINVAL; -} - -static void delay_dtr(struct dm_target *ti) -{ - struct delay_c *dc = ti->private; - - flush_workqueue(kdelayd_wq); - - dm_put_device(ti, dc->dev_read); - - if (dc->dev_write) - dm_put_device(ti, dc->dev_write); - - mempool_destroy(dc->delayed_pool); - kfree(dc); -} - -static int delay_bio(struct delay_c *dc, int delay, struct bio *bio) -{ - struct delay_info *delayed; - unsigned long expires = 0; - - if (!delay || !atomic_read(&dc->may_delay)) - return 1; - - delayed = mempool_alloc(dc->delayed_pool, GFP_NOIO); - - delayed->context = dc; - delayed->bio = bio; - delayed->expires = expires = jiffies + (delay * HZ / 1000); - - mutex_lock(&delayed_bios_lock); - - if (bio_data_dir(bio) == WRITE) - dc->writes++; - else - dc->reads++; - - list_add_tail(&delayed->list, &dc->delayed_bios); - - mutex_unlock(&delayed_bios_lock); - - queue_timeout(dc, expires); - - return 0; -} - -static void delay_presuspend(struct dm_target *ti) -{ - struct delay_c *dc = ti->private; - - atomic_set(&dc->may_delay, 0); - del_timer_sync(&dc->delay_timer); - flush_bios(flush_delayed_bios(dc, 1)); -} - -static void delay_resume(struct dm_target *ti) -{ - struct delay_c *dc = ti->private; - - atomic_set(&dc->may_delay, 1); -} - -static int delay_map(struct dm_target *ti, struct bio *bio, - union map_info *map_context) -{ - struct delay_c *dc = ti->private; - - if ((bio_data_dir(bio) == WRITE) && (dc->dev_write)) { - bio->bi_bdev = dc->dev_write->bdev; - bio->bi_sector = dc->start_write + - (bio->bi_sector - ti->begin); - - return delay_bio(dc, dc->write_delay, bio); - } - - bio->bi_bdev = dc->dev_read->bdev; - bio->bi_sector = dc->start_read + - (bio->bi_sector - ti->begin); - - return delay_bio(dc, dc->read_delay, bio); -} - -static int delay_status(struct dm_target *ti, status_type_t type, - char *result, unsigned maxlen) -{ - struct delay_c *dc = ti->private; - int sz = 0; - - switch (type) { - case STATUSTYPE_INFO: - DMEMIT("%u %u", dc->reads, dc->writes); - break; - - case STATUSTYPE_TABLE: - DMEMIT("%s %llu %u", dc->dev_read->name, - (unsigned long long) dc->start_read, - dc->read_delay); - if (dc->dev_write) - DMEMIT("%s %llu %u", dc->dev_write->name, - (unsigned long long) dc->start_write, - dc->write_delay); - break; - } - - return 0; -} - -static struct target_type delay_target = { - .name = "delay", - .version = {1, 0, 2}, - .module = THIS_MODULE, - .ctr = delay_ctr, - .dtr = delay_dtr, - .map = delay_map, - .presuspend = delay_presuspend, - .resume = delay_resume, - .status = delay_status, -}; - -static int __init dm_delay_init(void) -{ - int r = -ENOMEM; - - kdelayd_wq = create_workqueue("kdelayd"); - if (!kdelayd_wq) { - DMERR("Couldn't start kdelayd"); - goto bad_queue; - } - - delayed_cache = kmem_cache_create("dm-delay", - sizeof(struct delay_info), - __alignof__(struct delay_info), - 0, NULL, NULL); - if (!delayed_cache) { - DMERR("Couldn't create delayed bio cache."); - goto bad_memcache; - } - - r = dm_register_target(&delay_target); - if (r < 0) { - DMERR("register failed %d", r); - goto bad_register; - } - - return 0; - -bad_register: - kmem_cache_destroy(delayed_cache); -bad_memcache: - destroy_workqueue(kdelayd_wq); -bad_queue: - return r; -} - -static void __exit dm_delay_exit(void) -{ - int r = dm_unregister_target(&delay_target); - - if (r < 0) - DMERR("unregister failed %d", r); - - kmem_cache_destroy(delayed_cache); - destroy_workqueue(kdelayd_wq); -} - -/* Module hooks */ -module_init(dm_delay_init); -module_exit(dm_delay_exit); - -MODULE_DESCRIPTION(DM_NAME " delay target"); -MODULE_AUTHOR("Heinz Mauelshagen "); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/md/dm-exception-store.c b/trunk/drivers/md/dm-exception-store.c index 07e0a0c84f6e..99cdffa7fbfe 100644 --- a/trunk/drivers/md/dm-exception-store.c +++ b/trunk/drivers/md/dm-exception-store.c @@ -1,8 +1,7 @@ /* - * dm-exception-store.c + * dm-snapshot.c * * Copyright (C) 2001-2002 Sistina Software (UK) Limited. - * Copyright (C) 2006 Red Hat GmbH * * This file is released under the GPL. */ @@ -124,7 +123,6 @@ struct pstore { atomic_t pending_count; uint32_t callback_count; struct commit_callback *callbacks; - struct dm_io_client *io_client; }; static inline unsigned int sectors_to_pages(unsigned int sectors) @@ -161,20 +159,14 @@ static void free_area(struct pstore *ps) */ static int chunk_io(struct pstore *ps, uint32_t chunk, int rw) { - struct io_region where = { - .bdev = ps->snap->cow->bdev, - .sector = ps->snap->chunk_size * chunk, - .count = ps->snap->chunk_size, - }; - struct dm_io_request io_req = { - .bi_rw = rw, - .mem.type = DM_IO_VMA, - .mem.ptr.vma = ps->area, - .client = ps->io_client, - .notify.fn = NULL, - }; - - return dm_io(&io_req, 1, &where, NULL); + struct io_region where; + unsigned long bits; + + where.bdev = ps->snap->cow->bdev; + where.sector = ps->snap->chunk_size * chunk; + where.count = ps->snap->chunk_size; + + return dm_io_sync_vm(1, &where, rw, ps->area, &bits); } /* @@ -221,18 +213,17 @@ static int read_header(struct pstore *ps, int *new_snapshot) chunk_size_supplied = 0; } - ps->io_client = dm_io_client_create(sectors_to_pages(ps->snap-> - chunk_size)); - if (IS_ERR(ps->io_client)) - return PTR_ERR(ps->io_client); + r = dm_io_get(sectors_to_pages(ps->snap->chunk_size)); + if (r) + return r; r = alloc_area(ps); if (r) - return r; + goto bad1; r = chunk_io(ps, 0, READ); if (r) - goto bad; + goto bad2; dh = (struct disk_header *) ps->area; @@ -244,7 +235,7 @@ static int read_header(struct pstore *ps, int *new_snapshot) if (le32_to_cpu(dh->magic) != SNAP_MAGIC) { DMWARN("Invalid or corrupt snapshot"); r = -ENXIO; - goto bad; + goto bad2; } *new_snapshot = 0; @@ -261,22 +252,27 @@ static int read_header(struct pstore *ps, int *new_snapshot) (unsigned long long)ps->snap->chunk_size); /* We had a bogus chunk_size. Fix stuff up. */ + dm_io_put(sectors_to_pages(ps->snap->chunk_size)); free_area(ps); ps->snap->chunk_size = chunk_size; ps->snap->chunk_mask = chunk_size - 1; ps->snap->chunk_shift = ffs(chunk_size) - 1; - r = dm_io_client_resize(sectors_to_pages(ps->snap->chunk_size), - ps->io_client); + r = dm_io_get(sectors_to_pages(chunk_size)); if (r) return r; r = alloc_area(ps); - return r; + if (r) + goto bad1; + + return 0; -bad: +bad2: free_area(ps); +bad1: + dm_io_put(sectors_to_pages(ps->snap->chunk_size)); return r; } @@ -409,7 +405,7 @@ static void persistent_destroy(struct exception_store *store) { struct pstore *ps = get_info(store); - dm_io_client_destroy(ps->io_client); + dm_io_put(sectors_to_pages(ps->snap->chunk_size)); vfree(ps->callbacks); free_area(ps); kfree(ps); diff --git a/trunk/drivers/md/dm-hw-handler.h b/trunk/drivers/md/dm-hw-handler.h index e0832e6fcf36..32eff28e4adc 100644 --- a/trunk/drivers/md/dm-hw-handler.h +++ b/trunk/drivers/md/dm-hw-handler.h @@ -16,7 +16,6 @@ struct hw_handler_type; struct hw_handler { struct hw_handler_type *type; - struct mapped_device *md; void *context; }; diff --git a/trunk/drivers/md/dm-io.c b/trunk/drivers/md/dm-io.c index 352c6fbeac53..8bdc8a87b249 100644 --- a/trunk/drivers/md/dm-io.c +++ b/trunk/drivers/md/dm-io.c @@ -1,6 +1,5 @@ /* * Copyright (C) 2003 Sistina Software - * Copyright (C) 2006 Red Hat GmbH * * This file is released under the GPL. */ @@ -13,17 +12,13 @@ #include #include -struct dm_io_client { - mempool_t *pool; - struct bio_set *bios; -}; +static struct bio_set *_bios; /* FIXME: can we shrink this ? */ struct io { unsigned long error; atomic_t count; struct task_struct *sleeper; - struct dm_io_client *client; io_notify_fn callback; void *context; }; @@ -31,58 +26,63 @@ struct io { /* * io contexts are only dynamically allocated for asynchronous * io. Since async io is likely to be the majority of io we'll - * have the same number of io contexts as bios! (FIXME: must reduce this). + * have the same number of io contexts as buffer heads ! (FIXME: + * must reduce this). */ +static unsigned _num_ios; +static mempool_t *_io_pool; static unsigned int pages_to_ios(unsigned int pages) { return 4 * pages; /* too many ? */ } -/* - * Create a client with mempool and bioset. - */ -struct dm_io_client *dm_io_client_create(unsigned num_pages) +static int resize_pool(unsigned int new_ios) { - unsigned ios = pages_to_ios(num_pages); - struct dm_io_client *client; - - client = kmalloc(sizeof(*client), GFP_KERNEL); - if (!client) - return ERR_PTR(-ENOMEM); - - client->pool = mempool_create_kmalloc_pool(ios, sizeof(struct io)); - if (!client->pool) - goto bad; + int r = 0; + + if (_io_pool) { + if (new_ios == 0) { + /* free off the pool */ + mempool_destroy(_io_pool); + _io_pool = NULL; + bioset_free(_bios); + + } else { + /* resize the pool */ + r = mempool_resize(_io_pool, new_ios, GFP_KERNEL); + } - client->bios = bioset_create(16, 16); - if (!client->bios) - goto bad; + } else { + /* create new pool */ + _io_pool = mempool_create_kmalloc_pool(new_ios, + sizeof(struct io)); + if (!_io_pool) + return -ENOMEM; + + _bios = bioset_create(16, 16); + if (!_bios) { + mempool_destroy(_io_pool); + _io_pool = NULL; + return -ENOMEM; + } + } - return client; + if (!r) + _num_ios = new_ios; - bad: - if (client->pool) - mempool_destroy(client->pool); - kfree(client); - return ERR_PTR(-ENOMEM); + return r; } -EXPORT_SYMBOL(dm_io_client_create); -int dm_io_client_resize(unsigned num_pages, struct dm_io_client *client) +int dm_io_get(unsigned int num_pages) { - return mempool_resize(client->pool, pages_to_ios(num_pages), - GFP_KERNEL); + return resize_pool(_num_ios + pages_to_ios(num_pages)); } -EXPORT_SYMBOL(dm_io_client_resize); -void dm_io_client_destroy(struct dm_io_client *client) +void dm_io_put(unsigned int num_pages) { - mempool_destroy(client->pool); - bioset_free(client->bios); - kfree(client); + resize_pool(_num_ios - pages_to_ios(num_pages)); } -EXPORT_SYMBOL(dm_io_client_destroy); /*----------------------------------------------------------------- * We need to keep track of which region a bio is doing io for. @@ -118,7 +118,7 @@ static void dec_count(struct io *io, unsigned int region, int error) io_notify_fn fn = io->callback; void *context = io->context; - mempool_free(io, io->client->pool); + mempool_free(io, _io_pool); fn(r, context); } } @@ -126,8 +126,7 @@ static void dec_count(struct io *io, unsigned int region, int error) static int endio(struct bio *bio, unsigned int done, int error) { - struct io *io; - unsigned region; + struct io *io = (struct io *) bio->bi_private; /* keep going until we've finished */ if (bio->bi_size) @@ -136,17 +135,10 @@ static int endio(struct bio *bio, unsigned int done, int error) if (error && bio_data_dir(bio) == READ) zero_fill_bio(bio); - /* - * The bio destructor in bio_put() may use the io object. - */ - io = bio->bi_private; - region = bio_get_region(bio); - + dec_count(io, bio_get_region(bio), error); bio->bi_max_vecs++; bio_put(bio); - dec_count(io, region, error); - return 0; } @@ -217,9 +209,6 @@ static void bvec_dp_init(struct dpages *dp, struct bio_vec *bvec) dp->context_ptr = bvec; } -/* - * Functions for getting the pages from a VMA. - */ static void vm_get_page(struct dpages *dp, struct page **p, unsigned long *len, unsigned *offset) { @@ -244,34 +233,7 @@ static void vm_dp_init(struct dpages *dp, void *data) static void dm_bio_destructor(struct bio *bio) { - struct io *io = bio->bi_private; - - bio_free(bio, io->client->bios); -} - -/* - * Functions for getting the pages from kernel memory. - */ -static void km_get_page(struct dpages *dp, struct page **p, unsigned long *len, - unsigned *offset) -{ - *p = virt_to_page(dp->context_ptr); - *offset = dp->context_u; - *len = PAGE_SIZE - dp->context_u; -} - -static void km_next_page(struct dpages *dp) -{ - dp->context_ptr += PAGE_SIZE - dp->context_u; - dp->context_u = 0; -} - -static void km_dp_init(struct dpages *dp, void *data) -{ - dp->get_page = km_get_page; - dp->next_page = km_next_page; - dp->context_u = ((unsigned long) data) & (PAGE_SIZE - 1); - dp->context_ptr = data; + bio_free(bio, _bios); } /*----------------------------------------------------------------- @@ -294,7 +256,7 @@ static void do_region(int rw, unsigned int region, struct io_region *where, * to hide it from bio_add_page(). */ num_bvecs = (remaining / (PAGE_SIZE >> SECTOR_SHIFT)) + 2; - bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios); + bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, _bios); bio->bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; bio->bi_end_io = endio; @@ -349,9 +311,8 @@ static void dispatch_io(int rw, unsigned int num_regions, dec_count(io, 0, 0); } -static int sync_io(struct dm_io_client *client, unsigned int num_regions, - struct io_region *where, int rw, struct dpages *dp, - unsigned long *error_bits) +static int sync_io(unsigned int num_regions, struct io_region *where, + int rw, struct dpages *dp, unsigned long *error_bits) { struct io io; @@ -363,7 +324,6 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions, io.error = 0; atomic_set(&io.count, 1); /* see dispatch_io() */ io.sleeper = current; - io.client = client; dispatch_io(rw, num_regions, where, dp, &io, 1); @@ -380,15 +340,12 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions, if (atomic_read(&io.count)) return -EINTR; - if (error_bits) - *error_bits = io.error; - + *error_bits = io.error; return io.error ? -EIO : 0; } -static int async_io(struct dm_io_client *client, unsigned int num_regions, - struct io_region *where, int rw, struct dpages *dp, - io_notify_fn fn, void *context) +static int async_io(unsigned int num_regions, struct io_region *where, int rw, + struct dpages *dp, io_notify_fn fn, void *context) { struct io *io; @@ -398,11 +355,10 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions, return -EIO; } - io = mempool_alloc(client->pool, GFP_NOIO); + io = mempool_alloc(_io_pool, GFP_NOIO); io->error = 0; atomic_set(&io->count, 1); /* see dispatch_io() */ io->sleeper = NULL; - io->client = client; io->callback = fn; io->context = context; @@ -410,51 +366,61 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions, return 0; } -static int dp_init(struct dm_io_request *io_req, struct dpages *dp) +int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw, + struct page_list *pl, unsigned int offset, + unsigned long *error_bits) { - /* Set up dpages based on memory type */ - switch (io_req->mem.type) { - case DM_IO_PAGE_LIST: - list_dp_init(dp, io_req->mem.ptr.pl, io_req->mem.offset); - break; - - case DM_IO_BVEC: - bvec_dp_init(dp, io_req->mem.ptr.bvec); - break; - - case DM_IO_VMA: - vm_dp_init(dp, io_req->mem.ptr.vma); - break; - - case DM_IO_KMEM: - km_dp_init(dp, io_req->mem.ptr.addr); - break; - - default: - return -EINVAL; - } + struct dpages dp; + list_dp_init(&dp, pl, offset); + return sync_io(num_regions, where, rw, &dp, error_bits); +} - return 0; +int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where, int rw, + struct bio_vec *bvec, unsigned long *error_bits) +{ + struct dpages dp; + bvec_dp_init(&dp, bvec); + return sync_io(num_regions, where, rw, &dp, error_bits); } -/* - * New collapsed (a)synchronous interface - */ -int dm_io(struct dm_io_request *io_req, unsigned num_regions, - struct io_region *where, unsigned long *sync_error_bits) +int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw, + void *data, unsigned long *error_bits) { - int r; struct dpages dp; + vm_dp_init(&dp, data); + return sync_io(num_regions, where, rw, &dp, error_bits); +} - r = dp_init(io_req, &dp); - if (r) - return r; +int dm_io_async(unsigned int num_regions, struct io_region *where, int rw, + struct page_list *pl, unsigned int offset, + io_notify_fn fn, void *context) +{ + struct dpages dp; + list_dp_init(&dp, pl, offset); + return async_io(num_regions, where, rw, &dp, fn, context); +} - if (!io_req->notify.fn) - return sync_io(io_req->client, num_regions, where, - io_req->bi_rw, &dp, sync_error_bits); +int dm_io_async_bvec(unsigned int num_regions, struct io_region *where, int rw, + struct bio_vec *bvec, io_notify_fn fn, void *context) +{ + struct dpages dp; + bvec_dp_init(&dp, bvec); + return async_io(num_regions, where, rw, &dp, fn, context); +} - return async_io(io_req->client, num_regions, where, io_req->bi_rw, - &dp, io_req->notify.fn, io_req->notify.context); +int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw, + void *data, io_notify_fn fn, void *context) +{ + struct dpages dp; + vm_dp_init(&dp, data); + return async_io(num_regions, where, rw, &dp, fn, context); } -EXPORT_SYMBOL(dm_io); + +EXPORT_SYMBOL(dm_io_get); +EXPORT_SYMBOL(dm_io_put); +EXPORT_SYMBOL(dm_io_sync); +EXPORT_SYMBOL(dm_io_async); +EXPORT_SYMBOL(dm_io_sync_bvec); +EXPORT_SYMBOL(dm_io_async_bvec); +EXPORT_SYMBOL(dm_io_sync_vm); +EXPORT_SYMBOL(dm_io_async_vm); diff --git a/trunk/drivers/md/dm-io.h b/trunk/drivers/md/dm-io.h index f647e2cceaa6..f9035bfd1a9f 100644 --- a/trunk/drivers/md/dm-io.h +++ b/trunk/drivers/md/dm-io.h @@ -12,7 +12,7 @@ struct io_region { struct block_device *bdev; sector_t sector; - sector_t count; /* If this is zero the region is ignored. */ + sector_t count; }; struct page_list { @@ -20,60 +20,55 @@ struct page_list { struct page *page; }; -typedef void (*io_notify_fn)(unsigned long error, void *context); - -enum dm_io_mem_type { - DM_IO_PAGE_LIST,/* Page list */ - DM_IO_BVEC, /* Bio vector */ - DM_IO_VMA, /* Virtual memory area */ - DM_IO_KMEM, /* Kernel memory */ -}; -struct dm_io_memory { - enum dm_io_mem_type type; - - union { - struct page_list *pl; - struct bio_vec *bvec; - void *vma; - void *addr; - } ptr; +/* + * 'error' is a bitset, with each bit indicating whether an error + * occurred doing io to the corresponding region. + */ +typedef void (*io_notify_fn)(unsigned long error, void *context); - unsigned offset; -}; - -struct dm_io_notify { - io_notify_fn fn; /* Callback for asynchronous requests */ - void *context; /* Passed to callback */ -}; /* - * IO request structure + * Before anyone uses the IO interface they should call + * dm_io_get(), specifying roughly how many pages they are + * expecting to perform io on concurrently. + * + * This function may block. */ -struct dm_io_client; -struct dm_io_request { - int bi_rw; /* READ|WRITE - not READA */ - struct dm_io_memory mem; /* Memory to use for io */ - struct dm_io_notify notify; /* Synchronous if notify.fn is NULL */ - struct dm_io_client *client; /* Client memory handler */ -}; +int dm_io_get(unsigned int num_pages); +void dm_io_put(unsigned int num_pages); /* - * For async io calls, users can alternatively use the dm_io() function below - * and dm_io_client_create() to create private mempools for the client. + * Synchronous IO. * - * Create/destroy may block. + * Please ensure that the rw flag in the next two functions is + * either READ or WRITE, ie. we don't take READA. Any + * regions with a zero count field will be ignored. */ -struct dm_io_client *dm_io_client_create(unsigned num_pages); -int dm_io_client_resize(unsigned num_pages, struct dm_io_client *client); -void dm_io_client_destroy(struct dm_io_client *client); +int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw, + struct page_list *pl, unsigned int offset, + unsigned long *error_bits); + +int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where, int rw, + struct bio_vec *bvec, unsigned long *error_bits); + +int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw, + void *data, unsigned long *error_bits); /* - * IO interface using private per-client pools. - * Each bit in the optional 'sync_error_bits' bitset indicates whether an - * error occurred doing io to the corresponding region. + * Aynchronous IO. + * + * The 'where' array may be safely allocated on the stack since + * the function takes a copy. */ -int dm_io(struct dm_io_request *io_req, unsigned num_regions, - struct io_region *region, unsigned long *sync_error_bits); +int dm_io_async(unsigned int num_regions, struct io_region *where, int rw, + struct page_list *pl, unsigned int offset, + io_notify_fn fn, void *context); + +int dm_io_async_bvec(unsigned int num_regions, struct io_region *where, int rw, + struct bio_vec *bvec, io_notify_fn fn, void *context); + +int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw, + void *data, io_notify_fn fn, void *context); #endif diff --git a/trunk/drivers/md/dm-log.c b/trunk/drivers/md/dm-log.c index a66428d860fe..6a9261351848 100644 --- a/trunk/drivers/md/dm-log.c +++ b/trunk/drivers/md/dm-log.c @@ -149,12 +149,9 @@ struct log_c { FORCESYNC, /* Force a sync to happen */ } sync; - struct dm_io_request io_req; - /* * Disk log fields */ - int log_dev_failed; struct dm_dev *log_dev; struct log_header header; @@ -202,20 +199,13 @@ static void header_from_disk(struct log_header *core, struct log_header *disk) core->nr_regions = le64_to_cpu(disk->nr_regions); } -static int rw_header(struct log_c *lc, int rw) -{ - lc->io_req.bi_rw = rw; - lc->io_req.mem.ptr.vma = lc->disk_header; - lc->io_req.notify.fn = NULL; - - return dm_io(&lc->io_req, 1, &lc->header_location, NULL); -} - static int read_header(struct log_c *log) { int r; + unsigned long ebits; - r = rw_header(log, READ); + r = dm_io_sync_vm(1, &log->header_location, READ, + log->disk_header, &ebits); if (r) return r; @@ -243,8 +233,11 @@ static int read_header(struct log_c *log) static inline int write_header(struct log_c *log) { + unsigned long ebits; + header_to_disk(&log->header, log->disk_header); - return rw_header(log, WRITE); + return dm_io_sync_vm(1, &log->header_location, WRITE, + log->disk_header, &ebits); } /*---------------------------------------------------------------- @@ -263,7 +256,6 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti, uint32_t region_size; unsigned int region_count; size_t bitset_size, buf_size; - int r; if (argc < 1 || argc > 2) { DMWARN("wrong number of arguments to mirror log"); @@ -323,7 +315,6 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti, lc->disk_header = NULL; } else { lc->log_dev = dev; - lc->log_dev_failed = 0; lc->header_location.bdev = lc->log_dev->bdev; lc->header_location.sector = 0; @@ -333,15 +324,6 @@ static int create_log_context(struct dirty_log *log, struct dm_target *ti, buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + bitset_size, ti->limits.hardsect_size); lc->header_location.count = buf_size >> SECTOR_SHIFT; - lc->io_req.mem.type = DM_IO_VMA; - lc->io_req.client = dm_io_client_create(dm_div_up(buf_size, - PAGE_SIZE)); - if (IS_ERR(lc->io_req.client)) { - r = PTR_ERR(lc->io_req.client); - DMWARN("couldn't allocate disk io client"); - kfree(lc); - return -ENOMEM; - } lc->disk_header = vmalloc(buf_size); if (!lc->disk_header) { @@ -442,7 +424,6 @@ static void disk_dtr(struct dirty_log *log) dm_put_device(lc->ti, lc->log_dev); vfree(lc->disk_header); - dm_io_client_destroy(lc->io_req.client); destroy_log_context(lc); } @@ -456,15 +437,6 @@ static int count_bits32(uint32_t *addr, unsigned size) return count; } -static void fail_log_device(struct log_c *lc) -{ - if (lc->log_dev_failed) - return; - - lc->log_dev_failed = 1; - dm_table_event(lc->ti->table); -} - static int disk_resume(struct dirty_log *log) { int r; @@ -474,19 +446,8 @@ static int disk_resume(struct dirty_log *log) /* read the disk header */ r = read_header(lc); - if (r) { - DMWARN("%s: Failed to read header on mirror log device", - lc->log_dev->name); - fail_log_device(lc); - /* - * If the log device cannot be read, we must assume - * all regions are out-of-sync. If we simply return - * here, the state will be uninitialized and could - * lead us to return 'in-sync' status for regions - * that are actually 'out-of-sync'. - */ - lc->header.nr_regions = 0; - } + if (r) + return r; /* set or clear any new bits -- device has grown */ if (lc->sync == NOSYNC) @@ -511,14 +472,7 @@ static int disk_resume(struct dirty_log *log) lc->header.nr_regions = lc->region_count; /* write the new header */ - r = write_header(lc); - if (r) { - DMWARN("%s: Failed to write header on mirror log device", - lc->log_dev->name); - fail_log_device(lc); - } - - return r; + return write_header(lc); } static uint32_t core_get_region_size(struct dirty_log *log) @@ -562,9 +516,7 @@ static int disk_flush(struct dirty_log *log) return 0; r = write_header(lc); - if (r) - fail_log_device(lc); - else + if (!r) lc->touched = 0; return r; @@ -639,7 +591,6 @@ static int core_status(struct dirty_log *log, status_type_t status, switch(status) { case STATUSTYPE_INFO: - DMEMIT("1 %s", log->type->name); break; case STATUSTYPE_TABLE: @@ -655,17 +606,17 @@ static int disk_status(struct dirty_log *log, status_type_t status, char *result, unsigned int maxlen) { int sz = 0; + char buffer[16]; struct log_c *lc = log->context; switch(status) { case STATUSTYPE_INFO: - DMEMIT("3 %s %s %c", log->type->name, lc->log_dev->name, - lc->log_dev_failed ? 'D' : 'A'); break; case STATUSTYPE_TABLE: + format_dev_t(buffer, lc->log_dev->bdev->bd_dev); DMEMIT("%s %u %s %u ", log->type->name, - lc->sync == DEFAULTSYNC ? 2 : 3, lc->log_dev->name, + lc->sync == DEFAULTSYNC ? 2 : 3, buffer, lc->region_size); DMEMIT_SYNC; } diff --git a/trunk/drivers/md/dm-mpath.c b/trunk/drivers/md/dm-mpath.c index de54b39e6ffe..3aa013506967 100644 --- a/trunk/drivers/md/dm-mpath.c +++ b/trunk/drivers/md/dm-mpath.c @@ -668,9 +668,6 @@ static int parse_hw_handler(struct arg_set *as, struct multipath *m) return -EINVAL; } - m->hw_handler.md = dm_table_get_md(ti->table); - dm_put(m->hw_handler.md); - r = hwht->create(&m->hw_handler, hw_argc - 1, as->argv); if (r) { dm_put_hw_handler(hwht); diff --git a/trunk/drivers/md/dm-raid1.c b/trunk/drivers/md/dm-raid1.c index ef124b71ccc8..23a642619bed 100644 --- a/trunk/drivers/md/dm-raid1.c +++ b/trunk/drivers/md/dm-raid1.c @@ -21,12 +21,16 @@ #include #define DM_MSG_PREFIX "raid1" -#define DM_IO_PAGES 64 - -#define DM_RAID1_HANDLE_ERRORS 0x01 +static struct workqueue_struct *_kmirrord_wq; +static struct work_struct _kmirrord_work; static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped); +static inline void wake(void) +{ + queue_work(_kmirrord_wq, &_kmirrord_work); +} + /*----------------------------------------------------------------- * Region hash * @@ -121,23 +125,17 @@ struct mirror_set { struct list_head list; struct region_hash rh; struct kcopyd_client *kcopyd_client; - uint64_t features; spinlock_t lock; /* protects the next two lists */ struct bio_list reads; struct bio_list writes; - struct dm_io_client *io_client; - /* recovery */ region_t nr_regions; int in_sync; struct mirror *default_mirror; /* Default mirror */ - struct workqueue_struct *kmirrord_wq; - struct work_struct kmirrord_work; - unsigned int nr_mirrors; struct mirror mirror[0]; }; @@ -155,11 +153,6 @@ static inline sector_t region_to_sector(struct region_hash *rh, region_t region) return region << rh->region_shift; } -static void wake(struct mirror_set *ms) -{ - queue_work(ms->kmirrord_wq, &ms->kmirrord_work); -} - /* FIXME move this */ static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw); @@ -405,7 +398,8 @@ static void rh_update_states(struct region_hash *rh) mempool_free(reg, rh->region_pool); } - rh->log->type->flush(rh->log); + if (!list_empty(&recovered)) + rh->log->type->flush(rh->log); list_for_each_entry_safe (reg, next, &clean, list) mempool_free(reg, rh->region_pool); @@ -477,7 +471,7 @@ static void rh_dec(struct region_hash *rh, region_t region) spin_unlock_irqrestore(&rh->region_lock, flags); if (should_wake) - wake(rh->ms); + wake(); } /* @@ -564,7 +558,7 @@ static void rh_recovery_end(struct region *reg, int success) list_add(®->list, ®->rh->recovered_regions); spin_unlock_irq(&rh->region_lock); - wake(rh->ms); + wake(); } static void rh_flush(struct region_hash *rh) @@ -598,7 +592,7 @@ static void rh_start_recovery(struct region_hash *rh) for (i = 0; i < MAX_RECOVERY; i++) up(&rh->recovery_count); - wake(rh->ms); + wake(); } /* @@ -741,7 +735,7 @@ static void do_reads(struct mirror_set *ms, struct bio_list *reads) /* * We can only read balance if the region is in sync. */ - if (rh_in_sync(&ms->rh, region, 1)) + if (rh_in_sync(&ms->rh, region, 0)) m = choose_mirror(ms, bio->bi_sector); else m = ms->default_mirror; @@ -798,14 +792,6 @@ static void do_write(struct mirror_set *ms, struct bio *bio) unsigned int i; struct io_region io[KCOPYD_MAX_REGIONS+1]; struct mirror *m; - struct dm_io_request io_req = { - .bi_rw = WRITE, - .mem.type = DM_IO_BVEC, - .mem.ptr.bvec = bio->bi_io_vec + bio->bi_idx, - .notify.fn = write_callback, - .notify.context = bio, - .client = ms->io_client, - }; for (i = 0; i < ms->nr_mirrors; i++) { m = ms->mirror + i; @@ -816,8 +802,9 @@ static void do_write(struct mirror_set *ms, struct bio *bio) } bio_set_ms(bio, ms); - - (void) dm_io(&io_req, ms->nr_mirrors, io, NULL); + dm_io_async_bvec(ms->nr_mirrors, io, WRITE, + bio->bi_io_vec + bio->bi_idx, + write_callback, bio); } static void do_writes(struct mirror_set *ms, struct bio_list *writes) @@ -883,10 +870,11 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes) /*----------------------------------------------------------------- * kmirrord *---------------------------------------------------------------*/ -static void do_mirror(struct work_struct *work) +static LIST_HEAD(_mirror_sets); +static DECLARE_RWSEM(_mirror_sets_lock); + +static void do_mirror(struct mirror_set *ms) { - struct mirror_set *ms =container_of(work, struct mirror_set, - kmirrord_work); struct bio_list reads, writes; spin_lock(&ms->lock); @@ -902,6 +890,16 @@ static void do_mirror(struct work_struct *work) do_writes(ms, &writes); } +static void do_work(struct work_struct *ignored) +{ + struct mirror_set *ms; + + down_read(&_mirror_sets_lock); + list_for_each_entry (ms, &_mirror_sets, list) + do_mirror(ms); + up_read(&_mirror_sets_lock); +} + /*----------------------------------------------------------------- * Target functions *---------------------------------------------------------------*/ @@ -933,13 +931,6 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors, ms->in_sync = 0; ms->default_mirror = &ms->mirror[DEFAULT_MIRROR]; - ms->io_client = dm_io_client_create(DM_IO_PAGES); - if (IS_ERR(ms->io_client)) { - ti->error = "Error creating dm_io client"; - kfree(ms); - return NULL; - } - if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) { ti->error = "Error creating dirty region hash"; kfree(ms); @@ -955,7 +946,6 @@ static void free_context(struct mirror_set *ms, struct dm_target *ti, while (m--) dm_put_device(ti, ms->mirror[m].dev); - dm_io_client_destroy(ms->io_client); rh_exit(&ms->rh); kfree(ms); } @@ -988,6 +978,23 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti, return 0; } +static int add_mirror_set(struct mirror_set *ms) +{ + down_write(&_mirror_sets_lock); + list_add_tail(&ms->list, &_mirror_sets); + up_write(&_mirror_sets_lock); + wake(); + + return 0; +} + +static void del_mirror_set(struct mirror_set *ms) +{ + down_write(&_mirror_sets_lock); + list_del(&ms->list); + up_write(&_mirror_sets_lock); +} + /* * Create dirty log: log_type #log_params */ @@ -1030,55 +1037,16 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti, return dl; } -static int parse_features(struct mirror_set *ms, unsigned argc, char **argv, - unsigned *args_used) -{ - unsigned num_features; - struct dm_target *ti = ms->ti; - - *args_used = 0; - - if (!argc) - return 0; - - if (sscanf(argv[0], "%u", &num_features) != 1) { - ti->error = "Invalid number of features"; - return -EINVAL; - } - - argc--; - argv++; - (*args_used)++; - - if (num_features > argc) { - ti->error = "Not enough arguments to support feature count"; - return -EINVAL; - } - - if (!strcmp("handle_errors", argv[0])) - ms->features |= DM_RAID1_HANDLE_ERRORS; - else { - ti->error = "Unrecognised feature requested"; - return -EINVAL; - } - - (*args_used)++; - - return 0; -} - /* * Construct a mirror mapping: * * log_type #log_params * #mirrors [mirror_path offset]{2,} - * [#features ] * * log_type is "core" or "disk" * #log_params is between 1 and 3 - * - * If present, features must be "handle_errors". */ +#define DM_IO_PAGES 64 static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) { int r; @@ -1102,8 +1070,8 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) argv++, argc--; - if (argc < nr_mirrors * 2) { - ti->error = "Too few mirror arguments"; + if (argc != nr_mirrors * 2) { + ti->error = "Wrong number of mirror arguments"; dm_destroy_dirty_log(dl); return -EINVAL; } @@ -1128,37 +1096,13 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) ti->private = ms; ti->split_io = ms->rh.region_size; - ms->kmirrord_wq = create_singlethread_workqueue("kmirrord"); - if (!ms->kmirrord_wq) { - DMERR("couldn't start kmirrord"); - free_context(ms, ti, m); - return -ENOMEM; - } - INIT_WORK(&ms->kmirrord_work, do_mirror); - - r = parse_features(ms, argc, argv, &args_used); - if (r) { - free_context(ms, ti, ms->nr_mirrors); - return r; - } - - argv += args_used; - argc -= args_used; - - if (argc) { - ti->error = "Too many mirror arguments"; - free_context(ms, ti, ms->nr_mirrors); - return -EINVAL; - } - r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client); if (r) { - destroy_workqueue(ms->kmirrord_wq); free_context(ms, ti, ms->nr_mirrors); return r; } - wake(ms); + add_mirror_set(ms); return 0; } @@ -1166,9 +1110,8 @@ static void mirror_dtr(struct dm_target *ti) { struct mirror_set *ms = (struct mirror_set *) ti->private; - flush_workqueue(ms->kmirrord_wq); + del_mirror_set(ms); kcopyd_client_destroy(ms->kcopyd_client); - destroy_workqueue(ms->kmirrord_wq); free_context(ms, ti, ms->nr_mirrors); } @@ -1184,7 +1127,7 @@ static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw) spin_unlock(&ms->lock); if (should_wake) - wake(ms); + wake(); } /* @@ -1279,9 +1222,11 @@ static void mirror_resume(struct dm_target *ti) static int mirror_status(struct dm_target *ti, status_type_t type, char *result, unsigned int maxlen) { - unsigned int m, sz = 0; + unsigned int m, sz; struct mirror_set *ms = (struct mirror_set *) ti->private; + sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen); + switch (type) { case STATUSTYPE_INFO: DMEMIT("%d ", ms->nr_mirrors); @@ -1292,21 +1237,13 @@ static int mirror_status(struct dm_target *ti, status_type_t type, (unsigned long long)ms->rh.log->type-> get_sync_count(ms->rh.log), (unsigned long long)ms->nr_regions); - - sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen); - break; case STATUSTYPE_TABLE: - sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen); - DMEMIT("%d", ms->nr_mirrors); for (m = 0; m < ms->nr_mirrors; m++) DMEMIT(" %s %llu", ms->mirror[m].dev->name, (unsigned long long)ms->mirror[m].offset); - - if (ms->features & DM_RAID1_HANDLE_ERRORS) - DMEMIT(" 1 handle_errors"); } return 0; @@ -1314,7 +1251,7 @@ static int mirror_status(struct dm_target *ti, status_type_t type, static struct target_type mirror_target = { .name = "mirror", - .version = {1, 0, 3}, + .version = {1, 0, 2}, .module = THIS_MODULE, .ctr = mirror_ctr, .dtr = mirror_dtr, @@ -1333,11 +1270,20 @@ static int __init dm_mirror_init(void) if (r) return r; + _kmirrord_wq = create_singlethread_workqueue("kmirrord"); + if (!_kmirrord_wq) { + DMERR("couldn't start kmirrord"); + dm_dirty_log_exit(); + return r; + } + INIT_WORK(&_kmirrord_work, do_work); + r = dm_register_target(&mirror_target); if (r < 0) { DMERR("%s: Failed to register mirror target", mirror_target.name); dm_dirty_log_exit(); + destroy_workqueue(_kmirrord_wq); } return r; @@ -1351,6 +1297,7 @@ static void __exit dm_mirror_exit(void) if (r < 0) DMERR("%s: unregister failed %d", mirror_target.name, r); + destroy_workqueue(_kmirrord_wq); dm_dirty_log_exit(); } diff --git a/trunk/drivers/md/dm-table.c b/trunk/drivers/md/dm-table.c index 2fc199b0016b..05befa91807a 100644 --- a/trunk/drivers/md/dm-table.c +++ b/trunk/drivers/md/dm-table.c @@ -425,15 +425,13 @@ static void close_dev(struct dm_dev *d, struct mapped_device *md) } /* - * If possible, this checks an area of a destination device is valid. + * If possible (ie. blk_size[major] is set), this checks an area + * of a destination device is valid. */ static int check_device_area(struct dm_dev *dd, sector_t start, sector_t len) { - sector_t dev_size = dd->bdev->bd_inode->i_size >> SECTOR_SHIFT; - - if (!dev_size) - return 1; - + sector_t dev_size; + dev_size = dd->bdev->bd_inode->i_size >> SECTOR_SHIFT; return ((start < dev_size) && (len <= (dev_size - start))); } diff --git a/trunk/drivers/md/dm.c b/trunk/drivers/md/dm.c index 2717a355dc5b..11a98df298ec 100644 --- a/trunk/drivers/md/dm.c +++ b/trunk/drivers/md/dm.c @@ -1236,7 +1236,6 @@ void dm_put(struct mapped_device *md) free_dev(md); } } -EXPORT_SYMBOL_GPL(dm_put); /* * Process the deferred bios diff --git a/trunk/drivers/md/kcopyd.c b/trunk/drivers/md/kcopyd.c index dbc234e3c69f..b46f6c575f7e 100644 --- a/trunk/drivers/md/kcopyd.c +++ b/trunk/drivers/md/kcopyd.c @@ -1,6 +1,5 @@ /* * Copyright (C) 2002 Sistina Software (UK) Limited. - * Copyright (C) 2006 Red Hat GmbH * * This file is released under the GPL. * @@ -46,8 +45,6 @@ struct kcopyd_client { unsigned int nr_pages; unsigned int nr_free_pages; - struct dm_io_client *io_client; - wait_queue_head_t destroyq; atomic_t nr_jobs; }; @@ -345,20 +342,16 @@ static void complete_io(unsigned long error, void *context) static int run_io_job(struct kcopyd_job *job) { int r; - struct dm_io_request io_req = { - .bi_rw = job->rw, - .mem.type = DM_IO_PAGE_LIST, - .mem.ptr.pl = job->pages, - .mem.offset = job->offset, - .notify.fn = complete_io, - .notify.context = job, - .client = job->kc->io_client, - }; if (job->rw == READ) - r = dm_io(&io_req, 1, &job->source, NULL); + r = dm_io_async(1, &job->source, job->rw, + job->pages, + job->offset, complete_io, job); + else - r = dm_io(&io_req, job->num_dests, job->dests, NULL); + r = dm_io_async(job->num_dests, job->dests, job->rw, + job->pages, + job->offset, complete_io, job); return r; } @@ -677,9 +670,8 @@ int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result) return r; } - kc->io_client = dm_io_client_create(nr_pages); - if (IS_ERR(kc->io_client)) { - r = PTR_ERR(kc->io_client); + r = dm_io_get(nr_pages); + if (r) { client_free_pages(kc); kfree(kc); kcopyd_exit(); @@ -699,7 +691,7 @@ void kcopyd_client_destroy(struct kcopyd_client *kc) /* Wait for completion of all jobs submitted by this client. */ wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs)); - dm_io_client_destroy(kc->io_client); + dm_io_put(kc->nr_pages); client_free_pages(kc); client_del(kc); kfree(kc); diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index 65814b0340cb..2b4315d7e5d6 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -33,7 +33,6 @@ */ #include -#include #include #include #include @@ -274,7 +273,6 @@ static mddev_t * mddev_find(dev_t unit) atomic_set(&new->active, 1); spin_lock_init(&new->write_lock); init_waitqueue_head(&new->sb_wait); - new->reshape_position = MaxSector; new->queue = blk_alloc_queue(GFP_KERNEL); if (!new->queue) { @@ -591,41 +589,14 @@ static int sb_equal(mdp_super_t *sb1, mdp_super_t *sb2) return ret; } - -static u32 md_csum_fold(u32 csum) -{ - csum = (csum & 0xffff) + (csum >> 16); - return (csum & 0xffff) + (csum >> 16); -} - static unsigned int calc_sb_csum(mdp_super_t * sb) { - u64 newcsum = 0; - u32 *sb32 = (u32*)sb; - int i; unsigned int disk_csum, csum; disk_csum = sb->sb_csum; sb->sb_csum = 0; - - for (i = 0; i < MD_SB_BYTES/4 ; i++) - newcsum += sb32[i]; - csum = (newcsum & 0xffffffff) + (newcsum>>32); - - -#ifdef CONFIG_ALPHA - /* This used to use csum_partial, which was wrong for several - * reasons including that different results are returned on - * different architectures. It isn't critical that we get exactly - * the same return value as before (we always csum_fold before - * testing, and that removes any differences). However as we - * know that csum_partial always returned a 16bit value on - * alphas, do a fold to maximise conformity to previous behaviour. - */ - sb->sb_csum = md_csum_fold(disk_csum); -#else + csum = csum_partial((void *)sb, MD_SB_BYTES, 0); sb->sb_csum = disk_csum; -#endif return csum; } @@ -713,7 +684,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version if (sb->raid_disks <= 0) goto abort; - if (md_csum_fold(calc_sb_csum(sb)) != md_csum_fold(sb->sb_csum)) { + if (csum_fold(calc_sb_csum(sb)) != csum_fold(sb->sb_csum)) { printk(KERN_WARNING "md: invalid superblock checksum on %s\n", b); goto abort; @@ -723,17 +694,6 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version rdev->data_offset = 0; rdev->sb_size = MD_SB_BYTES; - if (sb->state & (1<level != 1 && sb->level != 4 - && sb->level != 5 && sb->level != 6 - && sb->level != 10) { - /* FIXME use a better test */ - printk(KERN_WARNING - "md: bitmaps not supported for this level.\n"); - goto abort; - } - } - if (sb->level == LEVEL_MULTIPATH) rdev->desc_nr = -1; else @@ -832,8 +792,16 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) mddev->max_disks = MD_SB_DISKS; if (sb->state & (1<bitmap_file == NULL) + mddev->bitmap_file == NULL) { + if (mddev->level != 1 && mddev->level != 4 + && mddev->level != 5 && mddev->level != 6 + && mddev->level != 10) { + /* FIXME use a better test */ + printk(KERN_WARNING "md: bitmaps not supported for this level.\n"); + return -EINVAL; + } mddev->bitmap_offset = mddev->default_bitmap_offset; + } } else if (mddev->pers == NULL) { /* Insist on good event counter while assembling */ @@ -1090,18 +1058,6 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) bdevname(rdev->bdev,b)); return -EINVAL; } - if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET)) { - if (sb->level != cpu_to_le32(1) && - sb->level != cpu_to_le32(4) && - sb->level != cpu_to_le32(5) && - sb->level != cpu_to_le32(6) && - sb->level != cpu_to_le32(10)) { - printk(KERN_WARNING - "md: bitmaps not supported for this level.\n"); - return -EINVAL; - } - } - rdev->preferred_minor = 0xffff; rdev->data_offset = le64_to_cpu(sb->data_offset); atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read)); @@ -1185,9 +1141,14 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) mddev->max_disks = (4096-256)/2; if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) && - mddev->bitmap_file == NULL ) + mddev->bitmap_file == NULL ) { + if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6 + && mddev->level != 10) { + printk(KERN_WARNING "md: bitmaps not supported for this level.\n"); + return -EINVAL; + } mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset); - + } if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) { mddev->reshape_position = le64_to_cpu(sb->reshape_position); mddev->delta_disks = le32_to_cpu(sb->delta_disks); @@ -2243,10 +2204,6 @@ static ssize_t layout_show(mddev_t *mddev, char *page) { /* just a number, not meaningful for all levels */ - if (mddev->reshape_position != MaxSector && - mddev->layout != mddev->new_layout) - return sprintf(page, "%d (%d)\n", - mddev->new_layout, mddev->layout); return sprintf(page, "%d\n", mddev->layout); } @@ -2255,16 +2212,13 @@ layout_store(mddev_t *mddev, const char *buf, size_t len) { char *e; unsigned long n = simple_strtoul(buf, &e, 10); + if (mddev->pers) + return -EBUSY; if (!*buf || (*e && *e != '\n')) return -EINVAL; - if (mddev->pers) - return -EBUSY; - if (mddev->reshape_position != MaxSector) - mddev->new_layout = n; - else - mddev->layout = n; + mddev->layout = n; return len; } static struct md_sysfs_entry md_layout = @@ -2276,10 +2230,6 @@ raid_disks_show(mddev_t *mddev, char *page) { if (mddev->raid_disks == 0) return 0; - if (mddev->reshape_position != MaxSector && - mddev->delta_disks != 0) - return sprintf(page, "%d (%d)\n", mddev->raid_disks, - mddev->raid_disks - mddev->delta_disks); return sprintf(page, "%d\n", mddev->raid_disks); } @@ -2297,11 +2247,7 @@ raid_disks_store(mddev_t *mddev, const char *buf, size_t len) if (mddev->pers) rv = update_raid_disks(mddev, n); - else if (mddev->reshape_position != MaxSector) { - int olddisks = mddev->raid_disks - mddev->delta_disks; - mddev->delta_disks = n - olddisks; - mddev->raid_disks = n; - } else + else mddev->raid_disks = n; return rv ? rv : len; } @@ -2311,10 +2257,6 @@ __ATTR(raid_disks, S_IRUGO|S_IWUSR, raid_disks_show, raid_disks_store); static ssize_t chunk_size_show(mddev_t *mddev, char *page) { - if (mddev->reshape_position != MaxSector && - mddev->chunk_size != mddev->new_chunk) - return sprintf(page, "%d (%d)\n", mddev->new_chunk, - mddev->chunk_size); return sprintf(page, "%d\n", mddev->chunk_size); } @@ -2325,15 +2267,12 @@ chunk_size_store(mddev_t *mddev, const char *buf, size_t len) char *e; unsigned long n = simple_strtoul(buf, &e, 10); + if (mddev->pers) + return -EBUSY; if (!*buf || (*e && *e != '\n')) return -EINVAL; - if (mddev->pers) - return -EBUSY; - else if (mddev->reshape_position != MaxSector) - mddev->new_chunk = n; - else - mddev->chunk_size = n; + mddev->chunk_size = n; return len; } static struct md_sysfs_entry md_chunk_size = @@ -2698,7 +2637,8 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len) minor = simple_strtoul(buf, &e, 10); if (e==buf || (*e && *e != '\n') ) return -EINVAL; - if (major >= ARRAY_SIZE(super_types) || super_types[major].name == NULL) + if (major >= sizeof(super_types)/sizeof(super_types[0]) || + super_types[major].name == NULL) return -ENOENT; mddev->major_version = major; mddev->minor_version = minor; @@ -2919,37 +2859,6 @@ suspend_hi_store(mddev_t *mddev, const char *buf, size_t len) static struct md_sysfs_entry md_suspend_hi = __ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store); -static ssize_t -reshape_position_show(mddev_t *mddev, char *page) -{ - if (mddev->reshape_position != MaxSector) - return sprintf(page, "%llu\n", - (unsigned long long)mddev->reshape_position); - strcpy(page, "none\n"); - return 5; -} - -static ssize_t -reshape_position_store(mddev_t *mddev, const char *buf, size_t len) -{ - char *e; - unsigned long long new = simple_strtoull(buf, &e, 10); - if (mddev->pers) - return -EBUSY; - if (buf == e || (*e && *e != '\n')) - return -EINVAL; - mddev->reshape_position = new; - mddev->delta_disks = 0; - mddev->new_level = mddev->level; - mddev->new_layout = mddev->layout; - mddev->new_chunk = mddev->chunk_size; - return len; -} - -static struct md_sysfs_entry md_reshape_position = -__ATTR(reshape_position, S_IRUGO|S_IWUSR, reshape_position_show, - reshape_position_store); - static struct attribute *md_default_attrs[] = { &md_level.attr, @@ -2962,7 +2871,6 @@ static struct attribute *md_default_attrs[] = { &md_new_device.attr, &md_safe_delay.attr, &md_array_state.attr, - &md_reshape_position.attr, NULL, }; @@ -3501,7 +3409,6 @@ static int do_md_stop(mddev_t * mddev, int mode) mddev->size = 0; mddev->raid_disks = 0; mddev->recovery_cp = 0; - mddev->reshape_position = MaxSector; } else if (mddev->pers) printk(KERN_INFO "md: %s switched to read-only mode.\n", @@ -4112,7 +4019,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) if (info->raid_disks == 0) { /* just setting version number for superblock loading */ if (info->major_version < 0 || - info->major_version >= ARRAY_SIZE(super_types) || + info->major_version >= sizeof(super_types)/sizeof(super_types[0]) || super_types[info->major_version].name == NULL) { /* maybe try to auto-load a module? */ printk(KERN_INFO @@ -5034,6 +4941,15 @@ static int md_seq_open(struct inode *inode, struct file *file) return error; } +static int md_seq_release(struct inode *inode, struct file *file) +{ + struct seq_file *m = file->private_data; + struct mdstat_info *mi = m->private; + m->private = NULL; + kfree(mi); + return seq_release(inode, file); +} + static unsigned int mdstat_poll(struct file *filp, poll_table *wait) { struct seq_file *m = filp->private_data; @@ -5055,7 +4971,7 @@ static const struct file_operations md_seq_fops = { .open = md_seq_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_private, + .release = md_seq_release, .poll = mdstat_poll, }; diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c index 3a95cc5e029c..97ee870b265d 100644 --- a/trunk/drivers/md/raid1.c +++ b/trunk/drivers/md/raid1.c @@ -271,25 +271,21 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int */ update_head_pos(mirror, r1_bio); - if (uptodate) - set_bit(R1BIO_Uptodate, &r1_bio->state); - else { - /* If all other devices have failed, we want to return - * the error upwards rather than fail the last device. - * Here we redefine "uptodate" to mean "Don't want to retry" + if (uptodate || (conf->raid_disks - conf->mddev->degraded) <= 1) { + /* + * Set R1BIO_Uptodate in our master bio, so that + * we will return a good error code for to the higher + * levels even if IO on some other mirrored buffer fails. + * + * The 'master' represents the composite IO operation to + * user-side. So if something waits for IO, then it will + * wait for the 'master' bio. */ - unsigned long flags; - spin_lock_irqsave(&conf->device_lock, flags); - if (r1_bio->mddev->degraded == conf->raid_disks || - (r1_bio->mddev->degraded == conf->raid_disks-1 && - !test_bit(Faulty, &conf->mirrors[mirror].rdev->flags))) - uptodate = 1; - spin_unlock_irqrestore(&conf->device_lock, flags); - } + if (uptodate) + set_bit(R1BIO_Uptodate, &r1_bio->state); - if (uptodate) raid_end_bio_io(r1_bio); - else { + } else { /* * oops, read error: */ @@ -996,14 +992,13 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) unsigned long flags; spin_lock_irqsave(&conf->device_lock, flags); mddev->degraded++; - set_bit(Faulty, &rdev->flags); spin_unlock_irqrestore(&conf->device_lock, flags); /* * if recovery is running, make sure it aborts. */ set_bit(MD_RECOVERY_ERR, &mddev->recovery); - } else - set_bit(Faulty, &rdev->flags); + } + set_bit(Faulty, &rdev->flags); set_bit(MD_CHANGE_DEVS, &mddev->flags); printk(KERN_ALERT "raid1: Disk failure on %s, disabling device. \n" " Operation continuing on %d devices\n", diff --git a/trunk/drivers/md/raid5.c b/trunk/drivers/md/raid5.c index 061375ee6592..8d59914f2057 100644 --- a/trunk/drivers/md/raid5.c +++ b/trunk/drivers/md/raid5.c @@ -353,8 +353,8 @@ static int grow_stripes(raid5_conf_t *conf, int num) struct kmem_cache *sc; int devs = conf->raid_disks; - sprintf(conf->cache_name[0], "raid5-%s", mdname(conf->mddev)); - sprintf(conf->cache_name[1], "raid5-%s-alt", mdname(conf->mddev)); + sprintf(conf->cache_name[0], "raid5/%s", mdname(conf->mddev)); + sprintf(conf->cache_name[1], "raid5/%s-alt", mdname(conf->mddev)); conf->active_name = 0; sc = kmem_cache_create(conf->cache_name[conf->active_name], sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev), diff --git a/trunk/drivers/media/Kconfig b/trunk/drivers/media/Kconfig index 3a80e0cc7369..91d25798ae4a 100644 --- a/trunk/drivers/media/Kconfig +++ b/trunk/drivers/media/Kconfig @@ -3,7 +3,6 @@ # menu "Multimedia devices" - depends on HAS_IOMEM config VIDEO_DEV tristate "Video For Linux" diff --git a/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 9200a30dd1b9..68ed3a788083 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -3,7 +3,7 @@ * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) * see dvb-usb-init.c for copyright information. * - * This file contains functions for initializing the input-device and for handling remote-control-queries. + * This file contains functions for initializing the the input-device and for handling remote-control-queries. */ #include "dvb-usb-common.h" #include diff --git a/trunk/drivers/media/dvb/frontends/dib7000m.c b/trunk/drivers/media/dvb/frontends/dib7000m.c index f64546c6aeb5..f5d40aa3d27f 100644 --- a/trunk/drivers/media/dvb/frontends/dib7000m.c +++ b/trunk/drivers/media/dvb/frontends/dib7000m.c @@ -266,7 +266,7 @@ static int dib7000m_sad_calib(struct dib7000m_state *state) { /* internal */ -// dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is written in set_bandwidth +// dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth dib7000m_write_word(state, 929, (0 << 1) | (0 << 0)); dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096 diff --git a/trunk/drivers/media/dvb/frontends/dib7000p.c b/trunk/drivers/media/dvb/frontends/dib7000p.c index aece458cfe12..0349a4b5da3f 100644 --- a/trunk/drivers/media/dvb/frontends/dib7000p.c +++ b/trunk/drivers/media/dvb/frontends/dib7000p.c @@ -223,7 +223,7 @@ static int dib7000p_set_bandwidth(struct dvb_frontend *demod, u8 BW_Idx) static int dib7000p_sad_calib(struct dib7000p_state *state) { /* internal */ -// dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is written in set_bandwidth +// dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth dib7000p_write_word(state, 73, (0 << 1) | (0 << 0)); dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096 diff --git a/trunk/drivers/media/dvb/frontends/tda10021.c b/trunk/drivers/media/dvb/frontends/tda10021.c index e725f612a6b7..110536843e8e 100644 --- a/trunk/drivers/media/dvb/frontends/tda10021.c +++ b/trunk/drivers/media/dvb/frontends/tda10021.c @@ -1,6 +1,6 @@ /* TDA10021 - Single Chip Cable Channel Receiver driver module - used on the Siemens DVB-C cards + used on the the Siemens DVB-C cards Copyright (C) 1999 Convergence Integrated Media GmbH Copyright (C) 2004 Markus Schulz diff --git a/trunk/drivers/media/dvb/frontends/ves1x93.c b/trunk/drivers/media/dvb/frontends/ves1x93.c index 23fd0303c91b..54d7b07571b8 100644 --- a/trunk/drivers/media/dvb/frontends/ves1x93.c +++ b/trunk/drivers/media/dvb/frontends/ves1x93.c @@ -306,7 +306,7 @@ static int ves1x93_read_status(struct dvb_frontend* fe, fe_status_t* status) * The ves1893 sometimes returns sync values that make no sense, * because, e.g., the SIGNAL bit is 0, while some of the higher * bits are 1 (and how can there be a CARRIER w/o a SIGNAL?). - * Tests showed that the VITERBI and SYNC bits are returned + * Tests showed that the the VITERBI and SYNC bits are returned * reliably, while the SIGNAL and CARRIER bits ar sometimes wrong. * If such a case occurs, we read the value again, until we get a * valid value. diff --git a/trunk/drivers/media/video/em28xx/em28xx-i2c.c b/trunk/drivers/media/video/em28xx/em28xx-i2c.c index 54ccc6e1f92e..563a8319e608 100644 --- a/trunk/drivers/media/video/em28xx/em28xx-i2c.c +++ b/trunk/drivers/media/video/em28xx/em28xx-i2c.c @@ -70,7 +70,7 @@ static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr, ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); if (ret != 2 + len) { - em28xx_warn("writing to i2c device failed (error=%i)\n", ret); + em28xx_warn("writting to i2c device failed (error=%i)\n", ret); return -EIO; } for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; diff --git a/trunk/drivers/media/video/em28xx/em28xx-video.c b/trunk/drivers/media/video/em28xx/em28xx-video.c index 2c7b158ce7e1..bec67609500f 100644 --- a/trunk/drivers/media/video/em28xx/em28xx-video.c +++ b/trunk/drivers/media/video/em28xx/em28xx-video.c @@ -1729,7 +1729,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, endpoint = &interface->cur_altsetting->endpoint[1].desc; - /* check if the device has the iso in endpoint at the correct place */ + /* check if the the device has the iso in endpoint at the correct place */ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); diff --git a/trunk/drivers/media/video/pwc/philips.txt b/trunk/drivers/media/video/pwc/philips.txt index f9f3584281d8..f5e848410311 100644 --- a/trunk/drivers/media/video/pwc/philips.txt +++ b/trunk/drivers/media/video/pwc/philips.txt @@ -54,9 +54,9 @@ fps Specifies the desired framerate. Is an integer in the range of 4-30. fbufs - This parameter specifies the number of internal buffers to use for storing + This paramter specifies the number of internal buffers to use for storing frames from the cam. This will help if the process that reads images from - the cam is a bit slow or momentarily busy. However, on slow machines it + the cam is a bit slow or momentarely busy. However, on slow machines it only introduces lag, so choose carefully. The default is 3, which is reasonable. You can set it between 2 and 5. @@ -209,7 +209,7 @@ trace 128 0x80 PWCX debugging Off - For example, to trace the open() & read() functions, sum 8 + 4 = 12, + For example, to trace the open() & read() fuctions, sum 8 + 4 = 12, so you would supply trace=12 during insmod or modprobe. If you want to turn the initialization and probing tracing off, set trace=0. The default value for trace is 35 (0x23). diff --git a/trunk/drivers/media/video/usbvideo/vicam.c b/trunk/drivers/media/video/usbvideo/vicam.c index 982b115193f8..876fd2768242 100644 --- a/trunk/drivers/media/video/usbvideo/vicam.c +++ b/trunk/drivers/media/video/usbvideo/vicam.c @@ -28,7 +28,7 @@ * * Portions of this code were also copied from usbvideo.c * - * Special thanks to the whole team at Sourceforge for help making + * Special thanks to the the whole team at Sourceforge for help making * this driver become a reality. Notably: * Andy Armstrong who reverse engineered the color encoding and * Pavel Machek and Chris Cheney who worked on reverse engineering the diff --git a/trunk/drivers/message/fusion/Kconfig b/trunk/drivers/message/fusion/Kconfig index c88cc75ab49b..71037f91c222 100644 --- a/trunk/drivers/message/fusion/Kconfig +++ b/trunk/drivers/message/fusion/Kconfig @@ -1,6 +1,5 @@ menu "Fusion MPT device support" - depends on PCI config FUSION bool diff --git a/trunk/drivers/message/fusion/lsi/mpi_history.txt b/trunk/drivers/message/fusion/lsi/mpi_history.txt index ddc7ae029dd3..d6b4c607453b 100644 --- a/trunk/drivers/message/fusion/lsi/mpi_history.txt +++ b/trunk/drivers/message/fusion/lsi/mpi_history.txt @@ -571,7 +571,7 @@ mpi_fc.h * 11-02-00 01.01.01 Original release for post 1.0 work * 12-04-00 01.01.02 Added messages for Common Transport Send and * Primitive Send. - * 01-09-01 01.01.03 Modified some of the new flags to have an MPI prefix + * 01-09-01 01.01.03 Modifed some of the new flags to have an MPI prefix * and modified the FcPrimitiveSend flags. * 01-25-01 01.01.04 Move InitiatorIndex in LinkServiceRsp reply to a larger * field. diff --git a/trunk/drivers/message/fusion/mptbase.c b/trunk/drivers/message/fusion/mptbase.c index 5021d1a2a1d4..97471af4309c 100644 --- a/trunk/drivers/message/fusion/mptbase.c +++ b/trunk/drivers/message/fusion/mptbase.c @@ -3585,7 +3585,7 @@ initChainBuffers(MPT_ADAPTER *ioc) * index = chain_idx * * Calculate the number of chain buffers needed(plus 1) per I/O - * then multiply the maximum number of simultaneous cmds + * then multiply the the maximum number of simultaneous cmds * * num_sge = num sge in request frame + last chain buffer * scale = num sge per chain buffer if no chain element diff --git a/trunk/drivers/message/i2o/Kconfig b/trunk/drivers/message/i2o/Kconfig index f4ac21e5771e..6443392bffff 100644 --- a/trunk/drivers/message/i2o/Kconfig +++ b/trunk/drivers/message/i2o/Kconfig @@ -1,6 +1,5 @@ menu "I2O device support" - depends on PCI config I2O tristate "I2O support" diff --git a/trunk/drivers/mfd/Kconfig b/trunk/drivers/mfd/Kconfig index a20a51efe118..ab6e985275b2 100644 --- a/trunk/drivers/mfd/Kconfig +++ b/trunk/drivers/mfd/Kconfig @@ -3,7 +3,6 @@ # menu "Multifunction device drivers" - depends on HAS_IOMEM config MFD_SM501 tristate "Support for Silicon Motion SM501" diff --git a/trunk/drivers/misc/Kconfig b/trunk/drivers/misc/Kconfig index 2f2fbffafbe0..877e7909a0e5 100644 --- a/trunk/drivers/misc/Kconfig +++ b/trunk/drivers/misc/Kconfig @@ -130,7 +130,7 @@ config SONY_LAPTOP Read for more information. -config SONYPI_COMPAT +config SONY_LAPTOP_OLD bool "Sonypi compatibility" depends on SONY_LAPTOP ---help--- diff --git a/trunk/drivers/misc/asus-laptop.c b/trunk/drivers/misc/asus-laptop.c index 4f9060a2a2f2..65c32a95e121 100644 --- a/trunk/drivers/misc/asus-laptop.c +++ b/trunk/drivers/misc/asus-laptop.c @@ -30,7 +30,7 @@ * Eric Burghard - LED display support for W1N * Josh Green - Light Sens support * Thomas Tuttle - His first patch for led support was very helpfull - * Sam Lin - GPS support + * */ #include @@ -48,7 +48,7 @@ #include #include -#define ASUS_LAPTOP_VERSION "0.42" +#define ASUS_LAPTOP_VERSION "0.41" #define ASUS_HOTK_NAME "Asus Laptop Support" #define ASUS_HOTK_CLASS "hotkey" @@ -83,7 +83,6 @@ #define PLED_ON 0x20 //Phone LED #define GLED_ON 0x40 //Gaming LED #define LCD_ON 0x80 //LCD backlight -#define GPS_ON 0x100 //GPS #define ASUS_LOG ASUS_HOTK_FILE ": " #define ASUS_ERR KERN_ERR ASUS_LOG @@ -149,7 +148,7 @@ ASUS_HANDLE(display_set, ASUS_HOTK_PREFIX "SDSP"); ASUS_HANDLE(display_get, "\\_SB.PCI0.P0P1.VGA.GETD", /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */ "\\_SB.PCI0.P0P2.VGA.GETD", /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V - S5A M5A z33A W1Jc W2V G1 */ + S5A M5A z33A W1Jc W2V */ "\\_SB.PCI0.P0P3.VGA.GETD", /* A6V A6Q */ "\\_SB.PCI0.P0PA.VGA.GETD", /* A6T, A6M */ "\\_SB.PCI0.PCI1.VGAC.NMAP", /* L3C */ @@ -163,12 +162,6 @@ ASUS_HANDLE(display_get, "\\_SB.PCI0.P0P1.VGA.GETD", /* A6B, A6K A6R A7D F3JM L ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */ ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL"); /* Z71A Z71V */ -/* GPS */ -/* R2H use different handle for GPS on/off */ -ASUS_HANDLE(gps_on, ASUS_HOTK_PREFIX "SDON"); /* R2H */ -ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF"); /* R2H */ -ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST"); - /* * This is the main structure, we can use it to store anything interesting * about the hotk device @@ -285,28 +278,12 @@ static int read_wireless_status(int mask) return (hotk->status & mask) ? 1 : 0; } -static int read_gps_status(void) -{ - ulong status; - acpi_status rv = AE_OK; - - rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); - if (ACPI_FAILURE(rv)) - printk(ASUS_WARNING "Error reading GPS status\n"); - else - return status ? 1 : 0; - - return (hotk->status & GPS_ON) ? 1 : 0; -} - /* Generic LED functions */ static int read_status(int mask) { /* There is a special method for both wireless devices */ if (mask == BT_ON || mask == WL_ON) return read_wireless_status(mask); - else if (mask == GPS_ON) - return read_gps_status(); return (hotk->status & mask) ? 1 : 0; } @@ -322,10 +299,6 @@ static void write_status(acpi_handle handle, int out, int mask) case GLED_ON: out = (out & 0x1) + 1; break; - case GPS_ON: - handle = (out) ? gps_on_handle : gps_off_handle; - out = 0x02; - break; default: out &= 0x1; break; @@ -694,21 +667,6 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, return rv; } -/* - * GPS - */ -static ssize_t show_gps(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", read_status(GPS_ON)); -} - -static ssize_t store_gps(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - return store_status(buf, count, NULL, GPS_ON); -} - static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) { /* TODO Find a better way to handle events count. */ @@ -757,7 +715,6 @@ static ASUS_CREATE_DEVICE_ATTR(display); static ASUS_CREATE_DEVICE_ATTR(ledd); static ASUS_CREATE_DEVICE_ATTR(ls_switch); static ASUS_CREATE_DEVICE_ATTR(ls_level); -static ASUS_CREATE_DEVICE_ATTR(gps); static struct attribute *asuspf_attributes[] = { &dev_attr_infos.attr, @@ -767,7 +724,6 @@ static struct attribute *asuspf_attributes[] = { &dev_attr_ledd.attr, &dev_attr_ls_switch.attr, &dev_attr_ls_level.attr, - &dev_attr_gps.attr, NULL }; @@ -807,9 +763,6 @@ static void asus_hotk_add_fs(void) ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl); ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw); } - - if (gps_status_handle && gps_on_handle && gps_off_handle) - ASUS_SET_DEVICE_ATTR(gps, 0644, show_gps, store_gps); } static int asus_handle_init(char *name, acpi_handle * handle, @@ -937,13 +890,9 @@ static int asus_hotk_get_info(void) /* There is a lot of models with "ALSL", but a few get a real light sens, so we need to check it. */ - if (!ASUS_HANDLE_INIT(ls_switch)) + if (ASUS_HANDLE_INIT(ls_switch)) ASUS_HANDLE_INIT(ls_level); - ASUS_HANDLE_INIT(gps_on); - ASUS_HANDLE_INIT(gps_off); - ASUS_HANDLE_INIT(gps_status); - kfree(model); return AE_OK; @@ -1001,7 +950,7 @@ static int asus_hotk_add(struct acpi_device *device) * We install the handler, it will receive the hotk in parameter, so, we * could add other data to the hotk struct */ - status = acpi_install_notify_handler(hotk->handle, ACPI_ALL_NOTIFY, + status = acpi_install_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, asus_hotk_notify, hotk); if (ACPI_FAILURE(status)) printk(ASUS_ERR "Error installing notify handler\n"); @@ -1032,9 +981,6 @@ static int asus_hotk_add(struct acpi_device *device) if (ls_level_handle) set_light_sens_level(hotk->light_level); - /* GPS is on by default */ - write_status(NULL, 1, GPS_ON); - end: if (result) { kfree(hotk->name); @@ -1051,7 +997,7 @@ static int asus_hotk_remove(struct acpi_device *device, int type) if (!device || !acpi_driver_data(device)) return -EINVAL; - status = acpi_remove_notify_handler(hotk->handle, ACPI_ALL_NOTIFY, + status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY, asus_hotk_notify); if (ACPI_FAILURE(status)) printk(ASUS_ERR "Error removing notify handler\n"); diff --git a/trunk/drivers/misc/msi-laptop.c b/trunk/drivers/misc/msi-laptop.c index 41e901f53e7c..68c4b58525ba 100644 --- a/trunk/drivers/misc/msi-laptop.c +++ b/trunk/drivers/misc/msi-laptop.c @@ -85,7 +85,7 @@ static int set_lcd_level(int level) buf[0] = 0x80; buf[1] = (u8) (level*31); - return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, buf, sizeof(buf), NULL, 0, 1); + return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, buf, sizeof(buf), NULL, 0); } static int get_lcd_level(void) @@ -93,7 +93,7 @@ static int get_lcd_level(void) u8 wdata = 0, rdata; int result; - result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1, 1); + result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1); if (result < 0) return result; @@ -105,7 +105,7 @@ static int get_auto_brightness(void) u8 wdata = 4, rdata; int result; - result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1, 1); + result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1); if (result < 0) return result; @@ -119,14 +119,14 @@ static int set_auto_brightness(int enable) wdata[0] = 4; - result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 1, &rdata, 1, 1); + result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 1, &rdata, 1); if (result < 0) return result; wdata[0] = 0x84; wdata[1] = (rdata & 0xF7) | (enable ? 8 : 0); - return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0, 1); + return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0); } static int get_wireless_state(int *wlan, int *bluetooth) @@ -134,7 +134,7 @@ static int get_wireless_state(int *wlan, int *bluetooth) u8 wdata = 0, rdata; int result; - result = ec_transaction(MSI_EC_COMMAND_WIRELESS, &wdata, 1, &rdata, 1, 1); + result = ec_transaction(MSI_EC_COMMAND_WIRELESS, &wdata, 1, &rdata, 1); if (result < 0) return -1; diff --git a/trunk/drivers/misc/sony-laptop.c b/trunk/drivers/misc/sony-laptop.c index 8ee0321ef1c8..c15c1f61bd1b 100644 --- a/trunk/drivers/misc/sony-laptop.c +++ b/trunk/drivers/misc/sony-laptop.c @@ -63,7 +63,7 @@ #include #include #include -#ifdef CONFIG_SONYPI_COMPAT +#ifdef CONFIG_SONY_LAPTOP_OLD #include #include #endif @@ -114,7 +114,7 @@ MODULE_PARM_DESC(camera, "set this to 1 to enable Motion Eye camera controls " "(only use it if you have a C1VE or C1VN model)"); -#ifdef CONFIG_SONYPI_COMPAT +#ifdef CONFIG_SONY_LAPTOP_OLD static int minor = -1; module_param(minor, int, 0); MODULE_PARM_DESC(minor, @@ -1504,7 +1504,7 @@ static struct attribute_group spic_attribute_group = { }; /******** SONYPI compatibility **********/ -#ifdef CONFIG_SONYPI_COMPAT +#ifdef CONFIG_SONY_LAPTOP_OLD /* battery / brightness / temperature addresses */ #define SONYPI_BAT_FLAGS 0x81 @@ -1798,7 +1798,7 @@ static void sonypi_compat_exit(void) static int sonypi_compat_init(void) { return 0; } static void sonypi_compat_exit(void) { } static void sonypi_compat_report_event(u8 event) { } -#endif /* CONFIG_SONYPI_COMPAT */ +#endif /* CONFIG_SONY_LAPTOP_OLD */ /* * ACPI callbacks diff --git a/trunk/drivers/mmc/Kconfig b/trunk/drivers/mmc/Kconfig index c0b41e8bcd9d..45b7d53b949c 100644 --- a/trunk/drivers/mmc/Kconfig +++ b/trunk/drivers/mmc/Kconfig @@ -4,7 +4,6 @@ menuconfig MMC tristate "MMC/SD card support" - depends on HAS_IOMEM help MMC is the "multi-media card" bus protocol. diff --git a/trunk/drivers/mmc/core/core.c b/trunk/drivers/mmc/core/core.c index 7385acfa1dd9..b6c16704aaab 100644 --- a/trunk/drivers/mmc/core/core.c +++ b/trunk/drivers/mmc/core/core.c @@ -501,9 +501,9 @@ void mmc_detect_change(struct mmc_host *host, unsigned long delay) { #ifdef CONFIG_MMC_DEBUG unsigned long flags; - spin_lock_irqsave(&host->lock, flags); + spin_lock_irqsave(host->lock, flags); BUG_ON(host->removed); - spin_unlock_irqrestore(&host->lock, flags); + spin_unlock_irqrestore(host->lock, flags); #endif mmc_schedule_delayed_work(&host->detect, delay); diff --git a/trunk/drivers/mtd/Kconfig b/trunk/drivers/mtd/Kconfig index fbec8cd55e38..c1b47db29bd2 100644 --- a/trunk/drivers/mtd/Kconfig +++ b/trunk/drivers/mtd/Kconfig @@ -2,7 +2,6 @@ menuconfig MTD tristate "Memory Technology Device (MTD) support" - depends on HAS_IOMEM help Memory Technology Devices are flash, RAM and similar chips, often used for solid state file systems on embedded devices. This option diff --git a/trunk/drivers/mtd/chips/Kconfig b/trunk/drivers/mtd/chips/Kconfig index 479d32b57a1e..d28e0fc85e12 100644 --- a/trunk/drivers/mtd/chips/Kconfig +++ b/trunk/drivers/mtd/chips/Kconfig @@ -1,4 +1,5 @@ # drivers/mtd/chips/Kconfig +# $Id: Kconfig,v 1.18 2005/11/07 11:14:22 gleixner Exp $ menu "RAM/ROM/Flash chip drivers" depends on MTD!=n @@ -230,6 +231,45 @@ config MTD_ABSENT the system regardless of media presence. Device nodes created with this driver will return -ENODEV upon access. +config MTD_OBSOLETE_CHIPS + bool "Older (theoretically obsoleted now) drivers for non-CFI chips" + help + This option does not enable any code directly, but will allow you to + select some other chip drivers which are now considered obsolete, + because the generic CONFIG_JEDECPROBE code above should now detect + the chips which are supported by these drivers, and allow the generic + CFI-compatible drivers to drive the chips. Say 'N' here unless you have + already tried the CONFIG_JEDECPROBE method and reported its failure + to the MTD mailing list at + +config MTD_AMDSTD + tristate "AMD compatible flash chip support (non-CFI)" + depends on MTD_OBSOLETE_CHIPS && BROKEN + help + This option enables support for flash chips using AMD-compatible + commands, including some which are not CFI-compatible and hence + cannot be used with the CONFIG_MTD_CFI_AMDSTD option. + + It also works on AMD compatible chips that do conform to CFI. + +config MTD_SHARP + tristate "pre-CFI Sharp chip support" + depends on MTD_OBSOLETE_CHIPS + help + This option enables support for flash chips using Sharp-compatible + commands, including some which are not CFI-compatible and hence + cannot be used with the CONFIG_MTD_CFI_INTELxxx options. + +config MTD_JEDEC + tristate "JEDEC device support" + depends on MTD_OBSOLETE_CHIPS && BROKEN + help + Enable older JEDEC flash interface devices for self + programming flash. It is commonly used in older AMD chips. It is + only called JEDEC because the JEDEC association + distributes the identification codes for the + chips. + config MTD_XIP bool "XIP aware MTD support" depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARCH_MTD_XIP diff --git a/trunk/drivers/mtd/chips/Makefile b/trunk/drivers/mtd/chips/Makefile index 36582412ccda..75bc1c2a0f43 100644 --- a/trunk/drivers/mtd/chips/Makefile +++ b/trunk/drivers/mtd/chips/Makefile @@ -1,15 +1,19 @@ # # linux/drivers/chips/Makefile # +# $Id: Makefile.common,v 1.5 2005/11/07 11:14:22 gleixner Exp $ obj-$(CONFIG_MTD) += chipreg.o +obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o obj-$(CONFIG_MTD_CFI) += cfi_probe.o obj-$(CONFIG_MTD_CFI_UTIL) += cfi_util.o obj-$(CONFIG_MTD_CFI_STAA) += cfi_cmdset_0020.o obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o obj-$(CONFIG_MTD_GEN_PROBE) += gen_probe.o +obj-$(CONFIG_MTD_JEDEC) += jedec.o obj-$(CONFIG_MTD_JEDECPROBE) += jedec_probe.o obj-$(CONFIG_MTD_RAM) += map_ram.o obj-$(CONFIG_MTD_ROM) += map_rom.o +obj-$(CONFIG_MTD_SHARP) += sharp.o obj-$(CONFIG_MTD_ABSENT) += map_absent.o diff --git a/trunk/drivers/mtd/chips/amd_flash.c b/trunk/drivers/mtd/chips/amd_flash.c new file mode 100644 index 000000000000..e7999f15d85a --- /dev/null +++ b/trunk/drivers/mtd/chips/amd_flash.c @@ -0,0 +1,1396 @@ +/* + * MTD map driver for AMD compatible flash chips (non-CFI) + * + * Author: Jonas Holmberg + * + * $Id: amd_flash.c,v 1.28 2005/11/07 11:14:22 gleixner Exp $ + * + * Copyright (c) 2001 Axis Communications AB + * + * This file is under GPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* There's no limit. It exists only to avoid realloc. */ +#define MAX_AMD_CHIPS 8 + +#define DEVICE_TYPE_X8 (8 / 8) +#define DEVICE_TYPE_X16 (16 / 8) +#define DEVICE_TYPE_X32 (32 / 8) + +/* Addresses */ +#define ADDR_MANUFACTURER 0x0000 +#define ADDR_DEVICE_ID 0x0001 +#define ADDR_SECTOR_LOCK 0x0002 +#define ADDR_HANDSHAKE 0x0003 +#define ADDR_UNLOCK_1 0x0555 +#define ADDR_UNLOCK_2 0x02AA + +/* Commands */ +#define CMD_UNLOCK_DATA_1 0x00AA +#define CMD_UNLOCK_DATA_2 0x0055 +#define CMD_MANUFACTURER_UNLOCK_DATA 0x0090 +#define CMD_UNLOCK_BYPASS_MODE 0x0020 +#define CMD_PROGRAM_UNLOCK_DATA 0x00A0 +#define CMD_RESET_DATA 0x00F0 +#define CMD_SECTOR_ERASE_UNLOCK_DATA 0x0080 +#define CMD_SECTOR_ERASE_UNLOCK_DATA_2 0x0030 + +#define CMD_UNLOCK_SECTOR 0x0060 + +/* Manufacturers */ +#define MANUFACTURER_AMD 0x0001 +#define MANUFACTURER_ATMEL 0x001F +#define MANUFACTURER_FUJITSU 0x0004 +#define MANUFACTURER_ST 0x0020 +#define MANUFACTURER_SST 0x00BF +#define MANUFACTURER_TOSHIBA 0x0098 + +/* AMD */ +#define AM29F800BB 0x2258 +#define AM29F800BT 0x22D6 +#define AM29LV800BB 0x225B +#define AM29LV800BT 0x22DA +#define AM29LV160DT 0x22C4 +#define AM29LV160DB 0x2249 +#define AM29BDS323D 0x22D1 + +/* Atmel */ +#define AT49xV16x 0x00C0 +#define AT49xV16xT 0x00C2 + +/* Fujitsu */ +#define MBM29LV160TE 0x22C4 +#define MBM29LV160BE 0x2249 +#define MBM29LV800BB 0x225B + +/* ST - www.st.com */ +#define M29W800T 0x00D7 +#define M29W160DT 0x22C4 +#define M29W160DB 0x2249 + +/* SST */ +#define SST39LF800 0x2781 +#define SST39LF160 0x2782 + +/* Toshiba */ +#define TC58FVT160 0x00C2 +#define TC58FVB160 0x0043 + +#define D6_MASK 0x40 + +struct amd_flash_private { + int device_type; + int interleave; + int numchips; + unsigned long chipshift; + struct flchip chips[0]; +}; + +struct amd_flash_info { + const __u16 mfr_id; + const __u16 dev_id; + const char *name; + const u_long size; + const int numeraseregions; + const struct mtd_erase_region_info regions[4]; +}; + + + +static int amd_flash_read(struct mtd_info *, loff_t, size_t, size_t *, + u_char *); +static int amd_flash_write(struct mtd_info *, loff_t, size_t, size_t *, + const u_char *); +static int amd_flash_erase(struct mtd_info *, struct erase_info *); +static void amd_flash_sync(struct mtd_info *); +static int amd_flash_suspend(struct mtd_info *); +static void amd_flash_resume(struct mtd_info *); +static void amd_flash_destroy(struct mtd_info *); +static struct mtd_info *amd_flash_probe(struct map_info *map); + + +static struct mtd_chip_driver amd_flash_chipdrv = { + .probe = amd_flash_probe, + .destroy = amd_flash_destroy, + .name = "amd_flash", + .module = THIS_MODULE +}; + +static inline __u32 wide_read(struct map_info *map, __u32 addr) +{ + if (map->buswidth == 1) { + return map_read8(map, addr); + } else if (map->buswidth == 2) { + return map_read16(map, addr); + } else if (map->buswidth == 4) { + return map_read32(map, addr); + } + + return 0; +} + +static inline void wide_write(struct map_info *map, __u32 val, __u32 addr) +{ + if (map->buswidth == 1) { + map_write8(map, val, addr); + } else if (map->buswidth == 2) { + map_write16(map, val, addr); + } else if (map->buswidth == 4) { + map_write32(map, val, addr); + } +} + +static inline __u32 make_cmd(struct map_info *map, __u32 cmd) +{ + const struct amd_flash_private *private = map->fldrv_priv; + if ((private->interleave == 2) && + (private->device_type == DEVICE_TYPE_X16)) { + cmd |= (cmd << 16); + } + + return cmd; +} + +static inline void send_unlock(struct map_info *map, unsigned long base) +{ + wide_write(map, (CMD_UNLOCK_DATA_1 << 16) | CMD_UNLOCK_DATA_1, + base + (map->buswidth * ADDR_UNLOCK_1)); + wide_write(map, (CMD_UNLOCK_DATA_2 << 16) | CMD_UNLOCK_DATA_2, + base + (map->buswidth * ADDR_UNLOCK_2)); +} + +static inline void send_cmd(struct map_info *map, unsigned long base, __u32 cmd) +{ + send_unlock(map, base); + wide_write(map, make_cmd(map, cmd), + base + (map->buswidth * ADDR_UNLOCK_1)); +} + +static inline void send_cmd_to_addr(struct map_info *map, unsigned long base, + __u32 cmd, unsigned long addr) +{ + send_unlock(map, base); + wide_write(map, make_cmd(map, cmd), addr); +} + +static inline int flash_is_busy(struct map_info *map, unsigned long addr, + int interleave) +{ + + if ((interleave == 2) && (map->buswidth == 4)) { + __u32 read1, read2; + + read1 = wide_read(map, addr); + read2 = wide_read(map, addr); + + return (((read1 >> 16) & D6_MASK) != + ((read2 >> 16) & D6_MASK)) || + (((read1 & 0xffff) & D6_MASK) != + ((read2 & 0xffff) & D6_MASK)); + } + + return ((wide_read(map, addr) & D6_MASK) != + (wide_read(map, addr) & D6_MASK)); +} + +static inline void unlock_sector(struct map_info *map, unsigned long sect_addr, + int unlock) +{ + /* Sector lock address. A6 = 1 for unlock, A6 = 0 for lock */ + int SLA = unlock ? + (sect_addr | (0x40 * map->buswidth)) : + (sect_addr & ~(0x40 * map->buswidth)) ; + + __u32 cmd = make_cmd(map, CMD_UNLOCK_SECTOR); + + wide_write(map, make_cmd(map, CMD_RESET_DATA), 0); + wide_write(map, cmd, SLA); /* 1st cycle: write cmd to any address */ + wide_write(map, cmd, SLA); /* 2nd cycle: write cmd to any address */ + wide_write(map, cmd, SLA); /* 3rd cycle: write cmd to SLA */ +} + +static inline int is_sector_locked(struct map_info *map, + unsigned long sect_addr) +{ + int status; + + wide_write(map, CMD_RESET_DATA, 0); + send_cmd(map, sect_addr, CMD_MANUFACTURER_UNLOCK_DATA); + + /* status is 0x0000 for unlocked and 0x0001 for locked */ + status = wide_read(map, sect_addr + (map->buswidth * ADDR_SECTOR_LOCK)); + wide_write(map, CMD_RESET_DATA, 0); + return status; +} + +static int amd_flash_do_unlock(struct mtd_info *mtd, loff_t ofs, size_t len, + int is_unlock) +{ + struct map_info *map; + struct mtd_erase_region_info *merip; + int eraseoffset, erasesize, eraseblocks; + int i; + int retval = 0; + int lock_status; + + map = mtd->priv; + + /* Pass the whole chip through sector by sector and check for each + sector if the sector and the given interval overlap */ + for(i = 0; i < mtd->numeraseregions; i++) { + merip = &mtd->eraseregions[i]; + + eraseoffset = merip->offset; + erasesize = merip->erasesize; + eraseblocks = merip->numblocks; + + if (ofs > eraseoffset + erasesize) + continue; + + while (eraseblocks > 0) { + if (ofs < eraseoffset + erasesize && ofs + len > eraseoffset) { + unlock_sector(map, eraseoffset, is_unlock); + + lock_status = is_sector_locked(map, eraseoffset); + + if (is_unlock && lock_status) { + printk("Cannot unlock sector at address %x length %xx\n", + eraseoffset, merip->erasesize); + retval = -1; + } else if (!is_unlock && !lock_status) { + printk("Cannot lock sector at address %x length %x\n", + eraseoffset, merip->erasesize); + retval = -1; + } + } + eraseoffset += erasesize; + eraseblocks --; + } + } + return retval; +} + +static int amd_flash_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) +{ + return amd_flash_do_unlock(mtd, ofs, len, 1); +} + +static int amd_flash_lock(struct mtd_info *mtd, loff_t ofs, size_t len) +{ + return amd_flash_do_unlock(mtd, ofs, len, 0); +} + + +/* + * Reads JEDEC manufacturer ID and device ID and returns the index of the first + * matching table entry (-1 if not found or alias for already found chip). + */ +static int probe_new_chip(struct mtd_info *mtd, __u32 base, + struct flchip *chips, + struct amd_flash_private *private, + const struct amd_flash_info *table, int table_size) +{ + __u32 mfr_id; + __u32 dev_id; + struct map_info *map = mtd->priv; + struct amd_flash_private temp; + int i; + + temp.device_type = DEVICE_TYPE_X16; // Assume X16 (FIXME) + temp.interleave = 2; + map->fldrv_priv = &temp; + + /* Enter autoselect mode. */ + send_cmd(map, base, CMD_RESET_DATA); + send_cmd(map, base, CMD_MANUFACTURER_UNLOCK_DATA); + + mfr_id = wide_read(map, base + (map->buswidth * ADDR_MANUFACTURER)); + dev_id = wide_read(map, base + (map->buswidth * ADDR_DEVICE_ID)); + + if ((map->buswidth == 4) && ((mfr_id >> 16) == (mfr_id & 0xffff)) && + ((dev_id >> 16) == (dev_id & 0xffff))) { + mfr_id &= 0xffff; + dev_id &= 0xffff; + } else { + temp.interleave = 1; + } + + for (i = 0; i < table_size; i++) { + if ((mfr_id == table[i].mfr_id) && + (dev_id == table[i].dev_id)) { + if (chips) { + int j; + + /* Is this an alias for an already found chip? + * In that case that chip should be in + * autoselect mode now. + */ + for (j = 0; j < private->numchips; j++) { + __u32 mfr_id_other; + __u32 dev_id_other; + + mfr_id_other = + wide_read(map, chips[j].start + + (map->buswidth * + ADDR_MANUFACTURER + )); + dev_id_other = + wide_read(map, chips[j].start + + (map->buswidth * + ADDR_DEVICE_ID)); + if (temp.interleave == 2) { + mfr_id_other &= 0xffff; + dev_id_other &= 0xffff; + } + if ((mfr_id_other == mfr_id) && + (dev_id_other == dev_id)) { + + /* Exit autoselect mode. */ + send_cmd(map, base, + CMD_RESET_DATA); + + return -1; + } + } + + if (private->numchips == MAX_AMD_CHIPS) { + printk(KERN_WARNING + "%s: Too many flash chips " + "detected. Increase " + "MAX_AMD_CHIPS from %d.\n", + map->name, MAX_AMD_CHIPS); + + return -1; + } + + chips[private->numchips].start = base; + chips[private->numchips].state = FL_READY; + chips[private->numchips].mutex = + &chips[private->numchips]._spinlock; + private->numchips++; + } + + printk("%s: Found %d x %ldMiB %s at 0x%x\n", map->name, + temp.interleave, (table[i].size)/(1024*1024), + table[i].name, base); + + mtd->size += table[i].size * temp.interleave; + mtd->numeraseregions += table[i].numeraseregions; + + break; + } + } + + /* Exit autoselect mode. */ + send_cmd(map, base, CMD_RESET_DATA); + + if (i == table_size) { + printk(KERN_DEBUG "%s: unknown flash device at 0x%x, " + "mfr id 0x%x, dev id 0x%x\n", map->name, + base, mfr_id, dev_id); + map->fldrv_priv = NULL; + + return -1; + } + + private->device_type = temp.device_type; + private->interleave = temp.interleave; + + return i; +} + + + +static struct mtd_info *amd_flash_probe(struct map_info *map) +{ + static const struct amd_flash_info table[] = { + { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29LV160DT, + .name = "AMD AM29LV160DT", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, + { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29LV160DB, + .name = "AMD AM29LV160DB", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, + { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } + } + }, { + .mfr_id = MANUFACTURER_TOSHIBA, + .dev_id = TC58FVT160, + .name = "Toshiba TC58FVT160", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, + { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_FUJITSU, + .dev_id = MBM29LV160TE, + .name = "Fujitsu MBM29LV160TE", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, + { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_TOSHIBA, + .dev_id = TC58FVB160, + .name = "Toshiba TC58FVB160", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, + { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } + } + }, { + .mfr_id = MANUFACTURER_FUJITSU, + .dev_id = MBM29LV160BE, + .name = "Fujitsu MBM29LV160BE", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, + { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } + } + }, { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29LV800BB, + .name = "AMD AM29LV800BB", + .size = 0x00100000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, + { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 } + } + }, { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29F800BB, + .name = "AMD AM29F800BB", + .size = 0x00100000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, + { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 } + } + }, { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29LV800BT, + .name = "AMD AM29LV800BT", + .size = 0x00100000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, + { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29F800BT, + .name = "AMD AM29F800BT", + .size = 0x00100000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, + { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29LV800BB, + .name = "AMD AM29LV800BB", + .size = 0x00100000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, + { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_FUJITSU, + .dev_id = MBM29LV800BB, + .name = "Fujitsu MBM29LV800BB", + .size = 0x00100000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, + { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 } + } + }, { + .mfr_id = MANUFACTURER_ST, + .dev_id = M29W800T, + .name = "ST M29W800T", + .size = 0x00100000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 }, + { .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_ST, + .dev_id = M29W160DT, + .name = "ST M29W160DT", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, + { .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 } + } + }, { + .mfr_id = MANUFACTURER_ST, + .dev_id = M29W160DB, + .name = "ST M29W160DB", + .size = 0x00200000, + .numeraseregions = 4, + .regions = { + { .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 }, + { .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 }, + { .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } + } + }, { + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29BDS323D, + .name = "AMD AM29BDS323D", + .size = 0x00400000, + .numeraseregions = 3, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 48 }, + { .offset = 0x300000, .erasesize = 0x10000, .numblocks = 15 }, + { .offset = 0x3f0000, .erasesize = 0x02000, .numblocks = 8 }, + } + }, { + .mfr_id = MANUFACTURER_ATMEL, + .dev_id = AT49xV16x, + .name = "Atmel AT49xV16x", + .size = 0x00200000, + .numeraseregions = 2, + .regions = { + { .offset = 0x000000, .erasesize = 0x02000, .numblocks = 8 }, + { .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 } + } + }, { + .mfr_id = MANUFACTURER_ATMEL, + .dev_id = AT49xV16xT, + .name = "Atmel AT49xV16xT", + .size = 0x00200000, + .numeraseregions = 2, + .regions = { + { .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 }, + { .offset = 0x1F0000, .erasesize = 0x02000, .numblocks = 8 } + } + } + }; + + struct mtd_info *mtd; + struct flchip chips[MAX_AMD_CHIPS]; + int table_pos[MAX_AMD_CHIPS]; + struct amd_flash_private temp; + struct amd_flash_private *private; + u_long size; + unsigned long base; + int i; + int reg_idx; + int offset; + + mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); + if (!mtd) { + printk(KERN_WARNING + "%s: kmalloc failed for info structure\n", map->name); + return NULL; + } + mtd->priv = map; + + memset(&temp, 0, sizeof(temp)); + + printk("%s: Probing for AMD compatible flash...\n", map->name); + + if ((table_pos[0] = probe_new_chip(mtd, 0, NULL, &temp, table, + ARRAY_SIZE(table))) + == -1) { + printk(KERN_WARNING + "%s: Found no AMD compatible device at location zero\n", + map->name); + kfree(mtd); + + return NULL; + } + + chips[0].start = 0; + chips[0].state = FL_READY; + chips[0].mutex = &chips[0]._spinlock; + temp.numchips = 1; + for (size = mtd->size; size > 1; size >>= 1) { + temp.chipshift++; + } + switch (temp.interleave) { + case 2: + temp.chipshift += 1; + break; + case 4: + temp.chipshift += 2; + break; + } + + /* Find out if there are any more chips in the map. */ + for (base = (1 << temp.chipshift); + base < map->size; + base += (1 << temp.chipshift)) { + int numchips = temp.numchips; + table_pos[numchips] = probe_new_chip(mtd, base, chips, + &temp, table, ARRAY_SIZE(table)); + } + + mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * + mtd->numeraseregions, GFP_KERNEL); + if (!mtd->eraseregions) { + printk(KERN_WARNING "%s: Failed to allocate " + "memory for MTD erase region info\n", map->name); + kfree(mtd); + map->fldrv_priv = NULL; + return NULL; + } + + reg_idx = 0; + offset = 0; + for (i = 0; i < temp.numchips; i++) { + int dev_size; + int j; + + dev_size = 0; + for (j = 0; j < table[table_pos[i]].numeraseregions; j++) { + mtd->eraseregions[reg_idx].offset = offset + + (table[table_pos[i]].regions[j].offset * + temp.interleave); + mtd->eraseregions[reg_idx].erasesize = + table[table_pos[i]].regions[j].erasesize * + temp.interleave; + mtd->eraseregions[reg_idx].numblocks = + table[table_pos[i]].regions[j].numblocks; + if (mtd->erasesize < + mtd->eraseregions[reg_idx].erasesize) { + mtd->erasesize = + mtd->eraseregions[reg_idx].erasesize; + } + dev_size += mtd->eraseregions[reg_idx].erasesize * + mtd->eraseregions[reg_idx].numblocks; + reg_idx++; + } + offset += dev_size; + } + mtd->type = MTD_NORFLASH; + mtd->writesize = 1; + mtd->flags = MTD_CAP_NORFLASH; + mtd->name = map->name; + mtd->erase = amd_flash_erase; + mtd->read = amd_flash_read; + mtd->write = amd_flash_write; + mtd->sync = amd_flash_sync; + mtd->suspend = amd_flash_suspend; + mtd->resume = amd_flash_resume; + mtd->lock = amd_flash_lock; + mtd->unlock = amd_flash_unlock; + + private = kmalloc(sizeof(*private) + (sizeof(struct flchip) * + temp.numchips), GFP_KERNEL); + if (!private) { + printk(KERN_WARNING + "%s: kmalloc failed for private structure\n", map->name); + kfree(mtd); + map->fldrv_priv = NULL; + return NULL; + } + memcpy(private, &temp, sizeof(temp)); + memcpy(private->chips, chips, + sizeof(struct flchip) * private->numchips); + for (i = 0; i < private->numchips; i++) { + init_waitqueue_head(&private->chips[i].wq); + spin_lock_init(&private->chips[i]._spinlock); + } + + map->fldrv_priv = private; + + map->fldrv = &amd_flash_chipdrv; + + __module_get(THIS_MODULE); + return mtd; +} + + + +static inline int read_one_chip(struct map_info *map, struct flchip *chip, + loff_t adr, size_t len, u_char *buf) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long timeo = jiffies + HZ; + +retry: + spin_lock_bh(chip->mutex); + + if (chip->state != FL_READY){ + printk(KERN_INFO "%s: waiting for chip to read, state = %d\n", + map->name, chip->state); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if(signal_pending(current)) { + return -EINTR; + } + + timeo = jiffies + HZ; + + goto retry; + } + + adr += chip->start; + + chip->state = FL_READY; + + map_copy_from(map, buf, adr, len); + + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + + return 0; +} + + + +static int amd_flash_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct map_info *map = mtd->priv; + struct amd_flash_private *private = map->fldrv_priv; + unsigned long ofs; + int chipnum; + int ret = 0; + + if ((from + len) > mtd->size) { + printk(KERN_WARNING "%s: read request past end of device " + "(0x%lx)\n", map->name, (unsigned long)from + len); + + return -EINVAL; + } + + /* Offset within the first chip that the first read should start. */ + chipnum = (from >> private->chipshift); + ofs = from - (chipnum << private->chipshift); + + *retlen = 0; + + while (len) { + unsigned long this_len; + + if (chipnum >= private->numchips) { + break; + } + + if ((len + ofs - 1) >> private->chipshift) { + this_len = (1 << private->chipshift) - ofs; + } else { + this_len = len; + } + + ret = read_one_chip(map, &private->chips[chipnum], ofs, + this_len, buf); + if (ret) { + break; + } + + *retlen += this_len; + len -= this_len; + buf += this_len; + + ofs = 0; + chipnum++; + } + + return ret; +} + + + +static int write_one_word(struct map_info *map, struct flchip *chip, + unsigned long adr, __u32 datum) +{ + unsigned long timeo = jiffies + HZ; + struct amd_flash_private *private = map->fldrv_priv; + DECLARE_WAITQUEUE(wait, current); + int ret = 0; + int times_left; + +retry: + spin_lock_bh(chip->mutex); + + if (chip->state != FL_READY){ + printk("%s: waiting for chip to write, state = %d\n", + map->name, chip->state); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + printk(KERN_INFO "%s: woke up to write\n", map->name); + if(signal_pending(current)) + return -EINTR; + + timeo = jiffies + HZ; + + goto retry; + } + + chip->state = FL_WRITING; + + adr += chip->start; + ENABLE_VPP(map); + send_cmd(map, chip->start, CMD_PROGRAM_UNLOCK_DATA); + wide_write(map, datum, adr); + + times_left = 500000; + while (times_left-- && flash_is_busy(map, adr, private->interleave)) { + if (need_resched()) { + spin_unlock_bh(chip->mutex); + schedule(); + spin_lock_bh(chip->mutex); + } + } + + if (!times_left) { + printk(KERN_WARNING "%s: write to 0x%lx timed out!\n", + map->name, adr); + ret = -EIO; + } else { + __u32 verify; + if ((verify = wide_read(map, adr)) != datum) { + printk(KERN_WARNING "%s: write to 0x%lx failed. " + "datum = %x, verify = %x\n", + map->name, adr, datum, verify); + ret = -EIO; + } + } + + DISABLE_VPP(map); + chip->state = FL_READY; + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + + return ret; +} + + + +static int amd_flash_write(struct mtd_info *mtd, loff_t to , size_t len, + size_t *retlen, const u_char *buf) +{ + struct map_info *map = mtd->priv; + struct amd_flash_private *private = map->fldrv_priv; + int ret = 0; + int chipnum; + unsigned long ofs; + unsigned long chipstart; + + *retlen = 0; + if (!len) { + return 0; + } + + chipnum = to >> private->chipshift; + ofs = to - (chipnum << private->chipshift); + chipstart = private->chips[chipnum].start; + + /* If it's not bus-aligned, do the first byte write. */ + if (ofs & (map->buswidth - 1)) { + unsigned long bus_ofs = ofs & ~(map->buswidth - 1); + int i = ofs - bus_ofs; + int n = 0; + u_char tmp_buf[4]; + __u32 datum; + + map_copy_from(map, tmp_buf, + bus_ofs + private->chips[chipnum].start, + map->buswidth); + while (len && i < map->buswidth) + tmp_buf[i++] = buf[n++], len--; + + if (map->buswidth == 2) { + datum = *(__u16*)tmp_buf; + } else if (map->buswidth == 4) { + datum = *(__u32*)tmp_buf; + } else { + return -EINVAL; /* should never happen, but be safe */ + } + + ret = write_one_word(map, &private->chips[chipnum], bus_ofs, + datum); + if (ret) { + return ret; + } + + ofs += n; + buf += n; + (*retlen) += n; + + if (ofs >> private->chipshift) { + chipnum++; + ofs = 0; + if (chipnum == private->numchips) { + return 0; + } + } + } + + /* We are now aligned, write as much as possible. */ + while(len >= map->buswidth) { + __u32 datum; + + if (map->buswidth == 1) { + datum = *(__u8*)buf; + } else if (map->buswidth == 2) { + datum = *(__u16*)buf; + } else if (map->buswidth == 4) { + datum = *(__u32*)buf; + } else { + return -EINVAL; + } + + ret = write_one_word(map, &private->chips[chipnum], ofs, datum); + + if (ret) { + return ret; + } + + ofs += map->buswidth; + buf += map->buswidth; + (*retlen) += map->buswidth; + len -= map->buswidth; + + if (ofs >> private->chipshift) { + chipnum++; + ofs = 0; + if (chipnum == private->numchips) { + return 0; + } + chipstart = private->chips[chipnum].start; + } + } + + if (len & (map->buswidth - 1)) { + int i = 0, n = 0; + u_char tmp_buf[2]; + __u32 datum; + + map_copy_from(map, tmp_buf, + ofs + private->chips[chipnum].start, + map->buswidth); + while (len--) { + tmp_buf[i++] = buf[n++]; + } + + if (map->buswidth == 2) { + datum = *(__u16*)tmp_buf; + } else if (map->buswidth == 4) { + datum = *(__u32*)tmp_buf; + } else { + return -EINVAL; /* should never happen, but be safe */ + } + + ret = write_one_word(map, &private->chips[chipnum], ofs, datum); + + if (ret) { + return ret; + } + + (*retlen) += n; + } + + return 0; +} + + + +static inline int erase_one_block(struct map_info *map, struct flchip *chip, + unsigned long adr, u_long size) +{ + unsigned long timeo = jiffies + HZ; + struct amd_flash_private *private = map->fldrv_priv; + DECLARE_WAITQUEUE(wait, current); + +retry: + spin_lock_bh(chip->mutex); + + if (chip->state != FL_READY){ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if (signal_pending(current)) { + return -EINTR; + } + + timeo = jiffies + HZ; + + goto retry; + } + + chip->state = FL_ERASING; + + adr += chip->start; + ENABLE_VPP(map); + send_cmd(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA); + send_cmd_to_addr(map, chip->start, CMD_SECTOR_ERASE_UNLOCK_DATA_2, adr); + + timeo = jiffies + (HZ * 20); + + spin_unlock_bh(chip->mutex); + msleep(1000); + spin_lock_bh(chip->mutex); + + while (flash_is_busy(map, adr, private->interleave)) { + + if (chip->state != FL_ERASING) { + /* Someone's suspended the erase. Sleep */ + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + printk(KERN_INFO "%s: erase suspended. Sleeping\n", + map->name); + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if (signal_pending(current)) { + return -EINTR; + } + + timeo = jiffies + (HZ*2); /* FIXME */ + spin_lock_bh(chip->mutex); + continue; + } + + /* OK Still waiting */ + if (time_after(jiffies, timeo)) { + chip->state = FL_READY; + spin_unlock_bh(chip->mutex); + printk(KERN_WARNING "%s: waiting for erase to complete " + "timed out.\n", map->name); + DISABLE_VPP(map); + + return -EIO; + } + + /* Latency issues. Drop the lock, wait a while and retry */ + spin_unlock_bh(chip->mutex); + + if (need_resched()) + schedule(); + else + udelay(1); + + spin_lock_bh(chip->mutex); + } + + /* Verify every single word */ + { + int address; + int error = 0; + __u8 verify; + + for (address = adr; address < (adr + size); address++) { + if ((verify = map_read8(map, address)) != 0xFF) { + error = 1; + break; + } + } + if (error) { + chip->state = FL_READY; + spin_unlock_bh(chip->mutex); + printk(KERN_WARNING + "%s: verify error at 0x%x, size %ld.\n", + map->name, address, size); + DISABLE_VPP(map); + + return -EIO; + } + } + + DISABLE_VPP(map); + chip->state = FL_READY; + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + + return 0; +} + + + +static int amd_flash_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct map_info *map = mtd->priv; + struct amd_flash_private *private = map->fldrv_priv; + unsigned long adr, len; + int chipnum; + int ret = 0; + int i; + int first; + struct mtd_erase_region_info *regions = mtd->eraseregions; + + if (instr->addr > mtd->size) { + return -EINVAL; + } + + if ((instr->len + instr->addr) > mtd->size) { + return -EINVAL; + } + + /* Check that both start and end of the requested erase are + * aligned with the erasesize at the appropriate addresses. + */ + + i = 0; + + /* Skip all erase regions which are ended before the start of + the requested erase. Actually, to save on the calculations, + we skip to the first erase region which starts after the + start of the requested erase, and then go back one. + */ + + while ((i < mtd->numeraseregions) && + (instr->addr >= regions[i].offset)) { + i++; + } + i--; + + /* OK, now i is pointing at the erase region in which this + * erase request starts. Check the start of the requested + * erase range is aligned with the erase size which is in + * effect here. + */ + + if (instr->addr & (regions[i].erasesize-1)) { + return -EINVAL; + } + + /* Remember the erase region we start on. */ + + first = i; + + /* Next, check that the end of the requested erase is aligned + * with the erase region at that address. + */ + + while ((i < mtd->numeraseregions) && + ((instr->addr + instr->len) >= regions[i].offset)) { + i++; + } + + /* As before, drop back one to point at the region in which + * the address actually falls. + */ + + i--; + + if ((instr->addr + instr->len) & (regions[i].erasesize-1)) { + return -EINVAL; + } + + chipnum = instr->addr >> private->chipshift; + adr = instr->addr - (chipnum << private->chipshift); + len = instr->len; + + i = first; + + while (len) { + ret = erase_one_block(map, &private->chips[chipnum], adr, + regions[i].erasesize); + + if (ret) { + return ret; + } + + adr += regions[i].erasesize; + len -= regions[i].erasesize; + + if ((adr % (1 << private->chipshift)) == + ((regions[i].offset + (regions[i].erasesize * + regions[i].numblocks)) + % (1 << private->chipshift))) { + i++; + } + + if (adr >> private->chipshift) { + adr = 0; + chipnum++; + if (chipnum >= private->numchips) { + break; + } + } + } + + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + + return 0; +} + + + +static void amd_flash_sync(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct amd_flash_private *private = map->fldrv_priv; + int i; + struct flchip *chip; + int ret = 0; + DECLARE_WAITQUEUE(wait, current); + + for (i = 0; !ret && (i < private->numchips); i++) { + chip = &private->chips[i]; + + retry: + spin_lock_bh(chip->mutex); + + switch(chip->state) { + case FL_READY: + case FL_STATUS: + case FL_CFI_QUERY: + case FL_JEDEC_QUERY: + chip->oldstate = chip->state; + chip->state = FL_SYNCING; + /* No need to wake_up() on this state change - + * as the whole point is that nobody can do anything + * with the chip now anyway. + */ + case FL_SYNCING: + spin_unlock_bh(chip->mutex); + break; + + default: + /* Not an idle state */ + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + + remove_wait_queue(&chip->wq, &wait); + + goto retry; + } + } + + /* Unlock the chips again */ + for (i--; i >= 0; i--) { + chip = &private->chips[i]; + + spin_lock_bh(chip->mutex); + + if (chip->state == FL_SYNCING) { + chip->state = chip->oldstate; + wake_up(&chip->wq); + } + spin_unlock_bh(chip->mutex); + } +} + + + +static int amd_flash_suspend(struct mtd_info *mtd) +{ +printk("amd_flash_suspend(): not implemented!\n"); + return -EINVAL; +} + + + +static void amd_flash_resume(struct mtd_info *mtd) +{ +printk("amd_flash_resume(): not implemented!\n"); +} + + + +static void amd_flash_destroy(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct amd_flash_private *private = map->fldrv_priv; + kfree(private); +} + +int __init amd_flash_init(void) +{ + register_mtd_chip_driver(&amd_flash_chipdrv); + return 0; +} + +void __exit amd_flash_exit(void) +{ + unregister_mtd_chip_driver(&amd_flash_chipdrv); +} + +module_init(amd_flash_init); +module_exit(amd_flash_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jonas Holmberg "); +MODULE_DESCRIPTION("Old MTD chip driver for AMD flash chips"); diff --git a/trunk/drivers/mtd/chips/jedec.c b/trunk/drivers/mtd/chips/jedec.c new file mode 100644 index 000000000000..14e57b2bf842 --- /dev/null +++ b/trunk/drivers/mtd/chips/jedec.c @@ -0,0 +1,935 @@ + +/* JEDEC Flash Interface. + * This is an older type of interface for self programming flash. It is + * commonly use in older AMD chips and is obsolete compared with CFI. + * It is called JEDEC because the JEDEC association distributes the ID codes + * for the chips. + * + * See the AMD flash databook for information on how to operate the interface. + * + * This code does not support anything wider than 8 bit flash chips, I am + * not going to guess how to send commands to them, plus I expect they will + * all speak CFI.. + * + * $Id: jedec.c,v 1.22 2005/01/05 18:05:11 dwmw2 Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct mtd_info *jedec_probe(struct map_info *); +static int jedec_probe8(struct map_info *map,unsigned long base, + struct jedec_private *priv); +static int jedec_probe16(struct map_info *map,unsigned long base, + struct jedec_private *priv); +static int jedec_probe32(struct map_info *map,unsigned long base, + struct jedec_private *priv); +static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start, + unsigned long len); +static int flash_erase(struct mtd_info *mtd, struct erase_info *instr); +static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, + size_t *retlen, const u_char *buf); + +static unsigned long my_bank_size; + +/* Listing of parts and sizes. We need this table to learn the sector + size of the chip and the total length */ +static const struct JEDECTable JEDEC_table[] = { + { + .jedec = 0x013D, + .name = "AMD Am29F017D", + .size = 2*1024*1024, + .sectorsize = 64*1024, + .capabilities = MTD_CAP_NORFLASH + }, + { + .jedec = 0x01AD, + .name = "AMD Am29F016", + .size = 2*1024*1024, + .sectorsize = 64*1024, + .capabilities = MTD_CAP_NORFLASH + }, + { + .jedec = 0x01D5, + .name = "AMD Am29F080", + .size = 1*1024*1024, + .sectorsize = 64*1024, + .capabilities = MTD_CAP_NORFLASH + }, + { + .jedec = 0x01A4, + .name = "AMD Am29F040", + .size = 512*1024, + .sectorsize = 64*1024, + .capabilities = MTD_CAP_NORFLASH + }, + { + .jedec = 0x20E3, + .name = "AMD Am29W040B", + .size = 512*1024, + .sectorsize = 64*1024, + .capabilities = MTD_CAP_NORFLASH + }, + { + .jedec = 0xC2AD, + .name = "Macronix MX29F016", + .size = 2*1024*1024, + .sectorsize = 64*1024, + .capabilities = MTD_CAP_NORFLASH + }, + { .jedec = 0x0 } +}; + +static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id); +static void jedec_sync(struct mtd_info *mtd) {}; +static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); + +static struct mtd_info *jedec_probe(struct map_info *map); + + + +static struct mtd_chip_driver jedec_chipdrv = { + .probe = jedec_probe, + .name = "jedec", + .module = THIS_MODULE +}; + +/* Probe entry point */ + +static struct mtd_info *jedec_probe(struct map_info *map) +{ + struct mtd_info *MTD; + struct jedec_private *priv; + unsigned long Base; + unsigned long SectorSize; + unsigned count; + unsigned I,Uniq; + char Part[200]; + memset(&priv,0,sizeof(priv)); + + MTD = kzalloc(sizeof(struct mtd_info) + sizeof(struct jedec_private), GFP_KERNEL); + if (!MTD) + return NULL; + + priv = (struct jedec_private *)&MTD[1]; + + my_bank_size = map->size; + + if (map->size/my_bank_size > MAX_JEDEC_CHIPS) + { + printk("mtd: Increase MAX_JEDEC_CHIPS, too many banks.\n"); + kfree(MTD); + return NULL; + } + + for (Base = 0; Base < map->size; Base += my_bank_size) + { + // Perhaps zero could designate all tests? + if (map->buswidth == 0) + map->buswidth = 1; + + if (map->buswidth == 1){ + if (jedec_probe8(map,Base,priv) == 0) { + printk("did recognize jedec chip\n"); + kfree(MTD); + return NULL; + } + } + if (map->buswidth == 2) + jedec_probe16(map,Base,priv); + if (map->buswidth == 4) + jedec_probe32(map,Base,priv); + } + + // Get the biggest sector size + SectorSize = 0; + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + // printk("priv->chips[%d].jedec is %x\n",I,priv->chips[I].jedec); + // printk("priv->chips[%d].sectorsize is %lx\n",I,priv->chips[I].sectorsize); + if (priv->chips[I].sectorsize > SectorSize) + SectorSize = priv->chips[I].sectorsize; + } + + // Quickly ensure that the other sector sizes are factors of the largest + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + if ((SectorSize/priv->chips[I].sectorsize)*priv->chips[I].sectorsize != SectorSize) + { + printk("mtd: Failed. Device has incompatible mixed sector sizes\n"); + kfree(MTD); + return NULL; + } + } + + /* Generate a part name that includes the number of different chips and + other configuration information */ + count = 1; + strlcpy(Part,map->name,sizeof(Part)-10); + strcat(Part," "); + Uniq = 0; + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + const struct JEDECTable *JEDEC; + + if (priv->chips[I+1].jedec == priv->chips[I].jedec) + { + count++; + continue; + } + + // Locate the chip in the jedec table + JEDEC = jedec_idtoinf(priv->chips[I].jedec >> 8,priv->chips[I].jedec); + if (JEDEC == 0) + { + printk("mtd: Internal Error, JEDEC not set\n"); + kfree(MTD); + return NULL; + } + + if (Uniq != 0) + strcat(Part,","); + Uniq++; + + if (count != 1) + sprintf(Part+strlen(Part),"%x*[%s]",count,JEDEC->name); + else + sprintf(Part+strlen(Part),"%s",JEDEC->name); + if (strlen(Part) > sizeof(Part)*2/3) + break; + count = 1; + } + + /* Determine if the chips are organized in a linear fashion, or if there + are empty banks. Note, the last bank does not count here, only the + first banks are important. Holes on non-bank boundaries can not exist + due to the way the detection algorithm works. */ + if (priv->size < my_bank_size) + my_bank_size = priv->size; + priv->is_banked = 0; + //printk("priv->size is %x, my_bank_size is %x\n",priv->size,my_bank_size); + //printk("priv->bank_fill[0] is %x\n",priv->bank_fill[0]); + if (!priv->size) { + printk("priv->size is zero\n"); + kfree(MTD); + return NULL; + } + if (priv->size/my_bank_size) { + if (priv->size/my_bank_size == 1) { + priv->size = my_bank_size; + } + else { + for (I = 0; I != priv->size/my_bank_size - 1; I++) + { + if (priv->bank_fill[I] != my_bank_size) + priv->is_banked = 1; + + /* This even could be eliminated, but new de-optimized read/write + functions have to be written */ + printk("priv->bank_fill[%d] is %lx, priv->bank_fill[0] is %lx\n",I,priv->bank_fill[I],priv->bank_fill[0]); + if (priv->bank_fill[I] != priv->bank_fill[0]) + { + printk("mtd: Failed. Cannot handle unsymmetric banking\n"); + kfree(MTD); + return NULL; + } + } + } + } + if (priv->is_banked == 1) + strcat(Part,", banked"); + + // printk("Part: '%s'\n",Part); + + memset(MTD,0,sizeof(*MTD)); + // strlcpy(MTD->name,Part,sizeof(MTD->name)); + MTD->name = map->name; + MTD->type = MTD_NORFLASH; + MTD->flags = MTD_CAP_NORFLASH; + MTD->writesize = 1; + MTD->erasesize = SectorSize*(map->buswidth); + // printk("MTD->erasesize is %x\n",(unsigned int)MTD->erasesize); + MTD->size = priv->size; + // printk("MTD->size is %x\n",(unsigned int)MTD->size); + //MTD->module = THIS_MODULE; // ? Maybe this should be the low level module? + MTD->erase = flash_erase; + if (priv->is_banked == 1) + MTD->read = jedec_read_banked; + else + MTD->read = jedec_read; + MTD->write = flash_write; + MTD->sync = jedec_sync; + MTD->priv = map; + map->fldrv_priv = priv; + map->fldrv = &jedec_chipdrv; + __module_get(THIS_MODULE); + return MTD; +} + +/* Helper for the JEDEC function, JEDEC numbers all have odd parity */ +static int checkparity(u_char C) +{ + u_char parity = 0; + while (C != 0) + { + parity ^= C & 1; + C >>= 1; + } + + return parity == 1; +} + + +/* Take an array of JEDEC numbers that represent interleved flash chips + and process them. Check to make sure they are good JEDEC numbers, look + them up and then add them to the chip list */ +static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count, + unsigned long base,struct jedec_private *priv) +{ + unsigned I,J; + unsigned long Size; + unsigned long SectorSize; + const struct JEDECTable *JEDEC; + + // Test #2 JEDEC numbers exhibit odd parity + for (I = 0; I != Count; I++) + { + if (checkparity(Mfg[I]) == 0 || checkparity(Id[I]) == 0) + return 0; + } + + // Finally, just make sure all the chip sizes are the same + JEDEC = jedec_idtoinf(Mfg[0],Id[0]); + + if (JEDEC == 0) + { + printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]); + return 0; + } + + Size = JEDEC->size; + SectorSize = JEDEC->sectorsize; + for (I = 0; I != Count; I++) + { + JEDEC = jedec_idtoinf(Mfg[0],Id[0]); + if (JEDEC == 0) + { + printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]); + return 0; + } + + if (Size != JEDEC->size || SectorSize != JEDEC->sectorsize) + { + printk("mtd: Failed. Interleved flash does not have matching characteristics\n"); + return 0; + } + } + + // Load the Chips + for (I = 0; I != MAX_JEDEC_CHIPS; I++) + { + if (priv->chips[I].jedec == 0) + break; + } + + if (I + Count > MAX_JEDEC_CHIPS) + { + printk("mtd: Device has too many chips. Increase MAX_JEDEC_CHIPS\n"); + return 0; + } + + // Add them to the table + for (J = 0; J != Count; J++) + { + unsigned long Bank; + + JEDEC = jedec_idtoinf(Mfg[J],Id[J]); + priv->chips[I].jedec = (Mfg[J] << 8) | Id[J]; + priv->chips[I].size = JEDEC->size; + priv->chips[I].sectorsize = JEDEC->sectorsize; + priv->chips[I].base = base + J; + priv->chips[I].datashift = J*8; + priv->chips[I].capabilities = JEDEC->capabilities; + priv->chips[I].offset = priv->size + J; + + // log2 n :| + priv->chips[I].addrshift = 0; + for (Bank = Count; Bank != 1; Bank >>= 1, priv->chips[I].addrshift++); + + // Determine how filled this bank is. + Bank = base & (~(my_bank_size-1)); + if (priv->bank_fill[Bank/my_bank_size] < base + + (JEDEC->size << priv->chips[I].addrshift) - Bank) + priv->bank_fill[Bank/my_bank_size] = base + (JEDEC->size << priv->chips[I].addrshift) - Bank; + I++; + } + + priv->size += priv->chips[I-1].size*Count; + + return priv->chips[I-1].size; +} + +/* Lookup the chip information from the JEDEC ID table. */ +static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id) +{ + __u16 Id = (mfr << 8) | id; + unsigned long I = 0; + for (I = 0; JEDEC_table[I].jedec != 0; I++) + if (JEDEC_table[I].jedec == Id) + return JEDEC_table + I; + return NULL; +} + +// Look for flash using an 8 bit bus interface +static int jedec_probe8(struct map_info *map,unsigned long base, + struct jedec_private *priv) +{ + #define flread(x) map_read8(map,base+x) + #define flwrite(v,x) map_write8(map,v,base+x) + + const unsigned long AutoSel1 = 0xAA; + const unsigned long AutoSel2 = 0x55; + const unsigned long AutoSel3 = 0x90; + const unsigned long Reset = 0xF0; + __u32 OldVal; + __u8 Mfg[1]; + __u8 Id[1]; + unsigned I; + unsigned long Size; + + // Wait for any write/erase operation to settle + OldVal = flread(base); + for (I = 0; OldVal != flread(base) && I < 10000; I++) + OldVal = flread(base); + + // Reset the chip + flwrite(Reset,0x555); + + // Send the sequence + flwrite(AutoSel1,0x555); + flwrite(AutoSel2,0x2AA); + flwrite(AutoSel3,0x555); + + // Get the JEDEC numbers + Mfg[0] = flread(0); + Id[0] = flread(1); + // printk("Mfg is %x, Id is %x\n",Mfg[0],Id[0]); + + Size = handle_jedecs(map,Mfg,Id,1,base,priv); + // printk("handle_jedecs Size is %x\n",(unsigned int)Size); + if (Size == 0) + { + flwrite(Reset,0x555); + return 0; + } + + + // Reset. + flwrite(Reset,0x555); + + return 1; + + #undef flread + #undef flwrite +} + +// Look for flash using a 16 bit bus interface (ie 2 8-bit chips) +static int jedec_probe16(struct map_info *map,unsigned long base, + struct jedec_private *priv) +{ + return 0; +} + +// Look for flash using a 32 bit bus interface (ie 4 8-bit chips) +static int jedec_probe32(struct map_info *map,unsigned long base, + struct jedec_private *priv) +{ + #define flread(x) map_read32(map,base+((x)<<2)) + #define flwrite(v,x) map_write32(map,v,base+((x)<<2)) + + const unsigned long AutoSel1 = 0xAAAAAAAA; + const unsigned long AutoSel2 = 0x55555555; + const unsigned long AutoSel3 = 0x90909090; + const unsigned long Reset = 0xF0F0F0F0; + __u32 OldVal; + __u8 Mfg[4]; + __u8 Id[4]; + unsigned I; + unsigned long Size; + + // Wait for any write/erase operation to settle + OldVal = flread(base); + for (I = 0; OldVal != flread(base) && I < 10000; I++) + OldVal = flread(base); + + // Reset the chip + flwrite(Reset,0x555); + + // Send the sequence + flwrite(AutoSel1,0x555); + flwrite(AutoSel2,0x2AA); + flwrite(AutoSel3,0x555); + + // Test #1, JEDEC numbers are readable from 0x??00/0x??01 + if (flread(0) != flread(0x100) || + flread(1) != flread(0x101)) + { + flwrite(Reset,0x555); + return 0; + } + + // Split up the JEDEC numbers + OldVal = flread(0); + for (I = 0; I != 4; I++) + Mfg[I] = (OldVal >> (I*8)); + OldVal = flread(1); + for (I = 0; I != 4; I++) + Id[I] = (OldVal >> (I*8)); + + Size = handle_jedecs(map,Mfg,Id,4,base,priv); + if (Size == 0) + { + flwrite(Reset,0x555); + return 0; + } + + /* Check if there is address wrap around within a single bank, if this + returns JEDEC numbers then we assume that it is wrap around. Notice + we call this routine with the JEDEC return still enabled, if two or + more flashes have a truncated address space the probe test will still + work */ + if (base + (Size<<2)+0x555 < map->size && + base + (Size<<2)+0x555 < (base & (~(my_bank_size-1))) + my_bank_size) + { + if (flread(base+Size) != flread(base+Size + 0x100) || + flread(base+Size + 1) != flread(base+Size + 0x101)) + { + jedec_probe32(map,base+Size,priv); + } + } + + // Reset. + flwrite(0xF0F0F0F0,0x555); + + return 1; + + #undef flread + #undef flwrite +} + +/* Linear read. */ +static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct map_info *map = mtd->priv; + + map_copy_from(map, buf, from, len); + *retlen = len; + return 0; +} + +/* Banked read. Take special care to jump past the holes in the bank + mapping. This version assumes symetry in the holes.. */ +static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct map_info *map = mtd->priv; + struct jedec_private *priv = map->fldrv_priv; + + *retlen = 0; + while (len > 0) + { + // Determine what bank and offset into that bank the first byte is + unsigned long bank = from & (~(priv->bank_fill[0]-1)); + unsigned long offset = from & (priv->bank_fill[0]-1); + unsigned long get = len; + if (priv->bank_fill[0] - offset < len) + get = priv->bank_fill[0] - offset; + + bank /= priv->bank_fill[0]; + map_copy_from(map,buf + *retlen,bank*my_bank_size + offset,get); + + len -= get; + *retlen += get; + from += get; + } + return 0; +} + +/* Pass the flags value that the flash return before it re-entered read + mode. */ +static void jedec_flash_failed(unsigned char code) +{ + /* Bit 5 being high indicates that there was an internal device + failure, erasure time limits exceeded or something */ + if ((code & (1 << 5)) != 0) + { + printk("mtd: Internal Flash failure\n"); + return; + } + printk("mtd: Programming didn't take\n"); +} + +/* This uses the erasure function described in the AMD Flash Handbook, + it will work for flashes with a fixed sector size only. Flashes with + a selection of sector sizes (ie the AMD Am29F800B) will need a different + routine. This routine tries to parallize erasing multiple chips/sectors + where possible */ +static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + // Does IO to the currently selected chip + #define flread(x) map_read8(map,chip->base+((x)<addrshift)) + #define flwrite(v,x) map_write8(map,v,chip->base+((x)<addrshift)) + + unsigned long Time = 0; + unsigned long NoTime = 0; + unsigned long start = instr->addr, len = instr->len; + unsigned int I; + struct map_info *map = mtd->priv; + struct jedec_private *priv = map->fldrv_priv; + + // Verify the arguments.. + if (start + len > mtd->size || + (start % mtd->erasesize) != 0 || + (len % mtd->erasesize) != 0 || + (len/mtd->erasesize) == 0) + return -EINVAL; + + jedec_flash_chip_scan(priv,start,len); + + // Start the erase sequence on each chip + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + unsigned long off; + struct jedec_flash_chip *chip = priv->chips + I; + + if (chip->length == 0) + continue; + + if (chip->start + chip->length > chip->size) + { + printk("DIE\n"); + return -EIO; + } + + flwrite(0xF0,chip->start + 0x555); + flwrite(0xAA,chip->start + 0x555); + flwrite(0x55,chip->start + 0x2AA); + flwrite(0x80,chip->start + 0x555); + flwrite(0xAA,chip->start + 0x555); + flwrite(0x55,chip->start + 0x2AA); + + /* Once we start selecting the erase sectors the delay between each + command must not exceed 50us or it will immediately start erasing + and ignore the other sectors */ + for (off = 0; off < len; off += chip->sectorsize) + { + // Check to make sure we didn't timeout + flwrite(0x30,chip->start + off); + if (off == 0) + continue; + if ((flread(chip->start + off) & (1 << 3)) != 0) + { + printk("mtd: Ack! We timed out the erase timer!\n"); + return -EIO; + } + } + } + + /* We could split this into a timer routine and return early, performing + background erasure.. Maybe later if the need warrents */ + + /* Poll the flash for erasure completion, specs say this can take as long + as 480 seconds to do all the sectors (for a 2 meg flash). + Erasure time is dependent on chip age, temp and wear.. */ + + /* This being a generic routine assumes a 32 bit bus. It does read32s + and bundles interleved chips into the same grouping. This will work + for all bus widths */ + Time = 0; + NoTime = 0; + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + struct jedec_flash_chip *chip = priv->chips + I; + unsigned long off = 0; + unsigned todo[4] = {0,0,0,0}; + unsigned todo_left = 0; + unsigned J; + + if (chip->length == 0) + continue; + + /* Find all chips in this data line, realistically this is all + or nothing up to the interleve count */ + for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++) + { + if ((priv->chips[J].base & (~((1<addrshift)-1))) == + (chip->base & (~((1<addrshift)-1)))) + { + todo_left++; + todo[priv->chips[J].base & ((1<addrshift)-1)] = 1; + } + } + + /* printk("todo: %x %x %x %x\n",(short)todo[0],(short)todo[1], + (short)todo[2],(short)todo[3]); + */ + while (1) + { + __u32 Last[4]; + unsigned long Count = 0; + + /* During erase bit 7 is held low and bit 6 toggles, we watch this, + should it stop toggling or go high then the erase is completed, + or this is not really flash ;> */ + switch (map->buswidth) { + case 1: + Last[0] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[1] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[2] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + case 2: + Last[0] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[1] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[2] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + case 3: + Last[0] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[1] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); + Last[2] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + } + Count = 3; + while (todo_left != 0) + { + for (J = 0; J != 4; J++) + { + __u8 Byte1 = (Last[(Count-1)%4] >> (J*8)) & 0xFF; + __u8 Byte2 = (Last[(Count-2)%4] >> (J*8)) & 0xFF; + __u8 Byte3 = (Last[(Count-3)%4] >> (J*8)) & 0xFF; + if (todo[J] == 0) + continue; + + if ((Byte1 & (1 << 7)) == 0 && Byte1 != Byte2) + { +// printk("Check %x %x %x\n",(short)J,(short)Byte1,(short)Byte2); + continue; + } + + if (Byte1 == Byte2) + { + jedec_flash_failed(Byte3); + return -EIO; + } + + todo[J] = 0; + todo_left--; + } + +/* if (NoTime == 0) + Time += HZ/10 - schedule_timeout(HZ/10);*/ + NoTime = 0; + + switch (map->buswidth) { + case 1: + Last[Count % 4] = map_read8(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + case 2: + Last[Count % 4] = map_read16(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + case 4: + Last[Count % 4] = map_read32(map,(chip->base >> chip->addrshift) + chip->start + off); + break; + } + Count++; + +/* // Count time, max of 15s per sector (according to AMD) + if (Time > 15*len/mtd->erasesize*HZ) + { + printk("mtd: Flash Erase Timed out\n"); + return -EIO; + } */ + } + + // Skip to the next chip if we used chip erase + if (chip->length == chip->size) + off = chip->size; + else + off += chip->sectorsize; + + if (off >= chip->length) + break; + NoTime = 1; + } + + for (J = 0; priv->chips[J].jedec != 0 && J < MAX_JEDEC_CHIPS; J++) + { + if ((priv->chips[J].base & (~((1<addrshift)-1))) == + (chip->base & (~((1<addrshift)-1)))) + priv->chips[J].length = 0; + } + } + + //printk("done\n"); + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + return 0; + + #undef flread + #undef flwrite +} + +/* This is the simple flash writing function. It writes to every byte, in + sequence. It takes care of how to properly address the flash if + the flash is interleved. It can only be used if all the chips in the + array are identical!*/ +static int flash_write(struct mtd_info *mtd, loff_t start, size_t len, + size_t *retlen, const u_char *buf) +{ + /* Does IO to the currently selected chip. It takes the bank addressing + base (which is divisible by the chip size) adds the necessary lower bits + of addrshift (interleave index) and then adds the control register index. */ + #define flread(x) map_read8(map,base+(off&((1<addrshift)-1))+((x)<addrshift)) + #define flwrite(v,x) map_write8(map,v,base+(off&((1<addrshift)-1))+((x)<addrshift)) + + struct map_info *map = mtd->priv; + struct jedec_private *priv = map->fldrv_priv; + unsigned long base; + unsigned long off; + size_t save_len = len; + + if (start + len > mtd->size) + return -EIO; + + //printk("Here"); + + //printk("flash_write: start is %x, len is %x\n",start,(unsigned long)len); + while (len != 0) + { + struct jedec_flash_chip *chip = priv->chips; + unsigned long bank; + unsigned long boffset; + + // Compute the base of the flash. + off = ((unsigned long)start) % (chip->size << chip->addrshift); + base = start - off; + + // Perform banked addressing translation. + bank = base & (~(priv->bank_fill[0]-1)); + boffset = base & (priv->bank_fill[0]-1); + bank = (bank/priv->bank_fill[0])*my_bank_size; + base = bank + boffset; + + // printk("Flasing %X %X %X\n",base,chip->size,len); + // printk("off is %x, compare with %x\n",off,chip->size << chip->addrshift); + + // Loop over this page + for (; off != (chip->size << chip->addrshift) && len != 0; start++, len--, off++,buf++) + { + unsigned char oldbyte = map_read8(map,base+off); + unsigned char Last[4]; + unsigned long Count = 0; + + if (oldbyte == *buf) { + // printk("oldbyte and *buf is %x,len is %x\n",oldbyte,len); + continue; + } + if (((~oldbyte) & *buf) != 0) + printk("mtd: warn: Trying to set a 0 to a 1\n"); + + // Write + flwrite(0xAA,0x555); + flwrite(0x55,0x2AA); + flwrite(0xA0,0x555); + map_write8(map,*buf,base + off); + Last[0] = map_read8(map,base + off); + Last[1] = map_read8(map,base + off); + Last[2] = map_read8(map,base + off); + + /* Wait for the flash to finish the operation. We store the last 4 + status bytes that have been retrieved so we can determine why + it failed. The toggle bits keep toggling when there is a + failure */ + for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && + Count < 10000; Count++) + Last[Count % 4] = map_read8(map,base + off); + if (Last[(Count - 1) % 4] != *buf) + { + jedec_flash_failed(Last[(Count - 3) % 4]); + return -EIO; + } + } + } + *retlen = save_len; + return 0; +} + +/* This is used to enhance the speed of the erase routine, + when things are being done to multiple chips it is possible to + parallize the operations, particularly full memory erases of multi + chip memories benifit */ +static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start, + unsigned long len) +{ + unsigned int I; + + // Zero the records + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + priv->chips[I].start = priv->chips[I].length = 0; + + // Intersect the region with each chip + for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++) + { + struct jedec_flash_chip *chip = priv->chips + I; + unsigned long ByteStart; + unsigned long ChipEndByte = chip->offset + (chip->size << chip->addrshift); + + // End is before this chip or the start is after it + if (start+len < chip->offset || + ChipEndByte - (1 << chip->addrshift) < start) + continue; + + if (start < chip->offset) + { + ByteStart = chip->offset; + chip->start = 0; + } + else + { + chip->start = (start - chip->offset + (1 << chip->addrshift)-1) >> chip->addrshift; + ByteStart = start; + } + + if (start + len >= ChipEndByte) + chip->length = (ChipEndByte - ByteStart) >> chip->addrshift; + else + chip->length = (start + len - ByteStart + (1 << chip->addrshift)-1) >> chip->addrshift; + } +} + +int __init jedec_init(void) +{ + register_mtd_chip_driver(&jedec_chipdrv); + return 0; +} + +static void __exit jedec_exit(void) +{ + unregister_mtd_chip_driver(&jedec_chipdrv); +} + +module_init(jedec_init); +module_exit(jedec_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jason Gunthorpe et al."); +MODULE_DESCRIPTION("Old MTD chip driver for JEDEC-compliant flash chips"); diff --git a/trunk/drivers/mtd/chips/sharp.c b/trunk/drivers/mtd/chips/sharp.c new file mode 100644 index 000000000000..c9cd3d21ccfa --- /dev/null +++ b/trunk/drivers/mtd/chips/sharp.c @@ -0,0 +1,601 @@ +/* + * MTD chip driver for pre-CFI Sharp flash chips + * + * Copyright 2000,2001 David A. Schleef + * 2000,2001 Lineo, Inc. + * + * $Id: sharp.c,v 1.17 2005/11/29 14:28:28 gleixner Exp $ + * + * Devices supported: + * LH28F016SCT Symmetrical block flash memory, 2Mx8 + * LH28F008SCT Symmetrical block flash memory, 1Mx8 + * + * Documentation: + * http://www.sharpmeg.com/datasheets/memic/flashcmp/ + * http://www.sharpmeg.com/datasheets/memic/flashcmp/01symf/16m/016sctl9.pdf + * 016sctl9.pdf + * + * Limitations: + * This driver only supports 4x1 arrangement of chips. + * Not tested on anything but PowerPC. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CMD_RESET 0xffffffff +#define CMD_READ_ID 0x90909090 +#define CMD_READ_STATUS 0x70707070 +#define CMD_CLEAR_STATUS 0x50505050 +#define CMD_BLOCK_ERASE_1 0x20202020 +#define CMD_BLOCK_ERASE_2 0xd0d0d0d0 +#define CMD_BYTE_WRITE 0x40404040 +#define CMD_SUSPEND 0xb0b0b0b0 +#define CMD_RESUME 0xd0d0d0d0 +#define CMD_SET_BLOCK_LOCK_1 0x60606060 +#define CMD_SET_BLOCK_LOCK_2 0x01010101 +#define CMD_SET_MASTER_LOCK_1 0x60606060 +#define CMD_SET_MASTER_LOCK_2 0xf1f1f1f1 +#define CMD_CLEAR_BLOCK_LOCKS_1 0x60606060 +#define CMD_CLEAR_BLOCK_LOCKS_2 0xd0d0d0d0 + +#define SR_READY 0x80808080 // 1 = ready +#define SR_ERASE_SUSPEND 0x40404040 // 1 = block erase suspended +#define SR_ERROR_ERASE 0x20202020 // 1 = error in block erase or clear lock bits +#define SR_ERROR_WRITE 0x10101010 // 1 = error in byte write or set lock bit +#define SR_VPP 0x08080808 // 1 = Vpp is low +#define SR_WRITE_SUSPEND 0x04040404 // 1 = byte write suspended +#define SR_PROTECT 0x02020202 // 1 = lock bit set +#define SR_RESERVED 0x01010101 + +#define SR_ERRORS (SR_ERROR_ERASE|SR_ERROR_WRITE|SR_VPP|SR_PROTECT) + +/* Configuration options */ + +#undef AUTOUNLOCK /* automatically unlocks blocks before erasing */ + +static struct mtd_info *sharp_probe(struct map_info *); + +static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd); + +static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +static int sharp_write(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, const u_char *buf); +static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr); +static void sharp_sync(struct mtd_info *mtd); +static int sharp_suspend(struct mtd_info *mtd); +static void sharp_resume(struct mtd_info *mtd); +static void sharp_destroy(struct mtd_info *mtd); + +static int sharp_write_oneword(struct map_info *map, struct flchip *chip, + unsigned long adr, __u32 datum); +static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip, + unsigned long adr); +#ifdef AUTOUNLOCK +static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip, + unsigned long adr); +#endif + + +struct sharp_info{ + struct flchip *chip; + int bogus; + int chipshift; + int numchips; + struct flchip chips[1]; +}; + +static void sharp_destroy(struct mtd_info *mtd); + +static struct mtd_chip_driver sharp_chipdrv = { + .probe = sharp_probe, + .destroy = sharp_destroy, + .name = "sharp", + .module = THIS_MODULE +}; + + +static struct mtd_info *sharp_probe(struct map_info *map) +{ + struct mtd_info *mtd = NULL; + struct sharp_info *sharp = NULL; + int width; + + mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); + if(!mtd) + return NULL; + + sharp = kzalloc(sizeof(*sharp), GFP_KERNEL); + if(!sharp) { + kfree(mtd); + return NULL; + } + + width = sharp_probe_map(map,mtd); + if(!width){ + kfree(mtd); + kfree(sharp); + return NULL; + } + + mtd->priv = map; + mtd->type = MTD_NORFLASH; + mtd->erase = sharp_erase; + mtd->read = sharp_read; + mtd->write = sharp_write; + mtd->sync = sharp_sync; + mtd->suspend = sharp_suspend; + mtd->resume = sharp_resume; + mtd->flags = MTD_CAP_NORFLASH; + mtd->writesize = 1; + mtd->name = map->name; + + sharp->chipshift = 23; + sharp->numchips = 1; + sharp->chips[0].start = 0; + sharp->chips[0].state = FL_READY; + sharp->chips[0].mutex = &sharp->chips[0]._spinlock; + sharp->chips[0].word_write_time = 0; + init_waitqueue_head(&sharp->chips[0].wq); + spin_lock_init(&sharp->chips[0]._spinlock); + + map->fldrv = &sharp_chipdrv; + map->fldrv_priv = sharp; + + __module_get(THIS_MODULE); + return mtd; +} + +static inline void sharp_send_cmd(struct map_info *map, unsigned long cmd, unsigned long adr) +{ + map_word map_cmd; + map_cmd.x[0] = cmd; + map_write(map, map_cmd, adr); +} + +static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd) +{ + map_word tmp, read0, read4; + unsigned long base = 0; + int width = 4; + + tmp = map_read(map, base+0); + + sharp_send_cmd(map, CMD_READ_ID, base+0); + + read0 = map_read(map, base+0); + read4 = map_read(map, base+4); + if(read0.x[0] == 0x89898989){ + printk("Looks like sharp flash\n"); + switch(read4.x[0]){ + case 0xaaaaaaaa: + case 0xa0a0a0a0: + /* aa - LH28F016SCT-L95 2Mx8, 32 64k blocks*/ + /* a0 - LH28F016SCT-Z4 2Mx8, 32 64k blocks*/ + mtd->erasesize = 0x10000 * width; + mtd->size = 0x200000 * width; + return width; + case 0xa6a6a6a6: + /* a6 - LH28F008SCT-L12 1Mx8, 16 64k blocks*/ + /* a6 - LH28F008SCR-L85 1Mx8, 16 64k blocks*/ + mtd->erasesize = 0x10000 * width; + mtd->size = 0x100000 * width; + return width; +#if 0 + case 0x00000000: /* unknown */ + /* XX - LH28F004SCT 512kx8, 8 64k blocks*/ + mtd->erasesize = 0x10000 * width; + mtd->size = 0x80000 * width; + return width; +#endif + default: + printk("Sort-of looks like sharp flash, 0x%08lx 0x%08lx\n", + read0.x[0], read4.x[0]); + } + }else if((map_read(map, base+0).x[0] == CMD_READ_ID)){ + /* RAM, probably */ + printk("Looks like RAM\n"); + map_write(map, tmp, base+0); + }else{ + printk("Doesn't look like sharp flash, 0x%08lx 0x%08lx\n", + read0.x[0], read4.x[0]); + } + + return 0; +} + +/* This function returns with the chip->mutex lock held. */ +static int sharp_wait(struct map_info *map, struct flchip *chip) +{ + int i; + map_word status; + unsigned long timeo = jiffies + HZ; + DECLARE_WAITQUEUE(wait, current); + int adr = 0; + +retry: + spin_lock_bh(chip->mutex); + + switch(chip->state){ + case FL_READY: + sharp_send_cmd(map, CMD_READ_STATUS, adr); + chip->state = FL_STATUS; + case FL_STATUS: + for(i=0;i<100;i++){ + status = map_read(map, adr); + if((status.x[0] & SR_READY)==SR_READY) + break; + udelay(1); + } + break; + default: + printk("Waiting for chip\n"); + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + spin_unlock_bh(chip->mutex); + + schedule(); + remove_wait_queue(&chip->wq, &wait); + + if(signal_pending(current)) + return -EINTR; + + timeo = jiffies + HZ; + + goto retry; + } + + sharp_send_cmd(map, CMD_RESET, adr); + + chip->state = FL_READY; + + return 0; +} + +static void sharp_release(struct flchip *chip) +{ + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); +} + +static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct map_info *map = mtd->priv; + struct sharp_info *sharp = map->fldrv_priv; + int chipnum; + int ret = 0; + int ofs = 0; + + chipnum = (from >> sharp->chipshift); + ofs = from & ((1 << sharp->chipshift)-1); + + *retlen = 0; + + while(len){ + unsigned long thislen; + + if(chipnum>=sharp->numchips) + break; + + thislen = len; + if(ofs+thislen >= (1<chipshift)) + thislen = (1<chipshift) - ofs; + + ret = sharp_wait(map,&sharp->chips[chipnum]); + if(ret<0) + break; + + map_copy_from(map,buf,ofs,thislen); + + sharp_release(&sharp->chips[chipnum]); + + *retlen += thislen; + len -= thislen; + buf += thislen; + + ofs = 0; + chipnum++; + } + return ret; +} + +static int sharp_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct map_info *map = mtd->priv; + struct sharp_info *sharp = map->fldrv_priv; + int ret = 0; + int i,j; + int chipnum; + unsigned long ofs; + union { u32 l; unsigned char uc[4]; } tbuf; + + *retlen = 0; + + while(len){ + tbuf.l = 0xffffffff; + chipnum = to >> sharp->chipshift; + ofs = to & ((1<chipshift)-1); + + j=0; + for(i=ofs&3;i<4 && len;i++){ + tbuf.uc[i] = *buf; + buf++; + to++; + len--; + j++; + } + sharp_write_oneword(map, &sharp->chips[chipnum], ofs&~3, tbuf.l); + if(ret<0) + return ret; + (*retlen)+=j; + } + + return 0; +} + +static int sharp_write_oneword(struct map_info *map, struct flchip *chip, + unsigned long adr, __u32 datum) +{ + int ret; + int timeo; + int try; + int i; + map_word data, status; + + status.x[0] = 0; + ret = sharp_wait(map,chip); + + for(try=0;try<10;try++){ + sharp_send_cmd(map, CMD_BYTE_WRITE, adr); + /* cpu_to_le32 -> hack to fix the writel be->le conversion */ + data.x[0] = cpu_to_le32(datum); + map_write(map, data, adr); + + chip->state = FL_WRITING; + + timeo = jiffies + (HZ/2); + + sharp_send_cmd(map, CMD_READ_STATUS, adr); + for(i=0;i<100;i++){ + status = map_read(map, adr); + if((status.x[0] & SR_READY) == SR_READY) + break; + } + if(i==100){ + printk("sharp: timed out writing\n"); + } + + if(!(status.x[0] & SR_ERRORS)) + break; + + printk("sharp: error writing byte at addr=%08lx status=%08lx\n", adr, status.x[0]); + + sharp_send_cmd(map, CMD_CLEAR_STATUS, adr); + } + sharp_send_cmd(map, CMD_RESET, adr); + chip->state = FL_READY; + + wake_up(&chip->wq); + spin_unlock_bh(chip->mutex); + + return 0; +} + +static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct map_info *map = mtd->priv; + struct sharp_info *sharp = map->fldrv_priv; + unsigned long adr,len; + int chipnum, ret=0; + +//printk("sharp_erase()\n"); + if(instr->addr & (mtd->erasesize - 1)) + return -EINVAL; + if(instr->len & (mtd->erasesize - 1)) + return -EINVAL; + if(instr->len + instr->addr > mtd->size) + return -EINVAL; + + chipnum = instr->addr >> sharp->chipshift; + adr = instr->addr & ((1<chipshift)-1); + len = instr->len; + + while(len){ + ret = sharp_erase_oneblock(map, &sharp->chips[chipnum], adr); + if(ret)return ret; + + adr += mtd->erasesize; + len -= mtd->erasesize; + if(adr >> sharp->chipshift){ + adr = 0; + chipnum++; + if(chipnum>=sharp->numchips) + break; + } + } + + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + + return 0; +} + +static int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip, + unsigned long adr) +{ + int ret; + unsigned long timeo; + map_word status; + DECLARE_WAITQUEUE(wait, current); + + sharp_send_cmd(map, CMD_READ_STATUS, adr); + status = map_read(map, adr); + + timeo = jiffies + HZ; + + while(time_before(jiffies, timeo)){ + sharp_send_cmd(map, CMD_READ_STATUS, adr); + status = map_read(map, adr); + if((status.x[0] & SR_READY)==SR_READY){ + ret = 0; + goto out; + } + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + + //spin_unlock_bh(chip->mutex); + + schedule_timeout(1); + schedule(); + remove_wait_queue(&chip->wq, &wait); + + //spin_lock_bh(chip->mutex); + + if (signal_pending(current)){ + ret = -EINTR; + goto out; + } + + } + ret = -ETIME; +out: + return ret; +} + +static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip, + unsigned long adr) +{ + int ret; + //int timeo; + map_word status; + //int i; + +//printk("sharp_erase_oneblock()\n"); + +#ifdef AUTOUNLOCK + /* This seems like a good place to do an unlock */ + sharp_unlock_oneblock(map,chip,adr); +#endif + + sharp_send_cmd(map, CMD_BLOCK_ERASE_1, adr); + sharp_send_cmd(map, CMD_BLOCK_ERASE_2, adr); + + chip->state = FL_ERASING; + + ret = sharp_do_wait_for_ready(map,chip,adr); + if(ret<0)return ret; + + sharp_send_cmd(map, CMD_READ_STATUS, adr); + status = map_read(map, adr); + + if(!(status.x[0] & SR_ERRORS)){ + sharp_send_cmd(map, CMD_RESET, adr); + chip->state = FL_READY; + //spin_unlock_bh(chip->mutex); + return 0; + } + + printk("sharp: error erasing block at addr=%08lx status=%08lx\n", adr, status.x[0]); + sharp_send_cmd(map, CMD_CLEAR_STATUS, adr); + + //spin_unlock_bh(chip->mutex); + + return -EIO; +} + +#ifdef AUTOUNLOCK +static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip, + unsigned long adr) +{ + int i; + map_word status; + + sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_1, adr); + sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_2, adr); + + udelay(100); + + status = map_read(map, adr); + printk("status=%08lx\n", status.x[0]); + + for(i=0;i<1000;i++){ + //sharp_send_cmd(map, CMD_READ_STATUS, adr); + status = map_read(map, adr); + if((status.x[0] & SR_READY) == SR_READY) + break; + udelay(100); + } + if(i==1000){ + printk("sharp: timed out unlocking block\n"); + } + + if(!(status.x[0] & SR_ERRORS)){ + sharp_send_cmd(map, CMD_RESET, adr); + chip->state = FL_READY; + return; + } + + printk("sharp: error unlocking block at addr=%08lx status=%08lx\n", adr, status.x[0]); + sharp_send_cmd(map, CMD_CLEAR_STATUS, adr); +} +#endif + +static void sharp_sync(struct mtd_info *mtd) +{ + //printk("sharp_sync()\n"); +} + +static int sharp_suspend(struct mtd_info *mtd) +{ + printk("sharp_suspend()\n"); + return -EINVAL; +} + +static void sharp_resume(struct mtd_info *mtd) +{ + printk("sharp_resume()\n"); + +} + +static void sharp_destroy(struct mtd_info *mtd) +{ + printk("sharp_destroy()\n"); + +} + +static int __init sharp_probe_init(void) +{ + printk("MTD Sharp chip driver \n"); + + register_mtd_chip_driver(&sharp_chipdrv); + + return 0; +} + +static void __exit sharp_probe_exit(void) +{ + unregister_mtd_chip_driver(&sharp_chipdrv); +} + +module_init(sharp_probe_init); +module_exit(sharp_probe_exit); + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Schleef "); +MODULE_DESCRIPTION("Old MTD chip driver for pre-CFI Sharp flash chips"); diff --git a/trunk/drivers/mtd/devices/block2mtd.c b/trunk/drivers/mtd/devices/block2mtd.c index be4b9948c762..fc4cc8ba9e29 100644 --- a/trunk/drivers/mtd/devices/block2mtd.c +++ b/trunk/drivers/mtd/devices/block2mtd.c @@ -373,7 +373,7 @@ static inline void kill_final_newline(char *str) #ifndef MODULE static int block2mtd_init_called = 0; -static char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */ +static __initdata char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */ #endif diff --git a/trunk/drivers/mtd/maps/Kconfig b/trunk/drivers/mtd/maps/Kconfig index b665e4ac2208..d990d8141ef5 100644 --- a/trunk/drivers/mtd/maps/Kconfig +++ b/trunk/drivers/mtd/maps/Kconfig @@ -60,7 +60,7 @@ config MTD_PHYSMAP_BANKWIDTH (i.e., run-time calling physmap_configure()). config MTD_PHYSMAP_OF - tristate "Flash device in physical memory map based on OF description" + tristate "Flash device in physical memory map based on OF descirption" depends on PPC_OF && (MTD_CFI || MTD_JEDECPROBE || MTD_ROM) help This provides a 'mapping' driver which allows the NOR Flash and @@ -358,6 +358,22 @@ config MTD_CFI_FLAGADM Mapping for the Flaga digital module. If you don't have one, ignore this setting. +config MTD_BEECH + tristate "CFI Flash device mapped on IBM 405LP Beech" + depends on MTD_CFI && BEECH + help + This enables access routines for the flash chips on the IBM + 405LP Beech board. If you have one of these boards and would like + to use the flash chips on it, say 'Y'. + +config MTD_ARCTIC + tristate "CFI Flash device mapped on IBM 405LP Arctic" + depends on MTD_CFI && ARCTIC2 + help + This enables access routines for the flash chips on the IBM 405LP + Arctic board. If you have one of these boards and would like to + use the flash chips on it, say 'Y'. + config MTD_WALNUT tristate "Flash device mapped on IBM 405GP Walnut" depends on MTD_JEDECPROBE && WALNUT diff --git a/trunk/drivers/mtd/maps/Makefile b/trunk/drivers/mtd/maps/Makefile index 3acbb5d01ca4..de036c5e6139 100644 --- a/trunk/drivers/mtd/maps/Makefile +++ b/trunk/drivers/mtd/maps/Makefile @@ -58,6 +58,8 @@ obj-$(CONFIG_MTD_NETtel) += nettel.o obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o obj-$(CONFIG_MTD_EBONY) += ebony.o obj-$(CONFIG_MTD_OCOTEA) += ocotea.o +obj-$(CONFIG_MTD_BEECH) += beech-mtd.o +obj-$(CONFIG_MTD_ARCTIC) += arctic-mtd.o obj-$(CONFIG_MTD_WALNUT) += walnut.o obj-$(CONFIG_MTD_H720X) += h720x-flash.o obj-$(CONFIG_MTD_SBC8240) += sbc8240.o diff --git a/trunk/drivers/mtd/maps/arctic-mtd.c b/trunk/drivers/mtd/maps/arctic-mtd.c new file mode 100644 index 000000000000..2cc902436275 --- /dev/null +++ b/trunk/drivers/mtd/maps/arctic-mtd.c @@ -0,0 +1,145 @@ +/* + * $Id: arctic-mtd.c,v 1.14 2005/11/07 11:14:26 gleixner Exp $ + * + * drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for + * IBM 405LP Arctic boards. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Copyright (C) 2002, International Business Machines Corporation + * All Rights Reserved. + * + * Bishop Brock + * IBM Research, Austin Center for Low-Power Computing + * bcbrock@us.ibm.com + * March 2002 + * + * modified for Arctic by, + * David Gibson + * IBM OzLabs, Canberra, Australia + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +/* + * 0 : 0xFE00 0000 - 0xFEFF FFFF : Filesystem 1 (16MiB) + * 1 : 0xFF00 0000 - 0xFF4F FFFF : kernel (5.12MiB) + * 2 : 0xFF50 0000 - 0xFFF5 FFFF : Filesystem 2 (10.624MiB) (if non-XIP) + * 3 : 0xFFF6 0000 - 0xFFFF FFFF : PIBS Firmware (640KiB) + */ + +#define FFS1_SIZE 0x01000000 /* 16MiB */ +#define KERNEL_SIZE 0x00500000 /* 5.12MiB */ +#define FFS2_SIZE 0x00a60000 /* 10.624MiB */ +#define FIRMWARE_SIZE 0x000a0000 /* 640KiB */ + + +#define NAME "Arctic Linux Flash" +#define PADDR SUBZERO_BOOTFLASH_PADDR +#define BUSWIDTH 2 +#define SIZE SUBZERO_BOOTFLASH_SIZE +#define PARTITIONS 4 + +/* Flash memories on these boards are memory resources, accessed big-endian. */ + +{ + /* do nothing for now */ +} + +static struct map_info arctic_mtd_map = { + .name = NAME, + .size = SIZE, + .bankwidth = BUSWIDTH, + .phys = PADDR, +}; + +static struct mtd_info *arctic_mtd; + +static struct mtd_partition arctic_partitions[PARTITIONS] = { + { .name = "Filesystem", + .size = FFS1_SIZE, + .offset = 0,}, + { .name = "Kernel", + .size = KERNEL_SIZE, + .offset = FFS1_SIZE,}, + { .name = "Filesystem", + .size = FFS2_SIZE, + .offset = FFS1_SIZE + KERNEL_SIZE,}, + { .name = "Firmware", + .size = FIRMWARE_SIZE, + .offset = SUBZERO_BOOTFLASH_SIZE - FIRMWARE_SIZE,}, +}; + +static int __init +init_arctic_mtd(void) +{ + int err; + + printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); + + arctic_mtd_map.virt = ioremap(PADDR, SIZE); + + if (!arctic_mtd_map.virt) { + printk("%s: failed to ioremap 0x%x\n", NAME, PADDR); + return -EIO; + } + simple_map_init(&arctic_mtd_map); + + printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8); + arctic_mtd = do_map_probe("cfi_probe", &arctic_mtd_map); + + if (!arctic_mtd) { + iounmap(arctic_mtd_map.virt); + return -ENXIO; + } + + arctic_mtd->owner = THIS_MODULE; + + err = add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS); + if (err) { + printk("%s: add_mtd_partitions failed\n", NAME); + iounmap(arctic_mtd_map.virt); + } + + return err; +} + +static void __exit +cleanup_arctic_mtd(void) +{ + if (arctic_mtd) { + del_mtd_partitions(arctic_mtd); + map_destroy(arctic_mtd); + iounmap((void *) arctic_mtd_map.virt); + } +} + +module_init(init_arctic_mtd); +module_exit(cleanup_arctic_mtd); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Gibson "); +MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Arctic boards"); diff --git a/trunk/drivers/mtd/maps/beech-mtd.c b/trunk/drivers/mtd/maps/beech-mtd.c new file mode 100644 index 000000000000..d76d5981b863 --- /dev/null +++ b/trunk/drivers/mtd/maps/beech-mtd.c @@ -0,0 +1,122 @@ +/* + * $Id: beech-mtd.c,v 1.11 2005/11/07 11:14:26 gleixner Exp $ + * + * drivers/mtd/maps/beech-mtd.c MTD mappings and partition tables for + * IBM 405LP Beech boards. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Copyright (C) 2002, International Business Machines Corporation + * All Rights Reserved. + * + * Bishop Brock + * IBM Research, Austin Center for Low-Power Computing + * bcbrock@us.ibm.com + * March 2002 + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#define NAME "Beech Linux Flash" +#define PADDR BEECH_BIGFLASH_PADDR +#define SIZE BEECH_BIGFLASH_SIZE +#define BUSWIDTH 1 + +/* Flash memories on these boards are memory resources, accessed big-endian. */ + + +static struct map_info beech_mtd_map = { + .name = NAME, + .size = SIZE, + .bankwidth = BUSWIDTH, + .phys = PADDR +}; + +static struct mtd_info *beech_mtd; + +static struct mtd_partition beech_partitions[2] = { + { + .name = "Linux Kernel", + .size = BEECH_KERNEL_SIZE, + .offset = BEECH_KERNEL_OFFSET + }, { + .name = "Free Area", + .size = BEECH_FREE_AREA_SIZE, + .offset = BEECH_FREE_AREA_OFFSET + } +}; + +static int __init +init_beech_mtd(void) +{ + int err; + + printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); + + beech_mtd_map.virt = ioremap(PADDR, SIZE); + + if (!beech_mtd_map.virt) { + printk("%s: failed to ioremap 0x%x\n", NAME, PADDR); + return -EIO; + } + + simple_map_init(&beech_mtd_map); + + printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8); + beech_mtd = do_map_probe("cfi_probe", &beech_mtd_map); + + if (!beech_mtd) { + iounmap(beech_mtd_map.virt); + return -ENXIO; + } + + beech_mtd->owner = THIS_MODULE; + + err = add_mtd_partitions(beech_mtd, beech_partitions, 2); + if (err) { + printk("%s: add_mtd_partitions failed\n", NAME); + iounmap(beech_mtd_map.virt); + } + + return err; +} + +static void __exit +cleanup_beech_mtd(void) +{ + if (beech_mtd) { + del_mtd_partitions(beech_mtd); + map_destroy(beech_mtd); + iounmap((void *) beech_mtd_map.virt); + } +} + +module_init(init_beech_mtd); +module_exit(cleanup_beech_mtd); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Bishop Brock "); +MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Beech boards"); diff --git a/trunk/drivers/mtd/maps/nettel.c b/trunk/drivers/mtd/maps/nettel.c index 7b96cd02f82b..9f53c655af3a 100644 --- a/trunk/drivers/mtd/maps/nettel.c +++ b/trunk/drivers/mtd/maps/nettel.c @@ -358,7 +358,7 @@ int __init nettel_init(void) /* Turn other PAR off so the first probe doesn't find it */ *intel1par = 0; - /* Probe for the size of the first Intel flash */ + /* Probe for the the size of the first Intel flash */ nettel_intel_map.size = maxsize; nettel_intel_map.phys = intel0addr; nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); diff --git a/trunk/drivers/mtd/maps/physmap_of.c b/trunk/drivers/mtd/maps/physmap_of.c index bbb42c35b69b..72107dc06d67 100644 --- a/trunk/drivers/mtd/maps/physmap_of.c +++ b/trunk/drivers/mtd/maps/physmap_of.c @@ -186,7 +186,7 @@ static int __devinit of_physmap_probe(struct of_device *dev, const struct of_dev else { if (strcmp(of_probe, "ROM")) dev_dbg(&dev->dev, "map_probe: don't know probe type " - "'%s', mapping as rom\n", of_probe); + "'%s', mapping as rom\n"); info->mtd = do_map_probe("mtd_rom", &info->map); } if (info->mtd == NULL) { diff --git a/trunk/drivers/mtd/mtdpart.c b/trunk/drivers/mtd/mtdpart.c index 9c6236852942..1af989023c66 100644 --- a/trunk/drivers/mtd/mtdpart.c +++ b/trunk/drivers/mtd/mtdpart.c @@ -347,6 +347,7 @@ int add_mtd_partitions(struct mtd_info *master, slave->mtd.subpage_sft = master->subpage_sft; slave->mtd.name = parts[i].name; + slave->mtd.bank_size = master->bank_size; slave->mtd.owner = master->owner; slave->mtd.read = part_read; diff --git a/trunk/drivers/mtd/nand/Kconfig b/trunk/drivers/mtd/nand/Kconfig index f1d60b6f048e..d05873b8c155 100644 --- a/trunk/drivers/mtd/nand/Kconfig +++ b/trunk/drivers/mtd/nand/Kconfig @@ -232,13 +232,11 @@ config MTD_NAND_BASLER_EXCITE will be named "excite_nandflash.ko". config MTD_NAND_CAFE - tristate "NAND support for OLPC CAFÉ chip" - depends on PCI - select REED_SOLOMON - select REED_SOLOMON_DEC16 - help - Use NAND flash attached to the CAFÉ chip designed for the $100 - laptop. + tristate "NAND support for OLPC CAFÉ chip" + depends on PCI + help + Use NAND flash attached to the CAFÉ chip designed for the $100 + laptop. config MTD_NAND_CS553X tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)" @@ -272,13 +270,4 @@ config MTD_NAND_NANDSIM The simulator may simulate various NAND flash chips for the MTD nand layer. -config MTD_NAND_PLATFORM - tristate "Support for generic platform NAND driver" - depends on MTD_NAND - help - This implements a generic NAND driver for on-SOC platform - devices. You will need to provide platform-specific functions - via platform_data. - - endif # MTD_NAND diff --git a/trunk/drivers/mtd/nand/Makefile b/trunk/drivers/mtd/nand/Makefile index edba1db14bfa..6872031a3fb2 100644 --- a/trunk/drivers/mtd/nand/Makefile +++ b/trunk/drivers/mtd/nand/Makefile @@ -26,6 +26,6 @@ obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o -obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o nand-objs := nand_base.o nand_bbt.o +cafe_nand-objs := cafe.o cafe_ecc.o diff --git a/trunk/drivers/mtd/nand/at91_nand.c b/trunk/drivers/mtd/nand/at91_nand.c index 512e999177f7..14b80cc90a7b 100644 --- a/trunk/drivers/mtd/nand/at91_nand.c +++ b/trunk/drivers/mtd/nand/at91_nand.c @@ -82,10 +82,6 @@ static void at91_nand_disable(struct at91_nand_host *host) at91_set_gpio_value(host->board->enable_pin, 1); } -#ifdef CONFIG_MTD_PARTITIONS -const char *part_probes[] = { "cmdlinepart", NULL }; -#endif - /* * Probe for the NAND device. */ @@ -155,12 +151,6 @@ static int __init at91_nand_probe(struct platform_device *pdev) #ifdef CONFIG_MTD_PARTITIONS if (host->board->partition_info) partitions = host->board->partition_info(mtd->size, &num_partitions); -#ifdef CONFIG_MTD_CMDLINE_PARTS - else { - mtd->name = "at91_nand"; - num_partitions = parse_mtd_partitions(mtd, part_probes, &partitions, 0); - } -#endif if ((!partitions) || (num_partitions == 0)) { printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n"); diff --git a/trunk/drivers/mtd/nand/cafe_nand.c b/trunk/drivers/mtd/nand/cafe.c similarity index 88% rename from trunk/drivers/mtd/nand/cafe_nand.c rename to trunk/drivers/mtd/nand/cafe.c index cff969d05d4a..c328a7514510 100644 --- a/trunk/drivers/mtd/nand/cafe_nand.c +++ b/trunk/drivers/mtd/nand/cafe.c @@ -11,7 +11,6 @@ #undef DEBUG #include #include -#include #include #include #include @@ -47,14 +46,13 @@ #define CAFE_GLOBAL_IRQ_MASK 0x300c #define CAFE_NAND_RESET 0x3034 -/* Missing from the datasheet: bit 19 of CTRL1 sets CE0 vs. CE1 */ -#define CTRL1_CHIPSELECT (1<<19) +int cafe_correct_ecc(unsigned char *buf, + unsigned short *chk_syndrome_list); struct cafe_priv { struct nand_chip nand; struct pci_dev *pdev; void __iomem *mmio; - struct rs_control *rs; uint32_t ctl1; uint32_t ctl2; int datalen; @@ -197,8 +195,8 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, cafe->data_pos = cafe->datalen = 0; - /* Set command valid bit, mask in the chip select bit */ - ctl1 = 0x80000000 | command | (cafe->ctl1 & CTRL1_CHIPSELECT); + /* Set command valid bit */ + ctl1 = 0x80000000 | command; /* Set RD or WR bits as appropriate */ if (command == NAND_CMD_READID || command == NAND_CMD_STATUS) { @@ -311,16 +309,8 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, static void cafe_select_chip(struct mtd_info *mtd, int chipnr) { - struct cafe_priv *cafe = mtd->priv; - - cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr); - - /* Mask the appropriate bit into the stored value of ctl1 - which will be used by cafe_nand_cmdfunc() */ - if (chipnr) - cafe->ctl1 |= CTRL1_CHIPSELECT; - else - cafe->ctl1 &= ~CTRL1_CHIPSELECT; + //struct cafe_priv *cafe = mtd->priv; + // cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr); } static int cafe_nand_interrupt(int irq, void *id) @@ -384,66 +374,28 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) { - unsigned short syn[8], pat[4]; - int pos[4]; - u8 *oob = chip->oob_poi; - int i, n; + unsigned short syn[8]; + int i; for (i=0; i<8; i+=2) { uint32_t tmp = cafe_readl(cafe, NAND_ECC_SYN01 + (i*2)); - syn[i] = cafe->rs->index_of[tmp & 0xfff]; - syn[i+1] = cafe->rs->index_of[(tmp >> 16) & 0xfff]; - } - - n = decode_rs16(cafe->rs, NULL, NULL, 1367, syn, 0, pos, 0, - pat); - - for (i = 0; i < n; i++) { - int p = pos[i]; - - /* The 12-bit symbols are mapped to bytes here */ - - if (p > 1374) { - /* out of range */ - n = -1374; - } else if (p == 0) { - /* high four bits do not correspond to data */ - if (pat[i] > 0xff) - n = -2048; - else - buf[0] ^= pat[i]; - } else if (p == 1365) { - buf[2047] ^= pat[i] >> 4; - oob[0] ^= pat[i] << 4; - } else if (p > 1365) { - if ((p & 1) == 1) { - oob[3*p/2 - 2048] ^= pat[i] >> 4; - oob[3*p/2 - 2047] ^= pat[i] << 4; - } else { - oob[3*p/2 - 2049] ^= pat[i] >> 8; - oob[3*p/2 - 2048] ^= pat[i]; - } - } else if ((p & 1) == 1) { - buf[3*p/2] ^= pat[i] >> 4; - buf[3*p/2 + 1] ^= pat[i] << 4; - } else { - buf[3*p/2 - 1] ^= pat[i] >> 8; - buf[3*p/2] ^= pat[i]; - } + syn[i] = tmp & 0xfff; + syn[i+1] = (tmp >> 16) & 0xfff; } - if (n < 0) { + if ((i = cafe_correct_ecc(buf, syn)) < 0) { dev_dbg(&cafe->pdev->dev, "Failed to correct ECC at %08x\n", cafe_readl(cafe, NAND_ADDR2) * 2048); - for (i = 0; i < 0x5c; i += 4) + for (i=0; i< 0x5c; i+=4) printk("Register %x: %08x\n", i, readl(cafe->mmio + i)); mtd->ecc_stats.failed++; } else { - dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", n); - mtd->ecc_stats.corrected += n; + dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", i); + mtd->ecc_stats.corrected += i; } } + return 0; } @@ -464,7 +416,7 @@ static uint8_t cafe_mirror_pattern_512[] = { 0xBC }; static struct nand_bbt_descr cafe_bbt_main_descr_2048 = { .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE - | NAND_BBT_2BIT | NAND_BBT_VERSION, + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, .offs = 14, .len = 4, .veroffs = 18, @@ -474,7 +426,7 @@ static struct nand_bbt_descr cafe_bbt_main_descr_2048 = { static struct nand_bbt_descr cafe_bbt_mirror_descr_2048 = { .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE - | NAND_BBT_2BIT | NAND_BBT_VERSION, + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, .offs = 14, .len = 4, .veroffs = 18, @@ -490,7 +442,7 @@ static struct nand_ecclayout cafe_oobinfo_512 = { static struct nand_bbt_descr cafe_bbt_main_descr_512 = { .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE - | NAND_BBT_2BIT | NAND_BBT_VERSION, + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, .offs = 14, .len = 1, .veroffs = 15, @@ -500,7 +452,7 @@ static struct nand_bbt_descr cafe_bbt_main_descr_512 = { static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = { .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE - | NAND_BBT_2BIT | NAND_BBT_VERSION, + | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, .offs = 14, .len = 1, .veroffs = 15, @@ -573,48 +525,6 @@ static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) return 0; } -/* F_2[X]/(X**6+X+1) */ -static unsigned short __devinit gf64_mul(u8 a, u8 b) -{ - u8 c; - unsigned int i; - - c = 0; - for (i = 0; i < 6; i++) { - if (a & 1) - c ^= b; - a >>= 1; - b <<= 1; - if ((b & 0x40) != 0) - b ^= 0x43; - } - - return c; -} - -/* F_64[X]/(X**2+X+A**-1) with A the generator of F_64[X] */ -static u16 __devinit gf4096_mul(u16 a, u16 b) -{ - u8 ah, al, bh, bl, ch, cl; - - ah = a >> 6; - al = a & 0x3f; - bh = b >> 6; - bl = b & 0x3f; - - ch = gf64_mul(ah ^ al, bh ^ bl) ^ gf64_mul(al, bl); - cl = gf64_mul(gf64_mul(ah, bh), 0x21) ^ gf64_mul(al, bl); - - return (ch << 6) ^ cl; -} - -static int __devinit cafe_mul(int x) -{ - if (x == 0) - return 1; - return gf4096_mul(x, 0xe01); -} - static int __devinit cafe_nand_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -654,12 +564,6 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, } cafe->nand.buffers = (void *)cafe->dmabuf + 2112; - cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8); - if (!cafe->rs) { - err = -ENOMEM; - goto out_ior; - } - cafe->nand.cmdfunc = cafe_nand_cmdfunc; cafe->nand.dev_ready = cafe_device_ready; cafe->nand.read_byte = cafe_read_byte; @@ -742,7 +646,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK)); /* Scan to find existence of the device */ - if (nand_scan_ident(mtd, 2)) { + if (nand_scan_ident(mtd, 1)) { err = -ENXIO; goto out_irq; } @@ -809,7 +713,6 @@ static void __devexit cafe_nand_remove(struct pci_dev *pdev) cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); free_irq(pdev->irq, mtd); nand_release(mtd); - free_rs(cafe->rs); pci_iounmap(pdev, cafe->mmio); dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); kfree(mtd); diff --git a/trunk/drivers/mtd/nand/cafe_ecc.c b/trunk/drivers/mtd/nand/cafe_ecc.c new file mode 100644 index 000000000000..ea5c8491d2c5 --- /dev/null +++ b/trunk/drivers/mtd/nand/cafe_ecc.c @@ -0,0 +1,1381 @@ +/* Error correction for CAFÉ NAND controller + * + * © 2006 Marvell, Inc. + * Author: Tom Chiou + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +static unsigned short gf4096_mul(unsigned short, unsigned short); +static unsigned short gf64_mul(unsigned short, unsigned short); +static unsigned short gf4096_inv(unsigned short); +static unsigned short err_pos(unsigned short); +static void find_4bit_err_coefs(unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short, unsigned short *); +static void zero_4x5_col3(unsigned short[4][5]); +static void zero_4x5_col2(unsigned short[4][5]); +static void zero_4x5_col1(unsigned short[4][5]); +static void swap_4x5_rows(unsigned short[4][5], int, int, int); +static void swap_2x3_rows(unsigned short m[2][3]); +static void solve_4x5(unsigned short m[4][5], unsigned short *, int *); +static void sort_coefs(int *, unsigned short *, int); +static void find_4bit_err_pats(unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short, unsigned short *); +static void find_3bit_err_coefs(unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short, unsigned short, + unsigned short *); +static void zero_3x4_col2(unsigned short[3][4]); +static void zero_3x4_col1(unsigned short[3][4]); +static void swap_3x4_rows(unsigned short[3][4], int, int, int); +static void solve_3x4(unsigned short[3][4], unsigned short *, int *); +static void find_3bit_err_pats(unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short, unsigned short, + unsigned short *); + +static void find_2bit_err_pats(unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short *); +static void find_2x2_soln(unsigned short, unsigned short, unsigned short, + unsigned short, unsigned short, unsigned short, + unsigned short *); +static void solve_2x3(unsigned short[2][3], unsigned short *); +static int chk_no_err_only(unsigned short *, unsigned short *); +static int chk_1_err_only(unsigned short *, unsigned short *); +static int chk_2_err_only(unsigned short *, unsigned short *); +static int chk_3_err_only(unsigned short *, unsigned short *); +static int chk_4_err_only(unsigned short *, unsigned short *); + +static unsigned short gf64_mul(unsigned short a, unsigned short b) +{ + unsigned short tmp1, tmp2, tmp3, tmp4, tmp5; + unsigned short c_bit0, c_bit1, c_bit2, c_bit3, c_bit4, c_bit5, c; + + tmp1 = ((a) ^ (a >> 5)); + tmp2 = ((a >> 4) ^ (a >> 5)); + tmp3 = ((a >> 3) ^ (a >> 4)); + tmp4 = ((a >> 2) ^ (a >> 3)); + tmp5 = ((a >> 1) ^ (a >> 2)); + + c_bit0 = ((a & b) ^ ((a >> 5) & (b >> 1)) ^ ((a >> 4) & (b >> 2)) ^ + ((a >> 3) & (b >> 3)) ^ ((a >> 2) & (b >> 4)) ^ ((a >> 1) & (b >> 5))) & 0x1; + + c_bit1 = (((a >> 1) & b) ^ (tmp1 & (b >> 1)) ^ (tmp2 & (b >> 2)) ^ + (tmp3 & (b >> 3)) ^ (tmp4 & (b >> 4)) ^ (tmp5 & (b >> 5))) & 0x1; + + c_bit2 = (((a >> 2) & b) ^ ((a >> 1) & (b >> 1)) ^ (tmp1 & (b >> 2)) ^ + (tmp2 & (b >> 3)) ^ (tmp3 & (b >> 4)) ^ (tmp4 & (b >> 5))) & 0x1; + + c_bit3 = (((a >> 3) & b) ^ ((a >> 2) & (b >> 1)) ^ ((a >> 1) & (b >> 2)) ^ + (tmp1 & (b >> 3)) ^ (tmp2 & (b >> 4)) ^ (tmp3 & (b >> 5))) & 0x1; + + c_bit4 = (((a >> 4) & b) ^ ((a >> 3) & (b >> 1)) ^ ((a >> 2) & (b >> 2)) ^ + ((a >> 1) & (b >> 3)) ^ (tmp1 & (b >> 4)) ^ (tmp2 & (b >> 5))) & 0x1; + + c_bit5 = (((a >> 5) & b) ^ ((a >> 4) & (b >> 1)) ^ ((a >> 3) & (b >> 2)) ^ + ((a >> 2) & (b >> 3)) ^ ((a >> 1) & (b >> 4)) ^ (tmp1 & (b >> 5))) & 0x1; + + c = c_bit0 | (c_bit1 << 1) | (c_bit2 << 2) | (c_bit3 << 3) | (c_bit4 << 4) | (c_bit5 << 5); + + return c; +} + +static unsigned short gf4096_mul(unsigned short a, unsigned short b) +{ + unsigned short ah, al, bh, bl, alxah, blxbh, ablh, albl, ahbh, ahbhB, c; + + ah = (a >> 6) & 0x3f; + al = a & 0x3f; + bh = (b >> 6) & 0x3f; + bl = b & 0x3f; + alxah = al ^ ah; + blxbh = bl ^ bh; + + ablh = gf64_mul(alxah, blxbh); + albl = gf64_mul(al, bl); + ahbh = gf64_mul(ah, bh); + + ahbhB = ((ahbh & 0x1) << 5) | + ((ahbh & 0x20) >> 1) | + ((ahbh & 0x10) >> 1) | ((ahbh & 0x8) >> 1) | ((ahbh & 0x4) >> 1) | (((ahbh >> 1) ^ ahbh) & 0x1); + + c = ((ablh ^ albl) << 6) | (ahbhB ^ albl); + return c; +} + +static void find_2bit_err_pats(unsigned short s0, unsigned short s1, unsigned short r0, unsigned short r1, unsigned short *pats) +{ + find_2x2_soln(0x1, 0x1, r0, r1, s0, s1, pats); +} + +static void find_3bit_err_coefs(unsigned short s0, unsigned short s1, + unsigned short s2, unsigned short s3, unsigned short s4, unsigned short s5, unsigned short *coefs) +{ + unsigned short m[3][4]; + int row_order[3]; + + row_order[0] = 0; + row_order[1] = 1; + row_order[2] = 2; + m[0][0] = s2; + m[0][1] = s1; + m[0][2] = s0; + m[0][3] = s3; + m[1][0] = s3; + m[1][1] = s2; + m[1][2] = s1; + m[1][3] = s4; + m[2][0] = s4; + m[2][1] = s3; + m[2][2] = s2; + m[2][3] = s5; + + if (m[0][2] != 0x0) { + zero_3x4_col2(m); + } else if (m[1][2] != 0x0) { + swap_3x4_rows(m, 0, 1, 4); + zero_3x4_col2(m); + } else if (m[2][2] != 0x0) { + swap_3x4_rows(m, 0, 2, 4); + zero_3x4_col2(m); + } else { + printk(KERN_ERR "Error: find_3bit_err_coefs, s0,s1,s2 all zeros!\n"); + } + + if (m[1][1] != 0x0) { + zero_3x4_col1(m); + } else if (m[2][1] != 0x0) { + swap_3x4_rows(m, 1, 2, 4); + zero_3x4_col1(m); + } else { + printk(KERN_ERR "Error: find_3bit_err_coefs, cannot resolve col 1!\n"); + } + + /* solve coefs */ + solve_3x4(m, coefs, row_order); +} + +static void zero_3x4_col2(unsigned short m[3][4]) +{ + unsigned short minv1, minv2; + + minv1 = gf4096_mul(m[1][2], gf4096_inv(m[0][2])); + minv2 = gf4096_mul(m[2][2], gf4096_inv(m[0][2])); + m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1); + m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1); + m[1][3] = m[1][3] ^ gf4096_mul(m[0][3], minv1); + m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2); + m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2); + m[2][3] = m[2][3] ^ gf4096_mul(m[0][3], minv2); +} + +static void zero_3x4_col1(unsigned short m[3][4]) +{ + unsigned short minv; + minv = gf4096_mul(m[2][1], gf4096_inv(m[1][1])); + m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv); + m[2][3] = m[2][3] ^ gf4096_mul(m[1][3], minv); +} + +static void swap_3x4_rows(unsigned short m[3][4], int i, int j, int col_width) +{ + unsigned short tmp0; + int cnt; + for (cnt = 0; cnt < col_width; cnt++) { + tmp0 = m[i][cnt]; + m[i][cnt] = m[j][cnt]; + m[j][cnt] = tmp0; + } +} + +static void solve_3x4(unsigned short m[3][4], unsigned short *coefs, int *row_order) +{ + unsigned short tmp[3]; + tmp[0] = gf4096_mul(m[2][3], gf4096_inv(m[2][0])); + tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ m[1][3]), gf4096_inv(m[1][1])); + tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^ gf4096_mul(tmp[1], m[0][1]) ^ m[0][3]), gf4096_inv(m[0][2])); + sort_coefs(row_order, tmp, 3); + coefs[0] = tmp[0]; + coefs[1] = tmp[1]; + coefs[2] = tmp[2]; +} + +static void find_3bit_err_pats(unsigned short s0, unsigned short s1, + unsigned short s2, unsigned short r0, + unsigned short r1, unsigned short r2, + unsigned short *pats) +{ + find_2x2_soln(r0 ^ r2, r1 ^ r2, + gf4096_mul(r0, r0 ^ r2), gf4096_mul(r1, r1 ^ r2), + gf4096_mul(s0, r2) ^ s1, gf4096_mul(s1, r2) ^ s2, pats); + pats[2] = s0 ^ pats[0] ^ pats[1]; +} + +static void find_4bit_err_coefs(unsigned short s0, unsigned short s1, + unsigned short s2, unsigned short s3, + unsigned short s4, unsigned short s5, + unsigned short s6, unsigned short s7, + unsigned short *coefs) +{ + unsigned short m[4][5]; + int row_order[4]; + + row_order[0] = 0; + row_order[1] = 1; + row_order[2] = 2; + row_order[3] = 3; + + m[0][0] = s3; + m[0][1] = s2; + m[0][2] = s1; + m[0][3] = s0; + m[0][4] = s4; + m[1][0] = s4; + m[1][1] = s3; + m[1][2] = s2; + m[1][3] = s1; + m[1][4] = s5; + m[2][0] = s5; + m[2][1] = s4; + m[2][2] = s3; + m[2][3] = s2; + m[2][4] = s6; + m[3][0] = s6; + m[3][1] = s5; + m[3][2] = s4; + m[3][3] = s3; + m[3][4] = s7; + + if (m[0][3] != 0x0) { + zero_4x5_col3(m); + } else if (m[1][3] != 0x0) { + swap_4x5_rows(m, 0, 1, 5); + zero_4x5_col3(m); + } else if (m[2][3] != 0x0) { + swap_4x5_rows(m, 0, 2, 5); + zero_4x5_col3(m); + } else if (m[3][3] != 0x0) { + swap_4x5_rows(m, 0, 3, 5); + zero_4x5_col3(m); + } else { + printk(KERN_ERR "Error: find_4bit_err_coefs, s0,s1,s2,s3 all zeros!\n"); + } + + if (m[1][2] != 0x0) { + zero_4x5_col2(m); + } else if (m[2][2] != 0x0) { + swap_4x5_rows(m, 1, 2, 5); + zero_4x5_col2(m); + } else if (m[3][2] != 0x0) { + swap_4x5_rows(m, 1, 3, 5); + zero_4x5_col2(m); + } else { + printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 2!\n"); + } + + if (m[2][1] != 0x0) { + zero_4x5_col1(m); + } else if (m[3][1] != 0x0) { + swap_4x5_rows(m, 2, 3, 5); + zero_4x5_col1(m); + } else { + printk(KERN_ERR "Error: find_4bit_err_coefs, cannot resolve col 1!\n"); + } + + solve_4x5(m, coefs, row_order); +} + +static void zero_4x5_col3(unsigned short m[4][5]) +{ + unsigned short minv1, minv2, minv3; + + minv1 = gf4096_mul(m[1][3], gf4096_inv(m[0][3])); + minv2 = gf4096_mul(m[2][3], gf4096_inv(m[0][3])); + minv3 = gf4096_mul(m[3][3], gf4096_inv(m[0][3])); + + m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv1); + m[1][1] = m[1][1] ^ gf4096_mul(m[0][1], minv1); + m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv1); + m[1][4] = m[1][4] ^ gf4096_mul(m[0][4], minv1); + m[2][0] = m[2][0] ^ gf4096_mul(m[0][0], minv2); + m[2][1] = m[2][1] ^ gf4096_mul(m[0][1], minv2); + m[2][2] = m[2][2] ^ gf4096_mul(m[0][2], minv2); + m[2][4] = m[2][4] ^ gf4096_mul(m[0][4], minv2); + m[3][0] = m[3][0] ^ gf4096_mul(m[0][0], minv3); + m[3][1] = m[3][1] ^ gf4096_mul(m[0][1], minv3); + m[3][2] = m[3][2] ^ gf4096_mul(m[0][2], minv3); + m[3][4] = m[3][4] ^ gf4096_mul(m[0][4], minv3); +} + +static void zero_4x5_col2(unsigned short m[4][5]) +{ + unsigned short minv2, minv3; + + minv2 = gf4096_mul(m[2][2], gf4096_inv(m[1][2])); + minv3 = gf4096_mul(m[3][2], gf4096_inv(m[1][2])); + + m[2][0] = m[2][0] ^ gf4096_mul(m[1][0], minv2); + m[2][1] = m[2][1] ^ gf4096_mul(m[1][1], minv2); + m[2][4] = m[2][4] ^ gf4096_mul(m[1][4], minv2); + m[3][0] = m[3][0] ^ gf4096_mul(m[1][0], minv3); + m[3][1] = m[3][1] ^ gf4096_mul(m[1][1], minv3); + m[3][4] = m[3][4] ^ gf4096_mul(m[1][4], minv3); +} + +static void zero_4x5_col1(unsigned short m[4][5]) +{ + unsigned short minv; + + minv = gf4096_mul(m[3][1], gf4096_inv(m[2][1])); + + m[3][0] = m[3][0] ^ gf4096_mul(m[2][0], minv); + m[3][4] = m[3][4] ^ gf4096_mul(m[2][4], minv); +} + +static void swap_4x5_rows(unsigned short m[4][5], int i, int j, int col_width) +{ + unsigned short tmp0; + int cnt; + + for (cnt = 0; cnt < col_width; cnt++) { + tmp0 = m[i][cnt]; + m[i][cnt] = m[j][cnt]; + m[j][cnt] = tmp0; + } +} + +static void solve_4x5(unsigned short m[4][5], unsigned short *coefs, int *row_order) +{ + unsigned short tmp[4]; + + tmp[0] = gf4096_mul(m[3][4], gf4096_inv(m[3][0])); + tmp[1] = gf4096_mul((gf4096_mul(tmp[0], m[2][0]) ^ m[2][4]), gf4096_inv(m[2][1])); + tmp[2] = gf4096_mul((gf4096_mul(tmp[0], m[1][0]) ^ gf4096_mul(tmp[1], m[1][1]) ^ m[1][4]), gf4096_inv(m[1][2])); + tmp[3] = gf4096_mul((gf4096_mul(tmp[0], m[0][0]) ^ + gf4096_mul(tmp[1], m[0][1]) ^ gf4096_mul(tmp[2], m[0][2]) ^ m[0][4]), gf4096_inv(m[0][3])); + sort_coefs(row_order, tmp, 4); + coefs[0] = tmp[0]; + coefs[1] = tmp[1]; + coefs[2] = tmp[2]; + coefs[3] = tmp[3]; +} + +static void sort_coefs(int *order, unsigned short *soln, int len) +{ + int cnt, start_cnt, least_ord, least_cnt; + unsigned short tmp0; + for (start_cnt = 0; start_cnt < len; start_cnt++) { + for (cnt = start_cnt; cnt < len; cnt++) { + if (cnt == start_cnt) { + least_ord = order[cnt]; + least_cnt = start_cnt; + } else { + if (least_ord > order[cnt]) { + least_ord = order[cnt]; + least_cnt = cnt; + } + } + } + if (least_cnt != start_cnt) { + tmp0 = order[least_cnt]; + order[least_cnt] = order[start_cnt]; + order[start_cnt] = tmp0; + tmp0 = soln[least_cnt]; + soln[least_cnt] = soln[start_cnt]; + soln[start_cnt] = tmp0; + } + } +} + +static void find_4bit_err_pats(unsigned short s0, unsigned short s1, + unsigned short s2, unsigned short s3, + unsigned short z1, unsigned short z2, + unsigned short z3, unsigned short z4, + unsigned short *pats) +{ + unsigned short z4_z1, z3z4_z3z3, z4_z2, s0z4_s1, z1z4_z1z1, + z4_z3, z2z4_z2z2, s1z4_s2, z3z3z4_z3z3z3, z1z1z4_z1z1z1, z2z2z4_z2z2z2, s2z4_s3; + unsigned short tmp0, tmp1, tmp2, tmp3; + + z4_z1 = z4 ^ z1; + z3z4_z3z3 = gf4096_mul(z3, z4) ^ gf4096_mul(z3, z3); + z4_z2 = z4 ^ z2; + s0z4_s1 = gf4096_mul(s0, z4) ^ s1; + z1z4_z1z1 = gf4096_mul(z1, z4) ^ gf4096_mul(z1, z1); + z4_z3 = z4 ^ z3; + z2z4_z2z2 = gf4096_mul(z2, z4) ^ gf4096_mul(z2, z2); + s1z4_s2 = gf4096_mul(s1, z4) ^ s2; + z3z3z4_z3z3z3 = gf4096_mul(gf4096_mul(z3, z3), z4) ^ gf4096_mul(gf4096_mul(z3, z3), z3); + z1z1z4_z1z1z1 = gf4096_mul(gf4096_mul(z1, z1), z4) ^ gf4096_mul(gf4096_mul(z1, z1), z1); + z2z2z4_z2z2z2 = gf4096_mul(gf4096_mul(z2, z2), z4) ^ gf4096_mul(gf4096_mul(z2, z2), z2); + s2z4_s3 = gf4096_mul(s2, z4) ^ s3; + + //find err pat 0,1 + find_2x2_soln(gf4096_mul(z4_z1, z3z4_z3z3) ^ + gf4096_mul(z1z4_z1z1, z4_z3), gf4096_mul(z4_z2, + z3z4_z3z3) ^ + gf4096_mul(z2z4_z2z2, z4_z3), gf4096_mul(z1z4_z1z1, + z3z3z4_z3z3z3) ^ + gf4096_mul(z1z1z4_z1z1z1, z3z4_z3z3), + gf4096_mul(z2z4_z2z2, + z3z3z4_z3z3z3) ^ gf4096_mul(z2z2z4_z2z2z2, + z3z4_z3z3), + gf4096_mul(s0z4_s1, z3z4_z3z3) ^ gf4096_mul(s1z4_s2, + z4_z3), + gf4096_mul(s1z4_s2, z3z3z4_z3z3z3) ^ gf4096_mul(s2z4_s3, z3z4_z3z3), pats); + tmp0 = pats[0]; + tmp1 = pats[1]; + tmp2 = pats[0] ^ pats[1] ^ s0; + tmp3 = gf4096_mul(pats[0], z1) ^ gf4096_mul(pats[1], z2) ^ s1; + + //find err pat 2,3 + find_2x2_soln(0x1, 0x1, z3, z4, tmp2, tmp3, pats); + pats[2] = pats[0]; + pats[3] = pats[1]; + pats[0] = tmp0; + pats[1] = tmp1; +} + +static void find_2x2_soln(unsigned short c00, unsigned short c01, + unsigned short c10, unsigned short c11, + unsigned short lval0, unsigned short lval1, + unsigned short *soln) +{ + unsigned short m[2][3]; + m[0][0] = c00; + m[0][1] = c01; + m[0][2] = lval0; + m[1][0] = c10; + m[1][1] = c11; + m[1][2] = lval1; + + if (m[0][1] != 0x0) { + /* */ + } else if (m[1][1] != 0x0) { + swap_2x3_rows(m); + } else { + printk(KERN_ERR "Warning: find_2bit_err_coefs, s0,s1 all zeros!\n"); + } + + solve_2x3(m, soln); +} + +static void swap_2x3_rows(unsigned short m[2][3]) +{ + unsigned short tmp0; + int cnt; + + for (cnt = 0; cnt < 3; cnt++) { + tmp0 = m[0][cnt]; + m[0][cnt] = m[1][cnt]; + m[1][cnt] = tmp0; + } +} + +static void solve_2x3(unsigned short m[2][3], unsigned short *coefs) +{ + unsigned short minv; + + minv = gf4096_mul(m[1][1], gf4096_inv(m[0][1])); + m[1][0] = m[1][0] ^ gf4096_mul(m[0][0], minv); + m[1][2] = m[1][2] ^ gf4096_mul(m[0][2], minv); + coefs[0] = gf4096_mul(m[1][2], gf4096_inv(m[1][0])); + coefs[1] = gf4096_mul((gf4096_mul(coefs[0], m[0][0]) ^ m[0][2]), gf4096_inv(m[0][1])); +} + +static unsigned char gf64_inv[64] = { + 0, 1, 33, 62, 49, 43, 31, 44, 57, 37, 52, 28, 46, 40, 22, 25, + 61, 54, 51, 39, 26, 35, 14, 24, 23, 15, 20, 34, 11, 53, 45, 6, + 63, 2, 27, 21, 56, 9, 50, 19, 13, 47, 48, 5, 7, 30, 12, 41, + 42, 4, 38, 18, 10, 29, 17, 60, 36, 8, 59, 58, 55, 16, 3, 32 +}; + +static unsigned short gf4096_inv(unsigned short din) +{ + unsigned short alahxal, ah2B, deno, inv, bl, bh; + unsigned short ah, al, ahxal; + unsigned short dout; + + ah = (din >> 6) & 0x3f; + al = din & 0x3f; + ahxal = ah ^ al; + ah2B = (((ah ^ (ah >> 3)) & 0x1) << 5) | + ((ah >> 1) & 0x10) | + ((((ah >> 5) ^ (ah >> 2)) & 0x1) << 3) | + ((ah >> 2) & 0x4) | ((((ah >> 4) ^ (ah >> 1)) & 0x1) << 1) | (ah & 0x1); + alahxal = gf64_mul(ahxal, al); + deno = alahxal ^ ah2B; + inv = gf64_inv[deno]; + bl = gf64_mul(inv, ahxal); + bh = gf64_mul(inv, ah); + dout = ((bh & 0x3f) << 6) | (bl & 0x3f); + return (((bh & 0x3f) << 6) | (bl & 0x3f)); +} + +static unsigned short err_pos_lut[4096] = { + 0xfff, 0x000, 0x451, 0xfff, 0xfff, 0x3cf, 0xfff, 0x041, + 0xfff, 0xfff, 0xfff, 0xfff, 0x28a, 0xfff, 0x492, 0xfff, + 0x145, 0xfff, 0xfff, 0x514, 0xfff, 0x082, 0xfff, 0xfff, + 0xfff, 0x249, 0x38e, 0x410, 0xfff, 0x104, 0x208, 0x1c7, + 0xfff, 0xfff, 0xfff, 0xfff, 0x2cb, 0xfff, 0xfff, 0xfff, + 0x0c3, 0x34d, 0x4d3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x186, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x30c, 0x555, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x166, 0xfff, 0xfff, 0xfff, 0xfff, + 0x385, 0x14e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e1, + 0xfff, 0xfff, 0xfff, 0xfff, 0x538, 0xfff, 0x16d, 0xfff, + 0xfff, 0xfff, 0x45b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x29c, 0x2cc, 0x30b, 0x2b3, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0b3, 0xfff, 0x2f7, + 0xfff, 0x32b, 0xfff, 0xfff, 0xfff, 0xfff, 0x0a7, 0xfff, + 0xfff, 0x2da, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x07e, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x11c, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x22f, 0xfff, 0x1f4, 0xfff, 0xfff, + 0x2b0, 0x504, 0xfff, 0x114, 0xfff, 0xfff, 0xfff, 0x21d, + 0xfff, 0xfff, 0xfff, 0xfff, 0x00d, 0x3c4, 0x340, 0x10f, + 0xfff, 0xfff, 0x266, 0x02e, 0xfff, 0xfff, 0xfff, 0x4f8, + 0x337, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x07b, 0x168, 0xfff, 0xfff, 0x0fe, + 0xfff, 0xfff, 0x51a, 0xfff, 0x458, 0xfff, 0x36d, 0xfff, + 0xfff, 0xfff, 0xfff, 0x073, 0x37d, 0x415, 0x550, 0xfff, + 0xfff, 0xfff, 0x23b, 0x4b4, 0xfff, 0xfff, 0xfff, 0x1a1, + 0xfff, 0xfff, 0x3aa, 0xfff, 0x117, 0x04d, 0x341, 0xfff, + 0xfff, 0xfff, 0xfff, 0x518, 0x03e, 0x0f2, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x363, 0xfff, 0x0b9, 0xfff, 0xfff, + 0x241, 0xfff, 0xfff, 0x049, 0xfff, 0xfff, 0xfff, 0xfff, + 0x15f, 0x52d, 0xfff, 0xfff, 0xfff, 0x29e, 0xfff, 0xfff, + 0xfff, 0xfff, 0x4cf, 0x0fc, 0xfff, 0x36f, 0x3d3, 0xfff, + 0x228, 0xfff, 0xfff, 0x45e, 0xfff, 0xfff, 0xfff, 0xfff, + 0x238, 0xfff, 0xfff, 0xfff, 0xfff, 0x47f, 0xfff, 0xfff, + 0x43a, 0x265, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e8, + 0xfff, 0xfff, 0x01a, 0xfff, 0xfff, 0xfff, 0xfff, 0x21e, + 0x1fc, 0x40b, 0xfff, 0xfff, 0xfff, 0x2d0, 0x159, 0xfff, + 0xfff, 0x313, 0xfff, 0xfff, 0x05c, 0x4cc, 0xfff, 0xfff, + 0x0f6, 0x3d5, 0xfff, 0xfff, 0xfff, 0x54f, 0xfff, 0xfff, + 0xfff, 0x172, 0x1e4, 0x07c, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x53c, 0x1ad, 0x535, + 0x19b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x092, 0xfff, 0x2be, 0xfff, 0xfff, 0x482, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0e6, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x476, 0xfff, 0x51d, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x342, 0x2b5, 0x22e, 0x09a, 0xfff, 0x08d, + 0x44f, 0x3ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d1, 0xfff, + 0xfff, 0x543, 0xfff, 0x48f, 0xfff, 0x3d2, 0xfff, 0x0d5, + 0x113, 0x0ec, 0x427, 0xfff, 0xfff, 0xfff, 0x4c4, 0xfff, + 0xfff, 0x50a, 0xfff, 0x144, 0xfff, 0x105, 0x39f, 0x294, + 0x164, 0xfff, 0x31a, 0xfff, 0xfff, 0x49a, 0xfff, 0x130, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x1be, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x49e, 0x371, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x0e8, 0x49c, 0x0f4, 0xfff, + 0x338, 0x1a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x36c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x1ae, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x31b, 0xfff, 0xfff, 0x2dd, 0x522, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f4, + 0x3c6, 0x30d, 0xfff, 0xfff, 0xfff, 0xfff, 0x34c, 0x18f, + 0x30a, 0xfff, 0x01f, 0x079, 0xfff, 0xfff, 0x54d, 0x46b, + 0x28c, 0x37f, 0xfff, 0xfff, 0xfff, 0xfff, 0x355, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x14f, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x359, 0x3fe, 0x3c5, 0xfff, 0xfff, + 0xfff, 0xfff, 0x423, 0xfff, 0xfff, 0x34a, 0x22c, 0xfff, + 0x25a, 0xfff, 0xfff, 0x4ad, 0xfff, 0x28d, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x547, 0xfff, 0xfff, 0xfff, 0xfff, + 0x2e2, 0xfff, 0xfff, 0x1d5, 0xfff, 0x2a8, 0xfff, 0xfff, + 0x03f, 0xfff, 0xfff, 0xfff, 0xfff, 0x3eb, 0x0fa, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x55b, 0xfff, + 0x08e, 0xfff, 0x3ae, 0xfff, 0x3a4, 0xfff, 0x282, 0x158, + 0xfff, 0x382, 0xfff, 0xfff, 0x499, 0xfff, 0xfff, 0x08a, + 0xfff, 0xfff, 0xfff, 0x456, 0x3be, 0xfff, 0x1e2, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x559, 0xfff, 0x1a0, 0xfff, + 0xfff, 0x0b4, 0xfff, 0xfff, 0xfff, 0x2df, 0xfff, 0xfff, + 0xfff, 0x07f, 0x4f5, 0xfff, 0xfff, 0x27c, 0x133, 0x017, + 0xfff, 0x3fd, 0xfff, 0xfff, 0xfff, 0x44d, 0x4cd, 0x17a, + 0x0d7, 0x537, 0xfff, 0xfff, 0x353, 0xfff, 0xfff, 0x351, + 0x366, 0xfff, 0x44a, 0xfff, 0x1a6, 0xfff, 0xfff, 0xfff, + 0x291, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1e3, + 0xfff, 0xfff, 0xfff, 0xfff, 0x389, 0xfff, 0x07a, 0xfff, + 0x1b6, 0x2ed, 0xfff, 0xfff, 0xfff, 0xfff, 0x24e, 0x074, + 0xfff, 0xfff, 0x3dc, 0xfff, 0x4e3, 0xfff, 0xfff, 0xfff, + 0xfff, 0x4eb, 0xfff, 0xfff, 0x3b8, 0x4de, 0xfff, 0x19c, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x262, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x076, 0x4e8, 0x3da, + 0xfff, 0x531, 0xfff, 0xfff, 0x14a, 0xfff, 0x0a2, 0x433, + 0x3df, 0x1e9, 0xfff, 0xfff, 0xfff, 0xfff, 0x3e7, 0x285, + 0x2d8, 0xfff, 0xfff, 0xfff, 0x349, 0x18d, 0x098, 0xfff, + 0x0df, 0x4bf, 0xfff, 0xfff, 0x0b2, 0xfff, 0x346, 0x24d, + 0xfff, 0xfff, 0xfff, 0x24f, 0x4fa, 0x2f9, 0xfff, 0xfff, + 0x3c9, 0xfff, 0x2b4, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x056, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x179, 0xfff, 0x0e9, 0x3f0, 0x33d, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x1fd, 0xfff, 0xfff, 0x526, 0xfff, + 0xfff, 0xfff, 0x53d, 0xfff, 0xfff, 0xfff, 0x170, 0x331, + 0xfff, 0x068, 0xfff, 0xfff, 0xfff, 0x3f7, 0xfff, 0x3d8, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x09f, 0x556, 0xfff, 0xfff, 0x02d, 0xfff, 0xfff, + 0x553, 0xfff, 0xfff, 0xfff, 0x1f0, 0xfff, 0xfff, 0x4d6, + 0x41e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d5, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x248, 0xfff, 0xfff, 0xfff, 0x0a3, + 0xfff, 0x217, 0xfff, 0xfff, 0xfff, 0x4f1, 0x209, 0xfff, + 0xfff, 0x475, 0x234, 0x52b, 0x398, 0xfff, 0x08b, 0xfff, + 0xfff, 0xfff, 0xfff, 0x2c2, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x268, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x4a3, 0xfff, 0x0aa, 0xfff, 0x1d9, 0xfff, 0xfff, + 0xfff, 0xfff, 0x155, 0xfff, 0xfff, 0xfff, 0xfff, 0x0bf, + 0x539, 0xfff, 0xfff, 0x2f1, 0x545, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x2a7, 0x06f, 0xfff, 0x378, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x25e, 0xfff, + 0xfff, 0xfff, 0xfff, 0x15d, 0x02a, 0xfff, 0xfff, 0x0bc, + 0x235, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x150, 0xfff, 0x1a9, 0xfff, 0xfff, 0xfff, 0xfff, 0x381, + 0xfff, 0x04e, 0x270, 0x13f, 0xfff, 0xfff, 0x405, 0xfff, + 0x3cd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x2ef, 0xfff, 0x06a, 0xfff, 0xfff, 0xfff, 0x34f, + 0x212, 0xfff, 0xfff, 0x0e2, 0xfff, 0x083, 0x298, 0xfff, + 0xfff, 0xfff, 0x0c2, 0xfff, 0xfff, 0x52e, 0xfff, 0x488, + 0xfff, 0xfff, 0xfff, 0x36b, 0xfff, 0xfff, 0xfff, 0x442, + 0x091, 0xfff, 0x41c, 0xfff, 0xfff, 0x3a5, 0xfff, 0x4e6, + 0xfff, 0xfff, 0x40d, 0x31d, 0xfff, 0xfff, 0xfff, 0x4c1, + 0x053, 0xfff, 0x418, 0x13c, 0xfff, 0x350, 0xfff, 0x0ae, + 0xfff, 0xfff, 0x41f, 0xfff, 0x470, 0xfff, 0x4ca, 0xfff, + 0xfff, 0xfff, 0x02b, 0x450, 0xfff, 0x1f8, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x293, 0xfff, + 0xfff, 0xfff, 0xfff, 0x411, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x0b8, 0xfff, 0xfff, 0xfff, + 0x3e1, 0xfff, 0xfff, 0xfff, 0xfff, 0x43c, 0xfff, 0x2b2, + 0x2ab, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ec, + 0xfff, 0xfff, 0xfff, 0x3f8, 0x034, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x11a, 0xfff, 0x541, 0x45c, 0x134, + 0x1cc, 0xfff, 0xfff, 0xfff, 0x469, 0xfff, 0xfff, 0x44b, + 0x161, 0xfff, 0xfff, 0xfff, 0x055, 0xfff, 0xfff, 0xfff, + 0xfff, 0x307, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d1, 0xfff, + 0xfff, 0xfff, 0x124, 0x37b, 0x26b, 0x336, 0xfff, 0xfff, + 0x2e4, 0x3cb, 0xfff, 0xfff, 0x0f8, 0x3c8, 0xfff, 0xfff, + 0xfff, 0x461, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4b5, + 0x2cf, 0xfff, 0xfff, 0xfff, 0x20f, 0xfff, 0x35a, 0xfff, + 0x490, 0xfff, 0x185, 0xfff, 0xfff, 0xfff, 0xfff, 0x42e, + 0xfff, 0xfff, 0xfff, 0xfff, 0x54b, 0xfff, 0xfff, 0xfff, + 0x146, 0xfff, 0x412, 0xfff, 0xfff, 0xfff, 0x1ff, 0xfff, + 0xfff, 0x3e0, 0xfff, 0xfff, 0xfff, 0xfff, 0x2d5, 0xfff, + 0x4df, 0x505, 0xfff, 0x413, 0xfff, 0x1a5, 0xfff, 0x3b2, + 0xfff, 0xfff, 0xfff, 0x35b, 0xfff, 0x116, 0xfff, 0xfff, + 0x171, 0x4d0, 0xfff, 0x154, 0x12d, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x468, 0x4db, 0xfff, + 0xfff, 0x1df, 0xfff, 0xfff, 0xfff, 0xfff, 0x05a, 0xfff, + 0x0f1, 0x403, 0xfff, 0x22b, 0x2e0, 0xfff, 0xfff, 0xfff, + 0x2b7, 0x373, 0xfff, 0xfff, 0xfff, 0xfff, 0x13e, 0xfff, + 0xfff, 0xfff, 0x0d0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x329, 0x1d2, 0x3fa, 0x047, 0xfff, 0x2f2, 0xfff, 0xfff, + 0x141, 0x0ac, 0x1d7, 0xfff, 0x07d, 0xfff, 0xfff, 0xfff, + 0x1c1, 0xfff, 0x487, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x045, 0xfff, 0xfff, 0xfff, 0xfff, + 0x288, 0x0cd, 0xfff, 0xfff, 0xfff, 0xfff, 0x226, 0x1d8, + 0xfff, 0x153, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4cb, + 0x528, 0xfff, 0xfff, 0xfff, 0x20a, 0x343, 0x3a1, 0xfff, + 0xfff, 0xfff, 0x2d7, 0x2d3, 0x1aa, 0x4c5, 0xfff, 0xfff, + 0xfff, 0x42b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x3e9, 0xfff, 0x20b, 0x260, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x37c, 0x2fd, + 0xfff, 0xfff, 0x2c8, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x31e, 0xfff, 0x335, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x135, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x35c, 0x4dd, 0x129, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x1ef, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x34e, 0xfff, 0xfff, 0xfff, 0xfff, 0x407, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x3ad, 0xfff, 0xfff, 0xfff, + 0x379, 0xfff, 0xfff, 0x1d0, 0x38d, 0xfff, 0xfff, 0x1e8, + 0x184, 0x3c1, 0x1c4, 0xfff, 0x1f9, 0xfff, 0xfff, 0x424, + 0xfff, 0xfff, 0xfff, 0xfff, 0x1d3, 0x0d4, 0xfff, 0x4e9, + 0xfff, 0xfff, 0xfff, 0x530, 0x107, 0xfff, 0x106, 0x04f, + 0xfff, 0xfff, 0x4c7, 0x503, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x15c, 0xfff, 0x23f, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x4f3, 0xfff, 0xfff, 0x3c7, + 0xfff, 0x278, 0xfff, 0xfff, 0x0a6, 0xfff, 0xfff, 0xfff, + 0x122, 0x1cf, 0xfff, 0x327, 0xfff, 0x2e5, 0xfff, 0x29d, + 0xfff, 0xfff, 0x3f1, 0xfff, 0xfff, 0x48d, 0xfff, 0xfff, + 0xfff, 0xfff, 0x054, 0xfff, 0xfff, 0xfff, 0xfff, 0x178, + 0x27e, 0x4e0, 0x352, 0x02f, 0x09c, 0xfff, 0x2a0, 0xfff, + 0xfff, 0x46a, 0x457, 0xfff, 0xfff, 0x501, 0xfff, 0x2ba, + 0xfff, 0xfff, 0xfff, 0x54e, 0x2e7, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x551, 0xfff, 0xfff, 0x1db, 0x2aa, 0xfff, + 0xfff, 0x4bc, 0xfff, 0xfff, 0x395, 0xfff, 0x0de, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x455, 0xfff, 0x17e, + 0xfff, 0x221, 0x4a7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x388, 0xfff, 0xfff, 0xfff, 0x308, 0xfff, 0xfff, 0xfff, + 0x20e, 0x4b9, 0xfff, 0x273, 0x20c, 0x09e, 0xfff, 0x057, + 0xfff, 0xfff, 0xfff, 0xfff, 0x3f2, 0xfff, 0x1a8, 0x3a6, + 0x14c, 0xfff, 0xfff, 0x071, 0xfff, 0xfff, 0x53a, 0xfff, + 0xfff, 0xfff, 0xfff, 0x109, 0xfff, 0xfff, 0x399, 0xfff, + 0x061, 0x4f0, 0x39e, 0x244, 0xfff, 0x035, 0xfff, 0xfff, + 0x305, 0x47e, 0x297, 0xfff, 0xfff, 0x2b8, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1bc, 0xfff, 0x2fc, + 0xfff, 0xfff, 0x554, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b6, + 0xfff, 0xfff, 0xfff, 0x515, 0x397, 0xfff, 0xfff, 0x12f, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e5, + 0xfff, 0x4fc, 0xfff, 0xfff, 0x05e, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x0a8, 0x3af, 0x015, 0xfff, 0xfff, 0xfff, + 0xfff, 0x138, 0xfff, 0xfff, 0xfff, 0x540, 0xfff, 0xfff, + 0xfff, 0x027, 0x523, 0x2f0, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x16c, 0xfff, 0x27d, 0xfff, 0xfff, 0xfff, + 0xfff, 0x04c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4dc, + 0xfff, 0xfff, 0x059, 0x301, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x1a3, 0xfff, 0x15a, 0xfff, 0xfff, + 0x0a5, 0xfff, 0x435, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x051, 0xfff, 0xfff, 0x131, 0xfff, 0x4f4, 0xfff, + 0xfff, 0xfff, 0xfff, 0x441, 0xfff, 0x4fb, 0xfff, 0x03b, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ed, 0x274, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d3, 0x55e, 0x1b3, + 0xfff, 0x0bd, 0xfff, 0xfff, 0xfff, 0xfff, 0x225, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x4b7, 0xfff, 0xfff, 0x2ff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c3, 0xfff, + 0x383, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2f6, + 0xfff, 0xfff, 0x1ee, 0xfff, 0x03d, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x26f, 0x1dc, 0xfff, 0x0db, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x0ce, 0xfff, 0xfff, 0x127, 0x03a, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x311, 0xfff, + 0xfff, 0x13d, 0x09d, 0x47b, 0x2a6, 0x50d, 0x510, 0x19a, + 0xfff, 0x354, 0x414, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x44c, 0x3b0, 0xfff, 0x23d, 0x429, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x4c0, 0x416, 0xfff, 0x05b, 0xfff, 0xfff, 0x137, 0xfff, + 0x25f, 0x49f, 0xfff, 0x279, 0x013, 0xfff, 0xfff, 0xfff, + 0x269, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3d0, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x077, 0xfff, 0xfff, 0x3fb, + 0xfff, 0xfff, 0xfff, 0xfff, 0x271, 0x3a0, 0xfff, 0xfff, + 0x40f, 0xfff, 0xfff, 0x3de, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ab, 0x26a, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x489, 0xfff, 0xfff, + 0x252, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b7, 0x42f, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x3b7, + 0xfff, 0x2bb, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x0f7, 0x01d, 0xfff, 0x067, 0xfff, + 0xfff, 0xfff, 0xfff, 0x4e2, 0xfff, 0xfff, 0x4bb, 0xfff, + 0xfff, 0xfff, 0x17b, 0xfff, 0x0ee, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x36e, 0xfff, 0xfff, 0xfff, 0x533, 0xfff, + 0xfff, 0xfff, 0x4d4, 0x356, 0xfff, 0xfff, 0x375, 0xfff, + 0xfff, 0xfff, 0xfff, 0x4a4, 0x513, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4ff, 0xfff, 0x2af, + 0xfff, 0xfff, 0x026, 0xfff, 0x0ad, 0xfff, 0xfff, 0xfff, + 0xfff, 0x26e, 0xfff, 0xfff, 0xfff, 0xfff, 0x493, 0xfff, + 0x463, 0x4d2, 0x4be, 0xfff, 0xfff, 0xfff, 0xfff, 0x4f2, + 0x0b6, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x32d, 0x315, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x13a, 0x4a1, 0xfff, 0x27a, 0xfff, 0xfff, 0xfff, + 0x47a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x334, 0xfff, 0xfff, 0xfff, 0xfff, 0x54c, 0xfff, 0xfff, + 0xfff, 0x0c9, 0x007, 0xfff, 0xfff, 0x12e, 0xfff, 0x0ff, + 0xfff, 0xfff, 0x3f5, 0x509, 0xfff, 0xfff, 0xfff, 0xfff, + 0x1c3, 0x2ad, 0xfff, 0xfff, 0x47c, 0x261, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x152, 0xfff, 0xfff, 0xfff, 0x339, + 0xfff, 0x243, 0x1c0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x063, 0xfff, 0xfff, 0x254, 0xfff, 0xfff, 0x173, 0xfff, + 0x0c7, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x362, 0x259, 0x485, 0x374, 0x0dc, 0x3ab, 0xfff, + 0x1c5, 0x534, 0x544, 0xfff, 0xfff, 0x508, 0xfff, 0x402, + 0x408, 0xfff, 0x0e7, 0xfff, 0xfff, 0x00a, 0x205, 0xfff, + 0xfff, 0x2b9, 0xfff, 0xfff, 0xfff, 0x465, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x23a, 0xfff, 0xfff, 0xfff, + 0xfff, 0x147, 0x19d, 0x115, 0x214, 0xfff, 0x090, 0x368, + 0xfff, 0x210, 0xfff, 0xfff, 0x280, 0x52a, 0x163, 0x148, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x326, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x2de, 0xfff, 0xfff, 0xfff, 0xfff, + 0x206, 0x2c1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x189, 0xfff, 0xfff, 0xfff, 0xfff, 0x367, 0xfff, 0x1a4, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x443, 0xfff, 0x27b, + 0xfff, 0xfff, 0x251, 0x549, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x188, 0x04b, 0xfff, 0xfff, 0xfff, 0x31f, + 0x4a6, 0xfff, 0x246, 0x1de, 0x156, 0xfff, 0xfff, 0xfff, + 0x3a9, 0xfff, 0xfff, 0xfff, 0x2fa, 0xfff, 0x128, 0x0d1, + 0x449, 0x255, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x258, 0xfff, 0xfff, 0xfff, + 0x532, 0xfff, 0xfff, 0xfff, 0x303, 0x517, 0xfff, 0xfff, + 0x2a9, 0x24a, 0xfff, 0xfff, 0x231, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x4b6, 0x516, 0xfff, 0xfff, 0x0e4, 0x0eb, + 0xfff, 0x4e4, 0xfff, 0x275, 0xfff, 0xfff, 0x031, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x025, 0x21a, 0xfff, 0x0cc, + 0x45f, 0x3d9, 0x289, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x23e, 0xfff, 0xfff, 0xfff, 0x438, 0x097, + 0x419, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x0a9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x37e, 0x0e0, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x431, + 0x372, 0xfff, 0xfff, 0xfff, 0x1ba, 0x06e, 0xfff, 0x1b1, + 0xfff, 0xfff, 0x12a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x193, 0xfff, 0xfff, 0xfff, 0xfff, 0x10a, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x048, 0x1b4, + 0xfff, 0xfff, 0xfff, 0xfff, 0x295, 0x140, 0x108, 0xfff, + 0xfff, 0xfff, 0xfff, 0x16f, 0xfff, 0x0a4, 0x37a, 0xfff, + 0x29a, 0xfff, 0x284, 0xfff, 0xfff, 0xfff, 0xfff, 0x4c6, + 0x2a2, 0x3a3, 0xfff, 0x201, 0xfff, 0xfff, 0xfff, 0x4bd, + 0x005, 0x54a, 0x3b5, 0x204, 0x2ee, 0x11d, 0x436, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x3ec, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x11f, 0x498, 0x21c, 0xfff, + 0xfff, 0xfff, 0x3d6, 0xfff, 0x4ab, 0xfff, 0x432, 0x2eb, + 0x542, 0x4fd, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x4ce, 0xfff, 0xfff, 0x2fb, 0xfff, + 0xfff, 0x2e1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x1b9, 0x037, 0x0dd, + 0xfff, 0xfff, 0xfff, 0x2bf, 0x521, 0x496, 0x095, 0xfff, + 0xfff, 0x328, 0x070, 0x1bf, 0xfff, 0x393, 0xfff, 0xfff, + 0x102, 0xfff, 0xfff, 0x21b, 0xfff, 0x142, 0x263, 0x519, + 0xfff, 0x2a5, 0x177, 0xfff, 0x14d, 0x471, 0x4ae, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x1f6, 0xfff, 0x481, 0xfff, 0xfff, 0xfff, 0x151, 0xfff, + 0xfff, 0xfff, 0x085, 0x33f, 0xfff, 0xfff, 0xfff, 0x084, + 0xfff, 0xfff, 0xfff, 0x345, 0x3a2, 0xfff, 0xfff, 0x0a0, + 0x0da, 0x024, 0xfff, 0xfff, 0xfff, 0x1bd, 0xfff, 0x55c, + 0x467, 0x445, 0xfff, 0xfff, 0xfff, 0x052, 0xfff, 0xfff, + 0xfff, 0xfff, 0x51e, 0xfff, 0xfff, 0x39d, 0xfff, 0x35f, + 0xfff, 0x376, 0x3ee, 0xfff, 0xfff, 0xfff, 0xfff, 0x448, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x16a, + 0xfff, 0x036, 0x38f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x211, + 0xfff, 0xfff, 0xfff, 0x230, 0xfff, 0xfff, 0x3ba, 0xfff, + 0xfff, 0xfff, 0x3ce, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x229, 0xfff, 0x176, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x00b, 0xfff, 0x162, 0x018, 0xfff, + 0xfff, 0x233, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x400, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x12b, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x3f4, 0xfff, 0x0f0, 0xfff, 0x1ac, 0xfff, 0xfff, + 0x119, 0xfff, 0x2c0, 0xfff, 0xfff, 0xfff, 0x49b, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x23c, 0xfff, + 0x4b3, 0x010, 0x064, 0xfff, 0xfff, 0x4ba, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x3c2, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x006, 0x196, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x100, 0x191, 0xfff, + 0x1ea, 0x29f, 0xfff, 0xfff, 0xfff, 0x276, 0xfff, 0xfff, + 0x2b1, 0x3b9, 0xfff, 0x03c, 0xfff, 0xfff, 0xfff, 0x180, + 0xfff, 0x08f, 0xfff, 0xfff, 0x19e, 0x019, 0xfff, 0x0b0, + 0x0fd, 0x332, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x06b, 0x2e8, 0xfff, 0x446, 0xfff, 0xfff, 0x004, + 0x247, 0x197, 0xfff, 0x112, 0x169, 0x292, 0xfff, 0x302, + 0xfff, 0xfff, 0x33b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x287, 0x21f, 0xfff, 0x3ea, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x4e7, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x3a8, 0xfff, 0xfff, 0x2bc, 0xfff, + 0x484, 0x296, 0xfff, 0x1c9, 0x08c, 0x1e5, 0x48a, 0xfff, + 0x360, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x1ca, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x10d, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x066, 0x2ea, 0x28b, 0x25b, 0xfff, 0x072, + 0xfff, 0xfff, 0xfff, 0xfff, 0x2b6, 0xfff, 0xfff, 0x272, + 0xfff, 0xfff, 0x525, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x2ca, 0xfff, 0xfff, 0xfff, 0x299, 0xfff, 0xfff, 0xfff, + 0x558, 0x41a, 0xfff, 0x4f7, 0x557, 0xfff, 0x4a0, 0x344, + 0x12c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x125, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x40e, 0xfff, 0xfff, 0x502, 0xfff, 0x103, 0x3e6, 0xfff, + 0x527, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x45d, 0xfff, 0xfff, 0xfff, 0xfff, + 0x44e, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d2, 0x4c9, 0x35e, + 0x459, 0x2d9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x17d, + 0x0c4, 0xfff, 0xfff, 0xfff, 0x3ac, 0x390, 0x094, 0xfff, + 0x483, 0x0ab, 0xfff, 0x253, 0xfff, 0x391, 0xfff, 0xfff, + 0xfff, 0xfff, 0x123, 0x0ef, 0xfff, 0xfff, 0xfff, 0x330, + 0x38c, 0xfff, 0xfff, 0x2ae, 0xfff, 0xfff, 0xfff, 0x042, + 0x012, 0x06d, 0xfff, 0xfff, 0xfff, 0x32a, 0x3db, 0x364, + 0x2dc, 0xfff, 0x30f, 0x3d7, 0x4a5, 0x050, 0xfff, 0xfff, + 0x029, 0xfff, 0xfff, 0xfff, 0xfff, 0x1d1, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x480, 0xfff, + 0x4ed, 0x081, 0x0a1, 0xfff, 0xfff, 0xfff, 0x30e, 0x52f, + 0x257, 0xfff, 0xfff, 0x447, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x401, 0x3cc, 0xfff, 0xfff, 0x0fb, + 0x2c9, 0x42a, 0x314, 0x33e, 0x3bd, 0x318, 0xfff, 0x10e, + 0x2a1, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x24c, + 0x506, 0xfff, 0x267, 0xfff, 0xfff, 0x219, 0xfff, 0x1eb, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x309, 0x3e2, 0x46c, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x384, 0xfff, 0xfff, 0xfff, 0xfff, 0x50c, 0xfff, 0x24b, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x038, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x194, + 0x143, 0x3e3, 0xfff, 0xfff, 0xfff, 0x4c2, 0xfff, 0xfff, + 0x0e1, 0x25c, 0xfff, 0x237, 0xfff, 0x1fe, 0xfff, 0xfff, + 0xfff, 0x065, 0x2a4, 0xfff, 0x386, 0x55a, 0x11b, 0xfff, + 0xfff, 0x192, 0xfff, 0x183, 0x00e, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x4b2, 0x18e, 0xfff, 0xfff, 0xfff, + 0xfff, 0x486, 0x4ef, 0x0c6, 0x380, 0xfff, 0x4a8, 0xfff, + 0x0c5, 0xfff, 0xfff, 0xfff, 0xfff, 0x093, 0x1b8, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e6, + 0xfff, 0x0f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x28e, 0xfff, 0x53b, 0x420, 0x22a, 0x33a, 0xfff, 0x387, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2a3, 0xfff, 0xfff, + 0xfff, 0x428, 0x500, 0xfff, 0xfff, 0x120, 0x2c6, 0x290, + 0x2f5, 0x0e3, 0xfff, 0x0b7, 0xfff, 0x319, 0x474, 0xfff, + 0xfff, 0xfff, 0x529, 0x014, 0xfff, 0x41b, 0x40a, 0x18b, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x0d9, + 0xfff, 0x38a, 0xfff, 0xfff, 0xfff, 0xfff, 0x1ce, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x3b1, 0xfff, 0xfff, 0x05d, + 0x2c4, 0xfff, 0xfff, 0x4af, 0xfff, 0x030, 0xfff, 0xfff, + 0x203, 0xfff, 0x277, 0x256, 0xfff, 0xfff, 0xfff, 0x4f9, + 0xfff, 0x2c7, 0xfff, 0x466, 0x016, 0x1cd, 0xfff, 0x167, + 0xfff, 0xfff, 0x0c8, 0xfff, 0x43d, 0xfff, 0xfff, 0x020, + 0xfff, 0xfff, 0x232, 0x1cb, 0x1e0, 0xfff, 0xfff, 0x347, + 0xfff, 0x478, 0xfff, 0x365, 0xfff, 0xfff, 0xfff, 0xfff, + 0x358, 0xfff, 0x10b, 0xfff, 0x35d, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x452, 0x22d, 0xfff, 0xfff, 0x47d, 0xfff, + 0x2f3, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x460, 0xfff, + 0xfff, 0xfff, 0x50b, 0xfff, 0xfff, 0xfff, 0x2ec, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x4b1, 0x422, 0xfff, 0xfff, + 0xfff, 0x2d4, 0xfff, 0x239, 0xfff, 0xfff, 0xfff, 0x439, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x491, 0x075, 0xfff, 0xfff, 0xfff, 0x06c, 0xfff, + 0xfff, 0x0f9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x139, 0xfff, 0x4f6, 0xfff, 0xfff, 0x409, 0xfff, + 0xfff, 0x15b, 0xfff, 0xfff, 0x348, 0xfff, 0xfff, 0xfff, + 0xfff, 0x4a2, 0x49d, 0xfff, 0x033, 0x175, 0xfff, 0x039, + 0xfff, 0x312, 0x40c, 0xfff, 0xfff, 0x325, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x4aa, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0x165, 0x3bc, 0x48c, 0x310, 0x096, + 0xfff, 0xfff, 0x250, 0x1a2, 0xfff, 0xfff, 0xfff, 0xfff, + 0x20d, 0x2ac, 0xfff, 0xfff, 0x39b, 0xfff, 0x377, 0xfff, + 0x512, 0x495, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x357, 0x4ea, 0xfff, 0xfff, + 0xfff, 0xfff, 0x198, 0xfff, 0xfff, 0xfff, 0x434, 0x04a, + 0xfff, 0xfff, 0xfff, 0xfff, 0x062, 0xfff, 0x1d6, 0x1c8, + 0xfff, 0x1f3, 0x281, 0xfff, 0x462, 0xfff, 0xfff, 0xfff, + 0x4b0, 0xfff, 0x207, 0xfff, 0xfff, 0xfff, 0xfff, 0x3dd, + 0xfff, 0xfff, 0x55d, 0xfff, 0x552, 0x494, 0x1af, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x227, 0xfff, 0xfff, 0x069, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x43e, + 0x0b5, 0xfff, 0x524, 0x2d2, 0xfff, 0xfff, 0xfff, 0x28f, + 0xfff, 0x01b, 0x50e, 0xfff, 0xfff, 0x1bb, 0xfff, 0xfff, + 0x41d, 0xfff, 0x32e, 0x48e, 0xfff, 0x1f7, 0x224, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x394, 0xfff, 0xfff, 0xfff, + 0xfff, 0x52c, 0xfff, 0xfff, 0xfff, 0x392, 0xfff, 0x1e7, + 0xfff, 0xfff, 0x3f9, 0x3a7, 0xfff, 0x51f, 0xfff, 0x0bb, + 0x118, 0x3ca, 0xfff, 0x1dd, 0xfff, 0x48b, 0xfff, 0xfff, + 0xfff, 0xfff, 0x50f, 0xfff, 0x0d6, 0xfff, 0x1fa, 0xfff, + 0x11e, 0xfff, 0xfff, 0xfff, 0xfff, 0x4d7, 0xfff, 0x078, + 0x008, 0xfff, 0x25d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x032, 0x33c, 0xfff, 0x4d9, 0x160, 0xfff, 0xfff, 0x300, + 0x0b1, 0xfff, 0x322, 0xfff, 0x4ec, 0xfff, 0xfff, 0x200, + 0x00c, 0x369, 0x473, 0xfff, 0xfff, 0x32c, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x53e, 0x3d4, 0x417, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x34b, 0x001, 0x39a, 0x02c, 0xfff, 0xfff, 0x2ce, 0x00f, + 0xfff, 0x0ba, 0xfff, 0xfff, 0xfff, 0xfff, 0x060, 0xfff, + 0x406, 0xfff, 0xfff, 0xfff, 0x4ee, 0x4ac, 0xfff, 0x43f, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x29b, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x216, + 0x190, 0xfff, 0x396, 0x464, 0xfff, 0xfff, 0x323, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x2e9, 0xfff, 0x26d, + 0x2cd, 0x040, 0xfff, 0xfff, 0xfff, 0xfff, 0x38b, 0x3c0, + 0xfff, 0xfff, 0xfff, 0x1f2, 0xfff, 0x0ea, 0xfff, 0xfff, + 0x472, 0xfff, 0x1fb, 0xfff, 0xfff, 0x0af, 0x27f, 0xfff, + 0xfff, 0xfff, 0x479, 0x023, 0xfff, 0x0d8, 0x3b3, 0xfff, + 0xfff, 0xfff, 0x121, 0xfff, 0xfff, 0x3bf, 0xfff, 0xfff, + 0x16b, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x45a, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0x0be, 0xfff, 0xfff, 0xfff, 0x111, 0xfff, 0x220, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0x09b, 0x218, 0xfff, 0x022, 0x202, 0xfff, + 0x4c8, 0xfff, 0x0ed, 0xfff, 0xfff, 0x182, 0xfff, 0xfff, + 0xfff, 0x17f, 0x213, 0xfff, 0x321, 0x36a, 0xfff, 0x086, + 0xfff, 0xfff, 0xfff, 0x43b, 0x088, 0xfff, 0xfff, 0xfff, + 0xfff, 0x26c, 0xfff, 0x2f8, 0x3b4, 0xfff, 0xfff, 0xfff, + 0x132, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x333, 0x444, + 0x0c1, 0x4d8, 0x46d, 0x264, 0xfff, 0xfff, 0xfff, 0xfff, + 0x426, 0xfff, 0xfff, 0xfff, 0xfff, 0x2fe, 0xfff, 0xfff, + 0xfff, 0xfff, 0x011, 0xfff, 0x05f, 0xfff, 0xfff, 0xfff, + 0xfff, 0x10c, 0x101, 0xfff, 0xfff, 0xfff, 0xfff, 0x110, + 0xfff, 0x044, 0x304, 0x361, 0x404, 0xfff, 0x51b, 0x099, + 0xfff, 0x440, 0xfff, 0xfff, 0xfff, 0x222, 0xfff, 0xfff, + 0xfff, 0xfff, 0x1b5, 0xfff, 0x136, 0x430, 0xfff, 0x1da, + 0xfff, 0xfff, 0xfff, 0x043, 0xfff, 0x17c, 0xfff, 0xfff, + 0xfff, 0x01c, 0xfff, 0xfff, 0xfff, 0x425, 0x236, 0xfff, + 0x317, 0xfff, 0xfff, 0x437, 0x3fc, 0xfff, 0x1f1, 0xfff, + 0x324, 0xfff, 0xfff, 0x0ca, 0x306, 0xfff, 0x548, 0xfff, + 0x46e, 0xfff, 0xfff, 0xfff, 0x4b8, 0x1c2, 0x286, 0xfff, + 0xfff, 0x087, 0x18a, 0x19f, 0xfff, 0xfff, 0xfff, 0xfff, + 0x18c, 0xfff, 0x215, 0xfff, 0xfff, 0xfff, 0xfff, 0x283, + 0xfff, 0xfff, 0xfff, 0x126, 0xfff, 0xfff, 0x370, 0xfff, + 0x53f, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0x31c, 0xfff, + 0x4d1, 0xfff, 0xfff, 0xfff, 0x021, 0xfff, 0x157, 0xfff, + 0xfff, 0x028, 0x16e, 0xfff, 0x421, 0xfff, 0x1c6, 0xfff, + 0xfff, 0x511, 0xfff, 0xfff, 0x39c, 0x46f, 0x1b2, 0xfff, + 0xfff, 0x316, 0xfff, 0xfff, 0x009, 0xfff, 0xfff, 0x195, + 0xfff, 0x240, 0x546, 0xfff, 0xfff, 0x520, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x454, 0xfff, 0xfff, 0xfff, + 0x3f3, 0xfff, 0xfff, 0x187, 0xfff, 0x4a9, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x51c, 0x453, 0x1e6, 0xfff, + 0xfff, 0xfff, 0x1b0, 0xfff, 0x477, 0xfff, 0xfff, 0xfff, + 0x4fe, 0xfff, 0x32f, 0xfff, 0xfff, 0x15e, 0x1d4, 0xfff, + 0x0e5, 0xfff, 0xfff, 0xfff, 0x242, 0x14b, 0x046, 0xfff, + 0x3f6, 0x3bb, 0x3e4, 0xfff, 0xfff, 0x2e3, 0xfff, 0x245, + 0xfff, 0x149, 0xfff, 0xfff, 0xfff, 0x2db, 0xfff, 0xfff, + 0x181, 0xfff, 0x089, 0x2c5, 0xfff, 0x1f5, 0xfff, 0x2d6, + 0x507, 0xfff, 0x42d, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0x080, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, + 0xfff, 0xfff, 0xfff, 0xfff, 0x3c3, 0x320, 0xfff, 0x1e1, + 0xfff, 0x0f5, 0x13b, 0xfff, 0xfff, 0xfff, 0x003, 0x4da, + 0xfff, 0xfff, 0xfff, 0x42c, 0xfff, 0xfff, 0x0cb, 0xfff, + 0x536, 0x2c3, 0xfff, 0xfff, 0xfff, 0xfff, 0x199, 0xfff, + 0xfff, 0x0c0, 0xfff, 0x01e, 0x497, 0xfff, 0xfff, 0x3e5, + 0xfff, 0xfff, 0xfff, 0x0cf, 0xfff, 0x2bd, 0xfff, 0x223, + 0xfff, 0x3ff, 0xfff, 0x058, 0x174, 0x3ef, 0xfff, 0x002 +}; + +static unsigned short err_pos(unsigned short din) +{ + BUG_ON(din >= ARRAY_SIZE(err_pos_lut)); + return err_pos_lut[din]; +} +static int chk_no_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info) +{ + if ((chk_syndrome_list[0] | chk_syndrome_list[1] | + chk_syndrome_list[2] | chk_syndrome_list[3] | + chk_syndrome_list[4] | chk_syndrome_list[5] | + chk_syndrome_list[6] | chk_syndrome_list[7]) != 0x0) { + return -EINVAL; + } else { + err_info[0] = 0x0; + return 0; + } +} +static int chk_1_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info) +{ + unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + tmp0 = gf4096_mul(chk_syndrome_list[1], gf4096_inv(chk_syndrome_list[0])); + tmp1 = gf4096_mul(chk_syndrome_list[2], gf4096_inv(chk_syndrome_list[1])); + tmp2 = gf4096_mul(chk_syndrome_list[3], gf4096_inv(chk_syndrome_list[2])); + tmp3 = gf4096_mul(chk_syndrome_list[4], gf4096_inv(chk_syndrome_list[3])); + tmp4 = gf4096_mul(chk_syndrome_list[5], gf4096_inv(chk_syndrome_list[4])); + tmp5 = gf4096_mul(chk_syndrome_list[6], gf4096_inv(chk_syndrome_list[5])); + tmp6 = gf4096_mul(chk_syndrome_list[7], gf4096_inv(chk_syndrome_list[6])); + if ((tmp0 == tmp1) & (tmp1 == tmp2) & (tmp2 == tmp3) & (tmp3 == tmp4) & (tmp4 == tmp5) & (tmp5 == tmp6)) { + err_info[0] = 0x1; // encode 1-symbol error as 0x1 + err_info[1] = err_pos(tmp0); + err_info[1] = (unsigned short)(0x55e - err_info[1]); + err_info[5] = chk_syndrome_list[0]; + return 0; + } else + return -EINVAL; +} +static int chk_2_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info) +{ + unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + unsigned short coefs[4]; + unsigned short err_pats[4]; + int found_num_root = 0; + unsigned short bit2_root0, bit2_root1; + unsigned short bit2_root0_inv, bit2_root1_inv; + unsigned short err_loc_eqn, test_root; + unsigned short bit2_loc0, bit2_loc1; + unsigned short bit2_pat0, bit2_pat1; + + find_2x2_soln(chk_syndrome_list[1], + chk_syndrome_list[0], + chk_syndrome_list[2], chk_syndrome_list[1], chk_syndrome_list[2], chk_syndrome_list[3], coefs); + for (test_root = 0x1; test_root < 0xfff; test_root++) { + err_loc_eqn = + gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root) ^ 0x1; + if (err_loc_eqn == 0x0) { + if (found_num_root == 0) { + bit2_root0 = test_root; + found_num_root = 1; + } else if (found_num_root == 1) { + bit2_root1 = test_root; + found_num_root = 2; + break; + } + } + } + if (found_num_root != 2) + return -EINVAL; + else { + bit2_root0_inv = gf4096_inv(bit2_root0); + bit2_root1_inv = gf4096_inv(bit2_root1); + find_2bit_err_pats(chk_syndrome_list[0], + chk_syndrome_list[1], bit2_root0_inv, bit2_root1_inv, err_pats); + bit2_pat0 = err_pats[0]; + bit2_pat1 = err_pats[1]; + //for(x+1) + tmp0 = gf4096_mul(gf4096_mul(bit2_root0_inv, bit2_root0_inv), gf4096_mul(bit2_root0_inv, bit2_root0_inv)); //rinv0^4 + tmp1 = gf4096_mul(bit2_root0_inv, tmp0); //rinv0^5 + tmp2 = gf4096_mul(bit2_root0_inv, tmp1); //rinv0^6 + tmp3 = gf4096_mul(bit2_root0_inv, tmp2); //rinv0^7 + tmp4 = gf4096_mul(gf4096_mul(bit2_root1_inv, bit2_root1_inv), gf4096_mul(bit2_root1_inv, bit2_root1_inv)); //rinv1^4 + tmp5 = gf4096_mul(bit2_root1_inv, tmp4); //rinv1^5 + tmp6 = gf4096_mul(bit2_root1_inv, tmp5); //rinv1^6 + tmp7 = gf4096_mul(bit2_root1_inv, tmp6); //rinv1^7 + //check if only 2-bit error + if ((chk_syndrome_list[4] == + (gf4096_mul(bit2_pat0, tmp0) ^ + gf4096_mul(bit2_pat1, + tmp4))) & (chk_syndrome_list[5] == + (gf4096_mul(bit2_pat0, tmp1) ^ + gf4096_mul(bit2_pat1, + tmp5))) & + (chk_syndrome_list[6] == + (gf4096_mul(bit2_pat0, tmp2) ^ + gf4096_mul(bit2_pat1, + tmp6))) & (chk_syndrome_list[7] == + (gf4096_mul(bit2_pat0, tmp3) ^ gf4096_mul(bit2_pat1, tmp7)))) { + if ((err_pos(bit2_root0_inv) == 0xfff) | (err_pos(bit2_root1_inv) == 0xfff)) { + return -EINVAL; + } else { + bit2_loc0 = 0x55e - err_pos(bit2_root0_inv); + bit2_loc1 = 0x55e - err_pos(bit2_root1_inv); + err_info[0] = 0x2; // encode 2-symbol error as 0x2 + err_info[1] = bit2_loc0; + err_info[2] = bit2_loc1; + err_info[5] = bit2_pat0; + err_info[6] = bit2_pat1; + return 0; + } + } else + return -EINVAL; + } +} +static int chk_3_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info) +{ + unsigned short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + unsigned short coefs[4]; + unsigned short err_pats[4]; + int found_num_root = 0; + unsigned short bit3_root0, bit3_root1, bit3_root2; + unsigned short bit3_root0_inv, bit3_root1_inv, bit3_root2_inv; + unsigned short err_loc_eqn, test_root; + + find_3bit_err_coefs(chk_syndrome_list[0], chk_syndrome_list[1], + chk_syndrome_list[2], chk_syndrome_list[3], + chk_syndrome_list[4], chk_syndrome_list[5], coefs); + + for (test_root = 0x1; test_root < 0xfff; test_root++) { + err_loc_eqn = gf4096_mul(coefs[2], + gf4096_mul(gf4096_mul(test_root, test_root), + test_root)) ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) + ^ gf4096_mul(coefs[0], test_root) ^ 0x1; + + if (err_loc_eqn == 0x0) { + if (found_num_root == 0) { + bit3_root0 = test_root; + found_num_root = 1; + } else if (found_num_root == 1) { + bit3_root1 = test_root; + found_num_root = 2; + } else if (found_num_root == 2) { + bit3_root2 = test_root; + found_num_root = 3; + break; + } + } + } + if (found_num_root != 3) + return -EINVAL; + else { + bit3_root0_inv = gf4096_inv(bit3_root0); + bit3_root1_inv = gf4096_inv(bit3_root1); + bit3_root2_inv = gf4096_inv(bit3_root2); + + find_3bit_err_pats(chk_syndrome_list[0], chk_syndrome_list[1], + chk_syndrome_list[2], bit3_root0_inv, + bit3_root1_inv, bit3_root2_inv, err_pats); + + //check if only 3-bit error + tmp0 = gf4096_mul(bit3_root0_inv, bit3_root0_inv); + tmp0 = gf4096_mul(tmp0, tmp0); + tmp0 = gf4096_mul(tmp0, bit3_root0_inv); + tmp0 = gf4096_mul(tmp0, bit3_root0_inv); //rinv0^6 + tmp1 = gf4096_mul(tmp0, bit3_root0_inv); //rinv0^7 + tmp2 = gf4096_mul(bit3_root1_inv, bit3_root1_inv); + tmp2 = gf4096_mul(tmp2, tmp2); + tmp2 = gf4096_mul(tmp2, bit3_root1_inv); + tmp2 = gf4096_mul(tmp2, bit3_root1_inv); //rinv1^6 + tmp3 = gf4096_mul(tmp2, bit3_root1_inv); //rinv1^7 + tmp4 = gf4096_mul(bit3_root2_inv, bit3_root2_inv); + tmp4 = gf4096_mul(tmp4, tmp4); + tmp4 = gf4096_mul(tmp4, bit3_root2_inv); + tmp4 = gf4096_mul(tmp4, bit3_root2_inv); //rinv2^6 + tmp5 = gf4096_mul(tmp4, bit3_root2_inv); //rinv2^7 + + //check if only 3 errors + if ((chk_syndrome_list[6] == (gf4096_mul(err_pats[0], tmp0) ^ + gf4096_mul(err_pats[1], tmp2) ^ + gf4096_mul(err_pats[2], tmp4))) & + (chk_syndrome_list[7] == (gf4096_mul(err_pats[0], tmp1) ^ + gf4096_mul(err_pats[1], tmp3) ^ gf4096_mul(err_pats[2], tmp5)))) { + if ((err_pos(bit3_root0_inv) == 0xfff) | + (err_pos(bit3_root1_inv) == 0xfff) | (err_pos(bit3_root2_inv) == 0xfff)) { + return -EINVAL; + } else { + err_info[0] = 0x3; + err_info[1] = (0x55e - err_pos(bit3_root0_inv)); + err_info[2] = (0x55e - err_pos(bit3_root1_inv)); + err_info[3] = (0x55e - err_pos(bit3_root2_inv)); + err_info[5] = err_pats[0]; + err_info[6] = err_pats[1]; + err_info[7] = err_pats[2]; + return 0; + } + } else + return -EINVAL; + } +} +static int chk_4_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info) +{ + unsigned short coefs[4]; + unsigned short err_pats[4]; + int found_num_root = 0; + unsigned short bit4_root0, bit4_root1, bit4_root2, bit4_root3; + unsigned short bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv; + unsigned short err_loc_eqn, test_root; + + find_4bit_err_coefs(chk_syndrome_list[0], + chk_syndrome_list[1], + chk_syndrome_list[2], + chk_syndrome_list[3], + chk_syndrome_list[4], + chk_syndrome_list[5], chk_syndrome_list[6], chk_syndrome_list[7], coefs); + + for (test_root = 0x1; test_root < 0xfff; test_root++) { + err_loc_eqn = + gf4096_mul(coefs[3], + gf4096_mul(gf4096_mul + (gf4096_mul(test_root, test_root), + test_root), + test_root)) ^ gf4096_mul(coefs[2], + gf4096_mul + (gf4096_mul(test_root, test_root), test_root)) + ^ gf4096_mul(coefs[1], gf4096_mul(test_root, test_root)) ^ gf4096_mul(coefs[0], test_root) + ^ 0x1; + if (err_loc_eqn == 0x0) { + if (found_num_root == 0) { + bit4_root0 = test_root; + found_num_root = 1; + } else if (found_num_root == 1) { + bit4_root1 = test_root; + found_num_root = 2; + } else if (found_num_root == 2) { + bit4_root2 = test_root; + found_num_root = 3; + } else { + found_num_root = 4; + bit4_root3 = test_root; + break; + } + } + } + if (found_num_root != 4) { + return -EINVAL; + } else { + bit4_root0_inv = gf4096_inv(bit4_root0); + bit4_root1_inv = gf4096_inv(bit4_root1); + bit4_root2_inv = gf4096_inv(bit4_root2); + bit4_root3_inv = gf4096_inv(bit4_root3); + find_4bit_err_pats(chk_syndrome_list[0], + chk_syndrome_list[1], + chk_syndrome_list[2], + chk_syndrome_list[3], + bit4_root0_inv, bit4_root1_inv, bit4_root2_inv, bit4_root3_inv, err_pats); + err_info[0] = 0x4; + err_info[1] = (0x55e - err_pos(bit4_root0_inv)); + err_info[2] = (0x55e - err_pos(bit4_root1_inv)); + err_info[3] = (0x55e - err_pos(bit4_root2_inv)); + err_info[4] = (0x55e - err_pos(bit4_root3_inv)); + err_info[5] = err_pats[0]; + err_info[6] = err_pats[1]; + err_info[7] = err_pats[2]; + err_info[8] = err_pats[3]; + return 0; + } +} + +void correct_12bit_symbol(unsigned char *buf, unsigned short sym, + unsigned short val) +{ + if (unlikely(sym > 1366)) { + printk(KERN_ERR "Error: symbol %d out of range; cannot correct\n", sym); + } else if (sym == 0) { + buf[0] ^= val; + } else if (sym & 1) { + buf[1+(3*(sym-1))/2] ^= (val >> 4); + buf[2+(3*(sym-1))/2] ^= ((val & 0xf) << 4); + } else { + buf[2+(3*(sym-2))/2] ^= (val >> 8); + buf[3+(3*(sym-2))/2] ^= (val & 0xff); + } +} + +static int debugecc = 0; +module_param(debugecc, int, 0644); + +int cafe_correct_ecc(unsigned char *buf, + unsigned short *chk_syndrome_list) +{ + unsigned short err_info[9]; + int i; + + if (debugecc) { + printk(KERN_WARNING "cafe_correct_ecc invoked. Syndromes %x %x %x %x %x %x %x %x\n", + chk_syndrome_list[0], chk_syndrome_list[1], + chk_syndrome_list[2], chk_syndrome_list[3], + chk_syndrome_list[4], chk_syndrome_list[5], + chk_syndrome_list[6], chk_syndrome_list[7]); + for (i=0; i < 2048; i+=16) { + printk(KERN_WARNING "D %04x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + i, + buf[i], buf[i+1], buf[i+2], buf[i+3], + buf[i+4], buf[i+5], buf[i+6], buf[i+7], + buf[i+8], buf[i+9], buf[i+10], buf[i+11], + buf[i+12], buf[i+13], buf[i+14], buf[i+15]); + } + for ( ; i < 2112; i+=16) { + printk(KERN_WARNING "O %02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + i - 2048, + buf[i], buf[i+1], buf[i+2], buf[i+3], + buf[i+4], buf[i+5], buf[i+6], buf[i+7], + buf[i+8], buf[i+9], buf[i+10], buf[i+11], + buf[i+12], buf[i+13], buf[i+14], buf[i+15]); + } + } + + + + if (chk_no_err_only(chk_syndrome_list, err_info) && + chk_1_err_only(chk_syndrome_list, err_info) && + chk_2_err_only(chk_syndrome_list, err_info) && + chk_3_err_only(chk_syndrome_list, err_info) && + chk_4_err_only(chk_syndrome_list, err_info)) { + return -EIO; + } + + for (i=0; i < err_info[0]; i++) { + if (debugecc) + printk(KERN_WARNING "Correct symbol %d with 0x%03x\n", + err_info[1+i], err_info[5+i]); + + correct_12bit_symbol(buf, err_info[1+i], err_info[5+i]); + } + + return err_info[0]; +} + diff --git a/trunk/drivers/mtd/nand/nand_base.c b/trunk/drivers/mtd/nand/nand_base.c index 7e68203fe1ba..04de315e4937 100644 --- a/trunk/drivers/mtd/nand/nand_base.c +++ b/trunk/drivers/mtd/nand/nand_base.c @@ -303,27 +303,28 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) struct nand_chip *chip = mtd->priv; u16 bad; - page = (int)(ofs >> chip->page_shift) & chip->pagemask; - if (getchip) { + page = (int)(ofs >> chip->page_shift); chipnr = (int)(ofs >> chip->chip_shift); nand_get_device(chip, mtd, FL_READING); /* Select the NAND device */ chip->select_chip(mtd, chipnr); - } + } else + page = (int)(ofs >> chip->page_shift); if (chip->options & NAND_BUSWIDTH_16) { chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE, - page); + page & chip->pagemask); bad = cpu_to_le16(chip->read_word(mtd)); if (chip->badblockpos & 0x1) bad >>= 8; if ((bad & 0xFF) != 0xff) res = 1; } else { - chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, page); + chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, + page & chip->pagemask); if (chip->read_byte(mtd) != 0xff) res = 1; } diff --git a/trunk/drivers/mtd/nand/plat_nand.c b/trunk/drivers/mtd/nand/plat_nand.c deleted file mode 100644 index cd725fc5e813..000000000000 --- a/trunk/drivers/mtd/nand/plat_nand.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Generic NAND driver - * - * Author: Vitaly Wool - * - * 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 the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -struct plat_nand_data { - struct nand_chip chip; - struct mtd_info mtd; - void __iomem *io_base; -#ifdef CONFIG_MTD_PARTITIONS - int nr_parts; - struct mtd_partition *parts; -#endif -}; - -/* - * Probe for the NAND device. - */ -static int __init plat_nand_probe(struct platform_device *pdev) -{ - struct platform_nand_data *pdata = pdev->dev.platform_data; - struct plat_nand_data *data; - int res = 0; - - /* Allocate memory for the device structure (and zero it) */ - data = kzalloc(sizeof(struct plat_nand_data), GFP_KERNEL); - if (!data) { - dev_err(&pdev->dev, "failed to allocate device structure.\n"); - return -ENOMEM; - } - - data->io_base = ioremap(pdev->resource[0].start, - pdev->resource[0].end - pdev->resource[0].start + 1); - if (data->io_base == NULL) { - dev_err(&pdev->dev, "ioremap failed\n"); - kfree(data); - return -EIO; - } - - data->chip.priv = &data; - data->mtd.priv = &data->chip; - data->mtd.owner = THIS_MODULE; - - data->chip.IO_ADDR_R = data->io_base; - data->chip.IO_ADDR_W = data->io_base; - data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl; - data->chip.dev_ready = pdata->ctrl.dev_ready; - data->chip.select_chip = pdata->ctrl.select_chip; - data->chip.chip_delay = pdata->chip.chip_delay; - data->chip.options |= pdata->chip.options; - - data->chip.ecc.hwctl = pdata->ctrl.hwcontrol; - data->chip.ecc.layout = pdata->chip.ecclayout; - data->chip.ecc.mode = NAND_ECC_SOFT; - - platform_set_drvdata(pdev, data); - - /* Scan to find existance of the device */ - if (nand_scan(&data->mtd, 1)) { - res = -ENXIO; - goto out; - } - -#ifdef CONFIG_MTD_PARTITIONS - if (pdata->chip.part_probe_types) { - res = parse_mtd_partitions(&data->mtd, - pdata->chip.part_probe_types, - &data->parts, 0); - if (res > 0) { - add_mtd_partitions(&data->mtd, data->parts, res); - return 0; - } - } - if (pdata->chip.partitions) { - data->parts = pdata->chip.partitions; - res = add_mtd_partitions(&data->mtd, data->parts, - pdata->chip.nr_partitions); - } else -#endif - res = add_mtd_device(&data->mtd); - - if (!res) - return res; - - nand_release(&data->mtd); -out: - platform_set_drvdata(pdev, NULL); - iounmap(data->io_base); - kfree(data); - return res; -} - -/* - * Remove a NAND device. - */ -static int __devexit plat_nand_remove(struct platform_device *pdev) -{ - struct plat_nand_data *data = platform_get_drvdata(pdev); - struct platform_nand_data *pdata = pdev->dev.platform_data; - - nand_release(&data->mtd); -#ifdef CONFIG_MTD_PARTITIONS - if (data->parts && data->parts != pdata->chip.partitions) - kfree(data->parts); -#endif - iounmap(data->io_base); - kfree(data); - - return 0; -} - -static struct platform_driver plat_nand_driver = { - .probe = plat_nand_probe, - .remove = plat_nand_remove, - .driver = { - .name = "gen_nand", - .owner = THIS_MODULE, - }, -}; - -static int __init plat_nand_init(void) -{ - return platform_driver_register(&plat_nand_driver); -} - -static void __exit plat_nand_exit(void) -{ - platform_driver_unregister(&plat_nand_driver); -} - -module_init(plat_nand_init); -module_exit(plat_nand_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Vitaly Wool"); -MODULE_DESCRIPTION("Simple generic NAND driver"); diff --git a/trunk/drivers/mtd/onenand/onenand_base.c b/trunk/drivers/mtd/onenand/onenand_base.c index 0537fac8de74..000794c6caf5 100644 --- a/trunk/drivers/mtd/onenand/onenand_base.c +++ b/trunk/drivers/mtd/onenand/onenand_base.c @@ -2192,7 +2192,7 @@ static int onenand_check_maf(int manuf) * @param mtd MTD device structure * * OneNAND detection method: - * Compare the values from command with ones from register + * Compare the the values from command with ones from register */ static int onenand_probe(struct mtd_info *mtd) { diff --git a/trunk/drivers/net/3c509.c b/trunk/drivers/net/3c509.c index 127f60841b10..9588da3a30e7 100644 --- a/trunk/drivers/net/3c509.c +++ b/trunk/drivers/net/3c509.c @@ -95,7 +95,8 @@ static int max_interrupt_work = 10; #include #include -static char version[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n"; +static char versionA[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n"; +static char versionB[] __initdata = "http://www.scyld.com/network/3c509.html\n"; #if defined(CONFIG_PM) && (defined(CONFIG_MCA) || defined(CONFIG_EISA)) #define EL3_SUSPEND @@ -359,7 +360,7 @@ static int __init el3_common_init(struct net_device *dev) printk(", IRQ %d.\n", dev->irq); if (el3_debug > 0) - printk(KERN_INFO "%s", version); + printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); return 0; } diff --git a/trunk/drivers/net/3c59x.c b/trunk/drivers/net/3c59x.c index f26ca331615e..80924f76dee8 100644 --- a/trunk/drivers/net/3c59x.c +++ b/trunk/drivers/net/3c59x.c @@ -103,7 +103,7 @@ static int vortex_debug = 1; static char version[] __devinitdata = -DRV_NAME ": Donald Becker and others.\n"; +DRV_NAME ": Donald Becker and others. www.scyld.com/network/vortex.html\n"; MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("3Com 3c59x/3c9xx ethernet driver "); diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index fa489b10c38c..b86ccd2ecd5b 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -2493,28 +2493,12 @@ config PASEMI_MAC This driver supports the on-chip 1/10Gbit Ethernet controller on PA Semi's PWRficient line of chips. -config MLX4_CORE - tristate - depends on PCI - default n - -config MLX4_DEBUG - bool "Verbose debugging output" if (MLX4_CORE && EMBEDDED) - default y - ---help--- - This option causes debugging code to be compiled into the - mlx4_core driver. The output can be turned on via the - debug_level module parameter (which can also be set after - the driver is loaded through sysfs). - endmenu source "drivers/net/tokenring/Kconfig" source "drivers/net/wireless/Kconfig" -source "drivers/net/usb/Kconfig" - source "drivers/net/pcmcia/Kconfig" source "drivers/net/wan/Kconfig" diff --git a/trunk/drivers/net/Makefile b/trunk/drivers/net/Makefile index a77affa4f6e6..59c0459a037c 100644 --- a/trunk/drivers/net/Makefile +++ b/trunk/drivers/net/Makefile @@ -197,7 +197,6 @@ obj-$(CONFIG_SMC911X) += smc911x.o obj-$(CONFIG_DM9000) += dm9000.o obj-$(CONFIG_FEC_8XX) += fec_8xx/ obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o -obj-$(CONFIG_MLX4_CORE) += mlx4/ obj-$(CONFIG_MACB) += macb.o @@ -207,14 +206,6 @@ obj-$(CONFIG_TR) += tokenring/ obj-$(CONFIG_WAN) += wan/ obj-$(CONFIG_ARCNET) += arcnet/ obj-$(CONFIG_NET_PCMCIA) += pcmcia/ - -obj-$(CONFIG_USB_CATC) += usb/ -obj-$(CONFIG_USB_KAWETH) += usb/ -obj-$(CONFIG_USB_PEGASUS) += usb/ -obj-$(CONFIG_USB_RTL8150) += usb/ -obj-$(CONFIG_USB_USBNET) += usb/ -obj-$(CONFIG_USB_ZD1201) += usb/ - obj-y += wireless/ obj-$(CONFIG_NET_TULIP) += tulip/ obj-$(CONFIG_HAMRADIO) += hamradio/ diff --git a/trunk/drivers/net/atl1/atl1_main.c b/trunk/drivers/net/atl1/atl1_main.c index 78cf00ff3d38..d28f88bbdd5f 100644 --- a/trunk/drivers/net/atl1/atl1_main.c +++ b/trunk/drivers/net/atl1/atl1_main.c @@ -2038,15 +2038,6 @@ static int atl1_close(struct net_device *netdev) return 0; } -#ifdef CONFIG_NET_POLL_CONTROLLER -static void atl1_poll_controller(struct net_device *netdev) -{ - disable_irq(netdev->irq); - atl1_intr(netdev->irq, netdev); - enable_irq(netdev->irq); -} -#endif - /* * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT * will assert. We do soft reset <0x1400=1> according @@ -2199,9 +2190,6 @@ static int __devinit atl1_probe(struct pci_dev *pdev, netdev->do_ioctl = &atl1_ioctl; netdev->tx_timeout = &atl1_tx_timeout; netdev->watchdog_timeo = 5 * HZ; -#ifdef CONFIG_NET_POLL_CONTROLLER - netdev->poll_controller = atl1_poll_controller; -#endif netdev->vlan_rx_register = atl1_vlan_rx_register; netdev->vlan_rx_add_vid = atl1_vlan_rx_add_vid; netdev->vlan_rx_kill_vid = atl1_vlan_rx_kill_vid; diff --git a/trunk/drivers/net/atp.c b/trunk/drivers/net/atp.c index 82d78ff8399b..18aba838c1ff 100644 --- a/trunk/drivers/net/atp.c +++ b/trunk/drivers/net/atp.c @@ -31,8 +31,10 @@ */ -static const char version[] = +static const char versionA[] = "atp.c:v1.09=ac 2002/10/01 Donald Becker \n"; +static const char versionB[] = +" http://www.scyld.com/network/atp.html\n"; /* The user-configurable values. These may be modified when a driver module is loaded.*/ @@ -322,7 +324,7 @@ static int __init atp_probe1(long ioaddr) #ifndef MODULE if (net_debug) - printk(KERN_INFO "%s", version); + printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); #endif printk(KERN_NOTICE "%s: Pocket adapter found at %#3lx, IRQ %d, SAPROM " @@ -924,7 +926,7 @@ static void set_rx_mode_8012(struct net_device *dev) static int __init atp_init_module(void) { if (debug) /* Emit version even if no cards detected. */ - printk(KERN_INFO "%s", version); + printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); return atp_init(); } diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index 223517dcbcfd..724bce51f936 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -3461,7 +3461,7 @@ void bond_unregister_arp(struct bonding *bond) /*---------------------------- Hashing Policies -----------------------------*/ /* - * Hash for the output device based upon layer 3 and layer 4 data. If + * Hash for the the output device based upon layer 3 and layer 4 data. If * the packet is a frag or not TCP or UDP, just use layer 3 data. If it is * altogether not IP, mimic bond_xmit_hash_policy_l2() */ diff --git a/trunk/drivers/net/e1000/e1000_main.c b/trunk/drivers/net/e1000/e1000_main.c index 637ae8f68791..3a03a74c0609 100644 --- a/trunk/drivers/net/e1000/e1000_main.c +++ b/trunk/drivers/net/e1000/e1000_main.c @@ -1214,7 +1214,7 @@ e1000_remove(struct pci_dev *pdev) int i; #endif - cancel_work_sync(&adapter->reset_task); + flush_scheduled_work(); e1000_release_manageability(adapter); diff --git a/trunk/drivers/net/eepro.c b/trunk/drivers/net/eepro.c index 47680237f783..39654e1e2bed 100644 --- a/trunk/drivers/net/eepro.c +++ b/trunk/drivers/net/eepro.c @@ -1126,7 +1126,7 @@ static void eepro_tx_timeout (struct net_device *dev) printk (KERN_ERR "%s: transmit timed out, %s?\n", dev->name, "network cable problem"); /* This is not a duplicate. One message for the console, - one for the log file */ + one for the the log file */ printk (KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name, "network cable problem"); eepro_complete_selreset(ioaddr); diff --git a/trunk/drivers/net/eepro100.c b/trunk/drivers/net/eepro100.c index 9800341956a2..6c267c38df97 100644 --- a/trunk/drivers/net/eepro100.c +++ b/trunk/drivers/net/eepro100.c @@ -28,7 +28,7 @@ */ static const char * const version = -"eepro100.c:v1.09j-t 9/29/99 Donald Becker\n" +"eepro100.c:v1.09j-t 9/29/99 Donald Becker http://www.scyld.com/network/eepro100.html\n" "eepro100.c: $Revision: 1.36 $ 2000/11/17 Modified by Andrey V. Savochkin and others\n"; /* A few user-configurable values that apply to all boards. diff --git a/trunk/drivers/net/epic100.c b/trunk/drivers/net/epic100.c index 5e517946f46a..4e3f14c9c717 100644 --- a/trunk/drivers/net/epic100.c +++ b/trunk/drivers/net/epic100.c @@ -93,6 +93,8 @@ static int rx_copybreak; static char version[] __devinitdata = DRV_NAME ".c:v1.11 1/7/2001 Written by Donald Becker \n"; static char version2[] __devinitdata = +" http://www.scyld.com/network/epic100.html\n"; +static char version3[] __devinitdata = " (unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n"; MODULE_AUTHOR("Donald Becker "); @@ -321,8 +323,8 @@ static int __devinit epic_init_one (struct pci_dev *pdev, #ifndef MODULE static int printed_version; if (!printed_version++) - printk (KERN_INFO "%s" KERN_INFO "%s", - version, version2); + printk (KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s", + version, version2, version3); #endif card_idx++; @@ -1594,8 +1596,8 @@ static int __init epic_init (void) { /* when a module, this is printed whether or not devices are found in probe */ #ifdef MODULE - printk (KERN_INFO "%s" KERN_INFO "%s", - version, version2); + printk (KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s", + version, version2, version3); #endif return pci_register_driver(&epic_driver); diff --git a/trunk/drivers/net/hamradio/Kconfig b/trunk/drivers/net/hamradio/Kconfig index 36d2c7d4f4d0..6e90619b3b41 100644 --- a/trunk/drivers/net/hamradio/Kconfig +++ b/trunk/drivers/net/hamradio/Kconfig @@ -140,7 +140,7 @@ config BAYCOM_SER_HDX modems that connect to a serial interface. The driver supports the ser12 design in half-duplex mode. This is the old driver. It is still provided in case your serial interface chip does not work with - the full-duplex driver. This driver is deprecated. To configure + the full-duplex driver. This driver is depreciated. To configure the driver, use the sethdlc utility available in the standard ax25 utilities package. For information on the modems, see and diff --git a/trunk/drivers/net/irda/donauboe.h b/trunk/drivers/net/irda/donauboe.h index 1e67720f1066..2ab173d9a0e4 100644 --- a/trunk/drivers/net/irda/donauboe.h +++ b/trunk/drivers/net/irda/donauboe.h @@ -113,7 +113,7 @@ /* RxOver overflow in Recv FIFO */ /* SipRcv received serial gap (or other condition you set) */ /* Interrupts are enabled by writing a one to the IER register */ -/* Interrupts are cleared by writing a one to the ISR register */ +/* Interrupts are cleared by writting a one to the ISR register */ /* */ /* 6. The remaining registers: 0x6 and 0x3 appear to be */ /* reserved parts of 16 or 32 bit registersthe remainder */ diff --git a/trunk/drivers/net/ixgb/ixgb_ee.c b/trunk/drivers/net/ixgb/ixgb_ee.c index 52c99d01d568..f15aebde7b90 100644 --- a/trunk/drivers/net/ixgb/ixgb_ee.c +++ b/trunk/drivers/net/ixgb/ixgb_ee.c @@ -315,7 +315,7 @@ ixgb_wait_eeprom_command(struct ixgb_hw *hw) * hw - Struct containing variables accessed by shared code * * Reads the first 64 16 bit words of the EEPROM and sums the values read. - * If the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is + * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is * valid. * * Returns: diff --git a/trunk/drivers/net/meth.h b/trunk/drivers/net/meth.h index ea3b8fc86d1e..84960dae2a22 100644 --- a/trunk/drivers/net/meth.h +++ b/trunk/drivers/net/meth.h @@ -126,7 +126,7 @@ typedef struct rx_packet { /* Note: when loopback is set this bit becomes collision control. Setting this bit will */ /* cause a collision to be reported. */ - /* Bits 5 and 6 are used to determine the Destination address filter mode */ + /* Bits 5 and 6 are used to determine the the Destination address filter mode */ #define METH_ACCEPT_MY 0 /* 00: Accept PHY address only */ #define METH_ACCEPT_MCAST 0x20 /* 01: Accept physical, broadcast, and multicast filter matches only */ #define METH_ACCEPT_AMCAST 0x40 /* 10: Accept physical, broadcast, and all multicast packets */ diff --git a/trunk/drivers/net/mlx4/Makefile b/trunk/drivers/net/mlx4/Makefile deleted file mode 100644 index 0952a6528f58..000000000000 --- a/trunk/drivers/net/mlx4/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_MLX4_CORE) += mlx4_core.o - -mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \ - mr.o pd.o profile.o qp.o reset.o srq.o diff --git a/trunk/drivers/net/mlx4/alloc.c b/trunk/drivers/net/mlx4/alloc.c deleted file mode 100644 index 9ffdb9d29da9..000000000000 --- a/trunk/drivers/net/mlx4/alloc.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include - -#include "mlx4.h" - -u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap) -{ - u32 obj; - - spin_lock(&bitmap->lock); - - obj = find_next_zero_bit(bitmap->table, bitmap->max, bitmap->last); - if (obj >= bitmap->max) { - bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask; - obj = find_first_zero_bit(bitmap->table, bitmap->max); - } - - if (obj < bitmap->max) { - set_bit(obj, bitmap->table); - obj |= bitmap->top; - bitmap->last = obj + 1; - } else - obj = -1; - - spin_unlock(&bitmap->lock); - - return obj; -} - -void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj) -{ - obj &= bitmap->max - 1; - - spin_lock(&bitmap->lock); - clear_bit(obj, bitmap->table); - bitmap->last = min(bitmap->last, obj); - bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask; - spin_unlock(&bitmap->lock); -} - -int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved) -{ - int i; - - /* num must be a power of 2 */ - if (num != roundup_pow_of_two(num)) - return -EINVAL; - - bitmap->last = 0; - bitmap->top = 0; - bitmap->max = num; - bitmap->mask = mask; - spin_lock_init(&bitmap->lock); - bitmap->table = kzalloc(BITS_TO_LONGS(num) * sizeof (long), GFP_KERNEL); - if (!bitmap->table) - return -ENOMEM; - - for (i = 0; i < reserved; ++i) - set_bit(i, bitmap->table); - - return 0; -} - -void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap) -{ - kfree(bitmap->table); -} - -/* - * Handling for queue buffers -- we allocate a bunch of memory and - * register it in a memory region at HCA virtual address 0. If the - * requested size is > max_direct, we split the allocation into - * multiple pages, so we don't require too much contiguous memory. - */ - -int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct, - struct mlx4_buf *buf) -{ - dma_addr_t t; - - if (size <= max_direct) { - buf->nbufs = 1; - buf->npages = 1; - buf->page_shift = get_order(size) + PAGE_SHIFT; - buf->u.direct.buf = dma_alloc_coherent(&dev->pdev->dev, - size, &t, GFP_KERNEL); - if (!buf->u.direct.buf) - return -ENOMEM; - - buf->u.direct.map = t; - - while (t & ((1 << buf->page_shift) - 1)) { - --buf->page_shift; - buf->npages *= 2; - } - - memset(buf->u.direct.buf, 0, size); - } else { - int i; - - buf->nbufs = (size + PAGE_SIZE - 1) / PAGE_SIZE; - buf->npages = buf->nbufs; - buf->page_shift = PAGE_SHIFT; - buf->u.page_list = kzalloc(buf->nbufs * sizeof *buf->u.page_list, - GFP_KERNEL); - if (!buf->u.page_list) - return -ENOMEM; - - for (i = 0; i < buf->nbufs; ++i) { - buf->u.page_list[i].buf = - dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE, - &t, GFP_KERNEL); - if (!buf->u.page_list[i].buf) - goto err_free; - - buf->u.page_list[i].map = t; - - memset(buf->u.page_list[i].buf, 0, PAGE_SIZE); - } - } - - return 0; - -err_free: - mlx4_buf_free(dev, size, buf); - - return -ENOMEM; -} -EXPORT_SYMBOL_GPL(mlx4_buf_alloc); - -void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf) -{ - int i; - - if (buf->nbufs == 1) - dma_free_coherent(&dev->pdev->dev, size, buf->u.direct.buf, - buf->u.direct.map); - else { - for (i = 0; i < buf->nbufs; ++i) - dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, - buf->u.page_list[i].buf, - buf->u.page_list[i].map); - kfree(buf->u.page_list); - } -} -EXPORT_SYMBOL_GPL(mlx4_buf_free); diff --git a/trunk/drivers/net/mlx4/catas.c b/trunk/drivers/net/mlx4/catas.c deleted file mode 100644 index 1bb088aeaf71..000000000000 --- a/trunk/drivers/net/mlx4/catas.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "mlx4.h" - -void mlx4_handle_catas_err(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - int i; - - mlx4_err(dev, "Catastrophic error detected:\n"); - for (i = 0; i < priv->fw.catas_size; ++i) - mlx4_err(dev, " buf[%02x]: %08x\n", - i, swab32(readl(priv->catas_err.map + i))); - - mlx4_dispatch_event(dev, MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR, 0, 0); -} - -void mlx4_map_catas_buf(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - unsigned long addr; - - addr = pci_resource_start(dev->pdev, priv->fw.catas_bar) + - priv->fw.catas_offset; - - priv->catas_err.map = ioremap(addr, priv->fw.catas_size * 4); - if (!priv->catas_err.map) - mlx4_warn(dev, "Failed to map catastrophic error buffer at 0x%lx\n", - addr); - -} - -void mlx4_unmap_catas_buf(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - if (priv->catas_err.map) - iounmap(priv->catas_err.map); -} diff --git a/trunk/drivers/net/mlx4/cmd.c b/trunk/drivers/net/mlx4/cmd.c deleted file mode 100644 index c1f81a993f5d..000000000000 --- a/trunk/drivers/net/mlx4/cmd.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include - -#include - -#include - -#include "mlx4.h" - -#define CMD_POLL_TOKEN 0xffff - -enum { - /* command completed successfully: */ - CMD_STAT_OK = 0x00, - /* Internal error (such as a bus error) occurred while processing command: */ - CMD_STAT_INTERNAL_ERR = 0x01, - /* Operation/command not supported or opcode modifier not supported: */ - CMD_STAT_BAD_OP = 0x02, - /* Parameter not supported or parameter out of range: */ - CMD_STAT_BAD_PARAM = 0x03, - /* System not enabled or bad system state: */ - CMD_STAT_BAD_SYS_STATE = 0x04, - /* Attempt to access reserved or unallocaterd resource: */ - CMD_STAT_BAD_RESOURCE = 0x05, - /* Requested resource is currently executing a command, or is otherwise busy: */ - CMD_STAT_RESOURCE_BUSY = 0x06, - /* Required capability exceeds device limits: */ - CMD_STAT_EXCEED_LIM = 0x08, - /* Resource is not in the appropriate state or ownership: */ - CMD_STAT_BAD_RES_STATE = 0x09, - /* Index out of range: */ - CMD_STAT_BAD_INDEX = 0x0a, - /* FW image corrupted: */ - CMD_STAT_BAD_NVMEM = 0x0b, - /* Attempt to modify a QP/EE which is not in the presumed state: */ - CMD_STAT_BAD_QP_STATE = 0x10, - /* Bad segment parameters (Address/Size): */ - CMD_STAT_BAD_SEG_PARAM = 0x20, - /* Memory Region has Memory Windows bound to: */ - CMD_STAT_REG_BOUND = 0x21, - /* HCA local attached memory not present: */ - CMD_STAT_LAM_NOT_PRE = 0x22, - /* Bad management packet (silently discarded): */ - CMD_STAT_BAD_PKT = 0x30, - /* More outstanding CQEs in CQ than new CQ size: */ - CMD_STAT_BAD_SIZE = 0x40 -}; - -enum { - HCR_IN_PARAM_OFFSET = 0x00, - HCR_IN_MODIFIER_OFFSET = 0x08, - HCR_OUT_PARAM_OFFSET = 0x0c, - HCR_TOKEN_OFFSET = 0x14, - HCR_STATUS_OFFSET = 0x18, - - HCR_OPMOD_SHIFT = 12, - HCR_T_BIT = 21, - HCR_E_BIT = 22, - HCR_GO_BIT = 23 -}; - -enum { - GO_BIT_TIMEOUT = 10000 -}; - -struct mlx4_cmd_context { - struct completion done; - int result; - int next; - u64 out_param; - u16 token; -}; - -static int mlx4_status_to_errno(u8 status) { - static const int trans_table[] = { - [CMD_STAT_INTERNAL_ERR] = -EIO, - [CMD_STAT_BAD_OP] = -EPERM, - [CMD_STAT_BAD_PARAM] = -EINVAL, - [CMD_STAT_BAD_SYS_STATE] = -ENXIO, - [CMD_STAT_BAD_RESOURCE] = -EBADF, - [CMD_STAT_RESOURCE_BUSY] = -EBUSY, - [CMD_STAT_EXCEED_LIM] = -ENOMEM, - [CMD_STAT_BAD_RES_STATE] = -EBADF, - [CMD_STAT_BAD_INDEX] = -EBADF, - [CMD_STAT_BAD_NVMEM] = -EFAULT, - [CMD_STAT_BAD_QP_STATE] = -EINVAL, - [CMD_STAT_BAD_SEG_PARAM] = -EFAULT, - [CMD_STAT_REG_BOUND] = -EBUSY, - [CMD_STAT_LAM_NOT_PRE] = -EAGAIN, - [CMD_STAT_BAD_PKT] = -EINVAL, - [CMD_STAT_BAD_SIZE] = -ENOMEM, - }; - - if (status >= ARRAY_SIZE(trans_table) || - (status != CMD_STAT_OK && trans_table[status] == 0)) - return -EIO; - - return trans_table[status]; -} - -static int cmd_pending(struct mlx4_dev *dev) -{ - u32 status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET); - - return (status & swab32(1 << HCR_GO_BIT)) || - (mlx4_priv(dev)->cmd.toggle == - !!(status & swab32(1 << HCR_T_BIT))); -} - -static int mlx4_cmd_post(struct mlx4_dev *dev, u64 in_param, u64 out_param, - u32 in_modifier, u8 op_modifier, u16 op, u16 token, - int event) -{ - struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; - u32 __iomem *hcr = cmd->hcr; - int ret = -EAGAIN; - unsigned long end; - - mutex_lock(&cmd->hcr_mutex); - - end = jiffies; - if (event) - end += HZ * 10; - - while (cmd_pending(dev)) { - if (time_after_eq(jiffies, end)) - goto out; - cond_resched(); - } - - /* - * We use writel (instead of something like memcpy_toio) - * because writes of less than 32 bits to the HCR don't work - * (and some architectures such as ia64 implement memcpy_toio - * in terms of writeb). - */ - __raw_writel((__force u32) cpu_to_be32(in_param >> 32), hcr + 0); - __raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful), hcr + 1); - __raw_writel((__force u32) cpu_to_be32(in_modifier), hcr + 2); - __raw_writel((__force u32) cpu_to_be32(out_param >> 32), hcr + 3); - __raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), hcr + 4); - __raw_writel((__force u32) cpu_to_be32(token << 16), hcr + 5); - - /* __raw_writel may not order writes. */ - wmb(); - - __raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT) | - (cmd->toggle << HCR_T_BIT) | - (event ? (1 << HCR_E_BIT) : 0) | - (op_modifier << HCR_OPMOD_SHIFT) | - op), hcr + 6); - cmd->toggle = cmd->toggle ^ 1; - - ret = 0; - -out: - mutex_unlock(&cmd->hcr_mutex); - return ret; -} - -static int mlx4_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param, - int out_is_imm, u32 in_modifier, u8 op_modifier, - u16 op, unsigned long timeout) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - void __iomem *hcr = priv->cmd.hcr; - int err = 0; - unsigned long end; - - down(&priv->cmd.poll_sem); - - err = mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0, - in_modifier, op_modifier, op, CMD_POLL_TOKEN, 0); - if (err) - goto out; - - end = msecs_to_jiffies(timeout) + jiffies; - while (cmd_pending(dev) && time_before(jiffies, end)) - cond_resched(); - - if (cmd_pending(dev)) { - err = -ETIMEDOUT; - goto out; - } - - if (out_is_imm) - *out_param = - (u64) be32_to_cpu((__force __be32) - __raw_readl(hcr + HCR_OUT_PARAM_OFFSET)) << 32 | - (u64) be32_to_cpu((__force __be32) - __raw_readl(hcr + HCR_OUT_PARAM_OFFSET + 4)); - - err = mlx4_status_to_errno(be32_to_cpu((__force __be32) - __raw_readl(hcr + HCR_STATUS_OFFSET)) >> 24); - -out: - up(&priv->cmd.poll_sem); - return err; -} - -void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cmd_context *context = - &priv->cmd.context[token & priv->cmd.token_mask]; - - /* previously timed out command completing at long last */ - if (token != context->token) - return; - - context->result = mlx4_status_to_errno(status); - context->out_param = out_param; - - context->token += priv->cmd.token_mask + 1; - - complete(&context->done); -} - -static int mlx4_cmd_wait(struct mlx4_dev *dev, u64 in_param, u64 *out_param, - int out_is_imm, u32 in_modifier, u8 op_modifier, - u16 op, unsigned long timeout) -{ - struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; - struct mlx4_cmd_context *context; - int err = 0; - - down(&cmd->event_sem); - - spin_lock(&cmd->context_lock); - BUG_ON(cmd->free_head < 0); - context = &cmd->context[cmd->free_head]; - cmd->free_head = context->next; - spin_unlock(&cmd->context_lock); - - init_completion(&context->done); - - mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0, - in_modifier, op_modifier, op, context->token, 1); - - if (!wait_for_completion_timeout(&context->done, msecs_to_jiffies(timeout))) { - err = -EBUSY; - goto out; - } - - err = context->result; - if (err) - goto out; - - if (out_is_imm) - *out_param = context->out_param; - -out: - spin_lock(&cmd->context_lock); - context->next = cmd->free_head; - cmd->free_head = context - cmd->context; - spin_unlock(&cmd->context_lock); - - up(&cmd->event_sem); - return err; -} - -int __mlx4_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param, - int out_is_imm, u32 in_modifier, u8 op_modifier, - u16 op, unsigned long timeout) -{ - if (mlx4_priv(dev)->cmd.use_events) - return mlx4_cmd_wait(dev, in_param, out_param, out_is_imm, - in_modifier, op_modifier, op, timeout); - else - return mlx4_cmd_poll(dev, in_param, out_param, out_is_imm, - in_modifier, op_modifier, op, timeout); -} -EXPORT_SYMBOL_GPL(__mlx4_cmd); - -int mlx4_cmd_init(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - mutex_init(&priv->cmd.hcr_mutex); - sema_init(&priv->cmd.poll_sem, 1); - priv->cmd.use_events = 0; - priv->cmd.toggle = 1; - - priv->cmd.hcr = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_HCR_BASE, - MLX4_HCR_SIZE); - if (!priv->cmd.hcr) { - mlx4_err(dev, "Couldn't map command register."); - return -ENOMEM; - } - - priv->cmd.pool = pci_pool_create("mlx4_cmd", dev->pdev, - MLX4_MAILBOX_SIZE, - MLX4_MAILBOX_SIZE, 0); - if (!priv->cmd.pool) { - iounmap(priv->cmd.hcr); - return -ENOMEM; - } - - return 0; -} - -void mlx4_cmd_cleanup(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - pci_pool_destroy(priv->cmd.pool); - iounmap(priv->cmd.hcr); -} - -/* - * Switch to using events to issue FW commands (can only be called - * after event queue for command events has been initialized). - */ -int mlx4_cmd_use_events(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int i; - - priv->cmd.context = kmalloc(priv->cmd.max_cmds * - sizeof (struct mlx4_cmd_context), - GFP_KERNEL); - if (!priv->cmd.context) - return -ENOMEM; - - for (i = 0; i < priv->cmd.max_cmds; ++i) { - priv->cmd.context[i].token = i; - priv->cmd.context[i].next = i + 1; - } - - priv->cmd.context[priv->cmd.max_cmds - 1].next = -1; - priv->cmd.free_head = 0; - - sema_init(&priv->cmd.event_sem, priv->cmd.max_cmds); - spin_lock_init(&priv->cmd.context_lock); - - for (priv->cmd.token_mask = 1; - priv->cmd.token_mask < priv->cmd.max_cmds; - priv->cmd.token_mask <<= 1) - ; /* nothing */ - --priv->cmd.token_mask; - - priv->cmd.use_events = 1; - - down(&priv->cmd.poll_sem); - - return 0; -} - -/* - * Switch back to polling (used when shutting down the device) - */ -void mlx4_cmd_use_polling(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int i; - - priv->cmd.use_events = 0; - - for (i = 0; i < priv->cmd.max_cmds; ++i) - down(&priv->cmd.event_sem); - - kfree(priv->cmd.context); - - up(&priv->cmd.poll_sem); -} - -struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(struct mlx4_dev *dev) -{ - struct mlx4_cmd_mailbox *mailbox; - - mailbox = kmalloc(sizeof *mailbox, GFP_KERNEL); - if (!mailbox) - return ERR_PTR(-ENOMEM); - - mailbox->buf = pci_pool_alloc(mlx4_priv(dev)->cmd.pool, GFP_KERNEL, - &mailbox->dma); - if (!mailbox->buf) { - kfree(mailbox); - return ERR_PTR(-ENOMEM); - } - - return mailbox; -} -EXPORT_SYMBOL_GPL(mlx4_alloc_cmd_mailbox); - -void mlx4_free_cmd_mailbox(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox) -{ - if (!mailbox) - return; - - pci_pool_free(mlx4_priv(dev)->cmd.pool, mailbox->buf, mailbox->dma); - kfree(mailbox); -} -EXPORT_SYMBOL_GPL(mlx4_free_cmd_mailbox); diff --git a/trunk/drivers/net/mlx4/cq.c b/trunk/drivers/net/mlx4/cq.c deleted file mode 100644 index 437d78ad0912..000000000000 --- a/trunk/drivers/net/mlx4/cq.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2004 Voltaire, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include - -#include "mlx4.h" -#include "icm.h" - -struct mlx4_cq_context { - __be32 flags; - u16 reserved1[3]; - __be16 page_offset; - __be32 logsize_usrpage; - u8 reserved2; - u8 cq_period; - u8 reserved3; - u8 cq_max_count; - u8 reserved4[3]; - u8 comp_eqn; - u8 log_page_size; - u8 reserved5[2]; - u8 mtt_base_addr_h; - __be32 mtt_base_addr_l; - __be32 last_notified_index; - __be32 solicit_producer_index; - __be32 consumer_index; - __be32 producer_index; - u8 reserved6[2]; - __be64 db_rec_addr; -}; - -#define MLX4_CQ_STATUS_OK ( 0 << 28) -#define MLX4_CQ_STATUS_OVERFLOW ( 9 << 28) -#define MLX4_CQ_STATUS_WRITE_FAIL (10 << 28) -#define MLX4_CQ_FLAG_CC ( 1 << 18) -#define MLX4_CQ_FLAG_OI ( 1 << 17) -#define MLX4_CQ_STATE_ARMED ( 9 << 8) -#define MLX4_CQ_STATE_ARMED_SOL ( 6 << 8) -#define MLX4_EQ_STATE_FIRED (10 << 8) - -void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn) -{ - struct mlx4_cq *cq; - - cq = radix_tree_lookup(&mlx4_priv(dev)->cq_table.tree, - cqn & (dev->caps.num_cqs - 1)); - if (!cq) { - mlx4_warn(dev, "Completion event for bogus CQ %08x\n", cqn); - return; - } - - ++cq->arm_sn; - - cq->comp(cq); -} - -void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type) -{ - struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table; - struct mlx4_cq *cq; - - spin_lock(&cq_table->lock); - - cq = radix_tree_lookup(&cq_table->tree, cqn & (dev->caps.num_cqs - 1)); - if (cq) - atomic_inc(&cq->refcount); - - spin_unlock(&cq_table->lock); - - if (!cq) { - mlx4_warn(dev, "Async event for bogus CQ %08x\n", cqn); - return; - } - - cq->event(cq, event_type); - - if (atomic_dec_and_test(&cq->refcount)) - complete(&cq->free); -} - -static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int cq_num) -{ - return mlx4_cmd(dev, mailbox->dma, cq_num, 0, MLX4_CMD_SW2HW_CQ, - MLX4_CMD_TIME_CLASS_A); -} - -static int mlx4_HW2SW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int cq_num) -{ - return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, cq_num, - mailbox ? 0 : 1, MLX4_CMD_HW2SW_CQ, - MLX4_CMD_TIME_CLASS_A); -} - -int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt, - struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cq_table *cq_table = &priv->cq_table; - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_cq_context *cq_context; - u64 mtt_addr; - int err; - - cq->cqn = mlx4_bitmap_alloc(&cq_table->bitmap); - if (cq->cqn == -1) - return -ENOMEM; - - err = mlx4_table_get(dev, &cq_table->table, cq->cqn); - if (err) - goto err_out; - - err = mlx4_table_get(dev, &cq_table->cmpt_table, cq->cqn); - if (err) - goto err_put; - - spin_lock_irq(&cq_table->lock); - err = radix_tree_insert(&cq_table->tree, cq->cqn, cq); - spin_unlock_irq(&cq_table->lock); - if (err) - goto err_cmpt_put; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) { - err = PTR_ERR(mailbox); - goto err_radix; - } - - cq_context = mailbox->buf; - memset(cq_context, 0, sizeof *cq_context); - - cq_context->logsize_usrpage = cpu_to_be32((ilog2(nent) << 24) | uar->index); - cq_context->comp_eqn = priv->eq_table.eq[MLX4_EQ_COMP].eqn; - cq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT; - - mtt_addr = mlx4_mtt_addr(dev, mtt); - cq_context->mtt_base_addr_h = mtt_addr >> 32; - cq_context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff); - cq_context->db_rec_addr = cpu_to_be64(db_rec); - - err = mlx4_SW2HW_CQ(dev, mailbox, cq->cqn); - mlx4_free_cmd_mailbox(dev, mailbox); - if (err) - goto err_radix; - - cq->cons_index = 0; - cq->arm_sn = 1; - cq->uar = uar; - atomic_set(&cq->refcount, 1); - init_completion(&cq->free); - - return 0; - -err_radix: - spin_lock_irq(&cq_table->lock); - radix_tree_delete(&cq_table->tree, cq->cqn); - spin_unlock_irq(&cq_table->lock); - -err_cmpt_put: - mlx4_table_put(dev, &cq_table->cmpt_table, cq->cqn); - -err_put: - mlx4_table_put(dev, &cq_table->table, cq->cqn); - -err_out: - mlx4_bitmap_free(&cq_table->bitmap, cq->cqn); - - return err; -} -EXPORT_SYMBOL_GPL(mlx4_cq_alloc); - -void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cq_table *cq_table = &priv->cq_table; - int err; - - err = mlx4_HW2SW_CQ(dev, NULL, cq->cqn); - if (err) - mlx4_warn(dev, "HW2SW_CQ failed (%d) for CQN %06x\n", err, cq->cqn); - - synchronize_irq(priv->eq_table.eq[MLX4_EQ_COMP].irq); - - spin_lock_irq(&cq_table->lock); - radix_tree_delete(&cq_table->tree, cq->cqn); - spin_unlock_irq(&cq_table->lock); - - if (atomic_dec_and_test(&cq->refcount)) - complete(&cq->free); - wait_for_completion(&cq->free); - - mlx4_table_put(dev, &cq_table->table, cq->cqn); - mlx4_bitmap_free(&cq_table->bitmap, cq->cqn); -} -EXPORT_SYMBOL_GPL(mlx4_cq_free); - -int __devinit mlx4_init_cq_table(struct mlx4_dev *dev) -{ - struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table; - int err; - - spin_lock_init(&cq_table->lock); - INIT_RADIX_TREE(&cq_table->tree, GFP_ATOMIC); - - err = mlx4_bitmap_init(&cq_table->bitmap, dev->caps.num_cqs, - dev->caps.num_cqs - 1, dev->caps.reserved_cqs); - if (err) - return err; - - return 0; -} - -void mlx4_cleanup_cq_table(struct mlx4_dev *dev) -{ - /* Nothing to do to clean up radix_tree */ - mlx4_bitmap_cleanup(&mlx4_priv(dev)->cq_table.bitmap); -} diff --git a/trunk/drivers/net/mlx4/eq.c b/trunk/drivers/net/mlx4/eq.c deleted file mode 100644 index acf1c801a1b8..000000000000 --- a/trunk/drivers/net/mlx4/eq.c +++ /dev/null @@ -1,696 +0,0 @@ -/* - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include - -#include "mlx4.h" -#include "fw.h" - -enum { - MLX4_NUM_ASYNC_EQE = 0x100, - MLX4_NUM_SPARE_EQE = 0x80, - MLX4_EQ_ENTRY_SIZE = 0x20 -}; - -/* - * Must be packed because start is 64 bits but only aligned to 32 bits. - */ -struct mlx4_eq_context { - __be32 flags; - u16 reserved1[3]; - __be16 page_offset; - u8 log_eq_size; - u8 reserved2[4]; - u8 eq_period; - u8 reserved3; - u8 eq_max_count; - u8 reserved4[3]; - u8 intr; - u8 log_page_size; - u8 reserved5[2]; - u8 mtt_base_addr_h; - __be32 mtt_base_addr_l; - u32 reserved6[2]; - __be32 consumer_index; - __be32 producer_index; - u32 reserved7[4]; -}; - -#define MLX4_EQ_STATUS_OK ( 0 << 28) -#define MLX4_EQ_STATUS_WRITE_FAIL (10 << 28) -#define MLX4_EQ_OWNER_SW ( 0 << 24) -#define MLX4_EQ_OWNER_HW ( 1 << 24) -#define MLX4_EQ_FLAG_EC ( 1 << 18) -#define MLX4_EQ_FLAG_OI ( 1 << 17) -#define MLX4_EQ_STATE_ARMED ( 9 << 8) -#define MLX4_EQ_STATE_FIRED (10 << 8) -#define MLX4_EQ_STATE_ALWAYS_ARMED (11 << 8) - -#define MLX4_ASYNC_EVENT_MASK ((1ull << MLX4_EVENT_TYPE_PATH_MIG) | \ - (1ull << MLX4_EVENT_TYPE_COMM_EST) | \ - (1ull << MLX4_EVENT_TYPE_SQ_DRAINED) | \ - (1ull << MLX4_EVENT_TYPE_CQ_ERROR) | \ - (1ull << MLX4_EVENT_TYPE_WQ_CATAS_ERROR) | \ - (1ull << MLX4_EVENT_TYPE_EEC_CATAS_ERROR) | \ - (1ull << MLX4_EVENT_TYPE_PATH_MIG_FAILED) | \ - (1ull << MLX4_EVENT_TYPE_WQ_INVAL_REQ_ERROR) | \ - (1ull << MLX4_EVENT_TYPE_WQ_ACCESS_ERROR) | \ - (1ull << MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR) | \ - (1ull << MLX4_EVENT_TYPE_PORT_CHANGE) | \ - (1ull << MLX4_EVENT_TYPE_ECC_DETECT) | \ - (1ull << MLX4_EVENT_TYPE_SRQ_CATAS_ERROR) | \ - (1ull << MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE) | \ - (1ull << MLX4_EVENT_TYPE_SRQ_LIMIT) | \ - (1ull << MLX4_EVENT_TYPE_CMD)) -#define MLX4_CATAS_EVENT_MASK (1ull << MLX4_EVENT_TYPE_LOCAL_CATAS_ERROR) - -struct mlx4_eqe { - u8 reserved1; - u8 type; - u8 reserved2; - u8 subtype; - union { - u32 raw[6]; - struct { - __be32 cqn; - } __attribute__((packed)) comp; - struct { - u16 reserved1; - __be16 token; - u32 reserved2; - u8 reserved3[3]; - u8 status; - __be64 out_param; - } __attribute__((packed)) cmd; - struct { - __be32 qpn; - } __attribute__((packed)) qp; - struct { - __be32 srqn; - } __attribute__((packed)) srq; - struct { - __be32 cqn; - u32 reserved1; - u8 reserved2[3]; - u8 syndrome; - } __attribute__((packed)) cq_err; - struct { - u32 reserved1[2]; - __be32 port; - } __attribute__((packed)) port_change; - } event; - u8 reserved3[3]; - u8 owner; -} __attribute__((packed)); - -static void eq_set_ci(struct mlx4_eq *eq, int req_not) -{ - __raw_writel((__force u32) cpu_to_be32((eq->cons_index & 0xffffff) | - req_not << 31), - eq->doorbell); - /* We still want ordering, just not swabbing, so add a barrier */ - mb(); -} - -static struct mlx4_eqe *get_eqe(struct mlx4_eq *eq, u32 entry) -{ - unsigned long off = (entry & (eq->nent - 1)) * MLX4_EQ_ENTRY_SIZE; - return eq->page_list[off / PAGE_SIZE].buf + off % PAGE_SIZE; -} - -static struct mlx4_eqe *next_eqe_sw(struct mlx4_eq *eq) -{ - struct mlx4_eqe *eqe = get_eqe(eq, eq->cons_index); - return !!(eqe->owner & 0x80) ^ !!(eq->cons_index & eq->nent) ? NULL : eqe; -} - -static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) -{ - struct mlx4_eqe *eqe; - int cqn; - int eqes_found = 0; - int set_ci = 0; - - while ((eqe = next_eqe_sw(eq))) { - /* - * Make sure we read EQ entry contents after we've - * checked the ownership bit. - */ - rmb(); - - switch (eqe->type) { - case MLX4_EVENT_TYPE_COMP: - cqn = be32_to_cpu(eqe->event.comp.cqn) & 0xffffff; - mlx4_cq_completion(dev, cqn); - break; - - case MLX4_EVENT_TYPE_PATH_MIG: - case MLX4_EVENT_TYPE_COMM_EST: - case MLX4_EVENT_TYPE_SQ_DRAINED: - case MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE: - case MLX4_EVENT_TYPE_WQ_CATAS_ERROR: - case MLX4_EVENT_TYPE_PATH_MIG_FAILED: - case MLX4_EVENT_TYPE_WQ_INVAL_REQ_ERROR: - case MLX4_EVENT_TYPE_WQ_ACCESS_ERROR: - mlx4_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff, - eqe->type); - break; - - case MLX4_EVENT_TYPE_SRQ_LIMIT: - case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR: - mlx4_srq_event(dev, be32_to_cpu(eqe->event.srq.srqn) & 0xffffff, - eqe->type); - break; - - case MLX4_EVENT_TYPE_CMD: - mlx4_cmd_event(dev, - be16_to_cpu(eqe->event.cmd.token), - eqe->event.cmd.status, - be64_to_cpu(eqe->event.cmd.out_param)); - break; - - case MLX4_EVENT_TYPE_PORT_CHANGE: - mlx4_dispatch_event(dev, eqe->type, eqe->subtype, - be32_to_cpu(eqe->event.port_change.port) >> 28); - break; - - case MLX4_EVENT_TYPE_CQ_ERROR: - mlx4_warn(dev, "CQ %s on CQN %06x\n", - eqe->event.cq_err.syndrome == 1 ? - "overrun" : "access violation", - be32_to_cpu(eqe->event.cq_err.cqn) & 0xffffff); - mlx4_cq_event(dev, be32_to_cpu(eqe->event.cq_err.cqn), - eqe->type); - break; - - case MLX4_EVENT_TYPE_EQ_OVERFLOW: - mlx4_warn(dev, "EQ overrun on EQN %d\n", eq->eqn); - break; - - case MLX4_EVENT_TYPE_EEC_CATAS_ERROR: - case MLX4_EVENT_TYPE_ECC_DETECT: - default: - mlx4_warn(dev, "Unhandled event %02x(%02x) on EQ %d at index %u\n", - eqe->type, eqe->subtype, eq->eqn, eq->cons_index); - break; - }; - - ++eq->cons_index; - eqes_found = 1; - ++set_ci; - - /* - * The HCA will think the queue has overflowed if we - * don't tell it we've been processing events. We - * create our EQs with MLX4_NUM_SPARE_EQE extra - * entries, so we must update our consumer index at - * least that often. - */ - if (unlikely(set_ci >= MLX4_NUM_SPARE_EQE)) { - /* - * Conditional on hca_type is OK here because - * this is a rare case, not the fast path. - */ - eq_set_ci(eq, 0); - set_ci = 0; - } - } - - eq_set_ci(eq, 1); - - return eqes_found; -} - -static irqreturn_t mlx4_interrupt(int irq, void *dev_ptr) -{ - struct mlx4_dev *dev = dev_ptr; - struct mlx4_priv *priv = mlx4_priv(dev); - int work = 0; - int i; - - writel(priv->eq_table.clr_mask, priv->eq_table.clr_int); - - for (i = 0; i < MLX4_EQ_CATAS; ++i) - work |= mlx4_eq_int(dev, &priv->eq_table.eq[i]); - - return IRQ_RETVAL(work); -} - -static irqreturn_t mlx4_msi_x_interrupt(int irq, void *eq_ptr) -{ - struct mlx4_eq *eq = eq_ptr; - struct mlx4_dev *dev = eq->dev; - - mlx4_eq_int(dev, eq); - - /* MSI-X vectors always belong to us */ - return IRQ_HANDLED; -} - -static irqreturn_t mlx4_catas_interrupt(int irq, void *dev_ptr) -{ - mlx4_handle_catas_err(dev_ptr); - - /* MSI-X vectors always belong to us */ - return IRQ_HANDLED; -} - -static int mlx4_MAP_EQ(struct mlx4_dev *dev, u64 event_mask, int unmap, - int eq_num) -{ - return mlx4_cmd(dev, event_mask, (unmap << 31) | eq_num, - 0, MLX4_CMD_MAP_EQ, MLX4_CMD_TIME_CLASS_B); -} - -static int mlx4_SW2HW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int eq_num) -{ - return mlx4_cmd(dev, mailbox->dma, eq_num, 0, MLX4_CMD_SW2HW_EQ, - MLX4_CMD_TIME_CLASS_A); -} - -static int mlx4_HW2SW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int eq_num) -{ - return mlx4_cmd_box(dev, 0, mailbox->dma, eq_num, 0, MLX4_CMD_HW2SW_EQ, - MLX4_CMD_TIME_CLASS_A); -} - -static void __devinit __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, - struct mlx4_eq *eq) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int index; - - index = eq->eqn / 4 - dev->caps.reserved_eqs / 4; - - if (!priv->eq_table.uar_map[index]) { - priv->eq_table.uar_map[index] = - ioremap(pci_resource_start(dev->pdev, 2) + - ((eq->eqn / 4) << PAGE_SHIFT), - PAGE_SIZE); - if (!priv->eq_table.uar_map[index]) { - mlx4_err(dev, "Couldn't map EQ doorbell for EQN 0x%06x\n", - eq->eqn); - return NULL; - } - } - - return priv->eq_table.uar_map[index] + 0x800 + 8 * (eq->eqn % 4); -} - -static int __devinit mlx4_create_eq(struct mlx4_dev *dev, int nent, - u8 intr, struct mlx4_eq *eq) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_eq_context *eq_context; - int npages; - u64 *dma_list = NULL; - dma_addr_t t; - u64 mtt_addr; - int err = -ENOMEM; - int i; - - eq->dev = dev; - eq->nent = roundup_pow_of_two(max(nent, 2)); - npages = PAGE_ALIGN(eq->nent * MLX4_EQ_ENTRY_SIZE) / PAGE_SIZE; - - eq->page_list = kmalloc(npages * sizeof *eq->page_list, - GFP_KERNEL); - if (!eq->page_list) - goto err_out; - - for (i = 0; i < npages; ++i) - eq->page_list[i].buf = NULL; - - dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL); - if (!dma_list) - goto err_out_free; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - goto err_out_free; - eq_context = mailbox->buf; - - for (i = 0; i < npages; ++i) { - eq->page_list[i].buf = dma_alloc_coherent(&dev->pdev->dev, - PAGE_SIZE, &t, GFP_KERNEL); - if (!eq->page_list[i].buf) - goto err_out_free_pages; - - dma_list[i] = t; - eq->page_list[i].map = t; - - memset(eq->page_list[i].buf, 0, PAGE_SIZE); - } - - eq->eqn = mlx4_bitmap_alloc(&priv->eq_table.bitmap); - if (eq->eqn == -1) - goto err_out_free_pages; - - eq->doorbell = mlx4_get_eq_uar(dev, eq); - if (!eq->doorbell) { - err = -ENOMEM; - goto err_out_free_eq; - } - - err = mlx4_mtt_init(dev, npages, PAGE_SHIFT, &eq->mtt); - if (err) - goto err_out_free_eq; - - err = mlx4_write_mtt(dev, &eq->mtt, 0, npages, dma_list); - if (err) - goto err_out_free_mtt; - - memset(eq_context, 0, sizeof *eq_context); - eq_context->flags = cpu_to_be32(MLX4_EQ_STATUS_OK | - MLX4_EQ_STATE_ARMED); - eq_context->log_eq_size = ilog2(eq->nent); - eq_context->intr = intr; - eq_context->log_page_size = PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT; - - mtt_addr = mlx4_mtt_addr(dev, &eq->mtt); - eq_context->mtt_base_addr_h = mtt_addr >> 32; - eq_context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff); - - err = mlx4_SW2HW_EQ(dev, mailbox, eq->eqn); - if (err) { - mlx4_warn(dev, "SW2HW_EQ failed (%d)\n", err); - goto err_out_free_mtt; - } - - kfree(dma_list); - mlx4_free_cmd_mailbox(dev, mailbox); - - eq->cons_index = 0; - - return err; - -err_out_free_mtt: - mlx4_mtt_cleanup(dev, &eq->mtt); - -err_out_free_eq: - mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn); - -err_out_free_pages: - for (i = 0; i < npages; ++i) - if (eq->page_list[i].buf) - dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, - eq->page_list[i].buf, - eq->page_list[i].map); - - mlx4_free_cmd_mailbox(dev, mailbox); - -err_out_free: - kfree(eq->page_list); - kfree(dma_list); - -err_out: - return err; -} - -static void mlx4_free_eq(struct mlx4_dev *dev, - struct mlx4_eq *eq) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cmd_mailbox *mailbox; - int err; - int npages = PAGE_ALIGN(MLX4_EQ_ENTRY_SIZE * eq->nent) / PAGE_SIZE; - int i; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return; - - err = mlx4_HW2SW_EQ(dev, mailbox, eq->eqn); - if (err) - mlx4_warn(dev, "HW2SW_EQ failed (%d)\n", err); - - if (0) { - mlx4_dbg(dev, "Dumping EQ context %02x:\n", eq->eqn); - for (i = 0; i < sizeof (struct mlx4_eq_context) / 4; ++i) { - if (i % 4 == 0) - printk("[%02x] ", i * 4); - printk(" %08x", be32_to_cpup(mailbox->buf + i * 4)); - if ((i + 1) % 4 == 0) - printk("\n"); - } - } - - mlx4_mtt_cleanup(dev, &eq->mtt); - for (i = 0; i < npages; ++i) - pci_free_consistent(dev->pdev, PAGE_SIZE, - eq->page_list[i].buf, - eq->page_list[i].map); - - kfree(eq->page_list); - mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn); - mlx4_free_cmd_mailbox(dev, mailbox); -} - -static void mlx4_free_irqs(struct mlx4_dev *dev) -{ - struct mlx4_eq_table *eq_table = &mlx4_priv(dev)->eq_table; - int i; - - if (eq_table->have_irq) - free_irq(dev->pdev->irq, dev); - for (i = 0; i < MLX4_NUM_EQ; ++i) - if (eq_table->eq[i].have_irq) - free_irq(eq_table->eq[i].irq, eq_table->eq + i); -} - -static int __devinit mlx4_map_clr_int(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - priv->clr_base = ioremap(pci_resource_start(dev->pdev, priv->fw.clr_int_bar) + - priv->fw.clr_int_base, MLX4_CLR_INT_SIZE); - if (!priv->clr_base) { - mlx4_err(dev, "Couldn't map interrupt clear register, aborting.\n"); - return -ENOMEM; - } - - return 0; -} - -static void mlx4_unmap_clr_int(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - iounmap(priv->clr_base); -} - -int __devinit mlx4_map_eq_icm(struct mlx4_dev *dev, u64 icm_virt) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int ret; - - /* - * We assume that mapping one page is enough for the whole EQ - * context table. This is fine with all current HCAs, because - * we only use 32 EQs and each EQ uses 64 bytes of context - * memory, or 1 KB total. - */ - priv->eq_table.icm_virt = icm_virt; - priv->eq_table.icm_page = alloc_page(GFP_HIGHUSER); - if (!priv->eq_table.icm_page) - return -ENOMEM; - priv->eq_table.icm_dma = pci_map_page(dev->pdev, priv->eq_table.icm_page, 0, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(priv->eq_table.icm_dma)) { - __free_page(priv->eq_table.icm_page); - return -ENOMEM; - } - - ret = mlx4_MAP_ICM_page(dev, priv->eq_table.icm_dma, icm_virt); - if (ret) { - pci_unmap_page(dev->pdev, priv->eq_table.icm_dma, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - __free_page(priv->eq_table.icm_page); - } - - return ret; -} - -void mlx4_unmap_eq_icm(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - mlx4_UNMAP_ICM(dev, priv->eq_table.icm_virt, 1); - pci_unmap_page(dev->pdev, priv->eq_table.icm_dma, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - __free_page(priv->eq_table.icm_page); -} - -int __devinit mlx4_init_eq_table(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int err; - int i; - - err = mlx4_bitmap_init(&priv->eq_table.bitmap, dev->caps.num_eqs, - dev->caps.num_eqs - 1, dev->caps.reserved_eqs); - if (err) - return err; - - for (i = 0; i < ARRAY_SIZE(priv->eq_table.uar_map); ++i) - priv->eq_table.uar_map[i] = NULL; - - err = mlx4_map_clr_int(dev); - if (err) - goto err_out_free; - - priv->eq_table.clr_mask = - swab32(1 << (priv->eq_table.inta_pin & 31)); - priv->eq_table.clr_int = priv->clr_base + - (priv->eq_table.inta_pin < 32 ? 4 : 0); - - err = mlx4_create_eq(dev, dev->caps.num_cqs + MLX4_NUM_SPARE_EQE, - (dev->flags & MLX4_FLAG_MSI_X) ? MLX4_EQ_COMP : 0, - &priv->eq_table.eq[MLX4_EQ_COMP]); - if (err) - goto err_out_unmap; - - err = mlx4_create_eq(dev, MLX4_NUM_ASYNC_EQE + MLX4_NUM_SPARE_EQE, - (dev->flags & MLX4_FLAG_MSI_X) ? MLX4_EQ_ASYNC : 0, - &priv->eq_table.eq[MLX4_EQ_ASYNC]); - if (err) - goto err_out_comp; - - if (dev->flags & MLX4_FLAG_MSI_X) { - static const char *eq_name[] = { - [MLX4_EQ_COMP] = DRV_NAME " (comp)", - [MLX4_EQ_ASYNC] = DRV_NAME " (async)", - [MLX4_EQ_CATAS] = DRV_NAME " (catas)" - }; - - err = mlx4_create_eq(dev, 1, MLX4_EQ_CATAS, - &priv->eq_table.eq[MLX4_EQ_CATAS]); - if (err) - goto err_out_async; - - for (i = 0; i < MLX4_EQ_CATAS; ++i) { - err = request_irq(priv->eq_table.eq[i].irq, - mlx4_msi_x_interrupt, - 0, eq_name[i], priv->eq_table.eq + i); - if (err) - goto err_out_catas; - - priv->eq_table.eq[i].have_irq = 1; - } - - err = request_irq(priv->eq_table.eq[MLX4_EQ_CATAS].irq, - mlx4_catas_interrupt, 0, - eq_name[MLX4_EQ_CATAS], dev); - if (err) - goto err_out_catas; - - priv->eq_table.eq[MLX4_EQ_CATAS].have_irq = 1; - } else { - err = request_irq(dev->pdev->irq, mlx4_interrupt, - SA_SHIRQ, DRV_NAME, dev); - if (err) - goto err_out_async; - - priv->eq_table.have_irq = 1; - } - - err = mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0, - priv->eq_table.eq[MLX4_EQ_ASYNC].eqn); - if (err) - mlx4_warn(dev, "MAP_EQ for async EQ %d failed (%d)\n", - priv->eq_table.eq[MLX4_EQ_ASYNC].eqn, err); - - for (i = 0; i < MLX4_EQ_CATAS; ++i) - eq_set_ci(&priv->eq_table.eq[i], 1); - - if (dev->flags & MLX4_FLAG_MSI_X) { - err = mlx4_MAP_EQ(dev, MLX4_CATAS_EVENT_MASK, 0, - priv->eq_table.eq[MLX4_EQ_CATAS].eqn); - if (err) - mlx4_warn(dev, "MAP_EQ for catas EQ %d failed (%d)\n", - priv->eq_table.eq[MLX4_EQ_CATAS].eqn, err); - } - - return 0; - -err_out_catas: - mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_CATAS]); - -err_out_async: - mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_ASYNC]); - -err_out_comp: - mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_COMP]); - -err_out_unmap: - mlx4_unmap_clr_int(dev); - mlx4_free_irqs(dev); - -err_out_free: - mlx4_bitmap_cleanup(&priv->eq_table.bitmap); - return err; -} - -void mlx4_cleanup_eq_table(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int i; - - if (dev->flags & MLX4_FLAG_MSI_X) - mlx4_MAP_EQ(dev, MLX4_CATAS_EVENT_MASK, 1, - priv->eq_table.eq[MLX4_EQ_CATAS].eqn); - - mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 1, - priv->eq_table.eq[MLX4_EQ_ASYNC].eqn); - - mlx4_free_irqs(dev); - - for (i = 0; i < MLX4_EQ_CATAS; ++i) - mlx4_free_eq(dev, &priv->eq_table.eq[i]); - if (dev->flags & MLX4_FLAG_MSI_X) - mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_CATAS]); - - mlx4_unmap_clr_int(dev); - - for (i = 0; i < ARRAY_SIZE(priv->eq_table.uar_map); ++i) - if (priv->eq_table.uar_map[i]) - iounmap(priv->eq_table.uar_map[i]); - - mlx4_bitmap_cleanup(&priv->eq_table.bitmap); -} diff --git a/trunk/drivers/net/mlx4/fw.c b/trunk/drivers/net/mlx4/fw.c deleted file mode 100644 index c42717313663..000000000000 --- a/trunk/drivers/net/mlx4/fw.c +++ /dev/null @@ -1,775 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include "fw.h" -#include "icm.h" - -extern void __buggy_use_of_MLX4_GET(void); -extern void __buggy_use_of_MLX4_PUT(void); - -#define MLX4_GET(dest, source, offset) \ - do { \ - void *__p = (char *) (source) + (offset); \ - switch (sizeof (dest)) { \ - case 1: (dest) = *(u8 *) __p; break; \ - case 2: (dest) = be16_to_cpup(__p); break; \ - case 4: (dest) = be32_to_cpup(__p); break; \ - case 8: (dest) = be64_to_cpup(__p); break; \ - default: __buggy_use_of_MLX4_GET(); \ - } \ - } while (0) - -#define MLX4_PUT(dest, source, offset) \ - do { \ - void *__d = ((char *) (dest) + (offset)); \ - switch (sizeof(source)) { \ - case 1: *(u8 *) __d = (source); break; \ - case 2: *(__be16 *) __d = cpu_to_be16(source); break; \ - case 4: *(__be32 *) __d = cpu_to_be32(source); break; \ - case 8: *(__be64 *) __d = cpu_to_be64(source); break; \ - default: __buggy_use_of_MLX4_PUT(); \ - } \ - } while (0) - -static void dump_dev_cap_flags(struct mlx4_dev *dev, u32 flags) -{ - static const char *fname[] = { - [ 0] = "RC transport", - [ 1] = "UC transport", - [ 2] = "UD transport", - [ 3] = "SRC transport", - [ 4] = "reliable multicast", - [ 5] = "FCoIB support", - [ 6] = "SRQ support", - [ 7] = "IPoIB checksum offload", - [ 8] = "P_Key violation counter", - [ 9] = "Q_Key violation counter", - [10] = "VMM", - [16] = "MW support", - [17] = "APM support", - [18] = "Atomic ops support", - [19] = "Raw multicast support", - [20] = "Address vector port checking support", - [21] = "UD multicast support", - [24] = "Demand paging support", - [25] = "Router support" - }; - int i; - - mlx4_dbg(dev, "DEV_CAP flags:\n"); - for (i = 0; i < 32; ++i) - if (fname[i] && (flags & (1 << i))) - mlx4_dbg(dev, " %s\n", fname[i]); -} - -int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) -{ - struct mlx4_cmd_mailbox *mailbox; - u32 *outbox; - u8 field; - u16 size; - u16 stat_rate; - int err; - -#define QUERY_DEV_CAP_OUT_SIZE 0x100 -#define QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET 0x10 -#define QUERY_DEV_CAP_MAX_QP_SZ_OFFSET 0x11 -#define QUERY_DEV_CAP_RSVD_QP_OFFSET 0x12 -#define QUERY_DEV_CAP_MAX_QP_OFFSET 0x13 -#define QUERY_DEV_CAP_RSVD_SRQ_OFFSET 0x14 -#define QUERY_DEV_CAP_MAX_SRQ_OFFSET 0x15 -#define QUERY_DEV_CAP_RSVD_EEC_OFFSET 0x16 -#define QUERY_DEV_CAP_MAX_EEC_OFFSET 0x17 -#define QUERY_DEV_CAP_MAX_CQ_SZ_OFFSET 0x19 -#define QUERY_DEV_CAP_RSVD_CQ_OFFSET 0x1a -#define QUERY_DEV_CAP_MAX_CQ_OFFSET 0x1b -#define QUERY_DEV_CAP_MAX_MPT_OFFSET 0x1d -#define QUERY_DEV_CAP_RSVD_EQ_OFFSET 0x1e -#define QUERY_DEV_CAP_MAX_EQ_OFFSET 0x1f -#define QUERY_DEV_CAP_RSVD_MTT_OFFSET 0x20 -#define QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET 0x21 -#define QUERY_DEV_CAP_RSVD_MRW_OFFSET 0x22 -#define QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET 0x23 -#define QUERY_DEV_CAP_MAX_AV_OFFSET 0x27 -#define QUERY_DEV_CAP_MAX_REQ_QP_OFFSET 0x29 -#define QUERY_DEV_CAP_MAX_RES_QP_OFFSET 0x2b -#define QUERY_DEV_CAP_MAX_RDMA_OFFSET 0x2f -#define QUERY_DEV_CAP_RSZ_SRQ_OFFSET 0x33 -#define QUERY_DEV_CAP_ACK_DELAY_OFFSET 0x35 -#define QUERY_DEV_CAP_MTU_WIDTH_OFFSET 0x36 -#define QUERY_DEV_CAP_VL_PORT_OFFSET 0x37 -#define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b -#define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c -#define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f -#define QUERY_DEV_CAP_FLAGS_OFFSET 0x44 -#define QUERY_DEV_CAP_RSVD_UAR_OFFSET 0x48 -#define QUERY_DEV_CAP_UAR_SZ_OFFSET 0x49 -#define QUERY_DEV_CAP_PAGE_SZ_OFFSET 0x4b -#define QUERY_DEV_CAP_BF_OFFSET 0x4c -#define QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET 0x4d -#define QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET 0x4e -#define QUERY_DEV_CAP_LOG_MAX_BF_PAGES_OFFSET 0x4f -#define QUERY_DEV_CAP_MAX_SG_SQ_OFFSET 0x51 -#define QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET 0x52 -#define QUERY_DEV_CAP_MAX_SG_RQ_OFFSET 0x55 -#define QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET 0x56 -#define QUERY_DEV_CAP_MAX_QP_MCG_OFFSET 0x61 -#define QUERY_DEV_CAP_RSVD_MCG_OFFSET 0x62 -#define QUERY_DEV_CAP_MAX_MCG_OFFSET 0x63 -#define QUERY_DEV_CAP_RSVD_PD_OFFSET 0x64 -#define QUERY_DEV_CAP_MAX_PD_OFFSET 0x65 -#define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80 -#define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82 -#define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84 -#define QUERY_DEV_CAP_ALTC_ENTRY_SZ_OFFSET 0x86 -#define QUERY_DEV_CAP_EQC_ENTRY_SZ_OFFSET 0x88 -#define QUERY_DEV_CAP_CQC_ENTRY_SZ_OFFSET 0x8a -#define QUERY_DEV_CAP_SRQ_ENTRY_SZ_OFFSET 0x8c -#define QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET 0x8e -#define QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET 0x90 -#define QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET 0x92 -#define QUERY_DEV_CAP_BMME_FLAGS_OFFSET 0x97 -#define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98 -#define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0 - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - outbox = mailbox->buf; - - err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, - MLX4_CMD_TIME_CLASS_A); - - if (err) - goto out; - - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_QP_OFFSET); - dev_cap->reserved_qps = 1 << (field & 0xf); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_OFFSET); - dev_cap->max_qps = 1 << (field & 0x1f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_SRQ_OFFSET); - dev_cap->reserved_srqs = 1 << (field >> 4); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SRQ_OFFSET); - dev_cap->max_srqs = 1 << (field & 0x1f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_CQ_SZ_OFFSET); - dev_cap->max_cq_sz = 1 << field; - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_CQ_OFFSET); - dev_cap->reserved_cqs = 1 << (field & 0xf); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_CQ_OFFSET); - dev_cap->max_cqs = 1 << (field & 0x1f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MPT_OFFSET); - dev_cap->max_mpts = 1 << (field & 0x3f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_EQ_OFFSET); - dev_cap->reserved_eqs = 1 << (field & 0xf); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_EQ_OFFSET); - dev_cap->max_eqs = 1 << (field & 0x7); - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MTT_OFFSET); - dev_cap->reserved_mtts = 1 << (field >> 4); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET); - dev_cap->max_mrw_sz = 1 << field; - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MRW_OFFSET); - dev_cap->reserved_mrws = 1 << (field & 0xf); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MTT_SEG_OFFSET); - dev_cap->max_mtt_seg = 1 << (field & 0x3f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_REQ_QP_OFFSET); - dev_cap->max_requester_per_qp = 1 << (field & 0x3f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RES_QP_OFFSET); - dev_cap->max_responder_per_qp = 1 << (field & 0x3f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_RDMA_OFFSET); - dev_cap->max_rdma_global = 1 << (field & 0x3f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET); - dev_cap->local_ca_ack_delay = field & 0x1f; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET); - dev_cap->max_mtu = field >> 4; - dev_cap->max_port_width = field & 0xf; - MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET); - dev_cap->max_vl = field >> 4; - dev_cap->num_ports = field & 0xf; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET); - dev_cap->max_gids = 1 << (field & 0xf); - MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET); - dev_cap->stat_rate_support = stat_rate; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET); - dev_cap->max_pkeys = 1 << (field & 0xf); - MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET); - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET); - dev_cap->reserved_uars = field >> 4; - MLX4_GET(field, outbox, QUERY_DEV_CAP_UAR_SZ_OFFSET); - dev_cap->uar_size = 1 << ((field & 0x3f) + 20); - MLX4_GET(field, outbox, QUERY_DEV_CAP_PAGE_SZ_OFFSET); - dev_cap->min_page_sz = 1 << field; - - MLX4_GET(field, outbox, QUERY_DEV_CAP_BF_OFFSET); - if (field & 0x80) { - MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_BF_REG_SZ_OFFSET); - dev_cap->bf_reg_size = 1 << (field & 0x1f); - MLX4_GET(field, outbox, QUERY_DEV_CAP_LOG_MAX_BF_REGS_PER_PAGE_OFFSET); - dev_cap->bf_regs_per_page = 1 << (field & 0x3f); - mlx4_dbg(dev, "BlueFlame available (reg size %d, regs/page %d)\n", - dev_cap->bf_reg_size, dev_cap->bf_regs_per_page); - } else { - dev_cap->bf_reg_size = 0; - mlx4_dbg(dev, "BlueFlame not available\n"); - } - - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SG_SQ_OFFSET); - dev_cap->max_sq_sg = field; - MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_SQ_OFFSET); - dev_cap->max_sq_desc_sz = size; - - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_MCG_OFFSET); - dev_cap->max_qp_per_mcg = 1 << field; - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MCG_OFFSET); - dev_cap->reserved_mgms = field & 0xf; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MCG_OFFSET); - dev_cap->max_mcgs = 1 << field; - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_PD_OFFSET); - dev_cap->reserved_pds = field >> 4; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PD_OFFSET); - dev_cap->max_pds = 1 << (field & 0x3f); - - MLX4_GET(size, outbox, QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET); - dev_cap->rdmarc_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET); - dev_cap->qpc_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET); - dev_cap->aux_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_ALTC_ENTRY_SZ_OFFSET); - dev_cap->altc_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_EQC_ENTRY_SZ_OFFSET); - dev_cap->eqc_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_CQC_ENTRY_SZ_OFFSET); - dev_cap->cqc_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_SRQ_ENTRY_SZ_OFFSET); - dev_cap->srq_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_C_MPT_ENTRY_SZ_OFFSET); - dev_cap->cmpt_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_MTT_ENTRY_SZ_OFFSET); - dev_cap->mtt_entry_sz = size; - MLX4_GET(size, outbox, QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET); - dev_cap->dmpt_entry_sz = size; - - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET); - dev_cap->max_srq_sz = 1 << field; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_SZ_OFFSET); - dev_cap->max_qp_sz = 1 << field; - MLX4_GET(field, outbox, QUERY_DEV_CAP_RSZ_SRQ_OFFSET); - dev_cap->resize_srq = field & 1; - MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_SG_RQ_OFFSET); - dev_cap->max_rq_sg = field; - MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET); - dev_cap->max_rq_desc_sz = size; - - MLX4_GET(dev_cap->bmme_flags, outbox, - QUERY_DEV_CAP_BMME_FLAGS_OFFSET); - MLX4_GET(dev_cap->reserved_lkey, outbox, - QUERY_DEV_CAP_RSVD_LKEY_OFFSET); - MLX4_GET(dev_cap->max_icm_sz, outbox, - QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET); - - if (dev_cap->bmme_flags & 1) - mlx4_dbg(dev, "Base MM extensions: yes " - "(flags %d, rsvd L_Key %08x)\n", - dev_cap->bmme_flags, dev_cap->reserved_lkey); - else - mlx4_dbg(dev, "Base MM extensions: no\n"); - - /* - * Each UAR has 4 EQ doorbells; so if a UAR is reserved, then - * we can't use any EQs whose doorbell falls on that page, - * even if the EQ itself isn't reserved. - */ - dev_cap->reserved_eqs = max(dev_cap->reserved_uars * 4, - dev_cap->reserved_eqs); - - mlx4_dbg(dev, "Max ICM size %lld MB\n", - (unsigned long long) dev_cap->max_icm_sz >> 20); - mlx4_dbg(dev, "Max QPs: %d, reserved QPs: %d, entry size: %d\n", - dev_cap->max_qps, dev_cap->reserved_qps, dev_cap->qpc_entry_sz); - mlx4_dbg(dev, "Max SRQs: %d, reserved SRQs: %d, entry size: %d\n", - dev_cap->max_srqs, dev_cap->reserved_srqs, dev_cap->srq_entry_sz); - mlx4_dbg(dev, "Max CQs: %d, reserved CQs: %d, entry size: %d\n", - dev_cap->max_cqs, dev_cap->reserved_cqs, dev_cap->cqc_entry_sz); - mlx4_dbg(dev, "Max EQs: %d, reserved EQs: %d, entry size: %d\n", - dev_cap->max_eqs, dev_cap->reserved_eqs, dev_cap->eqc_entry_sz); - mlx4_dbg(dev, "reserved MPTs: %d, reserved MTTs: %d\n", - dev_cap->reserved_mrws, dev_cap->reserved_mtts); - mlx4_dbg(dev, "Max PDs: %d, reserved PDs: %d, reserved UARs: %d\n", - dev_cap->max_pds, dev_cap->reserved_pds, dev_cap->reserved_uars); - mlx4_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n", - dev_cap->max_pds, dev_cap->reserved_mgms); - mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n", - dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz); - mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n", - dev_cap->local_ca_ack_delay, 128 << dev_cap->max_mtu, - dev_cap->max_port_width); - mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n", - dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg); - mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n", - dev_cap->max_rq_desc_sz, dev_cap->max_rq_sg); - - dump_dev_cap_flags(dev, dev_cap->flags); - -out: - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} - -int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt) -{ - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_icm_iter iter; - __be64 *pages; - int lg; - int nent = 0; - int i; - int err = 0; - int ts = 0, tc = 0; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - memset(mailbox->buf, 0, MLX4_MAILBOX_SIZE); - pages = mailbox->buf; - - for (mlx4_icm_first(icm, &iter); - !mlx4_icm_last(&iter); - mlx4_icm_next(&iter)) { - /* - * We have to pass pages that are aligned to their - * size, so find the least significant 1 in the - * address or size and use that as our log2 size. - */ - lg = ffs(mlx4_icm_addr(&iter) | mlx4_icm_size(&iter)) - 1; - if (lg < MLX4_ICM_PAGE_SHIFT) { - mlx4_warn(dev, "Got FW area not aligned to %d (%llx/%lx).\n", - MLX4_ICM_PAGE_SIZE, - (unsigned long long) mlx4_icm_addr(&iter), - mlx4_icm_size(&iter)); - err = -EINVAL; - goto out; - } - - for (i = 0; i < mlx4_icm_size(&iter) >> lg; ++i) { - if (virt != -1) { - pages[nent * 2] = cpu_to_be64(virt); - virt += 1 << lg; - } - - pages[nent * 2 + 1] = - cpu_to_be64((mlx4_icm_addr(&iter) + (i << lg)) | - (lg - MLX4_ICM_PAGE_SHIFT)); - ts += 1 << (lg - 10); - ++tc; - - if (++nent == MLX4_MAILBOX_SIZE / 16) { - err = mlx4_cmd(dev, mailbox->dma, nent, 0, op, - MLX4_CMD_TIME_CLASS_B); - if (err) - goto out; - nent = 0; - } - } - } - - if (nent) - err = mlx4_cmd(dev, mailbox->dma, nent, 0, op, MLX4_CMD_TIME_CLASS_B); - if (err) - goto out; - - switch (op) { - case MLX4_CMD_MAP_FA: - mlx4_dbg(dev, "Mapped %d chunks/%d KB for FW.\n", tc, ts); - break; - case MLX4_CMD_MAP_ICM_AUX: - mlx4_dbg(dev, "Mapped %d chunks/%d KB for ICM aux.\n", tc, ts); - break; - case MLX4_CMD_MAP_ICM: - mlx4_dbg(dev, "Mapped %d chunks/%d KB at %llx for ICM.\n", - tc, ts, (unsigned long long) virt - (ts << 10)); - break; - } - -out: - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} - -int mlx4_MAP_FA(struct mlx4_dev *dev, struct mlx4_icm *icm) -{ - return mlx4_map_cmd(dev, MLX4_CMD_MAP_FA, icm, -1); -} - -int mlx4_UNMAP_FA(struct mlx4_dev *dev) -{ - return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_UNMAP_FA, MLX4_CMD_TIME_CLASS_B); -} - - -int mlx4_RUN_FW(struct mlx4_dev *dev) -{ - return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_RUN_FW, MLX4_CMD_TIME_CLASS_A); -} - -int mlx4_QUERY_FW(struct mlx4_dev *dev) -{ - struct mlx4_fw *fw = &mlx4_priv(dev)->fw; - struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; - struct mlx4_cmd_mailbox *mailbox; - u32 *outbox; - int err = 0; - u64 fw_ver; - u8 lg; - -#define QUERY_FW_OUT_SIZE 0x100 -#define QUERY_FW_VER_OFFSET 0x00 -#define QUERY_FW_MAX_CMD_OFFSET 0x0f -#define QUERY_FW_ERR_START_OFFSET 0x30 -#define QUERY_FW_ERR_SIZE_OFFSET 0x38 -#define QUERY_FW_ERR_BAR_OFFSET 0x3c - -#define QUERY_FW_SIZE_OFFSET 0x00 -#define QUERY_FW_CLR_INT_BASE_OFFSET 0x20 -#define QUERY_FW_CLR_INT_BAR_OFFSET 0x28 - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - outbox = mailbox->buf; - - err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_FW, - MLX4_CMD_TIME_CLASS_A); - if (err) - goto out; - - MLX4_GET(fw_ver, outbox, QUERY_FW_VER_OFFSET); - /* - * FW subminor version is at more signifant bits than minor - * version, so swap here. - */ - dev->caps.fw_ver = (fw_ver & 0xffff00000000ull) | - ((fw_ver & 0xffff0000ull) >> 16) | - ((fw_ver & 0x0000ffffull) << 16); - - MLX4_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET); - cmd->max_cmds = 1 << lg; - - mlx4_dbg(dev, "FW version %d.%d.%03d, max commands %d\n", - (int) (dev->caps.fw_ver >> 32), - (int) (dev->caps.fw_ver >> 16) & 0xffff, - (int) dev->caps.fw_ver & 0xffff, - cmd->max_cmds); - - MLX4_GET(fw->catas_offset, outbox, QUERY_FW_ERR_START_OFFSET); - MLX4_GET(fw->catas_size, outbox, QUERY_FW_ERR_SIZE_OFFSET); - MLX4_GET(fw->catas_bar, outbox, QUERY_FW_ERR_BAR_OFFSET); - fw->catas_bar = (fw->catas_bar >> 6) * 2; - - mlx4_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x, BAR %d\n", - (unsigned long long) fw->catas_offset, fw->catas_size, fw->catas_bar); - - MLX4_GET(fw->fw_pages, outbox, QUERY_FW_SIZE_OFFSET); - MLX4_GET(fw->clr_int_base, outbox, QUERY_FW_CLR_INT_BASE_OFFSET); - MLX4_GET(fw->clr_int_bar, outbox, QUERY_FW_CLR_INT_BAR_OFFSET); - fw->clr_int_bar = (fw->clr_int_bar >> 6) * 2; - - mlx4_dbg(dev, "FW size %d KB\n", fw->fw_pages >> 2); - - /* - * Round up number of system pages needed in case - * MLX4_ICM_PAGE_SIZE < PAGE_SIZE. - */ - fw->fw_pages = - ALIGN(fw->fw_pages, PAGE_SIZE / MLX4_ICM_PAGE_SIZE) >> - (PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT); - - mlx4_dbg(dev, "Clear int @ %llx, BAR %d\n", - (unsigned long long) fw->clr_int_base, fw->clr_int_bar); - -out: - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} - -static void get_board_id(void *vsd, char *board_id) -{ - int i; - -#define VSD_OFFSET_SIG1 0x00 -#define VSD_OFFSET_SIG2 0xde -#define VSD_OFFSET_MLX_BOARD_ID 0xd0 -#define VSD_OFFSET_TS_BOARD_ID 0x20 - -#define VSD_SIGNATURE_TOPSPIN 0x5ad - - memset(board_id, 0, MLX4_BOARD_ID_LEN); - - if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN && - be16_to_cpup(vsd + VSD_OFFSET_SIG2) == VSD_SIGNATURE_TOPSPIN) { - strlcpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MLX4_BOARD_ID_LEN); - } else { - /* - * The board ID is a string but the firmware byte - * swaps each 4-byte word before passing it back to - * us. Therefore we need to swab it before printing. - */ - for (i = 0; i < 4; ++i) - ((u32 *) board_id)[i] = - swab32(*(u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4)); - } -} - -int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter) -{ - struct mlx4_cmd_mailbox *mailbox; - u32 *outbox; - int err; - -#define QUERY_ADAPTER_OUT_SIZE 0x100 -#define QUERY_ADAPTER_VENDOR_ID_OFFSET 0x00 -#define QUERY_ADAPTER_DEVICE_ID_OFFSET 0x04 -#define QUERY_ADAPTER_REVISION_ID_OFFSET 0x08 -#define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10 -#define QUERY_ADAPTER_VSD_OFFSET 0x20 - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - outbox = mailbox->buf; - - err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_ADAPTER, - MLX4_CMD_TIME_CLASS_A); - if (err) - goto out; - - MLX4_GET(adapter->vendor_id, outbox, QUERY_ADAPTER_VENDOR_ID_OFFSET); - MLX4_GET(adapter->device_id, outbox, QUERY_ADAPTER_DEVICE_ID_OFFSET); - MLX4_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET); - MLX4_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET); - - get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4, - adapter->board_id); - -out: - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} - -int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) -{ - struct mlx4_cmd_mailbox *mailbox; - __be32 *inbox; - int err; - -#define INIT_HCA_IN_SIZE 0x200 -#define INIT_HCA_VERSION_OFFSET 0x000 -#define INIT_HCA_VERSION 2 -#define INIT_HCA_FLAGS_OFFSET 0x014 -#define INIT_HCA_QPC_OFFSET 0x020 -#define INIT_HCA_QPC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x10) -#define INIT_HCA_LOG_QP_OFFSET (INIT_HCA_QPC_OFFSET + 0x17) -#define INIT_HCA_SRQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x28) -#define INIT_HCA_LOG_SRQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x2f) -#define INIT_HCA_CQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x30) -#define INIT_HCA_LOG_CQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x37) -#define INIT_HCA_ALTC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x40) -#define INIT_HCA_AUXC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x50) -#define INIT_HCA_EQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x60) -#define INIT_HCA_LOG_EQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x67) -#define INIT_HCA_RDMARC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x70) -#define INIT_HCA_LOG_RD_OFFSET (INIT_HCA_QPC_OFFSET + 0x77) -#define INIT_HCA_MCAST_OFFSET 0x0c0 -#define INIT_HCA_MC_BASE_OFFSET (INIT_HCA_MCAST_OFFSET + 0x00) -#define INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12) -#define INIT_HCA_LOG_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x16) -#define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b) -#define INIT_HCA_TPT_OFFSET 0x0f0 -#define INIT_HCA_DMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00) -#define INIT_HCA_LOG_MPT_SZ_OFFSET (INIT_HCA_TPT_OFFSET + 0x0b) -#define INIT_HCA_MTT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x10) -#define INIT_HCA_CMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x18) -#define INIT_HCA_UAR_OFFSET 0x120 -#define INIT_HCA_LOG_UAR_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x0a) -#define INIT_HCA_UAR_PAGE_SZ_OFFSET (INIT_HCA_UAR_OFFSET + 0x0b) - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - inbox = mailbox->buf; - - memset(inbox, 0, INIT_HCA_IN_SIZE); - - *((u8 *) mailbox->buf + INIT_HCA_VERSION_OFFSET) = INIT_HCA_VERSION; - -#if defined(__LITTLE_ENDIAN) - *(inbox + INIT_HCA_FLAGS_OFFSET / 4) &= ~cpu_to_be32(1 << 1); -#elif defined(__BIG_ENDIAN) - *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1 << 1); -#else -#error Host endianness not defined -#endif - /* Check port for UD address vector: */ - *(inbox + INIT_HCA_FLAGS_OFFSET / 4) |= cpu_to_be32(1); - - /* QPC/EEC/CQC/EQC/RDMARC attributes */ - - MLX4_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET); - MLX4_PUT(inbox, param->log_num_qps, INIT_HCA_LOG_QP_OFFSET); - MLX4_PUT(inbox, param->srqc_base, INIT_HCA_SRQC_BASE_OFFSET); - MLX4_PUT(inbox, param->log_num_srqs, INIT_HCA_LOG_SRQ_OFFSET); - MLX4_PUT(inbox, param->cqc_base, INIT_HCA_CQC_BASE_OFFSET); - MLX4_PUT(inbox, param->log_num_cqs, INIT_HCA_LOG_CQ_OFFSET); - MLX4_PUT(inbox, param->altc_base, INIT_HCA_ALTC_BASE_OFFSET); - MLX4_PUT(inbox, param->auxc_base, INIT_HCA_AUXC_BASE_OFFSET); - MLX4_PUT(inbox, param->eqc_base, INIT_HCA_EQC_BASE_OFFSET); - MLX4_PUT(inbox, param->log_num_eqs, INIT_HCA_LOG_EQ_OFFSET); - MLX4_PUT(inbox, param->rdmarc_base, INIT_HCA_RDMARC_BASE_OFFSET); - MLX4_PUT(inbox, param->log_rd_per_qp, INIT_HCA_LOG_RD_OFFSET); - - /* multicast attributes */ - - MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET); - MLX4_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); - MLX4_PUT(inbox, param->log_mc_hash_sz, INIT_HCA_LOG_MC_HASH_SZ_OFFSET); - MLX4_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); - - /* TPT attributes */ - - MLX4_PUT(inbox, param->dmpt_base, INIT_HCA_DMPT_BASE_OFFSET); - MLX4_PUT(inbox, param->log_mpt_sz, INIT_HCA_LOG_MPT_SZ_OFFSET); - MLX4_PUT(inbox, param->mtt_base, INIT_HCA_MTT_BASE_OFFSET); - MLX4_PUT(inbox, param->cmpt_base, INIT_HCA_CMPT_BASE_OFFSET); - - /* UAR attributes */ - - MLX4_PUT(inbox, (u8) (PAGE_SHIFT - 12), INIT_HCA_UAR_PAGE_SZ_OFFSET); - MLX4_PUT(inbox, param->log_uar_sz, INIT_HCA_LOG_UAR_SZ_OFFSET); - - err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_INIT_HCA, 1000); - - if (err) - mlx4_err(dev, "INIT_HCA returns %d\n", err); - - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} - -int mlx4_INIT_PORT(struct mlx4_dev *dev, struct mlx4_init_port_param *param, int port) -{ - struct mlx4_cmd_mailbox *mailbox; - u32 *inbox; - int err; - u32 flags; - -#define INIT_PORT_IN_SIZE 256 -#define INIT_PORT_FLAGS_OFFSET 0x00 -#define INIT_PORT_FLAG_SIG (1 << 18) -#define INIT_PORT_FLAG_NG (1 << 17) -#define INIT_PORT_FLAG_G0 (1 << 16) -#define INIT_PORT_VL_SHIFT 4 -#define INIT_PORT_PORT_WIDTH_SHIFT 8 -#define INIT_PORT_MTU_OFFSET 0x04 -#define INIT_PORT_MAX_GID_OFFSET 0x06 -#define INIT_PORT_MAX_PKEY_OFFSET 0x0a -#define INIT_PORT_GUID0_OFFSET 0x10 -#define INIT_PORT_NODE_GUID_OFFSET 0x18 -#define INIT_PORT_SI_GUID_OFFSET 0x20 - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - inbox = mailbox->buf; - - memset(inbox, 0, INIT_PORT_IN_SIZE); - - flags = 0; - flags |= param->set_guid0 ? INIT_PORT_FLAG_G0 : 0; - flags |= param->set_node_guid ? INIT_PORT_FLAG_NG : 0; - flags |= param->set_si_guid ? INIT_PORT_FLAG_SIG : 0; - flags |= (param->vl_cap & 0xf) << INIT_PORT_VL_SHIFT; - flags |= (param->port_width_cap & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT; - MLX4_PUT(inbox, flags, INIT_PORT_FLAGS_OFFSET); - - MLX4_PUT(inbox, param->mtu, INIT_PORT_MTU_OFFSET); - MLX4_PUT(inbox, param->max_gid, INIT_PORT_MAX_GID_OFFSET); - MLX4_PUT(inbox, param->max_pkey, INIT_PORT_MAX_PKEY_OFFSET); - MLX4_PUT(inbox, param->guid0, INIT_PORT_GUID0_OFFSET); - MLX4_PUT(inbox, param->node_guid, INIT_PORT_NODE_GUID_OFFSET); - MLX4_PUT(inbox, param->si_guid, INIT_PORT_SI_GUID_OFFSET); - - err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT, - MLX4_CMD_TIME_CLASS_A); - - mlx4_free_cmd_mailbox(dev, mailbox); - - return err; -} -EXPORT_SYMBOL_GPL(mlx4_INIT_PORT); - -int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port) -{ - return mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 1000); -} -EXPORT_SYMBOL_GPL(mlx4_CLOSE_PORT); - -int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic) -{ - return mlx4_cmd(dev, 0, 0, panic, MLX4_CMD_CLOSE_HCA, 1000); -} - -int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages) -{ - int ret = mlx4_cmd_imm(dev, icm_size, aux_pages, 0, 0, - MLX4_CMD_SET_ICM_SIZE, - MLX4_CMD_TIME_CLASS_A); - if (ret) - return ret; - - /* - * Round up number of system pages needed in case - * MLX4_ICM_PAGE_SIZE < PAGE_SIZE. - */ - *aux_pages = ALIGN(*aux_pages, PAGE_SIZE / MLX4_ICM_PAGE_SIZE) >> - (PAGE_SHIFT - MLX4_ICM_PAGE_SHIFT); - - return 0; -} - -int mlx4_NOP(struct mlx4_dev *dev) -{ - /* Input modifier of 0x1f means "finish as soon as possible." */ - return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100); -} diff --git a/trunk/drivers/net/mlx4/fw.h b/trunk/drivers/net/mlx4/fw.h deleted file mode 100644 index 2616fa53d4d0..000000000000 --- a/trunk/drivers/net/mlx4/fw.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2006, 2007 Cisco Systems. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef MLX4_FW_H -#define MLX4_FW_H - -#include "mlx4.h" -#include "icm.h" - -struct mlx4_dev_cap { - int max_srq_sz; - int max_qp_sz; - int reserved_qps; - int max_qps; - int reserved_srqs; - int max_srqs; - int max_cq_sz; - int reserved_cqs; - int max_cqs; - int max_mpts; - int reserved_eqs; - int max_eqs; - int reserved_mtts; - int max_mrw_sz; - int reserved_mrws; - int max_mtt_seg; - int max_requester_per_qp; - int max_responder_per_qp; - int max_rdma_global; - int local_ca_ack_delay; - int max_mtu; - int max_port_width; - int max_vl; - int num_ports; - int max_gids; - u16 stat_rate_support; - int max_pkeys; - u32 flags; - int reserved_uars; - int uar_size; - int min_page_sz; - int bf_reg_size; - int bf_regs_per_page; - int max_sq_sg; - int max_sq_desc_sz; - int max_rq_sg; - int max_rq_desc_sz; - int max_qp_per_mcg; - int reserved_mgms; - int max_mcgs; - int reserved_pds; - int max_pds; - int qpc_entry_sz; - int rdmarc_entry_sz; - int altc_entry_sz; - int aux_entry_sz; - int srq_entry_sz; - int cqc_entry_sz; - int eqc_entry_sz; - int dmpt_entry_sz; - int cmpt_entry_sz; - int mtt_entry_sz; - int resize_srq; - u8 bmme_flags; - u32 reserved_lkey; - u64 max_icm_sz; -}; - -struct mlx4_adapter { - u32 vendor_id; - u32 device_id; - u32 revision_id; - char board_id[MLX4_BOARD_ID_LEN]; - u8 inta_pin; -}; - -struct mlx4_init_hca_param { - u64 qpc_base; - u64 rdmarc_base; - u64 auxc_base; - u64 altc_base; - u64 srqc_base; - u64 cqc_base; - u64 eqc_base; - u64 mc_base; - u64 dmpt_base; - u64 cmpt_base; - u64 mtt_base; - u16 log_mc_entry_sz; - u16 log_mc_hash_sz; - u8 log_num_qps; - u8 log_num_srqs; - u8 log_num_cqs; - u8 log_num_eqs; - u8 log_rd_per_qp; - u8 log_mc_table_sz; - u8 log_mpt_sz; - u8 log_uar_sz; -}; - -struct mlx4_init_ib_param { - int port_width; - int vl_cap; - int mtu_cap; - u16 gid_cap; - u16 pkey_cap; - int set_guid0; - u64 guid0; - int set_node_guid; - u64 node_guid; - int set_si_guid; - u64 si_guid; -}; - -struct mlx4_set_ib_param { - int set_si_guid; - int reset_qkey_viol; - u64 si_guid; - u32 cap_mask; -}; - -int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap); -int mlx4_MAP_FA(struct mlx4_dev *dev, struct mlx4_icm *icm); -int mlx4_UNMAP_FA(struct mlx4_dev *dev); -int mlx4_RUN_FW(struct mlx4_dev *dev); -int mlx4_QUERY_FW(struct mlx4_dev *dev); -int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter); -int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param); -int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic); -int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt); -int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages); -int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm); -int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev); -int mlx4_NOP(struct mlx4_dev *dev); - -#endif /* MLX4_FW_H */ diff --git a/trunk/drivers/net/mlx4/icm.c b/trunk/drivers/net/mlx4/icm.c deleted file mode 100644 index e96feaed6ed4..000000000000 --- a/trunk/drivers/net/mlx4/icm.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include - -#include "mlx4.h" -#include "icm.h" -#include "fw.h" - -/* - * We allocate in as big chunks as we can, up to a maximum of 256 KB - * per chunk. - */ -enum { - MLX4_ICM_ALLOC_SIZE = 1 << 18, - MLX4_TABLE_CHUNK_SIZE = 1 << 18 -}; - -void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm) -{ - struct mlx4_icm_chunk *chunk, *tmp; - int i; - - list_for_each_entry_safe(chunk, tmp, &icm->chunk_list, list) { - if (chunk->nsg > 0) - pci_unmap_sg(dev->pdev, chunk->mem, chunk->npages, - PCI_DMA_BIDIRECTIONAL); - - for (i = 0; i < chunk->npages; ++i) - __free_pages(chunk->mem[i].page, - get_order(chunk->mem[i].length)); - - kfree(chunk); - } - - kfree(icm); -} - -struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, - gfp_t gfp_mask) -{ - struct mlx4_icm *icm; - struct mlx4_icm_chunk *chunk = NULL; - int cur_order; - - icm = kmalloc(sizeof *icm, gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN)); - if (!icm) - return icm; - - icm->refcount = 0; - INIT_LIST_HEAD(&icm->chunk_list); - - cur_order = get_order(MLX4_ICM_ALLOC_SIZE); - - while (npages > 0) { - if (!chunk) { - chunk = kmalloc(sizeof *chunk, - gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN)); - if (!chunk) - goto fail; - - chunk->npages = 0; - chunk->nsg = 0; - list_add_tail(&chunk->list, &icm->chunk_list); - } - - while (1 << cur_order > npages) - --cur_order; - - chunk->mem[chunk->npages].page = alloc_pages(gfp_mask, cur_order); - if (chunk->mem[chunk->npages].page) { - chunk->mem[chunk->npages].length = PAGE_SIZE << cur_order; - chunk->mem[chunk->npages].offset = 0; - - if (++chunk->npages == MLX4_ICM_CHUNK_LEN) { - chunk->nsg = pci_map_sg(dev->pdev, chunk->mem, - chunk->npages, - PCI_DMA_BIDIRECTIONAL); - - if (chunk->nsg <= 0) - goto fail; - - chunk = NULL; - } - - npages -= 1 << cur_order; - } else { - --cur_order; - if (cur_order < 0) - goto fail; - } - } - - if (chunk) { - chunk->nsg = pci_map_sg(dev->pdev, chunk->mem, - chunk->npages, - PCI_DMA_BIDIRECTIONAL); - - if (chunk->nsg <= 0) - goto fail; - } - - return icm; - -fail: - mlx4_free_icm(dev, icm); - return NULL; -} - -static int mlx4_MAP_ICM(struct mlx4_dev *dev, struct mlx4_icm *icm, u64 virt) -{ - return mlx4_map_cmd(dev, MLX4_CMD_MAP_ICM, icm, virt); -} - -int mlx4_UNMAP_ICM(struct mlx4_dev *dev, u64 virt, u32 page_count) -{ - return mlx4_cmd(dev, virt, page_count, 0, MLX4_CMD_UNMAP_ICM, - MLX4_CMD_TIME_CLASS_B); -} - -int mlx4_MAP_ICM_page(struct mlx4_dev *dev, u64 dma_addr, u64 virt) -{ - struct mlx4_cmd_mailbox *mailbox; - __be64 *inbox; - int err; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - inbox = mailbox->buf; - - inbox[0] = cpu_to_be64(virt); - inbox[1] = cpu_to_be64(dma_addr); - - err = mlx4_cmd(dev, mailbox->dma, 1, 0, MLX4_CMD_MAP_ICM, - MLX4_CMD_TIME_CLASS_B); - - mlx4_free_cmd_mailbox(dev, mailbox); - - if (!err) - mlx4_dbg(dev, "Mapped page at %llx to %llx for ICM.\n", - (unsigned long long) dma_addr, (unsigned long long) virt); - - return err; -} - -int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm) -{ - return mlx4_map_cmd(dev, MLX4_CMD_MAP_ICM_AUX, icm, -1); -} - -int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev) -{ - return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_UNMAP_ICM_AUX, MLX4_CMD_TIME_CLASS_B); -} - -int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) -{ - int i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size); - int ret = 0; - - mutex_lock(&table->mutex); - - if (table->icm[i]) { - ++table->icm[i]->refcount; - goto out; - } - - table->icm[i] = mlx4_alloc_icm(dev, MLX4_TABLE_CHUNK_SIZE >> PAGE_SHIFT, - (table->lowmem ? GFP_KERNEL : GFP_HIGHUSER) | - __GFP_NOWARN); - if (!table->icm[i]) { - ret = -ENOMEM; - goto out; - } - - if (mlx4_MAP_ICM(dev, table->icm[i], table->virt + - (u64) i * MLX4_TABLE_CHUNK_SIZE)) { - mlx4_free_icm(dev, table->icm[i]); - table->icm[i] = NULL; - ret = -ENOMEM; - goto out; - } - - ++table->icm[i]->refcount; - -out: - mutex_unlock(&table->mutex); - return ret; -} - -void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) -{ - int i; - - i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size); - - mutex_lock(&table->mutex); - - if (--table->icm[i]->refcount == 0) { - mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE, - MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); - mlx4_free_icm(dev, table->icm[i]); - table->icm[i] = NULL; - } - - mutex_unlock(&table->mutex); -} - -void *mlx4_table_find(struct mlx4_icm_table *table, int obj) -{ - int idx, offset, i; - struct mlx4_icm_chunk *chunk; - struct mlx4_icm *icm; - struct page *page = NULL; - - if (!table->lowmem) - return NULL; - - mutex_lock(&table->mutex); - - idx = obj & (table->num_obj - 1); - icm = table->icm[idx / (MLX4_TABLE_CHUNK_SIZE / table->obj_size)]; - offset = idx % (MLX4_TABLE_CHUNK_SIZE / table->obj_size); - - if (!icm) - goto out; - - list_for_each_entry(chunk, &icm->chunk_list, list) { - for (i = 0; i < chunk->npages; ++i) { - if (chunk->mem[i].length > offset) { - page = chunk->mem[i].page; - goto out; - } - offset -= chunk->mem[i].length; - } - } - -out: - mutex_unlock(&table->mutex); - return page ? lowmem_page_address(page) + offset : NULL; -} - -int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - int start, int end) -{ - int inc = MLX4_TABLE_CHUNK_SIZE / table->obj_size; - int i, err; - - for (i = start; i <= end; i += inc) { - err = mlx4_table_get(dev, table, i); - if (err) - goto fail; - } - - return 0; - -fail: - while (i > start) { - i -= inc; - mlx4_table_put(dev, table, i); - } - - return err; -} - -void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - int start, int end) -{ - int i; - - for (i = start; i <= end; i += MLX4_TABLE_CHUNK_SIZE / table->obj_size) - mlx4_table_put(dev, table, i); -} - -int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u64 virt, int obj_size, int nobj, int reserved, - int use_lowmem) -{ - int obj_per_chunk; - int num_icm; - unsigned chunk_size; - int i; - - obj_per_chunk = MLX4_TABLE_CHUNK_SIZE / obj_size; - num_icm = (nobj + obj_per_chunk - 1) / obj_per_chunk; - - table->icm = kcalloc(num_icm, sizeof *table->icm, GFP_KERNEL); - if (!table->icm) - return -ENOMEM; - table->virt = virt; - table->num_icm = num_icm; - table->num_obj = nobj; - table->obj_size = obj_size; - table->lowmem = use_lowmem; - mutex_init(&table->mutex); - - for (i = 0; i * MLX4_TABLE_CHUNK_SIZE < reserved * obj_size; ++i) { - chunk_size = MLX4_TABLE_CHUNK_SIZE; - if ((i + 1) * MLX4_TABLE_CHUNK_SIZE > nobj * obj_size) - chunk_size = PAGE_ALIGN(nobj * obj_size - i * MLX4_TABLE_CHUNK_SIZE); - - table->icm[i] = mlx4_alloc_icm(dev, chunk_size >> PAGE_SHIFT, - (use_lowmem ? GFP_KERNEL : GFP_HIGHUSER) | - __GFP_NOWARN); - if (!table->icm[i]) - goto err; - if (mlx4_MAP_ICM(dev, table->icm[i], virt + i * MLX4_TABLE_CHUNK_SIZE)) { - mlx4_free_icm(dev, table->icm[i]); - table->icm[i] = NULL; - goto err; - } - - /* - * Add a reference to this ICM chunk so that it never - * gets freed (since it contains reserved firmware objects). - */ - ++table->icm[i]->refcount; - } - - return 0; - -err: - for (i = 0; i < num_icm; ++i) - if (table->icm[i]) { - mlx4_UNMAP_ICM(dev, virt + i * MLX4_TABLE_CHUNK_SIZE, - MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); - mlx4_free_icm(dev, table->icm[i]); - } - - return -ENOMEM; -} - -void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table) -{ - int i; - - for (i = 0; i < table->num_icm; ++i) - if (table->icm[i]) { - mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE, - MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); - mlx4_free_icm(dev, table->icm[i]); - } - - kfree(table->icm); -} diff --git a/trunk/drivers/net/mlx4/icm.h b/trunk/drivers/net/mlx4/icm.h deleted file mode 100644 index bea223d879a5..000000000000 --- a/trunk/drivers/net/mlx4/icm.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef MLX4_ICM_H -#define MLX4_ICM_H - -#include -#include -#include - -#define MLX4_ICM_CHUNK_LEN \ - ((256 - sizeof (struct list_head) - 2 * sizeof (int)) / \ - (sizeof (struct scatterlist))) - -enum { - MLX4_ICM_PAGE_SHIFT = 12, - MLX4_ICM_PAGE_SIZE = 1 << MLX4_ICM_PAGE_SHIFT, -}; - -struct mlx4_icm_chunk { - struct list_head list; - int npages; - int nsg; - struct scatterlist mem[MLX4_ICM_CHUNK_LEN]; -}; - -struct mlx4_icm { - struct list_head chunk_list; - int refcount; -}; - -struct mlx4_icm_iter { - struct mlx4_icm *icm; - struct mlx4_icm_chunk *chunk; - int page_idx; -}; - -struct mlx4_dev; - -struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, gfp_t gfp_mask); -void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm); - -int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); -void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); -int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - int start, int end); -void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - int start, int end); -int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, - u64 virt, int obj_size, int nobj, int reserved, - int use_lowmem); -void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table); -int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); -void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); -void *mlx4_table_find(struct mlx4_icm_table *table, int obj); -int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - int start, int end); -void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, - int start, int end); - -static inline void mlx4_icm_first(struct mlx4_icm *icm, - struct mlx4_icm_iter *iter) -{ - iter->icm = icm; - iter->chunk = list_empty(&icm->chunk_list) ? - NULL : list_entry(icm->chunk_list.next, - struct mlx4_icm_chunk, list); - iter->page_idx = 0; -} - -static inline int mlx4_icm_last(struct mlx4_icm_iter *iter) -{ - return !iter->chunk; -} - -static inline void mlx4_icm_next(struct mlx4_icm_iter *iter) -{ - if (++iter->page_idx >= iter->chunk->nsg) { - if (iter->chunk->list.next == &iter->icm->chunk_list) { - iter->chunk = NULL; - return; - } - - iter->chunk = list_entry(iter->chunk->list.next, - struct mlx4_icm_chunk, list); - iter->page_idx = 0; - } -} - -static inline dma_addr_t mlx4_icm_addr(struct mlx4_icm_iter *iter) -{ - return sg_dma_address(&iter->chunk->mem[iter->page_idx]); -} - -static inline unsigned long mlx4_icm_size(struct mlx4_icm_iter *iter) -{ - return sg_dma_len(&iter->chunk->mem[iter->page_idx]); -} - -int mlx4_UNMAP_ICM(struct mlx4_dev *dev, u64 virt, u32 page_count); -int mlx4_MAP_ICM_page(struct mlx4_dev *dev, u64 dma_addr, u64 virt); -int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm); -int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev); - -#endif /* MLX4_ICM_H */ diff --git a/trunk/drivers/net/mlx4/intf.c b/trunk/drivers/net/mlx4/intf.c deleted file mode 100644 index 65854f9e9c76..000000000000 --- a/trunk/drivers/net/mlx4/intf.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include "mlx4.h" - -struct mlx4_device_context { - struct list_head list; - struct mlx4_interface *intf; - void *context; -}; - -static LIST_HEAD(intf_list); -static LIST_HEAD(dev_list); -static DEFINE_MUTEX(intf_mutex); - -static void mlx4_add_device(struct mlx4_interface *intf, struct mlx4_priv *priv) -{ - struct mlx4_device_context *dev_ctx; - - dev_ctx = kmalloc(sizeof *dev_ctx, GFP_KERNEL); - if (!dev_ctx) - return; - - dev_ctx->intf = intf; - dev_ctx->context = intf->add(&priv->dev); - - if (dev_ctx->context) { - spin_lock_irq(&priv->ctx_lock); - list_add_tail(&dev_ctx->list, &priv->ctx_list); - spin_unlock_irq(&priv->ctx_lock); - } else - kfree(dev_ctx); -} - -static void mlx4_remove_device(struct mlx4_interface *intf, struct mlx4_priv *priv) -{ - struct mlx4_device_context *dev_ctx; - - list_for_each_entry(dev_ctx, &priv->ctx_list, list) - if (dev_ctx->intf == intf) { - spin_lock_irq(&priv->ctx_lock); - list_del(&dev_ctx->list); - spin_unlock_irq(&priv->ctx_lock); - - intf->remove(&priv->dev, dev_ctx->context); - kfree(dev_ctx); - return; - } -} - -int mlx4_register_interface(struct mlx4_interface *intf) -{ - struct mlx4_priv *priv; - - if (!intf->add || !intf->remove) - return -EINVAL; - - mutex_lock(&intf_mutex); - - list_add_tail(&intf->list, &intf_list); - list_for_each_entry(priv, &dev_list, dev_list) - mlx4_add_device(intf, priv); - - mutex_unlock(&intf_mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(mlx4_register_interface); - -void mlx4_unregister_interface(struct mlx4_interface *intf) -{ - struct mlx4_priv *priv; - - mutex_lock(&intf_mutex); - - list_for_each_entry(priv, &dev_list, dev_list) - mlx4_remove_device(intf, priv); - - list_del(&intf->list); - - mutex_unlock(&intf_mutex); -} -EXPORT_SYMBOL_GPL(mlx4_unregister_interface); - -void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_event type, - int subtype, int port) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_device_context *dev_ctx; - unsigned long flags; - - spin_lock_irqsave(&priv->ctx_lock, flags); - - list_for_each_entry(dev_ctx, &priv->ctx_list, list) - if (dev_ctx->intf->event) - dev_ctx->intf->event(dev, dev_ctx->context, type, - subtype, port); - - spin_unlock_irqrestore(&priv->ctx_lock, flags); -} - -int mlx4_register_device(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_interface *intf; - - INIT_LIST_HEAD(&priv->ctx_list); - spin_lock_init(&priv->ctx_lock); - - mutex_lock(&intf_mutex); - - list_add_tail(&priv->dev_list, &dev_list); - list_for_each_entry(intf, &intf_list, list) - mlx4_add_device(intf, priv); - - mutex_unlock(&intf_mutex); - - return 0; -} - -void mlx4_unregister_device(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_interface *intf; - - mutex_lock(&intf_mutex); - - list_for_each_entry(intf, &intf_list, list) - mlx4_remove_device(intf, priv); - - list_del(&priv->dev_list); - - mutex_unlock(&intf_mutex); -} diff --git a/trunk/drivers/net/mlx4/main.c b/trunk/drivers/net/mlx4/main.c deleted file mode 100644 index 4debb024eaf9..000000000000 --- a/trunk/drivers/net/mlx4/main.c +++ /dev/null @@ -1,936 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include "mlx4.h" -#include "fw.h" -#include "icm.h" - -MODULE_AUTHOR("Roland Dreier"); -MODULE_DESCRIPTION("Mellanox ConnectX HCA low-level driver"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION(DRV_VERSION); - -#ifdef CONFIG_MLX4_DEBUG - -int mlx4_debug_level = 0; -module_param_named(debug_level, mlx4_debug_level, int, 0644); -MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0"); - -#endif /* CONFIG_MLX4_DEBUG */ - -#ifdef CONFIG_PCI_MSI - -static int msi_x; -module_param(msi_x, int, 0444); -MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero"); - -#else /* CONFIG_PCI_MSI */ - -#define msi_x (0) - -#endif /* CONFIG_PCI_MSI */ - -static const char mlx4_version[] __devinitdata = - DRV_NAME ": Mellanox ConnectX core driver v" - DRV_VERSION " (" DRV_RELDATE ")\n"; - -static struct mlx4_profile default_profile = { - .num_qp = 1 << 16, - .num_srq = 1 << 16, - .rdmarc_per_qp = 4, - .num_cq = 1 << 16, - .num_mcg = 1 << 13, - .num_mpt = 1 << 17, - .num_mtt = 1 << 20, -}; - -static int __devinit mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) -{ - int err; - - err = mlx4_QUERY_DEV_CAP(dev, dev_cap); - if (err) { - mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n"); - return err; - } - - if (dev_cap->min_page_sz > PAGE_SIZE) { - mlx4_err(dev, "HCA minimum page size of %d bigger than " - "kernel PAGE_SIZE of %ld, aborting.\n", - dev_cap->min_page_sz, PAGE_SIZE); - return -ENODEV; - } - if (dev_cap->num_ports > MLX4_MAX_PORTS) { - mlx4_err(dev, "HCA has %d ports, but we only support %d, " - "aborting.\n", - dev_cap->num_ports, MLX4_MAX_PORTS); - return -ENODEV; - } - - if (dev_cap->uar_size > pci_resource_len(dev->pdev, 2)) { - mlx4_err(dev, "HCA reported UAR size of 0x%x bigger than " - "PCI resource 2 size of 0x%llx, aborting.\n", - dev_cap->uar_size, - (unsigned long long) pci_resource_len(dev->pdev, 2)); - return -ENODEV; - } - - dev->caps.num_ports = dev_cap->num_ports; - dev->caps.num_uars = dev_cap->uar_size / PAGE_SIZE; - dev->caps.vl_cap = dev_cap->max_vl; - dev->caps.mtu_cap = dev_cap->max_mtu; - dev->caps.gid_table_len = dev_cap->max_gids; - dev->caps.pkey_table_len = dev_cap->max_pkeys; - dev->caps.local_ca_ack_delay = dev_cap->local_ca_ack_delay; - dev->caps.bf_reg_size = dev_cap->bf_reg_size; - dev->caps.bf_regs_per_page = dev_cap->bf_regs_per_page; - dev->caps.max_sq_sg = dev_cap->max_sq_sg; - dev->caps.max_rq_sg = dev_cap->max_rq_sg; - dev->caps.max_wqes = dev_cap->max_qp_sz; - dev->caps.max_qp_init_rdma = dev_cap->max_requester_per_qp; - dev->caps.reserved_qps = dev_cap->reserved_qps; - dev->caps.max_srq_wqes = dev_cap->max_srq_sz; - dev->caps.max_srq_sge = dev_cap->max_rq_sg - 1; - dev->caps.reserved_srqs = dev_cap->reserved_srqs; - dev->caps.max_sq_desc_sz = dev_cap->max_sq_desc_sz; - dev->caps.max_rq_desc_sz = dev_cap->max_rq_desc_sz; - dev->caps.num_qp_per_mgm = MLX4_QP_PER_MGM; - /* - * Subtract 1 from the limit because we need to allocate a - * spare CQE so the HCA HW can tell the difference between an - * empty CQ and a full CQ. - */ - dev->caps.max_cqes = dev_cap->max_cq_sz - 1; - dev->caps.reserved_cqs = dev_cap->reserved_cqs; - dev->caps.reserved_eqs = dev_cap->reserved_eqs; - dev->caps.reserved_mtts = dev_cap->reserved_mtts; - dev->caps.reserved_mrws = dev_cap->reserved_mrws; - dev->caps.reserved_uars = dev_cap->reserved_uars; - dev->caps.reserved_pds = dev_cap->reserved_pds; - dev->caps.port_width_cap = dev_cap->max_port_width; - dev->caps.mtt_entry_sz = MLX4_MTT_ENTRY_PER_SEG * dev_cap->mtt_entry_sz; - dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1); - dev->caps.flags = dev_cap->flags; - dev->caps.stat_rate_support = dev_cap->stat_rate_support; - - return 0; -} - -static int __devinit mlx4_load_fw(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int err; - - priv->fw.fw_icm = mlx4_alloc_icm(dev, priv->fw.fw_pages, - GFP_HIGHUSER | __GFP_NOWARN); - if (!priv->fw.fw_icm) { - mlx4_err(dev, "Couldn't allocate FW area, aborting.\n"); - return -ENOMEM; - } - - err = mlx4_MAP_FA(dev, priv->fw.fw_icm); - if (err) { - mlx4_err(dev, "MAP_FA command failed, aborting.\n"); - goto err_free; - } - - err = mlx4_RUN_FW(dev); - if (err) { - mlx4_err(dev, "RUN_FW command failed, aborting.\n"); - goto err_unmap_fa; - } - - return 0; - -err_unmap_fa: - mlx4_UNMAP_FA(dev); - -err_free: - mlx4_free_icm(dev, priv->fw.fw_icm); - return err; -} - -static int __devinit mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base, - int cmpt_entry_sz) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int err; - - err = mlx4_init_icm_table(dev, &priv->qp_table.cmpt_table, - cmpt_base + - ((u64) (MLX4_CMPT_TYPE_QP * - cmpt_entry_sz) << MLX4_CMPT_SHIFT), - cmpt_entry_sz, dev->caps.num_qps, - dev->caps.reserved_qps, 0); - if (err) - goto err; - - err = mlx4_init_icm_table(dev, &priv->srq_table.cmpt_table, - cmpt_base + - ((u64) (MLX4_CMPT_TYPE_SRQ * - cmpt_entry_sz) << MLX4_CMPT_SHIFT), - cmpt_entry_sz, dev->caps.num_srqs, - dev->caps.reserved_srqs, 0); - if (err) - goto err_qp; - - err = mlx4_init_icm_table(dev, &priv->cq_table.cmpt_table, - cmpt_base + - ((u64) (MLX4_CMPT_TYPE_CQ * - cmpt_entry_sz) << MLX4_CMPT_SHIFT), - cmpt_entry_sz, dev->caps.num_cqs, - dev->caps.reserved_cqs, 0); - if (err) - goto err_srq; - - err = mlx4_init_icm_table(dev, &priv->eq_table.cmpt_table, - cmpt_base + - ((u64) (MLX4_CMPT_TYPE_EQ * - cmpt_entry_sz) << MLX4_CMPT_SHIFT), - cmpt_entry_sz, - roundup_pow_of_two(MLX4_NUM_EQ + - dev->caps.reserved_eqs), - MLX4_NUM_EQ + dev->caps.reserved_eqs, 0); - if (err) - goto err_cq; - - return 0; - -err_cq: - mlx4_cleanup_icm_table(dev, &priv->cq_table.cmpt_table); - -err_srq: - mlx4_cleanup_icm_table(dev, &priv->srq_table.cmpt_table); - -err_qp: - mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table); - -err: - return err; -} - -static int __devinit mlx4_init_icm(struct mlx4_dev *dev, - struct mlx4_dev_cap *dev_cap, - struct mlx4_init_hca_param *init_hca, - u64 icm_size) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - u64 aux_pages; - int err; - - err = mlx4_SET_ICM_SIZE(dev, icm_size, &aux_pages); - if (err) { - mlx4_err(dev, "SET_ICM_SIZE command failed, aborting.\n"); - return err; - } - - mlx4_dbg(dev, "%lld KB of HCA context requires %lld KB aux memory.\n", - (unsigned long long) icm_size >> 10, - (unsigned long long) aux_pages << 2); - - priv->fw.aux_icm = mlx4_alloc_icm(dev, aux_pages, - GFP_HIGHUSER | __GFP_NOWARN); - if (!priv->fw.aux_icm) { - mlx4_err(dev, "Couldn't allocate aux memory, aborting.\n"); - return -ENOMEM; - } - - err = mlx4_MAP_ICM_AUX(dev, priv->fw.aux_icm); - if (err) { - mlx4_err(dev, "MAP_ICM_AUX command failed, aborting.\n"); - goto err_free_aux; - } - - err = mlx4_init_cmpt_table(dev, init_hca->cmpt_base, dev_cap->cmpt_entry_sz); - if (err) { - mlx4_err(dev, "Failed to map cMPT context memory, aborting.\n"); - goto err_unmap_aux; - } - - err = mlx4_map_eq_icm(dev, init_hca->eqc_base); - if (err) { - mlx4_err(dev, "Failed to map EQ context memory, aborting.\n"); - goto err_unmap_cmpt; - } - - err = mlx4_init_icm_table(dev, &priv->mr_table.mtt_table, - init_hca->mtt_base, - dev->caps.mtt_entry_sz, - dev->caps.num_mtt_segs, - dev->caps.reserved_mtts, 1); - if (err) { - mlx4_err(dev, "Failed to map MTT context memory, aborting.\n"); - goto err_unmap_eq; - } - - err = mlx4_init_icm_table(dev, &priv->mr_table.dmpt_table, - init_hca->dmpt_base, - dev_cap->dmpt_entry_sz, - dev->caps.num_mpts, - dev->caps.reserved_mrws, 1); - if (err) { - mlx4_err(dev, "Failed to map dMPT context memory, aborting.\n"); - goto err_unmap_mtt; - } - - err = mlx4_init_icm_table(dev, &priv->qp_table.qp_table, - init_hca->qpc_base, - dev_cap->qpc_entry_sz, - dev->caps.num_qps, - dev->caps.reserved_qps, 0); - if (err) { - mlx4_err(dev, "Failed to map QP context memory, aborting.\n"); - goto err_unmap_dmpt; - } - - err = mlx4_init_icm_table(dev, &priv->qp_table.auxc_table, - init_hca->auxc_base, - dev_cap->aux_entry_sz, - dev->caps.num_qps, - dev->caps.reserved_qps, 0); - if (err) { - mlx4_err(dev, "Failed to map AUXC context memory, aborting.\n"); - goto err_unmap_qp; - } - - err = mlx4_init_icm_table(dev, &priv->qp_table.altc_table, - init_hca->altc_base, - dev_cap->altc_entry_sz, - dev->caps.num_qps, - dev->caps.reserved_qps, 0); - if (err) { - mlx4_err(dev, "Failed to map ALTC context memory, aborting.\n"); - goto err_unmap_auxc; - } - - err = mlx4_init_icm_table(dev, &priv->qp_table.rdmarc_table, - init_hca->rdmarc_base, - dev_cap->rdmarc_entry_sz << priv->qp_table.rdmarc_shift, - dev->caps.num_qps, - dev->caps.reserved_qps, 0); - if (err) { - mlx4_err(dev, "Failed to map RDMARC context memory, aborting\n"); - goto err_unmap_altc; - } - - err = mlx4_init_icm_table(dev, &priv->cq_table.table, - init_hca->cqc_base, - dev_cap->cqc_entry_sz, - dev->caps.num_cqs, - dev->caps.reserved_cqs, 0); - if (err) { - mlx4_err(dev, "Failed to map CQ context memory, aborting.\n"); - goto err_unmap_rdmarc; - } - - err = mlx4_init_icm_table(dev, &priv->srq_table.table, - init_hca->srqc_base, - dev_cap->srq_entry_sz, - dev->caps.num_srqs, - dev->caps.reserved_srqs, 0); - if (err) { - mlx4_err(dev, "Failed to map SRQ context memory, aborting.\n"); - goto err_unmap_cq; - } - - /* - * It's not strictly required, but for simplicity just map the - * whole multicast group table now. The table isn't very big - * and it's a lot easier than trying to track ref counts. - */ - err = mlx4_init_icm_table(dev, &priv->mcg_table.table, - init_hca->mc_base, MLX4_MGM_ENTRY_SIZE, - dev->caps.num_mgms + dev->caps.num_amgms, - dev->caps.num_mgms + dev->caps.num_amgms, - 0); - if (err) { - mlx4_err(dev, "Failed to map MCG context memory, aborting.\n"); - goto err_unmap_srq; - } - - return 0; - -err_unmap_srq: - mlx4_cleanup_icm_table(dev, &priv->srq_table.table); - -err_unmap_cq: - mlx4_cleanup_icm_table(dev, &priv->cq_table.table); - -err_unmap_rdmarc: - mlx4_cleanup_icm_table(dev, &priv->qp_table.rdmarc_table); - -err_unmap_altc: - mlx4_cleanup_icm_table(dev, &priv->qp_table.altc_table); - -err_unmap_auxc: - mlx4_cleanup_icm_table(dev, &priv->qp_table.auxc_table); - -err_unmap_qp: - mlx4_cleanup_icm_table(dev, &priv->qp_table.qp_table); - -err_unmap_dmpt: - mlx4_cleanup_icm_table(dev, &priv->mr_table.dmpt_table); - -err_unmap_mtt: - mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table); - -err_unmap_eq: - mlx4_unmap_eq_icm(dev); - -err_unmap_cmpt: - mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table); - mlx4_cleanup_icm_table(dev, &priv->cq_table.cmpt_table); - mlx4_cleanup_icm_table(dev, &priv->srq_table.cmpt_table); - mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table); - -err_unmap_aux: - mlx4_UNMAP_ICM_AUX(dev); - -err_free_aux: - mlx4_free_icm(dev, priv->fw.aux_icm); - - return err; -} - -static void mlx4_free_icms(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - mlx4_cleanup_icm_table(dev, &priv->mcg_table.table); - mlx4_cleanup_icm_table(dev, &priv->srq_table.table); - mlx4_cleanup_icm_table(dev, &priv->cq_table.table); - mlx4_cleanup_icm_table(dev, &priv->qp_table.rdmarc_table); - mlx4_cleanup_icm_table(dev, &priv->qp_table.altc_table); - mlx4_cleanup_icm_table(dev, &priv->qp_table.auxc_table); - mlx4_cleanup_icm_table(dev, &priv->qp_table.qp_table); - mlx4_cleanup_icm_table(dev, &priv->mr_table.dmpt_table); - mlx4_cleanup_icm_table(dev, &priv->mr_table.mtt_table); - mlx4_cleanup_icm_table(dev, &priv->eq_table.cmpt_table); - mlx4_cleanup_icm_table(dev, &priv->cq_table.cmpt_table); - mlx4_cleanup_icm_table(dev, &priv->srq_table.cmpt_table); - mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table); - mlx4_unmap_eq_icm(dev); - - mlx4_UNMAP_ICM_AUX(dev); - mlx4_free_icm(dev, priv->fw.aux_icm); -} - -static void mlx4_close_hca(struct mlx4_dev *dev) -{ - mlx4_CLOSE_HCA(dev, 0); - mlx4_free_icms(dev); - mlx4_UNMAP_FA(dev); - mlx4_free_icm(dev, mlx4_priv(dev)->fw.fw_icm); -} - -static int __devinit mlx4_init_hca(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_adapter adapter; - struct mlx4_dev_cap dev_cap; - struct mlx4_profile profile; - struct mlx4_init_hca_param init_hca; - u64 icm_size; - int err; - - err = mlx4_QUERY_FW(dev); - if (err) { - mlx4_err(dev, "QUERY_FW command failed, aborting.\n"); - return err; - } - - err = mlx4_load_fw(dev); - if (err) { - mlx4_err(dev, "Failed to start FW, aborting.\n"); - return err; - } - - err = mlx4_dev_cap(dev, &dev_cap); - if (err) { - mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n"); - goto err_stop_fw; - } - - profile = default_profile; - - icm_size = mlx4_make_profile(dev, &profile, &dev_cap, &init_hca); - if ((long long) icm_size < 0) { - err = icm_size; - goto err_stop_fw; - } - - init_hca.log_uar_sz = ilog2(dev->caps.num_uars); - - err = mlx4_init_icm(dev, &dev_cap, &init_hca, icm_size); - if (err) - goto err_stop_fw; - - err = mlx4_INIT_HCA(dev, &init_hca); - if (err) { - mlx4_err(dev, "INIT_HCA command failed, aborting.\n"); - goto err_free_icm; - } - - err = mlx4_QUERY_ADAPTER(dev, &adapter); - if (err) { - mlx4_err(dev, "QUERY_ADAPTER command failed, aborting.\n"); - goto err_close; - } - - priv->eq_table.inta_pin = adapter.inta_pin; - priv->rev_id = adapter.revision_id; - memcpy(priv->board_id, adapter.board_id, sizeof priv->board_id); - - return 0; - -err_close: - mlx4_close_hca(dev); - -err_free_icm: - mlx4_free_icms(dev); - -err_stop_fw: - mlx4_UNMAP_FA(dev); - mlx4_free_icm(dev, priv->fw.fw_icm); - - return err; -} - -static int __devinit mlx4_setup_hca(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int err; - - MLX4_INIT_DOORBELL_LOCK(&priv->doorbell_lock); - - err = mlx4_init_uar_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "user access region table, aborting.\n"); - return err; - } - - err = mlx4_uar_alloc(dev, &priv->driver_uar); - if (err) { - mlx4_err(dev, "Failed to allocate driver access region, " - "aborting.\n"); - goto err_uar_table_free; - } - - priv->kar = ioremap(priv->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE); - if (!priv->kar) { - mlx4_err(dev, "Couldn't map kernel access region, " - "aborting.\n"); - err = -ENOMEM; - goto err_uar_free; - } - - err = mlx4_init_pd_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "protection domain table, aborting.\n"); - goto err_kar_unmap; - } - - err = mlx4_init_mr_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "memory region table, aborting.\n"); - goto err_pd_table_free; - } - - mlx4_map_catas_buf(dev); - - err = mlx4_init_eq_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "event queue table, aborting.\n"); - goto err_catas_buf; - } - - err = mlx4_cmd_use_events(dev); - if (err) { - mlx4_err(dev, "Failed to switch to event-driven " - "firmware commands, aborting.\n"); - goto err_eq_table_free; - } - - err = mlx4_NOP(dev); - if (err) { - mlx4_err(dev, "NOP command failed to generate interrupt " - "(IRQ %d), aborting.\n", - priv->eq_table.eq[MLX4_EQ_ASYNC].irq); - if (dev->flags & MLX4_FLAG_MSI_X) - mlx4_err(dev, "Try again with MSI-X disabled.\n"); - else - mlx4_err(dev, "BIOS or ACPI interrupt routing problem?\n"); - - goto err_cmd_poll; - } - - mlx4_dbg(dev, "NOP command IRQ test passed\n"); - - err = mlx4_init_cq_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "completion queue table, aborting.\n"); - goto err_cmd_poll; - } - - err = mlx4_init_srq_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "shared receive queue table, aborting.\n"); - goto err_cq_table_free; - } - - err = mlx4_init_qp_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "queue pair table, aborting.\n"); - goto err_srq_table_free; - } - - err = mlx4_init_mcg_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "multicast group table, aborting.\n"); - goto err_qp_table_free; - } - - return 0; - -err_qp_table_free: - mlx4_cleanup_qp_table(dev); - -err_srq_table_free: - mlx4_cleanup_srq_table(dev); - -err_cq_table_free: - mlx4_cleanup_cq_table(dev); - -err_cmd_poll: - mlx4_cmd_use_polling(dev); - -err_eq_table_free: - mlx4_cleanup_eq_table(dev); - -err_catas_buf: - mlx4_unmap_catas_buf(dev); - mlx4_cleanup_mr_table(dev); - -err_pd_table_free: - mlx4_cleanup_pd_table(dev); - -err_kar_unmap: - iounmap(priv->kar); - -err_uar_free: - mlx4_uar_free(dev, &priv->driver_uar); - -err_uar_table_free: - mlx4_cleanup_uar_table(dev); - return err; -} - -static void __devinit mlx4_enable_msi_x(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct msix_entry entries[MLX4_NUM_EQ]; - int err; - int i; - - if (msi_x) { - for (i = 0; i < MLX4_NUM_EQ; ++i) - entries[i].entry = i; - - err = pci_enable_msix(dev->pdev, entries, ARRAY_SIZE(entries)); - if (err) { - if (err > 0) - mlx4_info(dev, "Only %d MSI-X vectors available, " - "not using MSI-X\n", err); - goto no_msi; - } - - for (i = 0; i < MLX4_NUM_EQ; ++i) - priv->eq_table.eq[i].irq = entries[i].vector; - - dev->flags |= MLX4_FLAG_MSI_X; - return; - } - -no_msi: - for (i = 0; i < MLX4_NUM_EQ; ++i) - priv->eq_table.eq[i].irq = dev->pdev->irq; -} - -static int __devinit mlx4_init_one(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - static int mlx4_version_printed; - struct mlx4_priv *priv; - struct mlx4_dev *dev; - int err; - - if (!mlx4_version_printed) { - printk(KERN_INFO "%s", mlx4_version); - ++mlx4_version_printed; - } - - printk(KERN_INFO PFX "Initializing %s\n", - pci_name(pdev)); - - err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "Cannot enable PCI device, " - "aborting.\n"); - return err; - } - - /* - * Check for BARs. We expect 0: 1MB, 2: 8MB, 4: DDR (may not - * be present) - */ - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || - pci_resource_len(pdev, 0) != 1 << 20) { - dev_err(&pdev->dev, "Missing DCS, aborting.\n"); - err = -ENODEV; - goto err_disable_pdev; - } - if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "Missing UAR, aborting.\n"); - err = -ENODEV; - goto err_disable_pdev; - } - - err = pci_request_region(pdev, 0, DRV_NAME); - if (err) { - dev_err(&pdev->dev, "Cannot request control region, aborting.\n"); - goto err_disable_pdev; - } - - err = pci_request_region(pdev, 2, DRV_NAME); - if (err) { - dev_err(&pdev->dev, "Cannot request UAR region, aborting.\n"); - goto err_release_bar0; - } - - pci_set_master(pdev); - - err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); - if (err) { - dev_warn(&pdev->dev, "Warning: couldn't set 64-bit PCI DMA mask.\n"); - err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (err) { - dev_err(&pdev->dev, "Can't set PCI DMA mask, aborting.\n"); - goto err_release_bar2; - } - } - err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); - if (err) { - dev_warn(&pdev->dev, "Warning: couldn't set 64-bit " - "consistent PCI DMA mask.\n"); - err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); - if (err) { - dev_err(&pdev->dev, "Can't set consistent PCI DMA mask, " - "aborting.\n"); - goto err_release_bar2; - } - } - - priv = kzalloc(sizeof *priv, GFP_KERNEL); - if (!priv) { - dev_err(&pdev->dev, "Device struct alloc failed, " - "aborting.\n"); - err = -ENOMEM; - goto err_release_bar2; - } - - dev = &priv->dev; - dev->pdev = pdev; - - /* - * Now reset the HCA before we touch the PCI capabilities or - * attempt a firmware command, since a boot ROM may have left - * the HCA in an undefined state. - */ - err = mlx4_reset(dev); - if (err) { - mlx4_err(dev, "Failed to reset HCA, aborting.\n"); - goto err_free_dev; - } - - mlx4_enable_msi_x(dev); - - if (mlx4_cmd_init(dev)) { - mlx4_err(dev, "Failed to init command interface, aborting.\n"); - goto err_free_dev; - } - - err = mlx4_init_hca(dev); - if (err) - goto err_cmd; - - err = mlx4_setup_hca(dev); - if (err) - goto err_close; - - err = mlx4_register_device(dev); - if (err) - goto err_cleanup; - - pci_set_drvdata(pdev, dev); - - return 0; - -err_cleanup: - mlx4_cleanup_mcg_table(dev); - mlx4_cleanup_qp_table(dev); - mlx4_cleanup_srq_table(dev); - mlx4_cleanup_cq_table(dev); - mlx4_cmd_use_polling(dev); - mlx4_cleanup_eq_table(dev); - - mlx4_unmap_catas_buf(dev); - - mlx4_cleanup_mr_table(dev); - mlx4_cleanup_pd_table(dev); - mlx4_cleanup_uar_table(dev); - -err_close: - mlx4_close_hca(dev); - -err_cmd: - mlx4_cmd_cleanup(dev); - -err_free_dev: - if (dev->flags & MLX4_FLAG_MSI_X) - pci_disable_msix(pdev); - - kfree(priv); - -err_release_bar2: - pci_release_region(pdev, 2); - -err_release_bar0: - pci_release_region(pdev, 0); - -err_disable_pdev: - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - return err; -} - -static void __devexit mlx4_remove_one(struct pci_dev *pdev) -{ - struct mlx4_dev *dev = pci_get_drvdata(pdev); - struct mlx4_priv *priv = mlx4_priv(dev); - int p; - - if (dev) { - mlx4_unregister_device(dev); - - for (p = 1; p <= dev->caps.num_ports; ++p) - mlx4_CLOSE_PORT(dev, p); - - mlx4_cleanup_mcg_table(dev); - mlx4_cleanup_qp_table(dev); - mlx4_cleanup_srq_table(dev); - mlx4_cleanup_cq_table(dev); - mlx4_cmd_use_polling(dev); - mlx4_cleanup_eq_table(dev); - - mlx4_unmap_catas_buf(dev); - - mlx4_cleanup_mr_table(dev); - mlx4_cleanup_pd_table(dev); - - iounmap(priv->kar); - mlx4_uar_free(dev, &priv->driver_uar); - mlx4_cleanup_uar_table(dev); - mlx4_close_hca(dev); - mlx4_cmd_cleanup(dev); - - if (dev->flags & MLX4_FLAG_MSI_X) - pci_disable_msix(pdev); - - kfree(priv); - pci_release_region(pdev, 2); - pci_release_region(pdev, 0); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - } -} - -static struct pci_device_id mlx4_pci_table[] = { - { PCI_VDEVICE(MELLANOX, 0x6340) }, /* MT25408 "Hermon" SDR */ - { PCI_VDEVICE(MELLANOX, 0x634a) }, /* MT25408 "Hermon" DDR */ - { PCI_VDEVICE(MELLANOX, 0x6354) }, /* MT25408 "Hermon" QDR */ - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, mlx4_pci_table); - -static struct pci_driver mlx4_driver = { - .name = DRV_NAME, - .id_table = mlx4_pci_table, - .probe = mlx4_init_one, - .remove = __devexit_p(mlx4_remove_one) -}; - -static int __init mlx4_init(void) -{ - int ret; - - ret = pci_register_driver(&mlx4_driver); - return ret < 0 ? ret : 0; -} - -static void __exit mlx4_cleanup(void) -{ - pci_unregister_driver(&mlx4_driver); -} - -module_init(mlx4_init); -module_exit(mlx4_cleanup); diff --git a/trunk/drivers/net/mlx4/mcg.c b/trunk/drivers/net/mlx4/mcg.c deleted file mode 100644 index 672024a0ee71..000000000000 --- a/trunk/drivers/net/mlx4/mcg.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include - -#include - -#include "mlx4.h" - -struct mlx4_mgm { - __be32 next_gid_index; - __be32 members_count; - u32 reserved[2]; - u8 gid[16]; - __be32 qp[MLX4_QP_PER_MGM]; -}; - -static const u8 zero_gid[16]; /* automatically initialized to 0 */ - -static int mlx4_READ_MCG(struct mlx4_dev *dev, int index, - struct mlx4_cmd_mailbox *mailbox) -{ - return mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, MLX4_CMD_READ_MCG, - MLX4_CMD_TIME_CLASS_A); -} - -static int mlx4_WRITE_MCG(struct mlx4_dev *dev, int index, - struct mlx4_cmd_mailbox *mailbox) -{ - return mlx4_cmd(dev, mailbox->dma, index, 0, MLX4_CMD_WRITE_MCG, - MLX4_CMD_TIME_CLASS_A); -} - -static int mlx4_MGID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - u16 *hash) -{ - u64 imm; - int err; - - err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, 0, MLX4_CMD_MGID_HASH, - MLX4_CMD_TIME_CLASS_A); - - if (!err) - *hash = imm; - - return err; -} - -/* - * Caller must hold MCG table semaphore. gid and mgm parameters must - * be properly aligned for command interface. - * - * Returns 0 unless a firmware command error occurs. - * - * If GID is found in MGM or MGM is empty, *index = *hash, *prev = -1 - * and *mgm holds MGM entry. - * - * if GID is found in AMGM, *index = index in AMGM, *prev = index of - * previous entry in hash chain and *mgm holds AMGM entry. - * - * If no AMGM exists for given gid, *index = -1, *prev = index of last - * entry in hash chain and *mgm holds end of hash chain. - */ -static int find_mgm(struct mlx4_dev *dev, - u8 *gid, struct mlx4_cmd_mailbox *mgm_mailbox, - u16 *hash, int *prev, int *index) -{ - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_mgm *mgm = mgm_mailbox->buf; - u8 *mgid; - int err; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return -ENOMEM; - mgid = mailbox->buf; - - memcpy(mgid, gid, 16); - - err = mlx4_MGID_HASH(dev, mailbox, hash); - mlx4_free_cmd_mailbox(dev, mailbox); - if (err) - return err; - - if (0) - mlx4_dbg(dev, "Hash for %04x:%04x:%04x:%04x:" - "%04x:%04x:%04x:%04x is %04x\n", - be16_to_cpu(((__be16 *) gid)[0]), - be16_to_cpu(((__be16 *) gid)[1]), - be16_to_cpu(((__be16 *) gid)[2]), - be16_to_cpu(((__be16 *) gid)[3]), - be16_to_cpu(((__be16 *) gid)[4]), - be16_to_cpu(((__be16 *) gid)[5]), - be16_to_cpu(((__be16 *) gid)[6]), - be16_to_cpu(((__be16 *) gid)[7]), - *hash); - - *index = *hash; - *prev = -1; - - do { - err = mlx4_READ_MCG(dev, *index, mgm_mailbox); - if (err) - return err; - - if (!memcmp(mgm->gid, zero_gid, 16)) { - if (*index != *hash) { - mlx4_err(dev, "Found zero MGID in AMGM.\n"); - err = -EINVAL; - } - return err; - } - - if (!memcmp(mgm->gid, gid, 16)) - return err; - - *prev = *index; - *index = be32_to_cpu(mgm->next_gid_index) >> 6; - } while (*index); - - *index = -1; - return err; -} - -int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_mgm *mgm; - u32 members_count; - u16 hash; - int index, prev; - int link = 0; - int i; - int err; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - mgm = mailbox->buf; - - mutex_lock(&priv->mcg_table.mutex); - - err = find_mgm(dev, gid, mailbox, &hash, &prev, &index); - if (err) - goto out; - - if (index != -1) { - if (!memcmp(mgm->gid, zero_gid, 16)) - memcpy(mgm->gid, gid, 16); - } else { - link = 1; - - index = mlx4_bitmap_alloc(&priv->mcg_table.bitmap); - if (index == -1) { - mlx4_err(dev, "No AMGM entries left\n"); - err = -ENOMEM; - goto out; - } - index += dev->caps.num_mgms; - - err = mlx4_READ_MCG(dev, index, mailbox); - if (err) - goto out; - - memset(mgm, 0, sizeof *mgm); - memcpy(mgm->gid, gid, 16); - } - - members_count = be32_to_cpu(mgm->members_count); - if (members_count == MLX4_QP_PER_MGM) { - mlx4_err(dev, "MGM at index %x is full.\n", index); - err = -ENOMEM; - goto out; - } - - for (i = 0; i < members_count; ++i) - if (mgm->qp[i] == cpu_to_be32(qp->qpn)) { - mlx4_dbg(dev, "QP %06x already a member of MGM\n", qp->qpn); - err = 0; - goto out; - } - - mgm->qp[members_count++] = cpu_to_be32(qp->qpn); - mgm->members_count = cpu_to_be32(members_count); - - err = mlx4_WRITE_MCG(dev, index, mailbox); - if (err) - goto out; - - if (!link) - goto out; - - err = mlx4_READ_MCG(dev, prev, mailbox); - if (err) - goto out; - - mgm->next_gid_index = cpu_to_be32(index << 6); - - err = mlx4_WRITE_MCG(dev, prev, mailbox); - if (err) - goto out; - -out: - if (err && link && index != -1) { - if (index < dev->caps.num_mgms) - mlx4_warn(dev, "Got AMGM index %d < %d", - index, dev->caps.num_mgms); - else - mlx4_bitmap_free(&priv->mcg_table.bitmap, - index - dev->caps.num_mgms); - } - mutex_unlock(&priv->mcg_table.mutex); - - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} -EXPORT_SYMBOL_GPL(mlx4_multicast_attach); - -int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_mgm *mgm; - u32 members_count; - u16 hash; - int prev, index; - int i, loc; - int err; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - mgm = mailbox->buf; - - mutex_lock(&priv->mcg_table.mutex); - - err = find_mgm(dev, gid, mailbox, &hash, &prev, &index); - if (err) - goto out; - - if (index == -1) { - mlx4_err(dev, "MGID %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " - "not found\n", - be16_to_cpu(((__be16 *) gid)[0]), - be16_to_cpu(((__be16 *) gid)[1]), - be16_to_cpu(((__be16 *) gid)[2]), - be16_to_cpu(((__be16 *) gid)[3]), - be16_to_cpu(((__be16 *) gid)[4]), - be16_to_cpu(((__be16 *) gid)[5]), - be16_to_cpu(((__be16 *) gid)[6]), - be16_to_cpu(((__be16 *) gid)[7])); - err = -EINVAL; - goto out; - } - - members_count = be32_to_cpu(mgm->members_count); - for (loc = -1, i = 0; i < members_count; ++i) - if (mgm->qp[i] == cpu_to_be32(qp->qpn)) - loc = i; - - if (loc == -1) { - mlx4_err(dev, "QP %06x not found in MGM\n", qp->qpn); - err = -EINVAL; - goto out; - } - - - mgm->members_count = cpu_to_be32(--members_count); - mgm->qp[loc] = mgm->qp[i - 1]; - mgm->qp[i - 1] = 0; - - err = mlx4_WRITE_MCG(dev, index, mailbox); - if (err) - goto out; - - if (i != 1) - goto out; - - if (prev == -1) { - /* Remove entry from MGM */ - int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6; - if (amgm_index) { - err = mlx4_READ_MCG(dev, amgm_index, mailbox); - if (err) - goto out; - } else - memset(mgm->gid, 0, 16); - - err = mlx4_WRITE_MCG(dev, index, mailbox); - if (err) - goto out; - - if (amgm_index) { - if (amgm_index < dev->caps.num_mgms) - mlx4_warn(dev, "MGM entry %d had AMGM index %d < %d", - index, amgm_index, dev->caps.num_mgms); - else - mlx4_bitmap_free(&priv->mcg_table.bitmap, - amgm_index - dev->caps.num_mgms); - } - } else { - /* Remove entry from AMGM */ - int cur_next_index = be32_to_cpu(mgm->next_gid_index) >> 6; - err = mlx4_READ_MCG(dev, prev, mailbox); - if (err) - goto out; - - mgm->next_gid_index = cpu_to_be32(cur_next_index << 6); - - err = mlx4_WRITE_MCG(dev, prev, mailbox); - if (err) - goto out; - - if (index < dev->caps.num_mgms) - mlx4_warn(dev, "entry %d had next AMGM index %d < %d", - prev, index, dev->caps.num_mgms); - else - mlx4_bitmap_free(&priv->mcg_table.bitmap, - index - dev->caps.num_mgms); - } - -out: - mutex_unlock(&priv->mcg_table.mutex); - - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} -EXPORT_SYMBOL_GPL(mlx4_multicast_detach); - -int __devinit mlx4_init_mcg_table(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int err; - - err = mlx4_bitmap_init(&priv->mcg_table.bitmap, - dev->caps.num_amgms, dev->caps.num_amgms - 1, 0); - if (err) - return err; - - mutex_init(&priv->mcg_table.mutex); - - return 0; -} - -void mlx4_cleanup_mcg_table(struct mlx4_dev *dev) -{ - mlx4_bitmap_cleanup(&mlx4_priv(dev)->mcg_table.bitmap); -} diff --git a/trunk/drivers/net/mlx4/mlx4.h b/trunk/drivers/net/mlx4/mlx4.h deleted file mode 100644 index 9befbae3d196..000000000000 --- a/trunk/drivers/net/mlx4/mlx4.h +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005, 2006, 2007 Cisco Systems. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2004 Voltaire, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef MLX4_H -#define MLX4_H - -#include - -#include -#include - -#define DRV_NAME "mlx4_core" -#define PFX DRV_NAME ": " -#define DRV_VERSION "0.01" -#define DRV_RELDATE "May 1, 2007" - -enum { - MLX4_HCR_BASE = 0x80680, - MLX4_HCR_SIZE = 0x0001c, - MLX4_CLR_INT_SIZE = 0x00008 -}; - -enum { - MLX4_BOARD_ID_LEN = 64 -}; - -enum { - MLX4_MGM_ENTRY_SIZE = 0x40, - MLX4_QP_PER_MGM = 4 * (MLX4_MGM_ENTRY_SIZE / 16 - 2), - MLX4_MTT_ENTRY_PER_SEG = 8 -}; - -enum { - MLX4_EQ_ASYNC, - MLX4_EQ_COMP, - MLX4_EQ_CATAS, - MLX4_NUM_EQ -}; - -enum { - MLX4_NUM_PDS = 1 << 15 -}; - -enum { - MLX4_CMPT_TYPE_QP = 0, - MLX4_CMPT_TYPE_SRQ = 1, - MLX4_CMPT_TYPE_CQ = 2, - MLX4_CMPT_TYPE_EQ = 3, - MLX4_CMPT_NUM_TYPE -}; - -enum { - MLX4_CMPT_SHIFT = 24, - MLX4_NUM_CMPTS = MLX4_CMPT_NUM_TYPE << MLX4_CMPT_SHIFT -}; - -#ifdef CONFIG_MLX4_DEBUG -extern int mlx4_debug_level; - -#define mlx4_dbg(mdev, format, arg...) \ - do { \ - if (mlx4_debug_level) \ - dev_printk(KERN_DEBUG, &mdev->pdev->dev, format, ## arg); \ - } while (0) - -#else /* CONFIG_MLX4_DEBUG */ - -#define mlx4_dbg(mdev, format, arg...) do { (void) mdev; } while (0) - -#endif /* CONFIG_MLX4_DEBUG */ - -#define mlx4_err(mdev, format, arg...) \ - dev_err(&mdev->pdev->dev, format, ## arg) -#define mlx4_info(mdev, format, arg...) \ - dev_info(&mdev->pdev->dev, format, ## arg) -#define mlx4_warn(mdev, format, arg...) \ - dev_warn(&mdev->pdev->dev, format, ## arg) - -struct mlx4_bitmap { - u32 last; - u32 top; - u32 max; - u32 mask; - spinlock_t lock; - unsigned long *table; -}; - -struct mlx4_buddy { - unsigned long **bits; - int max_order; - spinlock_t lock; -}; - -struct mlx4_icm; - -struct mlx4_icm_table { - u64 virt; - int num_icm; - int num_obj; - int obj_size; - int lowmem; - struct mutex mutex; - struct mlx4_icm **icm; -}; - -struct mlx4_eq { - struct mlx4_dev *dev; - void __iomem *doorbell; - int eqn; - u32 cons_index; - u16 irq; - u16 have_irq; - int nent; - struct mlx4_buf_list *page_list; - struct mlx4_mtt mtt; -}; - -struct mlx4_profile { - int num_qp; - int rdmarc_per_qp; - int num_srq; - int num_cq; - int num_mcg; - int num_mpt; - int num_mtt; -}; - -struct mlx4_fw { - u64 clr_int_base; - u64 catas_offset; - struct mlx4_icm *fw_icm; - struct mlx4_icm *aux_icm; - u32 catas_size; - u16 fw_pages; - u8 clr_int_bar; - u8 catas_bar; -}; - -struct mlx4_cmd { - struct pci_pool *pool; - void __iomem *hcr; - struct mutex hcr_mutex; - struct semaphore poll_sem; - struct semaphore event_sem; - int max_cmds; - spinlock_t context_lock; - int free_head; - struct mlx4_cmd_context *context; - u16 token_mask; - u8 use_events; - u8 toggle; -}; - -struct mlx4_uar_table { - struct mlx4_bitmap bitmap; -}; - -struct mlx4_mr_table { - struct mlx4_bitmap mpt_bitmap; - struct mlx4_buddy mtt_buddy; - u64 mtt_base; - u64 mpt_base; - struct mlx4_icm_table mtt_table; - struct mlx4_icm_table dmpt_table; -}; - -struct mlx4_cq_table { - struct mlx4_bitmap bitmap; - spinlock_t lock; - struct radix_tree_root tree; - struct mlx4_icm_table table; - struct mlx4_icm_table cmpt_table; -}; - -struct mlx4_eq_table { - struct mlx4_bitmap bitmap; - void __iomem *clr_int; - void __iomem *uar_map[(MLX4_NUM_EQ + 6) / 4]; - u32 clr_mask; - struct mlx4_eq eq[MLX4_NUM_EQ]; - u64 icm_virt; - struct page *icm_page; - dma_addr_t icm_dma; - struct mlx4_icm_table cmpt_table; - int have_irq; - u8 inta_pin; -}; - -struct mlx4_srq_table { - struct mlx4_bitmap bitmap; - spinlock_t lock; - struct radix_tree_root tree; - struct mlx4_icm_table table; - struct mlx4_icm_table cmpt_table; -}; - -struct mlx4_qp_table { - struct mlx4_bitmap bitmap; - u32 rdmarc_base; - int rdmarc_shift; - spinlock_t lock; - struct mlx4_icm_table qp_table; - struct mlx4_icm_table auxc_table; - struct mlx4_icm_table altc_table; - struct mlx4_icm_table rdmarc_table; - struct mlx4_icm_table cmpt_table; -}; - -struct mlx4_mcg_table { - struct mutex mutex; - struct mlx4_bitmap bitmap; - struct mlx4_icm_table table; -}; - -struct mlx4_catas_err { - u32 __iomem *map; - int size; -}; - -struct mlx4_priv { - struct mlx4_dev dev; - - struct list_head dev_list; - struct list_head ctx_list; - spinlock_t ctx_lock; - - struct mlx4_fw fw; - struct mlx4_cmd cmd; - - struct mlx4_bitmap pd_bitmap; - struct mlx4_uar_table uar_table; - struct mlx4_mr_table mr_table; - struct mlx4_cq_table cq_table; - struct mlx4_eq_table eq_table; - struct mlx4_srq_table srq_table; - struct mlx4_qp_table qp_table; - struct mlx4_mcg_table mcg_table; - - struct mlx4_catas_err catas_err; - - void __iomem *clr_base; - - struct mlx4_uar driver_uar; - void __iomem *kar; - MLX4_DECLARE_DOORBELL_LOCK(doorbell_lock) - - u32 rev_id; - char board_id[MLX4_BOARD_ID_LEN]; -}; - -static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev) -{ - return container_of(dev, struct mlx4_priv, dev); -} - -u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap); -void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj); -int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved); -void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap); - -int mlx4_reset(struct mlx4_dev *dev); - -int mlx4_init_pd_table(struct mlx4_dev *dev); -int mlx4_init_uar_table(struct mlx4_dev *dev); -int mlx4_init_mr_table(struct mlx4_dev *dev); -int mlx4_init_eq_table(struct mlx4_dev *dev); -int mlx4_init_cq_table(struct mlx4_dev *dev); -int mlx4_init_qp_table(struct mlx4_dev *dev); -int mlx4_init_srq_table(struct mlx4_dev *dev); -int mlx4_init_mcg_table(struct mlx4_dev *dev); - -void mlx4_cleanup_pd_table(struct mlx4_dev *dev); -void mlx4_cleanup_uar_table(struct mlx4_dev *dev); -void mlx4_cleanup_mr_table(struct mlx4_dev *dev); -void mlx4_cleanup_eq_table(struct mlx4_dev *dev); -void mlx4_cleanup_cq_table(struct mlx4_dev *dev); -void mlx4_cleanup_qp_table(struct mlx4_dev *dev); -void mlx4_cleanup_srq_table(struct mlx4_dev *dev); -void mlx4_cleanup_mcg_table(struct mlx4_dev *dev); - -void mlx4_map_catas_buf(struct mlx4_dev *dev); -void mlx4_unmap_catas_buf(struct mlx4_dev *dev); - -int mlx4_register_device(struct mlx4_dev *dev); -void mlx4_unregister_device(struct mlx4_dev *dev); -void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_event type, - int subtype, int port); - -struct mlx4_dev_cap; -struct mlx4_init_hca_param; - -u64 mlx4_make_profile(struct mlx4_dev *dev, - struct mlx4_profile *request, - struct mlx4_dev_cap *dev_cap, - struct mlx4_init_hca_param *init_hca); - -int mlx4_map_eq_icm(struct mlx4_dev *dev, u64 icm_virt); -void mlx4_unmap_eq_icm(struct mlx4_dev *dev); - -int mlx4_cmd_init(struct mlx4_dev *dev); -void mlx4_cmd_cleanup(struct mlx4_dev *dev); -void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param); -int mlx4_cmd_use_events(struct mlx4_dev *dev); -void mlx4_cmd_use_polling(struct mlx4_dev *dev); - -void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn); -void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type); - -void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type); - -void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type); - -void mlx4_handle_catas_err(struct mlx4_dev *dev); - -#endif /* MLX4_H */ diff --git a/trunk/drivers/net/mlx4/mr.c b/trunk/drivers/net/mlx4/mr.c deleted file mode 100644 index b33864dab179..000000000000 --- a/trunk/drivers/net/mlx4/mr.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright (c) 2004 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include - -#include "mlx4.h" -#include "icm.h" - -/* - * Must be packed because mtt_seg is 64 bits but only aligned to 32 bits. - */ -struct mlx4_mpt_entry { - __be32 flags; - __be32 qpn; - __be32 key; - __be32 pd; - __be64 start; - __be64 length; - __be32 lkey; - __be32 win_cnt; - u8 reserved1[3]; - u8 mtt_rep; - __be64 mtt_seg; - __be32 mtt_sz; - __be32 entity_size; - __be32 first_byte_offset; -} __attribute__((packed)); - -#define MLX4_MPT_FLAG_SW_OWNS (0xfUL << 28) -#define MLX4_MPT_FLAG_MIO (1 << 17) -#define MLX4_MPT_FLAG_BIND_ENABLE (1 << 15) -#define MLX4_MPT_FLAG_PHYSICAL (1 << 9) -#define MLX4_MPT_FLAG_REGION (1 << 8) - -#define MLX4_MTT_FLAG_PRESENT 1 - -static u32 mlx4_buddy_alloc(struct mlx4_buddy *buddy, int order) -{ - int o; - int m; - u32 seg; - - spin_lock(&buddy->lock); - - for (o = order; o <= buddy->max_order; ++o) { - m = 1 << (buddy->max_order - o); - seg = find_first_bit(buddy->bits[o], m); - if (seg < m) - goto found; - } - - spin_unlock(&buddy->lock); - return -1; - - found: - clear_bit(seg, buddy->bits[o]); - - while (o > order) { - --o; - seg <<= 1; - set_bit(seg ^ 1, buddy->bits[o]); - } - - spin_unlock(&buddy->lock); - - seg <<= order; - - return seg; -} - -static void mlx4_buddy_free(struct mlx4_buddy *buddy, u32 seg, int order) -{ - seg >>= order; - - spin_lock(&buddy->lock); - - while (test_bit(seg ^ 1, buddy->bits[order])) { - clear_bit(seg ^ 1, buddy->bits[order]); - seg >>= 1; - ++order; - } - - set_bit(seg, buddy->bits[order]); - - spin_unlock(&buddy->lock); -} - -static int __devinit mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) -{ - int i, s; - - buddy->max_order = max_order; - spin_lock_init(&buddy->lock); - - buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *), - GFP_KERNEL); - if (!buddy->bits) - goto err_out; - - for (i = 0; i <= buddy->max_order; ++i) { - s = BITS_TO_LONGS(1 << (buddy->max_order - i)); - buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL); - if (!buddy->bits[i]) - goto err_out_free; - bitmap_zero(buddy->bits[i], 1 << (buddy->max_order - i)); - } - - set_bit(0, buddy->bits[buddy->max_order]); - - return 0; - -err_out_free: - for (i = 0; i <= buddy->max_order; ++i) - kfree(buddy->bits[i]); - - kfree(buddy->bits); - -err_out: - return -ENOMEM; -} - -static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy) -{ - int i; - - for (i = 0; i <= buddy->max_order; ++i) - kfree(buddy->bits[i]); - - kfree(buddy->bits); -} - -static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order) -{ - struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; - u32 seg; - - seg = mlx4_buddy_alloc(&mr_table->mtt_buddy, order); - if (seg == -1) - return -1; - - if (mlx4_table_get_range(dev, &mr_table->mtt_table, seg, - seg + (1 << order) - 1)) { - mlx4_buddy_free(&mr_table->mtt_buddy, seg, order); - return -1; - } - - return seg; -} - -int mlx4_mtt_init(struct mlx4_dev *dev, int npages, int page_shift, - struct mlx4_mtt *mtt) -{ - int i; - - if (!npages) { - mtt->order = -1; - mtt->page_shift = MLX4_ICM_PAGE_SHIFT; - return 0; - } else - mtt->page_shift = page_shift; - - for (mtt->order = 0, i = MLX4_MTT_ENTRY_PER_SEG; i < npages; i <<= 1) - ++mtt->order; - - mtt->first_seg = mlx4_alloc_mtt_range(dev, mtt->order); - if (mtt->first_seg == -1) - return -ENOMEM; - - return 0; -} -EXPORT_SYMBOL_GPL(mlx4_mtt_init); - -void mlx4_mtt_cleanup(struct mlx4_dev *dev, struct mlx4_mtt *mtt) -{ - struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; - - if (mtt->order < 0) - return; - - mlx4_buddy_free(&mr_table->mtt_buddy, mtt->first_seg, mtt->order); - mlx4_table_put_range(dev, &mr_table->mtt_table, mtt->first_seg, - mtt->first_seg + (1 << mtt->order) - 1); -} -EXPORT_SYMBOL_GPL(mlx4_mtt_cleanup); - -u64 mlx4_mtt_addr(struct mlx4_dev *dev, struct mlx4_mtt *mtt) -{ - return (u64) mtt->first_seg * dev->caps.mtt_entry_sz; -} -EXPORT_SYMBOL_GPL(mlx4_mtt_addr); - -static u32 hw_index_to_key(u32 ind) -{ - return (ind >> 24) | (ind << 8); -} - -static u32 key_to_hw_index(u32 key) -{ - return (key << 24) | (key >> 8); -} - -static int mlx4_SW2HW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int mpt_index) -{ - return mlx4_cmd(dev, mailbox->dma, mpt_index, 0, MLX4_CMD_SW2HW_MPT, - MLX4_CMD_TIME_CLASS_B); -} - -static int mlx4_HW2SW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int mpt_index) -{ - return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, mpt_index, - !mailbox, MLX4_CMD_HW2SW_MPT, MLX4_CMD_TIME_CLASS_B); -} - -int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access, - int npages, int page_shift, struct mlx4_mr *mr) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - u32 index; - int err; - - index = mlx4_bitmap_alloc(&priv->mr_table.mpt_bitmap); - if (index == -1) { - err = -ENOMEM; - goto err; - } - - mr->iova = iova; - mr->size = size; - mr->pd = pd; - mr->access = access; - mr->enabled = 0; - mr->key = hw_index_to_key(index); - - err = mlx4_mtt_init(dev, npages, page_shift, &mr->mtt); - if (err) - goto err_index; - - return 0; - -err_index: - mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index); - -err: - kfree(mr); - return err; -} -EXPORT_SYMBOL_GPL(mlx4_mr_alloc); - -void mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int err; - - if (mr->enabled) { - err = mlx4_HW2SW_MPT(dev, NULL, - key_to_hw_index(mr->key) & - (dev->caps.num_mpts - 1)); - if (err) - mlx4_warn(dev, "HW2SW_MPT failed (%d)\n", err); - } - - mlx4_mtt_cleanup(dev, &mr->mtt); - mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, key_to_hw_index(mr->key)); -} -EXPORT_SYMBOL_GPL(mlx4_mr_free); - -int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr) -{ - struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_mpt_entry *mpt_entry; - int err; - - err = mlx4_table_get(dev, &mr_table->dmpt_table, key_to_hw_index(mr->key)); - if (err) - return err; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) { - err = PTR_ERR(mailbox); - goto err_table; - } - mpt_entry = mailbox->buf; - - memset(mpt_entry, 0, sizeof *mpt_entry); - - mpt_entry->flags = cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS | - MLX4_MPT_FLAG_MIO | - MLX4_MPT_FLAG_REGION | - mr->access); - if (mr->mtt.order < 0) - mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL); - - mpt_entry->key = cpu_to_be32(key_to_hw_index(mr->key)); - mpt_entry->pd = cpu_to_be32(mr->pd); - mpt_entry->start = cpu_to_be64(mr->iova); - mpt_entry->length = cpu_to_be64(mr->size); - mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift); - mpt_entry->mtt_seg = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt)); - - err = mlx4_SW2HW_MPT(dev, mailbox, - key_to_hw_index(mr->key) & (dev->caps.num_mpts - 1)); - if (err) { - mlx4_warn(dev, "SW2HW_MPT failed (%d)\n", err); - goto err_cmd; - } - - mr->enabled = 1; - - mlx4_free_cmd_mailbox(dev, mailbox); - - return 0; - -err_cmd: - mlx4_free_cmd_mailbox(dev, mailbox); - -err_table: - mlx4_table_put(dev, &mr_table->dmpt_table, key_to_hw_index(mr->key)); - return err; -} -EXPORT_SYMBOL_GPL(mlx4_mr_enable); - -static int mlx4_WRITE_MTT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int num_mtt) -{ - return mlx4_cmd(dev, mailbox->dma, num_mtt, 0, MLX4_CMD_WRITE_MTT, - MLX4_CMD_TIME_CLASS_B); -} - -int mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, - int start_index, int npages, u64 *page_list) -{ - struct mlx4_cmd_mailbox *mailbox; - __be64 *mtt_entry; - int i; - int err = 0; - - if (mtt->order < 0) - return -EINVAL; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - - mtt_entry = mailbox->buf; - - while (npages > 0) { - mtt_entry[0] = cpu_to_be64(mlx4_mtt_addr(dev, mtt) + start_index * 8); - mtt_entry[1] = 0; - - for (i = 0; i < npages && i < MLX4_MAILBOX_SIZE / 8 - 2; ++i) - mtt_entry[i + 2] = cpu_to_be64(page_list[i] | - MLX4_MTT_FLAG_PRESENT); - - /* - * If we have an odd number of entries to write, add - * one more dummy entry for firmware efficiency. - */ - if (i & 1) - mtt_entry[i + 2] = 0; - - err = mlx4_WRITE_MTT(dev, mailbox, (i + 1) & ~1); - if (err) - goto out; - - npages -= i; - start_index += i; - page_list += i; - } - -out: - mlx4_free_cmd_mailbox(dev, mailbox); - - return err; -} -EXPORT_SYMBOL_GPL(mlx4_write_mtt); - -int mlx4_buf_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, - struct mlx4_buf *buf) -{ - u64 *page_list; - int err; - int i; - - page_list = kmalloc(buf->npages * sizeof *page_list, GFP_KERNEL); - if (!page_list) - return -ENOMEM; - - for (i = 0; i < buf->npages; ++i) - if (buf->nbufs == 1) - page_list[i] = buf->u.direct.map + (i << buf->page_shift); - else - page_list[i] = buf->u.page_list[i].map; - - err = mlx4_write_mtt(dev, mtt, 0, buf->npages, page_list); - - kfree(page_list); - return err; -} -EXPORT_SYMBOL_GPL(mlx4_buf_write_mtt); - -int __devinit mlx4_init_mr_table(struct mlx4_dev *dev) -{ - struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; - int err; - - err = mlx4_bitmap_init(&mr_table->mpt_bitmap, dev->caps.num_mpts, - ~0, dev->caps.reserved_mrws); - if (err) - return err; - - err = mlx4_buddy_init(&mr_table->mtt_buddy, - ilog2(dev->caps.num_mtt_segs)); - if (err) - goto err_buddy; - - if (dev->caps.reserved_mtts) { - if (mlx4_alloc_mtt_range(dev, ilog2(dev->caps.reserved_mtts)) == -1) { - mlx4_warn(dev, "MTT table of order %d is too small.\n", - mr_table->mtt_buddy.max_order); - err = -ENOMEM; - goto err_reserve_mtts; - } - } - - return 0; - -err_reserve_mtts: - mlx4_buddy_cleanup(&mr_table->mtt_buddy); - -err_buddy: - mlx4_bitmap_cleanup(&mr_table->mpt_bitmap); - - return err; -} - -void mlx4_cleanup_mr_table(struct mlx4_dev *dev) -{ - struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; - - mlx4_buddy_cleanup(&mr_table->mtt_buddy); - mlx4_bitmap_cleanup(&mr_table->mpt_bitmap); -} diff --git a/trunk/drivers/net/mlx4/pd.c b/trunk/drivers/net/mlx4/pd.c deleted file mode 100644 index 23dea1ee7750..000000000000 --- a/trunk/drivers/net/mlx4/pd.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include - -#include "mlx4.h" -#include "icm.h" - -int mlx4_pd_alloc(struct mlx4_dev *dev, u32 *pdn) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - *pdn = mlx4_bitmap_alloc(&priv->pd_bitmap); - if (*pdn == -1) - return -ENOMEM; - - return 0; -} -EXPORT_SYMBOL_GPL(mlx4_pd_alloc); - -void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn) -{ - mlx4_bitmap_free(&mlx4_priv(dev)->pd_bitmap, pdn); -} -EXPORT_SYMBOL_GPL(mlx4_pd_free); - -int __devinit mlx4_init_pd_table(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - return mlx4_bitmap_init(&priv->pd_bitmap, dev->caps.num_pds, - (1 << 24) - 1, dev->caps.reserved_pds); -} - -void mlx4_cleanup_pd_table(struct mlx4_dev *dev) -{ - mlx4_bitmap_cleanup(&mlx4_priv(dev)->pd_bitmap); -} - - -int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar) -{ - uar->index = mlx4_bitmap_alloc(&mlx4_priv(dev)->uar_table.bitmap); - if (uar->index == -1) - return -ENOMEM; - - uar->pfn = (pci_resource_start(dev->pdev, 2) >> PAGE_SHIFT) + uar->index; - - return 0; -} -EXPORT_SYMBOL_GPL(mlx4_uar_alloc); - -void mlx4_uar_free(struct mlx4_dev *dev, struct mlx4_uar *uar) -{ - mlx4_bitmap_free(&mlx4_priv(dev)->uar_table.bitmap, uar->index); -} -EXPORT_SYMBOL_GPL(mlx4_uar_free); - -int mlx4_init_uar_table(struct mlx4_dev *dev) -{ - return mlx4_bitmap_init(&mlx4_priv(dev)->uar_table.bitmap, - dev->caps.num_uars, dev->caps.num_uars - 1, - max(128, dev->caps.reserved_uars)); -} - -void mlx4_cleanup_uar_table(struct mlx4_dev *dev) -{ - mlx4_bitmap_cleanup(&mlx4_priv(dev)->uar_table.bitmap); -} diff --git a/trunk/drivers/net/mlx4/profile.c b/trunk/drivers/net/mlx4/profile.c deleted file mode 100644 index 9ca42b213d54..000000000000 --- a/trunk/drivers/net/mlx4/profile.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include "mlx4.h" -#include "fw.h" - -enum { - MLX4_RES_QP, - MLX4_RES_RDMARC, - MLX4_RES_ALTC, - MLX4_RES_AUXC, - MLX4_RES_SRQ, - MLX4_RES_CQ, - MLX4_RES_EQ, - MLX4_RES_DMPT, - MLX4_RES_CMPT, - MLX4_RES_MTT, - MLX4_RES_MCG, - MLX4_RES_NUM -}; - -static const char *res_name[] = { - [MLX4_RES_QP] = "QP", - [MLX4_RES_RDMARC] = "RDMARC", - [MLX4_RES_ALTC] = "ALTC", - [MLX4_RES_AUXC] = "AUXC", - [MLX4_RES_SRQ] = "SRQ", - [MLX4_RES_CQ] = "CQ", - [MLX4_RES_EQ] = "EQ", - [MLX4_RES_DMPT] = "DMPT", - [MLX4_RES_CMPT] = "CMPT", - [MLX4_RES_MTT] = "MTT", - [MLX4_RES_MCG] = "MCG", -}; - -u64 mlx4_make_profile(struct mlx4_dev *dev, - struct mlx4_profile *request, - struct mlx4_dev_cap *dev_cap, - struct mlx4_init_hca_param *init_hca) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource { - u64 size; - u64 start; - int type; - int num; - int log_num; - }; - - u64 total_size = 0; - struct mlx4_resource *profile; - struct mlx4_resource tmp; - int i, j; - - profile = kzalloc(MLX4_RES_NUM * sizeof *profile, GFP_KERNEL); - if (!profile) - return -ENOMEM; - - profile[MLX4_RES_QP].size = dev_cap->qpc_entry_sz; - profile[MLX4_RES_RDMARC].size = dev_cap->rdmarc_entry_sz; - profile[MLX4_RES_ALTC].size = dev_cap->altc_entry_sz; - profile[MLX4_RES_AUXC].size = dev_cap->aux_entry_sz; - profile[MLX4_RES_SRQ].size = dev_cap->srq_entry_sz; - profile[MLX4_RES_CQ].size = dev_cap->cqc_entry_sz; - profile[MLX4_RES_EQ].size = dev_cap->eqc_entry_sz; - profile[MLX4_RES_DMPT].size = dev_cap->dmpt_entry_sz; - profile[MLX4_RES_CMPT].size = dev_cap->cmpt_entry_sz; - profile[MLX4_RES_MTT].size = MLX4_MTT_ENTRY_PER_SEG * dev_cap->mtt_entry_sz; - profile[MLX4_RES_MCG].size = MLX4_MGM_ENTRY_SIZE; - - profile[MLX4_RES_QP].num = request->num_qp; - profile[MLX4_RES_RDMARC].num = request->num_qp * request->rdmarc_per_qp; - profile[MLX4_RES_ALTC].num = request->num_qp; - profile[MLX4_RES_AUXC].num = request->num_qp; - profile[MLX4_RES_SRQ].num = request->num_srq; - profile[MLX4_RES_CQ].num = request->num_cq; - profile[MLX4_RES_EQ].num = MLX4_NUM_EQ + dev_cap->reserved_eqs; - profile[MLX4_RES_DMPT].num = request->num_mpt; - profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS; - profile[MLX4_RES_MTT].num = request->num_mtt; - profile[MLX4_RES_MCG].num = request->num_mcg; - - for (i = 0; i < MLX4_RES_NUM; ++i) { - profile[i].type = i; - profile[i].num = roundup_pow_of_two(profile[i].num); - profile[i].log_num = ilog2(profile[i].num); - profile[i].size *= profile[i].num; - profile[i].size = max(profile[i].size, (u64) PAGE_SIZE); - } - - /* - * Sort the resources in decreasing order of size. Since they - * all have sizes that are powers of 2, we'll be able to keep - * resources aligned to their size and pack them without gaps - * using the sorted order. - */ - for (i = MLX4_RES_NUM; i > 0; --i) - for (j = 1; j < i; ++j) { - if (profile[j].size > profile[j - 1].size) { - tmp = profile[j]; - profile[j] = profile[j - 1]; - profile[j - 1] = tmp; - } - } - - for (i = 0; i < MLX4_RES_NUM; ++i) { - if (profile[i].size) { - profile[i].start = total_size; - total_size += profile[i].size; - } - - if (total_size > dev_cap->max_icm_sz) { - mlx4_err(dev, "Profile requires 0x%llx bytes; " - "won't fit in 0x%llx bytes of context memory.\n", - (unsigned long long) total_size, - (unsigned long long) dev_cap->max_icm_sz); - kfree(profile); - return -ENOMEM; - } - - if (profile[i].size) - mlx4_dbg(dev, " profile[%2d] (%6s): 2^%02d entries @ 0x%10llx, " - "size 0x%10llx\n", - i, res_name[profile[i].type], profile[i].log_num, - (unsigned long long) profile[i].start, - (unsigned long long) profile[i].size); - } - - mlx4_dbg(dev, "HCA context memory: reserving %d KB\n", - (int) (total_size >> 10)); - - for (i = 0; i < MLX4_RES_NUM; ++i) { - switch (profile[i].type) { - case MLX4_RES_QP: - dev->caps.num_qps = profile[i].num; - init_hca->qpc_base = profile[i].start; - init_hca->log_num_qps = profile[i].log_num; - break; - case MLX4_RES_RDMARC: - for (priv->qp_table.rdmarc_shift = 0; - request->num_qp << priv->qp_table.rdmarc_shift < profile[i].num; - ++priv->qp_table.rdmarc_shift) - ; /* nothing */ - dev->caps.max_qp_dest_rdma = 1 << priv->qp_table.rdmarc_shift; - priv->qp_table.rdmarc_base = (u32) profile[i].start; - init_hca->rdmarc_base = profile[i].start; - init_hca->log_rd_per_qp = priv->qp_table.rdmarc_shift; - break; - case MLX4_RES_ALTC: - init_hca->altc_base = profile[i].start; - break; - case MLX4_RES_AUXC: - init_hca->auxc_base = profile[i].start; - break; - case MLX4_RES_SRQ: - dev->caps.num_srqs = profile[i].num; - init_hca->srqc_base = profile[i].start; - init_hca->log_num_srqs = profile[i].log_num; - break; - case MLX4_RES_CQ: - dev->caps.num_cqs = profile[i].num; - init_hca->cqc_base = profile[i].start; - init_hca->log_num_cqs = profile[i].log_num; - break; - case MLX4_RES_EQ: - dev->caps.num_eqs = profile[i].num; - init_hca->eqc_base = profile[i].start; - init_hca->log_num_eqs = profile[i].log_num; - break; - case MLX4_RES_DMPT: - dev->caps.num_mpts = profile[i].num; - priv->mr_table.mpt_base = profile[i].start; - init_hca->dmpt_base = profile[i].start; - init_hca->log_mpt_sz = profile[i].log_num; - break; - case MLX4_RES_CMPT: - init_hca->cmpt_base = profile[i].start; - break; - case MLX4_RES_MTT: - dev->caps.num_mtt_segs = profile[i].num; - priv->mr_table.mtt_base = profile[i].start; - init_hca->mtt_base = profile[i].start; - break; - case MLX4_RES_MCG: - dev->caps.num_mgms = profile[i].num >> 1; - dev->caps.num_amgms = profile[i].num >> 1; - init_hca->mc_base = profile[i].start; - init_hca->log_mc_entry_sz = ilog2(MLX4_MGM_ENTRY_SIZE); - init_hca->log_mc_table_sz = profile[i].log_num; - init_hca->log_mc_hash_sz = profile[i].log_num - 1; - break; - default: - break; - } - } - - /* - * PDs don't take any HCA memory, but we assign them as part - * of the HCA profile anyway. - */ - dev->caps.num_pds = MLX4_NUM_PDS; - - kfree(profile); - return total_size; -} diff --git a/trunk/drivers/net/mlx4/qp.c b/trunk/drivers/net/mlx4/qp.c deleted file mode 100644 index 7f8b7d55b6e1..000000000000 --- a/trunk/drivers/net/mlx4/qp.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) 2004 Topspin Communications. All rights reserved. - * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2004 Voltaire, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include -#include - -#include "mlx4.h" -#include "icm.h" - -void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type) -{ - struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; - struct mlx4_qp *qp; - - spin_lock(&qp_table->lock); - - qp = __mlx4_qp_lookup(dev, qpn); - if (qp) - atomic_inc(&qp->refcount); - - spin_unlock(&qp_table->lock); - - if (!qp) { - mlx4_warn(dev, "Async event for bogus QP %08x\n", qpn); - return; - } - - qp->event(qp, event_type); - - if (atomic_dec_and_test(&qp->refcount)) - complete(&qp->free); -} - -int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, - enum mlx4_qp_state cur_state, enum mlx4_qp_state new_state, - struct mlx4_qp_context *context, enum mlx4_qp_optpar optpar, - int sqd_event, struct mlx4_qp *qp) -{ - static const u16 op[MLX4_QP_NUM_STATE][MLX4_QP_NUM_STATE] = { - [MLX4_QP_STATE_RST] = { - [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP, - [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP, - [MLX4_QP_STATE_INIT] = MLX4_CMD_RST2INIT_QP, - }, - [MLX4_QP_STATE_INIT] = { - [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP, - [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP, - [MLX4_QP_STATE_INIT] = MLX4_CMD_INIT2INIT_QP, - [MLX4_QP_STATE_RTR] = MLX4_CMD_INIT2RTR_QP, - }, - [MLX4_QP_STATE_RTR] = { - [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP, - [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP, - [MLX4_QP_STATE_RTS] = MLX4_CMD_RTR2RTS_QP, - }, - [MLX4_QP_STATE_RTS] = { - [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP, - [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP, - [MLX4_QP_STATE_RTS] = MLX4_CMD_RTS2RTS_QP, - [MLX4_QP_STATE_SQD] = MLX4_CMD_RTS2SQD_QP, - }, - [MLX4_QP_STATE_SQD] = { - [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP, - [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP, - [MLX4_QP_STATE_RTS] = MLX4_CMD_SQD2RTS_QP, - [MLX4_QP_STATE_SQD] = MLX4_CMD_SQD2SQD_QP, - }, - [MLX4_QP_STATE_SQER] = { - [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP, - [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP, - [MLX4_QP_STATE_RTS] = MLX4_CMD_SQERR2RTS_QP, - }, - [MLX4_QP_STATE_ERR] = { - [MLX4_QP_STATE_RST] = MLX4_CMD_2RST_QP, - [MLX4_QP_STATE_ERR] = MLX4_CMD_2ERR_QP, - } - }; - - struct mlx4_cmd_mailbox *mailbox; - int ret = 0; - - if (cur_state < 0 || cur_state >= MLX4_QP_NUM_STATE || - new_state < 0 || cur_state >= MLX4_QP_NUM_STATE || - !op[cur_state][new_state]) - return -EINVAL; - - if (op[cur_state][new_state] == MLX4_CMD_2RST_QP) - return mlx4_cmd(dev, 0, qp->qpn, 2, - MLX4_CMD_2RST_QP, MLX4_CMD_TIME_CLASS_A); - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - - if (cur_state == MLX4_QP_STATE_RST && new_state == MLX4_QP_STATE_INIT) { - u64 mtt_addr = mlx4_mtt_addr(dev, mtt); - context->mtt_base_addr_h = mtt_addr >> 32; - context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff); - context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT; - } - - *(__be32 *) mailbox->buf = cpu_to_be32(optpar); - memcpy(mailbox->buf + 8, context, sizeof *context); - - ((struct mlx4_qp_context *) (mailbox->buf + 8))->local_qpn = - cpu_to_be32(qp->qpn); - - ret = mlx4_cmd(dev, mailbox->dma, qp->qpn | (!!sqd_event << 31), - new_state == MLX4_QP_STATE_RST ? 2 : 0, - op[cur_state][new_state], MLX4_CMD_TIME_CLASS_C); - - mlx4_free_cmd_mailbox(dev, mailbox); - return ret; -} -EXPORT_SYMBOL_GPL(mlx4_qp_modify); - -int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_qp_table *qp_table = &priv->qp_table; - int err; - - if (sqpn) - qp->qpn = sqpn; - else { - qp->qpn = mlx4_bitmap_alloc(&qp_table->bitmap); - if (qp->qpn == -1) - return -ENOMEM; - } - - err = mlx4_table_get(dev, &qp_table->qp_table, qp->qpn); - if (err) - goto err_out; - - err = mlx4_table_get(dev, &qp_table->auxc_table, qp->qpn); - if (err) - goto err_put_qp; - - err = mlx4_table_get(dev, &qp_table->altc_table, qp->qpn); - if (err) - goto err_put_auxc; - - err = mlx4_table_get(dev, &qp_table->rdmarc_table, qp->qpn); - if (err) - goto err_put_altc; - - err = mlx4_table_get(dev, &qp_table->cmpt_table, qp->qpn); - if (err) - goto err_put_rdmarc; - - spin_lock_irq(&qp_table->lock); - err = radix_tree_insert(&dev->qp_table_tree, qp->qpn & (dev->caps.num_qps - 1), qp); - spin_unlock_irq(&qp_table->lock); - if (err) - goto err_put_cmpt; - - atomic_set(&qp->refcount, 1); - init_completion(&qp->free); - - return 0; - -err_put_cmpt: - mlx4_table_put(dev, &qp_table->cmpt_table, qp->qpn); - -err_put_rdmarc: - mlx4_table_put(dev, &qp_table->rdmarc_table, qp->qpn); - -err_put_altc: - mlx4_table_put(dev, &qp_table->altc_table, qp->qpn); - -err_put_auxc: - mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn); - -err_put_qp: - mlx4_table_put(dev, &qp_table->qp_table, qp->qpn); - -err_out: - if (!sqpn) - mlx4_bitmap_free(&qp_table->bitmap, qp->qpn); - - return err; -} -EXPORT_SYMBOL_GPL(mlx4_qp_alloc); - -void mlx4_qp_remove(struct mlx4_dev *dev, struct mlx4_qp *qp) -{ - struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; - unsigned long flags; - - spin_lock_irqsave(&qp_table->lock, flags); - radix_tree_delete(&dev->qp_table_tree, qp->qpn & (dev->caps.num_qps - 1)); - spin_unlock_irqrestore(&qp_table->lock, flags); -} -EXPORT_SYMBOL_GPL(mlx4_qp_remove); - -void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp) -{ - struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; - - if (atomic_dec_and_test(&qp->refcount)) - complete(&qp->free); - wait_for_completion(&qp->free); - - mlx4_table_put(dev, &qp_table->cmpt_table, qp->qpn); - mlx4_table_put(dev, &qp_table->rdmarc_table, qp->qpn); - mlx4_table_put(dev, &qp_table->altc_table, qp->qpn); - mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn); - mlx4_table_put(dev, &qp_table->qp_table, qp->qpn); - - mlx4_bitmap_free(&qp_table->bitmap, qp->qpn); -} -EXPORT_SYMBOL_GPL(mlx4_qp_free); - -static int mlx4_CONF_SPECIAL_QP(struct mlx4_dev *dev, u32 base_qpn) -{ - return mlx4_cmd(dev, 0, base_qpn, 0, MLX4_CMD_CONF_SPECIAL_QP, - MLX4_CMD_TIME_CLASS_B); -} - -int __devinit mlx4_init_qp_table(struct mlx4_dev *dev) -{ - struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; - int err; - - spin_lock_init(&qp_table->lock); - INIT_RADIX_TREE(&dev->qp_table_tree, GFP_ATOMIC); - - /* - * We reserve 2 extra QPs per port for the special QPs. The - * block of special QPs must be aligned to a multiple of 8, so - * round up. - */ - dev->caps.sqp_start = ALIGN(dev->caps.reserved_qps, 8); - err = mlx4_bitmap_init(&qp_table->bitmap, dev->caps.num_qps, - (1 << 24) - 1, dev->caps.sqp_start + 8); - if (err) - return err; - - return mlx4_CONF_SPECIAL_QP(dev, dev->caps.sqp_start); -} - -void mlx4_cleanup_qp_table(struct mlx4_dev *dev) -{ - mlx4_CONF_SPECIAL_QP(dev, 0); - mlx4_bitmap_cleanup(&mlx4_priv(dev)->qp_table.bitmap); -} diff --git a/trunk/drivers/net/mlx4/reset.c b/trunk/drivers/net/mlx4/reset.c deleted file mode 100644 index 51eef8492e93..000000000000 --- a/trunk/drivers/net/mlx4/reset.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include - -#include "mlx4.h" - -int mlx4_reset(struct mlx4_dev *dev) -{ - void __iomem *reset; - u32 *hca_header = NULL; - int pcie_cap; - u16 devctl; - u16 linkctl; - u16 vendor; - unsigned long end; - u32 sem; - int i; - int err = 0; - -#define MLX4_RESET_BASE 0xf0000 -#define MLX4_RESET_SIZE 0x400 -#define MLX4_SEM_OFFSET 0x3fc -#define MLX4_RESET_OFFSET 0x10 -#define MLX4_RESET_VALUE swab32(1) - -#define MLX4_SEM_TIMEOUT_JIFFIES (10 * HZ) -#define MLX4_RESET_TIMEOUT_JIFFIES (2 * HZ) - - /* - * Reset the chip. This is somewhat ugly because we have to - * save off the PCI header before reset and then restore it - * after the chip reboots. We skip config space offsets 22 - * and 23 since those have a special meaning. - */ - - /* Do we need to save off the full 4K PCI Express header?? */ - hca_header = kmalloc(256, GFP_KERNEL); - if (!hca_header) { - err = -ENOMEM; - mlx4_err(dev, "Couldn't allocate memory to save HCA " - "PCI header, aborting.\n"); - goto out; - } - - pcie_cap = pci_find_capability(dev->pdev, PCI_CAP_ID_EXP); - - for (i = 0; i < 64; ++i) { - if (i == 22 || i == 23) - continue; - if (pci_read_config_dword(dev->pdev, i * 4, hca_header + i)) { - err = -ENODEV; - mlx4_err(dev, "Couldn't save HCA " - "PCI header, aborting.\n"); - goto out; - } - } - - reset = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_RESET_BASE, - MLX4_RESET_SIZE); - if (!reset) { - err = -ENOMEM; - mlx4_err(dev, "Couldn't map HCA reset register, aborting.\n"); - goto out; - } - - /* grab HW semaphore to lock out flash updates */ - end = jiffies + MLX4_SEM_TIMEOUT_JIFFIES; - do { - sem = readl(reset + MLX4_SEM_OFFSET); - if (!sem) - break; - - msleep(1); - } while (time_before(jiffies, end)); - - if (sem) { - mlx4_err(dev, "Failed to obtain HW semaphore, aborting\n"); - err = -EAGAIN; - iounmap(reset); - goto out; - } - - /* actually hit reset */ - writel(MLX4_RESET_VALUE, reset + MLX4_RESET_OFFSET); - iounmap(reset); - - end = jiffies + MLX4_RESET_TIMEOUT_JIFFIES; - do { - if (!pci_read_config_word(dev->pdev, PCI_VENDOR_ID, &vendor) && - vendor != 0xffff) - break; - - msleep(1); - } while (time_before(jiffies, end)); - - if (vendor == 0xffff) { - err = -ENODEV; - mlx4_err(dev, "PCI device did not come back after reset, " - "aborting.\n"); - goto out; - } - - /* Now restore the PCI headers */ - if (pcie_cap) { - devctl = hca_header[(pcie_cap + PCI_EXP_DEVCTL) / 4]; - if (pci_write_config_word(dev->pdev, pcie_cap + PCI_EXP_DEVCTL, - devctl)) { - err = -ENODEV; - mlx4_err(dev, "Couldn't restore HCA PCI Express " - "Device Control register, aborting.\n"); - goto out; - } - linkctl = hca_header[(pcie_cap + PCI_EXP_LNKCTL) / 4]; - if (pci_write_config_word(dev->pdev, pcie_cap + PCI_EXP_LNKCTL, - linkctl)) { - err = -ENODEV; - mlx4_err(dev, "Couldn't restore HCA PCI Express " - "Link control register, aborting.\n"); - goto out; - } - } - - for (i = 0; i < 16; ++i) { - if (i * 4 == PCI_COMMAND) - continue; - - if (pci_write_config_dword(dev->pdev, i * 4, hca_header[i])) { - err = -ENODEV; - mlx4_err(dev, "Couldn't restore HCA reg %x, " - "aborting.\n", i); - goto out; - } - } - - if (pci_write_config_dword(dev->pdev, PCI_COMMAND, - hca_header[PCI_COMMAND / 4])) { - err = -ENODEV; - mlx4_err(dev, "Couldn't restore HCA COMMAND, " - "aborting.\n"); - goto out; - } - -out: - kfree(hca_header); - - return err; -} diff --git a/trunk/drivers/net/mlx4/srq.c b/trunk/drivers/net/mlx4/srq.c deleted file mode 100644 index 2134f83aed87..000000000000 --- a/trunk/drivers/net/mlx4/srq.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include - -#include "mlx4.h" -#include "icm.h" - -struct mlx4_srq_context { - __be32 state_logsize_srqn; - u8 logstride; - u8 reserved1[3]; - u8 pg_offset; - u8 reserved2[3]; - u32 reserved3; - u8 log_page_size; - u8 reserved4[2]; - u8 mtt_base_addr_h; - __be32 mtt_base_addr_l; - __be32 pd; - __be16 limit_watermark; - __be16 wqe_cnt; - u16 reserved5; - __be16 wqe_counter; - u32 reserved6; - __be64 db_rec_addr; -}; - -void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type) -{ - struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; - struct mlx4_srq *srq; - - spin_lock(&srq_table->lock); - - srq = radix_tree_lookup(&srq_table->tree, srqn & (dev->caps.num_srqs - 1)); - if (srq) - atomic_inc(&srq->refcount); - - spin_unlock(&srq_table->lock); - - if (!srq) { - mlx4_warn(dev, "Async event for bogus SRQ %08x\n", srqn); - return; - } - - srq->event(srq, event_type); - - if (atomic_dec_and_test(&srq->refcount)) - complete(&srq->free); -} - -static int mlx4_SW2HW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int srq_num) -{ - return mlx4_cmd(dev, mailbox->dma, srq_num, 0, MLX4_CMD_SW2HW_SRQ, - MLX4_CMD_TIME_CLASS_A); -} - -static int mlx4_HW2SW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, - int srq_num) -{ - return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, srq_num, - mailbox ? 0 : 1, MLX4_CMD_HW2SW_SRQ, - MLX4_CMD_TIME_CLASS_A); -} - -static int mlx4_ARM_SRQ(struct mlx4_dev *dev, int srq_num, int limit_watermark) -{ - return mlx4_cmd(dev, limit_watermark, srq_num, 0, MLX4_CMD_ARM_SRQ, - MLX4_CMD_TIME_CLASS_B); -} - -int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt, - u64 db_rec, struct mlx4_srq *srq) -{ - struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_srq_context *srq_context; - u64 mtt_addr; - int err; - - srq->srqn = mlx4_bitmap_alloc(&srq_table->bitmap); - if (srq->srqn == -1) - return -ENOMEM; - - err = mlx4_table_get(dev, &srq_table->table, srq->srqn); - if (err) - goto err_out; - - err = mlx4_table_get(dev, &srq_table->cmpt_table, srq->srqn); - if (err) - goto err_put; - - spin_lock_irq(&srq_table->lock); - err = radix_tree_insert(&srq_table->tree, srq->srqn, srq); - spin_unlock_irq(&srq_table->lock); - if (err) - goto err_cmpt_put; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) { - err = PTR_ERR(mailbox); - goto err_radix; - } - - srq_context = mailbox->buf; - memset(srq_context, 0, sizeof *srq_context); - - srq_context->state_logsize_srqn = cpu_to_be32((ilog2(srq->max) << 24) | - srq->srqn); - srq_context->logstride = srq->wqe_shift - 4; - srq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT; - - mtt_addr = mlx4_mtt_addr(dev, mtt); - srq_context->mtt_base_addr_h = mtt_addr >> 32; - srq_context->mtt_base_addr_l = cpu_to_be32(mtt_addr & 0xffffffff); - srq_context->pd = cpu_to_be32(pdn); - srq_context->db_rec_addr = cpu_to_be64(db_rec); - - err = mlx4_SW2HW_SRQ(dev, mailbox, srq->srqn); - mlx4_free_cmd_mailbox(dev, mailbox); - if (err) - goto err_radix; - - atomic_set(&srq->refcount, 1); - init_completion(&srq->free); - - return 0; - -err_radix: - spin_lock_irq(&srq_table->lock); - radix_tree_delete(&srq_table->tree, srq->srqn); - spin_unlock_irq(&srq_table->lock); - -err_cmpt_put: - mlx4_table_put(dev, &srq_table->cmpt_table, srq->srqn); - -err_put: - mlx4_table_put(dev, &srq_table->table, srq->srqn); - -err_out: - mlx4_bitmap_free(&srq_table->bitmap, srq->srqn); - - return err; -} -EXPORT_SYMBOL_GPL(mlx4_srq_alloc); - -void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq) -{ - struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; - int err; - - err = mlx4_HW2SW_SRQ(dev, NULL, srq->srqn); - if (err) - mlx4_warn(dev, "HW2SW_SRQ failed (%d) for SRQN %06x\n", err, srq->srqn); - - spin_lock_irq(&srq_table->lock); - radix_tree_delete(&srq_table->tree, srq->srqn); - spin_unlock_irq(&srq_table->lock); - - if (atomic_dec_and_test(&srq->refcount)) - complete(&srq->free); - wait_for_completion(&srq->free); - - mlx4_table_put(dev, &srq_table->table, srq->srqn); - mlx4_bitmap_free(&srq_table->bitmap, srq->srqn); -} -EXPORT_SYMBOL_GPL(mlx4_srq_free); - -int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark) -{ - return mlx4_ARM_SRQ(dev, srq->srqn, limit_watermark); -} -EXPORT_SYMBOL_GPL(mlx4_srq_arm); - -int __devinit mlx4_init_srq_table(struct mlx4_dev *dev) -{ - struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; - int err; - - spin_lock_init(&srq_table->lock); - INIT_RADIX_TREE(&srq_table->tree, GFP_ATOMIC); - - err = mlx4_bitmap_init(&srq_table->bitmap, dev->caps.num_srqs, - dev->caps.num_srqs - 1, dev->caps.reserved_srqs); - if (err) - return err; - - return 0; -} - -void mlx4_cleanup_srq_table(struct mlx4_dev *dev) -{ - mlx4_bitmap_cleanup(&mlx4_priv(dev)->srq_table.bitmap); -} diff --git a/trunk/drivers/net/natsemi.c b/trunk/drivers/net/natsemi.c index 4cf0d3fcb519..223e0e6264ba 100644 --- a/trunk/drivers/net/natsemi.c +++ b/trunk/drivers/net/natsemi.c @@ -131,6 +131,7 @@ static const char version[] __devinitdata = KERN_INFO DRV_NAME " dp8381x driver, version " DRV_VERSION ", " DRV_RELDATE "\n" KERN_INFO " originally by Donald Becker \n" + KERN_INFO " http://www.scyld.com/network/natsemi.html\n" KERN_INFO " 2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n"; MODULE_AUTHOR("Donald Becker "); diff --git a/trunk/drivers/net/ne2k-pci.c b/trunk/drivers/net/ne2k-pci.c index 995c0a5d4066..589785d1e762 100644 --- a/trunk/drivers/net/ne2k-pci.c +++ b/trunk/drivers/net/ne2k-pci.c @@ -63,7 +63,8 @@ static int options[MAX_UNITS]; /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = -KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " D. Becker/P. Gortmaker\n"; +KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " D. Becker/P. Gortmaker\n" +KERN_INFO " http://www.scyld.com/network/ne2k-pci.html\n"; #if defined(__powerpc__) #define inl_le(addr) le32_to_cpu(inl(addr)) diff --git a/trunk/drivers/net/pcmcia/ibmtr_cs.c b/trunk/drivers/net/pcmcia/ibmtr_cs.c index 4ecb8ca5a992..1060154ae750 100644 --- a/trunk/drivers/net/pcmcia/ibmtr_cs.c +++ b/trunk/drivers/net/pcmcia/ibmtr_cs.c @@ -189,20 +189,16 @@ static void ibmtr_detach(struct pcmcia_device *link) { struct ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; - struct tok_info *ti = netdev_priv(dev); DEBUG(0, "ibmtr_detach(0x%p)\n", link); - - /* - * When the card removal interrupt hits tok_interrupt(), - * bail out early, so we don't crash the machine - */ - ti->sram_phys |= 1; if (link->dev_node) unregister_netdev(dev); - - del_timer_sync(&(ti->tr_timer)); + + { + struct tok_info *ti = netdev_priv(dev); + del_timer_sync(&(ti->tr_timer)); + } ibmtr_release(link); diff --git a/trunk/drivers/net/phy/Kconfig b/trunk/drivers/net/phy/Kconfig index c0d3101eb6a0..f994f129f3d8 100644 --- a/trunk/drivers/net/phy/Kconfig +++ b/trunk/drivers/net/phy/Kconfig @@ -3,7 +3,6 @@ # menu "PHY device support" - depends on !S390 config PHYLIB tristate "PHY Device support and infrastructure" diff --git a/trunk/drivers/net/phy/phy.c b/trunk/drivers/net/phy/phy.c index f71dab347667..eed433d6056a 100644 --- a/trunk/drivers/net/phy/phy.c +++ b/trunk/drivers/net/phy/phy.c @@ -662,10 +662,10 @@ int phy_stop_interrupts(struct phy_device *phydev) phy_error(phydev); /* - * Finish any pending work; we might have been scheduled to be called - * from keventd ourselves, but cancel_work_sync() handles that. + * Finish any pending work; we might have been scheduled + * to be called from keventd ourselves, though. */ - cancel_work_sync(&phydev->phy_queue); + run_scheduled_work(&phydev->phy_queue); free_irq(phydev->irq, phydev); diff --git a/trunk/drivers/net/skge.c b/trunk/drivers/net/skge.c index e0489578945d..b07da1054add 100644 --- a/trunk/drivers/net/skge.c +++ b/trunk/drivers/net/skge.c @@ -3594,9 +3594,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, skge->duplex = -1; skge->speed = -1; skge->advertising = skge_supported_modes(hw); - - if (pci_wake_enabled(hw->pdev)) - skge->wol = wol_supported(hw) & WAKE_MAGIC; + skge->wol = pci_wake_enabled(hw->pdev) ? wol_supported(hw) : 0; hw->dev[port] = dev; diff --git a/trunk/drivers/net/sundance.c b/trunk/drivers/net/sundance.c index e1f912d04043..f51ba31970aa 100644 --- a/trunk/drivers/net/sundance.c +++ b/trunk/drivers/net/sundance.c @@ -110,7 +110,8 @@ static char *media[MAX_UNITS]; /* These identify the driver base version and may not be removed. */ static char version[] = -KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n"; +KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n" +KERN_INFO " http://www.scyld.com/network/sundance.html\n"; MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("Sundance Alta Ethernet driver"); diff --git a/trunk/drivers/net/tg3.c b/trunk/drivers/net/tg3.c index 923b9c725cc3..e5e901ecd808 100644 --- a/trunk/drivers/net/tg3.c +++ b/trunk/drivers/net/tg3.c @@ -3716,8 +3716,10 @@ static void tg3_reset_task(struct work_struct *work) unsigned int restart_timer; tg3_full_lock(tp, 0); + tp->tg3_flags |= TG3_FLAG_IN_RESET_TASK; if (!netif_running(tp->dev)) { + tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK; tg3_full_unlock(tp); return; } @@ -3748,6 +3750,8 @@ static void tg3_reset_task(struct work_struct *work) mod_timer(&tp->timer, jiffies + 1); out: + tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK; + tg3_full_unlock(tp); } @@ -7386,7 +7390,12 @@ static int tg3_close(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); - cancel_work_sync(&tp->reset_task); + /* Calling flush_scheduled_work() may deadlock because + * linkwatch_event() may be on the workqueue and it will try to get + * the rtnl_lock which we are holding. + */ + while (tp->tg3_flags & TG3_FLAG_IN_RESET_TASK) + msleep(1); netif_stop_queue(dev); diff --git a/trunk/drivers/net/tg3.h b/trunk/drivers/net/tg3.h index bd9f4f428e5b..4d334cf5a243 100644 --- a/trunk/drivers/net/tg3.h +++ b/trunk/drivers/net/tg3.h @@ -2228,7 +2228,7 @@ struct tg3 { #define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 #define TG3_FLAG_10_100_ONLY 0x01000000 #define TG3_FLAG_PAUSE_AUTONEG 0x02000000 - +#define TG3_FLAG_IN_RESET_TASK 0x04000000 #define TG3_FLAG_40BIT_DMA_BUG 0x08000000 #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 #define TG3_FLAG_SUPPORT_MSI 0x20000000 diff --git a/trunk/drivers/net/tulip/interrupt.c b/trunk/drivers/net/tulip/interrupt.c index ea896777bcaf..9b08afbd1f65 100644 --- a/trunk/drivers/net/tulip/interrupt.c +++ b/trunk/drivers/net/tulip/interrupt.c @@ -269,7 +269,7 @@ int tulip_poll(struct net_device *dev, int *budget) This would turn on IM for devices that is not contributing to backlog congestion with unnecessary latency. - We monitor the device RX-ring and have: + We monitor the the device RX-ring and have: HW Interrupt Mitigation either ON or OFF. diff --git a/trunk/drivers/net/tulip/winbond-840.c b/trunk/drivers/net/tulip/winbond-840.c index 38f3b99716b8..fa440706fb4a 100644 --- a/trunk/drivers/net/tulip/winbond-840.c +++ b/trunk/drivers/net/tulip/winbond-840.c @@ -1021,7 +1021,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) np->tx_ring[entry].length |= DescEndRing; /* Now acquire the irq spinlock. - * The difficult race is the ordering between + * The difficult race is the the ordering between * increasing np->cur_tx and setting DescOwned: * - if np->cur_tx is increased first the interrupt * handler could consider the packet as transmitted diff --git a/trunk/drivers/net/tulip/xircom_cb.c b/trunk/drivers/net/tulip/xircom_cb.c index 2470b1ee33c0..985a1810ca59 100644 --- a/trunk/drivers/net/tulip/xircom_cb.c +++ b/trunk/drivers/net/tulip/xircom_cb.c @@ -1043,7 +1043,7 @@ static int enable_promisc(struct xircom_private *card) /* -link_status() checks the links status and will return 0 for no link, 10 for 10mbit link and 100 for.. guess what. +link_status() checks the the links status and will return 0 for no link, 10 for 10mbit link and 100 for.. guess what. Must be called in locked state with interrupts disabled */ diff --git a/trunk/drivers/net/typhoon.c b/trunk/drivers/net/typhoon.c index f72573594121..f2dd7763cd0b 100644 --- a/trunk/drivers/net/typhoon.c +++ b/trunk/drivers/net/typhoon.c @@ -639,7 +639,7 @@ typhoon_issue_command(struct typhoon *tp, int num_cmd, struct cmd_desc *cmd, typhoon_inc_cmd_index(&ring->lastWrite, num_cmd); - /* "I feel a presence... another warrior is on the mesa." + /* "I feel a presence... another warrior is on the the mesa." */ wmb(); iowrite32(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY); diff --git a/trunk/drivers/net/wireless/Kconfig b/trunk/drivers/net/wireless/Kconfig index e3f5bb0fe603..e273347dc606 100644 --- a/trunk/drivers/net/wireless/Kconfig +++ b/trunk/drivers/net/wireless/Kconfig @@ -3,7 +3,6 @@ # menu "Wireless LAN" - depends on !S390 config WLAN_PRE80211 bool "Wireless LAN (pre-802.11)" diff --git a/trunk/drivers/net/wireless/airport.c b/trunk/drivers/net/wireless/airport.c index 7d5b8c2cc614..38fac3bbcd82 100644 --- a/trunk/drivers/net/wireless/airport.c +++ b/trunk/drivers/net/wireless/airport.c @@ -149,7 +149,7 @@ static int airport_hard_reset(struct orinoco_private *priv) /* Vitally important. If we don't do this it seems we get an * interrupt somewhere during the power cycle, since * hw_unavailable is already set it doesn't get ACKed, we get - * into an interrupt loop and the PMU decides to turn us + * into an interrupt loop and the the PMU decides to turn us * off. */ disable_irq(dev->irq); diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h b/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h index 10e07e865426..f8483c179e4c 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -658,6 +658,12 @@ struct bcm43xx_pio { #define BCM43xx_MAX_80211_CORES 2 +#ifdef CONFIG_BCM947XX +#define core_offset(bcm) (bcm)->current_core_offset +#else +#define core_offset(bcm) 0 +#endif + /* Generic information about a core. */ struct bcm43xx_coreinfo { u8 available:1, @@ -783,6 +789,10 @@ struct bcm43xx_private { /* The currently active core. */ struct bcm43xx_coreinfo *current_core; +#ifdef CONFIG_BCM947XX + /** current core memory offset */ + u32 current_core_offset; +#endif struct bcm43xx_coreinfo *active_80211_core; /* coreinfo structs for all possible cores follow. * Note that a core might not exist. @@ -933,25 +943,25 @@ struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy, static inline u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset) { - return ioread16(bcm->mmio_addr + offset); + return ioread16(bcm->mmio_addr + core_offset(bcm) + offset); } static inline void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value) { - iowrite16(value, bcm->mmio_addr + offset); + iowrite16(value, bcm->mmio_addr + core_offset(bcm) + offset); } static inline u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset) { - return ioread32(bcm->mmio_addr + offset); + return ioread32(bcm->mmio_addr + core_offset(bcm) + offset); } static inline void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value) { - iowrite32(value, bcm->mmio_addr + offset); + iowrite32(value, bcm->mmio_addr + core_offset(bcm) + offset); } static inline diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index 1f7731fcfbd5..e3d2e61a31ee 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -660,6 +660,10 @@ struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm, ring->routing = BCM43xx_DMA32_CLIENTTRANS; if (dma64) ring->routing = BCM43xx_DMA64_CLIENTTRANS; +#ifdef CONFIG_BCM947XX + if (bcm->pci_dev->bus->number == 0) + ring->routing = dma64 ? BCM43xx_DMA64_NOTRANS : BCM43xx_DMA32_NOTRANS; +#endif ring->bcm = bcm; ring->nr_slots = nr_slots; diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c index ef6b253a92ce..5e96bca6730a 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -61,6 +61,10 @@ MODULE_AUTHOR("Stefano Brivio"); MODULE_AUTHOR("Michael Buesch"); MODULE_LICENSE("GPL"); +#ifdef CONFIG_BCM947XX +extern char *nvram_get(char *name); +#endif + #if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO) static int modparam_pio; module_param_named(pio, modparam_pio, int, 0444); @@ -138,6 +142,10 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple fi { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Broadcom 43XG 802.11b/g */ { PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#ifdef CONFIG_BCM947XX + /* SB bus on BCM947xx */ + { PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#endif { 0 }, }; MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl); @@ -778,6 +786,9 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm) { u16 value; u16 *sprom; +#ifdef CONFIG_BCM947XX + char *c; +#endif sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16), GFP_KERNEL); @@ -785,7 +796,28 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm) printk(KERN_ERR PFX "sprom_extract OOM\n"); return -ENOMEM; } +#ifdef CONFIG_BCM947XX + sprom[BCM43xx_SPROM_BOARDFLAGS2] = atoi(nvram_get("boardflags2")); + sprom[BCM43xx_SPROM_BOARDFLAGS] = atoi(nvram_get("boardflags")); + + if ((c = nvram_get("il0macaddr")) != NULL) + e_aton(c, (char *) &(sprom[BCM43xx_SPROM_IL0MACADDR])); + + if ((c = nvram_get("et1macaddr")) != NULL) + e_aton(c, (char *) &(sprom[BCM43xx_SPROM_ET1MACADDR])); + + sprom[BCM43xx_SPROM_PA0B0] = atoi(nvram_get("pa0b0")); + sprom[BCM43xx_SPROM_PA0B1] = atoi(nvram_get("pa0b1")); + sprom[BCM43xx_SPROM_PA0B2] = atoi(nvram_get("pa0b2")); + + sprom[BCM43xx_SPROM_PA1B0] = atoi(nvram_get("pa1b0")); + sprom[BCM43xx_SPROM_PA1B1] = atoi(nvram_get("pa1b1")); + sprom[BCM43xx_SPROM_PA1B2] = atoi(nvram_get("pa1b2")); + + sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev")); +#else bcm43xx_sprom_read(bcm, sprom); +#endif /* boardflags2 */ value = sprom[BCM43xx_SPROM_BOARDFLAGS2]; @@ -1193,6 +1225,12 @@ static int _switch_core(struct bcm43xx_private *bcm, int core) goto error; udelay(10); } +#ifdef CONFIG_BCM947XX + if (bcm->pci_dev->bus->number == 0) + bcm->current_core_offset = 0x1000 * core; + else + bcm->current_core_offset = 0; +#endif return 0; error: @@ -1349,6 +1387,19 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy) if ((bcm43xx_core_enabled(bcm)) && !bcm43xx_using_pio(bcm)) { +//FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here? +#if 0 +#ifndef CONFIG_BCM947XX + /* reset all used DMA controllers. */ + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE); + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA2_BASE); + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA3_BASE); + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); + bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA1_BASE); + if (bcm->current_core->rev < 5) + bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); +#endif +#endif } if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) { bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, @@ -2089,11 +2140,32 @@ static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm) return err; } +#ifdef CONFIG_BCM947XX +static struct pci_device_id bcm43xx_47xx_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) }, + { 0 } +}; +#endif + static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) { int err; bcm->irq = bcm->pci_dev->irq; +#ifdef CONFIG_BCM947XX + if (bcm->pci_dev->bus->number == 0) { + struct pci_dev *d; + struct pci_device_id *id; + for (id = bcm43xx_47xx_ids; id->vendor; id++) { + d = pci_get_device(id->vendor, id->device, NULL); + if (d != NULL) { + bcm->irq = d->irq; + pci_dev_put(d); + break; + } + } + } +#endif err = request_irq(bcm->irq, bcm43xx_interrupt_handler, IRQF_SHARED, KBUILD_MODNAME, bcm); if (err) @@ -2573,6 +2645,10 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) chip_id_16 = 0x4610; else if ((pci_device >= 0x4710) && (pci_device <= 0x4715)) chip_id_16 = 0x4710; +#ifdef CONFIG_BCM947XX + else if ((pci_device >= 0x4320) && (pci_device <= 0x4325)) + chip_id_16 = 0x4309; +#endif else { printk(KERN_ERR PFX "Could not determine Chip ID\n"); return -ENODEV; @@ -4068,6 +4144,11 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, struct bcm43xx_private *bcm; int err; +#ifdef CONFIG_BCM947XX + if ((pdev->bus->number == 0) && (pdev->device != 0x0800)) + return -ENODEV; +#endif + #ifdef DEBUG_SINGLE_DEVICE_ONLY if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY)) return -ENODEV; diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.h index c8f3c532bab5..f76357178e4d 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -33,6 +33,25 @@ #include "bcm43xx.h" +#ifdef CONFIG_BCM947XX +#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0) + +static inline void e_aton(char *str, char *dest) +{ + int i = 0; + u16 *d = (u16 *) dest; + + for (;;) { + dest[i++] = (char) simple_strtoul(str, NULL, 16); + str += 2; + if (!*str++ || i == 6) + break; + } + for (i = 0; i < 3; i++) + d[i] = cpu_to_be16(d[i]); +} +#endif + #define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes] #define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes) /* Magic helper macro to pad structures. Ignore those above. It's magic. */ diff --git a/trunk/drivers/net/wireless/prism54/isl_ioctl.c b/trunk/drivers/net/wireless/prism54/isl_ioctl.c index 283be4a70524..841b3c136ad9 100644 --- a/trunk/drivers/net/wireless/prism54/isl_ioctl.c +++ b/trunk/drivers/net/wireless/prism54/isl_ioctl.c @@ -3054,7 +3054,7 @@ static const iw_handler prism54_handler[] = { (iw_handler) prism54_set_wap, /* SIOCSIWAP */ (iw_handler) prism54_get_wap, /* SIOCGIWAP */ (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCGIWAPLIST deprecated */ + (iw_handler) NULL, /* SIOCGIWAPLIST depreciated */ (iw_handler) prism54_set_scan, /* SIOCSIWSCAN */ (iw_handler) prism54_get_scan, /* SIOCGIWSCAN */ (iw_handler) prism54_set_essid, /* SIOCSIWESSID */ diff --git a/trunk/drivers/net/wireless/prism54/islpci_dev.c b/trunk/drivers/net/wireless/prism54/islpci_dev.c index 084795355b74..a037b11dac9d 100644 --- a/trunk/drivers/net/wireless/prism54/islpci_dev.c +++ b/trunk/drivers/net/wireless/prism54/islpci_dev.c @@ -115,7 +115,7 @@ isl_upload_firmware(islpci_private *priv) ISL38XX_MEMORY_WINDOW_SIZE : fw_len; u32 __iomem *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN; - /* set the card's base address for writing the data */ + /* set the cards base address for writting the data */ isl38xx_w32_flush(device_base, reg, ISL38XX_DIR_MEM_BASE_REG); wmb(); /* be paranoid */ diff --git a/trunk/drivers/net/wireless/wavelan_cs.c b/trunk/drivers/net/wireless/wavelan_cs.c index 5740d4d4267c..67b867f837ca 100644 --- a/trunk/drivers/net/wireless/wavelan_cs.c +++ b/trunk/drivers/net/wireless/wavelan_cs.c @@ -176,7 +176,7 @@ psa_write(struct net_device * dev, volatile u_char __iomem *verify = lp->mem + PSA_ADDR + (psaoff(0, psa_comp_number) << 1); - /* Authorize writing to PSA */ + /* Authorize writting to PSA */ hacr_write(base, HACR_PWR_STAT | HACR_ROM_WEN); while(n-- > 0) @@ -1676,7 +1676,7 @@ wv_set_frequency(u_long base, /* i/o port of the card */ fee_write(base, 0x60, dac, 2); - /* We now should verify here that the EEprom writing was ok */ + /* We now should verify here that the EEprom writting was ok */ /* ReRead the first area */ fee_read(base, 0x00, diff --git a/trunk/drivers/net/wireless/wavelan_cs.p.h b/trunk/drivers/net/wireless/wavelan_cs.p.h index 4b9de0093a7b..4d1c4905c749 100644 --- a/trunk/drivers/net/wireless/wavelan_cs.p.h +++ b/trunk/drivers/net/wireless/wavelan_cs.p.h @@ -120,7 +120,7 @@ * the Wavelan itself (NCR -> AT&T -> Lucent). * * All started with Anders Klemets , - * writing a Wavelan ISA driver for the MACH microkernel. Girish + * writting a Wavelan ISA driver for the MACH microkernel. Girish * Welling had also worked on it. * Keith Moore modify this for the Pcmcia hardware. * diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c index 8459549d0cee..e04cffc8adf3 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c @@ -40,7 +40,6 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x0df6, 0x9075), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 }, @@ -68,11 +67,8 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0586, 0x3410), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0baf, 0x0121), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B }, /* "Driverless" devices that need ejecting */ { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, - { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, {} }; diff --git a/trunk/drivers/net/yellowfin.c b/trunk/drivers/net/yellowfin.c index f2a90a7fa2d6..3f4a7cf9efea 100644 --- a/trunk/drivers/net/yellowfin.c +++ b/trunk/drivers/net/yellowfin.c @@ -109,6 +109,7 @@ static int gx_fix; /* These identify the driver base version and may not be removed. */ static char version[] __devinitdata = KERN_INFO DRV_NAME ".c:v1.05 1/09/2001 Written by Donald Becker \n" +KERN_INFO " http://www.scyld.com/network/yellowfin.html\n" KERN_INFO " (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n"; MODULE_AUTHOR("Donald Becker "); diff --git a/trunk/drivers/parport/Kconfig b/trunk/drivers/parport/Kconfig index f46c69e4ed82..36c6a1bfe558 100644 --- a/trunk/drivers/parport/Kconfig +++ b/trunk/drivers/parport/Kconfig @@ -6,7 +6,6 @@ # menu "Parallel port support" - depends on HAS_IOMEM config PARPORT tristate "Parallel port support" diff --git a/trunk/drivers/pci/pci-driver.c b/trunk/drivers/pci/pci-driver.c index 8e58ea3d95c0..3bb7739d26a5 100644 --- a/trunk/drivers/pci/pci-driver.c +++ b/trunk/drivers/pci/pci-driver.c @@ -119,7 +119,7 @@ static inline int pci_create_newid_file(struct pci_driver *drv) * system is in its list of supported devices. Returns the matching * pci_device_id structure or %NULL if there is no match. * - * Deprecated, don't use this as it will not catch any dynamic ids + * Depreciated, don't use this as it will not catch any dynamic ids * that a driver might want to check for. */ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, diff --git a/trunk/drivers/pnp/Kconfig b/trunk/drivers/pnp/Kconfig index 1959cef8e9de..c5143201419a 100644 --- a/trunk/drivers/pnp/Kconfig +++ b/trunk/drivers/pnp/Kconfig @@ -3,7 +3,6 @@ # menu "Plug and Play support" - depends on HAS_IOMEM config PNP bool "Plug and Play support" diff --git a/trunk/drivers/rtc/Kconfig b/trunk/drivers/rtc/Kconfig index 1759baad439c..5e439836db2d 100644 --- a/trunk/drivers/rtc/Kconfig +++ b/trunk/drivers/rtc/Kconfig @@ -3,7 +3,6 @@ # menu "Real Time Clock" - depends on !S390 config RTC_LIB tristate @@ -99,7 +98,7 @@ config RTC_INTF_DEV_UIE_EMUL bool "RTC UIE emulation on dev interface" depends on RTC_INTF_DEV help - Provides an emulation for RTC_UIE if the underlying rtc chip + Provides an emulation for RTC_UIE if the underlaying rtc chip driver does not expose RTC_UIE ioctls. Those requests generate once-per-second update interrupts, used for synchronization. diff --git a/trunk/drivers/rtc/rtc-sh.c b/trunk/drivers/rtc/rtc-sh.c index e0f91dfce0f5..6abf4811958c 100644 --- a/trunk/drivers/rtc/rtc-sh.c +++ b/trunk/drivers/rtc/rtc-sh.c @@ -104,7 +104,7 @@ static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id) writeb(tmp, rtc->regbase + RCR1); - rtc_update_irq(rtc->rtc_dev, 1, events); + rtc_update_irq(&rtc->rtc_dev, 1, events); spin_unlock(&rtc->lock); @@ -139,7 +139,7 @@ static irqreturn_t sh_rtc_alarm(int irq, void *dev_id) rtc->rearm_aie = 1; - rtc_update_irq(rtc->rtc_dev, 1, events); + rtc_update_irq(&rtc->rtc_dev, 1, events); } spin_unlock(&rtc->lock); @@ -153,7 +153,7 @@ static irqreturn_t sh_rtc_periodic(int irq, void *dev_id) spin_lock(&rtc->lock); - rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF); + rtc_update_irq(&rtc->rtc_dev, 1, RTC_PF | RTC_IRQF); spin_unlock(&rtc->lock); @@ -341,7 +341,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_sec--; #endif - dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " + dev_dbg(&dev, "%s: tm is secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour, diff --git a/trunk/drivers/s390/char/Kconfig b/trunk/drivers/s390/Kconfig similarity index 59% rename from trunk/drivers/s390/char/Kconfig rename to trunk/drivers/s390/Kconfig index 66102a184322..165af398fdea 100644 --- a/trunk/drivers/s390/char/Kconfig +++ b/trunk/drivers/s390/Kconfig @@ -1,9 +1,69 @@ +config CCW + bool + default y + +source "drivers/block/Kconfig" + +source "drivers/md/Kconfig" + + +menu "Character device drivers" + +config UNIX98_PTYS + bool "Unix98 PTY support" + ---help--- + A pseudo terminal (PTY) is a software device consisting of two + halves: a master and a slave. The slave device behaves identical to + a physical terminal; the master device is used by a process to + read data from and write data to the slave, thereby emulating a + terminal. Typical programs for the master side are telnet servers + and xterms. + + Linux has traditionally used the BSD-like names /dev/ptyxx for + masters and /dev/ttyxx for slaves of pseudo terminals. This scheme + has a number of problems. The GNU C library glibc 2.1 and later, + however, supports the Unix98 naming standard: in order to acquire a + pseudo terminal, a process opens /dev/ptmx; the number of the pseudo + terminal is then made available to the process and the pseudo + terminal slave can be accessed as /dev/pts/. What was + traditionally /dev/ttyp2 will then be /dev/pts/2, for example. + + The entries in /dev/pts/ are created on the fly by a virtual + file system; therefore, if you say Y here you should say Y to + "/dev/pts file system for Unix98 PTYs" as well. + + If you want to say Y here, you need to have the C library glibc 2.1 + or later (equal to libc-6.1, check with "ls -l /lib/libc.so.*"). + Read the instructions in pertaining to + pseudo terminals. It's safe to say N. + +config UNIX98_PTY_COUNT + int "Maximum number of Unix98 PTYs in use (0-2048)" + depends on UNIX98_PTYS + default "256" + help + The maximum number of Unix98 PTYs that can be used at any one time. + The default is 256, and should be enough for desktop systems. Server + machines which support incoming telnet/rlogin/ssh connections and/or + serve several X terminals may want to increase this: every incoming + connection and every xterm uses up one PTY. + + When not in use, each additional set of 256 PTYs occupy + approximately 8 KB of kernel memory on 32-bit architectures. + +config HANGCHECK_TIMER + tristate "Hangcheck timer" + help + The hangcheck-timer module detects when the system has gone + out to lunch past a certain margin. It can reboot the system + or merely print a warning. + +source "drivers/char/watchdog/Kconfig" + comment "S/390 character device drivers" - depends on S390 config TN3270 tristate "Support for locally attached 3270 terminals" - depends on CCW help Include support for IBM 3270 terminals. @@ -28,7 +88,6 @@ config TN3270_CONSOLE config TN3215 bool "Support for 3215 line mode terminal" - depends on CCW help Include support for IBM 3215 line-mode terminals. @@ -40,19 +99,12 @@ config TN3215_CONSOLE Linux system console. config CCW_CONSOLE - bool - depends on TN3215_CONSOLE || TN3270_CONSOLE - default y - -config SCLP - bool "Support for SCLP" - depends on S390 - help - Include support for the SCLP interface to the service element. - + bool + depends on TN3215_CONSOLE || TN3270_CONSOLE + default y + config SCLP_TTY bool "Support for SCLP line mode terminal" - depends on SCLP help Include support for IBM SCLP line-mode terminals. @@ -65,7 +117,6 @@ config SCLP_CONSOLE config SCLP_VT220_TTY bool "Support for SCLP VT220-compatible terminal" - depends on SCLP help Include support for an IBM SCLP VT220-compatible terminal. @@ -78,7 +129,6 @@ config SCLP_VT220_CONSOLE config SCLP_CPI tristate "Control-Program Identification" - depends on SCLP help This option enables the hardware console interface for system identification. This is commonly used for workload management and @@ -90,7 +140,6 @@ config SCLP_CPI config S390_TAPE tristate "S/390 tape device support" - depends on CCW help Select this option if you want to access channel-attached tape devices on IBM S/390 or zSeries. @@ -145,7 +194,6 @@ config VMLOGRDR config VMCP tristate "Support for the z/VM CP interface (VM only)" - depends on S390 help Select this option if you want to be able to interact with the control program on z/VM @@ -159,8 +207,33 @@ config MONREADER config MONWRITER tristate "API for writing z/VM monitor service records" - depends on S390 default "m" help Character device driver for writing z/VM monitor service records +endmenu + +menu "Cryptographic devices" + +config ZCRYPT + tristate "Support for PCI-attached cryptographic adapters" + select ZCRYPT_MONOLITHIC if ZCRYPT="y" + default "m" + help + Select this option if you want to use a PCI-attached cryptographic + adapter like: + + PCI Cryptographic Accelerator (PCICA) + + PCI Cryptographic Coprocessor (PCICC) + + PCI-X Cryptographic Coprocessor (PCIXCC) + + Crypto Express2 Coprocessor (CEX2C) + + Crypto Express2 Accelerator (CEX2A) + +config ZCRYPT_MONOLITHIC + bool "Monolithic zcrypt module" + depends on ZCRYPT="m" + help + Select this option if you want to have a single module z90crypt.ko + that contains all parts of the crypto device driver (ap bus, + request router and all the card drivers). + +endmenu diff --git a/trunk/drivers/s390/block/Kconfig b/trunk/drivers/s390/block/Kconfig index e879b212cf43..b250c5354503 100644 --- a/trunk/drivers/s390/block/Kconfig +++ b/trunk/drivers/s390/block/Kconfig @@ -1,9 +1,11 @@ +if S390 && BLOCK + comment "S/390 block device drivers" - depends on S390 && BLOCK + depends on S390 config BLK_DEV_XPRAM tristate "XPRAM disk support" - depends on S390 && BLOCK + depends on S390 help Select this option if you want to use your expanded storage on S/390 or zSeries as a disk. This is useful as a _fast_ swap device if you @@ -13,13 +15,12 @@ config BLK_DEV_XPRAM config DCSSBLK tristate "DCSSBLK support" - depends on S390 && BLOCK help Support for dcss block device config DASD tristate "Support for DASD devices" - depends on CCW && BLOCK + depends on CCW help Enable this option if you want to access DASDs directly utilizing S/390s channel subsystem commands. This is necessary for running @@ -61,3 +62,5 @@ config DASD_EER This driver provides a character device interface to the DASD extended error reporting. This is only needed if you want to use applications written for the EER facility. + +endif diff --git a/trunk/drivers/s390/block/dasd.c b/trunk/drivers/s390/block/dasd.c index bfeca57098fa..977521013fe8 100644 --- a/trunk/drivers/s390/block/dasd.c +++ b/trunk/drivers/s390/block/dasd.c @@ -2174,10 +2174,9 @@ dasd_generic_notify(struct ccw_device *cdev, int event) return ret; } -static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device, - void *rdc_buffer, - int rdc_buffer_size, - char *magic) +struct dasd_ccw_req * dasd_generic_build_rdc(struct dasd_device *device, + void *rdc_buffer, + int rdc_buffer_size, char *magic) { struct dasd_ccw_req *cqr; struct ccw1 *ccw; @@ -2220,7 +2219,6 @@ int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic, dasd_sfree_request(cqr, cqr->device); return ret; } -EXPORT_SYMBOL_GPL(dasd_generic_read_dev_chars); static int __init dasd_init(void) diff --git a/trunk/drivers/s390/block/dasd_diag.c b/trunk/drivers/s390/block/dasd_diag.c index eccac1c3b71b..e810e4a44ed4 100644 --- a/trunk/drivers/s390/block/dasd_diag.c +++ b/trunk/drivers/s390/block/dasd_diag.c @@ -50,7 +50,6 @@ struct dasd_diag_private { struct dasd_diag_rw_io iob; struct dasd_diag_init_io iib; blocknum_t pt_block; - struct ccw_dev_id dev_id; }; struct dasd_diag_req { @@ -103,7 +102,7 @@ mdsk_init_io(struct dasd_device *device, unsigned int blocksize, iib = &private->iib; memset(iib, 0, sizeof (struct dasd_diag_init_io)); - iib->dev_nr = private->dev_id.devno; + iib->dev_nr = _ccw_device_get_device_number(device->cdev); iib->block_size = blocksize; iib->offset = offset; iib->flaga = DASD_DIAG_FLAGA_DEFAULT; @@ -128,7 +127,7 @@ mdsk_term_io(struct dasd_device * device) private = (struct dasd_diag_private *) device->private; iib = &private->iib; memset(iib, 0, sizeof (struct dasd_diag_init_io)); - iib->dev_nr = private->dev_id.devno; + iib->dev_nr = _ccw_device_get_device_number(device->cdev); rc = dia250(iib, TERM_BIO); return rc; } @@ -167,7 +166,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr) private = (struct dasd_diag_private *) device->private; dreq = (struct dasd_diag_req *) cqr->data; - private->iob.dev_nr = private->dev_id.devno; + private->iob.dev_nr = _ccw_device_get_device_number(device->cdev); private->iob.key = 0; private->iob.flags = DASD_DIAG_RWFLAG_ASYNC; private->iob.block_count = dreq->block_count; @@ -324,12 +323,11 @@ dasd_diag_check_device(struct dasd_device *device) "memory allocation failed for private data"); return -ENOMEM; } - ccw_device_get_id(device->cdev, &private->dev_id); device->private = (void *) private; } /* Read Device Characteristics */ rdc_data = (void *) &(private->rdc_data); - rdc_data->dev_nr = private->dev_id.devno; + rdc_data->dev_nr = _ccw_device_get_device_number(device->cdev); rdc_data->rdc_len = sizeof (struct dasd_diag_characteristics); rc = diag210((struct diag210 *) rdc_data); diff --git a/trunk/drivers/s390/block/dasd_eckd.c b/trunk/drivers/s390/block/dasd_eckd.c index 418b4e63a4fa..c9583fbc2a7d 100644 --- a/trunk/drivers/s390/block/dasd_eckd.c +++ b/trunk/drivers/s390/block/dasd_eckd.c @@ -450,9 +450,9 @@ dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid) return 0; } -static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device, - void *rcd_buffer, - struct ciw *ciw, __u8 lpm) +struct dasd_ccw_req * dasd_eckd_build_rcd_lpm(struct dasd_device *device, + void *rcd_buffer, + struct ciw *ciw, __u8 lpm) { struct dasd_ccw_req *cqr; struct ccw1 *ccw; diff --git a/trunk/drivers/s390/block/dasd_ioctl.c b/trunk/drivers/s390/block/dasd_ioctl.c index 672eb0a3dd0b..758cfb542865 100644 --- a/trunk/drivers/s390/block/dasd_ioctl.c +++ b/trunk/drivers/s390/block/dasd_ioctl.c @@ -255,7 +255,6 @@ dasd_ioctl_information(struct dasd_device *device, unsigned long flags; int rc; struct ccw_device *cdev; - struct ccw_dev_id dev_id; if (!device->discipline->fill_info) return -EINVAL; @@ -271,9 +270,8 @@ dasd_ioctl_information(struct dasd_device *device, } cdev = device->cdev; - ccw_device_get_id(cdev, &dev_id); - dasd_info->devno = dev_id.devno; + dasd_info->devno = _ccw_device_get_device_number(device->cdev); dasd_info->schid = _ccw_device_get_subchannel_number(device->cdev); dasd_info->cu_type = cdev->id.cu_type; dasd_info->cu_model = cdev->id.cu_model; diff --git a/trunk/drivers/s390/char/monreader.c b/trunk/drivers/s390/char/monreader.c index 67009bfa093e..8df7b1323c05 100644 --- a/trunk/drivers/s390/char/monreader.c +++ b/trunk/drivers/s390/char/monreader.c @@ -97,7 +97,7 @@ static u8 user_data_sever[16] = { * Create the 8 bytes EBCDIC DCSS segment name from * an ASCII name, incl. padding */ -static void dcss_mkname(char *ascii_name, char *ebcdic_name) +static inline void dcss_mkname(char *ascii_name, char *ebcdic_name) { int i; @@ -191,7 +191,7 @@ static inline u32 mon_rec_end(struct mon_msg *monmsg) return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 8)); } -static int mon_check_mca(struct mon_msg *monmsg) +static inline int mon_check_mca(struct mon_msg *monmsg) { if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) || (mon_rec_start(monmsg) < mon_dcss_start) || @@ -209,8 +209,8 @@ static int mon_check_mca(struct mon_msg *monmsg) return 0; } -static int mon_send_reply(struct mon_msg *monmsg, - struct mon_private *monpriv) +static inline int mon_send_reply(struct mon_msg *monmsg, + struct mon_private *monpriv) { int rc; @@ -236,7 +236,7 @@ static int mon_send_reply(struct mon_msg *monmsg, return 0; } -static void mon_free_mem(struct mon_private *monpriv) +static inline void mon_free_mem(struct mon_private *monpriv) { int i; @@ -246,7 +246,7 @@ static void mon_free_mem(struct mon_private *monpriv) kfree(monpriv); } -static struct mon_private *mon_alloc_mem(void) +static inline struct mon_private *mon_alloc_mem(void) { int i; struct mon_private *monpriv; @@ -307,7 +307,7 @@ static inline void mon_next_mca(struct mon_msg *monmsg) monmsg->pos = 0; } -static struct mon_msg *mon_next_message(struct mon_private *monpriv) +static inline struct mon_msg *mon_next_message(struct mon_private *monpriv) { struct mon_msg *monmsg; diff --git a/trunk/drivers/s390/char/raw3270.c b/trunk/drivers/s390/char/raw3270.c index f6ef90ee3e7d..8facd14adb7c 100644 --- a/trunk/drivers/s390/char/raw3270.c +++ b/trunk/drivers/s390/char/raw3270.c @@ -589,10 +589,9 @@ static int __raw3270_size_device_vm(struct raw3270 *rp) { int rc, model; - struct ccw_dev_id dev_id; - ccw_device_get_id(rp->cdev, &dev_id); - raw3270_init_diag210.vrdcdvno = dev_id.devno; + raw3270_init_diag210.vrdcdvno = + _ccw_device_get_device_number(rp->cdev); raw3270_init_diag210.vrdclen = sizeof(struct diag210); rc = diag210(&raw3270_init_diag210); if (rc) diff --git a/trunk/drivers/s390/char/sclp.h b/trunk/drivers/s390/char/sclp.h index dbb99d1b6f57..87ac4a3ad49d 100644 --- a/trunk/drivers/s390/char/sclp.h +++ b/trunk/drivers/s390/char/sclp.h @@ -132,9 +132,6 @@ int sclp_deactivate(void); int sclp_reactivate(void); int sclp_service_call(sclp_cmdw_t command, void *sccb); -int sclp_sdias_init(void); -void sclp_sdias_exit(void); - /* useful inlines */ /* VM uses EBCDIC 037, LPAR+native(SE+HMC) use EBCDIC 500 */ diff --git a/trunk/drivers/s390/char/sclp_rw.c b/trunk/drivers/s390/char/sclp_rw.c index d6b06ab81188..bbd5b8b66f42 100644 --- a/trunk/drivers/s390/char/sclp_rw.c +++ b/trunk/drivers/s390/char/sclp_rw.c @@ -23,7 +23,7 @@ /* * The room for the SCCB (only for writing) is not equal to a pages size - * (as it is specified as the maximum size in the SCLP documentation) + * (as it is specified as the maximum size in the the SCLP documentation) * because of the additional data structure described above. */ #define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer)) diff --git a/trunk/drivers/s390/char/sclp_sdias.c b/trunk/drivers/s390/char/sclp_sdias.c index 1c064976b32b..52283daddaef 100644 --- a/trunk/drivers/s390/char/sclp_sdias.c +++ b/trunk/drivers/s390/char/sclp_sdias.c @@ -66,9 +66,9 @@ static DEFINE_MUTEX(sdias_mutex); static void sdias_callback(struct sclp_req *request, void *data) { - struct sdias_sccb *cbsccb; + struct sdias_sccb *sccb; - cbsccb = (struct sdias_sccb *) request->sccb; + sccb = (struct sdias_sccb *) request->sccb; sclp_req_done = 1; wake_up(&sdias_wq); /* Inform caller, that request is complete */ TRACE("callback done\n"); @@ -229,7 +229,7 @@ int sclp_sdias_copy(void *dest, int start_blk, int nr_blks) return rc; } -int __init sclp_sdias_init(void) +int __init sdias_init(void) { int rc; @@ -248,7 +248,7 @@ int __init sclp_sdias_init(void) return 0; } -void __exit sclp_sdias_exit(void) +void __exit sdias_exit(void) { debug_unregister(sdias_dbf); sclp_unregister(&sclp_sdias_register); diff --git a/trunk/drivers/s390/char/zcore.c b/trunk/drivers/s390/char/zcore.c index 66eb0688d523..89d439316a53 100644 --- a/trunk/drivers/s390/char/zcore.c +++ b/trunk/drivers/s390/char/zcore.c @@ -21,7 +21,6 @@ #include #include #include -#include "sclp.h" #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x) #define MSG(x...) printk( KERN_ALERT x ) @@ -565,6 +564,8 @@ static void __init zcore_header_init(int arch, struct zcore_header *hdr) get_cpu_id(&hdr->cpu_id); } +extern int sdias_init(void); + static int __init zcore_init(void) { unsigned char arch; @@ -581,7 +582,7 @@ static int __init zcore_init(void) TRACE("wwpn: %llx\n", (unsigned long long) ipl_info.data.fcp.wwpn); TRACE("lun: %llx\n", (unsigned long long) ipl_info.data.fcp.lun); - rc = sclp_sdias_init(); + rc = sdias_init(); if (rc) goto fail; @@ -633,10 +634,12 @@ static int __init zcore_init(void) return rc; } +extern void sdias_exit(void); + static void __exit zcore_exit(void) { debug_unregister(zcore_dbf); - sclp_sdias_exit(); + sdias_exit(); diag308(DIAG308_REL_HSA, NULL); } diff --git a/trunk/drivers/s390/cio/css.c b/trunk/drivers/s390/cio/css.c index dfca0ef139fd..27c6d9e55b23 100644 --- a/trunk/drivers/s390/cio/css.c +++ b/trunk/drivers/s390/cio/css.c @@ -191,7 +191,8 @@ static int css_register_subchannel(struct subchannel *sch) return ret; } -static int css_probe_device(struct subchannel_id schid) +int +css_probe_device(struct subchannel_id schid) { int ret; struct subchannel *sch; diff --git a/trunk/drivers/s390/cio/css.h b/trunk/drivers/s390/cio/css.h index ed7977531c3f..71fcfdc42800 100644 --- a/trunk/drivers/s390/cio/css.h +++ b/trunk/drivers/s390/cio/css.h @@ -138,7 +138,9 @@ struct css_driver { * all css_drivers have the css_bus_type */ extern struct bus_type css_bus_type; +extern struct css_driver io_subchannel_driver; +extern int css_probe_device(struct subchannel_id); extern int css_sch_device_register(struct subchannel *); extern void css_sch_device_unregister(struct subchannel *); extern struct subchannel * get_subchannel_by_schid(struct subchannel_id); diff --git a/trunk/drivers/s390/cio/device.c b/trunk/drivers/s390/cio/device.c index a8b373f69cf0..a23ff582db9d 100644 --- a/trunk/drivers/s390/cio/device.c +++ b/trunk/drivers/s390/cio/device.c @@ -129,7 +129,7 @@ static void io_subchannel_verify(struct device *); static void io_subchannel_ioterm(struct device *); static void io_subchannel_shutdown(struct subchannel *); -static struct css_driver io_subchannel_driver = { +struct css_driver io_subchannel_driver = { .subchannel_type = SUBCHANNEL_TYPE_IO, .drv = { .name = "io_subchannel", @@ -546,7 +546,7 @@ static struct attribute_group ccwdev_attr_group = { .attrs = ccwdev_attrs, }; -static struct attribute_group *ccwdev_attr_groups[] = { +struct attribute_group *ccwdev_attr_groups[] = { &ccwdev_attr_group, NULL, }; diff --git a/trunk/drivers/s390/cio/device_ops.c b/trunk/drivers/s390/cio/device_ops.c index a5d263fb55ae..16f59fcb66b1 100644 --- a/trunk/drivers/s390/cio/device_ops.c +++ b/trunk/drivers/s390/cio/device_ops.c @@ -616,17 +616,6 @@ ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no) return chp_get_chp_desc(chpid); } -/** - * ccw_device_get_id - obtain a ccw device id - * @cdev: device to obtain the id for - * @dev_id: where to fill in the values - */ -void ccw_device_get_id(struct ccw_device *cdev, struct ccw_dev_id *dev_id) -{ - *dev_id = cdev->private->dev_id; -} -EXPORT_SYMBOL(ccw_device_get_id); - // FIXME: these have to go: int diff --git a/trunk/drivers/s390/cio/qdio.c b/trunk/drivers/s390/cio/qdio.c index e70aeb7a3781..f770018fe1d5 100644 --- a/trunk/drivers/s390/cio/qdio.c +++ b/trunk/drivers/s390/cio/qdio.c @@ -1983,7 +1983,6 @@ qdio_handle_pci(struct qdio_irq *irq_ptr) if (q->is_input_q&QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT) qdio_mark_q(q); else { - qdio_perf_stat_dec(&perf_stats.tl_runs); __qdio_inbound_processing(q); } } diff --git a/trunk/drivers/s390/net/Kconfig b/trunk/drivers/s390/net/Kconfig index eada69dec4fe..f98fa465df0a 100644 --- a/trunk/drivers/s390/net/Kconfig +++ b/trunk/drivers/s390/net/Kconfig @@ -3,7 +3,7 @@ menu "S/390 network device drivers" config LCS tristate "Lan Channel Station Interface" - depends on CCW && NETDEVICES && (NET_ETHERNET || TR || FDDI) + depends on NETDEVICES && (NET_ETHERNET || TR || FDDI) help Select this option if you want to use LCS networking on IBM S/390 or zSeries. This device driver supports Token Ring (IEEE 802.5), @@ -13,7 +13,7 @@ config LCS config CTC tristate "CTC device support" - depends on CCW && NETDEVICES + depends on NETDEVICES help Select this option if you want to use channel-to-channel networking on IBM S/390 or zSeries. This device driver supports real CTC @@ -42,7 +42,7 @@ config SMSGIUCV config CLAW tristate "CLAW device support" - depends on CCW && NETDEVICES + depends on NETDEVICES help This driver supports channel attached CLAW devices. CLAW is Common Link Access for Workstation. Common devices @@ -52,7 +52,7 @@ config CLAW config QETH tristate "Gigabit Ethernet device support" - depends on CCW && NETDEVICES && IP_MULTICAST && QDIO + depends on NETDEVICES && IP_MULTICAST && QDIO help This driver supports the IBM S/390 and zSeries OSA Express adapters in QDIO mode (all media types), HiperSockets interfaces and VM GuestLAN diff --git a/trunk/drivers/s390/net/qeth_main.c b/trunk/drivers/s390/net/qeth_main.c index 0b96d49dd636..29d176036e5c 100644 --- a/trunk/drivers/s390/net/qeth_main.c +++ b/trunk/drivers/s390/net/qeth_main.c @@ -2860,7 +2860,7 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, if (!atomic_read(&queue->set_pci_flags_count)){ /* * there's no outstanding PCI any more, so we - * have to request a PCI to be sure that the PCI + * have to request a PCI to be sure the the PCI * will wake at some time in the future then we * can flush packed buffers that might still be * hanging around, which can happen if no diff --git a/trunk/drivers/s390/net/qeth_mpc.c b/trunk/drivers/s390/net/qeth_mpc.c index f29a4bc4f6f2..f54fdfdbf06f 100644 --- a/trunk/drivers/s390/net/qeth_mpc.c +++ b/trunk/drivers/s390/net/qeth_mpc.c @@ -162,7 +162,7 @@ struct ipa_rc_msg { char *msg; }; -static struct ipa_rc_msg qeth_ipa_rc_msg[] = { +struct ipa_rc_msg qeth_ipa_rc_msg[] = { {IPA_RC_SUCCESS, "success"}, {IPA_RC_NOTSUPP, "Command not supported"}, {IPA_RC_IP_TABLE_FULL, "Add Addr IP Table Full - ipv6"}, @@ -226,7 +226,7 @@ struct ipa_cmd_names { char *name; }; -static struct ipa_cmd_names qeth_ipa_cmd_names[] = { +struct ipa_cmd_names qeth_ipa_cmd_names[] = { {IPA_CMD_STARTLAN, "startlan"}, {IPA_CMD_STOPLAN, "stoplan"}, {IPA_CMD_SETVMAC, "setvmac"}, diff --git a/trunk/drivers/s390/scsi/zfcp_aux.c b/trunk/drivers/s390/scsi/zfcp_aux.c index ddff40c4212c..324899c96efe 100644 --- a/trunk/drivers/s390/scsi/zfcp_aux.c +++ b/trunk/drivers/s390/scsi/zfcp_aux.c @@ -607,7 +607,8 @@ zfcp_sg_list_free(struct zfcp_sg_list *sg_list) * @sg_count: elements in array * Return: size of entire scatter-gather list */ -static size_t zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count) +size_t +zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count) { unsigned int i; struct scatterlist *p; @@ -974,7 +975,8 @@ zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter) mempool_destroy(adapter->pool.data_gid_pn); } -static void zfcp_dummy_release(struct device *dev) +void +zfcp_dummy_release(struct device *dev) { return; } @@ -1334,7 +1336,7 @@ zfcp_nameserver_enqueue(struct zfcp_adapter *adapter) #define ZFCP_LOG_AREA ZFCP_LOG_AREA_FC -static void +void zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter, struct fsf_status_read_buffer *status_buffer) { diff --git a/trunk/drivers/s390/scsi/zfcp_dbf.c b/trunk/drivers/s390/scsi/zfcp_dbf.c index 5f3212440f68..d8191d115c14 100644 --- a/trunk/drivers/s390/scsi/zfcp_dbf.c +++ b/trunk/drivers/s390/scsi/zfcp_dbf.c @@ -478,7 +478,7 @@ static struct debug_view zfcp_hba_dbf_view = { NULL }; -static void +void _zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req, u32 s_id, u32 d_id, void *buffer, int buflen) { diff --git a/trunk/drivers/s390/scsi/zfcp_qdio.c b/trunk/drivers/s390/scsi/zfcp_qdio.c index bdf5782b8a7a..cb08ca3cc0f9 100644 --- a/trunk/drivers/s390/scsi/zfcp_qdio.c +++ b/trunk/drivers/s390/scsi/zfcp_qdio.c @@ -222,7 +222,7 @@ zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status, * Since we have been using this adapter, it is save to assume * that it is not failed but recoverable. The card seems to * report link-up events by self-initiated queue shutdown. - * That is why we need to clear the link-down flag + * That is why we need to clear the the link-down flag * which is set again in case we have missed by a mile. */ zfcp_erp_adapter_reopen( diff --git a/trunk/drivers/sbus/char/bpp.c b/trunk/drivers/sbus/char/bpp.c index 4fab0c23814c..74b999d77bbf 100644 --- a/trunk/drivers/sbus/char/bpp.c +++ b/trunk/drivers/sbus/char/bpp.c @@ -156,7 +156,7 @@ static unsigned short get_pins(unsigned minor) #define BPP_ICR 0x18 #define BPP_SIZE 0x1A -/* BPP_CSR. Bits of type RW1 are cleared with writing '1'. */ +/* BPP_CSR. Bits of type RW1 are cleared with writting '1'. */ #define P_DEV_ID_MASK 0xf0000000 /* R */ #define P_DEV_ID_ZEBRA 0x40000000 #define P_DEV_ID_L64854 0xa0000000 /* == NCR 89C100+89C105. Pity. */ diff --git a/trunk/drivers/scsi/aic7xxx/aic79xx_pci.c b/trunk/drivers/scsi/aic7xxx/aic79xx_pci.c index 0bada0028aa0..8d72bbae96ad 100644 --- a/trunk/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/trunk/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -966,7 +966,7 @@ ahd_aic790X_setup(struct ahd_softc *ahd) | AHD_BUSFREEREV_BUG; ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG; - /* If the user requested that the SLOWCRC bit to be set. */ + /* If the user requested the the SLOWCRC bit to be set. */ if (aic79xx_slowcrc) ahd->features |= AHD_AIC79XXB_SLOWCRC; diff --git a/trunk/drivers/scsi/aic94xx/Makefile b/trunk/drivers/scsi/aic94xx/Makefile index e78ce0fa44d2..e6b70123940c 100644 --- a/trunk/drivers/scsi/aic94xx/Makefile +++ b/trunk/drivers/scsi/aic94xx/Makefile @@ -6,7 +6,7 @@ # # This file is licensed under GPLv2. # -# This file is part of the aic94xx driver. +# This file is part of the the aic94xx driver. # # The aic94xx driver is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as diff --git a/trunk/drivers/scsi/dc395x.c b/trunk/drivers/scsi/dc395x.c index 564ea90ed3a0..a965ed3548d5 100644 --- a/trunk/drivers/scsi/dc395x.c +++ b/trunk/drivers/scsi/dc395x.c @@ -541,7 +541,7 @@ static struct ParameterData __devinitdata cfg_data[] = { /* - * Safe settings. If set to zero the BIOS/default values with + * Safe settings. If set to zero the the BIOS/default values with * command line overrides will be used. If set to 1 then safe and * slow settings will be used. */ @@ -617,7 +617,7 @@ static void __devinit fix_settings(void) /* * Mapping from the eeprom delay index value (index into this array) - * to the number of actual seconds that the delay should be for. + * to the the number of actual seconds that the delay should be for. */ static char __devinitdata eeprom_index_to_delay_map[] = { 1, 3, 5, 10, 16, 30, 60, 120 }; @@ -4136,7 +4136,7 @@ static void __devinit trms1040_write_all(struct NvRamType *eeprom, unsigned long * @io_port: base I/O address * @addr: offset into SEEPROM * - * Returns the byte read. + * Returns the the byte read. **/ static u8 __devinit trms1040_get_data(unsigned long io_port, u8 addr) { diff --git a/trunk/drivers/scsi/ide-scsi.c b/trunk/drivers/scsi/ide-scsi.c index 8263f752809d..2b5b8a93bc10 100644 --- a/trunk/drivers/scsi/ide-scsi.c +++ b/trunk/drivers/scsi/ide-scsi.c @@ -721,23 +721,19 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r return ide_stopped; } -#ifdef CONFIG_IDE_PROC_FS static void idescsi_add_settings(ide_drive_t *drive) { idescsi_scsi_t *scsi = drive_to_idescsi(drive); /* - * drive setting name read/write data type min max mul_factor div_factor data pointer set function + * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function */ - ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); - ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); - ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); - ide_add_setting(drive, "transform", SETTING_RW, TYPE_INT, 0, 3, 1, 1, &scsi->transform, NULL); - ide_add_setting(drive, "log", SETTING_RW, TYPE_INT, 0, 1, 1, 1, &scsi->log, NULL); + ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); + ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); + ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); + ide_add_setting(drive, "transform", SETTING_RW, -1, -1, TYPE_INT, 0, 3, 1, 1, &scsi->transform, NULL); + ide_add_setting(drive, "log", SETTING_RW, -1, -1, TYPE_INT, 0, 1, 1, 1, &scsi->log, NULL); } -#else -static inline void idescsi_add_settings(ide_drive_t *drive) { ; } -#endif /* * Driver initialization. @@ -760,7 +756,7 @@ static void ide_scsi_remove(ide_drive_t *drive) struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost); struct gendisk *g = scsi->disk; - ide_proc_unregister_driver(drive, scsi->driver); + ide_unregister_subdriver(drive, scsi->driver); ide_unregister_region(g); @@ -774,11 +770,13 @@ static void ide_scsi_remove(ide_drive_t *drive) static int ide_scsi_probe(ide_drive_t *); -#ifdef CONFIG_IDE_PROC_FS +#ifdef CONFIG_PROC_FS static ide_proc_entry_t idescsi_proc[] = { { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, { NULL, 0, NULL, NULL } }; +#else +# define idescsi_proc NULL #endif static ide_driver_t idescsi_driver = { @@ -792,13 +790,11 @@ static ide_driver_t idescsi_driver = { .version = IDESCSI_VERSION, .media = ide_scsi, .supports_dsc_overlap = 0, + .proc = idescsi_proc, .do_request = idescsi_do_request, .end_request = idescsi_end_request, .error = idescsi_atapi_error, .abort = idescsi_atapi_abort, -#ifdef CONFIG_IDE_PROC_FS - .proc = idescsi_proc, -#endif }; static int idescsi_ide_open(struct inode *inode, struct file *filp) @@ -1157,7 +1153,7 @@ static int ide_scsi_probe(ide_drive_t *drive) idescsi->host = host; idescsi->disk = g; g->private_data = &idescsi->driver; - ide_proc_register_driver(drive, &idescsi_driver); + ide_register_subdriver(drive, &idescsi_driver); err = 0; idescsi_setup(drive, idescsi); g->fops = &idescsi_ops; @@ -1169,7 +1165,7 @@ static int ide_scsi_probe(ide_drive_t *drive) } /* fall through on error */ ide_unregister_region(g); - ide_proc_unregister_driver(drive, &idescsi_driver); + ide_unregister_subdriver(drive, &idescsi_driver); put_disk(g); out_host_put: diff --git a/trunk/drivers/scsi/scsi_lib.c b/trunk/drivers/scsi/scsi_lib.c index 1f5a07bf2a75..61fbcdcbb009 100644 --- a/trunk/drivers/scsi/scsi_lib.c +++ b/trunk/drivers/scsi/scsi_lib.c @@ -173,7 +173,7 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) * @retries: number of times to retry request * @flags: or into request flags; * - * returns the req->errors value which is the scsi_cmnd result + * returns the req->errors value which is the the scsi_cmnd result * field. **/ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, diff --git a/trunk/drivers/serial/Kconfig b/trunk/drivers/serial/Kconfig index a6f5bfbb777b..e8efe938c4e7 100644 --- a/trunk/drivers/serial/Kconfig +++ b/trunk/drivers/serial/Kconfig @@ -5,7 +5,6 @@ # menu "Serial drivers" - depends on HAS_IOMEM # # The new 8250/16550 serial drivers diff --git a/trunk/drivers/serial/sunzilog.c b/trunk/drivers/serial/sunzilog.c index 0985193dc57d..da73205e54cd 100644 --- a/trunk/drivers/serial/sunzilog.c +++ b/trunk/drivers/serial/sunzilog.c @@ -92,8 +92,6 @@ struct uart_sunzilog_port { #define SUNZILOG_FLAG_REGS_HELD 0x00000040 #define SUNZILOG_FLAG_TX_STOPPED 0x00000080 #define SUNZILOG_FLAG_TX_ACTIVE 0x00000100 -#define SUNZILOG_FLAG_ESCC 0x00000200 -#define SUNZILOG_FLAG_ISR_HANDLER 0x00000400 unsigned int cflag; @@ -176,11 +174,9 @@ static void sunzilog_clear_fifo(struct zilog_channel __iomem *channel) /* This function must only be called when the TX is not busy. The UART * port lock must be held and local interrupts disabled. */ -static int __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs) +static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs) { int i; - int escc; - unsigned char r15; /* Let pending transmits finish. */ for (i = 0; i < 1000; i++) { @@ -233,25 +229,11 @@ static int __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *r write_zsreg(channel, R14, regs[R14]); /* External status interrupt control. */ - write_zsreg(channel, R15, (regs[R15] | WR7pEN) & ~FIFOEN); - - /* ESCC Extension Register */ - r15 = read_zsreg(channel, R15); - if (r15 & 0x01) { - write_zsreg(channel, R7, regs[R7p]); - - /* External status interrupt and FIFO control. */ - write_zsreg(channel, R15, regs[R15] & ~WR7pEN); - escc = 1; - } else { - /* Clear FIFO bit case it is an issue */ - regs[R15] &= ~FIFOEN; - escc = 0; - } + write_zsreg(channel, R15, regs[R15]); /* Reset external status interrupts. */ - write_zsreg(channel, R0, RES_EXT_INT); /* First Latch */ - write_zsreg(channel, R0, RES_EXT_INT); /* Second Latch */ + write_zsreg(channel, R0, RES_EXT_INT); + write_zsreg(channel, R0, RES_EXT_INT); /* Rewrite R3/R5, this time without enables masked. */ write_zsreg(channel, R3, regs[R3]); @@ -259,8 +241,6 @@ static int __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *r /* Rewrite R1, this time without IRQ enabled masked. */ write_zsreg(channel, R1, regs[R1]); - - return escc; } /* Reprogram the Zilog channel HW registers with the copies found in the @@ -751,7 +731,7 @@ static void sunzilog_enable_ms(struct uart_port *port) up->curregs[R15] = new_reg; /* NOTE: Not subject to 'transmitter active' rule. */ - write_zsreg(channel, R15, up->curregs[R15] & ~WR7pEN); + write_zsreg(channel, R15, up->curregs[R15]); } } @@ -881,44 +861,44 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag, up->curregs[R14] = BRSRC | BRENAB; /* Character size, stop bits, and parity. */ - up->curregs[R3] &= ~RxN_MASK; - up->curregs[R5] &= ~TxN_MASK; + up->curregs[3] &= ~RxN_MASK; + up->curregs[5] &= ~TxN_MASK; switch (cflag & CSIZE) { case CS5: - up->curregs[R3] |= Rx5; - up->curregs[R5] |= Tx5; + up->curregs[3] |= Rx5; + up->curregs[5] |= Tx5; up->parity_mask = 0x1f; break; case CS6: - up->curregs[R3] |= Rx6; - up->curregs[R5] |= Tx6; + up->curregs[3] |= Rx6; + up->curregs[5] |= Tx6; up->parity_mask = 0x3f; break; case CS7: - up->curregs[R3] |= Rx7; - up->curregs[R5] |= Tx7; + up->curregs[3] |= Rx7; + up->curregs[5] |= Tx7; up->parity_mask = 0x7f; break; case CS8: default: - up->curregs[R3] |= Rx8; - up->curregs[R5] |= Tx8; + up->curregs[3] |= Rx8; + up->curregs[5] |= Tx8; up->parity_mask = 0xff; break; }; - up->curregs[R4] &= ~0x0c; + up->curregs[4] &= ~0x0c; if (cflag & CSTOPB) - up->curregs[R4] |= SB2; + up->curregs[4] |= SB2; else - up->curregs[R4] |= SB1; + up->curregs[4] |= SB1; if (cflag & PARENB) - up->curregs[R4] |= PAR_ENAB; + up->curregs[4] |= PAR_ENAB; else - up->curregs[R4] &= ~PAR_ENAB; + up->curregs[4] &= ~PAR_ENAB; if (!(cflag & PARODD)) - up->curregs[R4] |= PAR_EVEN; + up->curregs[4] |= PAR_EVEN; else - up->curregs[R4] &= ~PAR_EVEN; + up->curregs[4] &= ~PAR_EVEN; up->port.read_status_mask = Rx_OVR; if (iflag & INPCK) @@ -972,9 +952,7 @@ sunzilog_set_termios(struct uart_port *port, struct ktermios *termios, static const char *sunzilog_type(struct uart_port *port) { - struct uart_sunzilog_port *up = UART_ZILOG(port); - - return (up->flags & SUNZILOG_FLAG_ESCC) ? "zs (ESCC)" : "zs"; + return "zs"; } /* We do not request/release mappings of the registers here, this @@ -1192,7 +1170,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options) spin_lock_irqsave(&up->port.lock, flags); - up->curregs[R15] |= BRKIE; + up->curregs[R15] = BRKIE; sunzilog_convert_to_zs(up, con->cflag, 0, brg); sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); @@ -1251,7 +1229,7 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe baud = 4800; } - up->curregs[R15] |= BRKIE; + up->curregs[R15] = BRKIE; brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); sunzilog_convert_to_zs(up, up->cflag, 0, brg); sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); @@ -1305,18 +1283,8 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) if (up->flags & (SUNZILOG_FLAG_CONS_KEYB | SUNZILOG_FLAG_CONS_MOUSE)) { - up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; - up->curregs[R4] = PAR_EVEN | X16CLK | SB1; - up->curregs[R3] = RxENAB | Rx8; - up->curregs[R5] = TxENAB | Tx8; - up->curregs[R6] = 0x00; /* SDLC Address */ - up->curregs[R7] = 0x7E; /* SDLC Flag */ - up->curregs[R9] = NV; - up->curregs[R7p] = 0x00; sunzilog_init_kbdms(up, up->port.line); - /* Only enable interrupts if an ISR handler available */ - if (up->flags & SUNZILOG_FLAG_ISR_HANDLER) - up->curregs[R9] |= MIE; + up->curregs[R9] |= (NV | MIE); write_zsreg(channel, R9, up->curregs[R9]); } else { /* Normal serial TTY. */ @@ -1325,9 +1293,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) up->curregs[R4] = PAR_EVEN | X16CLK | SB1; up->curregs[R3] = RxENAB | Rx8; up->curregs[R5] = TxENAB | Tx8; - up->curregs[R6] = 0x00; /* SDLC Address */ - up->curregs[R7] = 0x7E; /* SDLC Flag */ - up->curregs[R9] = NV; + up->curregs[R9] = NV | MIE; up->curregs[R10] = NRZ; up->curregs[R11] = TCBR | RCBR; baud = 9600; @@ -1335,14 +1301,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up) up->curregs[R12] = (brg & 0xff); up->curregs[R13] = (brg >> 8) & 0xff; up->curregs[R14] = BRSRC | BRENAB; - up->curregs[R15] = FIFOEN; /* Use FIFO if on ESCC */ - up->curregs[R7p] = TxFIFO_LVL | RxFIFO_LVL; - if (__load_zsregs(channel, up->curregs)) { - up->flags |= SUNZILOG_FLAG_ESCC; - } - /* Only enable interrupts if an ISR handler available */ - if (up->flags & SUNZILOG_FLAG_ISR_HANDLER) - up->curregs[R9] |= MIE; + __load_zsregs(channel, up->curregs); write_zsreg(channel, R9, up->curregs[R9]); } @@ -1431,14 +1390,12 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m return err; } } else { - printk(KERN_INFO "%s: Keyboard at MMIO 0x%lx (irq = %d) " - "is a %s\n", - op->dev.bus_id, up[0].port.mapbase, op->irqs[0], - sunzilog_type (&up[0].port)); - printk(KERN_INFO "%s: Mouse at MMIO 0x%lx (irq = %d) " - "is a %s\n", - op->dev.bus_id, up[1].port.mapbase, op->irqs[0], - sunzilog_type (&up[1].port)); + printk(KERN_INFO "%s: Keyboard at MMIO %lx (irq = %d) " + "is a zs\n", + op->dev.bus_id, up[0].port.mapbase, op->irqs[0]); + printk(KERN_INFO "%s: Mouse at MMIO %lx (irq = %d) " + "is a zs\n", + op->dev.bus_id, up[1].port.mapbase, op->irqs[0]); } dev_set_drvdata(&op->dev, &up[0]); @@ -1530,23 +1487,10 @@ static int __init sunzilog_init(void) goto out_unregister_uart; if (zilog_irq != -1) { - struct uart_sunzilog_port *up = sunzilog_irq_chain; err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED, "zs", sunzilog_irq_chain); if (err) goto out_unregister_driver; - - /* Enable Interrupts */ - while (up) { - struct zilog_channel __iomem *channel; - - /* printk (KERN_INFO "Enable IRQ for ZILOG Hardware %p\n", up); */ - channel = ZILOG_CHANNEL_FROM_PORT(&up->port); - up->flags |= SUNZILOG_FLAG_ISR_HANDLER; - up->curregs[R9] |= MIE; - write_zsreg(channel, R9, up->curregs[R9]); - up = up->next; - } } out: @@ -1571,20 +1515,6 @@ static void __exit sunzilog_exit(void) of_unregister_driver(&zs_driver); if (zilog_irq != -1) { - struct uart_sunzilog_port *up = sunzilog_irq_chain; - - /* Disable Interrupts */ - while (up) { - struct zilog_channel __iomem *channel; - - /* printk (KERN_INFO "Disable IRQ for ZILOG Hardware %p\n", up); */ - channel = ZILOG_CHANNEL_FROM_PORT(&up->port); - up->flags &= ~SUNZILOG_FLAG_ISR_HANDLER; - up->curregs[R9] &= ~MIE; - write_zsreg(channel, R9, up->curregs[R9]); - up = up->next; - } - free_irq(zilog_irq, sunzilog_irq_chain); zilog_irq = -1; } diff --git a/trunk/drivers/serial/sunzilog.h b/trunk/drivers/serial/sunzilog.h index 5dec7b47cc38..7939b6d71270 100644 --- a/trunk/drivers/serial/sunzilog.h +++ b/trunk/drivers/serial/sunzilog.h @@ -13,8 +13,7 @@ struct zilog_layout { struct zilog_channel channelA; }; -#define NUM_ZSREGS 17 -#define R7p 16 /* Written as R7 with P15 bit 0 set */ +#define NUM_ZSREGS 16 /* Conversion routines to/from brg time constants from/to bits * per second. @@ -128,15 +127,6 @@ struct zilog_layout { /* Write Register 7 (Sync bits 8-15/SDLC 01111110) */ -/* Write Register 7' (ESCC Only) */ -#define AUTO_TxFLAG 1 /* Automatic Tx SDLC Flag */ -#define AUTO_EOM_RST 2 /* Automatic EOM Reset */ -#define AUTOnRTS 4 /* Automatic /RTS pin deactivation */ -#define RxFIFO_LVL 8 /* Receive FIFO interrupt level */ -#define nDTRnREQ 0x10 /* /DTR/REQ timing */ -#define TxFIFO_LVL 0x20 /* Transmit FIFO interrupt level */ -#define EXT_RD_EN 0x40 /* Extended read register enable */ - /* Write Register 8 (transmit buffer) */ /* Write Register 9 (Master interrupt control) */ @@ -145,7 +135,6 @@ struct zilog_layout { #define DLC 4 /* Disable Lower Chain */ #define MIE 8 /* Master Interrupt Enable */ #define STATHI 0x10 /* Status high */ -#define SWIACK 0x20 /* Software Interrupt Ack (not on NMOS) */ #define NORESET 0 /* No reset on write to R9 */ #define CHRB 0x40 /* Reset channel B */ #define CHRA 0x80 /* Reset channel A */ @@ -198,9 +187,7 @@ struct zilog_layout { #define SNRZI 0xe0 /* Set NRZI mode */ /* Write Register 15 (external/status interrupt control) */ -#define WR7pEN 1 /* WR7' Enable (ESCC only) */ #define ZCIE 2 /* Zero count IE */ -#define FIFOEN 4 /* FIFO Enable (ESCC only) */ #define DCDIE 8 /* DCD IE */ #define SYNCIE 0x10 /* Sync/hunt IE */ #define CTSIE 0x20 /* CTS IE */ @@ -254,10 +241,6 @@ struct zilog_layout { #define CHATxIP 0x10 /* Channel A Tx IP */ #define CHARxIP 0x20 /* Channel A Rx IP */ -/* Read Register 6 (LSB frame byte count [Not on NMOS]) */ - -/* Read Register 7 (MSB frame byte count and FIFO status [Not on NMOS]) */ - /* Read Register 8 (receive data register) */ /* Read Register 10 (misc status bits) */ diff --git a/trunk/drivers/spi/Kconfig b/trunk/drivers/spi/Kconfig index 7c9d37f651e3..07c587ec71be 100644 --- a/trunk/drivers/spi/Kconfig +++ b/trunk/drivers/spi/Kconfig @@ -6,7 +6,6 @@ # fully appropriate there, so it'd need some thought to do well. # menu "SPI support" - depends on HAS_IOMEM config SPI bool "SPI support" diff --git a/trunk/drivers/spi/atmel_spi.c b/trunk/drivers/spi/atmel_spi.c index 1d8a2f6bb8eb..66e7bc985797 100644 --- a/trunk/drivers/spi/atmel_spi.c +++ b/trunk/drivers/spi/atmel_spi.c @@ -22,7 +22,10 @@ #include #include #include + +#ifdef CONFIG_ARCH_AT91 #include +#endif #include "atmel_spi.h" @@ -549,8 +552,10 @@ static int __init atmel_spi_probe(struct platform_device *pdev) goto out_free_buffer; as->irq = irq; as->clk = clk; +#ifdef CONFIG_ARCH_AT91 if (!cpu_is_at91rm9200()) as->new_1 = 1; +#endif ret = request_irq(irq, atmel_spi_interrupt, 0, pdev->dev.bus_id, master); diff --git a/trunk/drivers/telephony/Kconfig b/trunk/drivers/telephony/Kconfig index dd1d6a53f3c0..7625b1816baf 100644 --- a/trunk/drivers/telephony/Kconfig +++ b/trunk/drivers/telephony/Kconfig @@ -3,7 +3,6 @@ # menu "Telephony Support" - depends on HAS_IOMEM config PHONE tristate "Linux telephony support" diff --git a/trunk/drivers/usb/Kconfig b/trunk/drivers/usb/Kconfig index 15499b7e33f4..b847bbc8b0e1 100644 --- a/trunk/drivers/usb/Kconfig +++ b/trunk/drivers/usb/Kconfig @@ -3,7 +3,6 @@ # menu "USB support" - depends on HAS_IOMEM # Host-side USB depends on having a host controller # NOTE: dummy_hcd is always an option, but it's ignored here ... @@ -88,6 +87,8 @@ source "drivers/usb/storage/Kconfig" source "drivers/usb/image/Kconfig" +source "drivers/usb/net/Kconfig" + source "drivers/usb/mon/Kconfig" comment "USB port drivers" diff --git a/trunk/drivers/usb/Makefile b/trunk/drivers/usb/Makefile index 72464b586990..0ef090b1b37c 100644 --- a/trunk/drivers/usb/Makefile +++ b/trunk/drivers/usb/Makefile @@ -23,6 +23,13 @@ obj-$(CONFIG_USB_PRINTER) += class/ obj-$(CONFIG_USB_STORAGE) += storage/ obj-$(CONFIG_USB) += storage/ +obj-$(CONFIG_USB_CATC) += net/ +obj-$(CONFIG_USB_KAWETH) += net/ +obj-$(CONFIG_USB_PEGASUS) += net/ +obj-$(CONFIG_USB_RTL8150) += net/ +obj-$(CONFIG_USB_USBNET) += net/ +obj-$(CONFIG_USB_ZD1201) += net/ + obj-$(CONFIG_USB_MDC800) += image/ obj-$(CONFIG_USB_MICROTEK) += image/ diff --git a/trunk/drivers/usb/atm/usbatm.c b/trunk/drivers/usb/atm/usbatm.c index 11e9b15ca45a..b082d95bbbaa 100644 --- a/trunk/drivers/usb/atm/usbatm.c +++ b/trunk/drivers/usb/atm/usbatm.c @@ -1033,7 +1033,7 @@ static int usbatm_do_heavy_init(void *arg) static int usbatm_heavy_init(struct usbatm_data *instance) { - int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_FS | CLONE_FILES); + int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_KERNEL); if (ret < 0) { usb_err(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret); diff --git a/trunk/drivers/usb/misc/auerswald.c b/trunk/drivers/usb/misc/auerswald.c index 88fb56d5db8f..b5332e679c46 100644 --- a/trunk/drivers/usb/misc/auerswald.c +++ b/trunk/drivers/usb/misc/auerswald.c @@ -1307,7 +1307,7 @@ static int auerswald_addservice (pauerswald_t cp, pauerscon_t scp) } -/* remove a service from the device +/* remove a service from the the device scp->id must be set! */ static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp) { diff --git a/trunk/drivers/net/usb/Kconfig b/trunk/drivers/usb/net/Kconfig similarity index 100% rename from trunk/drivers/net/usb/Kconfig rename to trunk/drivers/usb/net/Kconfig diff --git a/trunk/drivers/net/usb/Makefile b/trunk/drivers/usb/net/Makefile similarity index 100% rename from trunk/drivers/net/usb/Makefile rename to trunk/drivers/usb/net/Makefile diff --git a/trunk/drivers/net/usb/asix.c b/trunk/drivers/usb/net/asix.c similarity index 100% rename from trunk/drivers/net/usb/asix.c rename to trunk/drivers/usb/net/asix.c diff --git a/trunk/drivers/net/usb/catc.c b/trunk/drivers/usb/net/catc.c similarity index 100% rename from trunk/drivers/net/usb/catc.c rename to trunk/drivers/usb/net/catc.c diff --git a/trunk/drivers/net/usb/cdc_ether.c b/trunk/drivers/usb/net/cdc_ether.c similarity index 100% rename from trunk/drivers/net/usb/cdc_ether.c rename to trunk/drivers/usb/net/cdc_ether.c diff --git a/trunk/drivers/net/usb/cdc_subset.c b/trunk/drivers/usb/net/cdc_subset.c similarity index 100% rename from trunk/drivers/net/usb/cdc_subset.c rename to trunk/drivers/usb/net/cdc_subset.c diff --git a/trunk/drivers/net/usb/dm9601.c b/trunk/drivers/usb/net/dm9601.c similarity index 100% rename from trunk/drivers/net/usb/dm9601.c rename to trunk/drivers/usb/net/dm9601.c diff --git a/trunk/drivers/net/usb/gl620a.c b/trunk/drivers/usb/net/gl620a.c similarity index 100% rename from trunk/drivers/net/usb/gl620a.c rename to trunk/drivers/usb/net/gl620a.c diff --git a/trunk/drivers/net/usb/kaweth.c b/trunk/drivers/usb/net/kaweth.c similarity index 100% rename from trunk/drivers/net/usb/kaweth.c rename to trunk/drivers/usb/net/kaweth.c diff --git a/trunk/drivers/net/usb/kawethfw.h b/trunk/drivers/usb/net/kawethfw.h similarity index 100% rename from trunk/drivers/net/usb/kawethfw.h rename to trunk/drivers/usb/net/kawethfw.h diff --git a/trunk/drivers/net/usb/mcs7830.c b/trunk/drivers/usb/net/mcs7830.c similarity index 100% rename from trunk/drivers/net/usb/mcs7830.c rename to trunk/drivers/usb/net/mcs7830.c diff --git a/trunk/drivers/net/usb/net1080.c b/trunk/drivers/usb/net/net1080.c similarity index 100% rename from trunk/drivers/net/usb/net1080.c rename to trunk/drivers/usb/net/net1080.c diff --git a/trunk/drivers/net/usb/pegasus.c b/trunk/drivers/usb/net/pegasus.c similarity index 100% rename from trunk/drivers/net/usb/pegasus.c rename to trunk/drivers/usb/net/pegasus.c diff --git a/trunk/drivers/net/usb/pegasus.h b/trunk/drivers/usb/net/pegasus.h similarity index 100% rename from trunk/drivers/net/usb/pegasus.h rename to trunk/drivers/usb/net/pegasus.h diff --git a/trunk/drivers/net/usb/plusb.c b/trunk/drivers/usb/net/plusb.c similarity index 100% rename from trunk/drivers/net/usb/plusb.c rename to trunk/drivers/usb/net/plusb.c diff --git a/trunk/drivers/net/usb/rndis_host.c b/trunk/drivers/usb/net/rndis_host.c similarity index 100% rename from trunk/drivers/net/usb/rndis_host.c rename to trunk/drivers/usb/net/rndis_host.c diff --git a/trunk/drivers/net/usb/rtl8150.c b/trunk/drivers/usb/net/rtl8150.c similarity index 100% rename from trunk/drivers/net/usb/rtl8150.c rename to trunk/drivers/usb/net/rtl8150.c diff --git a/trunk/drivers/net/usb/usbnet.c b/trunk/drivers/usb/net/usbnet.c similarity index 100% rename from trunk/drivers/net/usb/usbnet.c rename to trunk/drivers/usb/net/usbnet.c diff --git a/trunk/drivers/net/usb/usbnet.h b/trunk/drivers/usb/net/usbnet.h similarity index 99% rename from trunk/drivers/net/usb/usbnet.h rename to trunk/drivers/usb/net/usbnet.h index 82db5a8e528e..cbb53e065d6c 100644 --- a/trunk/drivers/net/usb/usbnet.h +++ b/trunk/drivers/usb/net/usbnet.h @@ -129,7 +129,7 @@ extern void usbnet_disconnect(struct usb_interface *); /* Drivers that reuse some of the standard USB CDC infrastructure - * (notably, using multiple interfaces according to the CDC + * (notably, using multiple interfaces according to the the CDC * union descriptor) get some helper code. */ struct cdc_state { diff --git a/trunk/drivers/net/usb/zaurus.c b/trunk/drivers/usb/net/zaurus.c similarity index 100% rename from trunk/drivers/net/usb/zaurus.c rename to trunk/drivers/usb/net/zaurus.c diff --git a/trunk/drivers/usb/serial/Kconfig b/trunk/drivers/usb/serial/Kconfig index 3efe67092f15..ba5d1dc03036 100644 --- a/trunk/drivers/usb/serial/Kconfig +++ b/trunk/drivers/usb/serial/Kconfig @@ -558,7 +558,7 @@ config USB_SERIAL_DEBUG tristate "USB Debugging Device" depends on USB_SERIAL help - Say Y here if you have a USB debugging device used to receive + Say Y here if you have a USB debugging device used to recieve debugging data from another machine. The most common of these devices is the NetChip TurboCONNECT device. diff --git a/trunk/drivers/usb/serial/aircable.c b/trunk/drivers/usb/serial/aircable.c index fbc8c27d5d99..b675735bfbee 100644 --- a/trunk/drivers/usb/serial/aircable.c +++ b/trunk/drivers/usb/serial/aircable.c @@ -9,7 +9,7 @@ * The device works as an standard CDC device, it has 2 interfaces, the first * one is for firmware access and the second is the serial one. * The protocol is very simply, there are two posibilities reading or writing. - * When writing the first urb must have a Header that starts with 0x20 0x29 the + * When writting the first urb must have a Header that starts with 0x20 0x29 the * next two bytes must say how much data will be sended. * When reading the process is almost equal except that the header starts with * 0x00 0x20. @@ -18,7 +18,7 @@ * buffer: The First and Second byte is used for a Header, the Third and Fourth * tells the device the amount of information the package holds. * Packages are 60 bytes long Header Stuff. - * When writing to the device the first two bytes of the header are 0x20 0x29 + * When writting to the device the first two bytes of the header are 0x20 0x29 * When reading the bytes are 0x00 0x20, or 0x00 0x10, there is an strange * situation, when too much data arrives to the device because it sends the data * but with out the header. I will use a simply hack to override this situation, diff --git a/trunk/drivers/usb/serial/io_edgeport.c b/trunk/drivers/usb/serial/io_edgeport.c index 4807f960150b..18f74ac76565 100644 --- a/trunk/drivers/usb/serial/io_edgeport.c +++ b/trunk/drivers/usb/serial/io_edgeport.c @@ -2465,7 +2465,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r ((edge_serial->is_epic) && (!edge_serial->epic_descriptor.Supports.IOSPWriteMCR) && (regNum == MCR))) { - dbg("SendCmdWriteUartReg - Not writing to MCR Register"); + dbg("SendCmdWriteUartReg - Not writting to MCR Register"); return 0; } @@ -2473,7 +2473,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r ((edge_serial->is_epic) && (!edge_serial->epic_descriptor.Supports.IOSPWriteLCR) && (regNum == LCR))) { - dbg ("SendCmdWriteUartReg - Not writing to LCR Register"); + dbg ("SendCmdWriteUartReg - Not writting to LCR Register"); return 0; } diff --git a/trunk/drivers/video/Kconfig b/trunk/drivers/video/Kconfig index f54438828cb9..1132ba5ff391 100644 --- a/trunk/drivers/video/Kconfig +++ b/trunk/drivers/video/Kconfig @@ -3,7 +3,6 @@ # menu "Graphics support" - depends on HAS_IOMEM source "drivers/video/backlight/Kconfig" source "drivers/video/display/Kconfig" @@ -1349,20 +1348,6 @@ config FB_VOODOO1 Please read the for supported options and other important info support. -config FB_VT8623 - tristate "VIA VT8623 support" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_TILEBLITTING - select FB_SVGALIB - select VGASTATE - select FONT_8x16 if FRAMEBUFFER_CONSOLE - ---help--- - Driver for CastleRock integrated graphics core in the - VIA VT8623 [Apollo CLE266] chipset. - config FB_CYBLA tristate "Cyberblade/i1 support" depends on FB && PCI && X86_32 && !64BIT @@ -1416,20 +1401,6 @@ config FB_TRIDENT_ACCEL This will compile the Trident frame buffer device with acceleration functions. -config FB_ARK - tristate "ARK 2000PV support" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_TILEBLITTING - select FB_SVGALIB - select VGASTATE - select FONT_8x16 if FRAMEBUFFER_CONSOLE - ---help--- - Driver for PCI graphics boards with ARK 2000PV chip - and ICS 5342 RAMDAC. - config FB_PM3 tristate "Permedia3 support" depends on FB && PCI && BROKEN diff --git a/trunk/drivers/video/Makefile b/trunk/drivers/video/Makefile index 0b70567458fb..a916c204274f 100644 --- a/trunk/drivers/video/Makefile +++ b/trunk/drivers/video/Makefile @@ -54,12 +54,10 @@ obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o obj-$(CONFIG_FB_CT65550) += chipsfb.o obj-$(CONFIG_FB_IMSTT) += imsttfb.o obj-$(CONFIG_FB_FM2) += fm2fb.o -obj-$(CONFIG_FB_VT8623) += vt8623fb.o obj-$(CONFIG_FB_CYBLA) += cyblafb.o obj-$(CONFIG_FB_TRIDENT) += tridentfb.o obj-$(CONFIG_FB_LE80578) += vermilion/ obj-$(CONFIG_FB_S3) += s3fb.o -obj-$(CONFIG_FB_ARK) += arkfb.o obj-$(CONFIG_FB_STI) += stifb.o obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o diff --git a/trunk/drivers/video/arkfb.c b/trunk/drivers/video/arkfb.c deleted file mode 100644 index ba6fede5c466..000000000000 --- a/trunk/drivers/video/arkfb.c +++ /dev/null @@ -1,1200 +0,0 @@ -/* - * linux/drivers/video/arkfb.c -- Frame buffer device driver for ARK 2000PV - * with ICS 5342 dac (it is easy to add support for different dacs). - * - * Copyright (c) 2007 Ondrej Zajicek - * - * 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. - * - * Code is based on s3fb - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* Why should fb driver call console functions? because acquire_console_sem() */ -#include