diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-02-09 14:58:11 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-09 14:58:11 +0100 |
commit | 249d51b53aea1b7cdb1be65a1a9a0c59d9e06f3e (patch) | |
tree | 7fc06930e46ee13d394f5b031166c40206af3189 | |
parent | 44581a28e805a31661469c4b466b9cd14b36e7b6 (diff) | |
parent | 8e4921515c1a379539607eb443d51c30f4f7f338 (diff) | |
download | kernel_goldelico_gta04-249d51b53aea1b7cdb1be65a1a9a0c59d9e06f3e.zip kernel_goldelico_gta04-249d51b53aea1b7cdb1be65a1a9a0c59d9e06f3e.tar.gz kernel_goldelico_gta04-249d51b53aea1b7cdb1be65a1a9a0c59d9e06f3e.tar.bz2 |
Merge commit 'v2.6.29-rc4' into core/percpu
Conflicts:
arch/x86/mach-voyager/voyager_smp.c
arch/x86/mm/fault.c
586 files changed, 9633 insertions, 5782 deletions
@@ -92,6 +92,7 @@ Rudolf Marek <R.Marek@sh.cvut.cz> Rui Saraiva <rmps@joel.ist.utl.pt> Sachin P Sant <ssant@in.ibm.com> Sam Ravnborg <sam@mars.ravnborg.org> +Sascha Hauer <s.hauer@pengutronix.de> S.ÇaÄŸlar Onur <caglar@pardus.org.tr> Simon Kelley <simon@thekelleys.org.uk> Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr> @@ -100,6 +101,7 @@ Tejun Heo <htejun@gmail.com> Thomas Graf <tgraf@suug.ch> Tony Luck <tony.luck@intel.com> Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com> -Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com> Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de> +Uwe Kleine-König <ukl@pengutronix.de> +Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com> Valdis Kletnieks <Valdis.Kletnieks@vt.edu> diff --git a/Documentation/block/queue-sysfs.txt b/Documentation/block/queue-sysfs.txt new file mode 100644 index 0000000..e164403 --- /dev/null +++ b/Documentation/block/queue-sysfs.txt @@ -0,0 +1,63 @@ +Queue sysfs files +================= + +This text file will detail the queue files that are located in the sysfs tree +for each block device. Note that stacked devices typically do not export +any settings, since their queue merely functions are a remapping target. +These files are the ones found in the /sys/block/xxx/queue/ directory. + +Files denoted with a RO postfix are readonly and the RW postfix means +read-write. + +hw_sector_size (RO) +------------------- +This is the hardware sector size of the device, in bytes. + +max_hw_sectors_kb (RO) +---------------------- +This is the maximum number of kilobytes supported in a single data transfer. + +max_sectors_kb (RW) +------------------- +This is the maximum number of kilobytes that the block layer will allow +for a filesystem request. Must be smaller than or equal to the maximum +size allowed by the hardware. + +nomerges (RW) +------------- +This enables the user to disable the lookup logic involved with IO merging +requests in the block layer. Merging may still occur through a direct +1-hit cache, since that comes for (almost) free. The IO scheduler will not +waste cycles doing tree/hash lookups for merges if nomerges is 1. Defaults +to 0, enabling all merges. + +nr_requests (RW) +---------------- +This controls how many requests may be allocated in the block layer for +read or write requests. Note that the total allocated number may be twice +this amount, since it applies only to reads or writes (not the accumulated +sum). + +read_ahead_kb (RW) +------------------ +Maximum number of kilobytes to read-ahead for filesystems on this block +device. + +rq_affinity (RW) +---------------- +If this option is enabled, the block layer will migrate request completions +to the CPU that originally submitted the request. For some workloads +this provides a significant reduction in CPU cycles due to caching effects. + +scheduler (RW) +-------------- +When read, this file will display the current and available IO schedulers +for this block device. The currently active IO scheduler will be enclosed +in [] brackets. Writing an IO scheduler name to this file will switch +control of this block device to that new IO scheduler. Note that writing +an IO scheduler name to this file will attempt to load that IO scheduler +module, if it isn't already present in the system. + + + +Jens Axboe <jens.axboe@oracle.com>, February 2009 diff --git a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt index e3443dd..917918f 100644 --- a/Documentation/cpu-freq/user-guide.txt +++ b/Documentation/cpu-freq/user-guide.txt @@ -195,19 +195,3 @@ scaling_setspeed. By "echoing" a new frequency into this you can change the speed of the CPU, but only within the limits of scaling_min_freq and scaling_max_freq. - - -3.2 Deprecated Interfaces -------------------------- - -Depending on your kernel configuration, you might find the following -cpufreq-related files: -/proc/cpufreq -/proc/sys/cpu/*/speed -/proc/sys/cpu/*/speed-min -/proc/sys/cpu/*/speed-max - -These are files for deprecated interfaces to cpufreq, which offer far -less functionality. Because of this, these interfaces aren't described -here. - diff --git a/Documentation/filesystems/sysfs-pci.txt b/Documentation/filesystems/sysfs-pci.txt index 68ef488..9f8740c 100644 --- a/Documentation/filesystems/sysfs-pci.txt +++ b/Documentation/filesystems/sysfs-pci.txt @@ -9,6 +9,7 @@ that support it. For example, a given bus might look like this: | |-- class | |-- config | |-- device + | |-- enable | |-- irq | |-- local_cpus | |-- resource @@ -32,6 +33,7 @@ files, each with their own function. class PCI class (ascii, ro) config PCI config space (binary, rw) device PCI device (ascii, ro) + enable Whether the device is enabled (ascii, rw) irq IRQ number (ascii, ro) local_cpus nearby CPU mask (cpumask, ro) resource PCI resource host addresses (ascii, ro) @@ -57,10 +59,19 @@ used to do actual device programming from userspace. Note that some platforms don't support mmapping of certain resources, so be sure to check the return value from any attempted mmap. +The 'enable' file provides a counter that indicates how many times the device +has been enabled. If the 'enable' file currently returns '4', and a '1' is +echoed into it, it will then return '5'. Echoing a '0' into it will decrease +the count. Even when it returns to 0, though, some of the initialisation +may not be reversed. + The 'rom' file is special in that it provides read-only access to the device's ROM file, if available. It's disabled by default, however, so applications should write the string "1" to the file to enable it before attempting a read -call, and disable it following the access by writing "0" to the file. +call, and disable it following the access by writing "0" to the file. Note +that the device must be enabled for a rom read to return data succesfully. +In the event a driver is not bound to the device, it can be enabled using the +'enable' file, documented above. Accessing legacy resources through sysfs ---------------------------------------- diff --git a/Documentation/filesystems/ubifs.txt b/Documentation/filesystems/ubifs.txt index 84da2a4..12fedb7 100644 --- a/Documentation/filesystems/ubifs.txt +++ b/Documentation/filesystems/ubifs.txt @@ -79,13 +79,6 @@ Mount options (*) == default. -norm_unmount (*) commit on unmount; the journal is committed - when the file-system is unmounted so that the - next mount does not have to replay the journal - and it becomes very fast; -fast_unmount do not commit on unmount; this option makes - unmount faster, but the next mount slower - because of the need to replay the journal. bulk_read read more in one go to take advantage of flash media that read faster sequentially no_bulk_read (*) do not bulk-read diff --git a/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt b/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt new file mode 100644 index 0000000..8447fd7 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt @@ -0,0 +1,180 @@ +MPC5200 Device Tree Bindings +---------------------------- + +(c) 2006-2009 Secret Lab Technologies Ltd +Grant Likely <grant.likely@secretlab.ca> + +Naming conventions +------------------ +For mpc5200 on-chip devices, the format for each compatible value is +<chip>-<device>[-<mode>]. The OS should be able to match a device driver +to the device based solely on the compatible value. If two drivers +match on the compatible list; the 'most compatible' driver should be +selected. + +The split between the MPC5200 and the MPC5200B leaves a bit of a +conundrum. How should the compatible property be set up to provide +maximum compatibility information; but still accurately describe the +chip? For the MPC5200; the answer is easy. Most of the SoC devices +originally appeared on the MPC5200. Since they didn't exist anywhere +else; the 5200 compatible properties will contain only one item; +"fsl,mpc5200-<device>". + +The 5200B is almost the same as the 5200, but not quite. It fixes +silicon bugs and it adds a small number of enhancements. Most of the +devices either provide exactly the same interface as on the 5200. A few +devices have extra functions but still have a backwards compatible mode. +To express this information as completely as possible, 5200B device trees +should have two items in the compatible list: + compatible = "fsl,mpc5200b-<device>","fsl,mpc5200-<device>"; + +It is *strongly* recommended that 5200B device trees follow this convention +(instead of only listing the base mpc5200 item). + +ie. ethernet on mpc5200: compatible = "fsl,mpc5200-fec"; + ethernet on mpc5200b: compatible = "fsl,mpc5200b-fec", "fsl,mpc5200-fec"; + +Modal devices, like PSCs, also append the configured function to the +end of the compatible field. ie. A PSC in i2s mode would specify +"fsl,mpc5200-psc-i2s", not "fsl,mpc5200-i2s". This convention is chosen to +avoid naming conflicts with non-psc devices providing the same +function. For example, "fsl,mpc5200-spi" and "fsl,mpc5200-psc-spi" describe +the mpc5200 simple spi device and a PSC spi mode respectively. + +At the time of writing, exact chip may be either 'fsl,mpc5200' or +'fsl,mpc5200b'. + +The soc node +------------ +This node describes the on chip SOC peripherals. Every mpc5200 based +board will have this node, and as such there is a common naming +convention for SOC devices. + +Required properties: +name description +---- ----------- +ranges Memory range of the internal memory mapped registers. + Should be <0 [baseaddr] 0xc000> +reg Should be <[baseaddr] 0x100> +compatible mpc5200: "fsl,mpc5200-immr" + mpc5200b: "fsl,mpc5200b-immr" +system-frequency 'fsystem' frequency in Hz; XLB, IPB, USB and PCI + clocks are derived from the fsystem clock. +bus-frequency IPB bus frequency in Hz. Clock rate + used by most of the soc devices. + +soc child nodes +--------------- +Any on chip SOC devices available to Linux must appear as soc5200 child nodes. + +Note: The tables below show the value for the mpc5200. A mpc5200b device +tree should use the "fsl,mpc5200b-<device>","fsl,mpc5200-<device>" form. + +Required soc5200 child nodes: +name compatible Description +---- ---------- ----------- +cdm@<addr> fsl,mpc5200-cdm Clock Distribution +interrupt-controller@<addr> fsl,mpc5200-pic need an interrupt + controller to boot +bestcomm@<addr> fsl,mpc5200-bestcomm Bestcomm DMA controller + +Recommended soc5200 child nodes; populate as needed for your board +name compatible Description +---- ---------- ----------- +timer@<addr> fsl,mpc5200-gpt General purpose timers +gpio@<addr> fsl,mpc5200-gpio MPC5200 simple gpio controller +gpio@<addr> fsl,mpc5200-gpio-wkup MPC5200 wakeup gpio controller +rtc@<addr> fsl,mpc5200-rtc Real time clock +mscan@<addr> fsl,mpc5200-mscan CAN bus controller +pci@<addr> fsl,mpc5200-pci PCI bridge +serial@<addr> fsl,mpc5200-psc-uart PSC in serial mode +i2s@<addr> fsl,mpc5200-psc-i2s PSC in i2s mode +ac97@<addr> fsl,mpc5200-psc-ac97 PSC in ac97 mode +spi@<addr> fsl,mpc5200-psc-spi PSC in spi mode +irda@<addr> fsl,mpc5200-psc-irda PSC in IrDA mode +spi@<addr> fsl,mpc5200-spi MPC5200 spi device +ethernet@<addr> fsl,mpc5200-fec MPC5200 ethernet device +ata@<addr> fsl,mpc5200-ata IDE ATA interface +i2c@<addr> fsl,mpc5200-i2c I2C controller +usb@<addr> fsl,mpc5200-ohci,ohci-be USB controller +xlb@<addr> fsl,mpc5200-xlb XLB arbitrator + +fsl,mpc5200-gpt nodes +--------------------- +On the mpc5200 and 5200b, GPT0 has a watchdog timer function. If the board +design supports the internal wdt, then the device node for GPT0 should +include the empty property 'fsl,has-wdt'. + +An mpc5200-gpt can be used as a single line GPIO controller. To do so, +add the following properties to the gpt node: + gpio-controller; + #gpio-cells = <2>; +When referencing the GPIO line from another node, the first cell must always +be zero and the second cell represents the gpio flags and described in the +gpio device tree binding. + +An mpc5200-gpt can be used as a single line edge sensitive interrupt +controller. To do so, add the following properties to the gpt node: + interrupt-controller; + #interrupt-cells = <1>; +When referencing the IRQ line from another node, the cell represents the +sense mode; 1 for edge rising, 2 for edge falling. + +fsl,mpc5200-psc nodes +--------------------- +The PSCs should include a cell-index which is the index of the PSC in +hardware. cell-index is used to determine which shared SoC registers to +use when setting up PSC clocking. cell-index number starts at '0'. ie: + PSC1 has 'cell-index = <0>' + PSC4 has 'cell-index = <3>' + +PSC in i2s mode: The mpc5200 and mpc5200b PSCs are not compatible when in +i2s mode. An 'mpc5200b-psc-i2s' node cannot include 'mpc5200-psc-i2s' in the +compatible field. + + +fsl,mpc5200-gpio and fsl,mpc5200-gpio-wkup nodes +------------------------------------------------ +Each GPIO controller node should have the empty property gpio-controller and +#gpio-cells set to 2. First cell is the GPIO number which is interpreted +according to the bit numbers in the GPIO control registers. The second cell +is for flags which is currently unused. + +fsl,mpc5200-fec nodes +--------------------- +The FEC node can specify one of the following properties to configure +the MII link: +- fsl,7-wire-mode - An empty property that specifies the link uses 7-wire + mode instead of MII +- current-speed - Specifies that the MII should be configured for a fixed + speed. This property should contain two cells. The + first cell specifies the speed in Mbps and the second + should be '0' for half duplex and '1' for full duplex +- phy-handle - Contains a phandle to an Ethernet PHY. + +Interrupt controller (fsl,mpc5200-pic) node +------------------------------------------- +The mpc5200 pic binding splits hardware IRQ numbers into two levels. The +split reflects the layout of the PIC hardware itself, which groups +interrupts into one of three groups; CRIT, MAIN or PERP. Also, the +Bestcomm dma engine has it's own set of interrupt sources which are +cascaded off of peripheral interrupt 0, which the driver interprets as a +fourth group, SDMA. + +The interrupts property for device nodes using the mpc5200 pic consists +of three cells; <L1 L2 level> + + L1 := [CRIT=0, MAIN=1, PERP=2, SDMA=3] + L2 := interrupt number; directly mapped from the value in the + "ICTL PerStat, MainStat, CritStat Encoded Register" + level := [LEVEL_HIGH=0, EDGE_RISING=1, EDGE_FALLING=2, LEVEL_LOW=3] + +For external IRQs, use the following interrupt property values (how to +specify external interrupts is a frequently asked question): +External interrupts: + external irq0: interrupts = <0 0 n>; + external irq1: interrupts = <1 1 n>; + external irq2: interrupts = <1 2 n>; + external irq3: interrupts = <1 3 n>; +'n' is sense (0: level high, 1: edge rising, 2: edge falling 3: level low) + diff --git a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt deleted file mode 100644 index 6f12f1c..0000000 --- a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt +++ /dev/null @@ -1,277 +0,0 @@ -MPC5200 Device Tree Bindings ----------------------------- - -(c) 2006-2007 Secret Lab Technologies Ltd -Grant Likely <grant.likely at secretlab.ca> - -********** DRAFT *********** -* WARNING: Do not depend on the stability of these bindings just yet. -* The MPC5200 device tree conventions are still in flux -* Keep an eye on the linuxppc-dev mailing list for more details -********** DRAFT *********** - -I - Introduction -================ -Boards supported by the arch/powerpc architecture require device tree be -passed by the boot loader to the kernel at boot time. The device tree -describes what devices are present on the board and how they are -connected. The device tree can either be passed as a binary blob (as -described in Documentation/powerpc/booting-without-of.txt), or passed -by Open Firmware (IEEE 1275) compatible firmware using an OF compatible -client interface API. - -This document specifies the requirements on the device-tree for mpc5200 -based boards. These requirements are above and beyond the details -specified in either the Open Firmware spec or booting-without-of.txt - -All new mpc5200-based boards are expected to match this document. In -cases where this document is not sufficient to support a new board port, -this document should be updated as part of adding the new board support. - -II - Philosophy -=============== -The core of this document is naming convention. The whole point of -defining this convention is to reduce or eliminate the number of -special cases required to support a 5200 board. If all 5200 boards -follow the same convention, then generic 5200 support code will work -rather than coding special cases for each new board. - -This section tries to capture the thought process behind why the naming -convention is what it is. - -1. names ---------- -There is strong convention/requirements already established for children -of the root node. 'cpus' describes the processor cores, 'memory' -describes memory, and 'chosen' provides boot configuration. Other nodes -are added to describe devices attached to the processor local bus. - -Following convention already established with other system-on-chip -processors, 5200 device trees should use the name 'soc5200' for the -parent node of on chip devices, and the root node should be its parent. - -Child nodes are typically named after the configured function. ie. -the FEC node is named 'ethernet', and a PSC in uart mode is named 'serial'. - -2. device_type property ------------------------ -similar to the node name convention above; the device_type reflects the -configured function of a device. ie. 'serial' for a uart and 'spi' for -an spi controller. However, while node names *should* reflect the -configured function, device_type *must* match the configured function -exactly. - -3. compatible property ----------------------- -Since device_type isn't enough to match devices to drivers, there also -needs to be a naming convention for the compatible property. Compatible -is an list of device descriptions sorted from specific to generic. For -the mpc5200, the required format for each compatible value is -<chip>-<device>[-<mode>]. The OS should be able to match a device driver -to the device based solely on the compatible value. If two drivers -match on the compatible list; the 'most compatible' driver should be -selected. - -The split between the MPC5200 and the MPC5200B leaves a bit of a -conundrum. How should the compatible property be set up to provide -maximum compatibility information; but still accurately describe the -chip? For the MPC5200; the answer is easy. Most of the SoC devices -originally appeared on the MPC5200. Since they didn't exist anywhere -else; the 5200 compatible properties will contain only one item; -"mpc5200-<device>". - -The 5200B is almost the same as the 5200, but not quite. It fixes -silicon bugs and it adds a small number of enhancements. Most of the -devices either provide exactly the same interface as on the 5200. A few -devices have extra functions but still have a backwards compatible mode. -To express this information as completely as possible, 5200B device trees -should have two items in the compatible list; -"mpc5200b-<device>\0mpc5200-<device>". It is *strongly* recommended -that 5200B device trees follow this convention (instead of only listing -the base mpc5200 item). - -If another chip appear on the market with one of the mpc5200 SoC -devices, then the compatible list should include mpc5200-<device>. - -ie. ethernet on mpc5200: compatible = "mpc5200-ethernet" - ethernet on mpc5200b: compatible = "mpc5200b-ethernet\0mpc5200-ethernet" - -Modal devices, like PSCs, also append the configured function to the -end of the compatible field. ie. A PSC in i2s mode would specify -"mpc5200-psc-i2s", not "mpc5200-i2s". This convention is chosen to -avoid naming conflicts with non-psc devices providing the same -function. For example, "mpc5200-spi" and "mpc5200-psc-spi" describe -the mpc5200 simple spi device and a PSC spi mode respectively. - -If the soc device is more generic and present on other SOCs, the -compatible property can specify the more generic device type also. - -ie. mscan: compatible = "mpc5200-mscan\0fsl,mscan"; - -At the time of writing, exact chip may be either 'mpc5200' or -'mpc5200b'. - -Device drivers should always try to match as generically as possible. - -III - Structure -=============== -The device tree for an mpc5200 board follows the structure defined in -booting-without-of.txt with the following additional notes: - -0) the root node ----------------- -Typical root description node; see booting-without-of - -1) The cpus node ----------------- -The cpus node follows the basic layout described in booting-without-of. -The bus-frequency property holds the XLB bus frequency -The clock-frequency property holds the core frequency - -2) The memory node ------------------- -Typical memory description node; see booting-without-of. - -3) The soc5200 node -------------------- -This node describes the on chip SOC peripherals. Every mpc5200 based -board will have this node, and as such there is a common naming -convention for SOC devices. - -Required properties: -name type description ----- ---- ----------- -device_type string must be "soc" -ranges int should be <0 baseaddr baseaddr+10000> -reg int must be <baseaddr 10000> -compatible string mpc5200: "mpc5200-soc" - mpc5200b: "mpc5200b-soc\0mpc5200-soc" -system-frequency int Fsystem frequency; source of all - other clocks. -bus-frequency int IPB bus frequency in HZ. Clock rate - used by most of the soc devices. -#interrupt-cells int must be <3>. - -Recommended properties: -name type description ----- ---- ----------- -model string Exact model of the chip; - ie: model="fsl,mpc5200" -revision string Silicon revision of chip - ie: revision="M08A" - -The 'model' and 'revision' properties are *strongly* recommended. Having -them presence acts as a bit of a safety net for working around as yet -undiscovered bugs on one version of silicon. For example, device drivers -can use the model and revision properties to decide if a bug fix should -be turned on. - -4) soc5200 child nodes ----------------------- -Any on chip SOC devices available to Linux must appear as soc5200 child nodes. - -Note: The tables below show the value for the mpc5200. A mpc5200b device -tree should use the "mpc5200b-<device>\0mpc5200-<device> form. - -Required soc5200 child nodes: -name device_type compatible Description ----- ----------- ---------- ----------- -cdm@<addr> cdm mpc5200-cmd Clock Distribution -pic@<addr> interrupt-controller mpc5200-pic need an interrupt - controller to boot -bestcomm@<addr> dma-controller mpc5200-bestcomm 5200 pic also requires - the bestcomm device - -Recommended soc5200 child nodes; populate as needed for your board -name device_type compatible Description ----- ----------- ---------- ----------- -gpt@<addr> gpt fsl,mpc5200-gpt General purpose timers -gpt@<addr> gpt fsl,mpc5200-gpt-gpio General purpose - timers in GPIO mode -gpio@<addr> fsl,mpc5200-gpio MPC5200 simple gpio - controller -gpio@<addr> fsl,mpc5200-gpio-wkup MPC5200 wakeup gpio - controller -rtc@<addr> rtc mpc5200-rtc Real time clock -mscan@<addr> mscan mpc5200-mscan CAN bus controller -pci@<addr> pci mpc5200-pci PCI bridge -serial@<addr> serial mpc5200-psc-uart PSC in serial mode -i2s@<addr> sound mpc5200-psc-i2s PSC in i2s mode -ac97@<addr> sound mpc5200-psc-ac97 PSC in ac97 mode -spi@<addr> spi mpc5200-psc-spi PSC in spi mode -irda@<addr> irda mpc5200-psc-irda PSC in IrDA mode -spi@<addr> spi mpc5200-spi MPC5200 spi device -ethernet@<addr> network mpc5200-fec MPC5200 ethernet device -ata@<addr> ata mpc5200-ata IDE ATA interface -i2c@<addr> i2c mpc5200-i2c I2C controller -usb@<addr> usb-ohci-be mpc5200-ohci,ohci-be USB controller -xlb@<addr> xlb mpc5200-xlb XLB arbitrator - -Important child node properties -name type description ----- ---- ----------- -cell-index int When multiple devices are present, is the - index of the device in the hardware (ie. There - are 6 PSC on the 5200 numbered PSC1 to PSC6) - PSC1 has 'cell-index = <0>' - PSC4 has 'cell-index = <3>' - -5) General Purpose Timer nodes (child of soc5200 node) -On the mpc5200 and 5200b, GPT0 has a watchdog timer function. If the board -design supports the internal wdt, then the device node for GPT0 should -include the empty property 'fsl,has-wdt'. - -6) PSC nodes (child of soc5200 node) -PSC nodes can define the optional 'port-number' property to force assignment -order of serial ports. For example, PSC5 might be physically connected to -the port labeled 'COM1' and PSC1 wired to 'COM1'. In this case, PSC5 would -have a "port-number = <0>" property, and PSC1 would have "port-number = <1>". - -PSC in i2s mode: The mpc5200 and mpc5200b PSCs are not compatible when in -i2s mode. An 'mpc5200b-psc-i2s' node cannot include 'mpc5200-psc-i2s' in the -compatible field. - -7) GPIO controller nodes -Each GPIO controller node should have the empty property gpio-controller and -#gpio-cells set to 2. First cell is the GPIO number which is interpreted -according to the bit numbers in the GPIO control registers. The second cell -is for flags which is currently unsused. - -8) FEC nodes -The FEC node can specify one of the following properties to configure -the MII link: -"fsl,7-wire-mode" - An empty property that specifies the link uses 7-wire - mode instead of MII -"current-speed" - Specifies that the MII should be configured for a fixed - speed. This property should contain two cells. The - first cell specifies the speed in Mbps and the second - should be '0' for half duplex and '1' for full duplex -"phy-handle" - Contains a phandle to an Ethernet PHY. - -IV - Extra Notes -================ - -1. Interrupt mapping --------------------- -The mpc5200 pic driver splits hardware IRQ numbers into two levels. The -split reflects the layout of the PIC hardware itself, which groups -interrupts into one of three groups; CRIT, MAIN or PERP. Also, the -Bestcomm dma engine has it's own set of interrupt sources which are -cascaded off of peripheral interrupt 0, which the driver interprets as a -fourth group, SDMA. - -The interrupts property for device nodes using the mpc5200 pic consists -of three cells; <L1 L2 level> - - L1 := [CRIT=0, MAIN=1, PERP=2, SDMA=3] - L2 := interrupt number; directly mapped from the value in the - "ICTL PerStat, MainStat, CritStat Encoded Register" - level := [LEVEL_HIGH=0, EDGE_RISING=1, EDGE_FALLING=2, LEVEL_LOW=3] - -2. Shared registers -------------------- -Some SoC devices share registers between them. ie. the i2c devices use -a single clock control register, and almost all device are affected by -the port_config register. Devices which need to manipulate shared regs -should look to the parent SoC node. The soc node is responsible -for arbitrating all shared register access. diff --git a/Documentation/video4linux/v4lgrab.c b/Documentation/video4linux/v4lgrab.c index 079b628..d6e70be 100644 --- a/Documentation/video4linux/v4lgrab.c +++ b/Documentation/video4linux/v4lgrab.c @@ -4,12 +4,21 @@ * * Compile with: * gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab - * Use as: - * v4lgrab >image.ppm + * Use as: + * v4lgrab >image.ppm * * Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org> - * Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c - * with minor modifications (Dave Forrest, drf5n@virginia.edu). + * Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c + * with minor modifications (Dave Forrest, drf5n@virginia.edu). + * + * + * For some cameras you may need to pre-load libv4l to perform + * the necessary decompression, e.g.: + * + * export LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so + * ./v4lgrab >image.ppm + * + * see http://hansdegoede.livejournal.com/3636.html for details. * */ @@ -24,7 +33,7 @@ #include <linux/types.h> #include <linux/videodev.h> -#define FILE "/dev/video0" +#define VIDEO_DEV "/dev/video0" /* Stole this from tvset.c */ @@ -90,7 +99,7 @@ int get_brightness_adj(unsigned char *image, long size, int *brightness) { int main(int argc, char ** argv) { - int fd = open(FILE, O_RDONLY), f; + int fd = open(VIDEO_DEV, O_RDONLY), f; struct video_capability cap; struct video_window win; struct video_picture vpic; @@ -100,13 +109,13 @@ int main(int argc, char ** argv) unsigned int i, src_depth; if (fd < 0) { - perror(FILE); + perror(VIDEO_DEV); exit(1); } if (ioctl(fd, VIDIOCGCAP, &cap) < 0) { perror("VIDIOGCAP"); - fprintf(stderr, "(" FILE " not a video4linux device?)\n"); + fprintf(stderr, "(" VIDEO_DEV " not a video4linux device?)\n"); close(fd); exit(1); } diff --git a/MAINTAINERS b/MAINTAINERS index 474ec0c..0ea3a6d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -911,7 +911,7 @@ S: Maintained BLACKFIN ARCHITECTURE P: Bryan Wu M: cooloney@kernel.org -L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only) +L: uclinux-dist-devel@blackfin.uclinux.org W: http://blackfin.uclinux.org S: Supported @@ -1021,6 +1021,14 @@ M: mb@bu3sch.de W: http://bu3sch.de/btgpio.php S: Maintained +BTRFS FILE SYSTEM +P: Chris Mason +M: chris.mason@oracle.com +L: linux-btrfs@vger.kernel.org +W: http://btrfs.wiki.kernel.org/ +T: git kernel.org:/pub/scm/linux/kernel/git/mason/btrfs-unstable.git +S: Maintained + BTTV VIDEO4LINUX DRIVER P: Mauro Carvalho Chehab M: mchehab@infradead.org @@ -2212,7 +2220,7 @@ P: Sean Hefty M: sean.hefty@intel.com P: Hal Rosenstock M: hal.rosenstock@gmail.com -L: general@lists.openfabrics.org +L: general@lists.openfabrics.org (moderated for non-subscribers) W: http://www.openib.org/ T: git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git S: Supported @@ -4841,6 +4849,7 @@ P: Ingo Molnar M: mingo@redhat.com P: H. Peter Anvin M: hpa@zytor.com +M: x86@kernel.org L: linux-kernel@vger.kernel.org T: git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git S: Maintained @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 29 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = Erotic Pickled Herring # *DOCUMENTATION* diff --git a/arch/alpha/include/asm/bug.h b/arch/alpha/include/asm/bug.h index 7b85b7c..1720c8a 100644 --- a/arch/alpha/include/asm/bug.h +++ b/arch/alpha/include/asm/bug.h @@ -8,12 +8,12 @@ /* ??? Would be nice to use .gprel32 here, but we can't be sure that the function loaded the GP, so this could fail in modules. */ -#define BUG() { \ +#define BUG() do { \ __asm__ __volatile__( \ "call_pal %0 # bugchk\n\t" \ ".long %1\n\t.8byte %2" \ : : "i"(PAL_bugchk), "i"(__LINE__), "i"(__FILE__)); \ - for ( ; ; ); } + for ( ; ; ); } while (0) #define HAVE_ARCH_BUG #endif diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 77b0474..85040cf 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -650,6 +650,7 @@ ENTRY(fp_enter) no_fp: mov pc, lr __und_usr_unknown: + enable_irq mov r0, sp adr lr, ret_from_exception b do_undefinstr diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 06269ea..49a6ba9 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -136,7 +136,7 @@ ENTRY(mcount) ldmia sp!, {r0-r3, pc} trace: - ldr r1, [fp, #-4] + ldr r1, [fp, #-4] @ lr of instrumented routine mov r0, lr sub r0, r0, #MCOUNT_INSN_SIZE mov lr, pc diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 4bb723e..45eacb5 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -101,7 +101,7 @@ unlock: /* Handle bad interrupts */ static struct irq_desc bad_irq_desc = { .handle_irq = handle_bad_irq, - .lock = SPIN_LOCK_UNLOCKED + .lock = __SPIN_LOCK_UNLOCKED(bad_irq_desc.lock), }; #ifdef CONFIG_CPUMASK_OFFSTACK diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c index c2a96e3..e61967d 100644 --- a/arch/arm/mach-msm/board-halibut.c +++ b/arch/arm/mach-msm/board-halibut.c @@ -27,6 +27,7 @@ #include <asm/mach/map.h> #include <asm/mach/flash.h> +#include <mach/irqs.h> #include <mach/board.h> #include <mach/msm_iomap.h> diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index 77382d8..ba5d7c0 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c @@ -181,7 +181,7 @@ void __init omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, } size = OMAP1_MMC_SIZE; - omap_mmc_add(i, base, size, irq, mmc_data[i]); + omap_mmc_add("mmci-omap", i, base, size, irq, mmc_data[i]); }; } diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c index ca7a0cc..575ba31 100644 --- a/arch/arm/mach-omap1/mcbsp.c +++ b/arch/arm/mach-omap1/mcbsp.c @@ -28,81 +28,8 @@ #define DPS_RSTCT2_PER_EN (1 << 0) #define DSP_RSTCT2_WD_PER_EN (1 << 1) -struct mcbsp_internal_clk { - struct clk clk; - struct clk **childs; - int n_childs; -}; - #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) -static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk) -{ - const char *clk_names[] = { "dsp_ck", "api_ck", "dspxor_ck" }; - int i; - - mclk->n_childs = ARRAY_SIZE(clk_names); - mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *), - GFP_KERNEL); - - for (i = 0; i < mclk->n_childs; i++) { - /* We fake a platform device to get correct device id */ - struct platform_device pdev; - - pdev.dev.bus = &platform_bus_type; - pdev.id = mclk->clk.id; - mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]); - if (IS_ERR(mclk->childs[i])) - printk(KERN_ERR "Could not get clock %s (%d).\n", - clk_names[i], mclk->clk.id); - } -} - -static int omap_mcbsp_clk_enable(struct clk *clk) -{ - struct mcbsp_internal_clk *mclk = container_of(clk, - struct mcbsp_internal_clk, clk); - int i; - - for (i = 0; i < mclk->n_childs; i++) - clk_enable(mclk->childs[i]); - return 0; -} - -static void omap_mcbsp_clk_disable(struct clk *clk) -{ - struct mcbsp_internal_clk *mclk = container_of(clk, - struct mcbsp_internal_clk, clk); - int i; - - for (i = 0; i < mclk->n_childs; i++) - clk_disable(mclk->childs[i]); -} - -static struct mcbsp_internal_clk omap_mcbsp_clks[] = { - { - .clk = { - .name = "mcbsp_clk", - .id = 1, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, - { - .clk = { - .name = "mcbsp_clk", - .id = 3, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, -}; - -#define omap_mcbsp_clks_size ARRAY_SIZE(omap_mcbsp_clks) -#else -#define omap_mcbsp_clks_size 0 -static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks; -static inline void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk) -{ } +const char *clk_names[] = { "dsp_ck", "api_ck", "dspxor_ck" }; #endif static void omap1_mcbsp_request(unsigned int id) @@ -167,8 +94,9 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP1RX, .tx_irq = INT_McBSP1TX, .ops = &omap1_mcbsp_ops, - .clk_name = "mcbsp_clk", - }, + .clk_names = clk_names, + .num_clks = 3, + }, { .phys_base = OMAP1510_MCBSP2_BASE, .dma_rx_sync = OMAP_DMA_MCBSP2_RX, @@ -184,7 +112,8 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP3RX, .tx_irq = INT_McBSP3TX, .ops = &omap1_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 3, }, }; #define OMAP15XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap15xx_mcbsp_pdata) @@ -202,7 +131,8 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP1RX, .tx_irq = INT_McBSP1TX, .ops = &omap1_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 3, }, { .phys_base = OMAP1610_MCBSP2_BASE, @@ -219,7 +149,8 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP3RX, .tx_irq = INT_McBSP3TX, .ops = &omap1_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 3, }, }; #define OMAP16XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap16xx_mcbsp_pdata) @@ -230,15 +161,6 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { int __init omap1_mcbsp_init(void) { - int i; - - for (i = 0; i < omap_mcbsp_clks_size; i++) { - if (cpu_is_omap15xx() || cpu_is_omap16xx()) { - omap_mcbsp_clk_init(&omap_mcbsp_clks[i]); - clk_register(&omap_mcbsp_clks[i].clk); - } - } - if (cpu_is_omap730()) omap_mcbsp_count = OMAP730_MCBSP_PDATA_SZ; if (cpu_is_omap15xx()) diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 9d7216f..ce03fa7 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -421,6 +421,7 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers) { int i; + char *name; for (i = 0; i < nr_controllers; i++) { unsigned long base, size; @@ -450,12 +451,14 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, continue; } - if (cpu_is_omap2420()) + if (cpu_is_omap2420()) { size = OMAP2420_MMC_SIZE; - else + name = "mmci-omap"; + } else { size = HSMMC_SIZE; - - omap_mmc_add(i, base, size, irq, mmc_data[i]); + name = "mmci-omap-hs"; + } + omap_mmc_add(name, i, base, size, irq, mmc_data[i]); }; } diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index b0f8e7d..b52a02f 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -172,9 +172,13 @@ void __init omap34xx_check_revision(void) omap_revision = OMAP3430_REV_ES3_0; rev_name = "ES3.0"; break; + case 4: + omap_revision = OMAP3430_REV_ES3_1; + rev_name = "ES3.1"; + break; default: /* Use the latest known revision as default */ - omap_revision = OMAP3430_REV_ES3_0; + omap_revision = OMAP3430_REV_ES3_1; rev_name = "Unknown revision\n"; } } diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index 636e282..9ba20d9 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -134,6 +134,7 @@ static struct irq_chip omap_irq_chip = { .ack = omap_mask_ack_irq, .mask = omap_mask_irq, .unmask = omap_unmask_irq, + .disable = omap_mask_irq, }; static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank) diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index e20023c..a9e631f 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -24,106 +24,7 @@ #include <mach/cpu.h> #include <mach/mcbsp.h> -struct mcbsp_internal_clk { - struct clk clk; - struct clk **childs; - int n_childs; -}; - -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) -static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk) -{ - const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" }; - int i; - - mclk->n_childs = ARRAY_SIZE(clk_names); - mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *), - GFP_KERNEL); - - for (i = 0; i < mclk->n_childs; i++) { - /* We fake a platform device to get correct device id */ - struct platform_device pdev; - - pdev.dev.bus = &platform_bus_type; - pdev.id = mclk->clk.id; - mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]); - if (IS_ERR(mclk->childs[i])) - printk(KERN_ERR "Could not get clock %s (%d).\n", - clk_names[i], mclk->clk.id); - } -} - -static int omap_mcbsp_clk_enable(struct clk *clk) -{ - struct mcbsp_internal_clk *mclk = container_of(clk, - struct mcbsp_internal_clk, clk); - int i; - - for (i = 0; i < mclk->n_childs; i++) - clk_enable(mclk->childs[i]); - return 0; -} - -static void omap_mcbsp_clk_disable(struct clk *clk) -{ - struct mcbsp_internal_clk *mclk = container_of(clk, - struct mcbsp_internal_clk, clk); - int i; - - for (i = 0; i < mclk->n_childs; i++) - clk_disable(mclk->childs[i]); -} - -static struct mcbsp_internal_clk omap_mcbsp_clks[] = { - { - .clk = { - .name = "mcbsp_clk", - .id = 1, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, - { - .clk = { - .name = "mcbsp_clk", - .id = 2, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, - { - .clk = { - .name = "mcbsp_clk", - .id = 3, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, - { - .clk = { - .name = "mcbsp_clk", - .id = 4, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, - { - .clk = { - .name = "mcbsp_clk", - .id = 5, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, -}; - -#define omap_mcbsp_clks_size ARRAY_SIZE(omap_mcbsp_clks) -#else -#define omap_mcbsp_clks_size 0 -static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks; -static inline void omap_mcbsp_clk_init(struct clk *clk) -{ } -#endif +const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" }; static void omap2_mcbsp2_mux_setup(void) { @@ -156,7 +57,8 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = INT_24XX_MCBSP1_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP24XX_MCBSP2_BASE, @@ -165,7 +67,8 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP2_IRQ_RX, .tx_irq = INT_24XX_MCBSP2_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, }; #define OMAP2420_MCBSP_PDATA_SZ ARRAY_SIZE(omap2420_mcbsp_pdata) @@ -183,7 +86,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = INT_24XX_MCBSP1_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP24XX_MCBSP2_BASE, @@ -192,7 +96,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP2_IRQ_RX, .tx_irq = INT_24XX_MCBSP2_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP2430_MCBSP3_BASE, @@ -201,7 +106,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP3_IRQ_RX, .tx_irq = INT_24XX_MCBSP3_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP2430_MCBSP4_BASE, @@ -210,7 +116,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP4_IRQ_RX, .tx_irq = INT_24XX_MCBSP4_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP2430_MCBSP5_BASE, @@ -219,7 +126,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP5_IRQ_RX, .tx_irq = INT_24XX_MCBSP5_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, }; #define OMAP2430_MCBSP_PDATA_SZ ARRAY_SIZE(omap2430_mcbsp_pdata) @@ -237,7 +145,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = INT_24XX_MCBSP1_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP2_BASE, @@ -246,7 +155,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP2_IRQ_RX, .tx_irq = INT_24XX_MCBSP2_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP3_BASE, @@ -255,7 +165,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP3_IRQ_RX, .tx_irq = INT_24XX_MCBSP3_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP4_BASE, @@ -264,7 +175,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP4_IRQ_RX, .tx_irq = INT_24XX_MCBSP4_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP5_BASE, @@ -273,7 +185,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP5_IRQ_RX, .tx_irq = INT_24XX_MCBSP5_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, }; #define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata) @@ -284,14 +197,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { static int __init omap2_mcbsp_init(void) { - int i; - - for (i = 0; i < omap_mcbsp_clks_size; i++) { - /* Once we call clk_get inside init, we do not register it */ - omap_mcbsp_clk_init(&omap_mcbsp_clks[i]); - clk_register(&omap_mcbsp_clks[i].clk); - } - if (cpu_is_omap2420()) omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ; if (cpu_is_omap2430()) diff --git a/arch/arm/mach-omap2/sleep24xx.S b/arch/arm/mach-omap2/sleep24xx.S index 43336b9..bf9e961 100644 --- a/arch/arm/mach-omap2/sleep24xx.S +++ b/arch/arm/mach-omap2/sleep24xx.S @@ -93,9 +93,8 @@ ENTRY(omap24xx_cpu_suspend) orr r4, r4, #0x40 @ enable self refresh on idle req mov r5, #0x2000 @ set delay (DPLL relock + DLL relock) str r4, [r2] @ make it so - mov r2, #0 nop - mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt + mcr p15, 0, r3, c7, c0, 4 @ wait for interrupt nop loop: subs r5, r5, #0x1 @ awake, wait just a bit diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c index ae60363..9fc13a2 100644 --- a/arch/arm/mach-omap2/timer-gp.c +++ b/arch/arm/mach-omap2/timer-gp.c @@ -118,7 +118,8 @@ static void __init omap2_gp_clockevent_init(void) clockevent_gpt.max_delta_ns = clockevent_delta2ns(0xffffffff, &clockevent_gpt); clockevent_gpt.min_delta_ns = - clockevent_delta2ns(1, &clockevent_gpt); + clockevent_delta2ns(3, &clockevent_gpt); + /* Timer internal resynch latency. */ clockevent_gpt.cpumask = cpumask_of(0); clockevents_register_device(&clockevent_gpt); diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index c1fbd5b..23cfdd5 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -289,7 +289,7 @@ static struct platform_device sa11x0pcmcia_device = { }; static struct platform_device sa11x0mtd_device = { - .name = "flash", + .name = "sa1100-mtd", .id = -1, }; diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 81d0b87..bc0099d 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -66,7 +66,10 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address) * fault (ie, is old), we can safely ignore any issues. */ if (ret && (pte_val(entry) & L_PTE_MT_MASK) != shared_pte_mask) { - flush_cache_page(vma, address, pte_pfn(entry)); + unsigned long pfn = pte_pfn(entry); + flush_cache_page(vma, address, pfn); + outer_flush_range((pfn << PAGE_SHIFT), + (pfn << PAGE_SHIFT) + PAGE_SIZE); pte_val(entry) &= ~L_PTE_MT_MASK; pte_val(entry) |= shared_pte_mask; set_pte_at(vma->vm_mm, address, pte, entry); diff --git a/arch/arm/plat-mxc/include/mach/mmc.h b/arch/arm/plat-mxc/include/mach/mmc.h new file mode 100644 index 0000000..de2128d --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/mmc.h @@ -0,0 +1,36 @@ +#ifndef ASMARM_ARCH_MMC_H +#define ASMARM_ARCH_MMC_H + +#include <linux/mmc/host.h> + +struct device; + +/* board specific SDHC data, optional. + * If not present, a writable card with 3,3V is assumed. + */ +struct imxmmc_platform_data { + /* Return values for the get_ro callback should be: + * 0 for a read/write card + * 1 for a read-only card + * -ENOSYS when not supported (equal to NULL callback) + * or a negative errno value when something bad happened + */ + int (*get_ro)(struct device *); + + /* board specific hook to (de)initialize the SD slot. + * The board code can call 'handler' on a card detection + * change giving data as argument. + */ + int (*init)(struct device *dev, irq_handler_t handler, void *data); + void (*exit)(struct device *dev, void *data); + + /* available voltages. If not given, assume + * MMC_VDD_32_33 | MMC_VDD_33_34 + */ + unsigned int ocr_avail; + + /* adjust slot voltage */ + void (*setpower)(struct device *, unsigned int vdd); +}; + +#endif diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index ac15c23..208dbb1 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -200,14 +200,15 @@ void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, /* * Register MMC devices. Called from mach-omap1 and mach-omap2 device init. */ -int __init omap_mmc_add(int id, unsigned long base, unsigned long size, - unsigned int irq, struct omap_mmc_platform_data *data) +int __init omap_mmc_add(const char *name, int id, unsigned long base, + unsigned long size, unsigned int irq, + struct omap_mmc_platform_data *data) { struct platform_device *pdev; struct resource res[OMAP_MMC_NR_RES]; int ret; - pdev = platform_device_alloc("mmci-omap", id); + pdev = platform_device_alloc(name, id); if (!pdev) return -ENOMEM; diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index e77373c..47ec77a 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -709,6 +709,7 @@ int omap_request_dma(int dev_id, const char *dev_name, chan->dev_name = dev_name; chan->callback = callback; chan->data = data; + chan->flags = 0; #ifndef CONFIG_ARCH_OMAP1 if (cpu_class_is_omap2()) { @@ -1888,11 +1889,11 @@ static int omap2_dma_handle_ch(int ch) status = dma_read(CSR(ch)); } + dma_write(status, CSR(ch)); + if (likely(dma_chan[ch].callback != NULL)) dma_chan[ch].callback(ch, status, dma_chan[ch].data); - dma_write(status, CSR(ch)); - return 0; } diff --git a/arch/arm/plat-omap/include/mach/cpu.h b/arch/arm/plat-omap/include/mach/cpu.h index b2062f1..a8e1178 100644 --- a/arch/arm/plat-omap/include/mach/cpu.h +++ b/arch/arm/plat-omap/include/mach/cpu.h @@ -339,6 +339,7 @@ IS_OMAP_TYPE(3430, 0x3430) #define OMAP3430_REV_ES2_0 0x34301034 #define OMAP3430_REV_ES2_1 0x34302034 #define OMAP3430_REV_ES3_0 0x34303034 +#define OMAP3430_REV_ES3_1 0x34304034 /* * omap_chip bits diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index eef873d..113c246 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -344,7 +344,8 @@ struct omap_mcbsp_platform_data { u8 dma_rx_sync, dma_tx_sync; u16 rx_irq, tx_irq; struct omap_mcbsp_ops *ops; - char const *clk_name; + char const **clk_names; + int num_clks; }; struct omap_mcbsp { @@ -376,7 +377,8 @@ struct omap_mcbsp { /* Protect the field .free, while checking if the mcbsp is in use */ spinlock_t lock; struct omap_mcbsp_platform_data *pdata; - struct clk *clk; + struct clk **clks; + int num_clks; }; extern struct omap_mcbsp **mcbsp_ptr; extern int omap_mcbsp_count; diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index 031250f..73a9e15 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -115,8 +115,9 @@ void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers); void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers); -int omap_mmc_add(int id, unsigned long base, unsigned long size, - unsigned int irq, struct omap_mmc_platform_data *data); +int omap_mmc_add(const char *name, int id, unsigned long base, + unsigned long size, unsigned int irq, + struct omap_mmc_platform_data *data); #else static inline void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers) @@ -126,8 +127,9 @@ static inline void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers) { } -static inline int omap_mmc_add(int id, unsigned long base, unsigned long size, - unsigned int irq, struct omap_mmc_platform_data *data) +static inline int omap_mmc_add(const char *name, int id, unsigned long base, + unsigned long size, unsigned int irq, + struct omap_mmc_platform_data *data) { return 0; } diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index f2401a8..e5842e3 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -214,6 +214,7 @@ EXPORT_SYMBOL(omap_mcbsp_set_io_type); int omap_mcbsp_request(unsigned int id) { struct omap_mcbsp *mcbsp; + int i; int err; if (!omap_mcbsp_check_valid_id(id)) { @@ -225,7 +226,8 @@ int omap_mcbsp_request(unsigned int id) if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request) mcbsp->pdata->ops->request(id); - clk_enable(mcbsp->clk); + for (i = 0; i < mcbsp->num_clks; i++) + clk_enable(mcbsp->clks[i]); spin_lock(&mcbsp->lock); if (!mcbsp->free) { @@ -276,6 +278,7 @@ EXPORT_SYMBOL(omap_mcbsp_request); void omap_mcbsp_free(unsigned int id) { struct omap_mcbsp *mcbsp; + int i; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); @@ -286,7 +289,8 @@ void omap_mcbsp_free(unsigned int id) if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) mcbsp->pdata->ops->free(id); - clk_disable(mcbsp->clk); + for (i = mcbsp->num_clks - 1; i >= 0; i--) + clk_disable(mcbsp->clks[i]); spin_lock(&mcbsp->lock); if (mcbsp->free) { @@ -872,6 +876,7 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data; struct omap_mcbsp *mcbsp; int id = pdev->id - 1; + int i; int ret = 0; if (!pdata) { @@ -916,14 +921,25 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) mcbsp->dma_rx_sync = pdata->dma_rx_sync; mcbsp->dma_tx_sync = pdata->dma_tx_sync; - if (pdata->clk_name) - mcbsp->clk = clk_get(&pdev->dev, pdata->clk_name); - if (IS_ERR(mcbsp->clk)) { - dev_err(&pdev->dev, - "Invalid clock configuration for McBSP%d.\n", - mcbsp->id); - ret = PTR_ERR(mcbsp->clk); - goto err_clk; + if (pdata->num_clks) { + mcbsp->num_clks = pdata->num_clks; + mcbsp->clks = kzalloc(mcbsp->num_clks * sizeof(struct clk *), + GFP_KERNEL); + if (!mcbsp->clks) { + ret = -ENOMEM; + goto exit; + } + for (i = 0; i < mcbsp->num_clks; i++) { + mcbsp->clks[i] = clk_get(&pdev->dev, pdata->clk_names[i]); + if (IS_ERR(mcbsp->clks[i])) { + dev_err(&pdev->dev, + "Invalid %s configuration for McBSP%d.\n", + pdata->clk_names[i], mcbsp->id); + ret = PTR_ERR(mcbsp->clks[i]); + goto err_clk; + } + } + } mcbsp->pdata = pdata; @@ -932,6 +948,9 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) return 0; err_clk: + while (i--) + clk_put(mcbsp->clks[i]); + kfree(mcbsp->clks); iounmap(mcbsp->io_base); err_ioremap: mcbsp->free = 0; @@ -942,6 +961,7 @@ exit: static int __devexit omap_mcbsp_remove(struct platform_device *pdev) { struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); + int i; platform_set_drvdata(pdev, NULL); if (mcbsp) { @@ -950,12 +970,18 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev) mcbsp->pdata->ops->free) mcbsp->pdata->ops->free(mcbsp->id); - clk_disable(mcbsp->clk); - clk_put(mcbsp->clk); + for (i = mcbsp->num_clks - 1; i >= 0; i--) { + clk_disable(mcbsp->clks[i]); + clk_put(mcbsp->clks[i]); + } iounmap(mcbsp->io_base); - mcbsp->clk = NULL; + if (mcbsp->num_clks) { + kfree(mcbsp->clks); + mcbsp->clks = NULL; + mcbsp->num_clks = 0; + } mcbsp->free = 0; mcbsp->dev = NULL; } diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index a949c4f..8f1f97d 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -169,26 +169,51 @@ config BF542 help BF542 Processor Support. +config BF542M + bool "BF542m" + help + BF542 Processor Support. + config BF544 bool "BF544" help BF544 Processor Support. +config BF544M + bool "BF544m" + help + BF544 Processor Support. + config BF547 bool "BF547" help BF547 Processor Support. +config BF547M + bool "BF547m" + help + BF547 Processor Support. + config BF548 bool "BF548" help BF548 Processor Support. +config BF548M + bool "BF548m" + help + BF548 Processor Support. + config BF549 bool "BF549" help BF549 Processor Support. +config BF549M + bool "BF549m" + help + BF549 Processor Support. + config BF561 bool "BF561" help @@ -224,39 +249,39 @@ config TICK_SOURCE_SYSTMR0 config BF_REV_MIN int - default 0 if (BF51x || BF52x || BF54x) + default 0 if (BF51x || BF52x || (BF54x && !BF54xM)) default 2 if (BF537 || BF536 || BF534) - default 3 if (BF561 ||BF533 || BF532 || BF531) + default 3 if (BF561 || BF533 || BF532 || BF531 || BF54xM) default 4 if (BF538 || BF539) config BF_REV_MAX int - default 2 if (BF51x || BF52x || BF54x) - default 3 if (BF537 || BF536 || BF534) + default 2 if (BF51x || BF52x || (BF54x && !BF54xM)) + default 3 if (BF537 || BF536 || BF534 || BF54xM) default 5 if (BF561 || BF538 || BF539) default 6 if (BF533 || BF532 || BF531) choice prompt "Silicon Rev" - default BF_REV_0_1 if (BF51x || BF52x || BF54x) + default BF_REV_0_1 if (BF51x || BF52x || (BF54x && !BF54xM)) default BF_REV_0_2 if (BF534 || BF536 || BF537) - default BF_REV_0_3 if (BF531 || BF532 || BF533 || BF561) + default BF_REV_0_3 if (BF531 || BF532 || BF533 || BF54xM || BF561) config BF_REV_0_0 bool "0.0" - depends on (BF51x || BF52x || BF54x) + depends on (BF51x || BF52x || (BF54x && !BF54xM)) config BF_REV_0_1 bool "0.1" - depends on (BF52x || BF54x) + depends on (BF52x || (BF54x && !BF54xM)) config BF_REV_0_2 bool "0.2" - depends on (BF52x || BF537 || BF536 || BF534 || BF54x) + depends on (BF52x || BF537 || BF536 || BF534 || (BF54x && !BF54xM)) config BF_REV_0_3 bool "0.3" - depends on (BF561 || BF537 || BF536 || BF534 || BF533 || BF532 || BF531) + depends on (BF54xM || BF561 || BF537 || BF536 || BF534 || BF533 || BF532 || BF531) config BF_REV_0_4 bool "0.4" @@ -293,9 +318,14 @@ config BF53x depends on (BF531 || BF532 || BF533 || BF534 || BF536 || BF537) default y +config BF54xM + bool + depends on (BF542M || BF544M || BF547M || BF548M || BF549M) + default y + config BF54x bool - depends on (BF542 || BF544 || BF547 || BF548 || BF549) + depends on (BF542 || BF544 || BF547 || BF548 || BF549 || BF54xM) default y config MEM_GENERIC_BOARD diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile index e550c8d..d54c828 100644 --- a/arch/blackfin/Makefile +++ b/arch/blackfin/Makefile @@ -21,57 +21,67 @@ KALLSYMS += --symbol-prefix=_ KBUILD_DEFCONFIG := BF537-STAMP_defconfig # setup the machine name and the machine dependent settings -machine-$(CONFIG_BF512) := bf518 -machine-$(CONFIG_BF514) := bf518 -machine-$(CONFIG_BF516) := bf518 -machine-$(CONFIG_BF518) := bf518 -machine-$(CONFIG_BF522) := bf527 -machine-$(CONFIG_BF523) := bf527 -machine-$(CONFIG_BF524) := bf527 -machine-$(CONFIG_BF525) := bf527 -machine-$(CONFIG_BF526) := bf527 -machine-$(CONFIG_BF527) := bf527 -machine-$(CONFIG_BF531) := bf533 -machine-$(CONFIG_BF532) := bf533 -machine-$(CONFIG_BF533) := bf533 -machine-$(CONFIG_BF534) := bf537 -machine-$(CONFIG_BF536) := bf537 -machine-$(CONFIG_BF537) := bf537 -machine-$(CONFIG_BF538) := bf538 -machine-$(CONFIG_BF539) := bf538 -machine-$(CONFIG_BF542) := bf548 -machine-$(CONFIG_BF544) := bf548 -machine-$(CONFIG_BF547) := bf548 -machine-$(CONFIG_BF548) := bf548 -machine-$(CONFIG_BF549) := bf548 -machine-$(CONFIG_BF561) := bf561 +machine-$(CONFIG_BF512) := bf518 +machine-$(CONFIG_BF514) := bf518 +machine-$(CONFIG_BF516) := bf518 +machine-$(CONFIG_BF518) := bf518 +machine-$(CONFIG_BF522) := bf527 +machine-$(CONFIG_BF523) := bf527 +machine-$(CONFIG_BF524) := bf527 +machine-$(CONFIG_BF525) := bf527 +machine-$(CONFIG_BF526) := bf527 +machine-$(CONFIG_BF527) := bf527 +machine-$(CONFIG_BF531) := bf533 +machine-$(CONFIG_BF532) := bf533 +machine-$(CONFIG_BF533) := bf533 +machine-$(CONFIG_BF534) := bf537 +machine-$(CONFIG_BF536) := bf537 +machine-$(CONFIG_BF537) := bf537 +machine-$(CONFIG_BF538) := bf538 +machine-$(CONFIG_BF539) := bf538 +machine-$(CONFIG_BF542) := bf548 +machine-$(CONFIG_BF542M) := bf548 +machine-$(CONFIG_BF544) := bf548 +machine-$(CONFIG_BF544M) := bf548 +machine-$(CONFIG_BF547) := bf548 +machine-$(CONFIG_BF547M) := bf548 +machine-$(CONFIG_BF548) := bf548 +machine-$(CONFIG_BF548M) := bf548 +machine-$(CONFIG_BF549) := bf548 +machine-$(CONFIG_BF549M) := bf548 +machine-$(CONFIG_BF561) := bf561 MACHINE := $(machine-y) export MACHINE -cpu-$(CONFIG_BF512) := bf512 -cpu-$(CONFIG_BF514) := bf514 -cpu-$(CONFIG_BF516) := bf516 -cpu-$(CONFIG_BF518) := bf518 -cpu-$(CONFIG_BF522) := bf522 -cpu-$(CONFIG_BF523) := bf523 -cpu-$(CONFIG_BF524) := bf524 -cpu-$(CONFIG_BF525) := bf525 -cpu-$(CONFIG_BF526) := bf526 -cpu-$(CONFIG_BF527) := bf527 -cpu-$(CONFIG_BF531) := bf531 -cpu-$(CONFIG_BF532) := bf532 -cpu-$(CONFIG_BF533) := bf533 -cpu-$(CONFIG_BF534) := bf534 -cpu-$(CONFIG_BF536) := bf536 -cpu-$(CONFIG_BF537) := bf537 -cpu-$(CONFIG_BF538) := bf538 -cpu-$(CONFIG_BF539) := bf539 -cpu-$(CONFIG_BF542) := bf542 -cpu-$(CONFIG_BF544) := bf544 -cpu-$(CONFIG_BF547) := bf547 -cpu-$(CONFIG_BF548) := bf548 -cpu-$(CONFIG_BF549) := bf549 -cpu-$(CONFIG_BF561) := bf561 +cpu-$(CONFIG_BF512) := bf512 +cpu-$(CONFIG_BF514) := bf514 +cpu-$(CONFIG_BF516) := bf516 +cpu-$(CONFIG_BF518) := bf518 +cpu-$(CONFIG_BF522) := bf522 +cpu-$(CONFIG_BF523) := bf523 +cpu-$(CONFIG_BF524) := bf524 +cpu-$(CONFIG_BF525) := bf525 +cpu-$(CONFIG_BF526) := bf526 +cpu-$(CONFIG_BF527) := bf527 +cpu-$(CONFIG_BF531) := bf531 +cpu-$(CONFIG_BF532) := bf532 +cpu-$(CONFIG_BF533) := bf533 +cpu-$(CONFIG_BF534) := bf534 +cpu-$(CONFIG_BF536) := bf536 +cpu-$(CONFIG_BF537) := bf537 +cpu-$(CONFIG_BF538) := bf538 +cpu-$(CONFIG_BF539) := bf539 +cpu-$(CONFIG_BF542) := bf542 +cpu-$(CONFIG_BF542M) := bf542m +cpu-$(CONFIG_BF544) := bf544 +cpu-$(CONFIG_BF544M) := bf544m +cpu-$(CONFIG_BF547) := bf547 +cpu-$(CONFIG_BF547M) := bf547m +cpu-$(CONFIG_BF548) := bf548 +cpu-$(CONFIG_BF548M) := bf548m +cpu-$(CONFIG_BF549) := bf549 +cpu-$(CONFIG_BF549M) := bf549m +cpu-$(CONFIG_BF561) := bf561 rev-$(CONFIG_BF_REV_0_0) := 0.0 rev-$(CONFIG_BF_REV_0_1) := 0.1 diff --git a/arch/blackfin/configs/BF518F-EZBRD_defconfig b/arch/blackfin/configs/BF518F-EZBRD_defconfig index defb978..4fdb9e0 100644 --- a/arch/blackfin/configs/BF518F-EZBRD_defconfig +++ b/arch/blackfin/configs/BF518F-EZBRD_defconfig @@ -1,6 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.28-rc2 +# Fri Jan 9 17:58:41 2009 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -149,6 +150,7 @@ CONFIG_BF_REV_0_0=y # CONFIG_BF_REV_ANY is not set # CONFIG_BF_REV_NONE is not set CONFIG_BF51x=y +CONFIG_MEM_MT48LC32M8A2_75=y CONFIG_BFIN518F_EZBRD=y # @@ -598,7 +600,10 @@ CONFIG_PHYLIB=y # CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y -# CONFIG_BFIN_MAC is not set +CONFIG_BFIN_MAC=y +CONFIG_BFIN_TX_DESC_NUM=10 +CONFIG_BFIN_RX_DESC_NUM=20 +# CONFIG_BFIN_MAC_RMII is not set # CONFIG_SMC91X is not set # CONFIG_SMSC911X is not set # CONFIG_DM9000 is not set @@ -679,7 +684,7 @@ CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF526-EZBRD_defconfig b/arch/blackfin/configs/BF526-EZBRD_defconfig index 992424f..8e2b855 100644 --- a/arch/blackfin/configs/BF526-EZBRD_defconfig +++ b/arch/blackfin/configs/BF526-EZBRD_defconfig @@ -723,7 +723,7 @@ CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig index 21e3c1a..833128b 100644 --- a/arch/blackfin/configs/BF527-EZKIT_defconfig +++ b/arch/blackfin/configs/BF527-EZKIT_defconfig @@ -767,7 +767,7 @@ CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig index 0bdf20a..334c94b 100644 --- a/arch/blackfin/configs/BF533-EZKIT_defconfig +++ b/arch/blackfin/configs/BF533-EZKIT_defconfig @@ -672,7 +672,7 @@ CONFIG_BFIN_DMA_INTERFACE=m CONFIG_SIMPLE_GPIO=m # CONFIG_VT is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig index 2f747d6..9d73343 100644 --- a/arch/blackfin/configs/BF533-STAMP_defconfig +++ b/arch/blackfin/configs/BF533-STAMP_defconfig @@ -679,7 +679,7 @@ CONFIG_BFIN_DMA_INTERFACE=m CONFIG_SIMPLE_GPIO=m # CONFIG_VT is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig index 8b0a812..4fb4108 100644 --- a/arch/blackfin/configs/BF537-STAMP_defconfig +++ b/arch/blackfin/configs/BF537-STAMP_defconfig @@ -722,7 +722,7 @@ CONFIG_BFIN_DMA_INTERFACE=m CONFIG_SIMPLE_GPIO=m # CONFIG_VT is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF538-EZKIT_defconfig b/arch/blackfin/configs/BF538-EZKIT_defconfig index a1f766b..cb32f56 100644 --- a/arch/blackfin/configs/BF538-EZKIT_defconfig +++ b/arch/blackfin/configs/BF538-EZKIT_defconfig @@ -726,7 +726,7 @@ CONFIG_BFIN_DMA_INTERFACE=m CONFIG_SIMPLE_GPIO=m # CONFIG_VT is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig index cd2da6b..0f869761 100644 --- a/arch/blackfin/configs/BF548-EZKIT_defconfig +++ b/arch/blackfin/configs/BF548-EZKIT_defconfig @@ -856,7 +856,7 @@ CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig index b398ca2..042c7ad 100644 --- a/arch/blackfin/configs/BF561-EZKIT_defconfig +++ b/arch/blackfin/configs/BF561-EZKIT_defconfig @@ -709,7 +709,7 @@ CONFIG_BFIN_DMA_INTERFACE=m CONFIG_SIMPLE_GPIO=m # CONFIG_VT is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/CM-BF527_defconfig b/arch/blackfin/configs/CM-BF527_defconfig index 9514694..865ed85 100644 --- a/arch/blackfin/configs/CM-BF527_defconfig +++ b/arch/blackfin/configs/CM-BF527_defconfig @@ -1,7 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.24.7 -# Fri Jul 18 18:00:41 2008 +# Linux kernel version: 2.6.28 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -9,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set CONFIG_BLACKFIN=y CONFIG_ZONE_DMA=y -CONFIG_SEMAPHORE_SLEEPERS=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y @@ -32,18 +30,16 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set -# CONFIG_USER_NS is not set -# CONFIG_PID_NS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_FAIR_USER_SCHED=y -# CONFIG_FAIR_CGROUP_SCHED is not set -# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_GROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set @@ -52,26 +48,35 @@ CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_ELF_CORE is not set +CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y CONFIG_EVENTFD=y +CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y CONFIG_TINY_SHMEM=y CONFIG_BASE_SMALL=0 CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set @@ -82,6 +87,7 @@ CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -95,9 +101,11 @@ CONFIG_IOSCHED_CFQ=y CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_CLASSIC_RCU=y # CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set +# CONFIG_FREEZER is not set # # Blackfin Processor Options @@ -106,6 +114,10 @@ CONFIG_PREEMPT_VOLUNTARY=y # # Processor and Board Settings # +# CONFIG_BF512 is not set +# CONFIG_BF514 is not set +# CONFIG_BF516 is not set +# CONFIG_BF518 is not set # CONFIG_BF522 is not set # CONFIG_BF523 is not set # CONFIG_BF524 is not set @@ -118,48 +130,32 @@ CONFIG_BF527=y # CONFIG_BF534 is not set # CONFIG_BF536 is not set # CONFIG_BF537 is not set +# CONFIG_BF538 is not set +# CONFIG_BF539 is not set # CONFIG_BF542 is not set +# CONFIG_BF542M is not set # CONFIG_BF544 is not set +# CONFIG_BF544M is not set # CONFIG_BF547 is not set +# CONFIG_BF547M is not set # CONFIG_BF548 is not set +# CONFIG_BF548M is not set # CONFIG_BF549 is not set +# CONFIG_BF549M is not set # CONFIG_BF561 is not set +CONFIG_BF_REV_MIN=0 +CONFIG_BF_REV_MAX=2 # CONFIG_BF_REV_0_0 is not set CONFIG_BF_REV_0_1=y # CONFIG_BF_REV_0_2 is not set # CONFIG_BF_REV_0_3 is not set # CONFIG_BF_REV_0_4 is not set # CONFIG_BF_REV_0_5 is not set +# CONFIG_BF_REV_0_6 is not set # CONFIG_BF_REV_ANY is not set # CONFIG_BF_REV_NONE is not set CONFIG_BF52x=y CONFIG_MEM_MT48LC16M16A2TG_75=y -# CONFIG_BFIN527_EZKIT is not set -CONFIG_BFIN527_BLUETECHNIX_CM=y - -# -# BF527 Specific Configuration -# - -# -# Alternative Multiplexing Scheme -# -# CONFIG_BF527_SPORT0_PORTF is not set -CONFIG_BF527_SPORT0_PORTG=y -CONFIG_BF527_SPORT0_TSCLK_PG10=y -# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set -CONFIG_BF527_UART1_PORTF=y -# CONFIG_BF527_UART1_PORTG is not set -# CONFIG_BF527_NAND_D_PORTF is not set -CONFIG_BF527_NAND_D_PORTH=y - -# -# Interrupt Priority Assignment -# - -# -# Priority -# CONFIG_IRQ_PLL_WAKEUP=7 CONFIG_IRQ_DMA0_ERROR=7 CONFIG_IRQ_DMAR0_BLK=7 @@ -179,7 +175,6 @@ CONFIG_IRQ_SPORT0_TX=9 CONFIG_IRQ_SPORT1_RX=9 CONFIG_IRQ_SPORT1_TX=9 CONFIG_IRQ_TWI=10 -CONFIG_IRQ_SPI=10 CONFIG_IRQ_UART0_RX=10 CONFIG_IRQ_UART0_TX=10 CONFIG_IRQ_UART1_RX=10 @@ -205,6 +200,34 @@ CONFIG_IRQ_MEM_DMA1=13 CONFIG_IRQ_WATCH=13 CONFIG_IRQ_PORTF_INTA=13 CONFIG_IRQ_PORTF_INTB=13 +# CONFIG_BFIN527_EZKIT is not set +CONFIG_BFIN527_BLUETECHNIX_CM=y +# CONFIG_BFIN526_EZBRD is not set + +# +# BF527 Specific Configuration +# + +# +# Alternative Multiplexing Scheme +# +# CONFIG_BF527_SPORT0_PORTF is not set +CONFIG_BF527_SPORT0_PORTG=y +CONFIG_BF527_SPORT0_TSCLK_PG10=y +# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set +CONFIG_BF527_UART1_PORTF=y +# CONFIG_BF527_UART1_PORTG is not set +# CONFIG_BF527_NAND_D_PORTF is not set +CONFIG_BF527_NAND_D_PORTH=y + +# +# Interrupt Priority Assignment +# + +# +# Priority +# +CONFIG_IRQ_SPI=10 CONFIG_IRQ_SPI_ERROR=7 CONFIG_IRQ_NFC_ERROR=7 CONFIG_IRQ_HDMA_ERROR=7 @@ -226,7 +249,6 @@ CONFIG_BOOT_LOAD=0x1000 # CONFIG_CLKIN_HZ=25000000 # CONFIG_BFIN_KERNEL_CLOCK is not set -CONFIG_MAX_MEM_SIZE=512 CONFIG_MAX_VCO_HZ=600000000 CONFIG_MIN_VCO_HZ=50000000 CONFIG_MAX_SCLK_HZ=133333333 @@ -240,10 +262,10 @@ CONFIG_HZ_250=y # CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 +# CONFIG_SCHED_HRTICK is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y # CONFIG_CYCLES_CLOCKSOURCE is not set -# CONFIG_TICK_ONESHOT is not set # CONFIG_NO_HZ is not set # CONFIG_HIGH_RES_TIMERS is not set CONFIG_GENERIC_CLOCKEVENTS_BUILD=y @@ -277,6 +299,12 @@ CONFIG_ACCESS_OK_L1=y CONFIG_CACHELINE_ALIGNED_L1=y # CONFIG_SYSCALL_TAB_L1 is not set # CONFIG_CPLB_SWITCH_TAB_L1 is not set +CONFIG_APP_STACK_L1=y + +# +# Speed Optimizations +# +CONFIG_BFIN_INS_LOWOVERHEAD=y CONFIG_RAMKERNEL=y # CONFIG_ROMKERNEL is not set CONFIG_SELECT_MEMORY_MODEL=y @@ -285,10 +313,10 @@ CONFIG_FLATMEM_MANUAL=y # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_VIRT_TO_BUS=y CONFIG_BFIN_GPTIMERS=y @@ -334,7 +362,6 @@ CONFIG_BANK_3=0xFFC0 # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) # -# CONFIG_PCI is not set # CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCCARD is not set @@ -345,25 +372,20 @@ CONFIG_BINFMT_ELF_FDPIC=y CONFIG_BINFMT_FLAT=y CONFIG_BINFMT_ZFLAT=y # CONFIG_BINFMT_SHARED_FLAT is not set +# CONFIG_HAVE_AOUT is not set # CONFIG_BINFMT_MISC is not set # # Power management options # # CONFIG_PM is not set -CONFIG_SUSPEND_UP_POSSIBLE=y -# CONFIG_PM_BFIN_SLEEP_DEEPER is not set -# CONFIG_PM_BFIN_SLEEP is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y # CONFIG_PM_WAKEUP_BY_GPIO is not set # # CPU Frequency scaling # # CONFIG_CPU_FREQ is not set - -# -# Networking -# CONFIG_NET=y # @@ -376,6 +398,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_USER is not set # CONFIG_XFRM_SUB_POLICY is not set # CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set # CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set @@ -405,8 +428,6 @@ CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TCP_MD5SIG is not set # CONFIG_IPV6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set # CONFIG_NETLABEL is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set @@ -415,6 +436,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set # CONFIG_LLC2 is not set @@ -431,14 +453,14 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # # CONFIG_NET_PKTGEN is not set # CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set - -# -# Wireless -# +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y # CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y # CONFIG_WIRELESS_EXT is not set # CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set @@ -456,6 +478,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set CONFIG_MTD=y @@ -464,6 +488,7 @@ CONFIG_MTD=y CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_REDBOOT_PARTS is not set # CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set # # User Modules And Translation Layers @@ -507,6 +532,7 @@ CONFIG_MTD_ROM=m # CONFIG_MTD_COMPLEX_MAPPINGS=y # CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_GPIO_ADDR is not set # CONFIG_MTD_UCLINUX is not set # CONFIG_MTD_PLATRAM is not set @@ -542,10 +568,12 @@ CONFIG_BLK_DEV=y 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_XIP is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set # CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y # CONFIG_IDE is not set # @@ -558,7 +586,6 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # CONFIG_ATA is not set # CONFIG_MD is not set CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_MACVLAN is not set @@ -579,6 +606,7 @@ CONFIG_PHYLIB=y # CONFIG_SMSC_PHY is not set # CONFIG_BROADCOM_PHY is not set # CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set # CONFIG_FIXED_PHY is not set # CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y @@ -591,11 +619,14 @@ CONFIG_BFIN_MAC_RMII=y # CONFIG_SMC91X is not set # CONFIG_SMSC911X is not set # CONFIG_DM9000 is not set +# CONFIG_ENC28J60 is not set # CONFIG_IBM_NEW_EMAC_ZMII is not set # CONFIG_IBM_NEW_EMAC_RGMII is not set # CONFIG_IBM_NEW_EMAC_TAH is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set -# CONFIG_B44 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set @@ -604,6 +635,7 @@ CONFIG_BFIN_MAC_RMII=y # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set # # USB Network Adapters @@ -616,7 +648,6 @@ CONFIG_BFIN_MAC_RMII=y # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set -# CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -642,14 +673,15 @@ CONFIG_BFIN_MAC_RMII=y # CONFIG_BF5xx_PPIFCD is not set # CONFIG_BFIN_SIMPLE_TIMER is not set # CONFIG_BF5xx_PPI is not set -CONFIG_BFIN_OTP=y -# CONFIG_BFIN_OTP_WRITE_ENABLE is not set +# CONFIG_BF5xx_EPPI is not set # CONFIG_BFIN_SPORT is not set # CONFIG_BFIN_TIMER_LATENCY is not set # CONFIG_TWI_LCD is not set +CONFIG_BFIN_DMA_INTERFACE=m CONFIG_SIMPLE_GPIO=m # CONFIG_VT is not set # CONFIG_DEVKMEM is not set +# CONFIG_BFIN_JTAG_COMM is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -673,6 +705,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_BFIN_SPORT is not set CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set +CONFIG_BFIN_OTP=y +# CONFIG_BFIN_OTP_WRITE_ENABLE is not set # # CAN, the car bus and industrial fieldbus @@ -680,44 +714,49 @@ CONFIG_UNIX98_PTYS=y # CONFIG_CAN4LINUX is not set # CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set -# CONFIG_GEN_RTC is not set # CONFIG_R3964 is not set # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_CHARDEV=m +CONFIG_I2C_HELPER_AUTO=y # -# I2C Algorithms +# I2C Hardware Bus support # -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -# CONFIG_I2C_ALGOPCA is not set # -# I2C Hardware Bus support +# I2C system bus drivers (mostly embedded / system-on-chip) # CONFIG_I2C_BLACKFIN_TWI=m CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100 # CONFIG_I2C_GPIO is not set # CONFIG_I2C_OCORES is not set -# CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_TAOS_EVM is not set -# CONFIG_I2C_STUB is not set # CONFIG_I2C_TINY_USB is not set # +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# # Miscellaneous I2C Chip support # -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set # CONFIG_DS1682 is not set +# CONFIG_AT24 is not set # CONFIG_SENSORS_AD5252 is not set -# CONFIG_EEPROM_LEGACY is not set +# CONFIG_SENSORS_EEPROM is not set # CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCF8575 is not set +# CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_MAX6875 is not set @@ -726,37 +765,41 @@ CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100 # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CHIP is not set - -# -# SPI support -# CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set CONFIG_SPI_MASTER=y # # SPI Master Controller Drivers # CONFIG_SPI_BFIN=y +# CONFIG_SPI_BFIN_LOCK is not set # CONFIG_SPI_BITBANG is not set # # SPI Protocol Masters # -# CONFIG_EEPROM_AT25 is not set +# CONFIG_SPI_AT25 is not set # CONFIG_SPI_SPIDEV is not set # CONFIG_SPI_TLE62X0 is not set +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +# CONFIG_GPIOLIB is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7414 is not set # CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set # CONFIG_SENSORS_ADM1029 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_F71805F is not set @@ -777,6 +820,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_MAX1111 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_PC87360 is not set @@ -785,6 +829,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set # CONFIG_SENSORS_THMC50 is not set # CONFIG_SENSORS_VT1211 is not set # CONFIG_SENSORS_W83781D is not set @@ -792,9 +837,12 @@ CONFIG_HWMON=y # CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83793 is not set # CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set # CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set CONFIG_WATCHDOG=y # CONFIG_WATCHDOG_NOWAYOUT is not set @@ -810,21 +858,31 @@ CONFIG_BFIN_WDT=y # CONFIG_USBPCWATCHDOG is not set # -# Sonics Silicon Backplane -# -CONFIG_SSB_POSSIBLE=y -# CONFIG_SSB is not set - -# # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_REGULATOR is not set # # Multimedia devices # + +# +# Multimedia core support +# # CONFIG_VIDEO_DEV is not set # CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# # CONFIG_DAB is not set # @@ -839,10 +897,6 @@ CONFIG_SSB_POSSIBLE=y # Display device support # # CONFIG_DISPLAY_SUPPORT is not set - -# -# Sound -# # CONFIG_SOUND is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y @@ -850,6 +904,7 @@ CONFIG_USB_ARCH_HAS_HCD=y # CONFIG_USB_ARCH_HAS_EHCI is not set CONFIG_USB=y # CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set # # Miscellaneous USB options @@ -860,40 +915,48 @@ CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set CONFIG_USB_OTG_BLACKLIST_HUB=y +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set # # USB Host Controller Drivers # +# CONFIG_USB_C67X00_HCD is not set # CONFIG_USB_ISP116X_HCD is not set -# CONFIG_USB_ISP1362_HCD is not set # CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set CONFIG_USB_MUSB_HDRC=y CONFIG_USB_MUSB_SOC=y # -# Blackfin high speed USB support +# Blackfin high speed USB Support # CONFIG_USB_MUSB_HOST=y # CONFIG_USB_MUSB_PERIPHERAL is not set # CONFIG_USB_MUSB_OTG is not set CONFIG_USB_MUSB_HDRC_HCD=y CONFIG_MUSB_PIO_ONLY=y -CONFIG_USB_MUSB_LOGLEVEL=0 +CONFIG_MUSB_DMA_POLL=y +# CONFIG_USB_MUSB_DEBUG is not set # # USB Device Class drivers # # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # # CONFIG_USB_LIBUSUAL is not set @@ -901,15 +964,10 @@ CONFIG_USB_MUSB_LOGLEVEL=0 # USB Imaging devices # # CONFIG_USB_MDC800 is not set -CONFIG_USB_MON=y # # USB port drivers # - -# -# USB Serial Converter support -# # CONFIG_USB_SERIAL is not set # @@ -918,7 +976,7 @@ CONFIG_USB_MON=y # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set # CONFIG_USB_ADUTUX is not set -# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_SEVSEG is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set @@ -934,17 +992,13 @@ CONFIG_USB_MON=y # CONFIG_USB_LD is not set # CONFIG_USB_TRANCEVIBRATOR is not set # CONFIG_USB_IOWARRIOR is not set - -# -# USB DSL modem support -# - -# -# USB Gadget Support -# +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y CONFIG_RTC_HCTOSYS=y @@ -973,51 +1027,59 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_PCF8563 is not set # CONFIG_RTC_DRV_PCF8583 is not set # CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set # # SPI RTC drivers # -# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set # CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set # # Platform RTC drivers # +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set # CONFIG_RTC_DRV_DS1553 is not set -# CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set # CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set # CONFIG_RTC_DRV_V3020 is not set # # on-CPU RTC drivers # CONFIG_RTC_DRV_BFIN=y - -# -# Userspace I/O -# +# CONFIG_DMADEVICES is not set # CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems # # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set -# CONFIG_EXT4DEV_FS is not set +# CONFIG_EXT4_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set +# CONFIG_DNOTIFY is not set CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set -# CONFIG_DNOTIFY is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_FUSE_FS is not set @@ -1059,8 +1121,11 @@ CONFIG_SYSFS=y # CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set CONFIG_NETWORK_FILESYSTEMS=y @@ -1068,13 +1133,12 @@ CONFIG_NFS_FS=m CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set # CONFIG_NFSD is not set CONFIG_LOCKD=m CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=m -# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_SUNRPC_REGISTER_V4 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -1130,7 +1194,6 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_KOI8_U is not set # CONFIG_NLS_UTF8 is not set # CONFIG_DLM is not set -# CONFIG_INSTRUMENTATION is not set # # Kernel hacking @@ -1138,14 +1201,61 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_PRINTK_TIME is not set CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 # CONFIG_MAGIC_SYSRQ is not set # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set -# CONFIG_DEBUG_KERNEL is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_FRAME_POINTER is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_KGDB_TESTCASE is not set +CONFIG_DEBUG_VERBOSE=y CONFIG_DEBUG_MMRS=y +# CONFIG_DEBUG_HWERR is not set +# CONFIG_DEBUG_DOUBLEFAULT is not set CONFIG_DEBUG_HUNT_FOR_ZERO=y CONFIG_DEBUG_BFIN_HWTRACE_ON=y CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y @@ -1154,7 +1264,7 @@ CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set -CONFIG_EARLY_PRINTK=y +# CONFIG_EARLY_PRINTK is not set # CONFIG_CPLB_INFO is not set CONFIG_ACCESS_CHECK=y @@ -1163,10 +1273,96 @@ CONFIG_ACCESS_CHECK=y # # CONFIG_KEYS is not set CONFIG_SECURITY=y +# CONFIG_SECURITYFS is not set # CONFIG_SECURITY_NETWORK is not set -# CONFIG_SECURITY_CAPABILITIES is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set # CONFIG_SECURITY_ROOTPLUG is not set -# CONFIG_CRYPTO is not set +CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0 +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y # # Library routines @@ -1174,6 +1370,7 @@ CONFIG_SECURITY=y CONFIG_BITREVERSE=y CONFIG_CRC_CCITT=m # CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y # CONFIG_CRC7 is not set diff --git a/arch/blackfin/include/asm/checksum.h b/arch/blackfin/include/asm/checksum.h index f67289a..793581f 100644 --- a/arch/blackfin/include/asm/checksum.h +++ b/arch/blackfin/include/asm/checksum.h @@ -63,23 +63,23 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, unsigned short proto, __wsum sum) { - - __asm__ ("%0 = %0 + %1;\n\t" - "CC = AC0;\n\t" - "if !CC jump 4;\n\t" - "%0 = %0 + %4;\n\t" - "%0 = %0 + %2;\n\t" - "CC = AC0;\n\t" - "if !CC jump 4;\n\t" - "%0 = %0 + %4;\n\t" - "%0 = %0 + %3;\n\t" - "CC = AC0;\n\t" - "if !CC jump 4;\n\t" - "%0 = %0 + %4;\n\t" - "NOP;\n\t" - : "=d" (sum) - : "d" (daddr), "d" (saddr), "d" ((ntohs(len)<<16)+proto*256), "d" (1), "0"(sum) - : "CC"); + unsigned int carry; + + __asm__ ("%0 = %0 + %2;\n\t" + "CC = AC0;\n\t" + "%1 = CC;\n\t" + "%0 = %0 + %1;\n\t" + "%0 = %0 + %3;\n\t" + "CC = AC0;\n\t" + "%1 = CC;\n\t" + "%0 = %0 + %1;\n\t" + "%0 = %0 + %4;\n\t" + "CC = AC0;\n\t" + "%1 = CC;\n\t" + "%0 = %0 + %1;\n\t" + : "=d" (sum), "=&d" (carry) + : "d" (daddr), "d" (saddr), "d" ((len + proto) << 8), "0"(sum) + : "CC"); return (sum); } diff --git a/arch/blackfin/include/asm/delay.h b/arch/blackfin/include/asm/delay.h index 0889c3a..c31f91c 100644 --- a/arch/blackfin/include/asm/delay.h +++ b/arch/blackfin/include/asm/delay.h @@ -13,29 +13,7 @@ static inline void __delay(unsigned long loops) { - if (ANOMALY_05000312) { - /* Interrupted loads to loop registers -> bad */ - unsigned long tmp; - __asm__ __volatile__( - "[--SP] = LC0;" - "[--SP] = LT0;" - "[--SP] = LB0;" - "LSETUP (1f,1f) LC0 = %1;" - "1: NOP;" - /* We take advantage of the fact that LC0 is 0 at - * the end of the loop. Otherwise we'd need some - * NOPs after the CLI here. - */ - "CLI %0;" - "LB0 = [SP++];" - "LT0 = [SP++];" - "LC0 = [SP++];" - "STI %0;" - : "=d" (tmp) - : "a" (loops) - ); - } else - __asm__ __volatile__ ( +__asm__ __volatile__ ( "LSETUP(1f, 1f) LC0 = %0;" "1: NOP;" : @@ -47,16 +25,15 @@ static inline void __delay(unsigned long loops) #include <linux/param.h> /* needed for HZ */ /* - * Use only for very small delays ( < 1 msec). Should probably use a - * lookup table, really, as the multiplications take much too long with - * short delays. This is a "reasonable" implementation, though (and the - * first constant multiplications gets optimized away if the delay is - * a constant) + * close approximation borrowed from m68knommu to avoid 64-bit math */ + +#define HZSCALE (268435456 / (1000000/HZ)) + static inline void udelay(unsigned long usecs) { extern unsigned long loops_per_jiffy; - __delay(usecs * loops_per_jiffy / (1000000 / HZ)); + __delay((((usecs * HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6); } #endif diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h index 9477d82..d4a082e 100644 --- a/arch/blackfin/include/asm/gpio.h +++ b/arch/blackfin/include/asm/gpio.h @@ -27,60 +27,6 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* -* Number BF537/6/4 BF561 BF533/2/1 -* BF527/5/2 -* -* GPIO_0 PF0 PF0 PF0 -* GPIO_1 PF1 PF1 PF1 -* GPIO_2 PF2 PF2 PF2 -* GPIO_3 PF3 PF3 PF3 -* GPIO_4 PF4 PF4 PF4 -* GPIO_5 PF5 PF5 PF5 -* GPIO_6 PF6 PF6 PF6 -* GPIO_7 PF7 PF7 PF7 -* GPIO_8 PF8 PF8 PF8 -* GPIO_9 PF9 PF9 PF9 -* GPIO_10 PF10 PF10 PF10 -* GPIO_11 PF11 PF11 PF11 -* GPIO_12 PF12 PF12 PF12 -* GPIO_13 PF13 PF13 PF13 -* GPIO_14 PF14 PF14 PF14 -* GPIO_15 PF15 PF15 PF15 -* GPIO_16 PG0 PF16 -* GPIO_17 PG1 PF17 -* GPIO_18 PG2 PF18 -* GPIO_19 PG3 PF19 -* GPIO_20 PG4 PF20 -* GPIO_21 PG5 PF21 -* GPIO_22 PG6 PF22 -* GPIO_23 PG7 PF23 -* GPIO_24 PG8 PF24 -* GPIO_25 PG9 PF25 -* GPIO_26 PG10 PF26 -* GPIO_27 PG11 PF27 -* GPIO_28 PG12 PF28 -* GPIO_29 PG13 PF29 -* GPIO_30 PG14 PF30 -* GPIO_31 PG15 PF31 -* GPIO_32 PH0 PF32 -* GPIO_33 PH1 PF33 -* GPIO_34 PH2 PF34 -* GPIO_35 PH3 PF35 -* GPIO_36 PH4 PF36 -* GPIO_37 PH5 PF37 -* GPIO_38 PH6 PF38 -* GPIO_39 PH7 PF39 -* GPIO_40 PH8 PF40 -* GPIO_41 PH9 PF41 -* GPIO_42 PH10 PF42 -* GPIO_43 PH11 PF43 -* GPIO_44 PH12 PF44 -* GPIO_45 PH13 PF45 -* GPIO_46 PH14 PF46 -* GPIO_47 PH15 PF47 -*/ - #ifndef __ARCH_BLACKFIN_GPIO_H__ #define __ARCH_BLACKFIN_GPIO_H__ @@ -295,10 +241,6 @@ int bfin_gpio_direction_output(unsigned gpio, int value); int bfin_gpio_get_value(unsigned gpio); void bfin_gpio_set_value(unsigned gpio, int value); -#ifndef BF548_FAMILY -#define bfin_gpio_set_value(gpio, value) set_gpio_data(gpio, value) -#endif - #ifdef CONFIG_GPIOLIB #include <asm-generic/gpio.h> /* cansleep wrappers */ diff --git a/arch/blackfin/include/asm/kgdb.h b/arch/blackfin/include/asm/kgdb.h index 26ebac6..c8b256d 100644 --- a/arch/blackfin/include/asm/kgdb.h +++ b/arch/blackfin/include/asm/kgdb.h @@ -1,32 +1,8 @@ -/* - * File: include/asm-blackfin/kgdb.h - * Based on: - * Author: Sonic Zhang - * - * Created: - * Description: - * - * Rev: $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $ - * - * Modified: - * Copyright 2005-2006 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ +/* Blackfin KGDB header * - * 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. + * Copyright 2005-2009 Analog Devices Inc. * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * Licensed under the GPL-2 or later. */ #ifndef __ASM_BLACKFIN_KGDB_H__ @@ -37,17 +13,18 @@ /* gdb locks */ #define KGDB_MAX_NO_CPUS 8 -/************************************************************************/ -/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ -/* at least NUMREGBYTES*2 are needed for register packets */ -/* Longer buffer is needed to list all threads */ +/* + * BUFMAX defines the maximum number of characters in inbound/outbound buffers. + * At least NUMREGBYTES*2 are needed for register packets. + * Longer buffer is needed to list all threads. + */ #define BUFMAX 2048 /* - * Note that this register image is different from - * the register image that Linux produces at interrupt time. - * - * Linux's register image is defined by struct pt_regs in ptrace.h. + * Note that this register image is different from + * the register image that Linux produces at interrupt time. + * + * Linux's register image is defined by struct pt_regs in ptrace.h. */ enum regnames { /* Core Registers */ @@ -104,14 +81,14 @@ enum regnames { BFIN_RETX, BFIN_RETN, BFIN_RETE, - + /* Pseudo Registers */ BFIN_PC, BFIN_CC, BFIN_EXTRA1, /* Address of .text section. */ BFIN_EXTRA2, /* Address of .data section. */ BFIN_EXTRA3, /* Address of .bss section. */ - BFIN_FDPIC_EXEC, + BFIN_FDPIC_EXEC, BFIN_FDPIC_INTERP, /* MMRs */ @@ -126,7 +103,7 @@ enum regnames { static inline void arch_kgdb_breakpoint(void) { - asm(" EXCPT 2;"); + asm("EXCPT 2;"); } #define BREAK_INSTR_SIZE 2 #define CACHE_FLUSH_IS_SAFE 1 diff --git a/arch/blackfin/include/asm/mem_init.h b/arch/blackfin/include/asm/mem_init.h index 255a931..61f7487 100644 --- a/arch/blackfin/include/asm/mem_init.h +++ b/arch/blackfin/include/asm/mem_init.h @@ -115,7 +115,7 @@ #define mem_SDRRC (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num) /* Enable SCLK Out */ -#define mem_SDGCTL (0x80000000 | SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS) +#define mem_SDGCTL (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS) #else #define mem_SDRRC CONFIG_MEM_SDRRC #define mem_SDGCTL CONFIG_MEM_SDGCTL diff --git a/arch/blackfin/include/asm/pda.h b/arch/blackfin/include/asm/pda.h index bd8d4a7..a671427 100644 --- a/arch/blackfin/include/asm/pda.h +++ b/arch/blackfin/include/asm/pda.h @@ -59,6 +59,7 @@ struct blackfin_pda { /* Per-processor Data Area */ unsigned long icplb_fault_addr; unsigned long retx; unsigned long seqstat; + unsigned int __nmi_count; /* number of times NMI asserted on this CPU */ }; extern struct blackfin_pda cpu_pda[]; diff --git a/arch/blackfin/include/asm/reboot.h b/arch/blackfin/include/asm/reboot.h index 4856d62..ae1e363 100644 --- a/arch/blackfin/include/asm/reboot.h +++ b/arch/blackfin/include/asm/reboot.h @@ -15,6 +15,6 @@ extern void native_machine_halt(void); extern void native_machine_power_off(void); /* common reboot workarounds */ -extern void bfin_gpio_reset_spi0_ssel1(void); +extern void bfin_reset_boot_spi_cs(unsigned short pin); #endif diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index 38a2333..4a92a86 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile @@ -15,6 +15,8 @@ else obj-y += time.o endif +CFLAGS_kgdb_test.o := -mlong-calls -O0 + obj-$(CONFIG_IPIPE) += ipipe.o obj-$(CONFIG_IPIPE_TRACE_MCOUNT) += mcount.o obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index 07e02c0..8531693 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c @@ -249,6 +249,13 @@ static void __dma_memcpy(u32 daddr, s16 dmod, u32 saddr, s16 smod, size_t cnt, u spin_lock_irqsave(&mdma_lock, flags); + /* Force a sync in case a previous config reset on this channel + * occurred. This is needed so subsequent writes to DMA registers + * are not spuriously lost/corrupted. Do it under irq lock and + * without the anomaly version (because we are atomic already). + */ + __builtin_bfin_ssync(); + if (bfin_read_MDMA_S0_CONFIG()) while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) continue; diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 4c14331..51dac55 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -27,59 +27,6 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* -* Number BF537/6/4 BF561 BF533/2/1 BF549/8/4/2 -* -* GPIO_0 PF0 PF0 PF0 PA0...PJ13 -* GPIO_1 PF1 PF1 PF1 -* GPIO_2 PF2 PF2 PF2 -* GPIO_3 PF3 PF3 PF3 -* GPIO_4 PF4 PF4 PF4 -* GPIO_5 PF5 PF5 PF5 -* GPIO_6 PF6 PF6 PF6 -* GPIO_7 PF7 PF7 PF7 -* GPIO_8 PF8 PF8 PF8 -* GPIO_9 PF9 PF9 PF9 -* GPIO_10 PF10 PF10 PF10 -* GPIO_11 PF11 PF11 PF11 -* GPIO_12 PF12 PF12 PF12 -* GPIO_13 PF13 PF13 PF13 -* GPIO_14 PF14 PF14 PF14 -* GPIO_15 PF15 PF15 PF15 -* GPIO_16 PG0 PF16 -* GPIO_17 PG1 PF17 -* GPIO_18 PG2 PF18 -* GPIO_19 PG3 PF19 -* GPIO_20 PG4 PF20 -* GPIO_21 PG5 PF21 -* GPIO_22 PG6 PF22 -* GPIO_23 PG7 PF23 -* GPIO_24 PG8 PF24 -* GPIO_25 PG9 PF25 -* GPIO_26 PG10 PF26 -* GPIO_27 PG11 PF27 -* GPIO_28 PG12 PF28 -* GPIO_29 PG13 PF29 -* GPIO_30 PG14 PF30 -* GPIO_31 PG15 PF31 -* GPIO_32 PH0 PF32 -* GPIO_33 PH1 PF33 -* GPIO_34 PH2 PF34 -* GPIO_35 PH3 PF35 -* GPIO_36 PH4 PF36 -* GPIO_37 PH5 PF37 -* GPIO_38 PH6 PF38 -* GPIO_39 PH7 PF39 -* GPIO_40 PH8 PF40 -* GPIO_41 PH9 PF41 -* GPIO_42 PH10 PF42 -* GPIO_43 PH11 PF43 -* GPIO_44 PH12 PF44 -* GPIO_45 PH13 PF45 -* GPIO_46 PH14 PF46 -* GPIO_47 PH15 PF47 -*/ - #include <linux/delay.h> #include <linux/module.h> #include <linux/err.h> @@ -119,62 +66,61 @@ enum { #define AWA_DUMMY_READ(...) do { } while (0) #endif +static struct gpio_port_t * const gpio_array[] = { #if defined(BF533_FAMILY) || defined(BF538_FAMILY) -static struct gpio_port_t *gpio_bankb[] = { (struct gpio_port_t *) FIO_FLAG_D, -}; -#endif - -#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) -static struct gpio_port_t *gpio_bankb[] = { +#elif defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) (struct gpio_port_t *) PORTFIO, (struct gpio_port_t *) PORTGIO, (struct gpio_port_t *) PORTHIO, +#elif defined(BF561_FAMILY) + (struct gpio_port_t *) FIO0_FLAG_D, + (struct gpio_port_t *) FIO1_FLAG_D, + (struct gpio_port_t *) FIO2_FLAG_D, +#elif defined(BF548_FAMILY) + (struct gpio_port_t *)PORTA_FER, + (struct gpio_port_t *)PORTB_FER, + (struct gpio_port_t *)PORTC_FER, + (struct gpio_port_t *)PORTD_FER, + (struct gpio_port_t *)PORTE_FER, + (struct gpio_port_t *)PORTF_FER, + (struct gpio_port_t *)PORTG_FER, + (struct gpio_port_t *)PORTH_FER, + (struct gpio_port_t *)PORTI_FER, + (struct gpio_port_t *)PORTJ_FER, +#else +# error no gpio arrays defined +#endif }; -static unsigned short *port_fer[] = { +#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) +static unsigned short * const port_fer[] = { (unsigned short *) PORTF_FER, (unsigned short *) PORTG_FER, (unsigned short *) PORTH_FER, }; -#endif -#if defined(BF527_FAMILY) || defined(BF518_FAMILY) -static unsigned short *port_mux[] = { +# if !defined(BF537_FAMILY) +static unsigned short * const port_mux[] = { (unsigned short *) PORTF_MUX, (unsigned short *) PORTG_MUX, (unsigned short *) PORTH_MUX, }; static const -u8 pmux_offset[][16] = - {{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */ - { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */ - { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */ - }; -#endif - -#ifdef BF561_FAMILY -static struct gpio_port_t *gpio_bankb[] = { - (struct gpio_port_t *) FIO0_FLAG_D, - (struct gpio_port_t *) FIO1_FLAG_D, - (struct gpio_port_t *) FIO2_FLAG_D, +u8 pmux_offset[][16] = { +# if defined(BF527_FAMILY) + { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */ + { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */ + { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */ +# elif defined(BF518_FAMILY) + { 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */ + { 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */ + { 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */ +# endif }; -#endif +# endif -#ifdef BF548_FAMILY -static struct gpio_port_t *gpio_array[] = { - (struct gpio_port_t *)PORTA_FER, - (struct gpio_port_t *)PORTB_FER, - (struct gpio_port_t *)PORTC_FER, - (struct gpio_port_t *)PORTD_FER, - (struct gpio_port_t *)PORTE_FER, - (struct gpio_port_t *)PORTF_FER, - (struct gpio_port_t *)PORTG_FER, - (struct gpio_port_t *)PORTH_FER, - (struct gpio_port_t *)PORTI_FER, - (struct gpio_port_t *)PORTJ_FER, -}; #endif static unsigned short reserved_gpio_map[GPIO_BANK_NUM]; @@ -188,35 +134,9 @@ static struct str_ident { } str_ident[MAX_RESOURCES]; #if defined(CONFIG_PM) -#if defined(CONFIG_BF54x) -static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM]; -#else -static unsigned short wakeup_map[GPIO_BANK_NUM]; -static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS]; static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM]; - -#ifdef BF533_FAMILY -static unsigned int sic_iwr_irqs[] = {IRQ_PROG_INTB}; -#endif - -#ifdef BF537_FAMILY -static unsigned int sic_iwr_irqs[] = {IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX}; -#endif - -#ifdef BF538_FAMILY -static unsigned int sic_iwr_irqs[] = {IRQ_PORTF_INTB}; #endif -#if defined(BF527_FAMILY) || defined(BF518_FAMILY) -static unsigned int sic_iwr_irqs[] = {IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB}; -#endif - -#ifdef BF561_FAMILY -static unsigned int sic_iwr_irqs[] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB}; -#endif -#endif -#endif /* CONFIG_PM */ - inline int check_gpio(unsigned gpio) { #if defined(BF548_FAMILY) @@ -330,9 +250,10 @@ static struct { {.res = P_SPI0_SSEL3, .offset = 0}, }; -static void portmux_setup(unsigned short per, unsigned short function) +static void portmux_setup(unsigned short per) { u16 y, offset, muxreg; + u16 function = P_FUNCT2MUX(per); for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) { if (port_mux_lut[y].res == per) { @@ -353,30 +274,33 @@ static void portmux_setup(unsigned short per, unsigned short function) } } #elif defined(BF548_FAMILY) -inline void portmux_setup(unsigned short portno, unsigned short function) +inline void portmux_setup(unsigned short per) { u32 pmux; + u16 ident = P_IDENT(per); + u16 function = P_FUNCT2MUX(per); - pmux = gpio_array[gpio_bank(portno)]->port_mux; + pmux = gpio_array[gpio_bank(ident)]->port_mux; - pmux &= ~(0x3 << (2 * gpio_sub_n(portno))); - pmux |= (function & 0x3) << (2 * gpio_sub_n(portno)); + pmux &= ~(0x3 << (2 * gpio_sub_n(ident))); + pmux |= (function & 0x3) << (2 * gpio_sub_n(ident)); - gpio_array[gpio_bank(portno)]->port_mux = pmux; + gpio_array[gpio_bank(ident)]->port_mux = pmux; } -inline u16 get_portmux(unsigned short portno) +inline u16 get_portmux(unsigned short per) { u32 pmux; + u16 ident = P_IDENT(per); - pmux = gpio_array[gpio_bank(portno)]->port_mux; + pmux = gpio_array[gpio_bank(ident)]->port_mux; - return (pmux >> (2 * gpio_sub_n(portno)) & 0x3); + return (pmux >> (2 * gpio_sub_n(ident)) & 0x3); } #elif defined(BF527_FAMILY) || defined(BF518_FAMILY) -inline void portmux_setup(unsigned short portno, unsigned short function) +inline void portmux_setup(unsigned short per) { - u16 pmux, ident = P_IDENT(portno); + u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per); u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; pmux = *port_mux[gpio_bank(ident)]; @@ -424,90 +348,71 @@ void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ unsigned long flags; \ local_irq_save_hw(flags); \ if (arg) \ - gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ + gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ else \ - gpio_bankb[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \ + gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \ AWA_DUMMY_READ(name); \ local_irq_restore_hw(flags); \ } \ EXPORT_SYMBOL(set_gpio_ ## name); -SET_GPIO(dir) -SET_GPIO(inen) -SET_GPIO(polar) -SET_GPIO(edge) -SET_GPIO(both) +SET_GPIO(dir) /* set_gpio_dir() */ +SET_GPIO(inen) /* set_gpio_inen() */ +SET_GPIO(polar) /* set_gpio_polar() */ +SET_GPIO(edge) /* set_gpio_edge() */ +SET_GPIO(both) /* set_gpio_both() */ -#if ANOMALY_05000311 || ANOMALY_05000323 #define SET_GPIO_SC(name) \ void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ { \ unsigned long flags; \ - local_irq_save_hw(flags); \ - if (arg) \ - gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ - else \ - gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ - AWA_DUMMY_READ(name); \ - local_irq_restore_hw(flags); \ -} \ -EXPORT_SYMBOL(set_gpio_ ## name); -#else -#define SET_GPIO_SC(name) \ -void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ -{ \ + if (ANOMALY_05000311 || ANOMALY_05000323) \ + local_irq_save_hw(flags); \ if (arg) \ - gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ + gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ else \ - gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ + gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ + if (ANOMALY_05000311 || ANOMALY_05000323) { \ + AWA_DUMMY_READ(name); \ + local_irq_restore_hw(flags); \ + } \ } \ EXPORT_SYMBOL(set_gpio_ ## name); -#endif SET_GPIO_SC(maska) SET_GPIO_SC(maskb) SET_GPIO_SC(data) -#if ANOMALY_05000311 || ANOMALY_05000323 void set_gpio_toggle(unsigned gpio) { unsigned long flags; - local_irq_save_hw(flags); - gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); - AWA_DUMMY_READ(toggle); - local_irq_restore_hw(flags); -} -#else -void set_gpio_toggle(unsigned gpio) -{ - gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); + if (ANOMALY_05000311 || ANOMALY_05000323) + local_irq_save_hw(flags); + gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio); + if (ANOMALY_05000311 || ANOMALY_05000323) { + AWA_DUMMY_READ(toggle); + local_irq_restore_hw(flags); + } } -#endif EXPORT_SYMBOL(set_gpio_toggle); /*Set current PORT date (16-bit word)*/ -#if ANOMALY_05000311 || ANOMALY_05000323 #define SET_GPIO_P(name) \ void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \ { \ unsigned long flags; \ - local_irq_save_hw(flags); \ - gpio_bankb[gpio_bank(gpio)]->name = arg; \ - AWA_DUMMY_READ(name); \ - local_irq_restore_hw(flags); \ + if (ANOMALY_05000311 || ANOMALY_05000323) \ + local_irq_save_hw(flags); \ + gpio_array[gpio_bank(gpio)]->name = arg; \ + if (ANOMALY_05000311 || ANOMALY_05000323) { \ + AWA_DUMMY_READ(name); \ + local_irq_restore_hw(flags); \ + } \ } \ EXPORT_SYMBOL(set_gpiop_ ## name); -#else -#define SET_GPIO_P(name) \ -void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \ -{ \ - gpio_bankb[gpio_bank(gpio)]->name = arg; \ -} \ -EXPORT_SYMBOL(set_gpiop_ ## name); -#endif SET_GPIO_P(data) SET_GPIO_P(dir) @@ -519,27 +424,21 @@ SET_GPIO_P(maska) SET_GPIO_P(maskb) /* Get a specific bit */ -#if ANOMALY_05000311 || ANOMALY_05000323 #define GET_GPIO(name) \ unsigned short get_gpio_ ## name(unsigned gpio) \ { \ unsigned long flags; \ unsigned short ret; \ - local_irq_save_hw(flags); \ - ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \ - AWA_DUMMY_READ(name); \ - local_irq_restore_hw(flags); \ + if (ANOMALY_05000311 || ANOMALY_05000323) \ + local_irq_save_hw(flags); \ + ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \ + if (ANOMALY_05000311 || ANOMALY_05000323) { \ + AWA_DUMMY_READ(name); \ + local_irq_restore_hw(flags); \ + } \ return ret; \ } \ EXPORT_SYMBOL(get_gpio_ ## name); -#else -#define GET_GPIO(name) \ -unsigned short get_gpio_ ## name(unsigned gpio) \ -{ \ - return (0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio))); \ -} \ -EXPORT_SYMBOL(get_gpio_ ## name); -#endif GET_GPIO(data) GET_GPIO(dir) @@ -552,27 +451,21 @@ GET_GPIO(maskb) /*Get current PORT date (16-bit word)*/ -#if ANOMALY_05000311 || ANOMALY_05000323 #define GET_GPIO_P(name) \ unsigned short get_gpiop_ ## name(unsigned gpio) \ { \ unsigned long flags; \ unsigned short ret; \ - local_irq_save_hw(flags); \ - ret = (gpio_bankb[gpio_bank(gpio)]->name); \ - AWA_DUMMY_READ(name); \ - local_irq_restore_hw(flags); \ + if (ANOMALY_05000311 || ANOMALY_05000323) \ + local_irq_save_hw(flags); \ + ret = (gpio_array[gpio_bank(gpio)]->name); \ + if (ANOMALY_05000311 || ANOMALY_05000323) { \ + AWA_DUMMY_READ(name); \ + local_irq_restore_hw(flags); \ + } \ return ret; \ } \ EXPORT_SYMBOL(get_gpiop_ ## name); -#else -#define GET_GPIO_P(name) \ -unsigned short get_gpiop_ ## name(unsigned gpio) \ -{ \ - return (gpio_bankb[gpio_bank(gpio)]->name);\ -} \ -EXPORT_SYMBOL(get_gpiop_ ## name); -#endif GET_GPIO_P(data) GET_GPIO_P(dir) @@ -585,6 +478,26 @@ GET_GPIO_P(maskb) #ifdef CONFIG_PM + +static unsigned short wakeup_map[GPIO_BANK_NUM]; +static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS]; + +static const unsigned int sic_iwr_irqs[] = { +#if defined(BF533_FAMILY) + IRQ_PROG_INTB +#elif defined(BF537_FAMILY) + IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX +#elif defined(BF538_FAMILY) + IRQ_PORTF_INTB +#elif defined(BF527_FAMILY) || defined(BF518_FAMILY) + IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB +#elif defined(BF561_FAMILY) + IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB +#else +# error no SIC_IWR defined +#endif +}; + /*********************************************************** * * FUNCTIONS: Blackfin PM Setup API @@ -669,18 +582,18 @@ u32 bfin_pm_standby_setup(void) mask = wakeup_map[gpio_bank(i)]; bank = gpio_bank(i); - gpio_bank_saved[bank].maskb = gpio_bankb[bank]->maskb; - gpio_bankb[bank]->maskb = 0; + gpio_bank_saved[bank].maskb = gpio_array[bank]->maskb; + gpio_array[bank]->maskb = 0; if (mask) { #if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) gpio_bank_saved[bank].fer = *port_fer[bank]; #endif - gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen; - gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar; - gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir; - gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge; - gpio_bank_saved[bank].both = gpio_bankb[bank]->both; + gpio_bank_saved[bank].inen = gpio_array[bank]->inen; + gpio_bank_saved[bank].polar = gpio_array[bank]->polar; + gpio_bank_saved[bank].dir = gpio_array[bank]->dir; + gpio_bank_saved[bank].edge = gpio_array[bank]->edge; + gpio_bank_saved[bank].both = gpio_array[bank]->both; gpio_bank_saved[bank].reserved = reserved_gpio_map[bank]; @@ -700,7 +613,7 @@ u32 bfin_pm_standby_setup(void) } bfin_internal_set_wake(sic_iwr_irqs[bank], 1); - gpio_bankb[bank]->maskb_set = wakeup_map[gpio_bank(i)]; + gpio_array[bank]->maskb_set = wakeup_map[gpio_bank(i)]; } } @@ -721,18 +634,18 @@ void bfin_pm_standby_restore(void) #if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) *port_fer[bank] = gpio_bank_saved[bank].fer; #endif - gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen; - gpio_bankb[bank]->dir = gpio_bank_saved[bank].dir; - gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar; - gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge; - gpio_bankb[bank]->both = gpio_bank_saved[bank].both; + gpio_array[bank]->inen = gpio_bank_saved[bank].inen; + gpio_array[bank]->dir = gpio_bank_saved[bank].dir; + gpio_array[bank]->polar = gpio_bank_saved[bank].polar; + gpio_array[bank]->edge = gpio_bank_saved[bank].edge; + gpio_array[bank]->both = gpio_bank_saved[bank].both; reserved_gpio_map[bank] = gpio_bank_saved[bank].reserved; bfin_internal_set_wake(sic_iwr_irqs[bank], 0); } - gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb; + gpio_array[bank]->maskb = gpio_bank_saved[bank].maskb; } AWA_DUMMY_READ(maskb); } @@ -745,21 +658,21 @@ void bfin_gpio_pm_hibernate_suspend(void) bank = gpio_bank(i); #if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) - gpio_bank_saved[bank].fer = *port_fer[bank]; + gpio_bank_saved[bank].fer = *port_fer[bank]; #if defined(BF527_FAMILY) || defined(BF518_FAMILY) - gpio_bank_saved[bank].mux = *port_mux[bank]; + gpio_bank_saved[bank].mux = *port_mux[bank]; #else - if (bank == 0) - gpio_bank_saved[bank].mux = bfin_read_PORT_MUX(); + if (bank == 0) + gpio_bank_saved[bank].mux = bfin_read_PORT_MUX(); #endif #endif - gpio_bank_saved[bank].data = gpio_bankb[bank]->data; - gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen; - gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar; - gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir; - gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge; - gpio_bank_saved[bank].both = gpio_bankb[bank]->both; - gpio_bank_saved[bank].maska = gpio_bankb[bank]->maska; + gpio_bank_saved[bank].data = gpio_array[bank]->data; + gpio_bank_saved[bank].inen = gpio_array[bank]->inen; + gpio_bank_saved[bank].polar = gpio_array[bank]->polar; + gpio_bank_saved[bank].dir = gpio_array[bank]->dir; + gpio_bank_saved[bank].edge = gpio_array[bank]->edge; + gpio_bank_saved[bank].both = gpio_array[bank]->both; + gpio_bank_saved[bank].maska = gpio_array[bank]->maska; } AWA_DUMMY_READ(maska); @@ -770,27 +683,27 @@ void bfin_gpio_pm_hibernate_restore(void) int i, bank; for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { - bank = gpio_bank(i); + bank = gpio_bank(i); #if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) #if defined(BF527_FAMILY) || defined(BF518_FAMILY) - *port_mux[bank] = gpio_bank_saved[bank].mux; + *port_mux[bank] = gpio_bank_saved[bank].mux; #else - if (bank == 0) - bfin_write_PORT_MUX(gpio_bank_saved[bank].mux); + if (bank == 0) + bfin_write_PORT_MUX(gpio_bank_saved[bank].mux); #endif - *port_fer[bank] = gpio_bank_saved[bank].fer; + *port_fer[bank] = gpio_bank_saved[bank].fer; #endif - gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen; - gpio_bankb[bank]->dir = gpio_bank_saved[bank].dir; - gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar; - gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge; - gpio_bankb[bank]->both = gpio_bank_saved[bank].both; + gpio_array[bank]->inen = gpio_bank_saved[bank].inen; + gpio_array[bank]->dir = gpio_bank_saved[bank].dir; + gpio_array[bank]->polar = gpio_bank_saved[bank].polar; + gpio_array[bank]->edge = gpio_bank_saved[bank].edge; + gpio_array[bank]->both = gpio_bank_saved[bank].both; - gpio_bankb[bank]->data_set = gpio_bank_saved[bank].data - | gpio_bank_saved[bank].dir; + gpio_array[bank]->data_set = gpio_bank_saved[bank].data + | gpio_bank_saved[bank].dir; - gpio_bankb[bank]->maska = gpio_bank_saved[bank].maska; + gpio_array[bank]->maska = gpio_bank_saved[bank].maska; } AWA_DUMMY_READ(maska); } @@ -817,12 +730,12 @@ void bfin_gpio_pm_hibernate_suspend(void) for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { bank = gpio_bank(i); - gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer; - gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux; - gpio_bank_saved[bank].data = gpio_array[bank]->port_data; - gpio_bank_saved[bank].data = gpio_array[bank]->port_data; - gpio_bank_saved[bank].inen = gpio_array[bank]->port_inen; - gpio_bank_saved[bank].dir = gpio_array[bank]->port_dir_set; + gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer; + gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux; + gpio_bank_saved[bank].data = gpio_array[bank]->data; + gpio_bank_saved[bank].data = gpio_array[bank]->data; + gpio_bank_saved[bank].inen = gpio_array[bank]->inen; + gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set; } } @@ -831,21 +744,21 @@ void bfin_gpio_pm_hibernate_restore(void) int i, bank; for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { - bank = gpio_bank(i); - - gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux; - gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer; - gpio_array[bank]->port_inen = gpio_bank_saved[bank].inen; - gpio_array[bank]->port_dir_set = gpio_bank_saved[bank].dir; - gpio_array[bank]->port_set = gpio_bank_saved[bank].data - | gpio_bank_saved[bank].dir; + bank = gpio_bank(i); + + gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux; + gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer; + gpio_array[bank]->inen = gpio_bank_saved[bank].inen; + gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir; + gpio_array[bank]->data_set = gpio_bank_saved[bank].data + | gpio_bank_saved[bank].dir; } } #endif unsigned short get_gpio_dir(unsigned gpio) { - return (0x01 & (gpio_array[gpio_bank(gpio)]->port_dir_clear >> gpio_sub_n(gpio))); + return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio))); } EXPORT_SYMBOL(get_gpio_dir); @@ -905,9 +818,7 @@ int peripheral_request(unsigned short per, const char *label) */ #ifdef BF548_FAMILY - u16 funct = get_portmux(ident); - - if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) { + if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) { #else if (!(per & P_MAYSHARE)) { #endif @@ -931,11 +842,7 @@ int peripheral_request(unsigned short per, const char *label) anyway: reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident); -#ifdef BF548_FAMILY - portmux_setup(ident, P_FUNCT2MUX(per)); -#else - portmux_setup(per, P_FUNCT2MUX(per)); -#endif + portmux_setup(per); port_setup(ident, PERIPHERAL_USAGE); local_irq_restore_hw(flags); @@ -977,9 +884,6 @@ void peripheral_free(unsigned short per) if (!(per & P_DEFINED)) return; - if (check_gpio(ident) < 0) - return; - local_irq_save_hw(flags); if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) { @@ -1056,9 +960,15 @@ int bfin_gpio_request(unsigned gpio, const char *label) local_irq_restore_hw(flags); return -EBUSY; } - if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) + if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) { printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!" " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio); + } +#ifndef BF548_FAMILY + else { /* Reset POLAR setting when acquiring a gpio for the first time */ + set_gpio_polar(gpio, 0); + } +#endif reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); set_label(gpio, label); @@ -1078,6 +988,8 @@ void bfin_gpio_free(unsigned gpio) if (check_gpio(gpio) < 0) return; + might_sleep(); + local_irq_save_hw(flags); if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { @@ -1158,8 +1070,16 @@ void bfin_gpio_irq_free(unsigned gpio) local_irq_restore_hw(flags); } - +static inline void __bfin_gpio_direction_input(unsigned gpio) +{ #ifdef BF548_FAMILY + gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio); +#else + gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); +#endif + gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio); +} + int bfin_gpio_direction_input(unsigned gpio) { unsigned long flags; @@ -1170,125 +1090,85 @@ int bfin_gpio_direction_input(unsigned gpio) } local_irq_save_hw(flags); - gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio); - gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio); + __bfin_gpio_direction_input(gpio); + AWA_DUMMY_READ(inen); local_irq_restore_hw(flags); return 0; } EXPORT_SYMBOL(bfin_gpio_direction_input); -int bfin_gpio_direction_output(unsigned gpio, int value) +void bfin_gpio_irq_prepare(unsigned gpio) { +#ifdef BF548_FAMILY unsigned long flags; +#endif - if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { - gpio_error(gpio); - return -EINVAL; - } + port_setup(gpio, GPIO_USAGE); +#ifdef BF548_FAMILY local_irq_save_hw(flags); - gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio); - gpio_set_value(gpio, value); - gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio); + __bfin_gpio_direction_input(gpio); local_irq_restore_hw(flags); - - return 0; +#endif } -EXPORT_SYMBOL(bfin_gpio_direction_output); void bfin_gpio_set_value(unsigned gpio, int arg) { if (arg) - gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio); + gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); else - gpio_array[gpio_bank(gpio)]->port_clear = gpio_bit(gpio); + gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio); } EXPORT_SYMBOL(bfin_gpio_set_value); -int bfin_gpio_get_value(unsigned gpio) -{ - return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio))); -} -EXPORT_SYMBOL(bfin_gpio_get_value); - -void bfin_gpio_irq_prepare(unsigned gpio) +int bfin_gpio_direction_output(unsigned gpio, int value) { unsigned long flags; - port_setup(gpio, GPIO_USAGE); + if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { + gpio_error(gpio); + return -EINVAL; + } local_irq_save_hw(flags); - gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio); - gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio); - local_irq_restore_hw(flags); -} + gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); + gpio_set_value(gpio, value); +#ifdef BF548_FAMILY + gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio); #else + gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio); +#endif + + AWA_DUMMY_READ(dir); + local_irq_restore_hw(flags); + + return 0; +} +EXPORT_SYMBOL(bfin_gpio_direction_output); int bfin_gpio_get_value(unsigned gpio) { +#ifdef BF548_FAMILY + return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio))); +#else unsigned long flags; - int ret; if (unlikely(get_gpio_edge(gpio))) { + int ret; local_irq_save_hw(flags); set_gpio_edge(gpio, 0); ret = get_gpio_data(gpio); set_gpio_edge(gpio, 1); local_irq_restore_hw(flags); - return ret; } else return get_gpio_data(gpio); +#endif } EXPORT_SYMBOL(bfin_gpio_get_value); - -int bfin_gpio_direction_input(unsigned gpio) -{ - unsigned long flags; - - if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { - gpio_error(gpio); - return -EINVAL; - } - - local_irq_save_hw(flags); - gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); - gpio_bankb[gpio_bank(gpio)]->inen |= gpio_bit(gpio); - AWA_DUMMY_READ(inen); - local_irq_restore_hw(flags); - - return 0; -} -EXPORT_SYMBOL(bfin_gpio_direction_input); - -int bfin_gpio_direction_output(unsigned gpio, int value) -{ - unsigned long flags; - - if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { - gpio_error(gpio); - return -EINVAL; - } - - local_irq_save_hw(flags); - gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); - - if (value) - gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); - else - gpio_bankb[gpio_bank(gpio)]->data_clear = gpio_bit(gpio); - - gpio_bankb[gpio_bank(gpio)]->dir |= gpio_bit(gpio); - AWA_DUMMY_READ(dir); - local_irq_restore_hw(flags); - - return 0; -} -EXPORT_SYMBOL(bfin_gpio_direction_output); - /* If we are booting from SPI and our board lacks a strong enough pull up, * the core can reset and execute the bootrom faster than the resistor can * pull the signal logically high. To work around this (common) error in @@ -1299,23 +1179,15 @@ EXPORT_SYMBOL(bfin_gpio_direction_output); * lives here as we need to force all the GPIO states w/out going through * BUG() checks and such. */ -void bfin_gpio_reset_spi0_ssel1(void) +void bfin_reset_boot_spi_cs(unsigned short pin) { - u16 gpio = P_IDENT(P_SPI0_SSEL1); - + unsigned short gpio = P_IDENT(pin); port_setup(gpio, GPIO_USAGE); - gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); + gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); AWA_DUMMY_READ(data_set); udelay(1); } -void bfin_gpio_irq_prepare(unsigned gpio) -{ - port_setup(gpio, GPIO_USAGE); -} - -#endif /*BF548_FAMILY */ - #if defined(CONFIG_PROC_FS) static int gpio_proc_read(char *buf, char **start, off_t offset, int len, int *unused_i, void *unused_v) @@ -1369,11 +1241,7 @@ int bfin_gpiolib_get_value(struct gpio_chip *chip, unsigned gpio) void bfin_gpiolib_set_value(struct gpio_chip *chip, unsigned gpio, int value) { -#ifdef BF548_FAMILY return bfin_gpio_set_value(gpio, value); -#else - return set_gpio_data(gpio, value); -#endif } int bfin_gpiolib_gpio_request(struct gpio_chip *chip, unsigned gpio) diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c index bdb9584..3e329a6 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c @@ -63,10 +63,8 @@ void __init generate_cplb_tables_cpu(unsigned int cpu) dcplb_tbl[cpu][i_d].addr = 0; dcplb_tbl[cpu][i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB; -#if 0 icplb_tbl[cpu][i_i].addr = 0; - icplb_tbl[cpu][i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_4KB; -#endif + icplb_tbl[cpu][i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_1KB; /* Cover kernel memory with 4M pages. */ addr = 0; diff --git a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c index 376249a..8cbb47c 100644 --- a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c +++ b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c @@ -163,12 +163,14 @@ MGR_ATTR static int icplb_miss(int cpu) nr_icplb_supv_miss[cpu]++; base = 0; - for (idx = 0; idx < icplb_nr_bounds; idx++) { + idx = 0; + do { eaddr = icplb_bounds[idx].eaddr; if (addr < eaddr) break; base = eaddr; - } + } while (++idx < icplb_nr_bounds); + if (unlikely(idx == icplb_nr_bounds)) return CPLB_NO_ADDR_MATCH; @@ -208,12 +210,14 @@ MGR_ATTR static int dcplb_miss(int cpu) nr_dcplb_supv_miss[cpu]++; base = 0; - for (idx = 0; idx < dcplb_nr_bounds; idx++) { + idx = 0; + do { eaddr = dcplb_bounds[idx].eaddr; if (addr < eaddr) break; base = eaddr; - } + } while (++idx < dcplb_nr_bounds); + if (unlikely(idx == dcplb_nr_bounds)) return CPLB_NO_ADDR_MATCH; diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 5780d6d..23e9aa0 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -35,6 +35,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <asm/trace.h> +#include <asm/pda.h> static atomic_t irq_err_count; static spinlock_t irq_controller_lock; @@ -96,8 +97,13 @@ int show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } else if (i == NR_IRQS) + } else if (i == NR_IRQS) { + seq_printf(p, "NMI: "); + for_each_online_cpu(j) + seq_printf(p, "%10u ", cpu_pda[j].__nmi_count); + seq_printf(p, " CORE Non Maskable Interrupt\n"); seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count)); + } return 0; } diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c index eeee8cb..53d08de 100644 --- a/arch/blackfin/kernel/reboot.c +++ b/arch/blackfin/kernel/reboot.c @@ -20,8 +20,8 @@ * reset while the Core B bit (on dual core parts) is cleared by * the core reset. */ -__attribute__((l1_text)) -static void _bfin_reset(void) +__attribute__ ((__l1_text__, __noreturn__)) +static void bfin_reset(void) { /* Wait for completion of "system" events such as cache line * line fills so that we avoid infinite stalls later on as @@ -30,7 +30,11 @@ static void _bfin_reset(void) */ __builtin_bfin_ssync(); - while (1) { + /* The bootrom checks to see how it was reset and will + * automatically perform a software reset for us when + * it starts executing after the core reset. + */ + if (ANOMALY_05000353 || ANOMALY_05000386) { /* Initiate System software reset. */ bfin_write_SWRST(0x7); @@ -50,6 +54,11 @@ static void _bfin_reset(void) /* Clear System software reset */ bfin_write_SWRST(0); + /* The BF526 ROM will crash during reset */ +#if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__) + bfin_read_SWRST(); +#endif + /* Wait for the SWRST write to complete. Cannot rely on SSYNC * though as the System state is all reset now. */ @@ -60,22 +69,11 @@ static void _bfin_reset(void) : "a" (15 * 1) : "LC1", "LB1", "LT1" ); + } + while (1) /* Issue core reset */ asm("raise 1"); - } -} - -static void bfin_reset(void) -{ - if (ANOMALY_05000353 || ANOMALY_05000386) - _bfin_reset(); - else - /* the bootrom checks to see how it was reset and will - * automatically perform a software reset for us when - * it starts executing boot - */ - asm("raise 1;"); } __attribute__((weak)) diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index b2a8113..e5c1162 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -60,7 +60,7 @@ void __initdata *init_retx, *init_saved_retx, *init_saved_seqstat, #define BFIN_MEMMAP_MAX 128 /* number of entries in bfin_memmap */ #define BFIN_MEMMAP_RAM 1 #define BFIN_MEMMAP_RESERVED 2 -struct bfin_memmap { +static struct bfin_memmap { int nr_map; struct bfin_memmap_entry { unsigned long long addr; /* start of memory segment */ @@ -824,7 +824,15 @@ void __init setup_arch(char **cmdline_p) flash_probe(); #endif + printk(KERN_INFO "Boot Mode: %i\n", bfin_read_SYSCR() & 0xF); + + /* Newer parts mirror SWRST bits in SYSCR */ +#if defined(CONFIG_BF53x) || defined(CONFIG_BF561) || \ + defined(CONFIG_BF538) || defined(CONFIG_BF539) _bfin_swrst = bfin_read_SWRST(); +#else + _bfin_swrst = bfin_read_SYSCR(); +#endif #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT bfin_write_SWRST(_bfin_swrst & ~DOUBLE_FAULT); @@ -853,7 +861,7 @@ void __init setup_arch(char **cmdline_p) else if (_bfin_swrst & RESET_SOFTWARE) printk(KERN_NOTICE "Reset caused by Software reset\n"); - printk(KERN_INFO "Blackfin support (C) 2004-2008 Analog Devices, Inc.\n"); + printk(KERN_INFO "Blackfin support (C) 2004-2009 Analog Devices, Inc.\n"); if (bfin_compiled_revid() == 0xffff) printk(KERN_INFO "Compiled for ADSP-%s Rev any\n", CPU); else if (bfin_compiled_revid() == -1) diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 5b0667d..ffe7fb5 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -673,6 +673,14 @@ static void decode_instruction(unsigned short *address) verbose_printk("RTI"); else if (opcode == 0x0012) verbose_printk("RTX"); + else if (opcode == 0x0013) + verbose_printk("RTN"); + else if (opcode == 0x0014) + verbose_printk("RTE"); + else if (opcode == 0x0025) + verbose_printk("EMUEXCPT"); + else if (opcode == 0x0040 && opcode <= 0x0047) + verbose_printk("STI R%i", opcode & 7); else if (opcode >= 0x0050 && opcode <= 0x0057) verbose_printk("JUMP (P%i)", opcode & 7); else if (opcode >= 0x0060 && opcode <= 0x0067) @@ -681,6 +689,10 @@ static void decode_instruction(unsigned short *address) verbose_printk("CALL (PC+P%i)", opcode & 7); else if (opcode >= 0x0080 && opcode <= 0x0087) verbose_printk("JUMP (PC+P%i)", opcode & 7); + else if (opcode >= 0x0090 && opcode <= 0x009F) + verbose_printk("RAISE 0x%x", opcode & 0xF); + else if (opcode >= 0x00A0 && opcode <= 0x00AF) + verbose_printk("EXCPT 0x%x", opcode & 0xF); else if ((opcode >= 0x1000 && opcode <= 0x13FF) || (opcode >= 0x1800 && opcode <= 0x1BFF)) verbose_printk("IF !CC JUMP"); else if ((opcode >= 0x1400 && opcode <= 0x17ff) || (opcode >= 0x1c00 && opcode <= 0x1fff)) @@ -820,11 +832,8 @@ void show_stack(struct task_struct *task, unsigned long *stack) decode_address(buf, (unsigned int)stack); printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf); - addr = (unsigned int *)((unsigned int)stack & ~0x3F); - /* First thing is to look for a frame pointer */ - for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0; - addr < endstack; addr++, i++) { + for (addr = (unsigned int *)((unsigned int)stack & ~0xF); addr < endstack; addr++) { if (*addr & 0x1) continue; ins_addr = (unsigned short *)*addr; @@ -834,7 +843,8 @@ void show_stack(struct task_struct *task, unsigned long *stack) if (fp) { /* Let's check to see if it is a frame pointer */ - while (fp >= (addr - 1) && fp < endstack && fp) + while (fp >= (addr - 1) && fp < endstack + && fp && ((unsigned int) fp & 0x3) == 0) fp = (unsigned int *)*fp; if (fp == 0 || fp == endstack) { fp = addr - 1; @@ -1052,8 +1062,9 @@ void show_regs(struct pt_regs *fp) char buf [150]; struct irqaction *action; unsigned int i; - unsigned long flags; + unsigned long flags = 0; unsigned int cpu = smp_processor_id(); + unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic(); verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", @@ -1073,17 +1084,22 @@ void show_regs(struct pt_regs *fp) } verbose_printk(KERN_NOTICE " EXCAUSE : 0x%lx\n", fp->seqstat & SEQSTAT_EXCAUSE); - for (i = 6; i <= 15 ; i++) { + for (i = 2; i <= 15 ; i++) { if (fp->ipend & (1 << i)) { - decode_address(buf, bfin_read32(EVT0 + 4*i)); - verbose_printk(KERN_NOTICE " physical IVG%i asserted : %s\n", i, buf); + if (i != 4) { + decode_address(buf, bfin_read32(EVT0 + 4*i)); + verbose_printk(KERN_NOTICE " physical IVG%i asserted : %s\n", i, buf); + } else + verbose_printk(KERN_NOTICE " interrupts disabled\n"); } } /* if no interrupts are going off, don't print this out */ if (fp->ipend & ~0x3F) { for (i = 0; i < (NR_IRQS - 1); i++) { - spin_lock_irqsave(&irq_desc[i].lock, flags); + if (!in_atomic) + spin_lock_irqsave(&irq_desc[i].lock, flags); + action = irq_desc[i].action; if (!action) goto unlock; @@ -1096,7 +1112,8 @@ void show_regs(struct pt_regs *fp) } verbose_printk("\n"); unlock: - spin_unlock_irqrestore(&irq_desc[i].lock, flags); + if (!in_atomic) + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } } diff --git a/arch/blackfin/mach-bf518/boards/ezbrd.c b/arch/blackfin/mach-bf518/boards/ezbrd.c index 15f1351..0e17534 100644 --- a/arch/blackfin/mach-bf518/boards/ezbrd.c +++ b/arch/blackfin/mach-bf518/boards/ezbrd.c @@ -46,6 +46,7 @@ #include <asm/dpmc.h> #include <asm/bfin_sdh.h> #include <linux/spi/ad7877.h> +#include <net/dsa.h> /* * Name the Board for the /proc/cpuinfo @@ -104,8 +105,31 @@ static struct platform_device rtc_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, +}; +#endif + +#if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE) +static struct dsa_platform_data ksz8893m_switch_data = { + .mii_bus = &bfin_mii_bus.dev, + .netdev = &bfin_mac_device.dev, + .port_names[0] = NULL, + .port_names[1] = "eth%d", + .port_names[2] = "eth%d", + .port_names[3] = "cpu", +}; + +static struct platform_device ksz8893m_switch_device = { + .name = "dsa", + .id = 0, + .num_resources = 0, + .dev.platform_data = &ksz8893m_switch_data, }; #endif @@ -147,6 +171,15 @@ static struct bfin5xx_spi_chip spi_adc_chip_info = { }; #endif +#if defined(CONFIG_NET_DSA_KSZ8893M) \ + || defined(CONFIG_NET_DSA_KSZ8893M_MODULE) +/* SPI SWITCH CHIP */ +static struct bfin5xx_spi_chip spi_switch_info = { + .enable_dma = 0, + .bits_per_word = 8, +}; +#endif + #if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE) static struct bfin5xx_spi_chip spi_mmc_chip_info = { .enable_dma = 1, @@ -226,6 +259,19 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { }, #endif +#if defined(CONFIG_NET_DSA_KSZ8893M) \ + || defined(CONFIG_NET_DSA_KSZ8893M_MODULE) + { + .modalias = "ksz8893m", + .max_speed_hz = 5000000, + .bus_num = 0, + .chip_select = 1, + .platform_data = NULL, + .controller_data = &spi_switch_info, + .mode = SPI_MODE_3, + }, +#endif + #if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE) { .modalias = "spi_mmc_dummy", @@ -473,7 +519,6 @@ static struct platform_device i2c_bfin_twi_device = { }; #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE) { @@ -487,7 +532,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }, #endif }; -#endif #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) static struct platform_device bfin_sport0_uart_device = { @@ -584,9 +628,14 @@ static struct platform_device *stamp_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif +#if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE) + &ksz8893m_switch_device, +#endif + #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) &bfin_spi0_device, &bfin_spi1_device, @@ -632,12 +681,8 @@ static struct platform_device *stamp_devices[] __initdata = { static int __init ezbrd_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); - -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info)); -#endif - platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info)); return 0; @@ -649,7 +694,7 @@ void native_machine_restart(char *cmd) { /* workaround reboot hang when booting from SPI */ if ((bfin_read_SYSCR() & 0x7) == 0x3) - bfin_gpio_reset_spi0_ssel1(); + bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS); } void bfin_get_ether_addr(char *addr) diff --git a/arch/blackfin/mach-bf518/include/mach/portmux.h b/arch/blackfin/mach-bf518/include/mach/portmux.h index ac16d54..f618b48 100644 --- a/arch/blackfin/mach-bf518/include/mach/portmux.h +++ b/arch/blackfin/mach-bf518/include/mach/portmux.h @@ -103,6 +103,8 @@ #define P_SPI1_SSEL4 (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(2)) #define P_SPI1_SSEL5 (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(2)) +#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2 + /* SPORT Port Mux */ #define P_SPORT0_DRPRI (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(0)) #define P_SPORT0_RSCLK (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(0)) diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c index a2c3578..856c097 100644 --- a/arch/blackfin/mach-bf527/boards/cm_bf527.c +++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c @@ -403,8 +403,13 @@ static struct platform_device isp1362_hcd_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -793,7 +798,6 @@ static struct platform_device i2c_bfin_twi_device = { }; #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE) { @@ -809,7 +813,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }, #endif }; -#endif #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) static struct platform_device bfin_sport0_uart_device = { @@ -920,6 +923,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif @@ -968,27 +972,23 @@ static struct platform_device *stamp_devices[] __initdata = { &bfin_gpios_device, }; -static int __init stamp_init(void) +static int __init cm_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); - -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info)); -#endif - platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info)); return 0; } -arch_initcall(stamp_init); +arch_initcall(cm_init); void native_machine_restart(char *cmd) { /* workaround reboot hang when booting from SPI */ if ((bfin_read_SYSCR() & 0x7) == 0x3) - bfin_gpio_reset_spi0_ssel1(); + bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS); } void bfin_get_ether_addr(char *addr) diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c index 0314bd3..83606fc 100644 --- a/arch/blackfin/mach-bf527/boards/ezbrd.c +++ b/arch/blackfin/mach-bf527/boards/ezbrd.c @@ -208,8 +208,13 @@ static struct platform_device rtc_device = { #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -590,7 +595,6 @@ static struct platform_device i2c_bfin_twi_device = { }; #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE) { @@ -604,7 +608,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }, #endif }; -#endif #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) static struct platform_device bfin_sport0_uart_device = { @@ -720,6 +723,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif @@ -764,27 +768,23 @@ static struct platform_device *stamp_devices[] __initdata = { &bfin_gpios_device, }; -static int __init stamp_init(void) +static int __init ezbrd_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); - -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info)); -#endif - platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info)); return 0; } -arch_initcall(stamp_init); +arch_initcall(ezbrd_init); void native_machine_restart(char *cmd) { /* workaround reboot hang when booting from SPI */ if ((bfin_read_SYSCR() & 0x7) == 0x3) - bfin_gpio_reset_spi0_ssel1(); + bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS); } void bfin_get_ether_addr(char *addr) diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index 9454fb7..d086411 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -425,8 +425,13 @@ static struct platform_device isp1362_hcd_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -830,7 +835,6 @@ static struct platform_device i2c_bfin_twi_device = { }; #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE) { @@ -844,7 +848,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }, #endif }; -#endif #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) static struct platform_device bfin_sport0_uart_device = { @@ -988,6 +991,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif @@ -1048,27 +1052,23 @@ static struct platform_device *stamp_devices[] __initdata = { &bfin_gpios_device, }; -static int __init stamp_init(void) +static int __init ezkit_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); - -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info)); -#endif - platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info)); return 0; } -arch_initcall(stamp_init); +arch_initcall(ezkit_init); void native_machine_restart(char *cmd) { /* workaround reboot hang when booting from SPI */ if ((bfin_read_SYSCR() & 0x7) == 0x3) - bfin_gpio_reset_spi0_ssel1(); + bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS); } void bfin_get_ether_addr(char *addr) diff --git a/arch/blackfin/mach-bf527/include/mach/portmux.h b/arch/blackfin/mach-bf527/include/mach/portmux.h index 7f6da2c..72b1652 100644 --- a/arch/blackfin/mach-bf527/include/mach/portmux.h +++ b/arch/blackfin/mach-bf527/include/mach/portmux.h @@ -73,6 +73,8 @@ #define P_HWAIT (P_DONTCARE) +#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL1 + #define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0)) #define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(2)) #define P_SPI0_SCK (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(2)) diff --git a/arch/blackfin/mach-bf533/boards/blackstamp.c b/arch/blackfin/mach-bf533/boards/blackstamp.c index 6ee607c..015c18f 100644 --- a/arch/blackfin/mach-bf533/boards/blackstamp.c +++ b/arch/blackfin/mach-bf533/boards/blackstamp.c @@ -309,10 +309,8 @@ static struct platform_device i2c_gpio_device = { }; #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }; -#endif static const unsigned int cclk_vlev_datasheet[] = { @@ -390,10 +388,8 @@ static int __init blackstamp_init(void) printk(KERN_INFO "%s(): registering device resources\n", __func__); -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info)); -#endif ret = platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); if (ret < 0) diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c index 07f9ad1..db96f33 100644 --- a/arch/blackfin/mach-bf533/boards/stamp.c +++ b/arch/blackfin/mach-bf533/boards/stamp.c @@ -441,7 +441,6 @@ static struct platform_device i2c_gpio_device = { }; #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE) { @@ -461,7 +460,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }, #endif }; -#endif static const unsigned int cclk_vlev_datasheet[] = { @@ -550,10 +548,8 @@ static int __init stamp_init(void) printk(KERN_INFO "%s(): registering device resources\n", __func__); -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info)); -#endif ret = platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); if (ret < 0) diff --git a/arch/blackfin/mach-bf533/include/mach/portmux.h b/arch/blackfin/mach-bf533/include/mach/portmux.h index 685a265..2f59ce0 100644 --- a/arch/blackfin/mach-bf533/include/mach/portmux.h +++ b/arch/blackfin/mach-bf533/include/mach/portmux.h @@ -54,14 +54,11 @@ #define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(GPIO_PF2)) #define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PF1)) #define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PF0)) +#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2 #define P_TMR2 (P_DONTCARE) #define P_TMR1 (P_DONTCARE) #define P_TMR0 (P_DONTCARE) #define P_TMRCLK (P_DEFINED | P_IDENT(GPIO_PF1)) - - - - #endif /* _MACH_PORTMUX_H_ */ diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c index 6ac8e4d..9cd8fb2 100644 --- a/arch/blackfin/mach-bf537/boards/cm_bf537.c +++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c @@ -479,8 +479,13 @@ static struct platform_device bfin_sport1_uart_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -591,6 +596,7 @@ static struct platform_device *cm_bf537_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c index dd6e6bf..da710fd 100644 --- a/arch/blackfin/mach-bf537/boards/generic_board.c +++ b/arch/blackfin/mach-bf537/boards/generic_board.c @@ -262,8 +262,13 @@ static struct platform_device isp1362_hcd_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -662,6 +667,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif @@ -708,7 +714,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif }; -static int __init stamp_init(void) +static int __init generic_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); @@ -720,13 +726,13 @@ static int __init stamp_init(void) return 0; } -arch_initcall(stamp_init); +arch_initcall(generic_init); void native_machine_restart(char *cmd) { /* workaround reboot hang when booting from SPI */ if ((bfin_read_SYSCR() & 0x7) == 0x3) - bfin_gpio_reset_spi0_ssel1(); + bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS); } #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) diff --git a/arch/blackfin/mach-bf537/boards/minotaur.c b/arch/blackfin/mach-bf537/boards/minotaur.c index bb79534..db7d3a3 100644 --- a/arch/blackfin/mach-bf537/boards/minotaur.c +++ b/arch/blackfin/mach-bf537/boards/minotaur.c @@ -61,8 +61,13 @@ static struct platform_device rtc_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -324,6 +329,7 @@ static struct platform_device *minotaur_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif @@ -377,5 +383,5 @@ void native_machine_restart(char *cmd) { /* workaround reboot hang when booting from SPI */ if ((bfin_read_SYSCR() & 0x7) == 0x3) - bfin_gpio_reset_spi0_ssel1(); + bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS); } diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c index 89de94f..590eb3a 100644 --- a/arch/blackfin/mach-bf537/boards/pnav10.c +++ b/arch/blackfin/mach-bf537/boards/pnav10.c @@ -198,8 +198,13 @@ static struct platform_device isp1362_hcd_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -529,6 +534,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif @@ -558,7 +564,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif }; -static int __init stamp_init(void) +static int __init pnav_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); @@ -569,7 +575,7 @@ static int __init stamp_init(void) return 0; } -arch_initcall(stamp_init); +arch_initcall(pnav_init); void bfin_get_ether_addr(char *addr) { diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index d812e25..cd04c5e 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -321,8 +321,13 @@ static struct platform_device isp1362_hcd_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -1068,7 +1073,6 @@ static struct adp5588_kpad_platform_data adp5588_kpad_data = { }; #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE) { @@ -1102,7 +1106,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }, #endif }; -#endif #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) static struct platform_device bfin_sport0_uart_device = { @@ -1217,6 +1220,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif @@ -1284,12 +1288,8 @@ static struct platform_device *stamp_devices[] __initdata = { static int __init stamp_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); - -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info)); -#endif - bfin_plat_nand_init(); platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info)); @@ -1307,7 +1307,7 @@ void native_machine_restart(char *cmd) { /* workaround reboot hang when booting from SPI */ if ((bfin_read_SYSCR() & 0x7) == 0x3) - bfin_gpio_reset_spi0_ssel1(); + bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS); } /* diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c index 2f4b066..3f4f203 100644 --- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c +++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c @@ -481,8 +481,13 @@ static struct platform_device bfin_sport1_uart_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -593,6 +598,7 @@ static struct platform_device *cm_bf537_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif @@ -615,7 +621,7 @@ static struct platform_device *cm_bf537_devices[] __initdata = { &bfin_gpios_device, }; -static int __init cm_bf537_init(void) +static int __init tcm_bf537_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); platform_add_devices(cm_bf537_devices, ARRAY_SIZE(cm_bf537_devices)); @@ -629,7 +635,7 @@ static int __init cm_bf537_init(void) return 0; } -arch_initcall(cm_bf537_init); +arch_initcall(tcm_bf537_init); void bfin_get_ether_addr(char *addr) { diff --git a/arch/blackfin/mach-bf537/include/mach/portmux.h b/arch/blackfin/mach-bf537/include/mach/portmux.h index 78fee6e..87285e7 100644 --- a/arch/blackfin/mach-bf537/include/mach/portmux.h +++ b/arch/blackfin/mach-bf537/include/mach/portmux.h @@ -31,6 +31,7 @@ #define P_PPI0_FS1 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1)) #define P_TACLK0 (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1)) #define P_TMRCLK (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1)) +#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL1 #define P_PPI0_D0 (P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(0)) #define P_PPI0_D1 (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0)) diff --git a/arch/blackfin/mach-bf538/include/mach/portmux.h b/arch/blackfin/mach-bf538/include/mach/portmux.h index 1e031b5..c8db264 100644 --- a/arch/blackfin/mach-bf538/include/mach/portmux.h +++ b/arch/blackfin/mach-bf538/include/mach/portmux.h @@ -102,5 +102,6 @@ #define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(GPIO_PF2)) #define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PF1)) #define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PF0)) +#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2 #endif /* _MACH_PORTMUX_H_ */ diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index 309c160..096e661 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -781,7 +781,6 @@ static struct platform_device i2c_bfin_twi1_device = { #endif #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info0[] = { }; @@ -800,7 +799,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info1[] = { #endif }; #endif -#endif #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) #include <linux/gpio_keys.h> @@ -956,14 +954,12 @@ static int __init ezkit_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info0, ARRAY_SIZE(bfin_i2c_board_info0)); #if !defined(CONFIG_BF542) /* The BF542 only has 1 TWI */ i2c_register_board_info(1, bfin_i2c_board_info1, ARRAY_SIZE(bfin_i2c_board_info1)); #endif -#endif platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices)); diff --git a/arch/blackfin/mach-bf548/include/mach/anomaly.h b/arch/blackfin/mach-bf548/include/mach/anomaly.h index 3b54309..23d03c5 100644 --- a/arch/blackfin/mach-bf548/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf548/include/mach/anomaly.h @@ -175,6 +175,7 @@ #define ANOMALY_05000311 (0) #define ANOMALY_05000323 (0) #define ANOMALY_05000363 (0) +#define ANOMALY_05000380 (0) #define ANOMALY_05000412 (0) #define ANOMALY_05000432 (0) #define ANOMALY_05000435 (0) diff --git a/arch/blackfin/mach-bf548/include/mach/bf548.h b/arch/blackfin/mach-bf548/include/mach/bf548.h index f0e5699..cd31f72 100644 --- a/arch/blackfin/mach-bf548/include/mach/bf548.h +++ b/arch/blackfin/mach-bf548/include/mach/bf548.h @@ -104,6 +104,18 @@ #define AMGCTLVAL (V_AMBEN | V_AMCKEN) +#if defined(CONFIG_BF542M) +# define CONFIG_BF542 +#elif defined(CONFIG_BF544M) +# define CONFIG_BF544 +#elif defined(CONFIG_BF547M) +# define CONFIG_BF547 +#elif defined(CONFIG_BF548M) +# define CONFIG_BF548 +#elif defined(CONFIG_BF549M) +# define CONFIG_BF549 +#endif + #if defined(CONFIG_BF542) # define CPU "BF542" # define CPUID 0x27de diff --git a/arch/blackfin/mach-bf548/include/mach/gpio.h b/arch/blackfin/mach-bf548/include/mach/gpio.h index bba82dc..3a20517 100644 --- a/arch/blackfin/mach-bf548/include/mach/gpio.h +++ b/arch/blackfin/mach-bf548/include/mach/gpio.h @@ -195,17 +195,17 @@ struct gpio_port_t { unsigned short port_fer; unsigned short dummy1; - unsigned short port_data; + unsigned short data; unsigned short dummy2; - unsigned short port_set; + unsigned short data_set; unsigned short dummy3; - unsigned short port_clear; + unsigned short data_clear; unsigned short dummy4; - unsigned short port_dir_set; + unsigned short dir_set; unsigned short dummy5; - unsigned short port_dir_clear; + unsigned short dir_clear; unsigned short dummy6; - unsigned short port_inen; + unsigned short inen; unsigned short dummy7; unsigned int port_mux; }; diff --git a/arch/blackfin/mach-bf548/include/mach/portmux.h b/arch/blackfin/mach-bf548/include/mach/portmux.h index 8177a56..ffb1d0a 100644 --- a/arch/blackfin/mach-bf548/include/mach/portmux.h +++ b/arch/blackfin/mach-bf548/include/mach/portmux.h @@ -125,6 +125,7 @@ #define P_KEY_COL2 (P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(3)) #define P_KEY_COL3 (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(3)) +#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL1 #define P_SPI0_SCK (P_DEFINED | P_IDENT(GPIO_PE0) | P_FUNCT(0)) #define P_SPI0_MISO (P_DEFINED | P_IDENT(GPIO_PE1) | P_FUNCT(0)) #define P_SPI0_MOSI (P_DEFINED | P_IDENT(GPIO_PE2) | P_FUNCT(0)) diff --git a/arch/blackfin/mach-bf561/include/mach/defBF561.h b/arch/blackfin/mach-bf561/include/mach/defBF561.h index d7c5097..cf92229 100644 --- a/arch/blackfin/mach-bf561/include/mach/defBF561.h +++ b/arch/blackfin/mach-bf561/include/mach/defBF561.h @@ -1106,6 +1106,8 @@ #define DLEN_8 0x0 /* PPI Data Length mask for DLEN=8 */ #define DLEN(x) (((x-9) & 0x07) << 11) /* PPI Data Length (only works for x=10-->x=16) */ #define POL 0x0000C000 /* PPI Signal Polarities */ +#define POLC 0x4000 /* PPI Clock Polarity */ +#define POLS 0x8000 /* PPI Frame Sync Polarity */ /* PPI_STATUS Masks */ #define FLD 0x00000400 /* Field Indicator */ diff --git a/arch/blackfin/mach-bf561/include/mach/portmux.h b/arch/blackfin/mach-bf561/include/mach/portmux.h index a6ee820..2e5ad63 100644 --- a/arch/blackfin/mach-bf561/include/mach/portmux.h +++ b/arch/blackfin/mach-bf561/include/mach/portmux.h @@ -85,5 +85,6 @@ #define P_SPI0_MOSI (P_DONTCARE) #define P_SPI0_MISO (P_DONTCARE) #define P_SPI0_SCK (P_DONTCARE) +#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2 #endif /* _MACH_PORTMUX_H_ */ diff --git a/arch/blackfin/mach-common/clocks-init.c b/arch/blackfin/mach-common/clocks-init.c index 5d182ab..9dddb6f 100644 --- a/arch/blackfin/mach-common/clocks-init.c +++ b/arch/blackfin/mach-common/clocks-init.c @@ -14,6 +14,7 @@ #include <asm/clocks.h> #include <asm/mem_init.h> +#define SDGCTL_WIDTH (1 << 31) /* SDRAM external data path width */ #define PLL_CTL_VAL \ (((CONFIG_VCO_MULT & 63) << 9) | CLKIN_HALF | \ (PLL_BYPASS << 8) | (ANOMALY_05000265 ? 0x8000 : 0)) @@ -76,7 +77,7 @@ void init_clocks(void) bfin_write_PLL_DIV(CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV); #ifdef EBIU_SDGCTL bfin_write_EBIU_SDRRC(mem_SDRRC); - bfin_write_EBIU_SDGCTL(mem_SDGCTL); + bfin_write_EBIU_SDGCTL((bfin_read_EBIU_SDGCTL() & SDGCTL_WIDTH) | mem_SDGCTL); #else bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() & ~(SRREQ)); do_sync(); diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index fae7746..88de053 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -151,13 +151,6 @@ ENTRY(_ex_syscall) jump.s _bfin_return_from_exception; ENDPROC(_ex_syscall) -ENTRY(_ex_soft_bp) - r7 = retx; - r7 += -2; - retx = r7; - jump.s _ex_trap_c; -ENDPROC(_ex_soft_bp) - ENTRY(_ex_single_step) /* If we just returned from an interrupt, the single step event is for the RTI instruction. */ @@ -1087,7 +1080,7 @@ ENTRY(_ex_table) * EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined */ .long _ex_syscall /* 0x00 - User Defined - Linux Syscall */ - .long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */ + .long _ex_trap_c /* 0x01 - User Defined - Software breakpoint */ #ifdef CONFIG_KGDB .long _ex_trap_c /* 0x02 - User Defined - KGDB initial connection and break signal trap */ diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index e1e42c0..698d4c0 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S @@ -17,6 +17,19 @@ __INIT +ENTRY(__init_clear_bss) + r2 = r2 - r1; + cc = r2 == 0; + if cc jump .L_bss_done; + r2 >>= 2; + p1 = r1; + p2 = r2; + lsetup (1f, 1f) lc0 = p2; +1: [p1++] = r0; +.L_bss_done: + rts; +ENDPROC(__init_clear_bss) + #define INITIAL_STACK (L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12) ENTRY(__start) @@ -144,6 +157,35 @@ ENTRY(__start) call _init_early_exception_vectors; #endif + r0 = 0 (x); + /* Zero out all of the fun bss regions */ +#if L1_DATA_A_LENGTH > 0 + r1.l = __sbss_l1; + r1.h = __sbss_l1; + r2.l = __ebss_l1; + r2.h = __ebss_l1; + call __init_clear_bss +#endif +#if L1_DATA_B_LENGTH > 0 + r1.l = __sbss_b_l1; + r1.h = __sbss_b_l1; + r2.l = __ebss_b_l1; + r2.h = __ebss_b_l1; + call __init_clear_bss +#endif +#if L2_LENGTH > 0 + r1.l = __sbss_l2; + r1.h = __sbss_l2; + r2.l = __ebss_l2; + r2.h = __ebss_l2; + call __init_clear_bss +#endif + r1.l = ___bss_start; + r1.h = ___bss_start; + r2.l = ___bss_stop; + r2.h = ___bss_stop; + call __init_clear_bss + /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */ call _bfin_relocate_l1_mem; #ifdef CONFIG_BFIN_KERNEL_CLOCK @@ -185,19 +227,6 @@ ENDPROC(__start) # define WDOG_CTL WDOGA_CTL #endif -ENTRY(__init_clear_bss) - r2 = r2 - r1; - cc = r2 == 0; - if cc jump .L_bss_done; - r2 >>= 2; - p1 = r1; - p2 = r2; - lsetup (1f, 1f) lc0 = p2; -1: [p1++] = r0; -.L_bss_done: - rts; -ENDPROC(__init_clear_bss) - ENTRY(_real_start) /* Enable nested interrupts */ [--sp] = reti; @@ -209,35 +238,6 @@ ENTRY(_real_start) w[p0] = r0; ssync; - r0 = 0 (x); - /* Zero out all of the fun bss regions */ -#if L1_DATA_A_LENGTH > 0 - r1.l = __sbss_l1; - r1.h = __sbss_l1; - r2.l = __ebss_l1; - r2.h = __ebss_l1; - call __init_clear_bss -#endif -#if L1_DATA_B_LENGTH > 0 - r1.l = __sbss_b_l1; - r1.h = __sbss_b_l1; - r2.l = __ebss_b_l1; - r2.h = __ebss_b_l1; - call __init_clear_bss -#endif -#if L2_LENGTH > 0 - r1.l = __sbss_l2; - r1.h = __sbss_l2; - r2.l = __ebss_l2; - r2.h = __ebss_l2; - call __init_clear_bss -#endif - r1.l = ___bss_start; - r1.h = ___bss_start; - r2.l = ___bss_stop; - r2.h = ___bss_stop; - call __init_clear_bss - /* Pass the u-boot arguments to the global value command line */ R0 = R7; call _cmdline_init; diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index 473df0f..43c4eb9 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -195,7 +195,7 @@ ENDPROC(_evt_ivhw) /* Interrupt routine for evt2 (NMI). * We don't actually use this, so just return. * For inner circle type details, please see: - * http://docs.blackfin.uclinux.org/doku.php?id=linux:nmi + * http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:nmi */ ENTRY(_evt_nmi) .weak _evt_nmi diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 1bba603..2024945 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -1101,10 +1101,9 @@ int __init init_arch_irq(void) IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; -#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \ - || defined(BF538_FAMILY) || defined(CONFIG_BF51x) +#ifdef SIC_IWR0 bfin_write_SIC_IWR0(IWR_DISABLE_ALL); -#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x) +# ifdef SIC_IWR1 /* BF52x/BF51x system reset does not properly reset SIC_IWR1 which * will screw up the bootrom as it relies on MDMA0/1 waking it * up from IDLE instructions. See this report for more info: @@ -1114,10 +1113,8 @@ int __init init_arch_irq(void) bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11)); else bfin_write_SIC_IWR1(IWR_DISABLE_ALL); -#else - bfin_write_SIC_IWR1(IWR_DISABLE_ALL); -#endif -# ifdef CONFIG_BF54x +# endif +# ifdef SIC_IWR2 bfin_write_SIC_IWR2(IWR_DISABLE_ALL); # endif #else diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index d3d70fd..f48a6ae 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c @@ -82,10 +82,9 @@ void bfin_pm_suspend_standby_enter(void) bfin_pm_standby_restore(); -#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) || \ - defined(CONFIG_BF538) || defined(CONFIG_BF539) || defined(CONFIG_BF51x) +#ifdef SIC_IWR0 bfin_write_SIC_IWR0(IWR_DISABLE_ALL); -#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x) +# ifdef SIC_IWR1 /* BF52x system reset does not properly reset SIC_IWR1 which * will screw up the bootrom as it relies on MDMA0/1 waking it * up from IDLE instructions. See this report for more info: @@ -95,10 +94,8 @@ void bfin_pm_suspend_standby_enter(void) bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11)); else bfin_write_SIC_IWR1(IWR_DISABLE_ALL); -#else - bfin_write_SIC_IWR1(IWR_DISABLE_ALL); -#endif -# ifdef CONFIG_BF54x +# endif +# ifdef SIC_IWR2 bfin_write_SIC_IWR2(IWR_DISABLE_ALL); # endif #else diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c index c5a2140..d0223ab 100644 --- a/arch/ia64/sn/kernel/io_acpi_init.c +++ b/arch/ia64/sn/kernel/io_acpi_init.c @@ -443,7 +443,7 @@ sn_acpi_slot_fixup(struct pci_dev *dev) size = pci_resource_len(dev, PCI_ROM_RESOURCE); addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE], size); - image_size = pci_get_rom_size(addr, size); + image_size = pci_get_rom_size(dev, addr, size); dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr; dev->resource[PCI_ROM_RESOURCE].end = (unsigned long) addr + image_size - 1; diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 4e1801b..e2eb2da 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -269,7 +269,7 @@ sn_io_slot_fixup(struct pci_dev *dev) rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE), size + 1); - image_size = pci_get_rom_size(rom, size + 1); + image_size = pci_get_rom_size(dev, rom, size + 1); dev->resource[PCI_ROM_RESOURCE].end = dev->resource[PCI_ROM_RESOURCE].start + image_size - 1; diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 52c80c2..600eef3 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -351,7 +351,7 @@ config SGI_IP27 select ARC64 select BOOT_ELF64 select DEFAULT_SGI_PARTITION - select DMA_IP27 + select DMA_COHERENT select SYS_HAS_EARLY_PRINTK select HW_HAS_PCI select NR_CPUS_DEFAULT_64 @@ -761,9 +761,6 @@ config CFE config DMA_COHERENT bool -config DMA_IP27 - bool - config DMA_NONCOHERENT bool select DMA_NEED_PCI_MAP_STATE @@ -1368,7 +1365,7 @@ config CPU_SUPPORTS_64BIT_KERNEL # config HARDWARE_WATCHPOINTS bool - default y if CPU_MIPS32 || CPU_MIPS64 + default y if CPU_MIPSR1 || CPU_MIPSR2 menu "Kernel type" diff --git a/arch/mips/alchemy/common/time.c b/arch/mips/alchemy/common/time.c index 3288014..6fd441d 100644 --- a/arch/mips/alchemy/common/time.c +++ b/arch/mips/alchemy/common/time.c @@ -89,7 +89,7 @@ static struct clock_event_device au1x_rtcmatch2_clockdev = { .irq = AU1000_RTC_MATCH2_INT, .set_next_event = au1x_rtcmatch2_set_next_event, .set_mode = au1x_rtcmatch2_set_mode, - .cpumask = CPU_MASK_ALL, + .cpumask = CPU_MASK_ALL_PTR, }; static struct irqaction au1x_rtcmatch2_irqaction = { diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index e085fed..5f4e49b 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -15,13 +15,11 @@ #include <linux/serial.h> #include <linux/types.h> #include <linux/string.h> /* for memset */ -#include <linux/serial.h> #include <linux/tty.h> #include <linux/time.h> #include <linux/platform_device.h> #include <linux/serial_core.h> #include <linux/serial_8250.h> -#include <linux/string.h> #include <asm/processor.h> #include <asm/reboot.h> diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig index 34ea319..f2baea3 100644 --- a/arch/mips/configs/ip27_defconfig +++ b/arch/mips/configs/ip27_defconfig @@ -53,7 +53,7 @@ CONFIG_GENERIC_TIME=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_ARC=y -CONFIG_DMA_IP27=y +CONFIG_DMA_COHERENT=y CONFIG_EARLY_PRINTK=y CONFIG_SYS_HAS_EARLY_PRINTK=y # CONFIG_NO_IOPORT is not set diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h index c996c3b..1b332e1 100644 --- a/arch/mips/include/asm/atomic.h +++ b/arch/mips/include/asm/atomic.h @@ -50,7 +50,7 @@ static __inline__ void atomic_add(int i, atomic_t * v) { if (cpu_has_llsc && R10000_LLSC_WAR) { - unsigned long temp; + int temp; __asm__ __volatile__( " .set mips3 \n" @@ -62,7 +62,7 @@ static __inline__ void atomic_add(int i, atomic_t * v) : "=&r" (temp), "=m" (v->counter) : "Ir" (i), "m" (v->counter)); } else if (cpu_has_llsc) { - unsigned long temp; + int temp; __asm__ __volatile__( " .set mips3 \n" @@ -95,7 +95,7 @@ static __inline__ void atomic_add(int i, atomic_t * v) static __inline__ void atomic_sub(int i, atomic_t * v) { if (cpu_has_llsc && R10000_LLSC_WAR) { - unsigned long temp; + int temp; __asm__ __volatile__( " .set mips3 \n" @@ -107,7 +107,7 @@ static __inline__ void atomic_sub(int i, atomic_t * v) : "=&r" (temp), "=m" (v->counter) : "Ir" (i), "m" (v->counter)); } else if (cpu_has_llsc) { - unsigned long temp; + int temp; __asm__ __volatile__( " .set mips3 \n" @@ -135,12 +135,12 @@ static __inline__ void atomic_sub(int i, atomic_t * v) */ static __inline__ int atomic_add_return(int i, atomic_t * v) { - unsigned long result; + int result; smp_llsc_mb(); if (cpu_has_llsc && R10000_LLSC_WAR) { - unsigned long temp; + int temp; __asm__ __volatile__( " .set mips3 \n" @@ -154,7 +154,7 @@ static __inline__ int atomic_add_return(int i, atomic_t * v) : "Ir" (i), "m" (v->counter) : "memory"); } else if (cpu_has_llsc) { - unsigned long temp; + int temp; __asm__ __volatile__( " .set mips3 \n" @@ -187,12 +187,12 @@ static __inline__ int atomic_add_return(int i, atomic_t * v) static __inline__ int atomic_sub_return(int i, atomic_t * v) { - unsigned long result; + int result; smp_llsc_mb(); if (cpu_has_llsc && R10000_LLSC_WAR) { - unsigned long temp; + int temp; __asm__ __volatile__( " .set mips3 \n" @@ -206,7 +206,7 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v) : "Ir" (i), "m" (v->counter) : "memory"); } else if (cpu_has_llsc) { - unsigned long temp; + int temp; __asm__ __volatile__( " .set mips3 \n" @@ -247,12 +247,12 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v) */ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) { - unsigned long result; + int result; smp_llsc_mb(); if (cpu_has_llsc && R10000_LLSC_WAR) { - unsigned long temp; + int temp; __asm__ __volatile__( " .set mips3 \n" @@ -270,7 +270,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) : "Ir" (i), "m" (v->counter) : "memory"); } else if (cpu_has_llsc) { - unsigned long temp; + int temp; __asm__ __volatile__( " .set mips3 \n" @@ -429,7 +429,7 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u) static __inline__ void atomic64_add(long i, atomic64_t * v) { if (cpu_has_llsc && R10000_LLSC_WAR) { - unsigned long temp; + long temp; __asm__ __volatile__( " .set mips3 \n" @@ -441,7 +441,7 @@ static __inline__ void atomic64_add(long i, atomic64_t * v) : "=&r" (temp), "=m" (v->counter) : "Ir" (i), "m" (v->counter)); } else if (cpu_has_llsc) { - unsigned long temp; + long temp; __asm__ __volatile__( " .set mips3 \n" @@ -474,7 +474,7 @@ static __inline__ void atomic64_add(long i, atomic64_t * v) static __inline__ void atomic64_sub(long i, atomic64_t * v) { if (cpu_has_llsc && R10000_LLSC_WAR) { - unsigned long temp; + long temp; __asm__ __volatile__( " .set mips3 \n" @@ -486,7 +486,7 @@ static __inline__ void atomic64_sub(long i, atomic64_t * v) : "=&r" (temp), "=m" (v->counter) : "Ir" (i), "m" (v->counter)); } else if (cpu_has_llsc) { - unsigned long temp; + long temp; __asm__ __volatile__( " .set mips3 \n" @@ -514,12 +514,12 @@ static __inline__ void atomic64_sub(long i, atomic64_t * v) */ static __inline__ long atomic64_add_return(long i, atomic64_t * v) { - unsigned long result; + long result; smp_llsc_mb(); if (cpu_has_llsc && R10000_LLSC_WAR) { - unsigned long temp; + long temp; __asm__ __volatile__( " .set mips3 \n" @@ -533,7 +533,7 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v) : "Ir" (i), "m" (v->counter) : "memory"); } else if (cpu_has_llsc) { - unsigned long temp; + long temp; __asm__ __volatile__( " .set mips3 \n" @@ -566,12 +566,12 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v) static __inline__ long atomic64_sub_return(long i, atomic64_t * v) { - unsigned long result; + long result; smp_llsc_mb(); if (cpu_has_llsc && R10000_LLSC_WAR) { - unsigned long temp; + long temp; __asm__ __volatile__( " .set mips3 \n" @@ -585,7 +585,7 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v) : "Ir" (i), "m" (v->counter) : "memory"); } else if (cpu_has_llsc) { - unsigned long temp; + long temp; __asm__ __volatile__( " .set mips3 \n" @@ -626,12 +626,12 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v) */ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) { - unsigned long result; + long result; smp_llsc_mb(); if (cpu_has_llsc && R10000_LLSC_WAR) { - unsigned long temp; + long temp; __asm__ __volatile__( " .set mips3 \n" @@ -649,7 +649,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) : "Ir" (i), "m" (v->counter) : "memory"); } else if (cpu_has_llsc) { - unsigned long temp; + long temp; __asm__ __volatile__( " .set mips3 \n" diff --git a/arch/mips/include/asm/mach-rc32434/gpio.h b/arch/mips/include/asm/mach-rc32434/gpio.h index b5cf645..3cb50d1 100644 --- a/arch/mips/include/asm/mach-rc32434/gpio.h +++ b/arch/mips/include/asm/mach-rc32434/gpio.h @@ -80,11 +80,8 @@ struct rb532_gpio_reg { /* Compact Flash GPIO pin */ #define CF_GPIO_NUM 13 -extern void set_434_reg(unsigned reg_offs, unsigned bit, unsigned len, unsigned val); -extern unsigned get_434_reg(unsigned reg_offs); -extern void set_latch_u5(unsigned char or_mask, unsigned char nand_mask); -extern unsigned char get_latch_u5(void); extern void rb532_gpio_set_ilevel(int bit, unsigned gpio); extern void rb532_gpio_set_istat(int bit, unsigned gpio); +extern void rb532_gpio_set_func(unsigned gpio); #endif /* _RC32434_GPIO_H_ */ diff --git a/arch/mips/include/asm/mach-rc32434/irq.h b/arch/mips/include/asm/mach-rc32434/irq.h index 56738d8..023a5b1 100644 --- a/arch/mips/include/asm/mach-rc32434/irq.h +++ b/arch/mips/include/asm/mach-rc32434/irq.h @@ -30,4 +30,7 @@ #define ETH0_RX_OVR_IRQ (GROUP3_IRQ_BASE + 9) #define ETH0_TX_UND_IRQ (GROUP3_IRQ_BASE + 10) +#define GPIO_MAPPED_IRQ_BASE GROUP4_IRQ_BASE +#define GPIO_MAPPED_IRQ_GROUP 4 + #endif /* __ASM_RC32434_IRQ_H */ diff --git a/arch/mips/include/asm/mach-rc32434/rb.h b/arch/mips/include/asm/mach-rc32434/rb.h index f25a849..6dc5f8d 100644 --- a/arch/mips/include/asm/mach-rc32434/rb.h +++ b/arch/mips/include/asm/mach-rc32434/rb.h @@ -83,4 +83,7 @@ struct mpmc_device { void __iomem *base; }; +extern void set_latch_u5(unsigned char or_mask, unsigned char nand_mask); +extern unsigned char get_latch_u5(void); + #endif /* __ASM_RC32434_RB_H */ diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h index 1f30d16..ce47118 100644 --- a/arch/mips/include/asm/ptrace.h +++ b/arch/mips/include/asm/ptrace.h @@ -105,7 +105,7 @@ struct pt_watch_regs { enum pt_watch_style style; union { struct mips32_watch_regs mips32; - struct mips32_watch_regs mips64; + struct mips64_watch_regs mips64; }; }; diff --git a/arch/mips/include/asm/termios.h b/arch/mips/include/asm/termios.h index a275661..8f77f77 100644 --- a/arch/mips/include/asm/termios.h +++ b/arch/mips/include/asm/termios.h @@ -9,6 +9,7 @@ #ifndef _ASM_TERMIOS_H #define _ASM_TERMIOS_H +#include <linux/errno.h> #include <asm/termbits.h> #include <asm/ioctls.h> @@ -94,38 +95,81 @@ struct termio { /* * Translate a "termio" structure into a "termios". Ugh. */ -#define user_termio_to_kernel_termios(termios, termio) \ -({ \ - unsigned short tmp; \ - get_user(tmp, &(termio)->c_iflag); \ - (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \ - get_user(tmp, &(termio)->c_oflag); \ - (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \ - get_user(tmp, &(termio)->c_cflag); \ - (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \ - get_user(tmp, &(termio)->c_lflag); \ - (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \ - get_user((termios)->c_line, &(termio)->c_line); \ - copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \ -}) +static inline int user_termio_to_kernel_termios(struct ktermios *termios, + struct termio __user *termio) +{ + unsigned short iflag, oflag, cflag, lflag; + unsigned int err; + + if (!access_ok(VERIFY_READ, termio, sizeof(struct termio))) + return -EFAULT; + + err = __get_user(iflag, &termio->c_iflag); + termios->c_iflag = (termios->c_iflag & 0xffff0000) | iflag; + err |=__get_user(oflag, &termio->c_oflag); + termios->c_oflag = (termios->c_oflag & 0xffff0000) | oflag; + err |=__get_user(cflag, &termio->c_cflag); + termios->c_cflag = (termios->c_cflag & 0xffff0000) | cflag; + err |=__get_user(lflag, &termio->c_lflag); + termios->c_lflag = (termios->c_lflag & 0xffff0000) | lflag; + err |=__get_user(termios->c_line, &termio->c_line); + if (err) + return -EFAULT; + + if (__copy_from_user(termios->c_cc, termio->c_cc, NCC)) + return -EFAULT; + + return 0; +} /* * Translate a "termios" structure into a "termio". Ugh. */ -#define kernel_termios_to_user_termio(termio, termios) \ -({ \ - put_user((termios)->c_iflag, &(termio)->c_iflag); \ - put_user((termios)->c_oflag, &(termio)->c_oflag); \ - put_user((termios)->c_cflag, &(termio)->c_cflag); \ - put_user((termios)->c_lflag, &(termio)->c_lflag); \ - put_user((termios)->c_line, &(termio)->c_line); \ - copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ -}) - -#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2)) -#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2)) -#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios)) -#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios)) +static inline int kernel_termios_to_user_termio(struct termio __user *termio, + struct ktermios *termios) +{ + int err; + + if (!access_ok(VERIFY_WRITE, termio, sizeof(struct termio))) + return -EFAULT; + + err = __put_user(termios->c_iflag, &termio->c_iflag); + err |= __put_user(termios->c_oflag, &termio->c_oflag); + err |= __put_user(termios->c_cflag, &termio->c_cflag); + err |= __put_user(termios->c_lflag, &termio->c_lflag); + err |= __put_user(termios->c_line, &termio->c_line); + if (err) + return -EFAULT; + + if (__copy_to_user(termio->c_cc, termios->c_cc, NCC)) + return -EFAULT; + + return 0; +} + +static inline int user_termios_to_kernel_termios(struct ktermios __user *k, + struct termios2 *u) +{ + return copy_from_user(k, u, sizeof(struct termios2)) ? -EFAULT : 0; +} + +static inline int kernel_termios_to_user_termios(struct termios2 __user *u, + struct ktermios *k) +{ + return copy_to_user(u, k, sizeof(struct termios2)) ? -EFAULT : 0; +} + +static inline int user_termios_to_kernel_termios_1(struct ktermios *k, + struct termios __user *u) +{ + return copy_from_user(k, u, sizeof(struct termios)) ? -EFAULT : 0; +} + +static inline int kernel_termios_to_user_termios_1(struct termios __user *u, + struct ktermios *k) +{ + return copy_to_user(u, k, sizeof(struct termios)) ? -EFAULT : 0; +} #endif /* defined(__KERNEL__) */ diff --git a/arch/mips/include/asm/txx9/tx4939.h b/arch/mips/include/asm/txx9/tx4939.h index 88badb4..964ef7e 100644 --- a/arch/mips/include/asm/txx9/tx4939.h +++ b/arch/mips/include/asm/txx9/tx4939.h @@ -541,5 +541,6 @@ void tx4939_irq_init(void); int tx4939_irq(void); void tx4939_mtd_init(int ch); void tx4939_ata_init(void); +void tx4939_rtc_init(void); #endif /* __ASM_TXX9_TX4939_H */ diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index fb6f731..8882e57 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -458,7 +458,11 @@ NESTED(nmi_handler, PT_SIZE, sp) BUILD_HANDLER fpe fpe fpe silent /* #15 */ BUILD_HANDLER mdmx mdmx sti silent /* #22 */ #ifdef CONFIG_HARDWARE_WATCHPOINTS - BUILD_HANDLER watch watch sti silent /* #23 */ + /* + * For watch, interrupts will be enabled after the watch + * registers are read. + */ + BUILD_HANDLER watch watch cli silent /* #23 */ #else BUILD_HANDLER watch watch sti verbose /* #23 */ #endif diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c index 5e77a3a..4246131 100644 --- a/arch/mips/kernel/mips-mt-fpaff.c +++ b/arch/mips/kernel/mips-mt-fpaff.c @@ -79,7 +79,8 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len, euid = current_euid(); retval = -EPERM; - if (euid != p->euid && euid != p->uid && !capable(CAP_SYS_NICE)) { + if (euid != p->cred->euid && euid != p->cred->uid && + !capable(CAP_SYS_NICE)) { read_unlock(&tasklist_lock); goto out_unlock; } diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index f6083c6..b2d7041 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -944,6 +944,9 @@ asmlinkage void do_mdmx(struct pt_regs *regs) force_sig(SIGILL, current); } +/* + * Called with interrupts disabled. + */ asmlinkage void do_watch(struct pt_regs *regs) { u32 cause; @@ -963,9 +966,12 @@ asmlinkage void do_watch(struct pt_regs *regs) */ if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) { mips_read_watch_registers(); + local_irq_enable(); force_sig(SIGTRAP, current); - } else + } else { mips_clear_watch_registers(); + local_irq_enable(); + } } asmlinkage void do_mcheck(struct pt_regs *regs) @@ -1582,7 +1588,11 @@ void __init set_handler(unsigned long offset, void *addr, unsigned long size) static char panic_null_cerr[] __cpuinitdata = "Trying to set NULL cache error exception handler"; -/* Install uncached CPU exception handler */ +/* + * Install uncached CPU exception handler. + * This is suitable only for the cache error exception which is the only + * exception handler that is being run uncached. + */ void __cpuinit set_uncached_handler(unsigned long offset, void *addr, unsigned long size) { @@ -1593,7 +1603,7 @@ void __cpuinit set_uncached_handler(unsigned long offset, void *addr, unsigned long uncached_ebase = TO_UNCAC(ebase); #endif if (cpu_has_mips_r2) - ebase += (read_c0_ebase() & 0x3ffff000); + uncached_ebase += (read_c0_ebase() & 0x3ffff000); if (!addr) panic(panic_null_cerr); diff --git a/arch/mips/lib/memcpy-inatomic.S b/arch/mips/lib/memcpy-inatomic.S index 736d0fb..68853a0 100644 --- a/arch/mips/lib/memcpy-inatomic.S +++ b/arch/mips/lib/memcpy-inatomic.S @@ -21,7 +21,7 @@ * end of memory on some systems. It's also a seriously bad idea on non * dma-coherent systems. */ -#if !defined(CONFIG_DMA_COHERENT) || !defined(CONFIG_DMA_IP27) +#ifdef CONFIG_DMA_NONCOHERENT #undef CONFIG_CPU_HAS_PREFETCH #endif #ifdef CONFIG_MIPS_MALTA diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S index c06cccf..56a1f85 100644 --- a/arch/mips/lib/memcpy.S +++ b/arch/mips/lib/memcpy.S @@ -21,7 +21,7 @@ * end of memory on some systems. It's also a seriously bad idea on non * dma-coherent systems. */ -#if !defined(CONFIG_DMA_COHERENT) || !defined(CONFIG_DMA_IP27) +#ifdef CONFIG_DMA_NONCOHERENT #undef CONFIG_CPU_HAS_PREFETCH #endif #ifdef CONFIG_MIPS_MALTA diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 6e99665..c43f4b2 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -618,15 +618,35 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size) if (cpu_has_inclusive_pcaches) { if (size >= scache_size) r4k_blast_scache(); - else + else { + unsigned long lsize = cpu_scache_line_size(); + unsigned long almask = ~(lsize - 1); + + /* + * There is no clearly documented alignment requirement + * for the cache instruction on MIPS processors and + * some processors, among them the RM5200 and RM7000 + * QED processors will throw an address error for cache + * hit ops with insufficient alignment. Solved by + * aligning the address to cache line size. + */ + cache_op(Hit_Writeback_Inv_SD, addr & almask); + cache_op(Hit_Writeback_Inv_SD, + (addr + size - 1) & almask); blast_inv_scache_range(addr, addr + size); + } return; } if (cpu_has_safe_index_cacheops && size >= dcache_size) { r4k_blast_dcache(); } else { + unsigned long lsize = cpu_dcache_line_size(); + unsigned long almask = ~(lsize - 1); + R4600_HIT_CACHEOP_WAR_IMPL; + cache_op(Hit_Writeback_Inv_D, addr & almask); + cache_op(Hit_Writeback_Inv_D, (addr + size - 1) & almask); blast_inv_dcache_range(addr, addr + size); } diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index fa636fc..55767ad 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -97,7 +97,6 @@ good_area: goto bad_area; } -survive: /* * If for any reason at all we couldn't handle the fault, * make sure we exit gracefully rather than endlessly redo @@ -167,21 +166,13 @@ no_context: field, regs->regs[31]); die("Oops", regs); -/* - * We ran out of memory, or some other thing happened to us that made - * us unable to handle the page fault gracefully. - */ out_of_memory: - up_read(&mm->mmap_sem); - if (is_global_init(tsk)) { - yield(); - down_read(&mm->mmap_sem); - goto survive; - } - printk("VM: killing process %s\n", tsk->comm); - if (user_mode(regs)) - do_group_exit(SIGKILL); - goto no_context; + /* + * We ran out of memory, call the OOM killer, and return the userspace + * (which will retry the fault, or kill us if we got oom-killed). + */ + pagefault_out_of_memory(); + return; do_sigbus: up_read(&mm->mmap_sem); diff --git a/arch/mips/pci/pci-rc32434.c b/arch/mips/pci/pci-rc32434.c index 1c2821e..71f7d27 100644 --- a/arch/mips/pci/pci-rc32434.c +++ b/arch/mips/pci/pci-rc32434.c @@ -205,6 +205,8 @@ static int __init rc32434_pcibridge_init(void) static int __init rc32434_pci_init(void) { + void __iomem *io_map_base; + pr_info("PCI: Initializing PCI\n"); ioport_resource.start = rc32434_res_pci_io1.start; @@ -212,6 +214,15 @@ static int __init rc32434_pci_init(void) rc32434_pcibridge_init(); + io_map_base = ioremap(rc32434_res_pci_io1.start, + rc32434_res_pci_io1.end - rc32434_res_pci_io1.start + 1); + + if (!io_map_base) + return -ENOMEM; + + rc32434_controller.io_map_base = + (unsigned long)io_map_base - rc32434_res_pci_io1.start; + register_pci_controller(&rc32434_controller); rc32434_sync(); diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index c1c2918..4a5f05b 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -24,6 +24,7 @@ #include <linux/mtd/partitions.h> #include <linux/gpio_keys.h> #include <linux/input.h> +#include <linux/serial_8250.h> #include <asm/bootinfo.h> @@ -39,6 +40,29 @@ #define ETH0_RX_DMA_ADDR (DMA0_BASE_ADDR + 0 * DMA_CHAN_OFFSET) #define ETH0_TX_DMA_ADDR (DMA0_BASE_ADDR + 1 * DMA_CHAN_OFFSET) +extern unsigned int idt_cpu_freq; + +static struct mpmc_device dev3; + +void set_latch_u5(unsigned char or_mask, unsigned char nand_mask) +{ + unsigned long flags; + + spin_lock_irqsave(&dev3.lock, flags); + + dev3.state = (dev3.state | or_mask) & ~nand_mask; + writeb(dev3.state, dev3.base); + + spin_unlock_irqrestore(&dev3.lock, flags); +} +EXPORT_SYMBOL(set_latch_u5); + +unsigned char get_latch_u5(void) +{ + return dev3.state; +} +EXPORT_SYMBOL(get_latch_u5); + static struct resource korina_dev0_res[] = { { .name = "korina_regs", @@ -86,7 +110,7 @@ static struct korina_device korina_dev0_data = { static struct platform_device korina_dev0 = { .id = -1, .name = "korina", - .dev.platform_data = &korina_dev0_data, + .dev.driver_data = &korina_dev0_data, .resource = korina_dev0_res, .num_resources = ARRAY_SIZE(korina_dev0_res), }; @@ -214,12 +238,32 @@ static struct platform_device rb532_wdt = { .num_resources = ARRAY_SIZE(rb532_wdt_res), }; +static struct plat_serial8250_port rb532_uart_res[] = { + { + .membase = (char *)KSEG1ADDR(REGBASE + UART0BASE), + .irq = UART0_IRQ, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF, + }, + { + .flags = 0, + } +}; + +static struct platform_device rb532_uart = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev.platform_data = &rb532_uart_res, +}; + static struct platform_device *rb532_devs[] = { &korina_dev0, &nand_slot0, &cf_slot0, &rb532_led, &rb532_button, + &rb532_uart, &rb532_wdt }; @@ -291,9 +335,20 @@ static int __init plat_setup_devices(void) nand_slot0_res[0].start = readl(IDT434_REG_BASE + DEV2BASE); nand_slot0_res[0].end = nand_slot0_res[0].start + 0x1000; + /* Read and map device controller 3 */ + dev3.base = ioremap_nocache(readl(IDT434_REG_BASE + DEV3BASE), 1); + + if (!dev3.base) { + printk(KERN_ERR "rb532: cannot remap device controller 3\n"); + return -ENXIO; + } + /* Initialise the NAND device */ rb532_nand_setup(); + /* set the uart clock to the current cpu frequency */ + rb532_uart_res[0].uartclk = idt_cpu_freq; + return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs)); } diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c index 0e84c8a..37de05d 100644 --- a/arch/mips/rb532/gpio.c +++ b/arch/mips/rb532/gpio.c @@ -41,8 +41,6 @@ struct rb532_gpio_chip { void __iomem *regbase; }; -struct mpmc_device dev3; - static struct resource rb532_gpio_reg0_res[] = { { .name = "gpio_reg0", @@ -52,61 +50,6 @@ static struct resource rb532_gpio_reg0_res[] = { } }; -static struct resource rb532_dev3_ctl_res[] = { - { - .name = "dev3_ctl", - .start = REGBASE + DEV3BASE, - .end = REGBASE + DEV3BASE + sizeof(struct dev_reg) - 1, - .flags = IORESOURCE_MEM, - } -}; - -void set_434_reg(unsigned reg_offs, unsigned bit, unsigned len, unsigned val) -{ - unsigned long flags; - unsigned data; - unsigned i = 0; - - spin_lock_irqsave(&dev3.lock, flags); - - data = readl(IDT434_REG_BASE + reg_offs); - for (i = 0; i != len; ++i) { - if (val & (1 << i)) - data |= (1 << (i + bit)); - else - data &= ~(1 << (i + bit)); - } - writel(data, (IDT434_REG_BASE + reg_offs)); - - spin_unlock_irqrestore(&dev3.lock, flags); -} -EXPORT_SYMBOL(set_434_reg); - -unsigned get_434_reg(unsigned reg_offs) -{ - return readl(IDT434_REG_BASE + reg_offs); -} -EXPORT_SYMBOL(get_434_reg); - -void set_latch_u5(unsigned char or_mask, unsigned char nand_mask) -{ - unsigned long flags; - - spin_lock_irqsave(&dev3.lock, flags); - - dev3.state = (dev3.state | or_mask) & ~nand_mask; - writel(dev3.state, &dev3.base); - - spin_unlock_irqrestore(&dev3.lock, flags); -} -EXPORT_SYMBOL(set_latch_u5); - -unsigned char get_latch_u5(void) -{ - return dev3.state; -} -EXPORT_SYMBOL(get_latch_u5); - /* rb532_set_bit - sanely set a bit * * bitval: new value for the bit @@ -119,13 +62,11 @@ static inline void rb532_set_bit(unsigned bitval, unsigned long flags; u32 val; - bitval = !!bitval; /* map parameter to {0,1} */ - local_irq_save(flags); val = readl(ioaddr); - val &= ~( ~bitval << offset ); /* unset bit if bitval == 0 */ - val |= ( bitval << offset ); /* set bit if bitval == 1 */ + val &= ~(!bitval << offset); /* unset bit if bitval == 0 */ + val |= (!!bitval << offset); /* set bit if bitval == 1 */ writel(val, ioaddr); local_irq_restore(flags); @@ -171,8 +112,8 @@ static int rb532_gpio_direction_input(struct gpio_chip *chip, unsigned offset) gpch = container_of(chip, struct rb532_gpio_chip, chip); - if (rb532_get_bit(offset, gpch->regbase + GPIOFUNC)) - return 1; /* alternate function, GPIOCFG is ignored */ + /* disable alternate function in case it's set */ + rb532_set_bit(0, offset, gpch->regbase + GPIOFUNC); rb532_set_bit(0, offset, gpch->regbase + GPIOCFG); return 0; @@ -188,8 +129,8 @@ static int rb532_gpio_direction_output(struct gpio_chip *chip, gpch = container_of(chip, struct rb532_gpio_chip, chip); - if (rb532_get_bit(offset, gpch->regbase + GPIOFUNC)) - return 1; /* alternate function, GPIOCFG is ignored */ + /* disable alternate function in case it's set */ + rb532_set_bit(0, offset, gpch->regbase + GPIOFUNC); /* set the initial output value */ rb532_set_bit(value, offset, gpch->regbase + GPIOD); @@ -233,10 +174,11 @@ EXPORT_SYMBOL(rb532_gpio_set_istat); /* * Configure GPIO alternate function */ -static void rb532_gpio_set_func(int bit, unsigned gpio) +void rb532_gpio_set_func(unsigned gpio) { - rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOFUNC); + rb532_set_bit(1, gpio, rb532_gpio_chip->regbase + GPIOFUNC); } +EXPORT_SYMBOL(rb532_gpio_set_func); int __init rb532_gpio_init(void) { @@ -253,20 +195,6 @@ int __init rb532_gpio_init(void) /* Register our GPIO chip */ gpiochip_add(&rb532_gpio_chip->chip); - r = rb532_dev3_ctl_res; - dev3.base = ioremap_nocache(r->start, r->end - r->start); - - if (!dev3.base) { - printk(KERN_ERR "rb532: cannot remap device controller 3\n"); - return -ENXIO; - } - - /* configure CF_GPIO_NUM as CFRDY IRQ source */ - rb532_gpio_set_func(0, CF_GPIO_NUM); - rb532_gpio_direction_input(&rb532_gpio_chip->chip, CF_GPIO_NUM); - rb532_gpio_set_ilevel(1, CF_GPIO_NUM); - rb532_gpio_set_istat(0, CF_GPIO_NUM); - return 0; } arch_initcall(rb532_gpio_init); diff --git a/arch/mips/rb532/irq.c b/arch/mips/rb532/irq.c index 549b46d..53eeb5e 100644 --- a/arch/mips/rb532/irq.c +++ b/arch/mips/rb532/irq.c @@ -46,6 +46,7 @@ #include <asm/system.h> #include <asm/mach-rc32434/irq.h> +#include <asm/mach-rc32434/gpio.h> struct intr_group { u32 mask; /* mask of valid bits in pending/mask registers */ @@ -150,6 +151,9 @@ static void rb532_disable_irq(unsigned int irq_nr) mask |= intr_bit; WRITE_MASK(addr, mask); + if (group == GPIO_MAPPED_IRQ_GROUP) + rb532_gpio_set_istat(0, irq_nr - GPIO_MAPPED_IRQ_BASE); + /* * if there are no more interrupts enabled in this * group, disable corresponding IP @@ -165,12 +169,35 @@ static void rb532_mask_and_ack_irq(unsigned int irq_nr) ack_local_irq(group_to_ip(irq_to_group(irq_nr))); } +static int rb532_set_type(unsigned int irq_nr, unsigned type) +{ + int gpio = irq_nr - GPIO_MAPPED_IRQ_BASE; + int group = irq_to_group(irq_nr); + + if (group != GPIO_MAPPED_IRQ_GROUP) + return (type == IRQ_TYPE_LEVEL_HIGH) ? 0 : -EINVAL; + + switch (type) { + case IRQ_TYPE_LEVEL_HIGH: + rb532_gpio_set_ilevel(1, gpio); + break; + case IRQ_TYPE_LEVEL_LOW: + rb532_gpio_set_ilevel(0, gpio); + break; + default: + return -EINVAL; + } + + return 0; +} + static struct irq_chip rc32434_irq_type = { .name = "RB532", .ack = rb532_disable_irq, .mask = rb532_disable_irq, .mask_ack = rb532_mask_and_ack_irq, .unmask = rb532_enable_irq, + .set_type = rb532_set_type, }; void __init arch_init_irq(void) diff --git a/arch/mips/rb532/serial.c b/arch/mips/rb532/serial.c index 3e0d7ec..00ed19f 100644 --- a/arch/mips/rb532/serial.c +++ b/arch/mips/rb532/serial.c @@ -36,7 +36,7 @@ extern unsigned int idt_cpu_freq; static struct uart_port rb532_uart = { - .type = PORT_16550A, + .flags = UPF_BOOT_AUTOCONF, .line = 0, .irq = UART0_IRQ, .iotype = UPIO_MEM, diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c index 6c0049a..5544096 100644 --- a/arch/mips/txx9/generic/setup_tx4939.c +++ b/arch/mips/txx9/generic/setup_tx4939.c @@ -435,6 +435,28 @@ void __init tx4939_ata_init(void) platform_device_register(&ata1_dev); } +void __init tx4939_rtc_init(void) +{ + static struct resource res[] = { + { + .start = TX4939_RTC_REG & 0xfffffffffULL, + .end = (TX4939_RTC_REG & 0xfffffffffULL) + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = TXX9_IRQ_BASE + TX4939_IR_RTC, + .flags = IORESOURCE_IRQ, + }, + }; + static struct platform_device rtc_dev = { + .name = "tx4939rtc", + .id = -1, + .num_resources = ARRAY_SIZE(res), + .resource = res, + }; + + platform_device_register(&rtc_dev); +} + static void __init tx4939_stop_unused_modules(void) { __u64 pcfg, rst = 0, ckd = 0; diff --git a/arch/mips/txx9/rbtx4939/setup.c b/arch/mips/txx9/rbtx4939/setup.c index 98fbd93..656603b 100644 --- a/arch/mips/txx9/rbtx4939/setup.c +++ b/arch/mips/txx9/rbtx4939/setup.c @@ -336,6 +336,7 @@ static void __init rbtx4939_device_init(void) rbtx4939_led_setup(); tx4939_wdt_init(); tx4939_ata_init(); + tx4939_rtc_init(); } static void __init rbtx4939_setup(void) diff --git a/arch/powerpc/configs/52xx/cm5200_defconfig b/arch/powerpc/configs/52xx/cm5200_defconfig index 99c495a..1239c61 100644 --- a/arch/powerpc/configs/52xx/cm5200_defconfig +++ b/arch/powerpc/configs/52xx/cm5200_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc4 -# Thu Nov 13 02:12:40 2008 +# Linux kernel version: 2.6.29-rc2 +# Mon Jan 26 21:41:58 2009 # # CONFIG_PPC64 is not set @@ -43,7 +43,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_PPC=y CONFIG_EARLY_PRINTK=y CONFIG_GENERIC_NVRAM=y -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_PPC_OF=y CONFIG_OF=y @@ -71,14 +71,23 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set CONFIG_GROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y # CONFIG_RT_GROUP_SCHED is not set CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set @@ -110,7 +119,6 @@ CONFIG_SLUB_DEBUG=y CONFIG_SLUB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_HAVE_IOREMAP_PROT=y @@ -121,13 +129,11 @@ CONFIG_HAVE_CLK=y # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_MODULES is not set CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -143,7 +149,6 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" -CONFIG_CLASSIC_RCU=y # CONFIG_FREEZER is not set # @@ -182,9 +187,8 @@ CONFIG_PPC_MPC5200_SIMPLE=y # CONFIG_TAU is not set # CONFIG_FSL_ULI1575 is not set CONFIG_PPC_BESTCOMM=y -# CONFIG_PPC_BESTCOMM_ATA is not set CONFIG_PPC_BESTCOMM_FEC=y -# CONFIG_PPC_BESTCOMM_GEN_BD is not set +# CONFIG_SIMPLE_GPIO is not set # # Kernel options @@ -211,6 +215,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_HAS_WALK_MEMORY=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y # CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_SELECT_MEMORY_MODEL=y @@ -222,12 +227,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y -# CONFIG_RESOURCES_64BIT is not set # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y CONFIG_UNEVICTABLE_LRU=y +CONFIG_PPC_4K_PAGES=y +# CONFIG_PPC_16K_PAGES is not set +# CONFIG_PPC_64K_PAGES is not set CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_PROC_DEVICETREE=y # CONFIG_CMDLINE_BOOL is not set @@ -268,6 +275,7 @@ CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -324,6 +332,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing @@ -336,6 +345,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_AF_RXRPC is not set # CONFIG_PHONET is not set # CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -427,6 +437,12 @@ CONFIG_MTD_PHYSMAP_OF=y # CONFIG_MTD_ONENAND is not set # +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_QINFO_PROBE is not set + +# # UBI - Unsorted block images # # CONFIG_MTD_UBI is not set @@ -514,6 +530,9 @@ CONFIG_LXT_PHY=y # CONFIG_BROADCOM_PHY is not set # CONFIG_ICPLUS_PHY is not set # CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set # CONFIG_FIXED_PHY is not set # CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y @@ -539,6 +558,10 @@ CONFIG_FEC_MPC52xx_MDIO=y # CONFIG_IWLWIFI_LEDS is not set # +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# # USB Network Adapters # # CONFIG_USB_CATC is not set @@ -588,8 +611,10 @@ CONFIG_SERIAL_MPC52xx=y CONFIG_SERIAL_MPC52xx_CONSOLE=y CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=57600 CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_HVC_UDBG is not set # CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set # CONFIG_NVRAM is not set @@ -629,8 +654,6 @@ CONFIG_I2C_MPC=y # Miscellaneous I2C Chip support # # CONFIG_DS1682 is not set -# CONFIG_EEPROM_AT24 is not set -# CONFIG_EEPROM_LEGACY is not set # CONFIG_SENSORS_PCF8574 is not set # CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set @@ -675,10 +698,12 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set # CONFIG_REGULATOR is not set # @@ -736,6 +761,7 @@ CONFIG_USB_DEVICEFS=y # USB Host Controller Drivers # # CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set CONFIG_USB_OHCI_HCD=y @@ -760,18 +786,17 @@ CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y # CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set # CONFIG_USB_STORAGE_DATAFAB is not set # CONFIG_USB_STORAGE_FREECOM is not set # CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set # CONFIG_USB_STORAGE_USBAT is not set # CONFIG_USB_STORAGE_SDDR09 is not set # CONFIG_USB_STORAGE_SDDR55 is not set @@ -817,6 +842,10 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set @@ -826,7 +855,6 @@ CONFIG_USB_STORAGE=y # CONFIG_DMADEVICES is not set # CONFIG_UIO is not set # CONFIG_STAGING is not set -CONFIG_STAGING_EXCLUDE_BUILD=y # # File systems @@ -847,6 +875,7 @@ CONFIG_FS_MBCACHE=y CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y @@ -883,10 +912,7 @@ CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set @@ -906,6 +932,7 @@ CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set @@ -1002,6 +1029,7 @@ CONFIG_NLS_ISO8859_1=y # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set # CONFIG_CRC_T10DIF is not set @@ -1053,6 +1081,7 @@ CONFIG_SCHED_DEBUG=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set @@ -1061,6 +1090,8 @@ CONFIG_SCHED_DEBUG=y # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y # # Tracers @@ -1069,11 +1100,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y # CONFIG_SCHED_TRACER is not set # CONFIG_CONTEXT_SWITCH_TRACER is not set # CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set # CONFIG_STACK_TRACER is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set +CONFIG_PRINT_STACK_DEPTH=64 # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_PAGEALLOC is not set @@ -1100,11 +1133,15 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set diff --git a/arch/powerpc/configs/52xx/lite5200b_defconfig b/arch/powerpc/configs/52xx/lite5200b_defconfig index 9796220..b7b8805 100644 --- a/arch/powerpc/configs/52xx/lite5200b_defconfig +++ b/arch/powerpc/configs/52xx/lite5200b_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc4 -# Thu Nov 13 02:10:16 2008 +# Linux kernel version: 2.6.29-rc2 +# Mon Jan 26 21:41:14 2009 # # CONFIG_PPC64 is not set @@ -43,7 +43,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_PPC=y CONFIG_EARLY_PRINTK=y CONFIG_GENERIC_NVRAM=y -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_PPC_OF=y CONFIG_OF=y @@ -72,14 +72,23 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set CONFIG_GROUP_SCHED=y # CONFIG_FAIR_GROUP_SCHED is not set # CONFIG_RT_GROUP_SCHED is not set CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set @@ -112,7 +121,6 @@ CONFIG_SLUB_DEBUG=y CONFIG_SLUB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_HAVE_IOREMAP_PROT=y @@ -123,7 +131,6 @@ CONFIG_HAVE_CLK=y # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y # CONFIG_MODULE_FORCE_LOAD is not set @@ -131,11 +138,9 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -151,7 +156,6 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" -CONFIG_CLASSIC_RCU=y CONFIG_FREEZER=y # @@ -192,7 +196,7 @@ CONFIG_PPC_LITE5200=y CONFIG_PPC_BESTCOMM=y CONFIG_PPC_BESTCOMM_ATA=y CONFIG_PPC_BESTCOMM_FEC=y -CONFIG_PPC_BESTCOMM_GEN_BD=y +# CONFIG_SIMPLE_GPIO is not set # # Kernel options @@ -220,6 +224,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_HAS_WALK_MEMORY=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y # CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_SELECT_MEMORY_MODEL=y @@ -231,12 +236,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y -# CONFIG_RESOURCES_64BIT is not set # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y CONFIG_UNEVICTABLE_LRU=y +CONFIG_PPC_4K_PAGES=y +# CONFIG_PPC_16K_PAGES is not set +# CONFIG_PPC_64K_PAGES is not set CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_PROC_DEVICETREE=y # CONFIG_CMDLINE_BOOL is not set @@ -264,6 +271,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y # CONFIG_PCI_MSI is not set CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set # CONFIG_PCCARD is not set # CONFIG_HOTPLUG_PCI is not set # CONFIG_HAS_RAPIDIO is not set @@ -286,6 +294,7 @@ CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -342,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing @@ -354,6 +364,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_AF_RXRPC is not set # CONFIG_PHONET is not set # CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -396,13 +407,19 @@ CONFIG_BLK_DEV_RAM_SIZE=32768 # CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_PHANTOM is not set -# CONFIG_EEPROM_93CX6 is not set # CONFIG_SGI_IOC4 is not set # CONFIG_TIFM_CORE is not set # CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_HP_ILO is not set # CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_93CX6 is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -445,6 +462,7 @@ CONFIG_SCSI_WAIT_SCAN=m # CONFIG_SCSI_SRP_ATTRS is not set CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set @@ -461,6 +479,8 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_LIBFC is not set +# CONFIG_FCOE is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_EATA is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set @@ -580,6 +600,9 @@ CONFIG_LXT_PHY=y # CONFIG_BROADCOM_PHY is not set # CONFIG_ICPLUS_PHY is not set # CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set # CONFIG_FIXED_PHY is not set # CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y @@ -626,6 +649,7 @@ CONFIG_NETDEV_1000=y # CONFIG_JME is not set CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set +CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set # CONFIG_ENIC is not set # CONFIG_IXGBE is not set @@ -648,6 +672,10 @@ CONFIG_NETDEV_10000=y # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set # CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -695,8 +723,10 @@ CONFIG_SERIAL_MPC52xx_CONSOLE=y CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200 # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_HVC_UDBG is not set # CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set # CONFIG_NVRAM is not set @@ -762,8 +792,6 @@ CONFIG_I2C_MPC=y # Miscellaneous I2C Chip support # # CONFIG_DS1682 is not set -# CONFIG_EEPROM_AT24 is not set -# CONFIG_EEPROM_LEGACY is not set # CONFIG_SENSORS_PCF8574 is not set # CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set @@ -796,10 +824,12 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set # CONFIG_REGULATOR is not set # @@ -846,9 +876,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y # # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# # CONFIG_UWB is not set # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set @@ -860,7 +894,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y # CONFIG_DMADEVICES is not set # CONFIG_UIO is not set # CONFIG_STAGING is not set -CONFIG_STAGING_EXCLUDE_BUILD=y # # File systems @@ -881,6 +914,7 @@ CONFIG_FS_MBCACHE=y CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y @@ -914,10 +948,7 @@ CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set @@ -926,6 +957,7 @@ CONFIG_TMPFS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set @@ -967,6 +999,7 @@ CONFIG_MSDOS_PARTITION=y # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set # CONFIG_CRC_T10DIF is not set @@ -1016,6 +1049,7 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set @@ -1024,6 +1058,8 @@ CONFIG_DEBUG_INFO=y # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y # # Tracers @@ -1032,11 +1068,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y # CONFIG_SCHED_TRACER is not set # CONFIG_CONTEXT_SWITCH_TRACER is not set # CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set # CONFIG_STACK_TRACER is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set +CONFIG_PRINT_STACK_DEPTH=64 # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_PAGEALLOC is not set @@ -1063,11 +1101,15 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set diff --git a/arch/powerpc/configs/52xx/motionpro_defconfig b/arch/powerpc/configs/52xx/motionpro_defconfig index d081e00..fb10f22 100644 --- a/arch/powerpc/configs/52xx/motionpro_defconfig +++ b/arch/powerpc/configs/52xx/motionpro_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc4 -# Thu Nov 13 02:11:02 2008 +# Linux kernel version: 2.6.29-rc2 +# Mon Jan 26 21:42:29 2009 # # CONFIG_PPC64 is not set @@ -43,7 +43,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_PPC=y CONFIG_EARLY_PRINTK=y CONFIG_GENERIC_NVRAM=y -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_PPC_OF=y CONFIG_OF=y @@ -71,14 +71,23 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set CONFIG_GROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y # CONFIG_RT_GROUP_SCHED is not set CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set @@ -110,7 +119,6 @@ CONFIG_SLUB_DEBUG=y CONFIG_SLUB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_HAVE_IOREMAP_PROT=y @@ -121,13 +129,11 @@ CONFIG_HAVE_CLK=y # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_MODULES is not set CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -143,7 +149,6 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" -CONFIG_CLASSIC_RCU=y # CONFIG_FREEZER is not set # @@ -182,9 +187,9 @@ CONFIG_PPC_MPC5200_SIMPLE=y # CONFIG_TAU is not set # CONFIG_FSL_ULI1575 is not set CONFIG_PPC_BESTCOMM=y -# CONFIG_PPC_BESTCOMM_ATA is not set +CONFIG_PPC_BESTCOMM_ATA=y CONFIG_PPC_BESTCOMM_FEC=y -# CONFIG_PPC_BESTCOMM_GEN_BD is not set +# CONFIG_SIMPLE_GPIO is not set # # Kernel options @@ -211,6 +216,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_HAS_WALK_MEMORY=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y # CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_SELECT_MEMORY_MODEL=y @@ -222,12 +228,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y -# CONFIG_RESOURCES_64BIT is not set # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y CONFIG_UNEVICTABLE_LRU=y +CONFIG_PPC_4K_PAGES=y +# CONFIG_PPC_16K_PAGES is not set +# CONFIG_PPC_64K_PAGES is not set CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_PROC_DEVICETREE=y # CONFIG_CMDLINE_BOOL is not set @@ -268,6 +276,7 @@ CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -324,6 +333,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing @@ -336,6 +346,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_AF_RXRPC is not set # CONFIG_PHONET is not set # CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -427,6 +438,12 @@ CONFIG_MTD_ROM=y # CONFIG_MTD_ONENAND is not set # +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_QINFO_PROBE is not set + +# # UBI - Unsorted block images # # CONFIG_MTD_UBI is not set @@ -447,10 +464,16 @@ CONFIG_BLK_DEV_RAM_SIZE=32768 # CONFIG_ATA_OVER_ETH is not set # CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y -# CONFIG_EEPROM_93CX6 is not set # CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +CONFIG_EEPROM_LEGACY=y +# CONFIG_EEPROM_93CX6 is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -492,6 +515,7 @@ CONFIG_CHR_DEV_SG=y # CONFIG_SCSI_SRP_ATTRS is not set CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set +# CONFIG_LIBFC is not set # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_DH is not set CONFIG_ATA=y @@ -525,6 +549,9 @@ CONFIG_SMSC_PHY=y CONFIG_BROADCOM_PHY=y CONFIG_ICPLUS_PHY=y # CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set # CONFIG_FIXED_PHY is not set CONFIG_MDIO_BITBANG=y CONFIG_NET_ETHERNET=y @@ -548,6 +575,10 @@ CONFIG_FEC_MPC52xx_MDIO=y # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set # CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -590,8 +621,10 @@ CONFIG_SERIAL_MPC52xx=y CONFIG_SERIAL_MPC52xx_CONSOLE=y CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200 CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_HVC_UDBG is not set # CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set # CONFIG_NVRAM is not set @@ -629,8 +662,6 @@ CONFIG_I2C_MPC=y # Miscellaneous I2C Chip support # # CONFIG_DS1682 is not set -# CONFIG_EEPROM_AT24 is not set -CONFIG_EEPROM_LEGACY=y # CONFIG_SENSORS_PCF8574 is not set # CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set @@ -659,6 +690,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set # CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ADT7475 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_F71805F is not set @@ -678,6 +710,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_PC87360 is not set @@ -721,10 +754,12 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set # CONFIG_REGULATOR is not set # @@ -835,7 +870,6 @@ CONFIG_RTC_DRV_DS1307=y # CONFIG_DMADEVICES is not set # CONFIG_UIO is not set # CONFIG_STAGING is not set -CONFIG_STAGING_EXCLUDE_BUILD=y # # File systems @@ -856,6 +890,7 @@ CONFIG_FS_MBCACHE=y CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y @@ -892,10 +927,7 @@ CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set @@ -915,6 +947,7 @@ CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set @@ -1011,6 +1044,7 @@ CONFIG_NLS_ISO8859_1=y # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set # CONFIG_CRC_T10DIF is not set @@ -1062,6 +1096,7 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set @@ -1070,6 +1105,8 @@ CONFIG_DEBUG_INFO=y # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y # # Tracers @@ -1078,11 +1115,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y # CONFIG_SCHED_TRACER is not set # CONFIG_CONTEXT_SWITCH_TRACER is not set # CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set # CONFIG_STACK_TRACER is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set +CONFIG_PRINT_STACK_DEPTH=64 # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_PAGEALLOC is not set @@ -1109,11 +1148,15 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set diff --git a/arch/powerpc/configs/52xx/pcm030_defconfig b/arch/powerpc/configs/52xx/pcm030_defconfig index b21b8e8..00944c0 100644 --- a/arch/powerpc/configs/52xx/pcm030_defconfig +++ b/arch/powerpc/configs/52xx/pcm030_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc4 -# Thu Nov 13 02:13:16 2008 +# Linux kernel version: 2.6.29-rc2 +# Mon Jan 26 21:41:33 2009 # # CONFIG_PPC64 is not set @@ -43,7 +43,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_PPC=y CONFIG_EARLY_PRINTK=y CONFIG_GENERIC_NVRAM=y -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_PPC_OF=y CONFIG_OF=y @@ -72,15 +72,24 @@ CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set CONFIG_GROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y # CONFIG_RT_GROUP_SCHED is not set CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set @@ -112,7 +121,6 @@ CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set # CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y @@ -124,7 +132,6 @@ CONFIG_HAVE_CLK=y # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y # CONFIG_MODULE_FORCE_LOAD is not set @@ -132,11 +139,9 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -152,7 +157,6 @@ CONFIG_IOSCHED_NOOP=y # CONFIG_DEFAULT_CFQ is not set CONFIG_DEFAULT_NOOP=y CONFIG_DEFAULT_IOSCHED="noop" -CONFIG_CLASSIC_RCU=y # CONFIG_FREEZER is not set # @@ -191,9 +195,9 @@ CONFIG_PPC_MPC5200_SIMPLE=y # CONFIG_TAU is not set # CONFIG_FSL_ULI1575 is not set CONFIG_PPC_BESTCOMM=y -CONFIG_PPC_BESTCOMM_ATA=y +CONFIG_PPC_BESTCOMM_ATA=m CONFIG_PPC_BESTCOMM_FEC=y -CONFIG_PPC_BESTCOMM_GEN_BD=y +# CONFIG_SIMPLE_GPIO is not set # # Kernel options @@ -212,7 +216,6 @@ CONFIG_SCHED_HRTICK=y # CONFIG_PREEMPT_NONE is not set # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y -# CONFIG_PREEMPT_RCU is not set CONFIG_BINFMT_ELF=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set # CONFIG_HAVE_AOUT is not set @@ -222,6 +225,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_HAS_WALK_MEMORY=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y # CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_SELECT_MEMORY_MODEL=y @@ -233,12 +237,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y -# CONFIG_RESOURCES_64BIT is not set # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y CONFIG_UNEVICTABLE_LRU=y +CONFIG_PPC_4K_PAGES=y +# CONFIG_PPC_16K_PAGES is not set +# CONFIG_PPC_64K_PAGES is not set CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_PROC_DEVICETREE=y # CONFIG_CMDLINE_BOOL is not set @@ -261,6 +267,7 @@ CONFIG_PCI_SYSCALL=y CONFIG_ARCH_SUPPORTS_MSI=y # CONFIG_PCI_MSI is not set CONFIG_PCI_LEGACY=y +# CONFIG_PCI_STUB is not set # CONFIG_PCCARD is not set # CONFIG_HOTPLUG_PCI is not set # CONFIG_HAS_RAPIDIO is not set @@ -283,6 +290,7 @@ CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -333,6 +341,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing @@ -345,6 +354,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_AF_RXRPC is not set # CONFIG_PHONET is not set # CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -365,6 +375,7 @@ CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set # CONFIG_MTD_CONCAT is not set CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_OF_PARTS is not set @@ -413,9 +424,7 @@ CONFIG_MTD_CFI_UTIL=y # # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x0 -CONFIG_MTD_PHYSMAP_LEN=0x0 -CONFIG_MTD_PHYSMAP_BANKWIDTH=1 +# CONFIG_MTD_PHYSMAP_COMPAT is not set # CONFIG_MTD_PHYSMAP_OF is not set # CONFIG_MTD_INTEL_VR_NOR is not set # CONFIG_MTD_PLATRAM is not set @@ -439,6 +448,12 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1 # CONFIG_MTD_ONENAND is not set # +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_QINFO_PROBE is not set + +# # UBI - Unsorted block images # # CONFIG_MTD_UBI is not set @@ -587,6 +602,9 @@ CONFIG_PHYLIB=y # CONFIG_BROADCOM_PHY is not set # CONFIG_ICPLUS_PHY is not set # CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set # CONFIG_FIXED_PHY is not set # CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y @@ -621,6 +639,10 @@ CONFIG_FEC_MPC52xx_MDIO=y # CONFIG_IWLWIFI_LEDS is not set # +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# # USB Network Adapters # # CONFIG_USB_CATC is not set @@ -675,7 +697,9 @@ CONFIG_SERIAL_MPC52xx_CONSOLE=y CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=9600 # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set +# CONFIG_HVC_UDBG is not set # CONFIG_IPMI_HANDLER is not set CONFIG_HW_RANDOM=y # CONFIG_NVRAM is not set @@ -740,8 +764,6 @@ CONFIG_I2C_MPC=y # Miscellaneous I2C Chip support # # CONFIG_DS1682 is not set -# CONFIG_EEPROM_AT24 is not set -CONFIG_EEPROM_LEGACY=m # CONFIG_SENSORS_PCF8574 is not set # CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set @@ -774,10 +796,12 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set # CONFIG_REGULATOR is not set # @@ -837,6 +861,7 @@ CONFIG_USB_DEVICEFS=y # # CONFIG_USB_C67X00_HCD is not set # CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set CONFIG_USB_OHCI_HCD=m @@ -864,18 +889,17 @@ CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y # CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_DEBUG is not set # CONFIG_USB_STORAGE_DATAFAB is not set # CONFIG_USB_STORAGE_FREECOM is not set # CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set # CONFIG_USB_STORAGE_USBAT is not set # CONFIG_USB_STORAGE_SDDR09 is not set # CONFIG_USB_STORAGE_SDDR55 is not set @@ -921,6 +945,10 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# # CONFIG_UWB is not set # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set @@ -983,7 +1011,6 @@ CONFIG_RTC_DRV_PCF8563=m # CONFIG_DMADEVICES is not set # CONFIG_UIO is not set # CONFIG_STAGING is not set -CONFIG_STAGING_EXCLUDE_BUILD=y # # File systems @@ -1004,6 +1031,7 @@ CONFIG_FS_MBCACHE=m CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set # CONFIG_DNOTIFY is not set # CONFIG_INOTIFY is not set # CONFIG_QUOTA is not set @@ -1039,10 +1067,7 @@ CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set @@ -1062,6 +1087,7 @@ CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set # CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set @@ -1141,6 +1167,7 @@ CONFIG_NLS_ISO8859_1=y # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set # CONFIG_CRC_T10DIF is not set @@ -1173,6 +1200,8 @@ CONFIG_FRAME_WARN=1024 # CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_LATENCYTOP is not set CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y # # Tracers @@ -1180,6 +1209,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y +CONFIG_PRINT_STACK_DEPTH=64 # CONFIG_IRQSTACKS is not set # CONFIG_BOOTX_TEXT is not set # CONFIG_PPC_EARLY_DEBUG is not set diff --git a/arch/powerpc/configs/52xx/tqm5200_defconfig b/arch/powerpc/configs/52xx/tqm5200_defconfig index 7995457..65237ad 100644 --- a/arch/powerpc/configs/52xx/tqm5200_defconfig +++ b/arch/powerpc/configs/52xx/tqm5200_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc4 -# Thu Nov 13 02:09:30 2008 +# Linux kernel version: 2.6.29-rc2 +# Mon Jan 26 21:42:58 2009 # # CONFIG_PPC64 is not set @@ -43,7 +43,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_PPC=y CONFIG_EARLY_PRINTK=y CONFIG_GENERIC_NVRAM=y -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_PPC_OF=y CONFIG_OF=y @@ -71,14 +71,23 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set CONFIG_GROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y # CONFIG_RT_GROUP_SCHED is not set CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set @@ -110,7 +119,6 @@ CONFIG_SLUB_DEBUG=y CONFIG_SLUB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_HAVE_IOREMAP_PROT=y @@ -121,7 +129,6 @@ CONFIG_HAVE_CLK=y # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y # CONFIG_MODULE_FORCE_LOAD is not set @@ -129,11 +136,9 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set CONFIG_MODVERSIONS=y # CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -149,7 +154,6 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" -CONFIG_CLASSIC_RCU=y # CONFIG_FREEZER is not set # @@ -188,9 +192,9 @@ CONFIG_PPC_MPC5200_BUGFIX=y # CONFIG_TAU is not set # CONFIG_FSL_ULI1575 is not set CONFIG_PPC_BESTCOMM=y -# CONFIG_PPC_BESTCOMM_ATA is not set +CONFIG_PPC_BESTCOMM_ATA=y CONFIG_PPC_BESTCOMM_FEC=y -# CONFIG_PPC_BESTCOMM_GEN_BD is not set +# CONFIG_SIMPLE_GPIO is not set # # Kernel options @@ -217,6 +221,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_HAS_WALK_MEMORY=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y # CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_SELECT_MEMORY_MODEL=y @@ -228,12 +233,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y -# CONFIG_RESOURCES_64BIT is not set # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y CONFIG_UNEVICTABLE_LRU=y +CONFIG_PPC_4K_PAGES=y +# CONFIG_PPC_16K_PAGES is not set +# CONFIG_PPC_64K_PAGES is not set CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_PROC_DEVICETREE=y # CONFIG_CMDLINE_BOOL is not set @@ -274,6 +281,7 @@ CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -330,6 +338,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing @@ -342,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_AF_RXRPC is not set # CONFIG_PHONET is not set # CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -364,6 +374,7 @@ CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set CONFIG_MTD_CONCAT=y CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_OF_PARTS is not set @@ -433,6 +444,12 @@ CONFIG_MTD_PHYSMAP_OF=y # CONFIG_MTD_ONENAND is not set # +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_QINFO_PROBE is not set + +# # UBI - Unsorted block images # # CONFIG_MTD_UBI is not set @@ -496,6 +513,7 @@ CONFIG_SCSI_WAIT_SCAN=m # CONFIG_SCSI_SRP_ATTRS is not set CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set +# CONFIG_LIBFC is not set # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_DH is not set CONFIG_ATA=y @@ -530,6 +548,9 @@ CONFIG_LXT_PHY=y # CONFIG_BROADCOM_PHY is not set # CONFIG_ICPLUS_PHY is not set # CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set # CONFIG_FIXED_PHY is not set # CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y @@ -555,6 +576,10 @@ CONFIG_FEC_MPC52xx_MDIO=y # CONFIG_IWLWIFI_LEDS is not set # +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# # USB Network Adapters # # CONFIG_USB_CATC is not set @@ -604,8 +629,10 @@ CONFIG_SERIAL_MPC52xx=y CONFIG_SERIAL_MPC52xx_CONSOLE=y CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200 CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_HVC_UDBG is not set # CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set # CONFIG_NVRAM is not set @@ -645,8 +672,6 @@ CONFIG_I2C_MPC=y # Miscellaneous I2C Chip support # # CONFIG_DS1682 is not set -# CONFIG_EEPROM_AT24 is not set -# CONFIG_EEPROM_LEGACY is not set # CONFIG_SENSORS_PCF8574 is not set # CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set @@ -675,6 +700,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set # CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ADT7475 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_F71805F is not set @@ -694,6 +720,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_PC87360 is not set @@ -742,10 +769,12 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set # CONFIG_REGULATOR is not set # @@ -803,6 +832,7 @@ CONFIG_USB_MON=y # USB Host Controller Drivers # # CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set CONFIG_USB_OHCI_HCD=y @@ -827,18 +857,17 @@ CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y # CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set # CONFIG_USB_STORAGE_DATAFAB is not set # CONFIG_USB_STORAGE_FREECOM is not set # CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set # CONFIG_USB_STORAGE_USBAT is not set # CONFIG_USB_STORAGE_SDDR09 is not set # CONFIG_USB_STORAGE_SDDR55 is not set @@ -884,6 +913,10 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set @@ -947,7 +980,6 @@ CONFIG_RTC_DRV_DS1307=y # CONFIG_DMADEVICES is not set # CONFIG_UIO is not set # CONFIG_STAGING is not set -CONFIG_STAGING_EXCLUDE_BUILD=y # # File systems @@ -968,6 +1000,7 @@ CONFIG_FS_MBCACHE=y CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y @@ -1004,10 +1037,7 @@ CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set @@ -1027,6 +1057,7 @@ CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set @@ -1123,6 +1154,7 @@ CONFIG_NLS_ISO8859_1=y # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set # CONFIG_CRC_T10DIF is not set @@ -1174,6 +1206,7 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set @@ -1182,6 +1215,8 @@ CONFIG_DEBUG_INFO=y # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y # # Tracers @@ -1190,11 +1225,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y # CONFIG_SCHED_TRACER is not set # CONFIG_CONTEXT_SWITCH_TRACER is not set # CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set # CONFIG_STACK_TRACER is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set +CONFIG_PRINT_STACK_DEPTH=64 # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_PAGEALLOC is not set @@ -1221,11 +1258,15 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig index 5ff3de2..81afc8b 100644 --- a/arch/powerpc/configs/mpc5200_defconfig +++ b/arch/powerpc/configs/mpc5200_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28-rc4 -# Thu Nov 13 02:09:07 2008 +# Linux kernel version: 2.6.29-rc2 +# Mon Jan 26 21:40:44 2009 # # CONFIG_PPC64 is not set @@ -43,7 +43,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_PPC=y CONFIG_EARLY_PRINTK=y CONFIG_GENERIC_NVRAM=y -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_PPC_OF=y CONFIG_OF=y @@ -72,10 +72,19 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set @@ -108,7 +117,6 @@ CONFIG_SLUB_DEBUG=y CONFIG_SLUB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_HAVE_IOREMAP_PROT=y @@ -119,7 +127,6 @@ CONFIG_HAVE_CLK=y # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y # CONFIG_MODULE_FORCE_LOAD is not set @@ -127,11 +134,9 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -147,7 +152,6 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" -CONFIG_CLASSIC_RCU=y CONFIG_FREEZER=y # @@ -192,7 +196,7 @@ CONFIG_RTAS_PROC=y CONFIG_PPC_BESTCOMM=y CONFIG_PPC_BESTCOMM_ATA=y CONFIG_PPC_BESTCOMM_FEC=y -CONFIG_PPC_BESTCOMM_GEN_BD=y +# CONFIG_SIMPLE_GPIO is not set # # Kernel options @@ -220,6 +224,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_HAS_WALK_MEMORY=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y # CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_SELECT_MEMORY_MODEL=y @@ -231,12 +236,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y -# CONFIG_RESOURCES_64BIT is not set # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y CONFIG_UNEVICTABLE_LRU=y +CONFIG_PPC_4K_PAGES=y +# CONFIG_PPC_16K_PAGES is not set +# CONFIG_PPC_64K_PAGES is not set CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_PROC_DEVICETREE=y # CONFIG_CMDLINE_BOOL is not set @@ -264,6 +271,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y # CONFIG_PCI_MSI is not set CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set # CONFIG_PCCARD is not set # CONFIG_HOTPLUG_PCI is not set # CONFIG_HAS_RAPIDIO is not set @@ -286,6 +294,7 @@ CONFIG_NET=y # # Networking options # +CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -342,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing @@ -354,6 +364,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_AF_RXRPC is not set # CONFIG_PHONET is not set # CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -376,6 +387,7 @@ CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set CONFIG_MTD_CONCAT=y CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_OF_PARTS is not set @@ -447,6 +459,12 @@ CONFIG_MTD_PHYSMAP_OF=y # CONFIG_MTD_ONENAND is not set # +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_QINFO_PROBE is not set + +# # UBI - Unsorted block images # # CONFIG_MTD_UBI is not set @@ -474,13 +492,19 @@ CONFIG_BLK_DEV_RAM_SIZE=32768 # CONFIG_BLK_DEV_HD is not set CONFIG_MISC_DEVICES=y # CONFIG_PHANTOM is not set -# CONFIG_EEPROM_93CX6 is not set # CONFIG_SGI_IOC4 is not set # CONFIG_TIFM_CORE is not set # CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_HP_ILO is not set # CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_93CX6 is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -539,6 +563,8 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_LIBFC is not set +# CONFIG_FCOE is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_EATA is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set @@ -659,6 +685,9 @@ CONFIG_PHYLIB=y # CONFIG_BROADCOM_PHY is not set # CONFIG_ICPLUS_PHY is not set # CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set # CONFIG_FIXED_PHY is not set # CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y @@ -693,6 +722,10 @@ CONFIG_FEC_MPC52xx_MDIO=y # CONFIG_IWLWIFI_LEDS is not set # +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# # USB Network Adapters # # CONFIG_USB_CATC is not set @@ -774,9 +807,11 @@ CONFIG_SERIAL_MPC52xx_CONSOLE=y CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200 # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_HVC_RTAS is not set +# CONFIG_HVC_UDBG is not set # CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set # CONFIG_NVRAM is not set @@ -844,8 +879,6 @@ CONFIG_I2C_MPC=y # Miscellaneous I2C Chip support # # CONFIG_DS1682 is not set -# CONFIG_EEPROM_AT24 is not set -# CONFIG_EEPROM_LEGACY is not set # CONFIG_SENSORS_PCF8574 is not set # CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set @@ -874,6 +907,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set # CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ADT7475 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_I5K_AMB is not set @@ -894,6 +928,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_PC87360 is not set @@ -953,10 +988,12 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set # CONFIG_REGULATOR is not set # @@ -1051,7 +1088,7 @@ CONFIG_LCD_CLASS_DEVICE=m # CONFIG_LCD_ILI9320 is not set # CONFIG_LCD_PLATFORM is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y -# CONFIG_BACKLIGHT_CORGI is not set +CONFIG_BACKLIGHT_GENERIC=y # # Display device support @@ -1093,21 +1130,22 @@ CONFIG_HID_COMPAT=y CONFIG_HID_A4TECH=y # CONFIG_HID_APPLE is not set CONFIG_HID_BELKIN=y -CONFIG_HID_BRIGHT=y CONFIG_HID_CHERRY=y # CONFIG_HID_CHICONY is not set CONFIG_HID_CYPRESS=y -CONFIG_HID_DELL=y CONFIG_HID_EZKEY=y # CONFIG_HID_GYRATION is not set # CONFIG_HID_LOGITECH is not set # CONFIG_HID_MICROSOFT is not set # CONFIG_HID_MONTEREY is not set +# CONFIG_HID_NTRIG is not set # CONFIG_HID_PANTHERLORD is not set # CONFIG_HID_PETALYNX is not set # CONFIG_HID_SAMSUNG is not set # CONFIG_HID_SONY is not set # CONFIG_HID_SUNPLUS is not set +# CONFIG_GREENASIA_FF is not set +# CONFIG_HID_TOPSEED is not set # CONFIG_THRUSTMASTER_FF is not set # CONFIG_ZEROPLUS_FF is not set CONFIG_USB_SUPPORT=y @@ -1137,6 +1175,7 @@ CONFIG_USB_MON=y # # CONFIG_USB_C67X00_HCD is not set # CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set CONFIG_USB_OHCI_HCD=y @@ -1164,18 +1203,17 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set # CONFIG_USB_STORAGE_DATAFAB is not set # CONFIG_USB_STORAGE_FREECOM is not set # CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set # CONFIG_USB_STORAGE_USBAT is not set # CONFIG_USB_STORAGE_SDDR09 is not set # CONFIG_USB_STORAGE_SDDR55 is not set @@ -1222,6 +1260,10 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# # CONFIG_UWB is not set # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set @@ -1243,7 +1285,6 @@ CONFIG_NEW_LEDS=y # CONFIG_DMADEVICES is not set # CONFIG_UIO is not set # CONFIG_STAGING is not set -CONFIG_STAGING_EXCLUDE_BUILD=y # # File systems @@ -1264,6 +1305,7 @@ CONFIG_FS_MBCACHE=y CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y @@ -1300,10 +1342,7 @@ CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set @@ -1323,6 +1362,7 @@ CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set @@ -1403,6 +1443,7 @@ CONFIG_NLS_ISO8859_1=y # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set # CONFIG_CRC_T10DIF is not set @@ -1454,6 +1495,7 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set @@ -1462,6 +1504,8 @@ CONFIG_DEBUG_INFO=y # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y # # Tracers @@ -1470,11 +1514,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y # CONFIG_SCHED_TRACER is not set # CONFIG_CONTEXT_SWITCH_TRACER is not set # CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set # CONFIG_STACK_TRACER is not set # CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set +CONFIG_PRINT_STACK_DEPTH=64 # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_PAGEALLOC is not set @@ -1501,11 +1547,15 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_CRYPTD is not set diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index da5a385..19b12d2 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -16,8 +16,6 @@ * 2 of the License, or (at your option) any later version. */ -#define DEBUG - #include <linux/kernel.h> #include <linux/pci.h> #include <linux/string.h> @@ -258,7 +256,8 @@ int pci_read_irq_line(struct pci_dev *pci_dev) } else { pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n", oirq.size, oirq.specifier[0], oirq.specifier[1], - oirq.controller->full_name); + oirq.controller ? oirq.controller->full_name : + "<default>"); virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c index c3f2c21..87ff522 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c @@ -20,14 +20,6 @@ /* ======================================================================== */ -/* PCI windows config */ -/* ======================================================================== */ - -#define MPC52xx_PCI_TARGET_IO 0xf0000000 -#define MPC52xx_PCI_TARGET_MEM 0x00000000 - - -/* ======================================================================== */ /* Structures mapping & Defines for PCI Unit */ /* ======================================================================== */ @@ -244,7 +236,7 @@ static struct pci_ops mpc52xx_pci_ops = { static void __init mpc52xx_pci_setup(struct pci_controller *hose, - struct mpc52xx_pci __iomem *pci_regs) + struct mpc52xx_pci __iomem *pci_regs, phys_addr_t pci_phys) { struct resource *res; u32 tmp; @@ -314,10 +306,14 @@ mpc52xx_pci_setup(struct pci_controller *hose, /* Set all the IWCR fields at once; they're in the same reg */ out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2)); - out_be32(&pci_regs->tbatr0, - MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO ); - out_be32(&pci_regs->tbatr1, - MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM ); + /* Map IMMR onto PCI bus */ + pci_phys &= 0xfffc0000; /* bar0 has only 14 significant bits */ + out_be32(&pci_regs->tbatr0, MPC52xx_PCI_TBATR_ENABLE | pci_phys); + out_be32(&pci_regs->bar0, PCI_BASE_ADDRESS_MEM_PREFETCH | pci_phys); + + /* Map memory onto PCI bus */ + out_be32(&pci_regs->tbatr1, MPC52xx_PCI_TBATR_ENABLE); + out_be32(&pci_regs->bar1, PCI_BASE_ADDRESS_MEM_PREFETCH); out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD | MPC52xx_PCI_TCR_WCT8); @@ -414,7 +410,7 @@ mpc52xx_add_bridge(struct device_node *node) /* Finish setting up PCI using values obtained by * pci_proces_bridge_OF_ranges */ - mpc52xx_pci_setup(hose, pci_regs); + mpc52xx_pci_setup(hose, pci_regs, rsrc.start); return 0; } diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c index caf4c33..7c35787 100644 --- a/arch/sh/boards/board-ap325rxa.c +++ b/arch/sh/boards/board-ap325rxa.c @@ -22,6 +22,7 @@ #include <linux/gpio.h> #include <linux/spi/spi.h> #include <linux/spi/spi_gpio.h> +#include <media/ov772x.h> #include <media/soc_camera_platform.h> #include <media/sh_mobile_ceu.h> #include <video/sh_mobile_lcdc.h> @@ -216,7 +217,14 @@ static struct platform_device lcdc_device = { }, }; +static void camera_power(int val) +{ + gpio_set_value(GPIO_PTZ5, val); /* RST_CAM/RSTB */ + mdelay(10); +} + #ifdef CONFIG_I2C +/* support for the old ncm03j camera */ static unsigned char camera_ncm03j_magic[] = { 0x87, 0x00, 0x88, 0x08, 0x89, 0x01, 0x8A, 0xE8, @@ -237,6 +245,23 @@ static unsigned char camera_ncm03j_magic[] = 0x63, 0xD4, 0x64, 0xEA, 0xD6, 0x0F, }; +static int camera_probe(void) +{ + struct i2c_adapter *a = i2c_get_adapter(0); + struct i2c_msg msg; + int ret; + + camera_power(1); + msg.addr = 0x6e; + msg.buf = camera_ncm03j_magic; + msg.len = 2; + msg.flags = 0; + ret = i2c_transfer(a, &msg, 1); + camera_power(0); + + return ret; +} + static int camera_set_capture(struct soc_camera_platform_info *info, int enable) { @@ -245,9 +270,11 @@ static int camera_set_capture(struct soc_camera_platform_info *info, int ret = 0; int i; + camera_power(0); if (!enable) return 0; /* no disable for now */ + camera_power(1); for (i = 0; i < ARRAY_SIZE(camera_ncm03j_magic); i += 2) { u_int8_t buf[8]; @@ -286,8 +313,35 @@ static struct platform_device camera_device = { .platform_data = &camera_info, }, }; + +static int __init camera_setup(void) +{ + if (camera_probe() > 0) + platform_device_register(&camera_device); + + return 0; +} +late_initcall(camera_setup); + #endif /* CONFIG_I2C */ +static int ov7725_power(struct device *dev, int mode) +{ + camera_power(0); + if (mode) + camera_power(1); + + return 0; +} + +static struct ov772x_camera_info ov7725_info = { + .buswidth = SOCAM_DATAWIDTH_8, + .flags = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP, + .link = { + .power = ov7725_power, + }, +}; + static struct sh_mobile_ceu_info sh_mobile_ceu_info = { .flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8, @@ -338,9 +392,6 @@ static struct platform_device *ap325rxa_devices[] __initdata = { &ap325rxa_nor_flash_device, &lcdc_device, &ceu_device, -#ifdef CONFIG_I2C - &camera_device, -#endif &nand_flash_device, &sdcard_cn3_device, }; @@ -349,6 +400,10 @@ static struct i2c_board_info __initdata ap325rxa_i2c_devices[] = { { I2C_BOARD_INFO("pcf8563", 0x51), }, + { + I2C_BOARD_INFO("ov772x", 0x21), + .platform_data = &ov7725_info, + }, }; static struct spi_board_info ap325rxa_spi_devices[] = { @@ -426,7 +481,7 @@ static int __init ap325rxa_devices_setup(void) gpio_request(GPIO_PTZ6, NULL); gpio_direction_output(GPIO_PTZ6, 0); /* STBY_CAM */ gpio_request(GPIO_PTZ5, NULL); - gpio_direction_output(GPIO_PTZ5, 1); /* RST_CAM */ + gpio_direction_output(GPIO_PTZ5, 0); /* RST_CAM */ gpio_request(GPIO_PTZ4, NULL); gpio_direction_output(GPIO_PTZ4, 0); /* SADDR */ diff --git a/arch/sh/configs/ap325rxa_defconfig b/arch/sh/configs/ap325rxa_defconfig index 5c423fa..352f87d 100644 --- a/arch/sh/configs/ap325rxa_defconfig +++ b/arch/sh/configs/ap325rxa_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28 -# Fri Jan 9 16:54:19 2009 +# Linux kernel version: 2.6.29-rc2 +# Tue Jan 27 11:45:08 2009 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -45,12 +45,12 @@ CONFIG_BSD_PROCESS_ACCT=y # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set CONFIG_GROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y # CONFIG_RT_GROUP_SCHED is not set CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set @@ -378,6 +378,7 @@ CONFIG_WIRELESS=y # CONFIG_WIRELESS_EXT is not set # CONFIG_LIB80211 is not set # CONFIG_MAC80211 is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -400,6 +401,7 @@ CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set CONFIG_MTD_CONCAT=y CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AR7_PARTS is not set @@ -447,9 +449,7 @@ CONFIG_MTD_CFI_UTIL=y # # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0xffffffff -CONFIG_MTD_PHYSMAP_LEN=0 -CONFIG_MTD_PHYSMAP_BANKWIDTH=0 +# CONFIG_MTD_PHYSMAP_COMPAT is not set # CONFIG_MTD_PLATRAM is not set # @@ -480,6 +480,12 @@ CONFIG_MTD_NAND_SH_FLCTL=y # CONFIG_MTD_ONENAND is not set # +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_QINFO_PROBE is not set + +# # UBI - Unsorted block images # CONFIG_MTD_UBI=y @@ -607,6 +613,10 @@ CONFIG_SMSC911X=y # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set # CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -790,6 +800,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set # CONFIG_REGULATOR is not set # @@ -837,7 +848,7 @@ CONFIG_SOC_CAMERA=y # CONFIG_SOC_CAMERA_MT9V022 is not set # CONFIG_SOC_CAMERA_TW9910 is not set CONFIG_SOC_CAMERA_PLATFORM=y -# CONFIG_SOC_CAMERA_OV772X is not set +CONFIG_SOC_CAMERA_OV772X=y CONFIG_VIDEO_SH_MOBILE_CEU=y # CONFIG_RADIO_ADAPTERS is not set # CONFIG_DAB is not set @@ -1012,6 +1023,7 @@ CONFIG_FS_POSIX_ACL=y CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y @@ -1060,6 +1072,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_JFFS2_FS is not set # CONFIG_UBIFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set diff --git a/arch/sh/configs/migor_defconfig b/arch/sh/configs/migor_defconfig index 7758263..6785767 100644 --- a/arch/sh/configs/migor_defconfig +++ b/arch/sh/configs/migor_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.28 -# Fri Jan 9 17:09:35 2009 +# Linux kernel version: 2.6.29-rc1 +# Thu Jan 22 09:16:16 2009 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -45,8 +45,12 @@ CONFIG_SYSVIPC_SYSCTL=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set + +# +# Control Group support +# +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set @@ -389,6 +393,7 @@ CONFIG_WIRELESS_EXT=y CONFIG_WIRELESS_EXT_SYSFS=y # CONFIG_LIB80211 is not set # CONFIG_MAC80211 is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -411,6 +416,7 @@ CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set CONFIG_MTD_CONCAT=y CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AR7_PARTS is not set @@ -458,9 +464,7 @@ CONFIG_MTD_CFI_UTIL=y # # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0xffffffff -CONFIG_MTD_PHYSMAP_LEN=0 -CONFIG_MTD_PHYSMAP_BANKWIDTH=0 +# CONFIG_MTD_PHYSMAP_COMPAT is not set # CONFIG_MTD_PLATRAM is not set # @@ -488,6 +492,12 @@ CONFIG_MTD_NAND_PLATFORM=y # CONFIG_MTD_ONENAND is not set # +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_QINFO_PROBE is not set + +# # UBI - Unsorted block images # # CONFIG_MTD_UBI is not set @@ -587,6 +597,10 @@ CONFIG_SMC91X=y # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set # CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -761,6 +775,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set # CONFIG_REGULATOR is not set # @@ -806,9 +821,9 @@ CONFIG_SOC_CAMERA=y # CONFIG_SOC_CAMERA_MT9M111 is not set # CONFIG_SOC_CAMERA_MT9T031 is not set # CONFIG_SOC_CAMERA_MT9V022 is not set -# CONFIG_SOC_CAMERA_TW9910 is not set -CONFIG_SOC_CAMERA_PLATFORM=y -# CONFIG_SOC_CAMERA_OV772X is not set +CONFIG_SOC_CAMERA_TW9910=y +# CONFIG_SOC_CAMERA_PLATFORM is not set +CONFIG_SOC_CAMERA_OV772X=y CONFIG_VIDEO_SH_MOBILE_CEU=y # CONFIG_RADIO_ADAPTERS is not set # CONFIG_DAB is not set @@ -866,11 +881,13 @@ CONFIG_USB_GADGET_SELECTED=y # CONFIG_USB_GADGET_PXA25X is not set # CONFIG_USB_GADGET_PXA27X is not set # CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_IMX is not set CONFIG_USB_GADGET_M66592=y CONFIG_USB_M66592=y CONFIG_SUPERH_BUILT_IN_M66592=y # CONFIG_USB_GADGET_AMD5536UDC is not set # CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_CI13XXX is not set # CONFIG_USB_GADGET_NET2280 is not set # CONFIG_USB_GADGET_GOKU is not set # CONFIG_USB_GADGET_DUMMY_HCD is not set @@ -883,6 +900,11 @@ CONFIG_USB_G_SERIAL=y # CONFIG_USB_MIDI_GADGET is not set # CONFIG_USB_G_PRINTER is not set # CONFIG_USB_CDC_COMPOSITE is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set @@ -961,6 +983,7 @@ CONFIG_UIO_PDRV_GENIRQ=y CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set # CONFIG_DNOTIFY is not set # CONFIG_INOTIFY is not set # CONFIG_QUOTA is not set @@ -1004,6 +1027,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set diff --git a/arch/sh/include/asm/mutex-llsc.h b/arch/sh/include/asm/mutex-llsc.h index ee839ee..090358a 100644 --- a/arch/sh/include/asm/mutex-llsc.h +++ b/arch/sh/include/asm/mutex-llsc.h @@ -21,38 +21,36 @@ static inline void __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) { - int __ex_flag, __res; + int __done, __res; __asm__ __volatile__ ( "movli.l @%2, %0 \n" "add #-1, %0 \n" "movco.l %0, @%2 \n" "movt %1 \n" - : "=&z" (__res), "=&r" (__ex_flag) + : "=&z" (__res), "=&r" (__done) : "r" (&(count)->counter) : "t"); - __res |= !__ex_flag; - if (unlikely(__res != 0)) + if (unlikely(!__done || __res != 0)) fail_fn(count); } static inline int __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) { - int __ex_flag, __res; + int __done, __res; __asm__ __volatile__ ( "movli.l @%2, %0 \n" "add #-1, %0 \n" "movco.l %0, @%2 \n" "movt %1 \n" - : "=&z" (__res), "=&r" (__ex_flag) + : "=&z" (__res), "=&r" (__done) : "r" (&(count)->counter) : "t"); - __res |= !__ex_flag; - if (unlikely(__res != 0)) + if (unlikely(!__done || __res != 0)) __res = fail_fn(count); return __res; @@ -61,19 +59,18 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) static inline void __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *)) { - int __ex_flag, __res; + int __done, __res; __asm__ __volatile__ ( "movli.l @%2, %0 \n\t" "add #1, %0 \n\t" "movco.l %0, @%2 \n\t" "movt %1 \n\t" - : "=&z" (__res), "=&r" (__ex_flag) + : "=&z" (__res), "=&r" (__done) : "r" (&(count)->counter) : "t"); - __res |= !__ex_flag; - if (unlikely(__res <= 0)) + if (unlikely(!__done || __res <= 0)) fail_fn(count); } diff --git a/arch/sh/include/asm/syscall_32.h b/arch/sh/include/asm/syscall_32.h index 05a868a..5bc3468 100644 --- a/arch/sh/include/asm/syscall_32.h +++ b/arch/sh/include/asm/syscall_32.h @@ -21,23 +21,10 @@ static inline void syscall_rollback(struct task_struct *task, */ } -static inline bool syscall_has_error(struct pt_regs *regs) -{ - return (regs->sr & 0x1) ? true : false; -} -static inline void syscall_set_error(struct pt_regs *regs) -{ - regs->sr |= 0x1; -} -static inline void syscall_clear_error(struct pt_regs *regs) -{ - regs->sr &= ~0x1; -} - static inline long syscall_get_error(struct task_struct *task, struct pt_regs *regs) { - return syscall_has_error(regs) ? regs->regs[0] : 0; + return IS_ERR_VALUE(regs->regs[0]) ? regs->regs[0] : 0; } static inline long syscall_get_return_value(struct task_struct *task, @@ -50,13 +37,10 @@ static inline void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs, int error, long val) { - if (error) { - syscall_set_error(regs); + if (error) regs->regs[0] = -error; - } else { - syscall_clear_error(regs); + else regs->regs[0] = val; - } } static inline void syscall_get_arguments(struct task_struct *task, diff --git a/arch/sh/include/asm/syscall_64.h b/arch/sh/include/asm/syscall_64.h index e1143b9..c3561ca 100644 --- a/arch/sh/include/asm/syscall_64.h +++ b/arch/sh/include/asm/syscall_64.h @@ -21,23 +21,10 @@ static inline void syscall_rollback(struct task_struct *task, */ } -static inline bool syscall_has_error(struct pt_regs *regs) -{ - return (regs->sr & 0x1) ? true : false; -} -static inline void syscall_set_error(struct pt_regs *regs) -{ - regs->sr |= 0x1; -} -static inline void syscall_clear_error(struct pt_regs *regs) -{ - regs->sr &= ~0x1; -} - static inline long syscall_get_error(struct task_struct *task, struct pt_regs *regs) { - return syscall_has_error(regs) ? regs->regs[9] : 0; + return IS_ERR_VALUE(regs->regs[9]) ? regs->regs[9] : 0; } static inline long syscall_get_return_value(struct task_struct *task, @@ -50,13 +37,10 @@ static inline void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs, int error, long val) { - if (error) { - syscall_set_error(regs); + if (error) regs->regs[9] = -error; - } else { - syscall_clear_error(regs); + else regs->regs[9] = val; - } } static inline void syscall_get_arguments(struct task_struct *task, diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c index 2780917..e3ea541 100644 --- a/arch/sh/kernel/cpu/sh4/fpu.c +++ b/arch/sh/kernel/cpu/sh4/fpu.c @@ -423,7 +423,7 @@ static int ieee_fpe_handler(struct pt_regs *regs) int m; unsigned int hx; - m = (finsn >> 9) & 0x7; + m = (finsn >> 8) & 0x7; hx = tsk->thread.fpu.hard.fp_regs[m]; if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR) diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 5342475..370d2cf 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -262,11 +262,11 @@ void __init setup_bootmem_allocator(unsigned long free_pfn) BOOTMEM_DEFAULT); /* - * reserve physical page 0 - it's a special BIOS page on many boxes, - * enabling clean reboots, SMP operation, laptop functions. + * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET. */ - reserve_bootmem(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET, - BOOTMEM_DEFAULT); + if (CONFIG_ZERO_PAGE_OFFSET != 0) + reserve_bootmem(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET, + BOOTMEM_DEFAULT); sparse_memory_present_with_active_regions(0); diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c index 77c21bd..17784e1 100644 --- a/arch/sh/kernel/signal_32.c +++ b/arch/sh/kernel/signal_32.c @@ -510,7 +510,6 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs, case -ERESTARTNOHAND: no_system_call_restart: regs->regs[0] = -EINTR; - regs->sr |= 1; break; case -ERESTARTSYS: @@ -589,8 +588,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - if (regs->sr & 1) - handle_syscall_restart(save_r0, regs, &ka.sa); + handle_syscall_restart(save_r0, regs, &ka.sa); /* Whee! Actually deliver the signal. */ if (handle_signal(signr, &ka, &info, oldset, diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index b22fdfa..0663a0e 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c @@ -60,7 +60,6 @@ handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa) case -ERESTARTNOHAND: no_system_call_restart: regs->regs[REG_RET] = -EINTR; - regs->sr |= 1; break; case -ERESTARTSYS: @@ -109,8 +108,7 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) signr = get_signal_to_deliver(&info, &ka, regs, 0); if (signr > 0) { - if (regs->sr & 1) - handle_syscall_restart(regs, &ka.sa); + handle_syscall_restart(regs, &ka.sa); /* Whee! Actually deliver the signal. */ if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { diff --git a/arch/sh/lib/checksum.S b/arch/sh/lib/checksum.S index cbdd0d4..356c8ec 100644 --- a/arch/sh/lib/checksum.S +++ b/arch/sh/lib/checksum.S @@ -36,8 +36,7 @@ */ /* - * unsigned int csum_partial(const unsigned char *buf, int len, - * unsigned int sum); + * asmlinkage __wsum csum_partial(const void *buf, int len, __wsum sum); */ .text @@ -49,11 +48,31 @@ ENTRY(csum_partial) * Fortunately, it is easy to convert 2-byte alignment to 4-byte * alignment for the unrolled loop. */ - mov r5, r1 mov r4, r0 - tst #2, r0 ! Check alignment. - bt 2f ! Jump if alignment is ok. + tst #3, r0 ! Check alignment. + bt/s 2f ! Jump if alignment is ok. + mov r4, r7 ! Keep a copy to check for alignment ! + tst #1, r0 ! Check alignment. + bt 21f ! Jump if alignment is boundary of 2bytes. + + ! buf is odd + tst r5, r5 + add #-1, r5 + bt 9f + mov.b @r4+, r0 + extu.b r0, r0 + addc r0, r6 ! t=0 from previous tst + mov r6, r0 + shll8 r6 + shlr16 r0 + shlr8 r0 + or r0, r6 + mov r4, r0 + tst #2, r0 + bt 2f +21: + ! buf is 2 byte aligned (len could be 0) add #-2, r5 ! Alignment uses up two bytes. cmp/pz r5 ! bt/s 1f ! Jump if we had at least two bytes. @@ -61,16 +80,17 @@ ENTRY(csum_partial) bra 6f add #2, r5 ! r5 was < 2. Deal with it. 1: - mov r5, r1 ! Save new len for later use. mov.w @r4+, r0 extu.w r0, r0 addc r0, r6 bf 2f add #1, r6 2: + ! buf is 4 byte aligned (len could be 0) + mov r5, r1 mov #-5, r0 - shld r0, r5 - tst r5, r5 + shld r0, r1 + tst r1, r1 bt/s 4f ! if it's =0, go to 4f clrt .align 2 @@ -92,30 +112,31 @@ ENTRY(csum_partial) addc r0, r6 addc r2, r6 movt r0 - dt r5 + dt r1 bf/s 3b cmp/eq #1, r0 - ! here, we know r5==0 - addc r5, r6 ! add carry to r6 + ! here, we know r1==0 + addc r1, r6 ! add carry to r6 4: - mov r1, r0 + mov r5, r0 and #0x1c, r0 tst r0, r0 - bt/s 6f - mov r0, r5 - shlr2 r5 + bt 6f + ! 4 bytes or more remaining + mov r0, r1 + shlr2 r1 mov #0, r2 5: addc r2, r6 mov.l @r4+, r2 movt r0 - dt r5 + dt r1 bf/s 5b cmp/eq #1, r0 addc r2, r6 - addc r5, r6 ! r5==0 here, so it means add carry-bit + addc r1, r6 ! r1==0 here, so it means add carry-bit 6: - mov r1, r5 + ! 3 bytes or less remaining mov #3, r0 and r0, r5 tst r5, r5 @@ -139,8 +160,18 @@ ENTRY(csum_partial) 8: addc r0, r6 mov #0, r0 - addc r0, r6 + addc r0, r6 9: + ! Check if the buffer was misaligned, if so realign sum + mov r7, r0 + tst #1, r0 + bt 10f + mov r6, r0 + shll8 r6 + shlr16 r0 + shlr8 r0 + or r0, r6 +10: rts mov r6, r0 diff --git a/arch/sparc/include/asm/cpudata_64.h b/arch/sparc/include/asm/cpudata_64.h index 7da7c13..a11b89e 100644 --- a/arch/sparc/include/asm/cpudata_64.h +++ b/arch/sparc/include/asm/cpudata_64.h @@ -17,7 +17,7 @@ typedef struct { /* Dcache line 1 */ unsigned int __softirq_pending; /* must be 1st, see rtrap.S */ - unsigned int __pad0; + unsigned int __nmi_count; unsigned long clock_tick; /* %tick's per second */ unsigned long __pad; unsigned int __pad1; diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h index d47d4a1..1934f2c 100644 --- a/arch/sparc/include/asm/irq_64.h +++ b/arch/sparc/include/asm/irq_64.h @@ -66,9 +66,6 @@ extern void virt_irq_free(unsigned int virt_irq); extern void __init init_IRQ(void); extern void fixup_irqs(void); -extern int register_perfctr_intr(void (*handler)(struct pt_regs *)); -extern void release_perfctr_intr(void (*handler)(struct pt_regs *)); - static inline void set_softint(unsigned long bits) { __asm__ __volatile__("wr %0, 0x0, %%set_softint" @@ -98,5 +95,6 @@ void __trigger_all_cpu_backtrace(void); extern void *hardirq_stack[NR_CPUS]; extern void *softirq_stack[NR_CPUS]; #define __ARCH_HAS_DO_SOFTIRQ +#define ARCH_HAS_NMI_WATCHDOG #endif diff --git a/arch/sparc/include/asm/kdebug_64.h b/arch/sparc/include/asm/kdebug_64.h index f905b77..feb3578 100644 --- a/arch/sparc/include/asm/kdebug_64.h +++ b/arch/sparc/include/asm/kdebug_64.h @@ -14,6 +14,8 @@ enum die_val { DIE_TRAP, DIE_TRAP_TL1, DIE_CALL, + DIE_NMI, + DIE_NMIWATCHDOG, }; #endif diff --git a/arch/sparc/include/asm/nmi.h b/arch/sparc/include/asm/nmi.h new file mode 100644 index 0000000..fbd546d --- /dev/null +++ b/arch/sparc/include/asm/nmi.h @@ -0,0 +1,10 @@ +#ifndef __NMI_H +#define __NMI_H + +extern int __init nmi_init(void); +extern void perfctr_irq(int irq, struct pt_regs *regs); +extern void nmi_adjust_hz(unsigned int new_hz); + +extern int nmi_usable; + +#endif /* __NMI_H */ diff --git a/arch/sparc/include/asm/pcr.h b/arch/sparc/include/asm/pcr.h new file mode 100644 index 0000000..a2f5c61 --- /dev/null +++ b/arch/sparc/include/asm/pcr.h @@ -0,0 +1,46 @@ +#ifndef __PCR_H +#define __PCR_H + +struct pcr_ops { + u64 (*read)(void); + void (*write)(u64); +}; +extern const struct pcr_ops *pcr_ops; + +extern void deferred_pcr_work_irq(int irq, struct pt_regs *regs); +extern void schedule_deferred_pcr_work(void); + +#define PCR_PIC_PRIV 0x00000001 /* PIC access is privileged */ +#define PCR_STRACE 0x00000002 /* Trace supervisor events */ +#define PCR_UTRACE 0x00000004 /* Trace user events */ +#define PCR_N2_HTRACE 0x00000008 /* Trace hypervisor events */ +#define PCR_N2_TOE_OV0 0x00000010 /* Trap if PIC 0 overflows */ +#define PCR_N2_TOE_OV1 0x00000020 /* Trap if PIC 1 overflows */ +#define PCR_N2_MASK0 0x00003fc0 +#define PCR_N2_MASK0_SHIFT 6 +#define PCR_N2_SL0 0x0003c000 +#define PCR_N2_SL0_SHIFT 14 +#define PCR_N2_OV0 0x00040000 +#define PCR_N2_MASK1 0x07f80000 +#define PCR_N2_MASK1_SHIFT 19 +#define PCR_N2_SL1 0x78000000 +#define PCR_N2_SL1_SHIFT 27 +#define PCR_N2_OV1 0x80000000 + +extern unsigned int picl_shift; + +/* In order to commonize as much of the implementation as + * possible, we use PICH as our counter. Mostly this is + * to accomodate Niagara-1 which can only count insn cycles + * in PICH. + */ +static inline u64 picl_value(unsigned int nmi_hz) +{ + u32 delta = local_cpu_data().clock_tick / (nmi_hz << picl_shift); + + return ((u64)((0 - delta) & 0xffffffff)) << 32; +} + +extern u64 pcr_enable; + +#endif /* __PCR_H */ diff --git a/arch/sparc/include/asm/pil.h b/arch/sparc/include/asm/pil.h index d573820..32a7efe 100644 --- a/arch/sparc/include/asm/pil.h +++ b/arch/sparc/include/asm/pil.h @@ -23,6 +23,7 @@ #define PIL_SMP_CTX_NEW_VERSION 4 #define PIL_DEVICE_IRQ 5 #define PIL_SMP_CALL_FUNC_SNGL 6 +#define PIL_DEFERRED_PCR_WORK 7 #define PIL_NORMAL_MAX 14 #define PIL_NMI 15 diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 53adcaa..54742e5 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -52,6 +52,8 @@ obj-$(CONFIG_SPARC64) += visemul.o obj-$(CONFIG_SPARC64) += hvapi.o obj-$(CONFIG_SPARC64) += sstate.o obj-$(CONFIG_SPARC64) += mdesc.o +obj-$(CONFIG_SPARC64) += pcr.o +obj-$(CONFIG_SPARC64) += nmi.o # sparc32 do not use GENERIC_HARDIRQS but uses the generic devres implementation obj-$(CONFIG_SPARC32) += devres.o diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c index 32d32b4..d85c3dc 100644 --- a/arch/sparc/kernel/cpu.c +++ b/arch/sparc/kernel/cpu.c @@ -26,6 +26,7 @@ EXPORT_PER_CPU_SYMBOL(__cpu_data); struct cpu_info { int psr_vers; const char *name; + const char *pmu_name; }; struct fpu_info { @@ -45,6 +46,9 @@ struct manufacturer_info { #define CPU(ver, _name) \ { .psr_vers = ver, .name = _name } +#define CPU_PMU(ver, _name, _pmu_name) \ +{ .psr_vers = ver, .name = _name, .pmu_name = _pmu_name } + #define FPU(ver, _name) \ { .fp_vers = ver, .name = _name } @@ -183,10 +187,10 @@ static const struct manufacturer_info __initconst manufacturer_info[] = { },{ 0x17, .cpu_info = { - CPU(0x10, "TI UltraSparc I (SpitFire)"), - CPU(0x11, "TI UltraSparc II (BlackBird)"), - CPU(0x12, "TI UltraSparc IIi (Sabre)"), - CPU(0x13, "TI UltraSparc IIe (Hummingbird)"), + CPU_PMU(0x10, "TI UltraSparc I (SpitFire)", "ultra12"), + CPU_PMU(0x11, "TI UltraSparc II (BlackBird)", "ultra12"), + CPU_PMU(0x12, "TI UltraSparc IIi (Sabre)", "ultra12"), + CPU_PMU(0x13, "TI UltraSparc IIe (Hummingbird)", "ultra12"), CPU(-1, NULL) }, .fpu_info = { @@ -199,7 +203,7 @@ static const struct manufacturer_info __initconst manufacturer_info[] = { },{ 0x22, .cpu_info = { - CPU(0x10, "TI UltraSparc I (SpitFire)"), + CPU_PMU(0x10, "TI UltraSparc I (SpitFire)", "ultra12"), CPU(-1, NULL) }, .fpu_info = { @@ -209,12 +213,12 @@ static const struct manufacturer_info __initconst manufacturer_info[] = { },{ 0x3e, .cpu_info = { - CPU(0x14, "TI UltraSparc III (Cheetah)"), - CPU(0x15, "TI UltraSparc III+ (Cheetah+)"), - CPU(0x16, "TI UltraSparc IIIi (Jalapeno)"), - CPU(0x18, "TI UltraSparc IV (Jaguar)"), - CPU(0x19, "TI UltraSparc IV+ (Panther)"), - CPU(0x22, "TI UltraSparc IIIi+ (Serrano)"), + CPU_PMU(0x14, "TI UltraSparc III (Cheetah)", "ultra3"), + CPU_PMU(0x15, "TI UltraSparc III+ (Cheetah+)", "ultra3+"), + CPU_PMU(0x16, "TI UltraSparc IIIi (Jalapeno)", "ultra3i"), + CPU_PMU(0x18, "TI UltraSparc IV (Jaguar)", "ultra3+"), + CPU_PMU(0x19, "TI UltraSparc IV+ (Panther)", "ultra4+"), + CPU_PMU(0x22, "TI UltraSparc IIIi+ (Serrano)", "ultra3i"), CPU(-1, NULL) }, .fpu_info = { @@ -234,6 +238,7 @@ static const struct manufacturer_info __initconst manufacturer_info[] = { const char *sparc_cpu_type; const char *sparc_fpu_type; +const char *sparc_pmu_type; unsigned int fsr_storage; @@ -244,6 +249,7 @@ static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) sparc_cpu_type = NULL; sparc_fpu_type = NULL; + sparc_pmu_type = NULL; manuf = NULL; for (i = 0; i < ARRAY_SIZE(manufacturer_info); i++) @@ -263,6 +269,7 @@ static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) { if (cpu->psr_vers == psr_vers) { sparc_cpu_type = cpu->name; + sparc_pmu_type = cpu->pmu_name; sparc_fpu_type = "No FPU"; break; } @@ -290,6 +297,8 @@ static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) psr_impl, fpu_vers); sparc_fpu_type = "Unknown FPU"; } + if (sparc_pmu_type == NULL) + sparc_pmu_type = "Unknown PMU"; } #ifdef CONFIG_SPARC32 @@ -315,11 +324,13 @@ static void __init sun4v_cpu_probe(void) case SUN4V_CHIP_NIAGARA1: sparc_cpu_type = "UltraSparc T1 (Niagara)"; sparc_fpu_type = "UltraSparc T1 integrated FPU"; + sparc_pmu_type = "niagara"; break; case SUN4V_CHIP_NIAGARA2: sparc_cpu_type = "UltraSparc T2 (Niagara2)"; sparc_fpu_type = "UltraSparc T2 integrated FPU"; + sparc_pmu_type = "niagara2"; break; default: diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index 4ac5c65..3d2c6ba 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c @@ -196,6 +196,11 @@ int show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); + } else if (i == NR_IRQS) { + seq_printf(p, "NMI: "); + for_each_online_cpu(j) + seq_printf(p, "%10u ", cpu_data(j).__nmi_count); + seq_printf(p, " Non-maskable interrupts\n"); } return 0; } @@ -779,69 +784,6 @@ void do_softirq(void) local_irq_restore(flags); } -static void unhandled_perf_irq(struct pt_regs *regs) -{ - unsigned long pcr, pic; - - read_pcr(pcr); - read_pic(pic); - - write_pcr(0); - - printk(KERN_EMERG "CPU %d: Got unexpected perf counter IRQ.\n", - smp_processor_id()); - printk(KERN_EMERG "CPU %d: PCR[%016lx] PIC[%016lx]\n", - smp_processor_id(), pcr, pic); -} - -/* Almost a direct copy of the powerpc PMC code. */ -static DEFINE_SPINLOCK(perf_irq_lock); -static void *perf_irq_owner_caller; /* mostly for debugging */ -static void (*perf_irq)(struct pt_regs *regs) = unhandled_perf_irq; - -/* Invoked from level 15 PIL handler in trap table. */ -void perfctr_irq(int irq, struct pt_regs *regs) -{ - clear_softint(1 << irq); - perf_irq(regs); -} - -int register_perfctr_intr(void (*handler)(struct pt_regs *)) -{ - int ret; - - if (!handler) - return -EINVAL; - - spin_lock(&perf_irq_lock); - if (perf_irq != unhandled_perf_irq) { - printk(KERN_WARNING "register_perfctr_intr: " - "perf IRQ busy (reserved by caller %p)\n", - perf_irq_owner_caller); - ret = -EBUSY; - goto out; - } - - perf_irq_owner_caller = __builtin_return_address(0); - perf_irq = handler; - - ret = 0; -out: - spin_unlock(&perf_irq_lock); - - return ret; -} -EXPORT_SYMBOL_GPL(register_perfctr_intr); - -void release_perfctr_intr(void (*handler)(struct pt_regs *)) -{ - spin_lock(&perf_irq_lock); - perf_irq_owner_caller = NULL; - perf_irq = unhandled_perf_irq; - spin_unlock(&perf_irq_lock); -} -EXPORT_SYMBOL_GPL(release_perfctr_intr); - #ifdef CONFIG_HOTPLUG_CPU void fixup_irqs(void) { diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index 81a972e..15d8a3f 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h @@ -5,6 +5,7 @@ /* cpu.c */ extern const char *sparc_cpu_type; +extern const char *sparc_pmu_type; extern const char *sparc_fpu_type; extern unsigned int fsr_storage; diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c new file mode 100644 index 0000000..09f088e --- /dev/null +++ b/arch/sparc/kernel/nmi.c @@ -0,0 +1,224 @@ +/* Pseudo NMI support on sparc64 systems. + * + * Copyright (C) 2009 David S. Miller <davem@davemloft.net> + * + * The NMI watchdog support and infrastructure is based almost + * entirely upon the x86 NMI support code. + */ +#include <linux/kernel.h> +#include <linux/param.h> +#include <linux/init.h> +#include <linux/percpu.h> +#include <linux/nmi.h> +#include <linux/module.h> +#include <linux/kprobes.h> +#include <linux/kernel_stat.h> +#include <linux/slab.h> +#include <linux/kdebug.h> +#include <linux/delay.h> +#include <linux/smp.h> + +#include <asm/ptrace.h> +#include <asm/local.h> +#include <asm/pcr.h> + +/* We don't have a real NMI on sparc64, but we can fake one + * up using profiling counter overflow interrupts and interrupt + * levels. + * + * The profile overflow interrupts at level 15, so we use + * level 14 as our IRQ off level. + */ + +static int nmi_watchdog_active; +static int panic_on_timeout; + +int nmi_usable; +EXPORT_SYMBOL_GPL(nmi_usable); + +static unsigned int nmi_hz = HZ; + +static DEFINE_PER_CPU(unsigned int, last_irq_sum); +static DEFINE_PER_CPU(local_t, alert_counter); +static DEFINE_PER_CPU(int, nmi_touch); + +void touch_nmi_watchdog(void) +{ + if (nmi_watchdog_active) { + int cpu; + + for_each_present_cpu(cpu) { + if (per_cpu(nmi_touch, cpu) != 1) + per_cpu(nmi_touch, cpu) = 1; + } + } + + touch_softlockup_watchdog(); +} +EXPORT_SYMBOL(touch_nmi_watchdog); + +static void die_nmi(const char *str, struct pt_regs *regs, int do_panic) +{ + if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, + pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP) + return; + + console_verbose(); + bust_spinlocks(1); + + printk(KERN_EMERG "%s", str); + printk(" on CPU%d, ip %08lx, registers:\n", + smp_processor_id(), regs->tpc); + show_regs(regs); + + bust_spinlocks(0); + + if (do_panic || panic_on_oops) + panic("Non maskable interrupt"); + + local_irq_enable(); + do_exit(SIGBUS); +} + +notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) +{ + unsigned int sum, touched = 0; + int cpu = smp_processor_id(); + + clear_softint(1 << irq); + pcr_ops->write(PCR_PIC_PRIV); + + local_cpu_data().__nmi_count++; + + if (notify_die(DIE_NMI, "nmi", regs, 0, + pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP) + touched = 1; + + sum = kstat_irqs_cpu(0, cpu); + if (__get_cpu_var(nmi_touch)) { + __get_cpu_var(nmi_touch) = 0; + touched = 1; + } + if (!touched && __get_cpu_var(last_irq_sum) == sum) { + local_inc(&__get_cpu_var(alert_counter)); + if (local_read(&__get_cpu_var(alert_counter)) == 5 * nmi_hz) + die_nmi("BUG: NMI Watchdog detected LOCKUP", + regs, panic_on_timeout); + } else { + __get_cpu_var(last_irq_sum) = sum; + local_set(&__get_cpu_var(alert_counter), 0); + } + if (nmi_usable) { + write_pic(picl_value(nmi_hz)); + pcr_ops->write(pcr_enable); + } +} + +static inline unsigned int get_nmi_count(int cpu) +{ + return cpu_data(cpu).__nmi_count; +} + +static int endflag __initdata; + +static __init void nmi_cpu_busy(void *data) +{ + local_irq_enable_in_hardirq(); + while (endflag == 0) + mb(); +} + +static void report_broken_nmi(int cpu, int *prev_nmi_count) +{ + printk(KERN_CONT "\n"); + + printk(KERN_WARNING + "WARNING: CPU#%d: NMI appears to be stuck (%d->%d)!\n", + cpu, prev_nmi_count[cpu], get_nmi_count(cpu)); + + printk(KERN_WARNING + "Please report this to bugzilla.kernel.org,\n"); + printk(KERN_WARNING + "and attach the output of the 'dmesg' command.\n"); + + nmi_usable = 0; +} + +static void stop_watchdog(void *unused) +{ + pcr_ops->write(PCR_PIC_PRIV); +} + +static int __init check_nmi_watchdog(void) +{ + unsigned int *prev_nmi_count; + int cpu, err; + + prev_nmi_count = kmalloc(nr_cpu_ids * sizeof(unsigned int), GFP_KERNEL); + if (!prev_nmi_count) { + err = -ENOMEM; + goto error; + } + + printk(KERN_INFO "Testing NMI watchdog ... "); + + smp_call_function(nmi_cpu_busy, (void *)&endflag, 0); + + for_each_possible_cpu(cpu) + prev_nmi_count[cpu] = get_nmi_count(cpu); + local_irq_enable(); + mdelay((20 * 1000) / nmi_hz); /* wait 20 ticks */ + + for_each_online_cpu(cpu) { + if (get_nmi_count(cpu) - prev_nmi_count[cpu] <= 5) + report_broken_nmi(cpu, prev_nmi_count); + } + endflag = 1; + if (!nmi_usable) { + kfree(prev_nmi_count); + err = -ENODEV; + goto error; + } + printk("OK.\n"); + + nmi_hz = 1; + + kfree(prev_nmi_count); + return 0; +error: + on_each_cpu(stop_watchdog, NULL, 1); + return err; +} + +static void start_watchdog(void *unused) +{ + pcr_ops->write(PCR_PIC_PRIV); + write_pic(picl_value(nmi_hz)); + + pcr_ops->write(pcr_enable); +} + +void nmi_adjust_hz(unsigned int new_hz) +{ + nmi_hz = new_hz; + on_each_cpu(start_watchdog, NULL, 1); +} +EXPORT_SYMBOL_GPL(nmi_adjust_hz); + +int __init nmi_init(void) +{ + nmi_usable = 1; + + on_each_cpu(start_watchdog, NULL, 1); + + return check_nmi_watchdog(); +} + +static int __init setup_nmi_watchdog(char *str) +{ + if (!strncmp(str, "panic", 5)) + panic_on_timeout = 1; + + return 0; +} +__setup("nmi_watchdog=", setup_nmi_watchdog); diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c new file mode 100644 index 0000000..92e0dda --- /dev/null +++ b/arch/sparc/kernel/pcr.c @@ -0,0 +1,153 @@ +/* pcr.c: Generic sparc64 performance counter infrastructure. + * + * Copyright (C) 2009 David S. Miller (davem@davemloft.net) + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/irq.h> + +#include <asm/pil.h> +#include <asm/pcr.h> +#include <asm/nmi.h> + +/* This code is shared between various users of the performance + * counters. Users will be oprofile, pseudo-NMI watchdog, and the + * perf_counter support layer. + */ + +#define PCR_SUN4U_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE) +#define PCR_N2_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE | \ + PCR_N2_TOE_OV1 | \ + (2 << PCR_N2_SL1_SHIFT) | \ + (0xff << PCR_N2_MASK1_SHIFT)) + +u64 pcr_enable; +unsigned int picl_shift; + +/* Performance counter interrupts run unmasked at PIL level 15. + * Therefore we can't do things like wakeups and other work + * that expects IRQ disabling to be adhered to in locking etc. + * + * Therefore in such situations we defer the work by signalling + * a lower level cpu IRQ. + */ +void deferred_pcr_work_irq(int irq, struct pt_regs *regs) +{ + clear_softint(1 << PIL_DEFERRED_PCR_WORK); +} + +void schedule_deferred_pcr_work(void) +{ + set_softint(1 << PIL_DEFERRED_PCR_WORK); +} + +const struct pcr_ops *pcr_ops; +EXPORT_SYMBOL_GPL(pcr_ops); + +static u64 direct_pcr_read(void) +{ + u64 val; + + read_pcr(val); + return val; +} + +static void direct_pcr_write(u64 val) +{ + write_pcr(val); +} + +static const struct pcr_ops direct_pcr_ops = { + .read = direct_pcr_read, + .write = direct_pcr_write, +}; + +static void n2_pcr_write(u64 val) +{ + unsigned long ret; + + ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val); + if (val != HV_EOK) + write_pcr(val); +} + +static const struct pcr_ops n2_pcr_ops = { + .read = direct_pcr_read, + .write = n2_pcr_write, +}; + +static unsigned long perf_hsvc_group; +static unsigned long perf_hsvc_major; +static unsigned long perf_hsvc_minor; + +static int __init register_perf_hsvc(void) +{ + if (tlb_type == hypervisor) { + switch (sun4v_chip_type) { + case SUN4V_CHIP_NIAGARA1: + perf_hsvc_group = HV_GRP_NIAG_PERF; + break; + + case SUN4V_CHIP_NIAGARA2: + perf_hsvc_group = HV_GRP_N2_CPU; + break; + + default: + return -ENODEV; + } + + + perf_hsvc_major = 1; + perf_hsvc_minor = 0; + if (sun4v_hvapi_register(perf_hsvc_group, + perf_hsvc_major, + &perf_hsvc_minor)) { + printk("perfmon: Could not register hvapi.\n"); + return -ENODEV; + } + } + return 0; +} + +static void __init unregister_perf_hsvc(void) +{ + if (tlb_type != hypervisor) + return; + sun4v_hvapi_unregister(perf_hsvc_group); +} + +int __init pcr_arch_init(void) +{ + int err = register_perf_hsvc(); + + if (err) + return err; + + switch (tlb_type) { + case hypervisor: + pcr_ops = &n2_pcr_ops; + pcr_enable = PCR_N2_ENABLE; + picl_shift = 2; + break; + + case cheetah: + case cheetah_plus: + case spitfire: + pcr_ops = &direct_pcr_ops; + pcr_enable = PCR_SUN4U_ENABLE; + break; + + default: + err = -ENODEV; + goto out_unregister; + } + + return nmi_init(); + +out_unregister: + unregister_perf_hsvc(); + return err; +} + +arch_initcall(pcr_arch_init); diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index cc8b560..a73954b 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -29,6 +29,7 @@ #include <linux/cpu.h> #include <linux/elfcore.h> #include <linux/sysrq.h> +#include <linux/nmi.h> #include <asm/uaccess.h> #include <asm/system.h> @@ -52,8 +53,10 @@ static void sparc64_yield(int cpu) { - if (tlb_type != hypervisor) + if (tlb_type != hypervisor) { + touch_nmi_watchdog(); return; + } clear_thread_flag(TIF_POLLING_NRFLAG); smp_mb__after_clear_bit(); diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 49d061f..f2bcfd2 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -354,6 +354,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused) seq_printf(m, "cpu\t\t: %s\n" "fpu\t\t: %s\n" + "pmu\t\t: %s\n" "prom\t\t: %s\n" "type\t\t: %s\n" "ncpus probed\t: %d\n" @@ -366,6 +367,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused) , sparc_cpu_type, sparc_fpu_type, + sparc_pmu_type, prom_version, ((tlb_type == hypervisor) ? "sun4v" : diff --git a/arch/sparc/kernel/ttable.S b/arch/sparc/kernel/ttable.S index ea92550..d9bdfb9 100644 --- a/arch/sparc/kernel/ttable.S +++ b/arch/sparc/kernel/ttable.S @@ -63,7 +63,8 @@ tl0_irq6: TRAP_IRQ(smp_call_function_single_client, 6) #else tl0_irq6: BTRAP(0x46) #endif -tl0_irq7: BTRAP(0x47) BTRAP(0x48) BTRAP(0x49) +tl0_irq7: TRAP_IRQ(deferred_pcr_work_irq, 7) +tl0_irq8: BTRAP(0x48) BTRAP(0x49) tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d) tl0_irq14: TRAP_IRQ(timer_interrupt, 14) tl0_irq15: TRAP_NMI_IRQ(perfctr_irq, 15) diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index a9e474b..4ab8993 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c @@ -19,6 +19,7 @@ #include <linux/interrupt.h> #include <linux/kprobes.h> #include <linux/kdebug.h> +#include <linux/percpu.h> #include <asm/page.h> #include <asm/pgtable.h> @@ -224,6 +225,30 @@ cannot_handle: unhandled_fault (address, current, regs); } +static void noinline bogus_32bit_fault_tpc(struct pt_regs *regs) +{ + static int times; + + if (times++ < 10) + printk(KERN_ERR "FAULT[%s:%d]: 32-bit process reports " + "64-bit TPC [%lx]\n", + current->comm, current->pid, + regs->tpc); + show_regs(regs); +} + +static void noinline bogus_32bit_fault_address(struct pt_regs *regs, + unsigned long addr) +{ + static int times; + + if (times++ < 10) + printk(KERN_ERR "FAULT[%s:%d]: 32-bit process " + "reports 64-bit fault address [%lx]\n", + current->comm, current->pid, addr); + show_regs(regs); +} + asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) { struct mm_struct *mm = current->mm; @@ -244,6 +269,19 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) (fault_code & FAULT_CODE_DTLB)) BUG(); + if (test_thread_flag(TIF_32BIT)) { + if (!(regs->tstate & TSTATE_PRIV)) { + if (unlikely((regs->tpc >> 32) != 0)) { + bogus_32bit_fault_tpc(regs); + goto intr_or_no_mm; + } + } + if (unlikely((address >> 32) != 0)) { + bogus_32bit_fault_address(regs, address); + goto intr_or_no_mm; + } + } + if (regs->tstate & TSTATE_PRIV) { unsigned long tpc = regs->tpc; @@ -264,12 +302,6 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) if (in_atomic() || !mm) goto intr_or_no_mm; - if (test_thread_flag(TIF_32BIT)) { - if (!(regs->tstate & TSTATE_PRIV)) - regs->tpc &= 0xffffffff; - address &= 0xffffffff; - } - if (!down_read_trylock(&mm->mmap_sem)) { if ((regs->tstate & TSTATE_PRIV) && !search_exception_tables(regs->tpc)) { diff --git a/arch/sparc/oprofile/init.c b/arch/sparc/oprofile/init.c index d6e170c..d172f86 100644 --- a/arch/sparc/oprofile/init.c +++ b/arch/sparc/oprofile/init.c @@ -13,217 +13,57 @@ #include <linux/init.h> #ifdef CONFIG_SPARC64 -#include <asm/hypervisor.h> -#include <asm/spitfire.h> -#include <asm/cpudata.h> -#include <asm/irq.h> +#include <linux/notifier.h> +#include <linux/rcupdate.h> +#include <linux/kdebug.h> +#include <asm/nmi.h> -static int nmi_enabled; - -struct pcr_ops { - u64 (*read)(void); - void (*write)(u64); -}; -static const struct pcr_ops *pcr_ops; - -static u64 direct_pcr_read(void) -{ - u64 val; - - read_pcr(val); - return val; -} - -static void direct_pcr_write(u64 val) -{ - write_pcr(val); -} - -static const struct pcr_ops direct_pcr_ops = { - .read = direct_pcr_read, - .write = direct_pcr_write, -}; - -static void n2_pcr_write(u64 val) +static int profile_timer_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data) { - unsigned long ret; - - ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val); - if (val != HV_EOK) - write_pcr(val); -} - -static const struct pcr_ops n2_pcr_ops = { - .read = direct_pcr_read, - .write = n2_pcr_write, -}; - -/* In order to commonize as much of the implementation as - * possible, we use PICH as our counter. Mostly this is - * to accomodate Niagara-1 which can only count insn cycles - * in PICH. - */ -static u64 picl_value(void) -{ - u32 delta = local_cpu_data().clock_tick / HZ; - - return ((u64)((0 - delta) & 0xffffffff)) << 32; -} - -#define PCR_PIC_PRIV 0x00000001 /* PIC access is privileged */ -#define PCR_STRACE 0x00000002 /* Trace supervisor events */ -#define PCR_UTRACE 0x00000004 /* Trace user events */ -#define PCR_N2_HTRACE 0x00000008 /* Trace hypervisor events */ -#define PCR_N2_TOE_OV0 0x00000010 /* Trap if PIC 0 overflows */ -#define PCR_N2_TOE_OV1 0x00000020 /* Trap if PIC 1 overflows */ -#define PCR_N2_MASK0 0x00003fc0 -#define PCR_N2_MASK0_SHIFT 6 -#define PCR_N2_SL0 0x0003c000 -#define PCR_N2_SL0_SHIFT 14 -#define PCR_N2_OV0 0x00040000 -#define PCR_N2_MASK1 0x07f80000 -#define PCR_N2_MASK1_SHIFT 19 -#define PCR_N2_SL1 0x78000000 -#define PCR_N2_SL1_SHIFT 27 -#define PCR_N2_OV1 0x80000000 - -#define PCR_SUN4U_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE) -#define PCR_N2_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE | \ - PCR_N2_TOE_OV1 | \ - (2 << PCR_N2_SL1_SHIFT) | \ - (0xff << PCR_N2_MASK1_SHIFT)) - -static u64 pcr_enable = PCR_SUN4U_ENABLE; - -static void nmi_handler(struct pt_regs *regs) -{ - pcr_ops->write(PCR_PIC_PRIV); - - if (nmi_enabled) { - oprofile_add_sample(regs, 0); - - write_pic(picl_value()); - pcr_ops->write(pcr_enable); - } -} - -/* We count "clock cycle" events in the lower 32-bit PIC. - * Then configure it such that it overflows every HZ, and thus - * generates a level 15 interrupt at that frequency. - */ -static void cpu_nmi_start(void *_unused) -{ - pcr_ops->write(PCR_PIC_PRIV); - write_pic(picl_value()); - - pcr_ops->write(pcr_enable); -} + struct die_args *args = (struct die_args *)data; + int ret = NOTIFY_DONE; -static void cpu_nmi_stop(void *_unused) -{ - pcr_ops->write(PCR_PIC_PRIV); -} - -static int nmi_start(void) -{ - int err = register_perfctr_intr(nmi_handler); - - if (!err) { - nmi_enabled = 1; - wmb(); - err = on_each_cpu(cpu_nmi_start, NULL, 1); - if (err) { - nmi_enabled = 0; - wmb(); - on_each_cpu(cpu_nmi_stop, NULL, 1); - release_perfctr_intr(nmi_handler); - } + switch (val) { + case DIE_NMI: + oprofile_add_sample(args->regs, 0); + ret = NOTIFY_STOP; + break; + default: + break; } - - return err; -} - -static void nmi_stop(void) -{ - nmi_enabled = 0; - wmb(); - - on_each_cpu(cpu_nmi_stop, NULL, 1); - release_perfctr_intr(nmi_handler); - synchronize_sched(); + return ret; } -static unsigned long perf_hsvc_group; -static unsigned long perf_hsvc_major; -static unsigned long perf_hsvc_minor; +static struct notifier_block profile_timer_exceptions_nb = { + .notifier_call = profile_timer_exceptions_notify, +}; -static int __init register_perf_hsvc(void) +static int timer_start(void) { - if (tlb_type == hypervisor) { - switch (sun4v_chip_type) { - case SUN4V_CHIP_NIAGARA1: - perf_hsvc_group = HV_GRP_NIAG_PERF; - break; - - case SUN4V_CHIP_NIAGARA2: - perf_hsvc_group = HV_GRP_N2_CPU; - break; - - default: - return -ENODEV; - } - - - perf_hsvc_major = 1; - perf_hsvc_minor = 0; - if (sun4v_hvapi_register(perf_hsvc_group, - perf_hsvc_major, - &perf_hsvc_minor)) { - printk("perfmon: Could not register N2 hvapi.\n"); - return -ENODEV; - } - } + if (register_die_notifier(&profile_timer_exceptions_nb)) + return 1; + nmi_adjust_hz(HZ); return 0; } -static void unregister_perf_hsvc(void) + +static void timer_stop(void) { - if (tlb_type != hypervisor) - return; - sun4v_hvapi_unregister(perf_hsvc_group); + nmi_adjust_hz(1); + unregister_die_notifier(&profile_timer_exceptions_nb); + synchronize_sched(); /* Allow already-started NMIs to complete. */ } -static int oprofile_nmi_init(struct oprofile_operations *ops) +static int op_nmi_timer_init(struct oprofile_operations *ops) { - int err = register_perf_hsvc(); - - if (err) - return err; - - switch (tlb_type) { - case hypervisor: - pcr_ops = &n2_pcr_ops; - pcr_enable = PCR_N2_ENABLE; - break; - - case cheetah: - case cheetah_plus: - pcr_ops = &direct_pcr_ops; - break; - - default: + if (!nmi_usable) return -ENODEV; - } - ops->create_files = NULL; - ops->setup = NULL; - ops->shutdown = NULL; - ops->start = nmi_start; - ops->stop = nmi_stop; + ops->start = timer_start; + ops->stop = timer_stop; ops->cpu_type = "timer"; - - printk(KERN_INFO "oprofile: Using perfctr based NMI timer interrupt.\n"); - + printk(KERN_INFO "oprofile: Using perfctr NMI timer interrupt.\n"); return 0; } #endif @@ -233,7 +73,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) int ret = -ENODEV; #ifdef CONFIG_SPARC64 - ret = oprofile_nmi_init(ops); + ret = op_nmi_timer_init(ops); if (!ret) return ret; #endif @@ -241,10 +81,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) return ret; } - void oprofile_arch_exit(void) { -#ifdef CONFIG_SPARC64 - unregister_perf_hsvc(); -#endif } diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c index 7511584..4a58c8c 100644 --- a/arch/x86/boot/video-vesa.c +++ b/arch/x86/boot/video-vesa.c @@ -269,9 +269,8 @@ void vesa_store_edid(void) we genuinely have to assume all registers are destroyed here. */ asm("pushw %%es; movw %2,%%es; "INT10"; popw %%es" - : "+a" (ax), "+b" (bx) - : "c" (cx), "D" (di) - : "esi"); + : "+a" (ax), "+b" (bx), "+c" (cx), "+D" (di) + : : "esi", "edx"); if (ax != 0x004f) return; /* No EDID */ @@ -285,9 +284,9 @@ void vesa_store_edid(void) dx = 0; /* EDID block number */ di =(size_t) &boot_params.edid_info; /* (ES:)Pointer to block */ asm(INT10 - : "+a" (ax), "+b" (bx), "+d" (dx), "=m" (boot_params.edid_info) - : "c" (cx), "D" (di) - : "esi"); + : "+a" (ax), "+b" (bx), "+d" (dx), "=m" (boot_params.edid_info), + "+c" (cx), "+D" (di) + : : "esi"); #endif /* CONFIG_FIRMWARE_EDID */ } diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 9c79b24..097a6b6 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -418,9 +418,9 @@ ENTRY(ia32_syscall) orl $TS_COMPAT,TI_status(%r10) testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) jnz ia32_tracesys -ia32_do_syscall: cmpl $(IA32_NR_syscalls-1),%eax - ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ + ja ia32_badsys +ia32_do_call: IA32_ARG_FIXUP call *ia32_sys_call_table(,%rax,8) # xxx: rip relative ia32_sysret: @@ -435,7 +435,9 @@ ia32_tracesys: call syscall_trace_enter LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST - jmp ia32_do_syscall + cmpl $(IA32_NR_syscalls-1),%eax + ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ + jmp ia32_do_call END(ia32_syscall) ia32_badsys: diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index 3d8cedd..00d41ce 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h @@ -49,6 +49,7 @@ #define E820_RESERVED_KERN 128 #ifndef __ASSEMBLY__ +#include <linux/types.h> struct e820entry { __u64 addr; /* start of memory segment */ __u64 size; /* size of memory segment */ diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h index b95162a..d2e3bf3 100644 --- a/arch/x86/include/asm/kvm.h +++ b/arch/x86/include/asm/kvm.h @@ -6,7 +6,7 @@ * */ -#include <asm/types.h> +#include <linux/types.h> #include <linux/ioctl.h> /* Architectural interrupt line count. */ diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 1d6e17c..32c6e17 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -3,8 +3,8 @@ #ifdef __x86_64__ +#include <linux/types.h> #include <asm/ioctls.h> -#include <asm/types.h> /* * Machine Check support for x86 @@ -115,8 +115,6 @@ extern int mce_notify_user(void); #endif /* !CONFIG_X86_32 */ - - #ifdef CONFIG_X86_MCE extern void mcheck_init(struct cpuinfo_x86 *c); #else @@ -126,5 +124,4 @@ extern void stop_mce(void); extern void restart_mce(void); #endif /* __KERNEL__ */ - #endif /* _ASM_X86_MCE_H */ diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index 14080d2..a51ada8 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -23,6 +23,7 @@ #ifndef _ASM_X86_MTRR_H #define _ASM_X86_MTRR_H +#include <linux/types.h> #include <linux/ioctl.h> #include <linux/errno.h> diff --git a/arch/x86/include/asm/ptrace-abi.h b/arch/x86/include/asm/ptrace-abi.h index 25f1bb8..8e0f8d1 100644 --- a/arch/x86/include/asm/ptrace-abi.h +++ b/arch/x86/include/asm/ptrace-abi.h @@ -83,7 +83,7 @@ #ifdef CONFIG_X86_PTRACE_BTS #ifndef __ASSEMBLY__ -#include <asm/types.h> +#include <linux/types.h> /* configuration/status structure used in PTRACE_BTS_CONFIG and PTRACE_BTS_STATUS commands. diff --git a/arch/x86/include/asm/sigcontext.h b/arch/x86/include/asm/sigcontext.h index 0afcb5e..ec66649 100644 --- a/arch/x86/include/asm/sigcontext.h +++ b/arch/x86/include/asm/sigcontext.h @@ -2,7 +2,7 @@ #define _ASM_X86_SIGCONTEXT_H #include <linux/compiler.h> -#include <asm/types.h> +#include <linux/types.h> #define FP_XSTATE_MAGIC1 0x46505853U #define FP_XSTATE_MAGIC2 0x46505845U diff --git a/arch/x86/include/asm/sigcontext32.h b/arch/x86/include/asm/sigcontext32.h index 6126188..ad1478c 100644 --- a/arch/x86/include/asm/sigcontext32.h +++ b/arch/x86/include/asm/sigcontext32.h @@ -1,6 +1,8 @@ #ifndef _ASM_X86_SIGCONTEXT32_H #define _ASM_X86_SIGCONTEXT32_H +#include <linux/types.h> + /* signal context for 32bit programs. */ #define X86_FXSR_MAGIC 0x0000 diff --git a/arch/x86/include/asm/swab.h b/arch/x86/include/asm/swab.h index 306d417..557cd9f 100644 --- a/arch/x86/include/asm/swab.h +++ b/arch/x86/include/asm/swab.h @@ -1,7 +1,7 @@ #ifndef _ASM_X86_SWAB_H #define _ASM_X86_SWAB_H -#include <asm/types.h> +#include <linux/types.h> #include <linux/compiler.h> static inline __attribute_const__ __u32 __arch_swab32(__u32 val) diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 4abff45..7c243a2 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -157,11 +157,11 @@ static int __init acpi_sleep_setup(char *str) #ifdef CONFIG_HIBERNATION if (strncmp(str, "s4_nohwsig", 10) == 0) acpi_no_s4_hw_signature(); + if (strncmp(str, "s4_nonvs", 8) == 0) + acpi_s4_no_nvs(); #endif if (strncmp(str, "old_ordering", 12) == 0) acpi_old_suspend_ordering(); - if (strncmp(str, "s4_nonvs", 8) == 0) - acpi_s4_no_nvs(); str = strchr(str, ','); if (str != NULL) str += strspn(str, ", \t"); diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index c6f1564..383d827 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c @@ -1461,7 +1461,7 @@ static int __init detect_init_APIC(void) switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) || - (boot_cpu_data.x86 == 15)) + (boot_cpu_data.x86 >= 15)) break; goto no_apic; case X86_VENDOR_INTEL: diff --git a/arch/x86/kernel/cpu/cpufreq/Kconfig b/arch/x86/kernel/cpu/cpufreq/Kconfig index efae3b2..65792c2 100644 --- a/arch/x86/kernel/cpu/cpufreq/Kconfig +++ b/arch/x86/kernel/cpu/cpufreq/Kconfig @@ -245,17 +245,6 @@ config X86_E_POWERSAVER comment "shared options" -config X86_ACPI_CPUFREQ_PROC_INTF - bool "/proc/acpi/processor/../performance interface (deprecated)" - depends on PROC_FS - depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI - help - This enables the deprecated /proc/acpi/processor/../performance - interface. While it is helpful for debugging, the generic, - cross-architecture cpufreq interfaces should be used. - - If in doubt, say N. - config X86_SPEEDSTEP_LIB tristate default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 549f2ad..430e5c3 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -30,7 +30,7 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) { /* Unmask CPUID levels if masked: */ - if (c->x86 == 6 && c->x86_model >= 15) { + if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) { u64 misc_enable; rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable); diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 58527a9..7293508 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -36,8 +36,11 @@ static struct _cache_table cache_table[] __cpuinitdata = { { 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */ { 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */ + { 0x09, LVL_1_INST, 32 }, /* 4-way set assoc, 64 byte line size */ { 0x0a, LVL_1_DATA, 8 }, /* 2 way set assoc, 32 byte line size */ { 0x0c, LVL_1_DATA, 16 }, /* 4-way set assoc, 32 byte line size */ + { 0x0d, LVL_1_DATA, 16 }, /* 4-way set assoc, 64 byte line size */ + { 0x21, LVL_2, 256 }, /* 8-way set assoc, 64 byte line size */ { 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */ { 0x23, LVL_3, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */ { 0x25, LVL_3, 2048 }, /* 8-way set assoc, sectored cache, 64 byte line size */ @@ -85,6 +88,18 @@ static struct _cache_table cache_table[] __cpuinitdata = { 0x85, LVL_2, 2048 }, /* 8-way set assoc, 32 byte line size */ { 0x86, LVL_2, 512 }, /* 4-way set assoc, 64 byte line size */ { 0x87, LVL_2, 1024 }, /* 8-way set assoc, 64 byte line size */ + { 0xd0, LVL_3, 512 }, /* 4-way set assoc, 64 byte line size */ + { 0xd1, LVL_3, 1024 }, /* 4-way set assoc, 64 byte line size */ + { 0xd2, LVL_3, 2048 }, /* 4-way set assoc, 64 byte line size */ + { 0xd6, LVL_3, 1024 }, /* 8-way set assoc, 64 byte line size */ + { 0xd7, LVL_3, 2038 }, /* 8-way set assoc, 64 byte line size */ + { 0xd8, LVL_3, 4096 }, /* 12-way set assoc, 64 byte line size */ + { 0xdc, LVL_3, 2048 }, /* 12-way set assoc, 64 byte line size */ + { 0xdd, LVL_3, 4096 }, /* 12-way set assoc, 64 byte line size */ + { 0xde, LVL_3, 8192 }, /* 12-way set assoc, 64 byte line size */ + { 0xe2, LVL_3, 2048 }, /* 16-way set assoc, 64 byte line size */ + { 0xe3, LVL_3, 4096 }, /* 16-way set assoc, 64 byte line size */ + { 0xe4, LVL_3, 8192 }, /* 16-way set assoc, 64 byte line size */ { 0x00, 0, 0} }; diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index d259e5d..236a401 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -1594,8 +1594,7 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) /* kvm/qemu doesn't have mtrr set right, don't trim them all */ if (!highest_pfn) { - WARN(!kvm_para_available(), KERN_WARNING - "WARNING: strange, CPU MTRRs all blank?\n"); + printk(KERN_INFO "CPU MTRRs all blank - virtualized system.\n"); return 0; } diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c index da91701..169a120 100644 --- a/arch/x86/kernel/ds.c +++ b/arch/x86/kernel/ds.c @@ -15,8 +15,8 @@ * - buffer allocation (memory accounting) * * - * Copyright (C) 2007-2008 Intel Corporation. - * Markus Metzger <markus.t.metzger@intel.com>, 2007-2008 + * Copyright (C) 2007-2009 Intel Corporation. + * Markus Metzger <markus.t.metzger@intel.com>, 2007-2009 */ @@ -890,7 +890,7 @@ int ds_set_pebs_reset(struct pebs_tracer *tracer, u64 value) } static const struct ds_configuration ds_cfg_netburst = { - .name = "netburst", + .name = "Netburst", .ctl[dsf_bts] = (1 << 2) | (1 << 3), .ctl[dsf_bts_kernel] = (1 << 5), .ctl[dsf_bts_user] = (1 << 6), @@ -904,7 +904,7 @@ static const struct ds_configuration ds_cfg_netburst = { #endif }; static const struct ds_configuration ds_cfg_pentium_m = { - .name = "pentium m", + .name = "Pentium M", .ctl[dsf_bts] = (1 << 6) | (1 << 7), .sizeof_field = sizeof(long), @@ -915,8 +915,8 @@ static const struct ds_configuration ds_cfg_pentium_m = { .sizeof_rec[ds_pebs] = sizeof(long) * 18, #endif }; -static const struct ds_configuration ds_cfg_core2 = { - .name = "core 2", +static const struct ds_configuration ds_cfg_core2_atom = { + .name = "Core 2/Atom", .ctl[dsf_bts] = (1 << 6) | (1 << 7), .ctl[dsf_bts_kernel] = (1 << 9), .ctl[dsf_bts_user] = (1 << 10), @@ -949,19 +949,22 @@ void __cpuinit ds_init_intel(struct cpuinfo_x86 *c) switch (c->x86) { case 0x6: switch (c->x86_model) { - case 0 ... 0xC: - /* sorry, don't know about them */ - break; - case 0xD: - case 0xE: /* Pentium M */ + case 0x9: + case 0xd: /* Pentium M */ ds_configure(&ds_cfg_pentium_m); break; - default: /* Core2, Atom, ... */ - ds_configure(&ds_cfg_core2); + case 0xf: + case 0x17: /* Core2 */ + case 0x1c: /* Atom */ + ds_configure(&ds_cfg_core2_atom); + break; + case 0x1a: /* i7 */ + default: + /* sorry, don't know about them */ break; } break; - case 0xF: + case 0xf: switch (c->x86_model) { case 0x0: case 0x1: diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index e4c9710..586bed6 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -347,6 +347,7 @@ ENTRY(save_args) popq_cfi %rax /* move return address... */ mov PER_CPU_VAR(irq_stack_ptr),%rsp EMPTY_FRAME 0 + pushq_cfi %rbp /* backlink for unwinder */ pushq_cfi %rax /* ... to the new stack */ /* * We entered an interrupt context - irqs are off: diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index e4d36bd..0a7f6d6 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c @@ -2527,14 +2527,15 @@ static void irq_complete_move(struct irq_desc **descp) vector = ~get_irq_regs()->orig_ax; me = smp_processor_id(); + + if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) { #ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC *descp = desc = move_irq_desc(desc, me); /* get the new one */ cfg = desc->chip_data; #endif - - if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) send_cleanup_vector(cfg); + } } #else static inline void irq_complete_move(struct irq_desc **descp) {} diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit_32.c index bf629ca..22608eb 100644 --- a/arch/x86/kernel/irqinit_32.c +++ b/arch/x86/kernel/irqinit_32.c @@ -78,15 +78,6 @@ void __init init_ISA_irqs(void) } } -/* - * IRQ2 is cascade interrupt to second interrupt controller - */ -static struct irqaction irq2 = { - .handler = no_action, - .mask = CPU_MASK_NONE, - .name = "cascade", -}; - DEFINE_PER_CPU(vector_irq_t, vector_irq) = { [0 ... IRQ0_VECTOR - 1] = -1, [IRQ0_VECTOR] = 0, @@ -185,9 +176,6 @@ void __init native_init_IRQ(void) alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); #endif - if (!acpi_ioapic) - setup_irq(2, &irq2); - /* setup after call gates are initialised (usually add in * the architecture specific gates) */ diff --git a/arch/x86/mach-default/setup.c b/arch/x86/mach-default/setup.c index df167f2..a265a7c 100644 --- a/arch/x86/mach-default/setup.c +++ b/arch/x86/mach-default/setup.c @@ -38,6 +38,15 @@ void __init pre_intr_init_hook(void) init_ISA_irqs(); } +/* + * IRQ2 is cascade interrupt to second interrupt controller + */ +static struct irqaction irq2 = { + .handler = no_action, + .mask = CPU_MASK_NONE, + .name = "cascade", +}; + /** * intr_init_hook - post gate setup interrupt initialisation * @@ -53,6 +62,9 @@ void __init intr_init_hook(void) if (x86_quirks->arch_intr_init()) return; } + if (!acpi_ioapic) + setup_irq(2, &irq2); + } /** diff --git a/arch/x86/mach-voyager/setup.c b/arch/x86/mach-voyager/setup.c index 0ade625..66b7eb5 100644 --- a/arch/x86/mach-voyager/setup.c +++ b/arch/x86/mach-voyager/setup.c @@ -34,13 +34,23 @@ void __init intr_init_hook(void) setup_irq(2, &irq2); } -void __init pre_setup_arch_hook(void) +static void voyager_disable_tsc(void) { /* Voyagers run their CPUs from independent clocks, so disable * the TSC code because we can't sync them */ setup_clear_cpu_cap(X86_FEATURE_TSC); } +void __init pre_setup_arch_hook(void) +{ + voyager_disable_tsc(); +} + +void __init pre_time_init_hook(void) +{ + voyager_disable_tsc(); +} + void __init trap_init_hook(void) { } diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c index 58c7cac..6f5a38c 100644 --- a/arch/x86/mach-voyager/voyager_smp.c +++ b/arch/x86/mach-voyager/voyager_smp.c @@ -81,7 +81,7 @@ static void enable_local_vic_irq(unsigned int irq); static void disable_local_vic_irq(unsigned int irq); static void before_handle_vic_irq(unsigned int irq); static void after_handle_vic_irq(unsigned int irq); -static void set_vic_irq_affinity(unsigned int irq, cpumask_t mask); +static void set_vic_irq_affinity(unsigned int irq, const struct cpumask *mask); static void ack_vic_irq(unsigned int irq); static void vic_enable_cpi(void); static void do_boot_cpu(__u8 cpuid); @@ -211,8 +211,6 @@ static __u32 cpu_booted_map; static cpumask_t smp_commenced_mask = CPU_MASK_NONE; /* This is for the new dynamic CPU boot code */ -cpumask_t cpu_callin_map = CPU_MASK_NONE; -cpumask_t cpu_callout_map = CPU_MASK_NONE; /* The per processor IRQ masks (these are usually kept in sync) */ static __u16 vic_irq_mask[NR_CPUS] __cacheline_aligned; @@ -378,7 +376,7 @@ void __init find_smp_config(void) cpus_addr(phys_cpu_present_map)[0] |= voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK + 3) << 24; - cpu_possible_map = phys_cpu_present_map; + init_cpu_possible(&phys_cpu_present_map); printk("VOYAGER SMP: phys_cpu_present_map = 0x%lx\n", cpus_addr(phys_cpu_present_map)[0]); /* Here we set up the VIC to enable SMP */ @@ -1598,16 +1596,16 @@ static void after_handle_vic_irq(unsigned int irq) * change the mask and then do an interrupt enable CPI to re-enable on * the selected processors */ -void set_vic_irq_affinity(unsigned int irq, cpumask_t mask) +void set_vic_irq_affinity(unsigned int irq, const struct cpumask *mask) { /* Only extended processors handle interrupts */ unsigned long real_mask; unsigned long irq_mask = 1 << irq; int cpu; - real_mask = cpus_addr(mask)[0] & voyager_extended_vic_processors; + real_mask = cpus_addr(*mask)[0] & voyager_extended_vic_processors; - if (cpus_addr(mask)[0] == 0) + if (cpus_addr(*mask)[0] == 0) /* can't have no CPUs to accept the interrupt -- extremely * bad things will happen */ return; @@ -1749,10 +1747,10 @@ static void __cpuinit voyager_smp_prepare_boot_cpu(void) int cpu = smp_processor_id(); switch_to_new_gdt(cpu); - cpu_set(cpu, cpu_online_map); - cpu_set(cpu, cpu_callout_map); - cpu_set(cpu, cpu_possible_map); - cpu_set(cpu, cpu_present_map); + cpu_online_map = cpumask_of_cpu(smp_processor_id()); + cpu_callout_map = cpumask_of_cpu(smp_processor_id()); + cpu_callin_map = CPU_MASK_NONE; + cpu_present_map = cpumask_of_cpu(smp_processor_id()); } static int __cpuinit voyager_cpu_up(unsigned int cpu) @@ -1781,9 +1779,9 @@ void __init smp_setup_processor_id(void) current_thread_info()->cpu = hard_smp_processor_id(); } -static void voyager_send_call_func(cpumask_t callmask) +static void voyager_send_call_func(const struct cpumask *callmask) { - __u32 mask = cpus_addr(callmask)[0] & ~(1 << smp_processor_id()); + __u32 mask = cpus_addr(*callmask)[0] & ~(1 << smp_processor_id()); send_CPI(mask, VIC_CALL_FUNCTION_CPI); } diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 65709a6..8c3f311 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -807,8 +807,6 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) /* get the address */ address = read_cr2(); - if (unlikely(notify_page_fault(regs))) - return; if (unlikely(kmmio_fault(regs, address))) return; @@ -838,6 +836,9 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) if (spurious_fault(error_code, address)) return; + /* kprobes don't want to hook the spurious faults. */ + if (notify_page_fault(regs)) + return; /* * Don't take the mm semaphore here. If we fixup a prefetch * fault we could otherwise deadlock. @@ -846,6 +847,8 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) return; } + if (unlikely(notify_page_fault(regs))) + return; /* * It's safe to allow irq's after cr2 has been saved and the * vmalloc fault has been handled. diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index 4064345..fecbce6 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c @@ -572,6 +572,7 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route case PCI_DEVICE_ID_INTEL_ICH7_1: case PCI_DEVICE_ID_INTEL_ICH7_30: case PCI_DEVICE_ID_INTEL_ICH7_31: + case PCI_DEVICE_ID_INTEL_TGP_LPC: case PCI_DEVICE_ID_INTEL_ESB2_0: case PCI_DEVICE_ID_INTEL_ICH8_0: case PCI_DEVICE_ID_INTEL_ICH8_1: diff --git a/arch/x86/xen/multicalls.h b/arch/x86/xen/multicalls.h index e786fa7..9e565da 100644 --- a/arch/x86/xen/multicalls.h +++ b/arch/x86/xen/multicalls.h @@ -19,8 +19,10 @@ DECLARE_PER_CPU(unsigned long, xen_mc_irq_flags); paired with xen_mc_issue() */ static inline void xen_mc_batch(void) { + unsigned long flags; /* need to disable interrupts until this entry is complete */ - local_irq_save(__get_cpu_var(xen_mc_irq_flags)); + local_irq_save(flags); + __get_cpu_var(xen_mc_irq_flags) = flags; } static inline struct multicall_space xen_mc_entry(size_t args) diff --git a/block/blk-core.c b/block/blk-core.c index ca69f3d..29bcfac 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -69,7 +69,7 @@ static void drive_stat_acct(struct request *rq, int new_io) int rw = rq_data_dir(rq); int cpu; - if (!blk_fs_request(rq) || !disk || !blk_queue_io_stat(disk->queue)) + if (!blk_fs_request(rq) || !disk || !blk_do_io_stat(disk->queue)) return; cpu = part_stat_lock(); @@ -1667,7 +1667,7 @@ static void blk_account_io_completion(struct request *req, unsigned int bytes) { struct gendisk *disk = req->rq_disk; - if (!disk || !blk_queue_io_stat(disk->queue)) + if (!disk || !blk_do_io_stat(disk->queue)) return; if (blk_fs_request(req)) { @@ -1686,7 +1686,7 @@ static void blk_account_io_done(struct request *req) { struct gendisk *disk = req->rq_disk; - if (!disk || !blk_queue_io_stat(disk->queue)) + if (!disk || !blk_do_io_stat(disk->queue)) return; /* diff --git a/block/blk.h b/block/blk.h index 6e1ed40..0dce92c 100644 --- a/block/blk.h +++ b/block/blk.h @@ -108,4 +108,12 @@ static inline int blk_cpu_to_group(int cpu) #endif } +static inline int blk_do_io_stat(struct request_queue *q) +{ + if (q) + return blk_queue_io_stat(q); + + return 0; +} + #endif diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index d7f9839..a7799a9 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -9,6 +9,7 @@ menuconfig ACPI depends on PCI depends on PM select PNP + select CPU_IDLE default y ---help--- Advanced Configuration and Power Interface (ACPI) support for @@ -287,7 +288,7 @@ config ACPI_CONTAINER support physical cpu/memory hot-plug. If one selects "m", this driver can be loaded with - "modprobe acpi_container". + "modprobe container". config ACPI_HOTPLUG_MEMORY tristate "Memory Hotplug" diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 9684cc8..22ce489 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -538,10 +538,9 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) if (ACPI_FAILURE(status)) { ACPI_WARNING((AE_INFO, "Truncating %u table entries!", - (unsigned) - (acpi_gbl_root_table_list.size - - acpi_gbl_root_table_list. - count))); + (unsigned) (table_count - + (acpi_gbl_root_table_list. + count - 2)))); break; } } diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index da9450b..9c9897d 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -116,9 +116,9 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) return_ACPI_STATUS(AE_NO_MEMORY); } - /* Default return value is SUPPORTED */ + /* Default return value is 0, NOT-SUPPORTED */ - return_desc->integer.value = ACPI_UINT32_MAX; + return_desc->integer.value = 0; walk_state->return_desc = return_desc; /* Compare input string to static table of supported interfaces */ @@ -127,10 +127,8 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) if (!ACPI_STRCMP (string_desc->string.pointer, acpi_interfaces_supported[i])) { - - /* The interface is supported */ - - return_ACPI_STATUS(AE_OK); + return_desc->integer.value = ACPI_UINT32_MAX; + goto done; } } @@ -141,15 +139,14 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) */ status = acpi_os_validate_interface(string_desc->string.pointer); if (ACPI_SUCCESS(status)) { - - /* The interface is supported */ - - return_ACPI_STATUS(AE_OK); + return_desc->integer.value = ACPI_UINT32_MAX; } - /* The interface is not supported */ +done: + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, "ACPI: BIOS _OSI(%s) %ssupported\n", + string_desc->string.pointer, + return_desc->integer.value == 0 ? "not-" : "")); - return_desc->integer.value = 0; return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 17020c1..fe0cdf8 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -163,7 +163,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) case ACPI_NOTIFY_BUS_CHECK: /* Fall through */ case ACPI_NOTIFY_DEVICE_CHECK: - printk("Container driver received %s event\n", + printk(KERN_WARNING "Container driver received %s event\n", (type == ACPI_NOTIFY_BUS_CHECK) ? "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"); status = acpi_bus_get_device(handle, &device); @@ -174,7 +174,8 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); else - printk("Failed to add container\n"); + printk(KERN_WARNING + "Failed to add container\n"); } } else { if (ACPI_SUCCESS(status)) { diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 5b30b8d..35094f2 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -855,10 +855,14 @@ fdd_out: static ssize_t show_docked(struct device *dev, struct device_attribute *attr, char *buf) { + struct acpi_device *tmp; + struct dock_station *dock_station = *((struct dock_station **) dev->platform_data); - return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station)); + if (ACPI_SUCCESS(acpi_bus_get_device(dock_station->handle, &tmp))) + return snprintf(buf, PAGE_SIZE, "1\n"); + return snprintf(buf, PAGE_SIZE, "0\n"); } static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); @@ -984,7 +988,7 @@ static int dock_add(acpi_handle handle) ret = device_create_file(&dock_device->dev, &dev_attr_docked); if (ret) { - printk("Error %d adding sysfs file\n", ret); + printk(KERN_ERR "Error %d adding sysfs file\n", ret); platform_device_unregister(dock_device); kfree(dock_station); dock_station = NULL; @@ -992,7 +996,7 @@ static int dock_add(acpi_handle handle) } ret = device_create_file(&dock_device->dev, &dev_attr_undock); if (ret) { - printk("Error %d adding sysfs file\n", ret); + printk(KERN_ERR "Error %d adding sysfs file\n", ret); device_remove_file(&dock_device->dev, &dev_attr_docked); platform_device_unregister(dock_device); kfree(dock_station); @@ -1001,7 +1005,7 @@ static int dock_add(acpi_handle handle) } ret = device_create_file(&dock_device->dev, &dev_attr_uid); if (ret) { - printk("Error %d adding sysfs file\n", ret); + printk(KERN_ERR "Error %d adding sysfs file\n", ret); device_remove_file(&dock_device->dev, &dev_attr_docked); device_remove_file(&dock_device->dev, &dev_attr_undock); platform_device_unregister(dock_device); @@ -1011,7 +1015,7 @@ static int dock_add(acpi_handle handle) } ret = device_create_file(&dock_device->dev, &dev_attr_flags); if (ret) { - printk("Error %d adding sysfs file\n", ret); + printk(KERN_ERR "Error %d adding sysfs file\n", ret); device_remove_file(&dock_device->dev, &dev_attr_docked); device_remove_file(&dock_device->dev, &dev_attr_undock); device_remove_file(&dock_device->dev, &dev_attr_uid); diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index a2b82c9..5c2f5d3 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -982,7 +982,7 @@ int __init acpi_ec_ecdt_probe(void) saved_ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); if (!saved_ec) return -ENOMEM; - memcpy(&saved_ec, boot_ec, sizeof(saved_ec)); + memcpy(saved_ec, boot_ec, sizeof(*saved_ec)); /* fall through */ } /* This workaround is needed only on some broken machines, diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index adec3d1..5479b9f 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -255,12 +255,12 @@ static int acpi_platform_notify(struct device *dev) } type = acpi_get_bus_type(dev->bus); if (!type) { - DBG("No ACPI bus support for %s\n", dev->bus_id); + DBG("No ACPI bus support for %s\n", dev_name(dev)); ret = -EINVAL; goto end; } if ((ret = type->find_device(dev, &handle)) != 0) - DBG("Can't get handler for %s\n", dev->bus_id); + DBG("Can't get handler for %s\n", dev_name(dev)); end: if (!ret) acpi_bind_one(dev, handle); @@ -271,10 +271,10 @@ static int acpi_platform_notify(struct device *dev) acpi_get_name(dev->archdata.acpi_handle, ACPI_FULL_PATHNAME, &buffer); - DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer); + DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer); kfree(buffer.pointer); } else - DBG("Device %s -> No ACPI support\n", dev->bus_id); + DBG("Device %s -> No ACPI support\n", dev_name(dev)); #endif return ret; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 6729a49..b3193ec 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -228,10 +228,10 @@ void acpi_os_vprintf(const char *fmt, va_list args) if (acpi_in_debugger) { kdb_printf("%s", buffer); } else { - printk("%s", buffer); + printk(KERN_CONT "%s", buffer); } #else - printk("%s", buffer); + printk(KERN_CONT "%s", buffer); #endif } @@ -1317,6 +1317,54 @@ acpi_os_validate_interface (char *interface) return AE_SUPPORT; } +#ifdef CONFIG_X86 + +struct aml_port_desc { + uint start; + uint end; + char* name; + char warned; +}; + +static struct aml_port_desc aml_invalid_port_list[] = { + {0x20, 0x21, "PIC0", 0}, + {0xA0, 0xA1, "PIC1", 0}, + {0x4D0, 0x4D1, "ELCR", 0} +}; + +/* + * valid_aml_io_address() + * + * if valid, return true + * else invalid, warn once, return false + */ +static bool valid_aml_io_address(uint address, uint length) +{ + int i; + int entries = sizeof(aml_invalid_port_list) / sizeof(struct aml_port_desc); + + for (i = 0; i < entries; ++i) { + if ((address >= aml_invalid_port_list[i].start && + address <= aml_invalid_port_list[i].end) || + (address + length >= aml_invalid_port_list[i].start && + address + length <= aml_invalid_port_list[i].end)) + { + if (!aml_invalid_port_list[i].warned) + { + printk(KERN_ERR "ACPI: Denied BIOS AML access" + " to invalid port 0x%x+0x%x (%s)\n", + address, length, + aml_invalid_port_list[i].name); + aml_invalid_port_list[i].warned = 1; + } + return false; /* invalid */ + } + } + return true; /* valid */ +} +#else +static inline bool valid_aml_io_address(uint address, uint length) { return true; } +#endif /****************************************************************************** * * FUNCTION: acpi_os_validate_address @@ -1346,6 +1394,8 @@ acpi_os_validate_address ( switch (space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: + if (!valid_aml_io_address(address, length)) + return AE_AML_ILLEGAL_ADDRESS; case ACPI_ADR_SPACE_SYSTEM_MEMORY: /* Only interference checks against SystemIO and SytemMemory are needed */ diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 1c6e73c..6c772ca 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -593,7 +593,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) return -ENODEV; } else { acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING; - printk(PREFIX "%s [%s] enabled at IRQ %d\n", + printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n", acpi_device_name(link->device), acpi_device_bid(link->device), link->irq.active); } diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 66a9d81..7bc22a4 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -66,43 +66,17 @@ ACPI_MODULE_NAME("processor_idle"); #define ACPI_PROCESSOR_FILE_POWER "power" #define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000) #define PM_TIMER_TICK_NS (1000000000ULL/PM_TIMER_FREQUENCY) -#ifndef CONFIG_CPU_IDLE -#define C2_OVERHEAD 4 /* 1us (3.579 ticks per us) */ -#define C3_OVERHEAD 4 /* 1us (3.579 ticks per us) */ -static void (*pm_idle_save) (void) __read_mostly; -#else #define C2_OVERHEAD 1 /* 1us */ #define C3_OVERHEAD 1 /* 1us */ -#endif #define PM_TIMER_TICKS_TO_US(p) (((p) * 1000)/(PM_TIMER_FREQUENCY/1000)) static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER; -#ifdef CONFIG_CPU_IDLE module_param(max_cstate, uint, 0000); -#else -module_param(max_cstate, uint, 0644); -#endif static unsigned int nocst __read_mostly; module_param(nocst, uint, 0000); -#ifndef CONFIG_CPU_IDLE -/* - * bm_history -- bit-mask with a bit per jiffy of bus-master activity - * 1000 HZ: 0xFFFFFFFF: 32 jiffies = 32ms - * 800 HZ: 0xFFFFFFFF: 32 jiffies = 40ms - * 100 HZ: 0x0000000F: 4 jiffies = 40ms - * reduce history for more aggressive entry into C3 - */ -static unsigned int bm_history __read_mostly = - (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1)); -module_param(bm_history, uint, 0644); - -static int acpi_processor_set_power_policy(struct acpi_processor *pr); - -#else /* CONFIG_CPU_IDLE */ static unsigned int latency_factor __read_mostly = 2; module_param(latency_factor, uint, 0644); -#endif /* * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3. @@ -224,71 +198,6 @@ static void acpi_safe_halt(void) current_thread_info()->status |= TS_POLLING; } -#ifndef CONFIG_CPU_IDLE - -static void -acpi_processor_power_activate(struct acpi_processor *pr, - struct acpi_processor_cx *new) -{ - struct acpi_processor_cx *old; - - if (!pr || !new) - return; - - old = pr->power.state; - - if (old) - old->promotion.count = 0; - new->demotion.count = 0; - - /* Cleanup from old state. */ - if (old) { - switch (old->type) { - case ACPI_STATE_C3: - /* Disable bus master reload */ - if (new->type != ACPI_STATE_C3 && pr->flags.bm_check) - acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0); - break; - } - } - - /* Prepare to use new state. */ - switch (new->type) { - case ACPI_STATE_C3: - /* Enable bus master reload */ - if (old->type != ACPI_STATE_C3 && pr->flags.bm_check) - acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1); - break; - } - - pr->power.state = new; - - return; -} - -static atomic_t c3_cpu_count; - -/* Common C-state entry for C2, C3, .. */ -static void acpi_cstate_enter(struct acpi_processor_cx *cstate) -{ - /* Don't trace irqs off for idle */ - stop_critical_timings(); - if (cstate->entry_method == ACPI_CSTATE_FFH) { - /* Call into architectural FFH based C-state */ - acpi_processor_ffh_cstate_enter(cstate); - } else { - int unused; - /* IO port based C-state */ - inb(cstate->address); - /* Dummy wait op - must do something useless after P_LVL2 read - because chipsets cannot guarantee that STPCLK# signal - gets asserted in time to freeze execution properly. */ - unused = inl(acpi_gbl_FADT.xpm_timer_block.address); - } - start_critical_timings(); -} -#endif /* !CONFIG_CPU_IDLE */ - #ifdef ARCH_APICTIMER_STOPS_ON_C3 /* @@ -390,421 +299,6 @@ static int tsc_halts_in_c(int state) } #endif -#ifndef CONFIG_CPU_IDLE -static void acpi_processor_idle(void) -{ - struct acpi_processor *pr = NULL; - struct acpi_processor_cx *cx = NULL; - struct acpi_processor_cx *next_state = NULL; - int sleep_ticks = 0; - u32 t1, t2 = 0; - - /* - * Interrupts must be disabled during bus mastering calculations and - * for C2/C3 transitions. - */ - local_irq_disable(); - - pr = __get_cpu_var(processors); - if (!pr) { - local_irq_enable(); - return; - } - - /* - * Check whether we truly need to go idle, or should - * reschedule: - */ - if (unlikely(need_resched())) { - local_irq_enable(); - return; - } - - cx = pr->power.state; - if (!cx || acpi_idle_suspend) { - if (pm_idle_save) { - pm_idle_save(); /* enables IRQs */ - } else { - acpi_safe_halt(); - local_irq_enable(); - } - - return; - } - - /* - * Check BM Activity - * ----------------- - * Check for bus mastering activity (if required), record, and check - * for demotion. - */ - if (pr->flags.bm_check) { - u32 bm_status = 0; - unsigned long diff = jiffies - pr->power.bm_check_timestamp; - - if (diff > 31) - diff = 31; - - pr->power.bm_activity <<= diff; - - acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); - if (bm_status) { - pr->power.bm_activity |= 0x1; - acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); - } - /* - * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect - * the true state of bus mastering activity; forcing us to - * manually check the BMIDEA bit of each IDE channel. - */ - else if (errata.piix4.bmisx) { - if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01) - || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01)) - pr->power.bm_activity |= 0x1; - } - - pr->power.bm_check_timestamp = jiffies; - - /* - * If bus mastering is or was active this jiffy, demote - * to avoid a faulty transition. Note that the processor - * won't enter a low-power state during this call (to this - * function) but should upon the next. - * - * TBD: A better policy might be to fallback to the demotion - * state (use it for this quantum only) istead of - * demoting -- and rely on duration as our sole demotion - * qualification. This may, however, introduce DMA - * issues (e.g. floppy DMA transfer overrun/underrun). - */ - if ((pr->power.bm_activity & 0x1) && - cx->demotion.threshold.bm) { - local_irq_enable(); - next_state = cx->demotion.state; - goto end; - } - } - -#ifdef CONFIG_HOTPLUG_CPU - /* - * Check for P_LVL2_UP flag before entering C2 and above on - * an SMP system. We do it here instead of doing it at _CST/P_LVL - * detection phase, to work cleanly with logical CPU hotplug. - */ - if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) && - !pr->flags.has_cst && !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) - cx = &pr->power.states[ACPI_STATE_C1]; -#endif - - /* - * Sleep: - * ------ - * Invoke the current Cx state to put the processor to sleep. - */ - if (cx->type == ACPI_STATE_C2 || cx->type == ACPI_STATE_C3) { - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we - * test NEED_RESCHED: - */ - smp_mb(); - if (need_resched()) { - current_thread_info()->status |= TS_POLLING; - local_irq_enable(); - return; - } - } - - switch (cx->type) { - - case ACPI_STATE_C1: - /* - * Invoke C1. - * Use the appropriate idle routine, the one that would - * be used without acpi C-states. - */ - if (pm_idle_save) { - pm_idle_save(); /* enables IRQs */ - } else { - acpi_safe_halt(); - local_irq_enable(); - } - - /* - * TBD: Can't get time duration while in C1, as resumes - * go to an ISR rather than here. Need to instrument - * base interrupt handler. - * - * Note: the TSC better not stop in C1, sched_clock() will - * skew otherwise. - */ - sleep_ticks = 0xFFFFFFFF; - - break; - - case ACPI_STATE_C2: - /* Get start time (ticks) */ - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); - /* Tell the scheduler that we are going deep-idle: */ - sched_clock_idle_sleep_event(); - /* Invoke C2 */ - acpi_state_timer_broadcast(pr, cx, 1); - acpi_cstate_enter(cx); - /* Get end time (ticks) */ - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); - -#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) - /* TSC halts in C2, so notify users */ - if (tsc_halts_in_c(ACPI_STATE_C2)) - mark_tsc_unstable("possible TSC halt in C2"); -#endif - /* Compute time (ticks) that we were actually asleep */ - sleep_ticks = ticks_elapsed(t1, t2); - - /* Tell the scheduler how much we idled: */ - sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); - - /* Re-enable interrupts */ - local_irq_enable(); - /* Do not account our idle-switching overhead: */ - sleep_ticks -= cx->latency_ticks + C2_OVERHEAD; - - current_thread_info()->status |= TS_POLLING; - acpi_state_timer_broadcast(pr, cx, 0); - break; - - case ACPI_STATE_C3: - acpi_unlazy_tlb(smp_processor_id()); - /* - * Must be done before busmaster disable as we might - * need to access HPET ! - */ - acpi_state_timer_broadcast(pr, cx, 1); - /* - * disable bus master - * bm_check implies we need ARB_DIS - * !bm_check implies we need cache flush - * bm_control implies whether we can do ARB_DIS - * - * That leaves a case where bm_check is set and bm_control is - * not set. In that case we cannot do much, we enter C3 - * without doing anything. - */ - if (pr->flags.bm_check && pr->flags.bm_control) { - if (atomic_inc_return(&c3_cpu_count) == - num_online_cpus()) { - /* - * All CPUs are trying to go to C3 - * Disable bus master arbitration - */ - acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); - } - } else if (!pr->flags.bm_check) { - /* SMP with no shared cache... Invalidate cache */ - ACPI_FLUSH_CPU_CACHE(); - } - - /* Get start time (ticks) */ - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); - /* Invoke C3 */ - /* Tell the scheduler that we are going deep-idle: */ - sched_clock_idle_sleep_event(); - acpi_cstate_enter(cx); - /* Get end time (ticks) */ - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); - if (pr->flags.bm_check && pr->flags.bm_control) { - /* Enable bus master arbitration */ - atomic_dec(&c3_cpu_count); - acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); - } - -#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) - /* TSC halts in C3, so notify users */ - if (tsc_halts_in_c(ACPI_STATE_C3)) - mark_tsc_unstable("TSC halts in C3"); -#endif - /* Compute time (ticks) that we were actually asleep */ - sleep_ticks = ticks_elapsed(t1, t2); - /* Tell the scheduler how much we idled: */ - sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); - - /* Re-enable interrupts */ - local_irq_enable(); - /* Do not account our idle-switching overhead: */ - sleep_ticks -= cx->latency_ticks + C3_OVERHEAD; - - current_thread_info()->status |= TS_POLLING; - acpi_state_timer_broadcast(pr, cx, 0); - break; - - default: - local_irq_enable(); - return; - } - cx->usage++; - if ((cx->type != ACPI_STATE_C1) && (sleep_ticks > 0)) - cx->time += sleep_ticks; - - next_state = pr->power.state; - -#ifdef CONFIG_HOTPLUG_CPU - /* Don't do promotion/demotion */ - if ((cx->type == ACPI_STATE_C1) && (num_online_cpus() > 1) && - !pr->flags.has_cst && !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) { - next_state = cx; - goto end; - } -#endif - - /* - * Promotion? - * ---------- - * Track the number of longs (time asleep is greater than threshold) - * and promote when the count threshold is reached. Note that bus - * mastering activity may prevent promotions. - * Do not promote above max_cstate. - */ - if (cx->promotion.state && - ((cx->promotion.state - pr->power.states) <= max_cstate)) { - if (sleep_ticks > cx->promotion.threshold.ticks && - cx->promotion.state->latency <= - pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) { - cx->promotion.count++; - cx->demotion.count = 0; - if (cx->promotion.count >= - cx->promotion.threshold.count) { - if (pr->flags.bm_check) { - if (! - (pr->power.bm_activity & cx-> - promotion.threshold.bm)) { - next_state = - cx->promotion.state; - goto end; - } - } else { - next_state = cx->promotion.state; - goto end; - } - } - } - } - - /* - * Demotion? - * --------- - * Track the number of shorts (time asleep is less than time threshold) - * and demote when the usage threshold is reached. - */ - if (cx->demotion.state) { - if (sleep_ticks < cx->demotion.threshold.ticks) { - cx->demotion.count++; - cx->promotion.count = 0; - if (cx->demotion.count >= cx->demotion.threshold.count) { - next_state = cx->demotion.state; - goto end; - } - } - } - - end: - /* - * Demote if current state exceeds max_cstate - * or if the latency of the current state is unacceptable - */ - if ((pr->power.state - pr->power.states) > max_cstate || - pr->power.state->latency > - pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) { - if (cx->demotion.state) - next_state = cx->demotion.state; - } - - /* - * New Cx State? - * ------------- - * If we're going to start using a new Cx state we must clean up - * from the previous and prepare to use the new. - */ - if (next_state != pr->power.state) - acpi_processor_power_activate(pr, next_state); -} - -static int acpi_processor_set_power_policy(struct acpi_processor *pr) -{ - unsigned int i; - unsigned int state_is_set = 0; - struct acpi_processor_cx *lower = NULL; - struct acpi_processor_cx *higher = NULL; - struct acpi_processor_cx *cx; - - - if (!pr) - return -EINVAL; - - /* - * This function sets the default Cx state policy (OS idle handler). - * Our scheme is to promote quickly to C2 but more conservatively - * to C3. We're favoring C2 for its characteristics of low latency - * (quick response), good power savings, and ability to allow bus - * mastering activity. Note that the Cx state policy is completely - * customizable and can be altered dynamically. - */ - - /* startup state */ - for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) { - cx = &pr->power.states[i]; - if (!cx->valid) - continue; - - if (!state_is_set) - pr->power.state = cx; - state_is_set++; - break; - } - - if (!state_is_set) - return -ENODEV; - - /* demotion */ - for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) { - cx = &pr->power.states[i]; - if (!cx->valid) - continue; - - if (lower) { - cx->demotion.state = lower; - cx->demotion.threshold.ticks = cx->latency_ticks; - cx->demotion.threshold.count = 1; - if (cx->type == ACPI_STATE_C3) - cx->demotion.threshold.bm = bm_history; - } - - lower = cx; - } - - /* promotion */ - for (i = (ACPI_PROCESSOR_MAX_POWER - 1); i > 0; i--) { - cx = &pr->power.states[i]; - if (!cx->valid) - continue; - - if (higher) { - cx->promotion.state = higher; - cx->promotion.threshold.ticks = cx->latency_ticks; - if (cx->type >= ACPI_STATE_C2) - cx->promotion.threshold.count = 4; - else - cx->promotion.threshold.count = 10; - if (higher->type == ACPI_STATE_C3) - cx->promotion.threshold.bm = bm_history; - } - - higher = cx; - } - - return 0; -} -#endif /* !CONFIG_CPU_IDLE */ - static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) { @@ -1047,11 +541,7 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) */ cx->valid = 1; -#ifndef CONFIG_CPU_IDLE - cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency); -#else cx->latency_ticks = cx->latency; -#endif return; } @@ -1121,7 +611,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, " for C3 to be enabled on SMP systems\n")); return; } - acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0); } /* @@ -1132,11 +621,16 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, */ cx->valid = 1; -#ifndef CONFIG_CPU_IDLE - cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency); -#else cx->latency_ticks = cx->latency; -#endif + /* + * On older chipsets, BM_RLD needs to be set + * in order for Bus Master activity to wake the + * system from C3. Newer chipsets handle DMA + * during C3 automatically and BM_RLD is a NOP. + * In either case, the proper way to + * handle BM_RLD is to set it and leave it set. + */ + acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1); return; } @@ -1201,20 +695,6 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr) pr->power.count = acpi_processor_power_verify(pr); -#ifndef CONFIG_CPU_IDLE - /* - * Set Default Policy - * ------------------ - * Now that we know which states are supported, set the default - * policy. Note that this policy can be changed dynamically - * (e.g. encourage deeper sleeps to conserve battery life when - * not on AC). - */ - result = acpi_processor_set_power_policy(pr); - if (result) - return result; -#endif - /* * if one state of type C2 or C3 is available, mark this * CPU as being "idle manageable" @@ -1312,69 +792,6 @@ static const struct file_operations acpi_processor_power_fops = { .release = single_release, }; -#ifndef CONFIG_CPU_IDLE - -int acpi_processor_cst_has_changed(struct acpi_processor *pr) -{ - int result = 0; - - if (boot_option_idle_override) - return 0; - - if (!pr) - return -EINVAL; - - if (nocst) { - return -ENODEV; - } - - if (!pr->flags.power_setup_done) - return -ENODEV; - - /* - * Fall back to the default idle loop, when pm_idle_save had - * been initialized. - */ - if (pm_idle_save) { - pm_idle = pm_idle_save; - /* Relies on interrupts forcing exit from idle. */ - synchronize_sched(); - } - - pr->flags.power = 0; - result = acpi_processor_get_power_info(pr); - if ((pr->flags.power == 1) && (pr->flags.power_setup_done)) - pm_idle = acpi_processor_idle; - - return result; -} - -#ifdef CONFIG_SMP -static void smp_callback(void *v) -{ - /* we already woke the CPU up, nothing more to do */ -} - -/* - * This function gets called when a part of the kernel has a new latency - * requirement. This means we need to get all processors out of their C-state, - * and then recalculate a new suitable C-state. Just do a cross-cpu IPI; that - * wakes them all right up. - */ -static int acpi_processor_latency_notify(struct notifier_block *b, - unsigned long l, void *v) -{ - smp_call_function(smp_callback, NULL, 1); - return NOTIFY_OK; -} - -static struct notifier_block acpi_processor_latency_notifier = { - .notifier_call = acpi_processor_latency_notify, -}; - -#endif - -#else /* CONFIG_CPU_IDLE */ /** * acpi_idle_bm_check - checks if bus master activity was detected @@ -1383,7 +800,7 @@ static int acpi_idle_bm_check(void) { u32 bm_status = 0; - acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); + acpi_get_register_unlocked(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); if (bm_status) acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); /* @@ -1400,25 +817,6 @@ static int acpi_idle_bm_check(void) } /** - * acpi_idle_update_bm_rld - updates the BM_RLD bit depending on target state - * @pr: the processor - * @target: the new target state - */ -static inline void acpi_idle_update_bm_rld(struct acpi_processor *pr, - struct acpi_processor_cx *target) -{ - if (pr->flags.bm_rld_set && target->type != ACPI_STATE_C3) { - acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0); - pr->flags.bm_rld_set = 0; - } - - if (!pr->flags.bm_rld_set && target->type == ACPI_STATE_C3) { - acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1); - pr->flags.bm_rld_set = 1; - } -} - -/** * acpi_idle_do_entry - a helper function that does C2 and C3 type entry * @cx: cstate data * @@ -1473,9 +871,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, return 0; } - if (pr->flags.bm_check) - acpi_idle_update_bm_rld(pr, cx); - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); acpi_idle_do_entry(cx); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); @@ -1527,9 +922,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, */ acpi_state_timer_broadcast(pr, cx, 1); - if (pr->flags.bm_check) - acpi_idle_update_bm_rld(pr, cx); - if (cx->type == ACPI_STATE_C3) ACPI_FLUSH_CPU_CACHE(); @@ -1621,8 +1013,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, */ acpi_state_timer_broadcast(pr, cx, 1); - acpi_idle_update_bm_rld(pr, cx); - /* * disable bus master * bm_check implies we need ARB_DIS @@ -1795,8 +1185,6 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) return ret; } -#endif /* CONFIG_CPU_IDLE */ - int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *device) { @@ -1825,10 +1213,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, "ACPI: processor limited to max C-state %d\n", max_cstate); first_run++; -#if !defined(CONFIG_CPU_IDLE) && defined(CONFIG_SMP) - pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY, - &acpi_processor_latency_notifier); -#endif } if (!pr) @@ -1852,11 +1236,9 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, * platforms that only support C1. */ if (pr->flags.power) { -#ifdef CONFIG_CPU_IDLE acpi_processor_setup_cpuidle(pr); if (cpuidle_register_device(&pr->power.dev)) return -EIO; -#endif printk(KERN_INFO PREFIX "CPU%d (power states:", pr->id); for (i = 1; i <= pr->power.count; i++) @@ -1864,13 +1246,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, printk(" C%d[C%d]", i, pr->power.states[i].type); printk(")\n"); - -#ifndef CONFIG_CPU_IDLE - if (pr->id == 0) { - pm_idle_save = pm_idle; - pm_idle = acpi_processor_idle; - } -#endif } /* 'power' [R] */ @@ -1889,34 +1264,12 @@ int acpi_processor_power_exit(struct acpi_processor *pr, if (boot_option_idle_override) return 0; -#ifdef CONFIG_CPU_IDLE cpuidle_unregister_device(&pr->power.dev); -#endif pr->flags.power_setup_done = 0; if (acpi_device_dir(device)) remove_proc_entry(ACPI_PROCESSOR_FILE_POWER, acpi_device_dir(device)); -#ifndef CONFIG_CPU_IDLE - - /* Unregister the idle handler when processor #0 is removed. */ - if (pr->id == 0) { - if (pm_idle_save) - pm_idle = pm_idle_save; - - /* - * We are about to unload the current idle thread pm callback - * (pm_idle), Wait for all processors to update cached/local - * copies of pm_idle before proceeding. - */ - cpu_idle_wait(); -#ifdef CONFIG_SMP - pm_qos_remove_notifier(PM_QOS_CPU_DMA_LATENCY, - &acpi_processor_latency_notifier); -#endif - } -#endif - return 0; } diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 846e227..9cc769b 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -31,14 +31,6 @@ #include <linux/init.h> #include <linux/cpufreq.h> -#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF -#include <linux/proc_fs.h> -#include <linux/seq_file.h> -#include <linux/mutex.h> - -#include <asm/uaccess.h> -#endif - #ifdef CONFIG_X86 #include <asm/cpufeature.h> #endif @@ -434,96 +426,6 @@ int acpi_processor_notify_smm(struct module *calling_module) EXPORT_SYMBOL(acpi_processor_notify_smm); -#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF -/* /proc/acpi/processor/../performance interface (DEPRECATED) */ - -static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file); -static struct file_operations acpi_processor_perf_fops = { - .owner = THIS_MODULE, - .open = acpi_processor_perf_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_processor *pr = seq->private; - int i; - - - if (!pr) - goto end; - - if (!pr->performance) { - seq_puts(seq, "<not supported>\n"); - goto end; - } - - seq_printf(seq, "state count: %d\n" - "active state: P%d\n", - pr->performance->state_count, pr->performance->state); - - seq_puts(seq, "states:\n"); - for (i = 0; i < pr->performance->state_count; i++) - seq_printf(seq, - " %cP%d: %d MHz, %d mW, %d uS\n", - (i == pr->performance->state ? '*' : ' '), i, - (u32) pr->performance->states[i].core_frequency, - (u32) pr->performance->states[i].power, - (u32) pr->performance->states[i].transition_latency); - - end: - return 0; -} - -static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_processor_perf_seq_show, - PDE(inode)->data); -} - -static void acpi_cpufreq_add_file(struct acpi_processor *pr) -{ - struct acpi_device *device = NULL; - - - if (acpi_bus_get_device(pr->handle, &device)) - return; - - /* add file 'performance' [R/W] */ - proc_create_data(ACPI_PROCESSOR_FILE_PERFORMANCE, S_IFREG | S_IRUGO, - acpi_device_dir(device), - &acpi_processor_perf_fops, acpi_driver_data(device)); - return; -} - -static void acpi_cpufreq_remove_file(struct acpi_processor *pr) -{ - struct acpi_device *device = NULL; - - - if (acpi_bus_get_device(pr->handle, &device)) - return; - - /* remove file 'performance' */ - remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE, - acpi_device_dir(device)); - - return; -} - -#else -static void acpi_cpufreq_add_file(struct acpi_processor *pr) -{ - return; -} -static void acpi_cpufreq_remove_file(struct acpi_processor *pr) -{ - return; -} -#endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */ - static int acpi_processor_get_psd(struct acpi_processor *pr) { int result = 0; @@ -747,14 +649,12 @@ err_ret: } EXPORT_SYMBOL(acpi_processor_preregister_performance); - int acpi_processor_register_performance(struct acpi_processor_performance *performance, unsigned int cpu) { struct acpi_processor *pr; - if (!(acpi_processor_ppc_status & PPC_REGISTERED)) return -EINVAL; @@ -781,8 +681,6 @@ acpi_processor_register_performance(struct acpi_processor_performance return -EIO; } - acpi_cpufreq_add_file(pr); - mutex_unlock(&performance_mutex); return 0; } @@ -795,7 +693,6 @@ acpi_processor_unregister_performance(struct acpi_processor_performance { struct acpi_processor *pr; - mutex_lock(&performance_mutex); pr = per_cpu(processors, cpu); @@ -808,8 +705,6 @@ acpi_processor_unregister_performance(struct acpi_processor_performance kfree(pr->performance->states); pr->performance = NULL; - acpi_cpufreq_remove_file(pr); - mutex_unlock(&performance_mutex); return; diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 7e3c609..5192666 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -90,31 +90,6 @@ void __init acpi_old_suspend_ordering(void) old_suspend_ordering = true; } -/* - * According to the ACPI specification the BIOS should make sure that ACPI is - * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, - * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI - * on such systems during resume. Unfortunately that doesn't help in - * particularly pathological cases in which SCI_EN has to be set directly on - * resume, although the specification states very clearly that this flag is - * owned by the hardware. The set_sci_en_on_resume variable will be set in such - * cases. - */ -static bool set_sci_en_on_resume; -/* - * The ACPI specification wants us to save NVS memory regions during hibernation - * and to restore them during the subsequent resume. However, it is not certain - * if this mechanism is going to work on all machines, so we allow the user to - * disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line - * option. - */ -static bool s4_no_nvs; - -void __init acpi_s4_no_nvs(void) -{ - s4_no_nvs = true; -} - /** * acpi_pm_disable_gpes - Disable the GPEs. */ @@ -193,6 +168,18 @@ static void acpi_pm_end(void) #endif /* CONFIG_ACPI_SLEEP */ #ifdef CONFIG_SUSPEND +/* + * According to the ACPI specification the BIOS should make sure that ACPI is + * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, + * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI + * on such systems during resume. Unfortunately that doesn't help in + * particularly pathological cases in which SCI_EN has to be set directly on + * resume, although the specification states very clearly that this flag is + * owned by the hardware. The set_sci_en_on_resume variable will be set in such + * cases. + */ +static bool set_sci_en_on_resume; + extern void do_suspend_lowlevel(void); static u32 acpi_suspend_states[] = { @@ -396,6 +383,20 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { #endif /* CONFIG_SUSPEND */ #ifdef CONFIG_HIBERNATION +/* + * The ACPI specification wants us to save NVS memory regions during hibernation + * and to restore them during the subsequent resume. However, it is not certain + * if this mechanism is going to work on all machines, so we allow the user to + * disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line + * option. + */ +static bool s4_no_nvs; + +void __init acpi_s4_no_nvs(void) +{ + s4_no_nvs = true; +} + static unsigned long s4_hardware_signature; static struct acpi_table_facs *facs; static bool nosigcheck; @@ -679,7 +680,7 @@ static void acpi_power_off_prepare(void) static void acpi_power_off(void) { /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ - printk("%s called\n", __func__); + printk(KERN_DEBUG "%s called\n", __func__); local_irq_disable(); acpi_enable_wakeup_device(ACPI_STATE_S5); acpi_enter_sleep_state(ACPI_STATE_S5); diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 775c97a..a885295 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -293,7 +293,12 @@ static void __init check_multiple_madt(void) int __init acpi_table_init(void) { - acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0); + acpi_status status; + + status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0); + if (ACPI_FAILURE(status)) + return 1; + check_multiple_madt(); return 0; } diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index f261737..bb5ed05 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1020,7 +1020,7 @@ acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset) } seq_printf(seq, "levels: "); - for (i = 0; i < dev->brightness->count; i++) + for (i = 2; i < dev->brightness->count; i++) seq_printf(seq, " %d", dev->brightness->levels[i]); seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr); @@ -1059,7 +1059,7 @@ acpi_video_device_write_brightness(struct file *file, return -EFAULT; /* validate through the list of available levels */ - for (i = 0; i < dev->brightness->count; i++) + for (i = 2; i < dev->brightness->count; i++) if (level == dev->brightness->levels[i]) { if (ACPI_SUCCESS (acpi_video_device_lcd_set_level(dev, level))) @@ -1260,7 +1260,7 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) printk(KERN_WARNING PREFIX "This indicates a BIOS bug. Please contact the manufacturer.\n"); } - printk("%llx\n", options); + printk(KERN_WARNING "%llx\n", options); seq_printf(seq, "can POST: <integrated video>"); if (options & 2) seq_printf(seq, " <PCI video>"); @@ -1712,7 +1712,7 @@ acpi_video_get_next_level(struct acpi_video_device *device, max = max_below = 0; min = min_above = 255; /* Find closest level to level_current */ - for (i = 0; i < device->brightness->count; i++) { + for (i = 2; i < device->brightness->count; i++) { l = device->brightness->levels[i]; if (abs(l - level_current) < abs(delta)) { delta = l - level_current; @@ -1722,7 +1722,7 @@ acpi_video_get_next_level(struct acpi_video_device *device, } /* Ajust level_current to closest available level */ level_current += delta; - for (i = 0; i < device->brightness->count; i++) { + for (i = 2; i < device->brightness->count; i++) { l = device->brightness->levels[i]; if (l < min) min = l; @@ -2006,6 +2006,12 @@ static int acpi_video_bus_add(struct acpi_device *device) device->pnp.bus_id[3] = '0' + instance; instance ++; } + /* a hack to fix the duplicate name "VGA" problem on Pa 3553 */ + if (!strcmp(device->pnp.bus_id, "VGA")) { + if (instance) + device->pnp.bus_id[3] = '0' + instance; + instance++; + } video->device = device; strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME); diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 77bba4c..a603bbf 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -61,9 +61,14 @@ #define EM_MSG_LED_VALUE_ON 0x00010000 static int ahci_skip_host_reset; +static int ahci_ignore_sss; + module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444); MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)"); +module_param_named(ignore_sss, ahci_ignore_sss, int, 0444); +MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)"); + static int ahci_enable_alpm(struct ata_port *ap, enum link_pm policy); static void ahci_disable_alpm(struct ata_port *ap); @@ -2692,8 +2697,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) host->iomap = pcim_iomap_table(pdev); host->private_data = hpriv; - if (!(hpriv->cap & HOST_CAP_SSS)) + if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) host->flags |= ATA_HOST_PARALLEL_SCAN; + else + printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n"); if (pi.flags & ATA_FLAG_EM) ahci_reset_em(host); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 88c2428..9fbf059 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -164,6 +164,11 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); +static bool ata_sstatus_online(u32 sstatus) +{ + return (sstatus & 0xf) == 0x3; +} + /** * ata_link_next - link iteration helper * @link: the previous link, NULL to start @@ -1015,18 +1020,6 @@ static const char *sata_spd_string(unsigned int spd) return spd_str[spd - 1]; } -void ata_dev_disable(struct ata_device *dev) -{ - if (ata_dev_enabled(dev)) { - if (ata_msg_drv(dev->link->ap)) - ata_dev_printk(dev, KERN_WARNING, "disabled\n"); - ata_acpi_on_disable(dev); - ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | - ATA_DNXFER_QUIET); - dev->class++; - } -} - static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy) { struct ata_link *link = dev->link; @@ -2239,6 +2232,40 @@ retry: return rc; } +static int ata_do_link_spd_horkage(struct ata_device *dev) +{ + struct ata_link *plink = ata_dev_phys_link(dev); + u32 target, target_limit; + + if (!sata_scr_valid(plink)) + return 0; + + if (dev->horkage & ATA_HORKAGE_1_5_GBPS) + target = 1; + else + return 0; + + target_limit = (1 << target) - 1; + + /* if already on stricter limit, no need to push further */ + if (plink->sata_spd_limit <= target_limit) + return 0; + + plink->sata_spd_limit = target_limit; + + /* Request another EH round by returning -EAGAIN if link is + * going faster than the target speed. Forward progress is + * guaranteed by setting sata_spd_limit to target_limit above. + */ + if (plink->sata_spd > target) { + ata_dev_printk(dev, KERN_INFO, + "applying link speed limit horkage to %s\n", + sata_spd_string(target)); + return -EAGAIN; + } + return 0; +} + static inline u8 ata_dev_knobble(struct ata_device *dev) { struct ata_port *ap = dev->link->ap; @@ -2329,6 +2356,10 @@ int ata_dev_configure(struct ata_device *dev) return 0; } + rc = ata_do_link_spd_horkage(dev); + if (rc) + return rc; + /* let ACPI work its magic */ rc = ata_acpi_on_devcfg(dev); if (rc) @@ -2784,7 +2815,7 @@ int ata_bus_probe(struct ata_port *ap) /* This is the last chance, better to slow * down than lose it. */ - sata_down_spd_limit(&ap->link); + sata_down_spd_limit(&ap->link, 0); ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); } } @@ -2880,21 +2911,27 @@ void ata_port_disable(struct ata_port *ap) /** * sata_down_spd_limit - adjust SATA spd limit downward * @link: Link to adjust SATA spd limit for + * @spd_limit: Additional limit * * Adjust SATA spd limit of @link downward. Note that this * function only adjusts the limit. The change must be applied * using sata_set_spd(). * + * If @spd_limit is non-zero, the speed is limited to equal to or + * lower than @spd_limit if such speed is supported. If + * @spd_limit is slower than any supported speed, only the lowest + * supported speed is allowed. + * * LOCKING: * Inherited from caller. * * RETURNS: * 0 on success, negative errno on failure */ -int sata_down_spd_limit(struct ata_link *link) +int sata_down_spd_limit(struct ata_link *link, u32 spd_limit) { u32 sstatus, spd, mask; - int rc, highbit; + int rc, bit; if (!sata_scr_valid(link)) return -EOPNOTSUPP; @@ -2903,7 +2940,7 @@ int sata_down_spd_limit(struct ata_link *link) * If not, use cached value in link->sata_spd. */ rc = sata_scr_read(link, SCR_STATUS, &sstatus); - if (rc == 0) + if (rc == 0 && ata_sstatus_online(sstatus)) spd = (sstatus >> 4) & 0xf; else spd = link->sata_spd; @@ -2913,8 +2950,8 @@ int sata_down_spd_limit(struct ata_link *link) return -EINVAL; /* unconditionally mask off the highest bit */ - highbit = fls(mask) - 1; - mask &= ~(1 << highbit); + bit = fls(mask) - 1; + mask &= ~(1 << bit); /* Mask off all speeds higher than or equal to the current * one. Force 1.5Gbps if current SPD is not available. @@ -2928,6 +2965,15 @@ int sata_down_spd_limit(struct ata_link *link) if (!mask) return -EINVAL; + if (spd_limit) { + if (mask & ((1 << spd_limit) - 1)) + mask &= (1 << spd_limit) - 1; + else { + bit = ffs(mask) - 1; + mask = 1 << bit; + } + } + link->sata_spd_limit = mask; ata_link_printk(link, KERN_WARNING, "limiting SATA link speed to %s\n", @@ -4215,6 +4261,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Devices that do not need bridging limits applied */ { "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, }, + /* Devices which aren't very happy with higher link speeds */ + { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, }, + /* End Marker */ { } }; @@ -4709,8 +4758,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) /** * ata_qc_new - Request an available ATA command, for queueing - * @ap: Port associated with device @dev - * @dev: Device from whom we request an available command structure + * @ap: target port * * LOCKING: * None. @@ -5175,7 +5223,7 @@ bool ata_phys_link_online(struct ata_link *link) u32 sstatus; if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 && - (sstatus & 0xf) == 0x3) + ata_sstatus_online(sstatus)) return true; return false; } @@ -5199,7 +5247,7 @@ bool ata_phys_link_offline(struct ata_link *link) u32 sstatus; if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 && - (sstatus & 0xf) != 0x3) + !ata_sstatus_online(sstatus)) return true; return false; } @@ -5412,8 +5460,8 @@ void ata_dev_init(struct ata_device *dev) dev->horkage = 0; spin_unlock_irqrestore(ap->lock, flags); - memset((void *)dev + ATA_DEVICE_CLEAR_OFFSET, 0, - sizeof(*dev) - ATA_DEVICE_CLEAR_OFFSET); + memset((void *)dev + ATA_DEVICE_CLEAR_BEGIN, 0, + ATA_DEVICE_CLEAR_END - ATA_DEVICE_CLEAR_BEGIN); dev->pio_mask = UINT_MAX; dev->mwdma_mask = UINT_MAX; dev->udma_mask = UINT_MAX; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 8147a83..ce2ef04 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -82,6 +82,10 @@ enum { ATA_EH_FASTDRAIN_INTERVAL = 3000, ATA_EH_UA_TRIES = 5, + + /* probe speed down parameters, see ata_eh_schedule_probe() */ + ATA_EH_PROBE_TRIAL_INTERVAL = 60000, /* 1 min */ + ATA_EH_PROBE_TRIALS = 2, }; /* The following table determines how we sequence resets. Each entry @@ -1176,6 +1180,32 @@ void ata_eh_qc_retry(struct ata_queued_cmd *qc) } /** + * ata_dev_disable - disable ATA device + * @dev: ATA device to disable + * + * Disable @dev. + * + * Locking: + * EH context. + */ +void ata_dev_disable(struct ata_device *dev) +{ + if (!ata_dev_enabled(dev)) + return; + + if (ata_msg_drv(dev->link->ap)) + ata_dev_printk(dev, KERN_WARNING, "disabled\n"); + ata_acpi_on_disable(dev); + ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET); + dev->class++; + + /* From now till the next successful probe, ering is used to + * track probe failures. Clear accumulated device error info. + */ + ata_ering_clear(&dev->ering); +} + +/** * ata_eh_detach_dev - detach ATA device * @dev: ATA device to detach * @@ -1849,7 +1879,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, /* speed down? */ if (verdict & ATA_EH_SPDN_SPEED_DOWN) { /* speed down SATA link speed if possible */ - if (sata_down_spd_limit(link) == 0) { + if (sata_down_spd_limit(link, 0) == 0) { action |= ATA_EH_RESET; goto done; } @@ -2601,11 +2631,11 @@ int ata_eh_reset(struct ata_link *link, int classify, } if (try == max_tries - 1) { - sata_down_spd_limit(link); + sata_down_spd_limit(link, 0); if (slave) - sata_down_spd_limit(slave); + sata_down_spd_limit(slave, 0); } else if (rc == -EPIPE) - sata_down_spd_limit(failed_link); + sata_down_spd_limit(failed_link, 0); if (hardreset) reset = hardreset; @@ -2744,6 +2774,8 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, readid_flags, dev->id); switch (rc) { case 0: + /* clear error info accumulated during probe */ + ata_ering_clear(&dev->ering); new_mask |= 1 << dev->devno; break; case -ENOENT: @@ -2947,9 +2979,24 @@ static int ata_eh_skip_recovery(struct ata_link *link) return 1; } +static int ata_count_probe_trials_cb(struct ata_ering_entry *ent, void *void_arg) +{ + u64 interval = msecs_to_jiffies(ATA_EH_PROBE_TRIAL_INTERVAL); + u64 now = get_jiffies_64(); + int *trials = void_arg; + + if (ent->timestamp < now - min(now, interval)) + return -1; + + (*trials)++; + return 0; +} + static int ata_eh_schedule_probe(struct ata_device *dev) { struct ata_eh_context *ehc = &dev->link->eh_context; + struct ata_link *link = ata_dev_phys_link(dev); + int trials = 0; if (!(ehc->i.probe_mask & (1 << dev->devno)) || (ehc->did_probe_mask & (1 << dev->devno))) @@ -2962,6 +3009,25 @@ static int ata_eh_schedule_probe(struct ata_device *dev) ehc->saved_xfer_mode[dev->devno] = 0; ehc->saved_ncq_enabled &= ~(1 << dev->devno); + /* Record and count probe trials on the ering. The specific + * error mask used is irrelevant. Because a successful device + * detection clears the ering, this count accumulates only if + * there are consecutive failed probes. + * + * If the count is equal to or higher than ATA_EH_PROBE_TRIALS + * in the last ATA_EH_PROBE_TRIAL_INTERVAL, link speed is + * forced to 1.5Gbps. + * + * This is to work around cases where failed link speed + * negotiation results in device misdetection leading to + * infinite DEVXCHG or PHRDY CHG events. + */ + ata_ering_record(&dev->ering, 0, AC_ERR_OTHER); + ata_ering_map(&dev->ering, ata_count_probe_trials_cb, &trials); + + if (trials > ATA_EH_PROBE_TRIALS) + sata_down_spd_limit(link, 1); + return 1; } @@ -2969,7 +3035,11 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err) { struct ata_eh_context *ehc = &dev->link->eh_context; - ehc->tries[dev->devno]--; + /* -EAGAIN from EH routine indicates retry without prejudice. + * The requester is responsible for ensuring forward progress. + */ + if (err != -EAGAIN) + ehc->tries[dev->devno]--; switch (err) { case -ENODEV: @@ -2979,12 +3049,13 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err) /* give it just one more chance */ ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1); case -EIO: - if (ehc->tries[dev->devno] == 1 && dev->pio_mode > XFER_PIO_0) { + if (ehc->tries[dev->devno] == 1) { /* This is the last chance, better to slow * down than lose it. */ - sata_down_spd_limit(ata_dev_phys_link(dev)); - ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); + sata_down_spd_limit(ata_dev_phys_link(dev), 0); + if (dev->pio_mode > XFER_PIO_0) + ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); } } diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 98ca07a..619f2c3 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -729,7 +729,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap, if (tries) { /* consecutive revalidation failures? speed down */ if (reval_failed) - sata_down_spd_limit(link); + sata_down_spd_limit(link, 0); else reval_failed = 1; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 3c4c5ae..b9747fa 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -415,6 +415,7 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, /** * ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl + * @ap: target port * @sdev: SCSI device to get identify data for * @arg: User buffer area for identify data * diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index fe2839e..cea8014 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -79,7 +79,6 @@ extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, unsigned int tag); extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev); -extern void ata_dev_disable(struct ata_device *dev); extern void ata_pio_queue_task(struct ata_port *ap, void *data, unsigned long delay); extern void ata_port_flush_task(struct ata_port *ap); @@ -100,7 +99,7 @@ extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags); extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, unsigned int readid_flags); extern int ata_dev_configure(struct ata_device *dev); -extern int sata_down_spd_limit(struct ata_link *link); +extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit); extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel); extern void ata_sg_clean(struct ata_queued_cmd *qc); extern void ata_qc_free(struct ata_queued_cmd *qc); @@ -160,6 +159,7 @@ extern void ata_scsi_error(struct Scsi_Host *host); extern void ata_port_wait_eh(struct ata_port *ap); extern void ata_eh_fastdrain_timerfn(unsigned long arg); extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc); +extern void ata_dev_disable(struct ata_device *dev); extern void ata_eh_detach_dev(struct ata_device *dev); extern void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev, unsigned int action); diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c index 3080f37..f1b26f7 100644 --- a/drivers/ata/pata_qdi.c +++ b/drivers/ata/pata_qdi.c @@ -12,7 +12,7 @@ * * Probe code based on drivers/ide/legacy/qd65xx.c * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by - * Samuel Thibault <samuel.thibault@fnac.net> + * Samuel Thibault <samuel.thibault@ens-lyon.org> */ #include <linux/kernel.h> diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index f2d8a020..4ae1a41 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -663,8 +663,8 @@ static const struct pci_device_id mv_pci_tbl[] = { { PCI_VDEVICE(MARVELL, 0x5081), chip_508x }, /* RocketRAID 1720/174x have different identifiers */ { PCI_VDEVICE(TTI, 0x1720), chip_6042 }, - { PCI_VDEVICE(TTI, 0x1740), chip_508x }, - { PCI_VDEVICE(TTI, 0x1742), chip_508x }, + { PCI_VDEVICE(TTI, 0x1740), chip_6042 }, + { PCI_VDEVICE(TTI, 0x1742), chip_6042 }, { PCI_VDEVICE(MARVELL, 0x6040), chip_604x }, { PCI_VDEVICE(MARVELL, 0x6041), chip_604x }, diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index c49ad0e..444af04 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -436,11 +436,16 @@ static struct ata_port_operations nv_nf2_ops = { .hardreset = nv_noclassify_hardreset, }; -/* CK804 finally gets hardreset right */ +/* For initial probing after boot and hot plugging, hardreset mostly + * works fine on CK804 but curiously, reprobing on the initial port by + * rescanning or rmmod/insmod fails to acquire the initial D2H Reg FIS + * in somewhat undeterministic way. Use noclassify hardreset. + */ static struct ata_port_operations nv_ck804_ops = { .inherits = &nv_common_ops, .freeze = nv_ck804_freeze, .thaw = nv_ck804_thaw, + .hardreset = nv_noclassify_hardreset, .host_stop = nv_ck804_host_stop, }; diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 9f02959..d009160 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -324,7 +324,7 @@ static void sil_fill_sg(struct ata_queued_cmd *qc) prd->addr = cpu_to_le32(addr); prd->flags_len = cpu_to_le32(sg_len); - VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, sg_len); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", si, addr, sg_len); last_prd = prd; prd++; diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index f5be808..735bbe2 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -761,7 +761,7 @@ source "drivers/char/hw_random/Kconfig" config NVRAM tristate "/dev/nvram support" - depends on ATARI || X86 || ARM || GENERIC_NVRAM + depends on ATARI || X86 || (ARM && RTC_DRV_CMOS) || GENERIC_NVRAM ---help--- If you say Y here and create a character special file /dev/nvram with major number 10 and minor number 144 using mknod ("man mknod"), diff --git a/drivers/char/selection.c b/drivers/char/selection.c index f29fbe9..cb8ca56 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c @@ -268,7 +268,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t /* Allocate a new buffer before freeing the old one ... */ multiplier = use_unicode ? 3 : 1; /* chars can take up to 3 bytes */ - bp = kmalloc((sel_end-sel_start)/2*multiplier+1, GFP_KERNEL); + bp = kmalloc(((sel_end-sel_start)/2+1)*multiplier, GFP_KERNEL); if (!bp) { printk(KERN_WARNING "selection: kmalloc() failed\n"); clear_selection(); diff --git a/drivers/char/sx.c b/drivers/char/sx.c index b60be7b..f146e90 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -1713,8 +1713,8 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, for (i = 0; i < SX_NBOARDS; i++) sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); sx_dprintk(SX_DEBUG_FIRMWARE, "\n"); - unlock_kernel(); - return -EIO; + rc = -EIO; + goto out; } switch (cmd) { @@ -1747,7 +1747,8 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, break; case SXIO_DO_RAMTEST: if (sx_initialized) /* Already initialized: better not ramtest the board. */ - return -EPERM; + rc = -EPERM; + break; if (IS_SX_BOARD(board)) { rc = do_memtest(board, 0, 0x7000); if (!rc) @@ -1844,6 +1845,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, rc = -ENOTTY; break; } +out: unlock_kernel(); func_exit(); return rc; diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c index 5543384..33bd753 100644 --- a/drivers/dca/dca-core.c +++ b/drivers/dca/dca-core.c @@ -28,7 +28,7 @@ #include <linux/device.h> #include <linux/dca.h> -#define DCA_VERSION "1.4" +#define DCA_VERSION "1.8" MODULE_VERSION(DCA_VERSION); MODULE_LICENSE("GPL"); @@ -60,16 +60,17 @@ int dca_add_requester(struct device *dev) { struct dca_provider *dca; int err, slot = -ENODEV; + unsigned long flags; if (!dev) return -EFAULT; - spin_lock(&dca_lock); + spin_lock_irqsave(&dca_lock, flags); /* check if the requester has not been added already */ dca = dca_find_provider_by_dev(dev); if (dca) { - spin_unlock(&dca_lock); + spin_unlock_irqrestore(&dca_lock, flags); return -EEXIST; } @@ -78,19 +79,21 @@ int dca_add_requester(struct device *dev) if (slot >= 0) break; } - if (slot < 0) { - spin_unlock(&dca_lock); + + spin_unlock_irqrestore(&dca_lock, flags); + + if (slot < 0) return slot; - } err = dca_sysfs_add_req(dca, dev, slot); if (err) { - dca->ops->remove_requester(dca, dev); - spin_unlock(&dca_lock); + spin_lock_irqsave(&dca_lock, flags); + if (dca == dca_find_provider_by_dev(dev)) + dca->ops->remove_requester(dca, dev); + spin_unlock_irqrestore(&dca_lock, flags); return err; } - spin_unlock(&dca_lock); return 0; } EXPORT_SYMBOL_GPL(dca_add_requester); @@ -103,25 +106,25 @@ int dca_remove_requester(struct device *dev) { struct dca_provider *dca; int slot; + unsigned long flags; if (!dev) return -EFAULT; - spin_lock(&dca_lock); + spin_lock_irqsave(&dca_lock, flags); dca = dca_find_provider_by_dev(dev); if (!dca) { - spin_unlock(&dca_lock); + spin_unlock_irqrestore(&dca_lock, flags); return -ENODEV; } slot = dca->ops->remove_requester(dca, dev); - if (slot < 0) { - spin_unlock(&dca_lock); + spin_unlock_irqrestore(&dca_lock, flags); + + if (slot < 0) return slot; - } dca_sysfs_remove_req(dca, slot); - spin_unlock(&dca_lock); return 0; } EXPORT_SYMBOL_GPL(dca_remove_requester); @@ -135,17 +138,18 @@ u8 dca_common_get_tag(struct device *dev, int cpu) { struct dca_provider *dca; u8 tag; + unsigned long flags; - spin_lock(&dca_lock); + spin_lock_irqsave(&dca_lock, flags); dca = dca_find_provider_by_dev(dev); if (!dca) { - spin_unlock(&dca_lock); + spin_unlock_irqrestore(&dca_lock, flags); return -ENODEV; } tag = dca->ops->get_tag(dca, dev, cpu); - spin_unlock(&dca_lock); + spin_unlock_irqrestore(&dca_lock, flags); return tag; } @@ -217,11 +221,16 @@ static BLOCKING_NOTIFIER_HEAD(dca_provider_chain); int register_dca_provider(struct dca_provider *dca, struct device *dev) { int err; + unsigned long flags; err = dca_sysfs_add_provider(dca, dev); if (err) return err; + + spin_lock_irqsave(&dca_lock, flags); list_add(&dca->node, &dca_providers); + spin_unlock_irqrestore(&dca_lock, flags); + blocking_notifier_call_chain(&dca_provider_chain, DCA_PROVIDER_ADD, NULL); return 0; @@ -234,9 +243,15 @@ EXPORT_SYMBOL_GPL(register_dca_provider); */ void unregister_dca_provider(struct dca_provider *dca) { + unsigned long flags; + blocking_notifier_call_chain(&dca_provider_chain, DCA_PROVIDER_REMOVE, NULL); + + spin_lock_irqsave(&dca_lock, flags); list_del(&dca->node); + spin_unlock_irqrestore(&dca_lock, flags); + dca_sysfs_remove_provider(dca); } EXPORT_SYMBOL_GPL(unregister_dca_provider); diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 7be2cf3..a5dd7a6 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -412,6 +412,7 @@ fw_card_add(struct fw_card *card, { u32 *config_rom; size_t length; + int err; card->max_receive = max_receive; card->link_speed = link_speed; @@ -422,7 +423,13 @@ fw_card_add(struct fw_card *card, list_add_tail(&card->link, &card_list); mutex_unlock(&card_mutex); - return card->driver->enable(card, config_rom, length); + err = card->driver->enable(card, config_rom, length); + if (err < 0) { + mutex_lock(&card_mutex); + list_del(&card->link); + mutex_unlock(&card_mutex); + } + return err; } EXPORT_SYMBOL(fw_card_add); diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 9da5814..6915fb8 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -136,7 +136,7 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size) obj = kcalloc(1, sizeof(*obj), GFP_KERNEL); obj->dev = dev; - obj->filp = shmem_file_setup("drm mm object", size, 0); + obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE); if (IS_ERR(obj->filp)) { kfree(obj); return NULL; diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c index 0370524..abf4dfc 100644 --- a/drivers/hwmon/hp_accel.c +++ b/drivers/hwmon/hp_accel.c @@ -153,7 +153,10 @@ static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3}; static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3}; static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3}; static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3}; +static struct axis_conversion lis3lv02d_axis_xy_rotated_left_usd = {-2, 1, -3}; static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3}; +static struct axis_conversion lis3lv02d_axis_xy_rotated_right = {2, -1, 3}; +static struct axis_conversion lis3lv02d_axis_xy_swap_yz_inverted = {2, -1, -3}; #define AXIS_DMI_MATCH(_ident, _name, _axis) { \ .ident = _ident, \ @@ -172,10 +175,12 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted), AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted), AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left), + AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd), + AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd), + AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right), + AXIS_DMI_MATCH("NC671xx", "HP Compaq 671", xy_swap_yz_inverted), { NULL, } /* Laptop models without axis info (yet): - * "NC651xx" "HP Compaq 651" - * "NC671xx" "HP Compaq 671" * "NC6910" "HP Compaq 6910" * HP Compaq 8710x Notebook PC / Mobile Workstation * "NC2400" "HP Compaq nc2400" diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index b1c6f68..3dad229 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -465,6 +465,16 @@ config BLK_DEV_CS5535 It is safe to say Y to this question. +config BLK_DEV_CS5536 + tristate "CS5536 chipset support" + depends on X86_32 + select BLK_DEV_IDEDMA_PCI + help + This option enables support for the AMD CS5536 + companion chip used with the Geode LX processor family. + + If unsure, say N. + config BLK_DEV_HPT366 tristate "HPT36X/37X chipset support" select BLK_DEV_IDEDMA_PCI diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index c2b9c93..d0e3d7d 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o obj-$(CONFIG_BLK_DEV_CS5520) += cs5520.o obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o obj-$(CONFIG_BLK_DEV_CS5535) += cs5535.o +obj-$(CONFIG_BLK_DEV_CS5536) += cs5536.o obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o obj-$(CONFIG_BLK_DEV_DELKIN) += delkin_cb.o diff --git a/drivers/ide/cs5536.c b/drivers/ide/cs5536.c new file mode 100644 index 0000000..7a62db7 --- /dev/null +++ b/drivers/ide/cs5536.c @@ -0,0 +1,308 @@ +/* + * CS5536 PATA support + * (C) 2007 Martin K. Petersen <mkp@mkp.net> + * (C) 2009 Bartlomiej Zolnierkiewicz + * + * 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 + * + * Documentation: + * Available from AMD web site. + * + * The IDE timing registers for the CS5536 live in the Geode Machine + * Specific Register file and not PCI config space. Most BIOSes + * virtualize the PCI registers so the chip looks like a standard IDE + * controller. Unfortunately not all implementations get this right. + * In particular some have problems with unaligned accesses to the + * virtualized PCI registers. This driver always does full dword + * writes to work around the issue. Also, in case of a bad BIOS this + * driver can be loaded with the "msr=1" parameter which forces using + * the Machine Specific Registers to configure the device. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/ide.h> +#include <asm/msr.h> + +#define DRV_NAME "cs5536" + +enum { + MSR_IDE_CFG = 0x51300010, + PCI_IDE_CFG = 0x40, + + CFG = 0, + DTC = 2, + CAST = 3, + ETC = 4, + + IDE_CFG_CHANEN = (1 << 1), + IDE_CFG_CABLE = (1 << 17) | (1 << 16), + + IDE_D0_SHIFT = 24, + IDE_D1_SHIFT = 16, + IDE_DRV_MASK = 0xff, + + IDE_CAST_D0_SHIFT = 6, + IDE_CAST_D1_SHIFT = 4, + IDE_CAST_DRV_MASK = 0x3, + + IDE_CAST_CMD_SHIFT = 24, + IDE_CAST_CMD_MASK = 0xff, + + IDE_ETC_UDMA_MASK = 0xc0, +}; + +static int use_msr; + +static int cs5536_read(struct pci_dev *pdev, int reg, u32 *val) +{ + if (unlikely(use_msr)) { + u32 dummy; + + rdmsr(MSR_IDE_CFG + reg, *val, dummy); + return 0; + } + + return pci_read_config_dword(pdev, PCI_IDE_CFG + reg * 4, val); +} + +static int cs5536_write(struct pci_dev *pdev, int reg, int val) +{ + if (unlikely(use_msr)) { + wrmsr(MSR_IDE_CFG + reg, val, 0); + return 0; + } + + return pci_write_config_dword(pdev, PCI_IDE_CFG + reg * 4, val); +} + +static void cs5536_program_dtc(ide_drive_t *drive, u8 tim) +{ + struct pci_dev *pdev = to_pci_dev(drive->hwif->dev); + int dshift = (drive->dn & 1) ? IDE_D1_SHIFT : IDE_D0_SHIFT; + u32 dtc; + + cs5536_read(pdev, DTC, &dtc); + dtc &= ~(IDE_DRV_MASK << dshift); + dtc |= tim << dshift; + cs5536_write(pdev, DTC, dtc); +} + +/** + * cs5536_cable_detect - detect cable type + * @hwif: Port to detect on + * + * Perform cable detection for ATA66 capable cable. + * + * Returns a cable type. + */ + +static u8 cs5536_cable_detect(ide_hwif_t *hwif) +{ + struct pci_dev *pdev = to_pci_dev(hwif->dev); + u32 cfg; + + cs5536_read(pdev, CFG, &cfg); + + if (cfg & IDE_CFG_CABLE) + return ATA_CBL_PATA80; + else + return ATA_CBL_PATA40; +} + +/** + * cs5536_set_pio_mode - PIO timing setup + * @drive: ATA device + * @pio: PIO mode number + */ + +static void cs5536_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + static const u8 drv_timings[5] = { + 0x98, 0x55, 0x32, 0x21, 0x20, + }; + + static const u8 addr_timings[5] = { + 0x2, 0x1, 0x0, 0x0, 0x0, + }; + + static const u8 cmd_timings[5] = { + 0x99, 0x92, 0x90, 0x22, 0x20, + }; + + struct pci_dev *pdev = to_pci_dev(drive->hwif->dev); + ide_drive_t *pair = ide_get_pair_dev(drive); + int cshift = (drive->dn & 1) ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT; + u32 cast; + u8 cmd_pio = pio; + + if (pair) + cmd_pio = min(pio, ide_get_best_pio_mode(pair, 255, 4)); + + drive->drive_data &= (IDE_DRV_MASK << 8); + drive->drive_data |= drv_timings[pio]; + + cs5536_program_dtc(drive, drv_timings[pio]); + + cs5536_read(pdev, CAST, &cast); + + cast &= ~(IDE_CAST_DRV_MASK << cshift); + cast |= addr_timings[pio] << cshift; + + cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT); + cast |= cmd_timings[cmd_pio] << IDE_CAST_CMD_SHIFT; + + cs5536_write(pdev, CAST, cast); +} + +/** + * cs5536_set_dma_mode - DMA timing setup + * @drive: ATA device + * @mode: DMA mode + */ + +static void cs5536_set_dma_mode(ide_drive_t *drive, const u8 mode) +{ + static const u8 udma_timings[6] = { + 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, + }; + + static const u8 mwdma_timings[3] = { + 0x67, 0x21, 0x20, + }; + + struct pci_dev *pdev = to_pci_dev(drive->hwif->dev); + int dshift = (drive->dn & 1) ? IDE_D1_SHIFT : IDE_D0_SHIFT; + u32 etc; + + cs5536_read(pdev, ETC, &etc); + + if (mode >= XFER_UDMA_0) { + etc &= ~(IDE_DRV_MASK << dshift); + etc |= udma_timings[mode - XFER_UDMA_0] << dshift; + } else { /* MWDMA */ + etc &= ~(IDE_ETC_UDMA_MASK << dshift); + drive->drive_data &= IDE_DRV_MASK; + drive->drive_data |= mwdma_timings[mode - XFER_MW_DMA_0] << 8; + } + + cs5536_write(pdev, ETC, etc); +} + +static void cs5536_dma_start(ide_drive_t *drive) +{ + if (drive->current_speed < XFER_UDMA_0 && + (drive->drive_data >> 8) != (drive->drive_data & IDE_DRV_MASK)) + cs5536_program_dtc(drive, drive->drive_data >> 8); + + ide_dma_start(drive); +} + +static int cs5536_dma_end(ide_drive_t *drive) +{ + int ret = ide_dma_end(drive); + + if (drive->current_speed < XFER_UDMA_0 && + (drive->drive_data >> 8) != (drive->drive_data & IDE_DRV_MASK)) + cs5536_program_dtc(drive, drive->drive_data & IDE_DRV_MASK); + + return ret; +} + +static const struct ide_port_ops cs5536_port_ops = { + .set_pio_mode = cs5536_set_pio_mode, + .set_dma_mode = cs5536_set_dma_mode, + .cable_detect = cs5536_cable_detect, +}; + +static const struct ide_dma_ops cs5536_dma_ops = { + .dma_host_set = ide_dma_host_set, + .dma_setup = ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = cs5536_dma_start, + .dma_end = cs5536_dma_end, + .dma_test_irq = ide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, +}; + +static const struct ide_port_info cs5536_info = { + .name = DRV_NAME, + .port_ops = &cs5536_port_ops, + .dma_ops = &cs5536_dma_ops, + .host_flags = IDE_HFLAG_SINGLE, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, +}; + +/** + * cs5536_init_one + * @dev: PCI device + * @id: Entry in match table + */ + +static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + u32 cfg; + + if (use_msr) + printk(KERN_INFO DRV_NAME ": Using MSR regs instead of PCI\n"); + + cs5536_read(dev, CFG, &cfg); + + if ((cfg & IDE_CFG_CHANEN) == 0) { + printk(KERN_ERR DRV_NAME ": disabled by BIOS\n"); + return -ENODEV; + } + + return ide_pci_init_one(dev, &cs5536_info, NULL); +} + +static const struct pci_device_id cs5536_pci_tbl[] = { + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), }, + { }, +}; + +static struct pci_driver cs5536_pci_driver = { + .name = DRV_NAME, + .id_table = cs5536_pci_tbl, + .probe = cs5536_init_one, + .remove = ide_pci_remove, + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, +}; + +static int __init cs5536_init(void) +{ + return pci_register_driver(&cs5536_pci_driver); +} + +static void __exit cs5536_exit(void) +{ + pci_unregister_driver(&cs5536_pci_driver); +} + +MODULE_AUTHOR("Martin K. Petersen, Bartlomiej Zolnierkiewicz"); +MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, cs5536_pci_tbl); + +module_param_named(msr, use_msr, int, 0644); +MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)"); + +module_init(cs5536_init); +module_exit(cs5536_exit); diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c index 97a35c6..415d7e2 100644 --- a/drivers/ide/icside.c +++ b/drivers/ide/icside.c @@ -534,7 +534,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec) d.dma_ops = NULL; } - ret = ide_host_register(host, NULL, hws); + ret = ide_host_register(host, &d, hws); if (ret) goto err_free; diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index d8f295b..ec7d07f 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -282,7 +282,7 @@ static int do_drive_get_GTF(ide_drive_t *drive, port = hwif->channel ? drive->dn - 2: drive->dn; DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n", - hwif->name, dev->bus_id, port, hwif->channel); + hwif->name, dev_name(dev), port, hwif->channel); if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) { DEBPRINT("%s drive %d:%d not present\n", diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index cae6937..0bfeb0c 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -787,6 +787,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) if (blk_fs_request(rq)) { ide_end_request(drive, 1, rq->nr_sectors); return ide_stopped; + } else if (rq->cmd_type == REQ_TYPE_ATA_PC && !rq->bio) { + ide_end_request(drive, 1, 1); + return ide_stopped; } goto end_request; } diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index cc16331..9ee51ad 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -418,11 +418,14 @@ void ide_map_sg(ide_drive_t *drive, struct request *rq) ide_hwif_t *hwif = drive->hwif; struct scatterlist *sg = hwif->sg_table; - if (rq->cmd_type != REQ_TYPE_ATA_TASKFILE) { - hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); - } else { + if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE); hwif->sg_nents = 1; + } else if (!rq->bio) { + sg_init_one(sg, rq->data, rq->data_len); + hwif->sg_nents = 1; + } else { + hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); } } diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 0db1ed9..ce0818a 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1467,6 +1467,30 @@ struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws) } EXPORT_SYMBOL_GPL(ide_host_alloc); +static void ide_port_free(ide_hwif_t *hwif) +{ + ide_port_free_devices(hwif); + ide_free_port_slot(hwif->index); + kfree(hwif); +} + +static void ide_disable_port(ide_hwif_t *hwif) +{ + struct ide_host *host = hwif->host; + int i; + + printk(KERN_INFO "%s: disabling port\n", hwif->name); + + for (i = 0; i < MAX_HOST_PORTS; i++) { + if (host->ports[i] == hwif) { + host->ports[i] = NULL; + host->n_ports--; + } + } + + ide_port_free(hwif); +} + int ide_host_register(struct ide_host *host, const struct ide_port_info *d, hw_regs_t **hws) { @@ -1507,8 +1531,12 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, hwif->present = 1; if (hwif->chipset != ide_4drives || !hwif->mate || - !hwif->mate->present) - ide_register_port(hwif); + !hwif->mate->present) { + if (ide_register_port(hwif)) { + ide_disable_port(hwif); + continue; + } + } if (hwif->present) ide_port_tune_devices(hwif); @@ -1521,7 +1549,8 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, if (hwif_init(hwif) == 0) { printk(KERN_INFO "%s: failed to initialize IDE " "interface\n", hwif->name); - hwif->present = 0; + device_unregister(&hwif->gendev); + ide_disable_port(hwif); continue; } @@ -1660,12 +1689,8 @@ void ide_host_free(struct ide_host *host) int i; ide_host_for_each_port(i, hwif, host) { - if (hwif == NULL) - continue; - - ide_port_free_devices(hwif); - ide_free_port_slot(hwif->index); - kfree(hwif); + if (hwif) + ide_port_free(hwif); } kfree(host); diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c index 5b2e3af4..08c4fa3 100644 --- a/drivers/ide/qd65xx.c +++ b/drivers/ide/qd65xx.c @@ -16,7 +16,7 @@ /* * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by - * Samuel Thibault <samuel.thibault@fnac.net> + * Samuel Thibault <samuel.thibault@ens-lyon.org> */ #include <linux/module.h> diff --git a/drivers/ide/qd65xx.h b/drivers/ide/qd65xx.h index 6636f96..d7e67a1 100644 --- a/drivers/ide/qd65xx.h +++ b/drivers/ide/qd65xx.h @@ -4,7 +4,7 @@ /* * Authors: Petr Soucek <petr@ryston.cz> - * Samuel Thibault <samuel.thibault@fnac.net> + * Samuel Thibault <samuel.thibault@ens-lyon.org> */ /* truncates a in [b,c] */ diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c index 882f6f0..40b0812 100644 --- a/drivers/ide/tx4939ide.c +++ b/drivers/ide/tx4939ide.c @@ -261,9 +261,9 @@ static int tx4939ide_build_dmatable(ide_drive_t *drive, struct request *rq) bcount = cur_len; /* * This workaround for zero count seems required. - * (standard ide_build_dmatable do it too) + * (standard ide_build_dmatable does it too) */ - if ((bcount & 0xffff) == 0x0000) + if (bcount == 0x10000) bcount = 0x8000; *table++ = bcount & 0xffff; *table++ = cur_addr; diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index 703c3ee..6092fe3 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c @@ -448,6 +448,11 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS; #endif +#ifdef CONFIG_AMIGAONE + if (machine_is(amigaone)) + d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS; +#endif + d.udma_mask = via_config->udma_mask; vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index a329e6b..3838bc4 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -1823,6 +1823,10 @@ static int dv1394_open(struct inode *inode, struct file *file) #endif + printk(KERN_INFO "%s: NOTE, the dv1394 interface is unsupported " + "and will not be available in the new firewire driver stack. " + "Try libraw1394 based programs instead.\n", current->comm); + return 0; } @@ -2567,10 +2571,6 @@ static int __init dv1394_init_module(void) { int ret; - printk(KERN_WARNING - "NOTE: The dv1394 driver is unsupported and may be removed in a " - "future Linux release. Use raw1394 instead.\n"); - cdev_init(&dv1394_cdev, &dv1394_fops); dv1394_cdev.owner = THIS_MODULE; ret = cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16); diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 1e3aea9..09658b2 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -25,13 +25,13 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector) { dev_info_t *hash; linear_conf_t *conf = mddev_to_conf(mddev); + sector_t idx = sector >> conf->sector_shift; /* * sector_div(a,b) returns the remainer and sets a to a/b */ - sector >>= conf->sector_shift; - (void)sector_div(sector, conf->spacing); - hash = conf->hash_table[sector]; + (void)sector_div(idx, conf->spacing); + hash = conf->hash_table[idx]; while (sector >= hash->num_sectors + hash->start_sector) hash++; diff --git a/drivers/md/md.c b/drivers/md/md.c index 41e2509..4495104 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1481,6 +1481,11 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) if (find_rdev_nr(mddev, rdev->desc_nr)) return -EBUSY; } + if (mddev->max_disks && rdev->desc_nr >= mddev->max_disks) { + printk(KERN_WARNING "md: %s: array is limited to %d devices\n", + mdname(mddev), mddev->max_disks); + return -EBUSY; + } bdevname(rdev->bdev,b); while ( (s=strchr(b, '/')) != NULL) *s = '!'; @@ -2441,6 +2446,15 @@ static void analyze_sbs(mddev_t * mddev) i = 0; rdev_for_each(rdev, tmp, mddev) { + if (rdev->desc_nr >= mddev->max_disks || + i > mddev->max_disks) { + printk(KERN_WARNING + "md: %s: %s: only %d devices permitted\n", + mdname(mddev), bdevname(rdev->bdev, b), + mddev->max_disks); + kick_rdev_from_array(rdev); + continue; + } if (rdev != freshest) if (super_types[mddev->major_version]. validate_super(mddev, rdev)) { @@ -4614,13 +4628,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) * noticed in interrupt contexts ... */ - if (rdev->desc_nr == mddev->max_disks) { - printk(KERN_WARNING "%s: can not hot-add to full array!\n", - mdname(mddev)); - err = -EBUSY; - goto abort_unbind_export; - } - rdev->raid_disk = -1; md_update_sb(mddev, 1); @@ -4634,9 +4641,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) md_new_event(mddev); return 0; -abort_unbind_export: - unbind_rdev_from_array(rdev); - abort_export: export_rdev(rdev); return err; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 7b4f5f7..01e3cff 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1640,7 +1640,8 @@ static void raid1d(mddev_t *mddev) } bio = r1_bio->bios[r1_bio->read_disk]; - if ((disk=read_balance(conf, r1_bio)) == -1) { + if ((disk=read_balance(conf, r1_bio)) == -1 || + disk == r1_bio->read_disk) { printk(KERN_ALERT "raid1: %s: unrecoverable I/O" " read error for block %llu\n", bdevname(bio->bi_bdev,b), diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 6098b62..47fee05 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -576,6 +576,7 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) vv->vflip = c->value; break; default: { + mutex_unlock(&dev->lock); return -EINVAL; } } diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c index 64379f2..3ec2894 100644 --- a/drivers/media/common/tuners/mxl5007t.c +++ b/drivers/media/common/tuners/mxl5007t.c @@ -657,7 +657,7 @@ static int mxl5007t_get_status(struct dvb_frontend *fe, u32 *status) { struct mxl5007t_state *state = fe->tuner_priv; int rf_locked, ref_locked; - s32 rf_input_level; + s32 rf_input_level = 0; int ret; if (fe->ops.i2c_gate_ctrl) diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c index 98ee167..7e3aeaa 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c @@ -93,6 +93,9 @@ struct dvb_ca_slot { /* current state of the CAM */ int slot_state; + /* mutex used for serializing access to one CI slot */ + struct mutex slot_lock; + /* Number of CAMCHANGES that have occurred since last processing */ atomic_t camchange_count; @@ -711,14 +714,20 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b dprintk("%s\n", __func__); - // sanity check + /* sanity check */ if (bytes_write > ca->slot_info[slot].link_buf_size) return -EINVAL; - /* check if interface is actually waiting for us to read from it, or if a read is in progress */ + /* it is possible we are dealing with a single buffer implementation, + thus if there is data available for read or if there is even a read + already in progress, we do nothing but awake the kernel thread to + process the data if necessary. */ if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exitnowrite; if (status & (STATUSREG_DA | STATUSREG_RE)) { + if (status & STATUSREG_DA) + dvb_ca_en50221_thread_wakeup(ca); + status = -EAGAIN; goto exitnowrite; } @@ -987,6 +996,8 @@ static int dvb_ca_en50221_thread(void *data) /* go through all the slots processing them */ for (slot = 0; slot < ca->slot_count; slot++) { + mutex_lock(&ca->slot_info[slot].slot_lock); + // check the cam status + deal with CAMCHANGEs while (dvb_ca_en50221_check_camstatus(ca, slot)) { /* clear down an old CI slot if necessary */ @@ -1122,7 +1133,7 @@ static int dvb_ca_en50221_thread(void *data) case DVB_CA_SLOTSTATE_RUNNING: if (!ca->open) - continue; + break; // poll slots for data pktcount = 0; @@ -1146,6 +1157,8 @@ static int dvb_ca_en50221_thread(void *data) } break; } + + mutex_unlock(&ca->slot_info[slot].slot_lock); } } @@ -1181,6 +1194,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, switch (cmd) { case CA_RESET: for (slot = 0; slot < ca->slot_count; slot++) { + mutex_lock(&ca->slot_info[slot].slot_lock); if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) { dvb_ca_en50221_slot_shutdown(ca, slot); if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) @@ -1188,6 +1202,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, slot, DVB_CA_EN50221_CAMCHANGE_INSERTED); } + mutex_unlock(&ca->slot_info[slot].slot_lock); } ca->next_read_slot = 0; dvb_ca_en50221_thread_wakeup(ca); @@ -1308,7 +1323,9 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file, goto exit; } + mutex_lock(&ca->slot_info[slot].slot_lock); status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2); + mutex_unlock(&ca->slot_info[slot].slot_lock); if (status == (fraglen + 2)) { written = 1; break; @@ -1664,6 +1681,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; atomic_set(&ca->slot_info[i].camchange_count, 0); ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; + mutex_init(&ca->slot_info[i].slot_lock); } if (signal_pending(current)) { diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h index 8467e63..7df2e14 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h @@ -45,8 +45,10 @@ struct dvb_ca_en50221 { /* the module owning this structure */ struct module* owner; - /* NOTE: the read_*, write_* and poll_slot_status functions must use locks as - * they may be called from several threads at once */ + /* NOTE: the read_*, write_* and poll_slot_status functions will be + * called for different slots concurrently and need to use locks where + * and if appropriate. There will be no concurrent access to one slot. + */ /* functions for accessing attribute memory on the CAM */ int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address); diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/dvb/dvb-usb/af9005-fe.c index b1a9c4c..199ece0 100644 --- a/drivers/media/dvb/dvb-usb/af9005-fe.c +++ b/drivers/media/dvb/dvb-usb/af9005-fe.c @@ -220,7 +220,7 @@ static int af9005_get_post_vit_ber(struct dvb_frontend *fe, u16 * abort_count) { u32 loc_cw_count = 0, loc_err_count; - u16 loc_abort_count; + u16 loc_abort_count = 0; int ret; ret = diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index e1e9aa5..6a97a40 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -694,7 +694,12 @@ static int af9015_read_config(struct usb_device *udev) /* IR remote controller */ req.addr = AF9015_EEPROM_IR_MODE; - ret = af9015_rw_udev(udev, &req); + /* first message will timeout often due to possible hw bug */ + for (i = 0; i < 4; i++) { + ret = af9015_rw_udev(udev, &req); + if (!ret) + break; + } if (ret) goto error; deb_info("%s: IR mode:%d\n", __func__, val); @@ -835,18 +840,19 @@ static int af9015_read_config(struct usb_device *udev) if (!dvb_usb_af9015_dual_mode) af9015_config.dual_mode = 0; - /* set buffer size according to USB port speed */ + /* Set adapter0 buffer size according to USB port speed, adapter1 buffer + size can be static because it is enabled only USB2.0 */ for (i = 0; i < af9015_properties_count; i++) { /* USB1.1 set smaller buffersize and disable 2nd adapter */ if (udev->speed == USB_SPEED_FULL) { - af9015_properties[i].adapter->stream.u.bulk.buffersize = - TS_USB11_MAX_PACKET_SIZE; + af9015_properties[i].adapter[0].stream.u.bulk.buffersize + = TS_USB11_MAX_PACKET_SIZE; /* disable 2nd adapter because we don't have PID-filters */ af9015_config.dual_mode = 0; } else { - af9015_properties[i].adapter->stream.u.bulk.buffersize = - TS_USB20_MAX_PACKET_SIZE; + af9015_properties[i].adapter[0].stream.u.bulk.buffersize + = TS_USB20_MAX_PACKET_SIZE; } } @@ -1254,6 +1260,12 @@ static struct dvb_usb_device_properties af9015_properties[] = { .type = USB_BULK, .count = 6, .endpoint = 0x85, + .u = { + .bulk = { + .buffersize = + TS_USB20_MAX_PACKET_SIZE, + } + } }, } }, @@ -1353,6 +1365,12 @@ static struct dvb_usb_device_properties af9015_properties[] = { .type = USB_BULK, .count = 6, .endpoint = 0x85, + .u = { + .bulk = { + .buffersize = + TS_USB20_MAX_PACKET_SIZE, + } + } }, } }, diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 3917327..635d30a 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -1393,6 +1393,9 @@ struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) }, /* 40 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E) }, { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E_SE) }, + { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_EXPRESS) }, + { USB_DEVICE(USB_VID_TERRATEC, + USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -1537,7 +1540,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { { "DiBcom STK7700D reference design", { &dib0700_usb_id_table[14], NULL }, { NULL }, - } + }, + }, .rc_interval = DEFAULT_RC_INTERVAL, @@ -1557,7 +1561,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 2, + .num_device_descs = 3, .devices = { { "ASUS My Cinema U3000 Mini DVBT Tuner", { &dib0700_usb_id_table[23], NULL }, @@ -1566,6 +1570,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { "Yuan EC372S", { &dib0700_usb_id_table[31], NULL }, { NULL }, + }, + { "Terratec Cinergy T Express", + { &dib0700_usb_id_table[42], NULL }, + { NULL }, } }, @@ -1653,7 +1661,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { } }, - .num_device_descs = 4, + .num_device_descs = 5, .devices = { { "DiBcom STK7070PD reference design", { &dib0700_usb_id_table[17], NULL }, @@ -1670,6 +1678,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { { "Hauppauge Nova-TD-500 (84xxx)", { &dib0700_usb_id_table[36], NULL }, { NULL }, + }, + { "Terratec Cinergy DT USB XS Diversity", + { &dib0700_usb_id_table[43], NULL }, + { NULL }, } } }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index a4fca3f..0db0c06 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -162,8 +162,10 @@ #define USB_PID_AVERMEDIA_A309 0xa309 #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a +#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 #define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060 +#define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e #define USB_PID_PINNACLE_PCTV2000E 0x022c diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c index ec4e08d..1e81e71 100644 --- a/drivers/media/dvb/frontends/drx397xD.c +++ b/drivers/media/dvb/frontends/drx397xD.c @@ -646,7 +646,7 @@ static int drx_tune(struct drx397xD_state *s, u32 edi = 0, ebx = 0, ebp = 0, edx = 0; u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0; - int rc, df_tuner; + int rc, df_tuner = 0; int a, b, c, d; pr_debug("%s %d\n", __func__, s->config.d60); diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c index cf4d893..3e08d98 100644 --- a/drivers/media/dvb/frontends/s5h1409.c +++ b/drivers/media/dvb/frontends/s5h1409.c @@ -545,9 +545,6 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe, s5h1409_enable_modulation(fe, p->u.vsb.modulation); - /* Allow the demod to settle */ - msleep(100); - if (fe->ops.tuner_ops.set_params) { if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -562,6 +559,10 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe, s5h1409_set_qam_interleave_mode(fe); } + /* Issue a reset to the demod so it knows to resync against the + newly tuned frequency */ + s5h1409_softreset(fe); + return 0; } diff --git a/drivers/media/dvb/frontends/stb0899_algo.c b/drivers/media/dvb/frontends/stb0899_algo.c index 83dc7e1..a67d177 100644 --- a/drivers/media/dvb/frontends/stb0899_algo.c +++ b/drivers/media/dvb/frontends/stb0899_algo.c @@ -31,6 +31,8 @@ inline u32 stb0899_do_div(u64 n, u32 d) return n; } +#if 0 +/* These functions are currently unused */ /* * stb0899_calc_srate * Compute symbol rate @@ -63,6 +65,7 @@ static u32 stb0899_get_srate(struct stb0899_state *state) return stb0899_calc_srate(internal->master_clk, sfr); } +#endif /* * stb0899_set_srate diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 1638e1d..83e9e77 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -470,6 +470,7 @@ static void frontend_init(struct budget *budget) budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config, &budget->i2c_adap); if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params; + budget->dvb_frontend->tuner_priv = NULL; break; } break; diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 0aa96df..d91e063 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -1384,7 +1384,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) static int ttusb_dec_init_stb(struct ttusb_dec *dec) { int result; - unsigned int mode, model, version; + unsigned int mode = 0, model = 0, version = 0; dprintk("%s\n", __func__); diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 0747dc8..fdfc7bf 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -194,10 +194,10 @@ static int amradio_start(struct amradio_device *radio) return retval; } - mutex_unlock(&radio->lock); - radio->muted = 0; + mutex_unlock(&radio->lock); + return retval; } @@ -230,10 +230,10 @@ static int amradio_stop(struct amradio_device *radio) return retval; } - mutex_unlock(&radio->lock); - radio->muted = 1; + mutex_unlock(&radio->lock); + return retval; } @@ -284,10 +284,10 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) return retval; } - mutex_unlock(&radio->lock); - radio->stereo = 0; + mutex_unlock(&radio->lock); + return retval; } diff --git a/drivers/media/video/cs5345.c b/drivers/media/video/cs5345.c index 14bebf8..87e9107 100644 --- a/drivers/media/video/cs5345.c +++ b/drivers/media/video/cs5345.c @@ -18,7 +18,6 @@ */ -#include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/i2c.h> diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 8f1db57..bfe2584 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c @@ -1586,7 +1586,8 @@ static int mpeg_open(struct file *file) lock_kernel(); list_for_each(list, &cx23885_devlist) { h = list_entry(list, struct cx23885_dev, devlist); - if (h->v4l_device->minor == minor) { + if (h->v4l_device && + h->v4l_device->minor == minor) { dev = h; break; } diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 2d81c4d..eaa1189 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -730,12 +730,13 @@ static int video_open(struct file *file) lock_kernel(); list_for_each(list, &cx23885_devlist) { h = list_entry(list, struct cx23885_dev, devlist); - if (h->video_dev->minor == minor) { + if (h->video_dev && + h->video_dev->minor == minor) { dev = h; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; } if (h->vbi_dev && - h->vbi_dev->minor == minor) { + h->vbi_dev->minor == minor) { dev = h; type = V4L2_BUF_TYPE_VBI_CAPTURE; } diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 88f2fd3..25eb3bec 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -1382,6 +1382,14 @@ static int cx25840_log_status(struct v4l2_subdev *sd) static int cx25840_command(struct i2c_client *client, unsigned cmd, void *arg) { + /* ignore this command */ + if (cmd == TUNER_SET_TYPE_ADDR || cmd == TUNER_SET_CONFIG) + return 0; + + /* Old-style drivers rely on initialization on first use, so + call the init whenever a command is issued to this driver. + New-style drivers using v4l2_subdev should call init explicitly. */ + cx25840_init(i2c_get_clientdata(client), 0); return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); } diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 613dfea..aef5297 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -614,34 +614,41 @@ static struct stv0288_config tevii_tuner_earda_config = { .set_ts_params = cx24116_set_ts_param, }; -static int dvb_register(struct cx8802_dev *dev) +static int cx8802_alloc_frontends(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; - struct videobuf_dvb_frontend *fe0, *fe1 = NULL; - int mfe_shared = 0; /* bus not shared by default */ + struct videobuf_dvb_frontend *fe = NULL; int i; - if (0 != core->i2c_rc) { - printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name); - goto frontend_detach; - } - - if (!core->board.num_frontends) - return -EINVAL; - mutex_init(&dev->frontends.lock); INIT_LIST_HEAD(&dev->frontends.felist); + if (!core->board.num_frontends) + return -ENODEV; + printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, core->board.num_frontends); for (i = 1; i <= core->board.num_frontends; i++) { - fe0 = videobuf_dvb_alloc_frontend(&dev->frontends, i); - if (!fe0) { + fe = videobuf_dvb_alloc_frontend(&dev->frontends, i); + if (!fe) { printk(KERN_ERR "%s() failed to alloc\n", __func__); videobuf_dvb_dealloc_frontends(&dev->frontends); - goto frontend_detach; + return -ENOMEM; } } + return 0; +} + +static int dvb_register(struct cx8802_dev *dev) +{ + struct cx88_core *core = dev->core; + struct videobuf_dvb_frontend *fe0, *fe1 = NULL; + int mfe_shared = 0; /* bus not shared by default */ + + if (0 != core->i2c_rc) { + printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name); + goto frontend_detach; + } /* Get the first frontend */ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); @@ -1243,6 +1250,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) struct cx88_core *core = drv->core; struct cx8802_dev *dev = drv->core->dvbdev; int err; + struct videobuf_dvb_frontend *fe; + int i; dprintk( 1, "%s\n", __func__); dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", @@ -1258,39 +1267,34 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) /* If vp3054 isn't enabled, a stub will just return 0 */ err = vp3054_i2c_probe(dev); if (0 != err) - goto fail_probe; + goto fail_core; /* dvb stuff */ printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); dev->ts_gen_cntrl = 0x0c; + err = cx8802_alloc_frontends(dev); + if (err) + goto fail_core; + err = -ENODEV; - if (core->board.num_frontends) { - struct videobuf_dvb_frontend *fe; - int i; - - for (i = 1; i <= core->board.num_frontends; i++) { - fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i); - if (fe == NULL) { - printk(KERN_ERR "%s() failed to get frontend(%d)\n", + for (i = 1; i <= core->board.num_frontends; i++) { + fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i); + if (fe == NULL) { + printk(KERN_ERR "%s() failed to get frontend(%d)\n", __func__, i); - goto fail_probe; - } - videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops, + goto fail_probe; + } + videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops, &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx88_buffer), dev); - /* init struct videobuf_dvb */ - fe->dvb.name = dev->core->name; - } - } else { - /* no frontends allocated */ - printk(KERN_ERR "%s/2 .num_frontends should be non-zero\n", - core->name); - goto fail_core; + /* init struct videobuf_dvb */ + fe->dvb.name = dev->core->name; } + err = dvb_register(dev); if (err) /* frontends/adapter de-allocated in dvb_register */ diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 60a8b31..6025fdd 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -336,8 +336,8 @@ struct cx88_core { /* config info -- dvb */ #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) int (*prev_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); - void (*gate_ctrl)(struct cx88_core *core, int open); #endif + void (*gate_ctrl)(struct cx88_core *core, int open); /* state info */ struct task_struct *kthread; diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 94378cc..5d882a4 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -62,9 +62,15 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) dprintk("Stopping isoc\n"); for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { - usb_unlink_urb(dev->adev.urb[i]); + if (!irqs_disabled()) + usb_kill_urb(dev->adev.urb[i]); + else + usb_unlink_urb(dev->adev.urb[i]); usb_free_urb(dev->adev.urb[i]); dev->adev.urb[i] = NULL; + + kfree(dev->adev.transfer_buffer[i]); + dev->adev.transfer_buffer[i] = NULL; } return 0; @@ -389,11 +395,15 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream *substream) { - struct em28xx *dev; + unsigned long flags; + struct em28xx *dev; snd_pcm_uframes_t hwptr_done; + dev = snd_pcm_substream_chip(substream); + spin_lock_irqsave(&dev->adev.slock, flags); hwptr_done = dev->adev.hwptr_done_capture; + spin_unlock_irqrestore(&dev->adev.slock, flags); return hwptr_done; } diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index ef9bf00..3b3ca3f 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -102,6 +102,18 @@ static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = { /* Board - EM2870 Kworld 355u Analog - No input analog */ +static struct em28xx_reg_seq kworld_330u_analog[] = { + {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, + {EM2880_R04_GPO, 0x00, 0xff, 10}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq kworld_330u_digital[] = { + {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, + {EM2880_R04_GPO, 0x08, 0xff, 10}, + { -1, -1, -1, -1}, +}; + /* Callback for the most boards */ static struct em28xx_reg_seq default_tuner_gpio[] = { {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, @@ -1177,29 +1189,33 @@ struct em28xx_board em28xx_boards[] = { .gpio = hauppauge_wintv_hvr_900_analog, } }, }, - [EM2883_BOARD_KWORLD_HYBRID_A316] = { + [EM2883_BOARD_KWORLD_HYBRID_330U] = { .name = "Kworld PlusTV HD Hybrid 330", .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, .decoder = EM28XX_TVP5150, .mts_firmware = 1, .has_dvb = 1, - .dvb_gpio = default_digital, + .dvb_gpio = kworld_330u_digital, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_EEPROM_ON_BOARD | EM28XX_I2C_EEPROM_KEY_VALID, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, - .gpio = default_analog, + .gpio = kworld_330u_analog, + .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, + .gpio = kworld_330u_analog, + .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, .amux = EM28XX_AMUX_LINE_IN, - .gpio = hauppauge_wintv_hvr_900_analog, + .gpio = kworld_330u_analog, } }, }, [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = { @@ -1249,7 +1265,7 @@ struct usb_device_id em28xx_id_table [] = { { USB_DEVICE(0xeb1a, 0xe310), .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD }, { USB_DEVICE(0xeb1a, 0xa316), - .driver_info = EM2883_BOARD_KWORLD_HYBRID_A316 }, + .driver_info = EM2883_BOARD_KWORLD_HYBRID_330U }, { USB_DEVICE(0xeb1a, 0xe320), .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD_II }, { USB_DEVICE(0xeb1a, 0xe323), @@ -1526,6 +1542,10 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) /* FIXME: Better to specify the needed IF */ ctl->demod = XC3028_FE_DEFAULT; break; + case EM2883_BOARD_KWORLD_HYBRID_330U: + ctl->demod = XC3028_FE_CHINA; + ctl->fname = XC2028_DEFAULT_FIRMWARE; + break; default: ctl->demod = XC3028_FE_OREN538; } diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index eb5fb05..94fb1b6 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -438,6 +438,10 @@ int em28xx_audio_analog_set(struct em28xx *dev) if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { int vol; + em28xx_write_ac97(dev, AC97_POWER_DOWN_CTRL, 0x4200); + em28xx_write_ac97(dev, AC97_EXT_AUD_CTRL, 0x0031); + em28xx_write_ac97(dev, AC97_PCM_IN_SRATE, 0xbb80); + /* LSB: left channel - both channels with the same level */ vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8); @@ -454,6 +458,15 @@ int em28xx_audio_analog_set(struct em28xx *dev) em28xx_warn("couldn't setup AC97 register %d\n", outputs[i].reg); } + + if (dev->ctl_aoutput & EM28XX_AOUT_PCM_IN) { + int sel = ac97_return_record_select(dev->ctl_aoutput); + + /* Use the same input for both left and right channels */ + sel |= (sel << 8); + + em28xx_write_ac97(dev, AC97_RECORD_SELECT, sel); + } } return ret; @@ -847,8 +860,11 @@ void em28xx_uninit_isoc(struct em28xx *dev) for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { urb = dev->isoc_ctl.urb[i]; if (urb) { - usb_kill_urb(urb); - usb_unlink_urb(urb); + if (!irqs_disabled()) + usb_kill_urb(urb); + else + usb_unlink_urb(urb); + if (dev->isoc_ctl.transfer_buffer[i]) { usb_buffer_free(dev->udev, urb->transfer_buffer_length, diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index d38cb21..9ad8527 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -28,6 +28,7 @@ #include "lgdt330x.h" #include "zl10353.h" +#include "s5h1409.h" #ifdef EM28XX_DRX397XD_SUPPORT #include "drx397xD.h" #endif @@ -232,6 +233,15 @@ static struct zl10353_config em28xx_zl10353_with_xc3028 = { .if2 = 45600, }; +static struct s5h1409_config em28xx_s5h1409_with_xc3028 = { + .demod_address = 0x32 >> 1, + .output_mode = S5H1409_PARALLEL_OUTPUT, + .gpio = S5H1409_GPIO_OFF, + .inversion = S5H1409_INVERSION_OFF, + .status_mode = S5H1409_DEMODLOCKING, + .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK +}; + #ifdef EM28XX_DRX397XD_SUPPORT /* [TODO] djh - not sure yet what the device config needs to contain */ static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { @@ -412,7 +422,6 @@ static int dvb_init(struct em28xx *dev) case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: - case EM2883_BOARD_KWORLD_HYBRID_A316: case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: dvb->frontend = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, @@ -433,6 +442,15 @@ static int dvb_init(struct em28xx *dev) goto out_free; } break; + case EM2883_BOARD_KWORLD_HYBRID_330U: + dvb->frontend = dvb_attach(s5h1409_attach, + &em28xx_s5h1409_with_xc3028, + &dev->i2c_adap); + if (attach_xc3028(0x61, dev) < 0) { + result = -EINVAL; + goto out_free; + } + break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: #ifdef EM28XX_DRX397XD_SUPPORT /* We don't have the config structure properly populated, so diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 416b691..8e61b2c 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -886,10 +886,10 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) if (0 == INPUT(i)->type) return -EINVAL; - mutex_lock(&dev->lock); - - video_mux(dev, i); + dev->ctl_input = i; + mutex_lock(&dev->lock); + video_mux(dev, dev->ctl_input); mutex_unlock(&dev->lock); return 0; } @@ -939,6 +939,12 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; + + if (a->index >= MAX_EM28XX_INPUT) + return -EINVAL; + if (0 == INPUT(a->index)->type) + return -EINVAL; + mutex_lock(&dev->lock); dev->ctl_ainput = INPUT(a->index)->amux; @@ -1950,6 +1956,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, int em28xx_register_analog_devices(struct em28xx *dev) { + u8 val; int ret; printk(KERN_INFO "%s: v4l2 driver version %d.%d.%d\n", @@ -1957,34 +1964,34 @@ int em28xx_register_analog_devices(struct em28xx *dev) (EM28XX_VERSION_CODE >> 16) & 0xff, (EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff); + /* set default norm */ + dev->norm = em28xx_video_template.current_norm; + dev->width = norm_maxw(dev); + dev->height = norm_maxh(dev); + dev->interlaced = EM28XX_INTERLACED_DEFAULT; + dev->hscale = 0; + dev->vscale = 0; + dev->ctl_input = 0; + /* Analog specific initialization */ dev->format = &format[0]; - video_mux(dev, 0); + video_mux(dev, dev->ctl_input); + + /* Audio defaults */ + dev->mute = 1; + dev->volume = 0x1f; /* enable vbi capturing */ /* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */ -/* em28xx_write_reg(dev, EM28XX_R0F_XCLK, 0x80); clk register */ + val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, (EM28XX_XCLK_AUDIO_UNMUTE | val)); em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51); - dev->mute = 1; /* maybe not the right place... */ - dev->volume = 0x1f; - em28xx_set_outfmt(dev); em28xx_colorlevels_set_default(dev); em28xx_compression_disable(dev); - /* set default norm */ - dev->norm = em28xx_video_template.current_norm; - dev->width = norm_maxw(dev); - dev->height = norm_maxh(dev); - dev->interlaced = EM28XX_INTERLACED_DEFAULT; - dev->hscale = 0; - dev->vscale = 0; - - /* FIXME: This is a very bad hack! Not all devices have TV on input 2 */ - dev->ctl_input = 2; - /* allocate and fill video video_device struct */ dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); if (!dev->vdev) { diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 6c6b94a..dd2cd36 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -94,7 +94,7 @@ #define EM2882_BOARD_KWORLD_VS_DVBT 54 #define EM2882_BOARD_TERRATEC_HYBRID_XS 55 #define EM2882_BOARD_PINNACLE_HYBRID_PRO 56 -#define EM2883_BOARD_KWORLD_HYBRID_A316 57 +#define EM2883_BOARD_KWORLD_HYBRID_330U 57 #define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58 #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 #define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61 @@ -300,13 +300,32 @@ enum em28xx_amux { }; enum em28xx_aout { + /* AC97 outputs */ EM28XX_AOUT_MASTER = 1 << 0, EM28XX_AOUT_LINE = 1 << 1, EM28XX_AOUT_MONO = 1 << 2, EM28XX_AOUT_LFE = 1 << 3, EM28XX_AOUT_SURR = 1 << 4, + + /* PCM IN Mixer - used by AC97_RECORD_SELECT register */ + EM28XX_AOUT_PCM_IN = 1 << 7, + + /* Bits 10-8 are used to indicate the PCM IN record select */ + EM28XX_AOUT_PCM_MIC_PCM = 0 << 8, + EM28XX_AOUT_PCM_CD = 1 << 8, + EM28XX_AOUT_PCM_VIDEO = 2 << 8, + EM28XX_AOUT_PCM_AUX = 3 << 8, + EM28XX_AOUT_PCM_LINE = 4 << 8, + EM28XX_AOUT_PCM_STEREO = 5 << 8, + EM28XX_AOUT_PCM_MONO = 6 << 8, + EM28XX_AOUT_PCM_PHONE = 7 << 8, }; +static inline int ac97_return_record_select(int a_out) +{ + return (a_out & 0x700) >> 8; +} + struct em28xx_reg_seq { int reg; unsigned char val, mask; diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 5e36b9a..2ed2452 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -423,7 +423,8 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) break; gspca_dev->urb[i] = NULL; - usb_kill_urb(urb); + if (!gspca_dev->present) + usb_kill_urb(urb); if (urb->transfer_buffer != NULL) usb_buffer_free(gspca_dev->dev, urb->transfer_buffer_length, @@ -1950,7 +1951,6 @@ void gspca_disconnect(struct usb_interface *intf) struct gspca_dev *gspca_dev = usb_get_intfdata(intf); gspca_dev->present = 0; - gspca_dev->streaming = 0; usb_set_intfdata(intf, NULL); diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index e8e5921..c46c990 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -949,8 +949,10 @@ static int __devinit ivtv_probe(struct pci_dev *dev, itv->instance = atomic_inc_return(&ivtv_instance) - 1; retval = v4l2_device_register(&dev->dev, &itv->device); - if (retval) + if (retval) { + kfree(itv); return retval; + } /* "ivtv + PCI ID" is a bit of a mouthful, so use "ivtv + instance" instead. */ snprintf(itv->device.name, sizeof(itv->device.name), diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 39fbc97..0d81018 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -62,7 +62,6 @@ #include <linux/poll.h> #include <linux/slab.h> #include <linux/vmalloc.h> -#include <linux/version.h> #include <asm/io.h> #include "pwc.h" diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index d6848f7..05221d4 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -149,7 +149,7 @@ static const struct i2c_reg_value saa7127_init_config_common[] = { { SAA7127_REG_COPYGEN_0, 0x77 }, { SAA7127_REG_COPYGEN_1, 0x41 }, { SAA7127_REG_COPYGEN_2, 0x00 }, /* Macrovision enable/disable */ - { SAA7127_REG_OUTPUT_PORT_CONTROL, 0x9e }, + { SAA7127_REG_OUTPUT_PORT_CONTROL, 0xbf }, { SAA7127_REG_GAIN_LUMINANCE_RGB, 0x00 }, { SAA7127_REG_GAIN_COLORDIFF_RGB, 0x00 }, { SAA7127_REG_INPUT_PORT_CONTROL_1, 0x80 }, /* for color bars */ @@ -488,12 +488,18 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output) break; case SAA7127_OUTPUT_TYPE_COMPOSITE: - state->reg_2d = 0x08; /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */ + if (state->ident == V4L2_IDENT_SAA7129) + state->reg_2d = 0x20; /* CVBS only */ + else + state->reg_2d = 0x08; /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */ state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ break; case SAA7127_OUTPUT_TYPE_SVIDEO: - state->reg_2d = 0xff; /* 11111111 croma -> R, luma -> CVBS + G + B */ + if (state->ident == V4L2_IDENT_SAA7129) + state->reg_2d = 0x18; /* Y + C */ + else + state->reg_2d = 0xff; /*11111111 croma -> R, luma -> CVBS + G + B */ state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ break; @@ -508,7 +514,10 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output) break; case SAA7127_OUTPUT_TYPE_BOTH: - state->reg_2d = 0xbf; + if (state->ident == V4L2_IDENT_SAA7129) + state->reg_2d = 0x38; + else + state->reg_2d = 0xbf; state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ break; @@ -731,24 +740,6 @@ static int saa7127_probe(struct i2c_client *client, return -ENODEV; } - /* Configure Encoder */ - - v4l2_dbg(1, debug, sd, "Configuring encoder\n"); - saa7127_write_inittab(sd, saa7127_init_config_common); - saa7127_set_std(sd, V4L2_STD_NTSC); - saa7127_set_output_type(sd, SAA7127_OUTPUT_TYPE_BOTH); - saa7127_set_vps(sd, &vbi); - saa7127_set_wss(sd, &vbi); - saa7127_set_cc(sd, &vbi); - saa7127_set_xds(sd, &vbi); - if (test_image == 1) - /* The Encoder has an internal Colorbar generator */ - /* This can be used for debugging */ - saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_TEST_IMAGE); - else - saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL); - saa7127_set_video_enable(sd, 1); - if (id->driver_data) { /* Chip type is already known */ state->ident = id->driver_data; } else { /* Needs detection */ @@ -770,6 +761,23 @@ static int saa7127_probe(struct i2c_client *client, v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, client->addr << 1, client->adapter->name); + + v4l2_dbg(1, debug, sd, "Configuring encoder\n"); + saa7127_write_inittab(sd, saa7127_init_config_common); + saa7127_set_std(sd, V4L2_STD_NTSC); + saa7127_set_output_type(sd, SAA7127_OUTPUT_TYPE_BOTH); + saa7127_set_vps(sd, &vbi); + saa7127_set_wss(sd, &vbi); + saa7127_set_cc(sd, &vbi); + saa7127_set_xds(sd, &vbi); + if (test_image == 1) + /* The Encoder has an internal Colorbar generator */ + /* This can be used for debugging */ + saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_TEST_IMAGE); + else + saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL); + saa7127_set_video_enable(sd, 1); + if (state->ident == V4L2_IDENT_SAA7129) saa7127_write_inittab(sd, saa7129_init_config_extra); return 0; diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 26194a0..c750d3d 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -1089,7 +1089,11 @@ static int saa7134_alsa_init(void) list_for_each(list,&saa7134_devlist) { dev = list_entry(list, struct saa7134_dev, devlist); - alsa_device_init(dev); + if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130) + printk(KERN_INFO "%s/alsa: %s doesn't support digital audio\n", + dev->name, saa7134_boards[dev->board].name); + else + alsa_device_init(dev); } if (dev == NULL) diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index dfbe08a..99221d7 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -660,6 +660,10 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) saa_writel(SAA7134_IRQ1, 0); saa_writel(SAA7134_IRQ2, 0); + + /* Clear any stale IRQ reports */ + saa_writel(SAA7134_IRQ_REPORT, saa_readl(SAA7134_IRQ_REPORT)); + mutex_init(&dev->lock); spin_lock_init(&dev->slock); diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c index 454ad1d..88c5e94 100644 --- a/drivers/media/video/saa717x.c +++ b/drivers/media/video/saa717x.c @@ -30,7 +30,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/sched.h> diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index 56f0c0e..00c6cbe 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -242,7 +242,7 @@ static int tda9875_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int tda9875_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) { struct tda9875 *t = to_state(sd); - int chvol=0, volume, balance, left, right; + int chvol = 0, volume = 0, balance = 0, left, right; switch (ctrl->id) { case V4L2_CID_AUDIO_VOLUME: diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 3b0b84c..78277ab 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -427,6 +427,9 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" }; memset(tvee, 0, sizeof(*tvee)); + tvee->tuner_type = TUNER_ABSENT; + tvee->tuner2_type = TUNER_ABSENT; + done = len = beenhere = 0; /* Different eeprom start offsets for em28xx, cx2388x and cx23418 */ diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c index ac9aa40..8e23aa5 100644 --- a/drivers/media/video/tvp514x.c +++ b/drivers/media/video/tvp514x.c @@ -1401,7 +1401,7 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) decoder->pdata = client->dev.platform_data; if (!decoder->pdata) { - v4l_err(client, "No platform data\n!!"); + v4l_err(client, "No platform data!!\n"); return -ENODEV; } /* diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index 4f16eff..f4522bb 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c @@ -21,7 +21,6 @@ */ -#include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/i2c.h> diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index 4b712f6..a5fb74b 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c @@ -21,7 +21,6 @@ * 02110-1301, USA. */ -#include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/i2c.h> diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index 9907b9a..6b66ae4 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -157,7 +157,7 @@ usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) struct i2c_msg *pmsg; struct usb_usbvision *usbvision; int i, ret; - unsigned char addr; + unsigned char addr = 0; usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap); diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 2208165..d2576f6 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -1,7 +1,7 @@ /* * uvc_ctrl.c -- USB Video Class driver - Controls * - * Copyright (C) 2005-2008 + * Copyright (C) 2005-2009 * Laurent Pinchart (laurent.pinchart@skynet.be) * * This program is free software; you can redistribute it and/or modify @@ -12,7 +12,6 @@ */ #include <linux/kernel.h> -#include <linux/version.h> #include <linux/list.h> #include <linux/module.h> #include <linux/uaccess.h> @@ -29,7 +28,7 @@ #define UVC_CTRL_DATA_BACKUP 1 /* ------------------------------------------------------------------------ - * Control, formats, ... + * Controls */ static struct uvc_control_info uvc_ctrls[] = { @@ -635,7 +634,7 @@ static __s32 uvc_get_le_value(struct uvc_control_mapping *mapping, mask = (1 << bits) - 1; } - /* Sign-extend the value if needed */ + /* Sign-extend the value if needed. */ if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) value |= -(value & (1 << (mapping->size - 1))); diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 89d8bd1..b128732 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -1,7 +1,7 @@ /* * uvc_driver.c -- USB Video Class driver * - * Copyright (C) 2005-2008 + * Copyright (C) 2005-2009 * Laurent Pinchart (laurent.pinchart@skynet.be) * * This program is free software; you can redistribute it and/or modify @@ -24,7 +24,6 @@ */ #include <linux/kernel.h> -#include <linux/version.h> #include <linux/list.h> #include <linux/module.h> #include <linux/usb.h> @@ -49,7 +48,7 @@ static unsigned int uvc_quirks_param; unsigned int uvc_trace_param; /* ------------------------------------------------------------------------ - * Control, formats, ... + * Video formats */ static struct uvc_format_desc uvc_fmts[] = { @@ -474,7 +473,7 @@ static int uvc_parse_format(struct uvc_device *dev, /* Several UVC chipsets screw up dwMaxVideoFrameBufferSize * completely. Observed behaviours range from setting the - * value to 1.1x the actual frame size of hardwiring the + * value to 1.1x the actual frame size to hardwiring the * 16 low bits to 0. This results in a higher than necessary * memory usage as well as a wrong image size information. For * uncompressed formats this can be fixed by computing the @@ -487,7 +486,7 @@ static int uvc_parse_format(struct uvc_device *dev, /* Some bogus devices report dwMinFrameInterval equal to * dwMaxFrameInterval and have dwFrameIntervalStep set to * zero. Setting all null intervals to 1 fixes the problem and - * some other divisions by zero which could happen. + * some other divisions by zero that could happen. */ for (i = 0; i < n; ++i) { interval = get_unaligned_le32(&buffer[26+4*i]); @@ -1200,13 +1199,13 @@ static void uvc_unregister_video(struct uvc_device *dev) * Scan the UVC descriptors to locate a chain starting at an Output Terminal * and containing the following units: * - * - a USB Streaming Output Terminal + * - one Output Terminal (USB Streaming or Display) * - zero or one Processing Unit * - zero, one or mode single-input Selector Units * - zero or one multiple-input Selector Units, provided all inputs are * connected to input terminals * - zero, one or mode single-input Extension Units - * - one Camera Input Terminal, or one or more External terminals. + * - one or more Input Terminals (Camera, External or USB Streaming) * * A side forward scan is made on each detected entity to check for additional * extension units. @@ -1531,10 +1530,6 @@ static int uvc_register_video(struct uvc_device *dev) /* Set the driver data before calling video_register_device, otherwise * uvc_v4l2_open might race us. - * - * FIXME: usb_set_intfdata hasn't been called so far. Is that a - * problem ? Does any function which could be called here get - * a pointer to the usb_interface ? */ dev->video.vdev = vdev; video_set_drvdata(vdev, &dev->video); @@ -1569,7 +1564,7 @@ void uvc_delete(struct kref *kref) struct uvc_device *dev = container_of(kref, struct uvc_device, kref); struct list_head *p, *n; - /* Unregister the video device */ + /* Unregister the video device. */ uvc_unregister_video(dev); usb_put_intf(dev->intf); usb_put_dev(dev->udev); @@ -1612,7 +1607,7 @@ static int uvc_probe(struct usb_interface *intf, uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n", udev->devpath); - /* Allocate memory for the device and initialize it */ + /* Allocate memory for the device and initialize it. */ if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL) return -ENOMEM; @@ -1633,14 +1628,14 @@ static int uvc_probe(struct usb_interface *intf, le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct)); - /* Parse the Video Class control descriptor */ + /* Parse the Video Class control descriptor. */ if (uvc_parse_control(dev) < 0) { uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC " "descriptors.\n"); goto error; } - uvc_printk(KERN_INFO, "Found UVC %u.%02u device %s (%04x:%04x)\n", + uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n", dev->uvc_version >> 8, dev->uvc_version & 0xff, udev->product ? udev->product : "<unnamed>", le16_to_cpu(udev->descriptor.idVendor), @@ -1653,18 +1648,18 @@ static int uvc_probe(struct usb_interface *intf, "linux-uvc-devel mailing list.\n"); } - /* Initialize controls */ + /* Initialize controls. */ if (uvc_ctrl_init_device(dev) < 0) goto error; - /* Register the video devices */ + /* Register the video devices. */ if (uvc_register_video(dev) < 0) goto error; - /* Save our data pointer in the interface data */ + /* Save our data pointer in the interface data. */ usb_set_intfdata(intf, dev); - /* Initialize the interrupt URB */ + /* Initialize the interrupt URB. */ if ((ret = uvc_status_init(dev)) < 0) { uvc_printk(KERN_INFO, "Unable to initialize the status " "endpoint (%d), status interrupt will not be " @@ -1839,24 +1834,24 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0 }, /* Apple Built-In iSight */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x05ac, .idProduct = 0x8501, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_MINMAX | UVC_QUIRK_BUILTIN_ISIGHT }, /* Genesys Logic USB 2.0 PC Camera */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x05e3, - .idProduct = 0x0505, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_STREAM_NO_FID }, + .idVendor = 0x05e3, + .idProduct = 0x0505, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_STREAM_NO_FID }, /* MT6227 */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, diff --git a/drivers/media/video/uvc/uvc_isight.c b/drivers/media/video/uvc/uvc_isight.c index 37bdefd..436f462 100644 --- a/drivers/media/video/uvc/uvc_isight.c +++ b/drivers/media/video/uvc/uvc_isight.c @@ -3,6 +3,8 @@ * * Copyright (C) 2006-2007 * Ivan N. Zlatev <contact@i-nz.net> + * Copyright (C) 2008-2009 + * Laurent Pinchart <laurent.pinchart@skynet.be> * * 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 diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index 4254634..0155752 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -1,7 +1,7 @@ /* * uvc_queue.c -- USB Video Class driver - Buffers management * - * Copyright (C) 2005-2008 + * Copyright (C) 2005-2009 * Laurent Pinchart (laurent.pinchart@skynet.be) * * This program is free software; you can redistribute it and/or modify @@ -12,7 +12,6 @@ */ #include <linux/kernel.h> -#include <linux/version.h> #include <linux/mm.h> #include <linux/list.h> #include <linux/module.h> @@ -37,22 +36,22 @@ * to user space will return -EBUSY. * * Video buffers are managed using two queues. However, unlike most USB video - * drivers which use an in queue and an out queue, we use a main queue which - * holds all queued buffers (both 'empty' and 'done' buffers), and an irq - * queue which holds empty buffers. This design (copied from video-buf) - * minimizes locking in interrupt, as only one queue is shared between - * interrupt and user contexts. + * drivers that use an in queue and an out queue, we use a main queue to hold + * all queued buffers (both 'empty' and 'done' buffers), and an irq queue to + * hold empty buffers. This design (copied from video-buf) minimizes locking + * in interrupt, as only one queue is shared between interrupt and user + * contexts. * * Use cases * --------- * - * Unless stated otherwise, all operations which modify the irq buffers queue + * Unless stated otherwise, all operations that modify the irq buffers queue * are protected by the irq spinlock. * * 1. The user queues the buffers, starts streaming and dequeues a buffer. * * The buffers are added to the main and irq queues. Both operations are - * protected by the queue lock, and the latert is protected by the irq + * protected by the queue lock, and the later is protected by the irq * spinlock as well. * * The completion handler fetches a buffer from the irq queue and fills it @@ -60,7 +59,7 @@ * returns immediately. * * When the buffer is full, the completion handler removes it from the irq - * queue, marks it as ready (UVC_BUF_STATE_DONE) and wake its wait queue. + * queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue. * At that point, any process waiting on the buffer will be woken up. If a * process tries to dequeue a buffer after it has been marked ready, the * dequeing will succeed immediately. @@ -91,8 +90,8 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) /* * Allocate the video buffers. * - * Pages are reserved to make sure they will not be swaped, as they will be - * filled in URB completion handler. + * Pages are reserved to make sure they will not be swapped, as they will be + * filled in the URB completion handler. * * Buffers will be individually mapped, so they must all be page aligned. */ @@ -210,8 +209,8 @@ int uvc_query_buffer(struct uvc_video_queue *queue, __uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf); done: - mutex_unlock(&queue->mutex); - return ret; + mutex_unlock(&queue->mutex); + return ret; } /* @@ -236,7 +235,7 @@ int uvc_queue_buffer(struct uvc_video_queue *queue, } mutex_lock(&queue->mutex); - if (v4l2_buf->index >= queue->count) { + if (v4l2_buf->index >= queue->count) { uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n"); ret = -EINVAL; goto done; @@ -429,7 +428,7 @@ done: * Cancel the video buffers queue. * * Cancelling the queue marks all buffers on the irq queue as erroneous, - * wakes them up and remove them from the queue. + * wakes them up and removes them from the queue. * * If the disconnect parameter is set, further calls to uvc_queue_buffer will * fail with -ENODEV. diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c index 5d60b26..c1e4ae2 100644 --- a/drivers/media/video/uvc/uvc_status.c +++ b/drivers/media/video/uvc/uvc_status.c @@ -1,7 +1,7 @@ /* * uvc_status.c -- USB Video Class driver - Status endpoint * - * Copyright (C) 2007-2008 + * Copyright (C) 2007-2009 * Laurent Pinchart (laurent.pinchart@skynet.be) * * This program is free software; you can redistribute it and/or modify @@ -12,7 +12,6 @@ */ #include <linux/kernel.h> -#include <linux/version.h> #include <linux/input.h> #include <linux/usb.h> #include <linux/usb/input.h> diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index fa150ff..d681519 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -1,7 +1,7 @@ /* * uvc_v4l2.c -- USB Video Class driver - V4L2 API * - * Copyright (C) 2005-2008 + * Copyright (C) 2005-2009 * Laurent Pinchart (laurent.pinchart@skynet.be) * * This program is free software; you can redistribute it and/or modify @@ -37,7 +37,7 @@ * must be grouped (for instance the Red Balance, Blue Balance and Do White * Balance V4L2 controls use the White Balance Component UVC control) or * otherwise translated. The approach we take here is to use a translation - * table for the controls which can be mapped directly, and handle the others + * table for the controls that can be mapped directly, and handle the others * manually. */ static int uvc_v4l2_query_menu(struct uvc_video_device *video, @@ -189,7 +189,7 @@ static int uvc_v4l2_try_format(struct uvc_video_device *video, probe->dwMaxVideoFrameSize = video->streaming->ctrl.dwMaxVideoFrameSize; - /* Probe the device */ + /* Probe the device. */ if ((ret = uvc_probe_video(video, probe)) < 0) goto done; @@ -354,11 +354,11 @@ static int uvc_v4l2_set_streamparm(struct uvc_video_device *video, * * Each open instance of a UVC device can either be in a privileged or * unprivileged state. Only a single instance can be in a privileged state at - * a given time. Trying to perform an operation which requires privileges will + * a given time. Trying to perform an operation that requires privileges will * automatically acquire the required privileges if possible, or return -EBUSY * otherwise. Privileges are dismissed when closing the instance. * - * Operations which require privileges are: + * Operations that require privileges are: * * - VIDIOC_S_INPUT * - VIDIOC_S_PARM diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index e7c3199..9bc4705 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -1,7 +1,7 @@ /* * uvc_video.c -- USB Video Class driver - Video handling * - * Copyright (C) 2005-2008 + * Copyright (C) 2005-2009 * Laurent Pinchart (laurent.pinchart@skynet.be) * * This program is free software; you can redistribute it and/or modify @@ -12,7 +12,6 @@ */ #include <linux/kernel.h> -#include <linux/version.h> #include <linux/list.h> #include <linux/module.h> #include <linux/usb.h> @@ -115,7 +114,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, ctrl->wCompQuality = le16_to_cpup((__le16 *)data); ret = 0; goto out; - } else if (query == GET_DEF && probe == 1) { + } else if (query == GET_DEF && probe == 1 && ret != size) { /* Many cameras don't support the GET_DEF request on their * video probe control. Warn once and return, the caller will * fall back to GET_CUR. @@ -160,7 +159,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, } /* Some broken devices return a null or wrong dwMaxVideoFrameSize. - * Try to get the value from the format and frame descriptor. + * Try to get the value from the format and frame descriptors. */ uvc_fixup_buffer_size(video, ctrl); ret = 0; @@ -191,9 +190,6 @@ static int uvc_set_video_ctrl(struct uvc_video_device *video, *(__le16 *)&data[12] = cpu_to_le16(ctrl->wCompQuality); *(__le16 *)&data[14] = cpu_to_le16(ctrl->wCompWindowSize); *(__le16 *)&data[16] = cpu_to_le16(ctrl->wDelay); - /* Note: Some of the fields below are not required for IN devices (see - * UVC spec, 4.3.1.1), but we still copy them in case support for OUT - * devices is added in the future. */ put_unaligned_le32(ctrl->dwMaxVideoFrameSize, &data[18]); put_unaligned_le32(ctrl->dwMaxPayloadTransferSize, &data[22]); @@ -400,7 +396,7 @@ static int uvc_video_decode_start(struct uvc_video_device *video, * * Empty buffers (bytesused == 0) don't trigger end of frame detection * as it doesn't make sense to return an empty buffer. This also - * avoids detecting and of frame conditions at FID toggling if the + * avoids detecting end of frame conditions at FID toggling if the * previous payload had the EOF bit set. */ if (fid != video->last_fid && buf->buf.bytesused != 0) { @@ -453,6 +449,17 @@ static void uvc_video_decode_end(struct uvc_video_device *video, } } +/* Video payload encoding is handled by uvc_video_encode_header() and + * uvc_video_encode_data(). Only bulk transfers are currently supported. + * + * uvc_video_encode_header is called at the start of a payload. It adds header + * data to the transfer buffer and returns the header size. As the only known + * UVC output device transfers a whole frame in a single payload, the EOF bit + * is always set in the header. + * + * uvc_video_encode_data is called for every URB and copies the data from the + * video buffer to the transfer buffer. + */ static int uvc_video_encode_header(struct uvc_video_device *video, struct uvc_buffer *buf, __u8 *data, int len) { @@ -953,7 +960,7 @@ int uvc_video_suspend(struct uvc_video_device *video) } /* - * Reconfigure the video interface and restart streaming if it was enable + * Reconfigure the video interface and restart streaming if it was enabled * before suspend. * * If an error occurs, disable the video queue. This will wake all pending @@ -985,8 +992,8 @@ int uvc_video_resume(struct uvc_video_device *video) */ /* - * Initialize the UVC video device by retrieving the default format and - * committing it. + * Initialize the UVC video device by switching to alternate setting 0 and + * retrieve the default format. * * Some cameras (namely the Fuji Finepix) set the format and frame * indexes to zero. The UVC standard doesn't clearly make this a spec @@ -1014,7 +1021,7 @@ int uvc_video_init(struct uvc_video_device *video) */ usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); - /* Some webcams don't suport GET_DEF request on the probe control. We + /* Some webcams don't suport GET_DEF requests on the probe control. We * fall back to GET_CUR if GET_DEF fails. */ if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 && diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index bcf4361..027947e 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -72,149 +72,149 @@ struct uvc_xu_control { * UVC constants */ -#define SC_UNDEFINED 0x00 -#define SC_VIDEOCONTROL 0x01 -#define SC_VIDEOSTREAMING 0x02 -#define SC_VIDEO_INTERFACE_COLLECTION 0x03 +#define SC_UNDEFINED 0x00 +#define SC_VIDEOCONTROL 0x01 +#define SC_VIDEOSTREAMING 0x02 +#define SC_VIDEO_INTERFACE_COLLECTION 0x03 -#define PC_PROTOCOL_UNDEFINED 0x00 +#define PC_PROTOCOL_UNDEFINED 0x00 -#define CS_UNDEFINED 0x20 -#define CS_DEVICE 0x21 -#define CS_CONFIGURATION 0x22 -#define CS_STRING 0x23 -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 +#define CS_UNDEFINED 0x20 +#define CS_DEVICE 0x21 +#define CS_CONFIGURATION 0x22 +#define CS_STRING 0x23 +#define CS_INTERFACE 0x24 +#define CS_ENDPOINT 0x25 /* VideoControl class specific interface descriptor */ -#define VC_DESCRIPTOR_UNDEFINED 0x00 -#define VC_HEADER 0x01 -#define VC_INPUT_TERMINAL 0x02 -#define VC_OUTPUT_TERMINAL 0x03 -#define VC_SELECTOR_UNIT 0x04 -#define VC_PROCESSING_UNIT 0x05 -#define VC_EXTENSION_UNIT 0x06 +#define VC_DESCRIPTOR_UNDEFINED 0x00 +#define VC_HEADER 0x01 +#define VC_INPUT_TERMINAL 0x02 +#define VC_OUTPUT_TERMINAL 0x03 +#define VC_SELECTOR_UNIT 0x04 +#define VC_PROCESSING_UNIT 0x05 +#define VC_EXTENSION_UNIT 0x06 /* VideoStreaming class specific interface descriptor */ -#define VS_UNDEFINED 0x00 -#define VS_INPUT_HEADER 0x01 -#define VS_OUTPUT_HEADER 0x02 -#define VS_STILL_IMAGE_FRAME 0x03 -#define VS_FORMAT_UNCOMPRESSED 0x04 -#define VS_FRAME_UNCOMPRESSED 0x05 -#define VS_FORMAT_MJPEG 0x06 -#define VS_FRAME_MJPEG 0x07 -#define VS_FORMAT_MPEG2TS 0x0a -#define VS_FORMAT_DV 0x0c -#define VS_COLORFORMAT 0x0d -#define VS_FORMAT_FRAME_BASED 0x10 -#define VS_FRAME_FRAME_BASED 0x11 -#define VS_FORMAT_STREAM_BASED 0x12 +#define VS_UNDEFINED 0x00 +#define VS_INPUT_HEADER 0x01 +#define VS_OUTPUT_HEADER 0x02 +#define VS_STILL_IMAGE_FRAME 0x03 +#define VS_FORMAT_UNCOMPRESSED 0x04 +#define VS_FRAME_UNCOMPRESSED 0x05 +#define VS_FORMAT_MJPEG 0x06 +#define VS_FRAME_MJPEG 0x07 +#define VS_FORMAT_MPEG2TS 0x0a +#define VS_FORMAT_DV 0x0c +#define VS_COLORFORMAT 0x0d +#define VS_FORMAT_FRAME_BASED 0x10 +#define VS_FRAME_FRAME_BASED 0x11 +#define VS_FORMAT_STREAM_BASED 0x12 /* Endpoint type */ -#define EP_UNDEFINED 0x00 -#define EP_GENERAL 0x01 -#define EP_ENDPOINT 0x02 -#define EP_INTERRUPT 0x03 +#define EP_UNDEFINED 0x00 +#define EP_GENERAL 0x01 +#define EP_ENDPOINT 0x02 +#define EP_INTERRUPT 0x03 /* Request codes */ -#define RC_UNDEFINED 0x00 -#define SET_CUR 0x01 -#define GET_CUR 0x81 -#define GET_MIN 0x82 -#define GET_MAX 0x83 -#define GET_RES 0x84 -#define GET_LEN 0x85 -#define GET_INFO 0x86 -#define GET_DEF 0x87 +#define RC_UNDEFINED 0x00 +#define SET_CUR 0x01 +#define GET_CUR 0x81 +#define GET_MIN 0x82 +#define GET_MAX 0x83 +#define GET_RES 0x84 +#define GET_LEN 0x85 +#define GET_INFO 0x86 +#define GET_DEF 0x87 /* VideoControl interface controls */ -#define VC_CONTROL_UNDEFINED 0x00 -#define VC_VIDEO_POWER_MODE_CONTROL 0x01 -#define VC_REQUEST_ERROR_CODE_CONTROL 0x02 +#define VC_CONTROL_UNDEFINED 0x00 +#define VC_VIDEO_POWER_MODE_CONTROL 0x01 +#define VC_REQUEST_ERROR_CODE_CONTROL 0x02 /* Terminal controls */ -#define TE_CONTROL_UNDEFINED 0x00 +#define TE_CONTROL_UNDEFINED 0x00 /* Selector Unit controls */ -#define SU_CONTROL_UNDEFINED 0x00 -#define SU_INPUT_SELECT_CONTROL 0x01 +#define SU_CONTROL_UNDEFINED 0x00 +#define SU_INPUT_SELECT_CONTROL 0x01 /* Camera Terminal controls */ -#define CT_CONTROL_UNDEFINED 0x00 -#define CT_SCANNING_MODE_CONTROL 0x01 -#define CT_AE_MODE_CONTROL 0x02 -#define CT_AE_PRIORITY_CONTROL 0x03 -#define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 -#define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 -#define CT_FOCUS_ABSOLUTE_CONTROL 0x06 -#define CT_FOCUS_RELATIVE_CONTROL 0x07 -#define CT_FOCUS_AUTO_CONTROL 0x08 -#define CT_IRIS_ABSOLUTE_CONTROL 0x09 -#define CT_IRIS_RELATIVE_CONTROL 0x0a -#define CT_ZOOM_ABSOLUTE_CONTROL 0x0b -#define CT_ZOOM_RELATIVE_CONTROL 0x0c -#define CT_PANTILT_ABSOLUTE_CONTROL 0x0d -#define CT_PANTILT_RELATIVE_CONTROL 0x0e -#define CT_ROLL_ABSOLUTE_CONTROL 0x0f -#define CT_ROLL_RELATIVE_CONTROL 0x10 -#define CT_PRIVACY_CONTROL 0x11 +#define CT_CONTROL_UNDEFINED 0x00 +#define CT_SCANNING_MODE_CONTROL 0x01 +#define CT_AE_MODE_CONTROL 0x02 +#define CT_AE_PRIORITY_CONTROL 0x03 +#define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 +#define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 +#define CT_FOCUS_ABSOLUTE_CONTROL 0x06 +#define CT_FOCUS_RELATIVE_CONTROL 0x07 +#define CT_FOCUS_AUTO_CONTROL 0x08 +#define CT_IRIS_ABSOLUTE_CONTROL 0x09 +#define CT_IRIS_RELATIVE_CONTROL 0x0a +#define CT_ZOOM_ABSOLUTE_CONTROL 0x0b +#define CT_ZOOM_RELATIVE_CONTROL 0x0c +#define CT_PANTILT_ABSOLUTE_CONTROL 0x0d +#define CT_PANTILT_RELATIVE_CONTROL 0x0e +#define CT_ROLL_ABSOLUTE_CONTROL 0x0f +#define CT_ROLL_RELATIVE_CONTROL 0x10 +#define CT_PRIVACY_CONTROL 0x11 /* Processing Unit controls */ -#define PU_CONTROL_UNDEFINED 0x00 -#define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 -#define PU_BRIGHTNESS_CONTROL 0x02 -#define PU_CONTRAST_CONTROL 0x03 -#define PU_GAIN_CONTROL 0x04 -#define PU_POWER_LINE_FREQUENCY_CONTROL 0x05 -#define PU_HUE_CONTROL 0x06 -#define PU_SATURATION_CONTROL 0x07 -#define PU_SHARPNESS_CONTROL 0x08 -#define PU_GAMMA_CONTROL 0x09 -#define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a -#define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b -#define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c -#define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d -#define PU_DIGITAL_MULTIPLIER_CONTROL 0x0e -#define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f -#define PU_HUE_AUTO_CONTROL 0x10 -#define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 -#define PU_ANALOG_LOCK_STATUS_CONTROL 0x12 +#define PU_CONTROL_UNDEFINED 0x00 +#define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 +#define PU_BRIGHTNESS_CONTROL 0x02 +#define PU_CONTRAST_CONTROL 0x03 +#define PU_GAIN_CONTROL 0x04 +#define PU_POWER_LINE_FREQUENCY_CONTROL 0x05 +#define PU_HUE_CONTROL 0x06 +#define PU_SATURATION_CONTROL 0x07 +#define PU_SHARPNESS_CONTROL 0x08 +#define PU_GAMMA_CONTROL 0x09 +#define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a +#define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b +#define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c +#define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d +#define PU_DIGITAL_MULTIPLIER_CONTROL 0x0e +#define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f +#define PU_HUE_AUTO_CONTROL 0x10 +#define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 +#define PU_ANALOG_LOCK_STATUS_CONTROL 0x12 #define LXU_MOTOR_PANTILT_RELATIVE_CONTROL 0x01 #define LXU_MOTOR_PANTILT_RESET_CONTROL 0x02 #define LXU_MOTOR_FOCUS_MOTOR_CONTROL 0x03 /* VideoStreaming interface controls */ -#define VS_CONTROL_UNDEFINED 0x00 -#define VS_PROBE_CONTROL 0x01 -#define VS_COMMIT_CONTROL 0x02 -#define VS_STILL_PROBE_CONTROL 0x03 -#define VS_STILL_COMMIT_CONTROL 0x04 -#define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 -#define VS_STREAM_ERROR_CODE_CONTROL 0x06 -#define VS_GENERATE_KEY_FRAME_CONTROL 0x07 -#define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 -#define VS_SYNC_DELAY_CONTROL 0x09 - -#define TT_VENDOR_SPECIFIC 0x0100 -#define TT_STREAMING 0x0101 +#define VS_CONTROL_UNDEFINED 0x00 +#define VS_PROBE_CONTROL 0x01 +#define VS_COMMIT_CONTROL 0x02 +#define VS_STILL_PROBE_CONTROL 0x03 +#define VS_STILL_COMMIT_CONTROL 0x04 +#define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 +#define VS_STREAM_ERROR_CODE_CONTROL 0x06 +#define VS_GENERATE_KEY_FRAME_CONTROL 0x07 +#define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 +#define VS_SYNC_DELAY_CONTROL 0x09 + +#define TT_VENDOR_SPECIFIC 0x0100 +#define TT_STREAMING 0x0101 /* Input Terminal types */ -#define ITT_VENDOR_SPECIFIC 0x0200 -#define ITT_CAMERA 0x0201 -#define ITT_MEDIA_TRANSPORT_INPUT 0x0202 +#define ITT_VENDOR_SPECIFIC 0x0200 +#define ITT_CAMERA 0x0201 +#define ITT_MEDIA_TRANSPORT_INPUT 0x0202 /* Output Terminal types */ -#define OTT_VENDOR_SPECIFIC 0x0300 -#define OTT_DISPLAY 0x0301 -#define OTT_MEDIA_TRANSPORT_OUTPUT 0x0302 +#define OTT_VENDOR_SPECIFIC 0x0300 +#define OTT_DISPLAY 0x0301 +#define OTT_MEDIA_TRANSPORT_OUTPUT 0x0302 /* External Terminal types */ -#define EXTERNAL_VENDOR_SPECIFIC 0x0400 -#define COMPOSITE_CONNECTOR 0x0401 -#define SVIDEO_CONNECTOR 0x0402 -#define COMPONENT_CONNECTOR 0x0403 +#define EXTERNAL_VENDOR_SPECIFIC 0x0400 +#define COMPOSITE_CONNECTOR 0x0401 +#define SVIDEO_CONNECTOR 0x0402 +#define COMPONENT_CONNECTOR 0x0403 #define UVC_TERM_INPUT 0x0000 #define UVC_TERM_OUTPUT 0x8000 @@ -541,11 +541,11 @@ struct uvc_streaming { }; enum uvc_buffer_state { - UVC_BUF_STATE_IDLE = 0, - UVC_BUF_STATE_QUEUED = 1, - UVC_BUF_STATE_ACTIVE = 2, - UVC_BUF_STATE_DONE = 3, - UVC_BUF_STATE_ERROR = 4, + UVC_BUF_STATE_IDLE = 0, + UVC_BUF_STATE_QUEUED = 1, + UVC_BUF_STATE_ACTIVE = 2, + UVC_BUF_STATE_DONE = 3, + UVC_BUF_STATE_ERROR = 4, }; struct uvc_buffer { diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index fbe9cc0..2120880 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -28,13 +28,13 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg) { switch (cmd) { case VIDIOC_QUERYCTRL: - return v4l2_subdev_call(sd, core, querymenu, arg); + return v4l2_subdev_call(sd, core, queryctrl, arg); case VIDIOC_G_CTRL: return v4l2_subdev_call(sd, core, g_ctrl, arg); case VIDIOC_S_CTRL: return v4l2_subdev_call(sd, core, s_ctrl, arg); case VIDIOC_QUERYMENU: - return v4l2_subdev_call(sd, core, queryctrl, arg); + return v4l2_subdev_call(sd, core, querymenu, arg); case VIDIOC_LOG_STATUS: return v4l2_subdev_call(sd, core, log_status); case VIDIOC_DBG_G_CHIP_IDENT: diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index 46b7ad4..e873a91 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h @@ -349,7 +349,6 @@ struct card_info { u16 i2c_decoder, i2c_encoder; /* I2C types */ u16 video_vfe, video_codec; /* videocodec types */ u16 audio_chip; /* audio type */ - u16 vendor_id, device_id; /* subsystem vendor/device ID */ int inputs; /* number of video inputs */ struct input { @@ -401,7 +400,6 @@ struct zoran { char name[32]; /* name of this device */ struct pci_dev *pci_dev; /* PCI device */ unsigned char revision; /* revision of zr36057 */ - unsigned int zr36057_adr; /* bus address of IO mem returned by PCI BIOS */ unsigned char __iomem *zr36057_mem;/* pointer to mapped IO memory */ spinlock_t spinlock; /* Spinlock */ @@ -490,16 +488,10 @@ struct zoran { wait_queue_head_t test_q; }; -/*The following should be done in more portable way. It depends on define - of _ALPHA_BUZ in the Makefile.*/ - -#ifdef _ALPHA_BUZ -#define btwrite(dat,adr) writel((dat), zr->zr36057_adr+(adr)) -#define btread(adr) readl(zr->zr36057_adr+(adr)) -#else +/* There was something called _ALPHA_BUZ that used the PCI address instead of + * the kernel iomapped address for btread/btwrite. */ #define btwrite(dat,adr) writel((dat), zr->zr36057_mem+(adr)) #define btread(adr) readl(zr->zr36057_mem+(adr)) -#endif #define btand(dat,adr) btwrite((dat) & btread(adr), adr) #define btor(dat,adr) btwrite((dat) | btread(adr), adr) diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 05f3919..5d2f090 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c @@ -61,17 +61,17 @@ extern const struct zoran_format zoran_formats[]; -static int card[BUZ_MAX] = { -1, -1, -1, -1 }; +static int card[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 }; module_param_array(card, int, NULL, 0444); -MODULE_PARM_DESC(card, "The type of card"); +MODULE_PARM_DESC(card, "Card type"); -static int encoder[BUZ_MAX] = { -1, -1, -1, -1 }; +static int encoder[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 }; module_param_array(encoder, int, NULL, 0444); -MODULE_PARM_DESC(encoder, "i2c TV encoder"); +MODULE_PARM_DESC(encoder, "Video encoder chip"); -static int decoder[BUZ_MAX] = { -1, -1, -1, -1 }; +static int decoder[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 }; module_param_array(decoder, int, NULL, 0444); -MODULE_PARM_DESC(decoder, "i2c TV decoder"); +MODULE_PARM_DESC(decoder, "Video decoder chip"); /* The video mem address of the video card. @@ -104,9 +104,9 @@ module_param(default_norm, int, 0444); MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)"); /* /dev/videoN, -1 for autodetect */ -static int video_nr[BUZ_MAX] = {-1, -1, -1, -1}; +static int video_nr[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 }; module_param_array(video_nr, int, NULL, 0444); -MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)"); +MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)"); /* Number and size of grab buffers for Video 4 Linux @@ -153,9 +153,21 @@ MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver"); MODULE_AUTHOR("Serguei Miridonov"); MODULE_LICENSE("GPL"); +#define ZR_DEVICE(subven, subdev, data) { \ + .vendor = PCI_VENDOR_ID_ZORAN, .device = PCI_DEVICE_ID_ZORAN_36057, \ + .subvendor = (subven), .subdevice = (subdev), .driver_data = (data) } + +static struct pci_device_id zr36067_pci_tbl[] = { + ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC10PLUS, DC10plus), + ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC30PLUS, DC30plus), + ZR_DEVICE(PCI_VENDOR_ID_ELECTRONICDESIGNGMBH, PCI_DEVICE_ID_LML_33R10, LML33R10), + ZR_DEVICE(PCI_VENDOR_ID_IOMEGA, PCI_DEVICE_ID_IOMEGA_BUZ, BUZ), + ZR_DEVICE(PCI_ANY_ID, PCI_ANY_ID, NUM_CARDS), + {0} +}; +MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl); -int zoran_num; /* number of Buzs in use */ -struct zoran *zoran[BUZ_MAX]; +static unsigned int zoran_num; /* number of cards found */ /* videocodec bus functions ZR36060 */ static u32 @@ -472,8 +484,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = DC10plus, .name = "DC10plus", - .vendor_id = PCI_VENDOR_ID_MIRO, - .device_id = PCI_DEVICE_ID_MIRO_DC10PLUS, .i2c_decoder = I2C_DRIVERID_SAA7110, .i2c_encoder = I2C_DRIVERID_ADV7175, .video_codec = CODEC_TYPE_ZR36060, @@ -531,8 +541,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = DC30plus, .name = "DC30plus", - .vendor_id = PCI_VENDOR_ID_MIRO, - .device_id = PCI_DEVICE_ID_MIRO_DC30PLUS, .i2c_decoder = I2C_DRIVERID_VPX3220, .i2c_encoder = I2C_DRIVERID_ADV7175, .video_codec = CODEC_TYPE_ZR36050, @@ -589,8 +597,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = LML33R10, .name = "LML33R10", - .vendor_id = PCI_VENDOR_ID_ELECTRONICDESIGNGMBH, - .device_id = PCI_DEVICE_ID_LML_33R10, .i2c_decoder = I2C_DRIVERID_SAA7114, .i2c_encoder = I2C_DRIVERID_ADV7170, .video_codec = CODEC_TYPE_ZR36060, @@ -618,8 +624,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { }, { .type = BUZ, .name = "Buz", - .vendor_id = PCI_VENDOR_ID_IOMEGA, - .device_id = PCI_DEVICE_ID_IOMEGA_BUZ, .i2c_decoder = I2C_DRIVERID_SAA7111A, .i2c_encoder = I2C_DRIVERID_SAA7185B, .video_codec = CODEC_TYPE_ZR36060, @@ -649,8 +653,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { .name = "6-Eyes", /* AverMedia chose not to brand the 6-Eyes. Thus it can't be autodetected, and requires card=x. */ - .vendor_id = -1, - .device_id = -1, .i2c_decoder = I2C_DRIVERID_KS0127, .i2c_encoder = I2C_DRIVERID_BT866, .video_codec = CODEC_TYPE_ZR36060, @@ -1138,7 +1140,8 @@ zr36057_init (struct zoran *zr) strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]); if (err < 0) - goto exit_unregister; + goto exit_free; + video_set_drvdata(zr->video_dev, zr); zoran_init_hardware(zr); if (zr36067_debug > 2) @@ -1153,19 +1156,19 @@ zr36057_init (struct zoran *zr) zr->initialized = 1; return 0; -exit_unregister: - zoran_unregister_i2c(zr); exit_free: kfree(zr->stat_com); kfree(zr->video_dev); return err; } -static void -zoran_release (struct zoran *zr) +static void __devexit zoran_remove(struct pci_dev *pdev) { + struct zoran *zr = pci_get_drvdata(pdev); + if (!zr->initialized) goto exit_free; + /* unregister videocodec bus */ if (zr->codec) { struct videocodec_master *master = zr->codec->master_data; @@ -1194,6 +1197,7 @@ zoran_release (struct zoran *zr) pci_disable_device(zr->pci_dev); video_unregister_device(zr->video_dev); exit_free: + pci_set_drvdata(pdev, NULL); kfree(zr); } @@ -1256,338 +1260,329 @@ zoran_setup_videocodec (struct zoran *zr, * Scan for a Buz card (actually for the PCI controller ZR36057), * request the irq and map the io memory */ -static int __devinit -find_zr36057 (void) +static int __devinit zoran_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { unsigned char latency, need_latency; struct zoran *zr; - struct pci_dev *dev = NULL; int result; struct videocodec_master *master_vfe = NULL; struct videocodec_master *master_codec = NULL; int card_num; char *i2c_enc_name, *i2c_dec_name, *codec_name, *vfe_name; + unsigned int nr; - zoran_num = 0; - while (zoran_num < BUZ_MAX && - (dev = pci_get_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057, dev)) != NULL) { - card_num = card[zoran_num]; - zr = kzalloc(sizeof(struct zoran), GFP_KERNEL); - if (!zr) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - kzalloc failed\n", - ZORAN_NAME); - continue; - } - zr->pci_dev = dev; - //zr->zr36057_mem = NULL; - zr->id = zoran_num; - snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id); - spin_lock_init(&zr->spinlock); - mutex_init(&zr->resource_lock); - if (pci_enable_device(dev)) - goto zr_free_mem; - zr->zr36057_adr = pci_resource_start(zr->pci_dev, 0); - pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION, - &zr->revision); - if (zr->revision < 2) { - dprintk(1, - KERN_INFO - "%s: Zoran ZR36057 (rev %d) irq: %d, memory: 0x%08x.\n", - ZR_DEVNAME(zr), zr->revision, zr->pci_dev->irq, - zr->zr36057_adr); - if (card_num == -1) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - no card specified, please use the card=X insmod option\n", - ZR_DEVNAME(zr)); - goto zr_free_mem; - } - } else { - int i; - unsigned short ss_vendor, ss_device; + nr = zoran_num++; + if (nr >= BUZ_MAX) { + dprintk(1, + KERN_ERR + "%s: driver limited to %d card(s) maximum\n", + ZORAN_NAME, BUZ_MAX); + return -ENOENT; + } - ss_vendor = zr->pci_dev->subsystem_vendor; - ss_device = zr->pci_dev->subsystem_device; + zr = kzalloc(sizeof(struct zoran), GFP_KERNEL); + if (!zr) { + dprintk(1, + KERN_ERR + "%s: find_zr36057() - kzalloc failed\n", + ZORAN_NAME); + return -ENOMEM; + } + zr->pci_dev = pdev; + zr->id = nr; + snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id); + spin_lock_init(&zr->spinlock); + mutex_init(&zr->resource_lock); + if (pci_enable_device(pdev)) + goto zr_free_mem; + pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION, &zr->revision); + + dprintk(1, + KERN_INFO + "%s: Zoran ZR360%c7 (rev %d), irq: %d, memory: 0x%08llx\n", + ZR_DEVNAME(zr), zr->revision < 2 ? '5' : '6', zr->revision, + zr->pci_dev->irq, (uint64_t)pci_resource_start(zr->pci_dev, 0)); + if (zr->revision >= 2) { + dprintk(1, + KERN_INFO + "%s: Subsystem vendor=0x%04x id=0x%04x\n", + ZR_DEVNAME(zr), zr->pci_dev->subsystem_vendor, + zr->pci_dev->subsystem_device); + } + + /* Use auto-detected card type? */ + if (card[nr] == -1) { + if (zr->revision < 2) { dprintk(1, - KERN_INFO - "%s: Zoran ZR36067 (rev %d) irq: %d, memory: 0x%08x\n", - ZR_DEVNAME(zr), zr->revision, zr->pci_dev->irq, - zr->zr36057_adr); + KERN_ERR + "%s: No card type specified, please use the card=X module parameter\n", + ZR_DEVNAME(zr)); dprintk(1, - KERN_INFO - "%s: subsystem vendor=0x%04x id=0x%04x\n", - ZR_DEVNAME(zr), ss_vendor, ss_device); - if (card_num == -1) { - dprintk(3, - KERN_DEBUG - "%s: find_zr36057() - trying to autodetect card type\n", - ZR_DEVNAME(zr)); - for (i=0;i<NUM_CARDS;i++) { - if (ss_vendor == zoran_cards[i].vendor_id && - ss_device == zoran_cards[i].device_id) { - dprintk(3, - KERN_DEBUG - "%s: find_zr36057() - card %s detected\n", - ZR_DEVNAME(zr), - zoran_cards[i].name); - card_num = i; - break; - } - } - if (i == NUM_CARDS) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - unknown card\n", - ZR_DEVNAME(zr)); - goto zr_free_mem; - } - } - } - - if (card_num < 0 || card_num >= NUM_CARDS) { - dprintk(2, KERN_ERR - "%s: find_zr36057() - invalid cardnum %d\n", - ZR_DEVNAME(zr), card_num); + "%s: It is not possible to auto-detect ZR36057 based cards\n", + ZR_DEVNAME(zr)); goto zr_free_mem; } - /* even though we make this a non pointer and thus - * theoretically allow for making changes to this struct - * on a per-individual card basis at runtime, this is - * strongly discouraged. This structure is intended to - * keep general card information, no settings or anything */ - zr->card = zoran_cards[card_num]; - snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), - "%s[%u]", zr->card.name, zr->id); - - zr->zr36057_mem = ioremap_nocache(zr->zr36057_adr, 0x1000); - if (!zr->zr36057_mem) { + card_num = ent->driver_data; + if (card_num >= NUM_CARDS) { dprintk(1, KERN_ERR - "%s: find_zr36057() - ioremap failed\n", + "%s: Unknown card, try specifying card=X module parameter\n", ZR_DEVNAME(zr)); goto zr_free_mem; } - - result = request_irq(zr->pci_dev->irq, - zoran_irq, - IRQF_SHARED | IRQF_DISABLED, - ZR_DEVNAME(zr), - (void *) zr); - if (result < 0) { - if (result == -EINVAL) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - bad irq number or handler\n", - ZR_DEVNAME(zr)); - } else if (result == -EBUSY) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - IRQ %d busy, change your PnP config in BIOS\n", - ZR_DEVNAME(zr), zr->pci_dev->irq); - } else { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - can't assign irq, error code %d\n", - ZR_DEVNAME(zr), result); - } - goto zr_unmap; - } - - /* set PCI latency timer */ - pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, - &latency); - need_latency = zr->revision > 1 ? 32 : 48; - if (latency != need_latency) { - dprintk(2, - KERN_INFO - "%s: Changing PCI latency from %d to %d.\n", - ZR_DEVNAME(zr), latency, need_latency); - pci_write_config_byte(zr->pci_dev, - PCI_LATENCY_TIMER, - need_latency); + dprintk(3, + KERN_DEBUG + "%s: %s() - card %s detected\n", + ZR_DEVNAME(zr), __func__, zoran_cards[card_num].name); + } else { + card_num = card[nr]; + if (card_num >= NUM_CARDS || card_num < 0) { + dprintk(1, + KERN_ERR + "%s: User specified card type %d out of range (0 .. %d)\n", + ZR_DEVNAME(zr), card_num, NUM_CARDS - 1); + goto zr_free_mem; } + } - zr36057_restart(zr); - /* i2c */ - dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n", - ZR_DEVNAME(zr)); + /* even though we make this a non pointer and thus + * theoretically allow for making changes to this struct + * on a per-individual card basis at runtime, this is + * strongly discouraged. This structure is intended to + * keep general card information, no settings or anything */ + zr->card = zoran_cards[card_num]; + snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), + "%s[%u]", zr->card.name, zr->id); + + zr->zr36057_mem = pci_ioremap_bar(zr->pci_dev, 0); + if (!zr->zr36057_mem) { + dprintk(1, + KERN_ERR + "%s: %s() - ioremap failed\n", + ZR_DEVNAME(zr), __func__); + goto zr_free_mem; + } - /* i2c decoder */ - if (decoder[zr->id] != -1) { - i2c_dec_name = i2cid_to_modulename(decoder[zr->id]); - zr->card.i2c_decoder = decoder[zr->id]; - } else if (zr->card.i2c_decoder != 0) { - i2c_dec_name = - i2cid_to_modulename(zr->card.i2c_decoder); + result = request_irq(zr->pci_dev->irq, zoran_irq, + IRQF_SHARED | IRQF_DISABLED, ZR_DEVNAME(zr), zr); + if (result < 0) { + if (result == -EINVAL) { + dprintk(1, + KERN_ERR + "%s: find_zr36057() - bad irq number or handler\n", + ZR_DEVNAME(zr)); + } else if (result == -EBUSY) { + dprintk(1, + KERN_ERR + "%s: find_zr36057() - IRQ %d busy, change your PnP config in BIOS\n", + ZR_DEVNAME(zr), zr->pci_dev->irq); } else { - i2c_dec_name = NULL; + dprintk(1, + KERN_ERR + "%s: find_zr36057() - can't assign irq, error code %d\n", + ZR_DEVNAME(zr), result); } + goto zr_unmap; + } - if (i2c_dec_name) { - if ((result = request_module(i2c_dec_name)) < 0) { - dprintk(1, - KERN_ERR - "%s: failed to load module %s: %d\n", - ZR_DEVNAME(zr), i2c_dec_name, result); - } - } + /* set PCI latency timer */ + pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, + &latency); + need_latency = zr->revision > 1 ? 32 : 48; + if (latency != need_latency) { + dprintk(2, + KERN_INFO + "%s: Changing PCI latency from %d to %d\n", + ZR_DEVNAME(zr), latency, need_latency); + pci_write_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, + need_latency); + } - /* i2c encoder */ - if (encoder[zr->id] != -1) { - i2c_enc_name = i2cid_to_modulename(encoder[zr->id]); - zr->card.i2c_encoder = encoder[zr->id]; - } else if (zr->card.i2c_encoder != 0) { - i2c_enc_name = - i2cid_to_modulename(zr->card.i2c_encoder); - } else { - i2c_enc_name = NULL; - } + zr36057_restart(zr); + /* i2c */ + dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n", + ZR_DEVNAME(zr)); + + /* i2c decoder */ + if (decoder[zr->id] != -1) { + i2c_dec_name = i2cid_to_modulename(decoder[zr->id]); + zr->card.i2c_decoder = decoder[zr->id]; + } else if (zr->card.i2c_decoder != 0) { + i2c_dec_name = i2cid_to_modulename(zr->card.i2c_decoder); + } else { + i2c_dec_name = NULL; + } - if (i2c_enc_name) { - if ((result = request_module(i2c_enc_name)) < 0) { - dprintk(1, - KERN_ERR - "%s: failed to load module %s: %d\n", - ZR_DEVNAME(zr), i2c_enc_name, result); - } + if (i2c_dec_name) { + result = request_module(i2c_dec_name); + if (result < 0) { + dprintk(1, + KERN_ERR + "%s: failed to load module %s: %d\n", + ZR_DEVNAME(zr), i2c_dec_name, result); } + } + + /* i2c encoder */ + if (encoder[zr->id] != -1) { + i2c_enc_name = i2cid_to_modulename(encoder[zr->id]); + zr->card.i2c_encoder = encoder[zr->id]; + } else if (zr->card.i2c_encoder != 0) { + i2c_enc_name = i2cid_to_modulename(zr->card.i2c_encoder); + } else { + i2c_enc_name = NULL; + } - if (zoran_register_i2c(zr) < 0) { + if (i2c_enc_name) { + result = request_module(i2c_enc_name); + if (result < 0) { dprintk(1, KERN_ERR - "%s: find_zr36057() - can't initialize i2c bus\n", - ZR_DEVNAME(zr)); - goto zr_free_irq; + "%s: failed to load module %s: %d\n", + ZR_DEVNAME(zr), i2c_enc_name, result); } + } - dprintk(2, - KERN_INFO "%s: Initializing videocodec bus...\n", + if (zoran_register_i2c(zr) < 0) { + dprintk(1, + KERN_ERR + "%s: find_zr36057() - can't initialize i2c bus\n", ZR_DEVNAME(zr)); + goto zr_free_irq; + } - if (zr->card.video_codec != 0 && - (codec_name = - codecid_to_modulename(zr->card.video_codec)) != NULL) { - if ((result = request_module(codec_name)) < 0) { + dprintk(2, + KERN_INFO "%s: Initializing videocodec bus...\n", + ZR_DEVNAME(zr)); + + if (zr->card.video_codec) { + codec_name = codecid_to_modulename(zr->card.video_codec); + if (codec_name) { + result = request_module(codec_name); + if (result) { dprintk(1, KERN_ERR "%s: failed to load modules %s: %d\n", ZR_DEVNAME(zr), codec_name, result); } } - if (zr->card.video_vfe != 0 && - (vfe_name = - codecid_to_modulename(zr->card.video_vfe)) != NULL) { - if ((result = request_module(vfe_name)) < 0) { + } + if (zr->card.video_vfe) { + vfe_name = codecid_to_modulename(zr->card.video_vfe); + if (vfe_name) { + result = request_module(vfe_name); + if (result < 0) { dprintk(1, KERN_ERR "%s: failed to load modules %s: %d\n", ZR_DEVNAME(zr), vfe_name, result); } } + } - /* reset JPEG codec */ - jpeg_codec_sleep(zr, 1); - jpeg_codec_reset(zr); - /* video bus enabled */ - /* display codec revision */ - if (zr->card.video_codec != 0) { - master_codec = zoran_setup_videocodec(zr, - zr->card.video_codec); - if (!master_codec) - goto zr_unreg_i2c; - zr->codec = videocodec_attach(master_codec); - if (!zr->codec) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - no codec found\n", - ZR_DEVNAME(zr)); - goto zr_free_codec; - } - if (zr->codec->type != zr->card.video_codec) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - wrong codec\n", - ZR_DEVNAME(zr)); - goto zr_detach_codec; - } + /* reset JPEG codec */ + jpeg_codec_sleep(zr, 1); + jpeg_codec_reset(zr); + /* video bus enabled */ + /* display codec revision */ + if (zr->card.video_codec != 0) { + master_codec = zoran_setup_videocodec(zr, zr->card.video_codec); + if (!master_codec) + goto zr_unreg_i2c; + zr->codec = videocodec_attach(master_codec); + if (!zr->codec) { + dprintk(1, + KERN_ERR + "%s: find_zr36057() - no codec found\n", + ZR_DEVNAME(zr)); + goto zr_free_codec; } - if (zr->card.video_vfe != 0) { - master_vfe = zoran_setup_videocodec(zr, - zr->card.video_vfe); - if (!master_vfe) - goto zr_detach_codec; - zr->vfe = videocodec_attach(master_vfe); - if (!zr->vfe) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() - no VFE found\n", - ZR_DEVNAME(zr)); - goto zr_free_vfe; - } - if (zr->vfe->type != zr->card.video_vfe) { - dprintk(1, - KERN_ERR - "%s: find_zr36057() = wrong VFE\n", - ZR_DEVNAME(zr)); - goto zr_detach_vfe; - } + if (zr->codec->type != zr->card.video_codec) { + dprintk(1, + KERN_ERR + "%s: find_zr36057() - wrong codec\n", + ZR_DEVNAME(zr)); + goto zr_detach_codec; + } + } + if (zr->card.video_vfe != 0) { + master_vfe = zoran_setup_videocodec(zr, zr->card.video_vfe); + if (!master_vfe) + goto zr_detach_codec; + zr->vfe = videocodec_attach(master_vfe); + if (!zr->vfe) { + dprintk(1, + KERN_ERR + "%s: find_zr36057() - no VFE found\n", + ZR_DEVNAME(zr)); + goto zr_free_vfe; + } + if (zr->vfe->type != zr->card.video_vfe) { + dprintk(1, + KERN_ERR + "%s: find_zr36057() = wrong VFE\n", + ZR_DEVNAME(zr)); + goto zr_detach_vfe; } - /* Success so keep the pci_dev referenced */ - pci_dev_get(zr->pci_dev); - zoran[zoran_num++] = zr; - continue; - - // Init errors - zr_detach_vfe: - videocodec_detach(zr->vfe); - zr_free_vfe: - kfree(master_vfe); - zr_detach_codec: - videocodec_detach(zr->codec); - zr_free_codec: - kfree(master_codec); - zr_unreg_i2c: - zoran_unregister_i2c(zr); - zr_free_irq: - btwrite(0, ZR36057_SPGPPCR); - free_irq(zr->pci_dev->irq, zr); - zr_unmap: - iounmap(zr->zr36057_mem); - zr_free_mem: - kfree(zr); - continue; } - if (dev) /* Clean up ref count on early exit */ - pci_dev_put(dev); - if (zoran_num == 0) { - dprintk(1, KERN_INFO "No known MJPEG cards found.\n"); + /* take care of Natoma chipset and a revision 1 zr36057 */ + if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) { + zr->jpg_buffers.need_contiguous = 1; + dprintk(1, + KERN_INFO + "%s: ZR36057/Natoma bug, max. buffer size is 128K\n", + ZR_DEVNAME(zr)); } - return zoran_num; + + if (zr36057_init(zr) < 0) + goto zr_detach_vfe; + + zoran_proc_init(zr); + + pci_set_drvdata(pdev, zr); + + return 0; + +zr_detach_vfe: + videocodec_detach(zr->vfe); +zr_free_vfe: + kfree(master_vfe); +zr_detach_codec: + videocodec_detach(zr->codec); +zr_free_codec: + kfree(master_codec); +zr_unreg_i2c: + zoran_unregister_i2c(zr); +zr_free_irq: + btwrite(0, ZR36057_SPGPPCR); + free_irq(zr->pci_dev->irq, zr); +zr_unmap: + iounmap(zr->zr36057_mem); +zr_free_mem: + kfree(zr); + + return -ENODEV; } -static int __init -init_dc10_cards (void) +static struct pci_driver zoran_driver = { + .name = "zr36067", + .id_table = zr36067_pci_tbl, + .probe = zoran_probe, + .remove = zoran_remove, +}; + +static int __init zoran_init(void) { - int i; + int res; - memset(zoran, 0, sizeof(zoran)); printk(KERN_INFO "Zoran MJPEG board driver version %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, RELEASE_VERSION); - /* Look for cards */ - if (find_zr36057() < 0) { - return -EIO; - } - if (zoran_num == 0) - return -ENODEV; - dprintk(1, KERN_INFO "%s: %d card(s) found\n", ZORAN_NAME, - zoran_num); /* check the parameters we have been given, adjust if necessary */ if (v4l_nbufs < 2) v4l_nbufs = 2; @@ -1629,37 +1624,22 @@ init_dc10_cards (void) ZORAN_NAME); } - /* take care of Natoma chipset and a revision 1 zr36057 */ - for (i = 0; i < zoran_num; i++) { - struct zoran *zr = zoran[i]; - - if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) { - zr->jpg_buffers.need_contiguous = 1; - dprintk(1, - KERN_INFO - "%s: ZR36057/Natoma bug, max. buffer size is 128K\n", - ZR_DEVNAME(zr)); - } - - if (zr36057_init(zr) < 0) { - for (i = 0; i < zoran_num; i++) - zoran_release(zoran[i]); - return -EIO; - } - zoran_proc_init(zr); + res = pci_register_driver(&zoran_driver); + if (res) { + dprintk(1, + KERN_ERR + "%s: Unable to register ZR36057 driver\n", + ZORAN_NAME); + return res; } return 0; } -static void __exit -unload_dc10_cards (void) +static void __exit zoran_exit(void) { - int i; - - for (i = 0; i < zoran_num; i++) - zoran_release(zoran[i]); + pci_unregister_driver(&zoran_driver); } -module_init(init_dc10_cards); -module_exit(unload_dc10_cards); +module_init(zoran_init); +module_exit(zoran_exit); diff --git a/drivers/media/video/zoran/zoran_card.h b/drivers/media/video/zoran/zoran_card.h index e4dc9d2..4507bdc 100644 --- a/drivers/media/video/zoran/zoran_card.h +++ b/drivers/media/video/zoran/zoran_card.h @@ -40,8 +40,6 @@ extern int zr36067_debug; /* Anybody who uses more than four? */ #define BUZ_MAX 4 -extern int zoran_num; -extern struct zoran *zoran[BUZ_MAX]; extern struct video_device zoran_template; diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index b58b9dd..120ef23 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -1196,83 +1196,54 @@ zoran_close_end_session (struct file *file) * Open a zoran card. Right now the flags stuff is just playing */ -static int -zoran_open(struct file *file) +static int zoran_open(struct file *file) { - unsigned int minor = video_devdata(file)->minor; - struct zoran *zr = NULL; + struct zoran *zr = video_drvdata(file); struct zoran_fh *fh; - int i, res, first_open = 0, have_module_locks = 0; + int res, first_open = 0; - lock_kernel(); - /* find the device */ - for (i = 0; i < zoran_num; i++) { - if (zoran[i]->video_dev->minor == minor) { - zr = zoran[i]; - break; - } - } + dprintk(2, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n", + ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user + 1); - if (!zr) { - dprintk(1, KERN_ERR "%s: device not found!\n", ZORAN_NAME); - res = -ENODEV; - goto open_unlock_and_return; - } + lock_kernel(); /* see fs/device.c - the kernel already locks during open(), * so locking ourselves only causes deadlocks */ /*mutex_lock(&zr->resource_lock);*/ + if (zr->user >= 2048) { + dprintk(1, KERN_ERR "%s: too many users (%d) on device\n", + ZR_DEVNAME(zr), zr->user); + res = -EBUSY; + goto fail_unlock; + } + if (!zr->decoder) { dprintk(1, KERN_ERR "%s: no TV decoder loaded for device!\n", ZR_DEVNAME(zr)); res = -EIO; - goto open_unlock_and_return; + goto fail_unlock; } - /* try to grab a module lock */ - if (!try_module_get(THIS_MODULE)) { - dprintk(1, - KERN_ERR - "%s: failed to acquire my own lock! PANIC!\n", - ZR_DEVNAME(zr)); - res = -ENODEV; - goto open_unlock_and_return; - } if (!try_module_get(zr->decoder->driver->driver.owner)) { dprintk(1, KERN_ERR - "%s: failed to grab ownership of i2c decoder\n", + "%s: failed to grab ownership of video decoder\n", ZR_DEVNAME(zr)); res = -EIO; - module_put(THIS_MODULE); - goto open_unlock_and_return; + goto fail_unlock; } if (zr->encoder && !try_module_get(zr->encoder->driver->driver.owner)) { dprintk(1, KERN_ERR - "%s: failed to grab ownership of i2c encoder\n", + "%s: failed to grab ownership of video encoder\n", ZR_DEVNAME(zr)); res = -EIO; - module_put(zr->decoder->driver->driver.owner); - module_put(THIS_MODULE); - goto open_unlock_and_return; + goto fail_decoder; } - have_module_locks = 1; - - if (zr->user >= 2048) { - dprintk(1, KERN_ERR "%s: too many users (%d) on device\n", - ZR_DEVNAME(zr), zr->user); - res = -EBUSY; - goto open_unlock_and_return; - } - - dprintk(1, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n", - ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user); - /* now, create the open()-specific file_ops struct */ fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL); if (!fh) { @@ -1281,7 +1252,7 @@ zoran_open(struct file *file) "%s: zoran_open() - allocation of zoran_fh failed\n", ZR_DEVNAME(zr)); res = -ENOMEM; - goto open_unlock_and_return; + goto fail_encoder; } /* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows * on norm-change! */ @@ -1292,9 +1263,8 @@ zoran_open(struct file *file) KERN_ERR "%s: zoran_open() - allocation of overlay_mask failed\n", ZR_DEVNAME(zr)); - kfree(fh); res = -ENOMEM; - goto open_unlock_and_return; + goto fail_fh; } if (zr->user++ == 0) @@ -1319,22 +1289,19 @@ zoran_open(struct file *file) return 0; -open_unlock_and_return: - /* if we grabbed locks, release them accordingly */ - if (have_module_locks) { - module_put(zr->decoder->driver->driver.owner); - if (zr->encoder) { - module_put(zr->encoder->driver->driver.owner); - } - module_put(THIS_MODULE); - } - - /* if there's no device found, we didn't obtain the lock either */ - if (zr) { - /*mutex_unlock(&zr->resource_lock);*/ - } +fail_fh: + kfree(fh); +fail_encoder: + if (zr->encoder) + module_put(zr->encoder->driver->driver.owner); +fail_decoder: + module_put(zr->decoder->driver->driver.owner); +fail_unlock: unlock_kernel(); + dprintk(2, KERN_INFO "%s: open failed (%d), users(-)=%d\n", + ZR_DEVNAME(zr), res, zr->user); + return res; } @@ -1344,8 +1311,8 @@ zoran_close(struct file *file) struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; - dprintk(1, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n", - ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user); + dprintk(2, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n", + ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user - 1); /* kernel locks (fs/device.c), so don't do that ourselves * (prevents deadlocks) */ @@ -1391,10 +1358,8 @@ zoran_close(struct file *file) /* release locks on the i2c modules */ module_put(zr->decoder->driver->driver.owner); - if (zr->encoder) { - module_put(zr->encoder->driver->driver.owner); - } - module_put(THIS_MODULE); + if (zr->encoder) + module_put(zr->encoder->driver->driver.owner); /*mutex_unlock(&zr->resource_lock);*/ diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 24508e2..ea9488e 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -626,7 +626,6 @@ static int __devinit pcf50633_probe(struct i2c_client *client, } if (client->irq) { - set_irq_handler(client->irq, handle_level_irq); ret = request_irq(client->irq, pcf50633_irq, IRQF_TRIGGER_LOW, "pcf50633", pcf); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 396d935..1c48408 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -217,6 +217,7 @@ config DELL_LAPTOP depends on EXPERIMENTAL depends on BACKLIGHT_CLASS_DEVICE depends on RFKILL + depends on POWER_SUPPLY default n ---help--- This driver adds support for rfkill and backlight control to Dell diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index bf5e4d0..558bf3f 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c @@ -35,7 +35,7 @@ struct ssc_device *ssc_request(unsigned int ssc_num) if (!ssc_valid) { spin_unlock(&user_lock); - dev_dbg(&ssc->pdev->dev, "could not find requested device\n"); + pr_err("ssc: ssc%d platform device is missing\n", ssc_num); return ERR_PTR(-ENODEV); } diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c index 10c421b..f26667a 100644 --- a/drivers/misc/hpilo.c +++ b/drivers/misc/hpilo.c @@ -207,7 +207,7 @@ static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data) &device_ccb->recv_ctrl); /* give iLO some time to process stop request */ - for (retries = 1000; retries > 0; retries--) { + for (retries = MAX_WAIT; retries > 0; retries--) { doorbell_set(driver_ccb); udelay(1); if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A)) @@ -309,7 +309,7 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot) doorbell_clr(driver_ccb); /* make sure iLO is really handling requests */ - for (i = 1000; i > 0; i--) { + for (i = MAX_WAIT; i > 0; i--) { if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL)) break; udelay(1); @@ -326,7 +326,7 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot) return 0; free: - pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa); + ilo_ccb_close(pdev, data); out: return error; } diff --git a/drivers/misc/hpilo.h b/drivers/misc/hpilo.h index a281207..b64a20e 100644 --- a/drivers/misc/hpilo.h +++ b/drivers/misc/hpilo.h @@ -19,6 +19,8 @@ #define MAX_ILO_DEV 1 /* max number of files */ #define MAX_OPEN (MAX_CCB * MAX_ILO_DEV) +/* spin counter for open/close delay */ +#define MAX_WAIT 10000 /* * Per device, used to track global memory allocations. diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h index a5bd658..275b788 100644 --- a/drivers/misc/sgi-xp/xpc.h +++ b/drivers/misc/sgi-xp/xpc.h @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2004-2009 Silicon Graphics, Inc. All Rights Reserved. */ /* @@ -514,7 +514,8 @@ struct xpc_channel_uv { /* partition's notify mq */ struct xpc_send_msg_slot_uv *send_msg_slots; - struct xpc_notify_mq_msg_uv *recv_msg_slots; + void *recv_msg_slots; /* each slot will hold a xpc_notify_mq_msg_uv */ + /* structure plus the user's payload */ struct xpc_fifo_head_uv msg_slot_free_list; struct xpc_fifo_head_uv recv_msg_list; /* deliverable payloads */ diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index f17f7d4..29c0502 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2008-2009 Silicon Graphics, Inc. All Rights Reserved. */ /* @@ -1010,8 +1010,8 @@ xpc_allocate_recv_msg_slot_uv(struct xpc_channel *ch) continue; for (entry = 0; entry < nentries; entry++) { - msg_slot = ch_uv->recv_msg_slots + entry * - ch->entry_size; + msg_slot = ch_uv->recv_msg_slots + + entry * ch->entry_size; msg_slot->hdr.msg_slot_number = entry; } @@ -1308,9 +1308,8 @@ xpc_handle_notify_mq_msg_uv(struct xpc_partition *part, /* we're dealing with a normal message sent via the notify_mq */ ch_uv = &ch->sn.uv; - msg_slot = (struct xpc_notify_mq_msg_uv *)((u64)ch_uv->recv_msg_slots + - (msg->hdr.msg_slot_number % ch->remote_nentries) * - ch->entry_size); + msg_slot = ch_uv->recv_msg_slots + + (msg->hdr.msg_slot_number % ch->remote_nentries) * ch->entry_size; BUG_ON(msg->hdr.msg_slot_number != msg_slot->hdr.msg_slot_number); BUG_ON(msg_slot->hdr.size != 0); diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c index 7957f52..6faefcf 100644 --- a/drivers/misc/sgi-xp/xpnet.c +++ b/drivers/misc/sgi-xp/xpnet.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1999-2008 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1999-2009 Silicon Graphics, Inc. All rights reserved. */ /* @@ -551,6 +551,7 @@ xpnet_init(void) netif_carrier_off(xpnet_device); + xpnet_device->netdev_ops = &xpnet_netdev_ops; xpnet_device->mtu = XPNET_DEF_MTU; /* diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 0efa390..99d4b28 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -145,6 +145,16 @@ config MMC_IMX If unsure, say N. +config MMC_MXC + tristate "Freescale i.MX2/3 Multimedia Card Interface support" + depends on ARCH_MXC + help + This selects the Freescale i.MX2/3 Multimedia card Interface. + If you have a i.MX platform with a Multimedia Card slot, + say Y or M here. + + If unsure, say N. + config MMC_TIFM_SD tristate "TI Flash Media MMC/SD Interface support (EXPERIMENTAL)" depends on EXPERIMENTAL && PCI diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 98cab84..dedec55 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -9,6 +9,7 @@ endif obj-$(CONFIG_MMC_ARMMMCI) += mmci.o obj-$(CONFIG_MMC_PXA) += pxamci.o obj-$(CONFIG_MMC_IMX) += imxmmc.o +obj-$(CONFIG_MMC_MXC) += mxcmmc.o obj-$(CONFIG_MMC_SDHCI) += sdhci.o obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 1bcbdd6..2909bbc8 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -430,6 +430,8 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) clk = 255; host->cclk = host->mclk / (2 * (clk + 1)); } + if (host->hw_designer == 0x80) + clk |= MCI_FCEN; /* Bug fix in ST IP block */ clk |= MCI_CLK_ENABLE; } @@ -440,15 +442,27 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) case MMC_POWER_OFF: break; case MMC_POWER_UP: - pwr |= MCI_PWR_UP; - break; + /* The ST version does not have this, fall through to POWER_ON */ + if (host->hw_designer != 0x80) { + pwr |= MCI_PWR_UP; + break; + } case MMC_POWER_ON: pwr |= MCI_PWR_ON; break; } - if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) - pwr |= MCI_ROD; + if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) { + if (host->hw_designer != 0x80) + pwr |= MCI_ROD; + else { + /* + * The ST Micro variant use the ROD bit for something + * else and only has OD (Open Drain). + */ + pwr |= MCI_OD; + } + } writel(clk, host->base + MMCICLOCK); @@ -500,6 +514,12 @@ static int mmci_probe(struct amba_device *dev, void *id) } host = mmc_priv(mmc); + /* Bits 12 thru 19 is the designer */ + host->hw_designer = (dev->periphid >> 12) & 0xff; + /* Bits 20 thru 23 is the revison */ + host->hw_revision = (dev->periphid >> 20) & 0xf; + DBG(host, "designer ID = 0x%02x\n", host->hw_designer); + DBG(host, "revision = 0x%01x\n", host->hw_revision); host->clk = clk_get(&dev->dev, NULL); if (IS_ERR(host->clk)) { ret = PTR_ERR(host->clk); @@ -693,6 +713,15 @@ static struct amba_id mmci_ids[] = { .id = 0x00041181, .mask = 0x000fffff, }, + /* ST Micro variants */ + { + .id = 0x00180180, + .mask = 0x00ffffff, + }, + { + .id = 0x00280180, + .mask = 0x00ffffff, + }, { 0, 0 }, }; diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 0f39c49..0441bac 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -11,13 +11,23 @@ #define MCI_PWR_OFF 0x00 #define MCI_PWR_UP 0x02 #define MCI_PWR_ON 0x03 +#define MCI_DATA2DIREN (1 << 2) +#define MCI_CMDDIREN (1 << 3) +#define MCI_DATA0DIREN (1 << 4) +#define MCI_DATA31DIREN (1 << 5) #define MCI_OD (1 << 6) #define MCI_ROD (1 << 7) +/* The ST Micro version does not have ROD */ +#define MCI_FBCLKEN (1 << 7) +#define MCI_DATA74DIREN (1 << 8) #define MMCICLOCK 0x004 #define MCI_CLK_ENABLE (1 << 8) #define MCI_CLK_PWRSAVE (1 << 9) #define MCI_CLK_BYPASS (1 << 10) +#define MCI_WIDE_BUS (1 << 11) +/* HW flow control on the ST Micro version */ +#define MCI_FCEN (1 << 13) #define MMCIARGUMENT 0x008 #define MMCICOMMAND 0x00c @@ -26,6 +36,10 @@ #define MCI_CPSM_INTERRUPT (1 << 8) #define MCI_CPSM_PENDING (1 << 9) #define MCI_CPSM_ENABLE (1 << 10) +#define MCI_SDIO_SUSP (1 << 11) +#define MCI_ENCMD_COMPL (1 << 12) +#define MCI_NIEN (1 << 13) +#define MCI_CE_ATACMD (1 << 14) #define MMCIRESPCMD 0x010 #define MMCIRESPONSE0 0x014 @@ -39,6 +53,11 @@ #define MCI_DPSM_DIRECTION (1 << 1) #define MCI_DPSM_MODE (1 << 2) #define MCI_DPSM_DMAENABLE (1 << 3) +#define MCI_DPSM_BLOCKSIZE (1 << 4) +#define MCI_DPSM_RWSTART (1 << 8) +#define MCI_DPSM_RWSTOP (1 << 9) +#define MCI_DPSM_RWMOD (1 << 10) +#define MCI_DPSM_SDIOEN (1 << 11) #define MMCIDATACNT 0x030 #define MMCISTATUS 0x034 @@ -63,6 +82,8 @@ #define MCI_RXFIFOEMPTY (1 << 19) #define MCI_TXDATAAVLBL (1 << 20) #define MCI_RXDATAAVLBL (1 << 21) +#define MCI_SDIOIT (1 << 22) +#define MCI_CEATAEND (1 << 23) #define MMCICLEAR 0x038 #define MCI_CMDCRCFAILCLR (1 << 0) @@ -75,6 +96,8 @@ #define MCI_CMDSENTCLR (1 << 7) #define MCI_DATAENDCLR (1 << 8) #define MCI_DATABLOCKENDCLR (1 << 10) +#define MCI_SDIOITC (1 << 22) +#define MCI_CEATAENDC (1 << 23) #define MMCIMASK0 0x03c #define MCI_CMDCRCFAILMASK (1 << 0) @@ -98,6 +121,8 @@ #define MCI_RXFIFOEMPTYMASK (1 << 19) #define MCI_TXDATAAVLBLMASK (1 << 20) #define MCI_RXDATAAVLBLMASK (1 << 21) +#define MCI_SDIOITMASK (1 << 22) +#define MCI_CEATAENDMASK (1 << 23) #define MMCIMASK1 0x040 #define MMCIFIFOCNT 0x048 @@ -136,6 +161,9 @@ struct mmci_host { u32 pwr; struct mmc_platform_data *plat; + u8 hw_designer; + u8 hw_revision:4; + struct timer_list timer; unsigned int oldstat; diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c new file mode 100644 index 0000000..dda0be4 --- /dev/null +++ b/drivers/mmc/host/mxcmmc.c @@ -0,0 +1,880 @@ +/* + * linux/drivers/mmc/host/mxcmmc.c - Freescale i.MX MMCI driver + * + * This is a driver for the SDHC controller found in Freescale MX2/MX3 + * SoCs. It is basically the same hardware as found on MX1 (imxmmc.c). + * Unlike the hardware found on MX1, this hardware just works and does + * not need all the quirks found in imxmmc.c, hence the seperate driver. + * + * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> + * Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com> + * + * derived from pxamci.c by Russell King + * + * 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 <linux/module.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/blkdev.h> +#include <linux/dma-mapping.h> +#include <linux/mmc/host.h> +#include <linux/mmc/card.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/gpio.h> + +#include <asm/dma.h> +#include <asm/irq.h> +#include <asm/sizes.h> +#include <mach/mmc.h> + +#ifdef CONFIG_ARCH_MX2 +#include <mach/dma-mx1-mx2.h> +#define HAS_DMA +#endif + +#define DRIVER_NAME "imx-mmc" + +#define MMC_REG_STR_STP_CLK 0x00 +#define MMC_REG_STATUS 0x04 +#define MMC_REG_CLK_RATE 0x08 +#define MMC_REG_CMD_DAT_CONT 0x0C +#define MMC_REG_RES_TO 0x10 +#define MMC_REG_READ_TO 0x14 +#define MMC_REG_BLK_LEN 0x18 +#define MMC_REG_NOB 0x1C +#define MMC_REG_REV_NO 0x20 +#define MMC_REG_INT_CNTR 0x24 +#define MMC_REG_CMD 0x28 +#define MMC_REG_ARG 0x2C +#define MMC_REG_RES_FIFO 0x34 +#define MMC_REG_BUFFER_ACCESS 0x38 + +#define STR_STP_CLK_RESET (1 << 3) +#define STR_STP_CLK_START_CLK (1 << 1) +#define STR_STP_CLK_STOP_CLK (1 << 0) + +#define STATUS_CARD_INSERTION (1 << 31) +#define STATUS_CARD_REMOVAL (1 << 30) +#define STATUS_YBUF_EMPTY (1 << 29) +#define STATUS_XBUF_EMPTY (1 << 28) +#define STATUS_YBUF_FULL (1 << 27) +#define STATUS_XBUF_FULL (1 << 26) +#define STATUS_BUF_UND_RUN (1 << 25) +#define STATUS_BUF_OVFL (1 << 24) +#define STATUS_SDIO_INT_ACTIVE (1 << 14) +#define STATUS_END_CMD_RESP (1 << 13) +#define STATUS_WRITE_OP_DONE (1 << 12) +#define STATUS_DATA_TRANS_DONE (1 << 11) +#define STATUS_READ_OP_DONE (1 << 11) +#define STATUS_WR_CRC_ERROR_CODE_MASK (3 << 10) +#define STATUS_CARD_BUS_CLK_RUN (1 << 8) +#define STATUS_BUF_READ_RDY (1 << 7) +#define STATUS_BUF_WRITE_RDY (1 << 6) +#define STATUS_RESP_CRC_ERR (1 << 5) +#define STATUS_CRC_READ_ERR (1 << 3) +#define STATUS_CRC_WRITE_ERR (1 << 2) +#define STATUS_TIME_OUT_RESP (1 << 1) +#define STATUS_TIME_OUT_READ (1 << 0) +#define STATUS_ERR_MASK 0x2f + +#define CMD_DAT_CONT_CMD_RESP_LONG_OFF (1 << 12) +#define CMD_DAT_CONT_STOP_READWAIT (1 << 11) +#define CMD_DAT_CONT_START_READWAIT (1 << 10) +#define CMD_DAT_CONT_BUS_WIDTH_4 (2 << 8) +#define CMD_DAT_CONT_INIT (1 << 7) +#define CMD_DAT_CONT_WRITE (1 << 4) +#define CMD_DAT_CONT_DATA_ENABLE (1 << 3) +#define CMD_DAT_CONT_RESPONSE_48BIT_CRC (1 << 0) +#define CMD_DAT_CONT_RESPONSE_136BIT (2 << 0) +#define CMD_DAT_CONT_RESPONSE_48BIT (3 << 0) + +#define INT_SDIO_INT_WKP_EN (1 << 18) +#define INT_CARD_INSERTION_WKP_EN (1 << 17) +#define INT_CARD_REMOVAL_WKP_EN (1 << 16) +#define INT_CARD_INSERTION_EN (1 << 15) +#define INT_CARD_REMOVAL_EN (1 << 14) +#define INT_SDIO_IRQ_EN (1 << 13) +#define INT_DAT0_EN (1 << 12) +#define INT_BUF_READ_EN (1 << 4) +#define INT_BUF_WRITE_EN (1 << 3) +#define INT_END_CMD_RES_EN (1 << 2) +#define INT_WRITE_OP_DONE_EN (1 << 1) +#define INT_READ_OP_EN (1 << 0) + +struct mxcmci_host { + struct mmc_host *mmc; + struct resource *res; + void __iomem *base; + int irq; + int detect_irq; + int dma; + int do_dma; + unsigned int power_mode; + struct imxmmc_platform_data *pdata; + + struct mmc_request *req; + struct mmc_command *cmd; + struct mmc_data *data; + + unsigned int dma_nents; + unsigned int datasize; + unsigned int dma_dir; + + u16 rev_no; + unsigned int cmdat; + + struct clk *clk; + + int clock; + + struct work_struct datawork; +}; + +static inline int mxcmci_use_dma(struct mxcmci_host *host) +{ + return host->do_dma; +} + +static void mxcmci_softreset(struct mxcmci_host *host) +{ + int i; + + /* reset sequence */ + writew(STR_STP_CLK_RESET, host->base + MMC_REG_STR_STP_CLK); + writew(STR_STP_CLK_RESET | STR_STP_CLK_START_CLK, + host->base + MMC_REG_STR_STP_CLK); + + for (i = 0; i < 8; i++) + writew(STR_STP_CLK_START_CLK, host->base + MMC_REG_STR_STP_CLK); + + writew(0xff, host->base + MMC_REG_RES_TO); +} + +static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) +{ + unsigned int nob = data->blocks; + unsigned int blksz = data->blksz; + unsigned int datasize = nob * blksz; +#ifdef HAS_DMA + struct scatterlist *sg; + int i; +#endif + if (data->flags & MMC_DATA_STREAM) + nob = 0xffff; + + host->data = data; + data->bytes_xfered = 0; + + writew(nob, host->base + MMC_REG_NOB); + writew(blksz, host->base + MMC_REG_BLK_LEN); + host->datasize = datasize; + +#ifdef HAS_DMA + for_each_sg(data->sg, sg, data->sg_len, i) { + if (sg->offset & 3 || sg->length & 3) { + host->do_dma = 0; + return; + } + } + + if (data->flags & MMC_DATA_READ) { + host->dma_dir = DMA_FROM_DEVICE; + host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, + data->sg_len, host->dma_dir); + + imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, datasize, + host->res->start + MMC_REG_BUFFER_ACCESS, + DMA_MODE_READ); + } else { + host->dma_dir = DMA_TO_DEVICE; + host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, + data->sg_len, host->dma_dir); + + imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, datasize, + host->res->start + MMC_REG_BUFFER_ACCESS, + DMA_MODE_WRITE); + } + + wmb(); + + imx_dma_enable(host->dma); +#endif /* HAS_DMA */ +} + +static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, + unsigned int cmdat) +{ + WARN_ON(host->cmd != NULL); + host->cmd = cmd; + + switch (mmc_resp_type(cmd)) { + case MMC_RSP_R1: /* short CRC, OPCODE */ + case MMC_RSP_R1B:/* short CRC, OPCODE, BUSY */ + cmdat |= CMD_DAT_CONT_RESPONSE_48BIT_CRC; + break; + case MMC_RSP_R2: /* long 136 bit + CRC */ + cmdat |= CMD_DAT_CONT_RESPONSE_136BIT; + break; + case MMC_RSP_R3: /* short */ + cmdat |= CMD_DAT_CONT_RESPONSE_48BIT; + break; + case MMC_RSP_NONE: + break; + default: + dev_err(mmc_dev(host->mmc), "unhandled response type 0x%x\n", + mmc_resp_type(cmd)); + cmd->error = -EINVAL; + return -EINVAL; + } + + if (mxcmci_use_dma(host)) + writel(INT_READ_OP_EN | INT_WRITE_OP_DONE_EN | + INT_END_CMD_RES_EN, + host->base + MMC_REG_INT_CNTR); + else + writel(INT_END_CMD_RES_EN, host->base + MMC_REG_INT_CNTR); + + writew(cmd->opcode, host->base + MMC_REG_CMD); + writel(cmd->arg, host->base + MMC_REG_ARG); + writew(cmdat, host->base + MMC_REG_CMD_DAT_CONT); + + return 0; +} + +static void mxcmci_finish_request(struct mxcmci_host *host, + struct mmc_request *req) +{ + writel(0, host->base + MMC_REG_INT_CNTR); + + host->req = NULL; + host->cmd = NULL; + host->data = NULL; + + mmc_request_done(host->mmc, req); +} + +static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat) +{ + struct mmc_data *data = host->data; + int data_error; + +#ifdef HAS_DMA + if (mxcmci_use_dma(host)) { + imx_dma_disable(host->dma); + dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents, + host->dma_dir); + } +#endif + + if (stat & STATUS_ERR_MASK) { + dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", + stat); + if (stat & STATUS_CRC_READ_ERR) { + data->error = -EILSEQ; + } else if (stat & STATUS_CRC_WRITE_ERR) { + u32 err_code = (stat >> 9) & 0x3; + if (err_code == 2) /* No CRC response */ + data->error = -ETIMEDOUT; + else + data->error = -EILSEQ; + } else if (stat & STATUS_TIME_OUT_READ) { + data->error = -ETIMEDOUT; + } else { + data->error = -EIO; + } + } else { + data->bytes_xfered = host->datasize; + } + + data_error = data->error; + + host->data = NULL; + + return data_error; +} + +static void mxcmci_read_response(struct mxcmci_host *host, unsigned int stat) +{ + struct mmc_command *cmd = host->cmd; + int i; + u32 a, b, c; + + if (!cmd) + return; + + if (stat & STATUS_TIME_OUT_RESP) { + dev_dbg(mmc_dev(host->mmc), "CMD TIMEOUT\n"); + cmd->error = -ETIMEDOUT; + } else if (stat & STATUS_RESP_CRC_ERR && cmd->flags & MMC_RSP_CRC) { + dev_dbg(mmc_dev(host->mmc), "cmd crc error\n"); + cmd->error = -EILSEQ; + } + + if (cmd->flags & MMC_RSP_PRESENT) { + if (cmd->flags & MMC_RSP_136) { + for (i = 0; i < 4; i++) { + a = readw(host->base + MMC_REG_RES_FIFO); + b = readw(host->base + MMC_REG_RES_FIFO); + cmd->resp[i] = a << 16 | b; + } + } else { + a = readw(host->base + MMC_REG_RES_FIFO); + b = readw(host->base + MMC_REG_RES_FIFO); + c = readw(host->base + MMC_REG_RES_FIFO); + cmd->resp[0] = a << 24 | b << 8 | c >> 8; + } + } +} + +static int mxcmci_poll_status(struct mxcmci_host *host, u32 mask) +{ + u32 stat; + unsigned long timeout = jiffies + HZ; + + do { + stat = readl(host->base + MMC_REG_STATUS); + if (stat & STATUS_ERR_MASK) + return stat; + if (time_after(jiffies, timeout)) + return STATUS_TIME_OUT_READ; + if (stat & mask) + return 0; + cpu_relax(); + } while (1); +} + +static int mxcmci_pull(struct mxcmci_host *host, void *_buf, int bytes) +{ + unsigned int stat; + u32 *buf = _buf; + + while (bytes > 3) { + stat = mxcmci_poll_status(host, + STATUS_BUF_READ_RDY | STATUS_READ_OP_DONE); + if (stat) + return stat; + *buf++ = readl(host->base + MMC_REG_BUFFER_ACCESS); + bytes -= 4; + } + + if (bytes) { + u8 *b = (u8 *)buf; + u32 tmp; + + stat = mxcmci_poll_status(host, + STATUS_BUF_READ_RDY | STATUS_READ_OP_DONE); + if (stat) + return stat; + tmp = readl(host->base + MMC_REG_BUFFER_ACCESS); + memcpy(b, &tmp, bytes); + } + + return 0; +} + +static int mxcmci_push(struct mxcmci_host *host, void *_buf, int bytes) +{ + unsigned int stat; + u32 *buf = _buf; + + while (bytes > 3) { + stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); + if (stat) + return stat; + writel(*buf++, host->base + MMC_REG_BUFFER_ACCESS); + bytes -= 4; + } + + if (bytes) { + u8 *b = (u8 *)buf; + u32 tmp; + + stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); + if (stat) + return stat; + + memcpy(&tmp, b, bytes); + writel(tmp, host->base + MMC_REG_BUFFER_ACCESS); + } + + stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); + if (stat) + return stat; + + return 0; +} + +static int mxcmci_transfer_data(struct mxcmci_host *host) +{ + struct mmc_data *data = host->req->data; + struct scatterlist *sg; + int stat, i; + + host->datasize = 0; + + host->data = data; + host->datasize = 0; + + if (data->flags & MMC_DATA_READ) { + for_each_sg(data->sg, sg, data->sg_len, i) { + stat = mxcmci_pull(host, sg_virt(sg), sg->length); + if (stat) + return stat; + host->datasize += sg->length; + } + } else { + for_each_sg(data->sg, sg, data->sg_len, i) { + stat = mxcmci_push(host, sg_virt(sg), sg->length); + if (stat) + return stat; + host->datasize += sg->length; + } + stat = mxcmci_poll_status(host, STATUS_WRITE_OP_DONE); + if (stat) + return stat; + } + return 0; +} + +static void mxcmci_datawork(struct work_struct *work) +{ + struct mxcmci_host *host = container_of(work, struct mxcmci_host, + datawork); + int datastat = mxcmci_transfer_data(host); + mxcmci_finish_data(host, datastat); + + if (host->req->stop) { + if (mxcmci_start_cmd(host, host->req->stop, 0)) { + mxcmci_finish_request(host, host->req); + return; + } + } else { + mxcmci_finish_request(host, host->req); + } +} + +#ifdef HAS_DMA +static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat) +{ + struct mmc_data *data = host->data; + int data_error; + + if (!data) + return; + + data_error = mxcmci_finish_data(host, stat); + + mxcmci_read_response(host, stat); + host->cmd = NULL; + + if (host->req->stop) { + if (mxcmci_start_cmd(host, host->req->stop, 0)) { + mxcmci_finish_request(host, host->req); + return; + } + } else { + mxcmci_finish_request(host, host->req); + } +} +#endif /* HAS_DMA */ + +static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat) +{ + mxcmci_read_response(host, stat); + host->cmd = NULL; + + if (!host->data && host->req) { + mxcmci_finish_request(host, host->req); + return; + } + + /* For the DMA case the DMA engine handles the data transfer + * automatically. For non DMA we have to to it ourselves. + * Don't do it in interrupt context though. + */ + if (!mxcmci_use_dma(host) && host->data) + schedule_work(&host->datawork); + +} + +static irqreturn_t mxcmci_irq(int irq, void *devid) +{ + struct mxcmci_host *host = devid; + u32 stat; + + stat = readl(host->base + MMC_REG_STATUS); + writel(stat, host->base + MMC_REG_STATUS); + + dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); + + if (stat & STATUS_END_CMD_RESP) + mxcmci_cmd_done(host, stat); +#ifdef HAS_DMA + if (mxcmci_use_dma(host) && + (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) + mxcmci_data_done(host, stat); +#endif + return IRQ_HANDLED; +} + +static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req) +{ + struct mxcmci_host *host = mmc_priv(mmc); + unsigned int cmdat = host->cmdat; + + WARN_ON(host->req != NULL); + + host->req = req; + host->cmdat &= ~CMD_DAT_CONT_INIT; +#ifdef HAS_DMA + host->do_dma = 1; +#endif + if (req->data) { + mxcmci_setup_data(host, req->data); + + cmdat |= CMD_DAT_CONT_DATA_ENABLE; + + if (req->data->flags & MMC_DATA_WRITE) + cmdat |= CMD_DAT_CONT_WRITE; + } + + if (mxcmci_start_cmd(host, req->cmd, cmdat)) + mxcmci_finish_request(host, req); +} + +static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios) +{ + unsigned int divider; + int prescaler = 0; + unsigned int clk_in = clk_get_rate(host->clk); + + while (prescaler <= 0x800) { + for (divider = 1; divider <= 0xF; divider++) { + int x; + + x = (clk_in / (divider + 1)); + + if (prescaler) + x /= (prescaler * 2); + + if (x <= clk_ios) + break; + } + if (divider < 0x10) + break; + + if (prescaler == 0) + prescaler = 1; + else + prescaler <<= 1; + } + + writew((prescaler << 4) | divider, host->base + MMC_REG_CLK_RATE); + + dev_dbg(mmc_dev(host->mmc), "scaler: %d divider: %d in: %d out: %d\n", + prescaler, divider, clk_in, clk_ios); +} + +static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct mxcmci_host *host = mmc_priv(mmc); +#ifdef HAS_DMA + unsigned int blen; + /* + * use burstlen of 64 in 4 bit mode (--> reg value 0) + * use burstlen of 16 in 1 bit mode (--> reg value 16) + */ + if (ios->bus_width == MMC_BUS_WIDTH_4) + blen = 0; + else + blen = 16; + + imx_dma_config_burstlen(host->dma, blen); +#endif + if (ios->bus_width == MMC_BUS_WIDTH_4) + host->cmdat |= CMD_DAT_CONT_BUS_WIDTH_4; + else + host->cmdat &= ~CMD_DAT_CONT_BUS_WIDTH_4; + + if (host->power_mode != ios->power_mode) { + if (host->pdata && host->pdata->setpower) + host->pdata->setpower(mmc_dev(mmc), ios->vdd); + host->power_mode = ios->power_mode; + if (ios->power_mode == MMC_POWER_ON) + host->cmdat |= CMD_DAT_CONT_INIT; + } + + if (ios->clock) { + mxcmci_set_clk_rate(host, ios->clock); + writew(STR_STP_CLK_START_CLK, host->base + MMC_REG_STR_STP_CLK); + } else { + writew(STR_STP_CLK_STOP_CLK, host->base + MMC_REG_STR_STP_CLK); + } + + host->clock = ios->clock; +} + +static irqreturn_t mxcmci_detect_irq(int irq, void *data) +{ + struct mmc_host *mmc = data; + + dev_dbg(mmc_dev(mmc), "%s\n", __func__); + + mmc_detect_change(mmc, msecs_to_jiffies(250)); + return IRQ_HANDLED; +} + +static int mxcmci_get_ro(struct mmc_host *mmc) +{ + struct mxcmci_host *host = mmc_priv(mmc); + + if (host->pdata && host->pdata->get_ro) + return !!host->pdata->get_ro(mmc_dev(mmc)); + /* + * Board doesn't support read only detection; let the mmc core + * decide what to do. + */ + return -ENOSYS; +} + + +static const struct mmc_host_ops mxcmci_ops = { + .request = mxcmci_request, + .set_ios = mxcmci_set_ios, + .get_ro = mxcmci_get_ro, +}; + +static int mxcmci_probe(struct platform_device *pdev) +{ + struct mmc_host *mmc; + struct mxcmci_host *host = NULL; + struct resource *r; + int ret = 0, irq; + + printk(KERN_INFO "i.MX SDHC driver\n"); + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + if (!r || irq < 0) + return -EINVAL; + + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (!r) + return -EBUSY; + + mmc = mmc_alloc_host(sizeof(struct mxcmci_host), &pdev->dev); + if (!mmc) { + ret = -ENOMEM; + goto out_release_mem; + } + + mmc->ops = &mxcmci_ops; + mmc->caps = MMC_CAP_4_BIT_DATA; + + /* MMC core transfer sizes tunable parameters */ + mmc->max_hw_segs = 64; + mmc->max_phys_segs = 64; + mmc->max_blk_size = 2048; + mmc->max_blk_count = 65535; + mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + mmc->max_seg_size = mmc->max_seg_size; + + host = mmc_priv(mmc); + host->base = ioremap(r->start, resource_size(r)); + if (!host->base) { + ret = -ENOMEM; + goto out_free; + } + + host->mmc = mmc; + host->pdata = pdev->dev.platform_data; + + if (host->pdata && host->pdata->ocr_avail) + mmc->ocr_avail = host->pdata->ocr_avail; + else + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + + host->res = r; + host->irq = irq; + + host->clk = clk_get(&pdev->dev, "sdhc_clk"); + if (IS_ERR(host->clk)) { + ret = PTR_ERR(host->clk); + goto out_iounmap; + } + clk_enable(host->clk); + + mxcmci_softreset(host); + + host->rev_no = readw(host->base + MMC_REG_REV_NO); + if (host->rev_no != 0x400) { + ret = -ENODEV; + dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n", + host->rev_no); + goto out_clk_put; + } + + mmc->f_min = clk_get_rate(host->clk) >> 7; + mmc->f_max = clk_get_rate(host->clk) >> 1; + + /* recommended in data sheet */ + writew(0x2db4, host->base + MMC_REG_READ_TO); + + writel(0, host->base + MMC_REG_INT_CNTR); + +#ifdef HAS_DMA + host->dma = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_LOW); + if (host->dma < 0) { + dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n"); + ret = -EBUSY; + goto out_clk_put; + } + + r = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (!r) { + ret = -EINVAL; + goto out_free_dma; + } + + ret = imx_dma_config_channel(host->dma, + IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO, + IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, + r->start, 0); + if (ret) { + dev_err(mmc_dev(host->mmc), "failed to config DMA channel\n"); + goto out_free_dma; + } +#endif + INIT_WORK(&host->datawork, mxcmci_datawork); + + ret = request_irq(host->irq, mxcmci_irq, 0, DRIVER_NAME, host); + if (ret) + goto out_free_dma; + + platform_set_drvdata(pdev, mmc); + + if (host->pdata && host->pdata->init) { + ret = host->pdata->init(&pdev->dev, mxcmci_detect_irq, + host->mmc); + if (ret) + goto out_free_irq; + } + + mmc_add_host(mmc); + + return 0; + +out_free_irq: + free_irq(host->irq, host); +out_free_dma: +#ifdef HAS_DMA + imx_dma_free(host->dma); +#endif +out_clk_put: + clk_disable(host->clk); + clk_put(host->clk); +out_iounmap: + iounmap(host->base); +out_free: + mmc_free_host(mmc); +out_release_mem: + release_mem_region(host->res->start, resource_size(host->res)); + return ret; +} + +static int mxcmci_remove(struct platform_device *pdev) +{ + struct mmc_host *mmc = platform_get_drvdata(pdev); + struct mxcmci_host *host = mmc_priv(mmc); + + platform_set_drvdata(pdev, NULL); + + mmc_remove_host(mmc); + + if (host->pdata && host->pdata->exit) + host->pdata->exit(&pdev->dev, mmc); + + free_irq(host->irq, host); + iounmap(host->base); +#ifdef HAS_DMA + imx_dma_free(host->dma); +#endif + clk_disable(host->clk); + clk_put(host->clk); + + release_mem_region(host->res->start, resource_size(host->res)); + release_resource(host->res); + + mmc_free_host(mmc); + + return 0; +} + +#ifdef CONFIG_PM +static int mxcmci_suspend(struct platform_device *dev, pm_message_t state) +{ + struct mmc_host *mmc = platform_get_drvdata(dev); + int ret = 0; + + if (mmc) + ret = mmc_suspend_host(mmc, state); + + return ret; +} + +static int mxcmci_resume(struct platform_device *dev) +{ + struct mmc_host *mmc = platform_get_drvdata(dev); + struct mxcmci_host *host; + int ret = 0; + + if (mmc) { + host = mmc_priv(mmc); + ret = mmc_resume_host(mmc); + } + + return ret; +} +#else +#define mxcmci_suspend NULL +#define mxcmci_resume NULL +#endif /* CONFIG_PM */ + +static struct platform_driver mxcmci_driver = { + .probe = mxcmci_probe, + .remove = mxcmci_remove, + .suspend = mxcmci_suspend, + .resume = mxcmci_resume, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + } +}; + +static int __init mxcmci_init(void) +{ + return platform_driver_register(&mxcmci_driver); +} + +static void __exit mxcmci_exit(void) +{ + platform_driver_unregister(&mxcmci_driver); +} + +module_init(mxcmci_init); +module_exit(mxcmci_exit); + +MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver"); +MODULE_AUTHOR("Sascha Hauer, Pengutronix"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:imx-mmc"); diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 3c5483b..9702ad3 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -180,7 +180,15 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) else DALGN &= ~(1 << host->dma); DDADR(host->dma) = host->sg_dma; - DCSR(host->dma) = DCSR_RUN; + + /* + * workaround for erratum #91: + * only start DMA now if we are doing a read, + * otherwise we wait until CMD/RESP has finished + * before starting DMA. + */ + if (!cpu_is_pxa27x() || data->flags & MMC_DATA_READ) + DCSR(host->dma) = DCSR_RUN; } static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, unsigned int cmdat) @@ -251,23 +259,28 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat) if (stat & STAT_TIME_OUT_RESPONSE) { cmd->error = -ETIMEDOUT; } else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) { -#ifdef CONFIG_PXA27x /* * workaround for erratum #42: * Intel PXA27x Family Processor Specification Update Rev 001 * A bogus CRC error can appear if the msb of a 136 bit * response is a one. */ - if (cmd->flags & MMC_RSP_136 && cmd->resp[0] & 0x80000000) { + if (cpu_is_pxa27x() && + (cmd->flags & MMC_RSP_136 && cmd->resp[0] & 0x80000000)) pr_debug("ignoring CRC from command %d - *risky*\n", cmd->opcode); - } else -#endif - cmd->error = -EILSEQ; + else + cmd->error = -EILSEQ; } pxamci_disable_irq(host, END_CMD_RES); if (host->data && !cmd->error) { pxamci_enable_irq(host, DATA_TRAN_DONE); + /* + * workaround for erratum #91, if doing write + * enable DMA late + */ + if (cpu_is_pxa27x() && host->data->flags & MMC_DATA_WRITE) + DCSR(host->dma) = DCSR_RUN; } else { pxamci_finish_request(host, host->mrq); } diff --git a/drivers/mmc/host/ricoh_mmc.c b/drivers/mmc/host/ricoh_mmc.c index be9e7b3..f627905 100644 --- a/drivers/mmc/host/ricoh_mmc.c +++ b/drivers/mmc/host/ricoh_mmc.c @@ -196,7 +196,7 @@ static void __devexit ricoh_mmc_remove(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } -static int ricoh_mmc_suspend(struct pci_dev *pdev, pm_message_t state) +static int ricoh_mmc_suspend_late(struct pci_dev *pdev, pm_message_t state) { struct pci_dev *fw_dev = NULL; @@ -210,7 +210,7 @@ static int ricoh_mmc_suspend(struct pci_dev *pdev, pm_message_t state) return 0; } -static int ricoh_mmc_resume(struct pci_dev *pdev) +static int ricoh_mmc_resume_early(struct pci_dev *pdev) { struct pci_dev *fw_dev = NULL; @@ -229,8 +229,8 @@ static struct pci_driver ricoh_mmc_driver = { .id_table = pci_ids, .probe = ricoh_mmc_probe, .remove = __devexit_p(ricoh_mmc_remove), - .suspend = ricoh_mmc_suspend, - .resume = ricoh_mmc_resume, + .suspend_late = ricoh_mmc_suspend_late, + .resume_early = ricoh_mmc_resume_early, }; /*****************************************************************************\ diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index 7df6bbf..6f6a0f6 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c @@ -453,7 +453,7 @@ static struct platform_driver sa1100_mtd_driver = { .resume = sa1100_mtd_resume, .shutdown = sa1100_mtd_shutdown, .driver = { - .name = "flash", + .name = "sa1100-mtd", .owner = THIS_MODULE, }, }; @@ -474,4 +474,4 @@ module_exit(sa1100_mtd_exit); MODULE_AUTHOR("Nicolas Pitre"); MODULE_DESCRIPTION("SA1100 CFI map driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:flash"); +MODULE_ALIAS("platform:sa1100-mtd"); diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index d15d8b7..54b52e5 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -646,7 +646,7 @@ static const struct net_device_ops etherh_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_set_mac_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 840b3d1..bbbc3bb 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -806,7 +806,7 @@ static int cas_reset_mii_phy(struct cas *cp) cas_phy_write(cp, MII_BMCR, BMCR_RESET); udelay(100); - while (limit--) { + while (--limit) { val = cas_phy_read(cp, MII_BMCR); if ((val & BMCR_RESET) == 0) break; @@ -979,7 +979,7 @@ static void cas_phy_init(struct cas *cp) writel(val, cp->regs + REG_PCS_MII_CTRL); limit = STOP_TRIES; - while (limit-- > 0) { + while (--limit > 0) { udelay(10); if ((readl(cp->regs + REG_PCS_MII_CTRL) & PCS_MII_RESET) == 0) diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 379a132..d31791f 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -2276,8 +2276,7 @@ no_mem: } else if ((len = ntohl(r->len_cq)) != 0) { struct sge_fl *fl; - if (eth) - lro = qs->lro_enabled && is_eth_tcp(rss_hi); + lro &= eth && is_eth_tcp(rss_hi); fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0]; if (fl->use_pages) { diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index c986978..6bd63cc 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -940,7 +940,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, err = pci_enable_device(pdev); } else { bars = pci_select_bars(pdev, IORESOURCE_MEM); - err = pci_enable_device(pdev); + err = pci_enable_device_mem(pdev); } if (err) return err; diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 3f7eab4..acae2d8 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -351,6 +351,9 @@ static int gfar_probe(struct of_device *ofdev, /* Reset MAC layer */ gfar_write(&priv->regs->maccfg1, MACCFG1_SOFT_RESET); + /* We need to delay at least 3 TX clocks */ + udelay(2); + tempval = (MACCFG1_TX_FLOW | MACCFG1_RX_FLOW); gfar_write(&priv->regs->maccfg1, tempval); diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index b1a8334..eaa8689 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -312,7 +312,7 @@ extern const char gfar_driver_version[]; #define ATTRELI_EI(x) (x) #define BD_LFLAG(flags) ((flags) << 16) -#define BD_LENGTH_MASK 0x00ff +#define BD_LENGTH_MASK 0x0000ffff /* TxBD status field bits */ #define TXBD_READY 0x8000 diff --git a/drivers/net/ibm_newemac/phy.c b/drivers/net/ibm_newemac/phy.c index c40cd8d..ac9d964 100644 --- a/drivers/net/ibm_newemac/phy.c +++ b/drivers/net/ibm_newemac/phy.c @@ -60,7 +60,7 @@ int emac_mii_reset_phy(struct mii_phy *phy) udelay(300); - while (limit--) { + while (--limit) { val = phy_read(phy, MII_BMCR); if (val >= 0 && (val & BMCR_RESET) == 0) break; @@ -84,7 +84,7 @@ int emac_mii_reset_gpcs(struct mii_phy *phy) udelay(300); - while (limit--) { + while (--limit) { val = gpcs_phy_read(phy, MII_BMCR); if (val >= 0 && (val & BMCR_RESET) == 0) break; diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index f5e2e72..13ca73f 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -699,11 +699,18 @@ static s32 igb_check_for_link_82575(struct e1000_hw *hw) /* SGMII link check is done through the PCS register. */ if ((hw->phy.media_type != e1000_media_type_copper) || - (igb_sgmii_active_82575(hw))) + (igb_sgmii_active_82575(hw))) { ret_val = igb_get_pcs_speed_and_duplex_82575(hw, &speed, &duplex); - else + /* + * Use this flag to determine if link needs to be checked or + * not. If we have link clear the flag so that we do not + * continue to check for link. + */ + hw->mac.get_link_status = !hw->mac.serdes_has_link; + } else { ret_val = igb_check_for_copper_link(hw); + } return ret_val; } diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 5a27825..aebef8e 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -300,11 +300,10 @@ struct igb_adapter { #define IGB_FLAG_HAS_MSI (1 << 0) #define IGB_FLAG_MSI_ENABLE (1 << 1) -#define IGB_FLAG_HAS_DCA (1 << 2) -#define IGB_FLAG_DCA_ENABLED (1 << 3) -#define IGB_FLAG_IN_NETPOLL (1 << 5) -#define IGB_FLAG_QUAD_PORT_A (1 << 6) -#define IGB_FLAG_NEED_CTX_IDX (1 << 7) +#define IGB_FLAG_DCA_ENABLED (1 << 2) +#define IGB_FLAG_IN_NETPOLL (1 << 3) +#define IGB_FLAG_QUAD_PORT_A (1 << 4) +#define IGB_FLAG_NEED_CTX_IDX (1 << 5) enum e1000_state_t { __IGB_TESTING, diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index b82b0fb..a50db53 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -206,10 +206,11 @@ static int __init igb_init_module(void) global_quad_port_a = 0; - ret = pci_register_driver(&igb_driver); #ifdef CONFIG_IGB_DCA dca_register_notify(&dca_notifier); #endif + + ret = pci_register_driver(&igb_driver); return ret; } @@ -1156,11 +1157,10 @@ static int __devinit igb_probe(struct pci_dev *pdev, /* set flags */ switch (hw->mac.type) { - case e1000_82576: case e1000_82575: - adapter->flags |= IGB_FLAG_HAS_DCA; adapter->flags |= IGB_FLAG_NEED_CTX_IDX; break; + case e1000_82576: default: break; } @@ -1310,8 +1310,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, goto err_register; #ifdef CONFIG_IGB_DCA - if ((adapter->flags & IGB_FLAG_HAS_DCA) && - (dca_add_requester(&pdev->dev) == 0)) { + if (dca_add_requester(&pdev->dev) == 0) { adapter->flags |= IGB_FLAG_DCA_ENABLED; dev_info(&pdev->dev, "DCA enabled\n"); /* Always use CB2 mode, difference is masked @@ -1835,11 +1834,11 @@ static void igb_setup_rctl(struct igb_adapter *adapter) rctl |= E1000_RCTL_SECRC; /* - * disable store bad packets, long packet enable, and clear size bits. + * disable store bad packets and clear size bits. */ - rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_LPE | E1000_RCTL_SZ_256); + rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_SZ_256); - if (adapter->netdev->mtu > ETH_DATA_LEN) + /* enable LPE when to prevent packets larger than max_frame_size */ rctl |= E1000_RCTL_LPE; /* Setup buffer sizes */ @@ -1865,7 +1864,7 @@ static void igb_setup_rctl(struct igb_adapter *adapter) */ /* allocations using alloc_page take too long for regular MTU * so only enable packet split for jumbo frames */ - if (rctl & E1000_RCTL_LPE) { + if (adapter->netdev->mtu > ETH_DATA_LEN) { adapter->rx_ps_hdr_size = IGB_RXBUFFER_128; srrctl |= adapter->rx_ps_hdr_size << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT; @@ -3473,19 +3472,16 @@ static int __igb_notify_dca(struct device *dev, void *data) struct e1000_hw *hw = &adapter->hw; unsigned long event = *(unsigned long *)data; - if (!(adapter->flags & IGB_FLAG_HAS_DCA)) - goto out; - switch (event) { case DCA_PROVIDER_ADD: /* if already enabled, don't do it again */ if (adapter->flags & IGB_FLAG_DCA_ENABLED) break; - adapter->flags |= IGB_FLAG_DCA_ENABLED; /* Always use CB2 mode, difference is masked * in the CB driver. */ wr32(E1000_DCA_CTRL, 2); if (dca_add_requester(dev) == 0) { + adapter->flags |= IGB_FLAG_DCA_ENABLED; dev_info(&adapter->pdev->dev, "DCA enabled\n"); igb_setup_dca(adapter); break; @@ -3502,7 +3498,7 @@ static int __igb_notify_dca(struct device *dev, void *data) } break; } -out: + return 0; } diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index c38ed77..a699940 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -586,7 +586,7 @@ static int pcnet_config(struct pcmcia_device *link) } if ((link->conf.ConfigBase == 0x03c0) - && (link->manf_id == 0x149) && (link->card_id = 0xc1ab)) { + && (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { printk(KERN_INFO "pcnet_cs: this is an AX88190 card!\n"); printk(KERN_INFO "pcnet_cs: use axnet_cs instead.\n"); goto failed; diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index ec23142..335da483 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c @@ -2168,7 +2168,7 @@ static void gelic_wl_connected_event(struct gelic_wl_info *wl, complete(&wl->assoc_done); netif_carrier_on(port_to_netdev(wl_port(wl))); } else - pr_debug("%s: event %#lx under wpa\n", + pr_debug("%s: event %#llx under wpa\n", __func__, event); } diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index c1dadad..e6fdce9 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -787,12 +787,12 @@ struct mbox_params { struct flash_params { u8 dev_id_str[4]; - u16 size; - u16 csum; - u16 ver; - u16 sub_dev_id; + __le16 size; + __le16 csum; + __le16 ver; + __le16 sub_dev_id; u8 mac_addr[6]; - u16 res; + __le16 res; }; diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 45421c8..3d1d7b6 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -641,7 +641,7 @@ static void ql_enable_all_completion_interrupts(struct ql_adapter *qdev) } -static int ql_read_flash_word(struct ql_adapter *qdev, int offset, u32 *data) +static int ql_read_flash_word(struct ql_adapter *qdev, int offset, __le32 *data) { int status = 0; /* wait for reg to come ready */ @@ -656,8 +656,11 @@ static int ql_read_flash_word(struct ql_adapter *qdev, int offset, u32 *data) FLASH_ADDR, FLASH_ADDR_RDY, FLASH_ADDR_ERR); if (status) goto exit; - /* get the data */ - *data = ql_read32(qdev, FLASH_DATA); + /* This data is stored on flash as an array of + * __le32. Since ql_read32() returns cpu endian + * we need to swap it back. + */ + *data = cpu_to_le32(ql_read32(qdev, FLASH_DATA)); exit: return status; } @@ -666,13 +669,20 @@ static int ql_get_flash_params(struct ql_adapter *qdev) { int i; int status; - u32 *p = (u32 *)&qdev->flash; + __le32 *p = (__le32 *)&qdev->flash; + u32 offset = 0; + + /* Second function's parameters follow the first + * function's. + */ + if (qdev->func) + offset = sizeof(qdev->flash) / sizeof(u32); if (ql_sem_spinlock(qdev, SEM_FLASH_MASK)) return -ETIMEDOUT; for (i = 0; i < sizeof(qdev->flash) / sizeof(u32); i++, p++) { - status = ql_read_flash_word(qdev, i, p); + status = ql_read_flash_word(qdev, i+offset, p); if (status) { QPRINTK(qdev, IFUP, ERR, "Error reading flash.\n"); goto exit; @@ -3826,7 +3836,7 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *ndev = pci_get_drvdata(pdev); struct ql_adapter *qdev = netdev_priv(ndev); - int err; + int err, i; netif_device_detach(ndev); @@ -3836,6 +3846,9 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) return err; } + for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++) + netif_napi_del(&qdev->rx_ring[i].napi); + err = pci_save_state(pdev); if (err) return err; diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 101c00a..847e9bb 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -676,9 +676,8 @@ static int efx_init_port(struct efx_nic *efx) rc = efx->phy_op->init(efx); if (rc) return rc; - efx->phy_op->reconfigure(efx); - mutex_lock(&efx->mac_lock); + efx->phy_op->reconfigure(efx); rc = falcon_switch_mac(efx); mutex_unlock(&efx->mac_lock); if (rc) @@ -686,7 +685,7 @@ static int efx_init_port(struct efx_nic *efx) efx->mac_op->reconfigure(efx); efx->port_initialized = true; - efx->stats_enabled = true; + efx_stats_enable(efx); return 0; fail: @@ -735,6 +734,7 @@ static void efx_fini_port(struct efx_nic *efx) if (!efx->port_initialized) return; + efx_stats_disable(efx); efx->phy_op->fini(efx); efx->port_initialized = false; @@ -1368,6 +1368,20 @@ static int efx_net_stop(struct net_device *net_dev) return 0; } +void efx_stats_disable(struct efx_nic *efx) +{ + spin_lock(&efx->stats_lock); + ++efx->stats_disable_count; + spin_unlock(&efx->stats_lock); +} + +void efx_stats_enable(struct efx_nic *efx) +{ + spin_lock(&efx->stats_lock); + --efx->stats_disable_count; + spin_unlock(&efx->stats_lock); +} + /* Context: process, dev_base_lock or RTNL held, non-blocking. */ static struct net_device_stats *efx_net_stats(struct net_device *net_dev) { @@ -1376,12 +1390,12 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev) struct net_device_stats *stats = &net_dev->stats; /* Update stats if possible, but do not wait if another thread - * is updating them (or resetting the NIC); slightly stale - * stats are acceptable. + * is updating them or if MAC stats fetches are temporarily + * disabled; slightly stale stats are acceptable. */ if (!spin_trylock(&efx->stats_lock)) return stats; - if (efx->stats_enabled) { + if (!efx->stats_disable_count) { efx->mac_op->update_stats(efx); falcon_update_nic_stats(efx); } @@ -1629,16 +1643,12 @@ static void efx_unregister_netdev(struct efx_nic *efx) /* Tears down the entire software state and most of the hardware state * before reset. */ -void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) +void efx_reset_down(struct efx_nic *efx, enum reset_type method, + struct ethtool_cmd *ecmd) { EFX_ASSERT_RESET_SERIALISED(efx); - /* The net_dev->get_stats handler is quite slow, and will fail - * if a fetch is pending over reset. Serialise against it. */ - spin_lock(&efx->stats_lock); - efx->stats_enabled = false; - spin_unlock(&efx->stats_lock); - + efx_stats_disable(efx); efx_stop_all(efx); mutex_lock(&efx->mac_lock); mutex_lock(&efx->spi_lock); @@ -1646,6 +1656,8 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) efx->phy_op->get_settings(efx, ecmd); efx_fini_channels(efx); + if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) + efx->phy_op->fini(efx); } /* This function will always ensure that the locks acquired in @@ -1653,7 +1665,8 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) * that we were unable to reinitialise the hardware, and the * driver should be disabled. If ok is false, then the rx and tx * engines are not restarted, pending a RESET_DISABLE. */ -int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok) +int efx_reset_up(struct efx_nic *efx, enum reset_type method, + struct ethtool_cmd *ecmd, bool ok) { int rc; @@ -1665,6 +1678,15 @@ int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok) ok = false; } + if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) { + if (ok) { + rc = efx->phy_op->init(efx); + if (rc) + ok = false; + } else + efx->port_initialized = false; + } + if (ok) { efx_init_channels(efx); @@ -1677,7 +1699,7 @@ int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok) if (ok) { efx_start_all(efx); - efx->stats_enabled = true; + efx_stats_enable(efx); } return rc; } @@ -1709,7 +1731,7 @@ static int efx_reset(struct efx_nic *efx) EFX_INFO(efx, "resetting (%d)\n", method); - efx_reset_down(efx, &ecmd); + efx_reset_down(efx, method, &ecmd); rc = falcon_reset_hw(efx, method); if (rc) { @@ -1728,10 +1750,10 @@ static int efx_reset(struct efx_nic *efx) /* Leave device stopped if necessary */ if (method == RESET_TYPE_DISABLE) { - efx_reset_up(efx, &ecmd, false); + efx_reset_up(efx, method, &ecmd, false); rc = -EIO; } else { - rc = efx_reset_up(efx, &ecmd, true); + rc = efx_reset_up(efx, method, &ecmd, true); } out_disable: @@ -1883,6 +1905,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, efx->rx_checksum_enabled = true; spin_lock_init(&efx->netif_stop_lock); spin_lock_init(&efx->stats_lock); + efx->stats_disable_count = 1; mutex_init(&efx->mac_lock); efx->mac_op = &efx_dummy_mac_operations; efx->phy_op = &efx_dummy_phy_operations; diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h index 0dd7a53..55d0f13 100644 --- a/drivers/net/sfc/efx.h +++ b/drivers/net/sfc/efx.h @@ -36,13 +36,16 @@ extern void efx_process_channel_now(struct efx_channel *channel); extern void efx_flush_queues(struct efx_nic *efx); /* Ports */ +extern void efx_stats_disable(struct efx_nic *efx); +extern void efx_stats_enable(struct efx_nic *efx); extern void efx_reconfigure_port(struct efx_nic *efx); extern void __efx_reconfigure_port(struct efx_nic *efx); /* Reset handling */ -extern void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd); -extern int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, - bool ok); +extern void efx_reset_down(struct efx_nic *efx, enum reset_type method, + struct ethtool_cmd *ecmd); +extern int efx_reset_up(struct efx_nic *efx, enum reset_type method, + struct ethtool_cmd *ecmd, bool ok); /* Global */ extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type); diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 53d259e..7b5924c0 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -219,9 +219,6 @@ int efx_ethtool_set_settings(struct net_device *net_dev, struct efx_nic *efx = netdev_priv(net_dev); int rc; - if (EFX_WORKAROUND_13963(efx) && !ecmd->autoneg) - return -EINVAL; - /* Falcon GMAC does not support 1000Mbps HD */ if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) { EFX_LOG(efx, "rejecting unsupported 1000Mbps HD" diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 5b9f2d9..d5378e6 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -824,10 +824,6 @@ static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue, rx_ev_pause_frm ? " [PAUSE]" : ""); } #endif - - if (unlikely(rx_ev_eth_crc_err && EFX_WORKAROUND_10750(efx) && - efx->phy_type == PHY_TYPE_SFX7101)) - tenxpress_crc_err(efx); } /* Handle receive events that are not in-order. */ @@ -1887,7 +1883,7 @@ static int falcon_reset_macs(struct efx_nic *efx) /* MAC stats will fail whilst the TX fifo is draining. Serialise * the drain sequence with the statistics fetch */ - spin_lock(&efx->stats_lock); + efx_stats_disable(efx); falcon_read(efx, ®, MAC0_CTRL_REG_KER); EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, 1); @@ -1917,7 +1913,7 @@ static int falcon_reset_macs(struct efx_nic *efx) udelay(10); } - spin_unlock(&efx->stats_lock); + efx_stats_enable(efx); /* If we've reset the EM block and the link is up, then * we'll have to kick the XAUI link so the PHY can recover */ @@ -2277,6 +2273,10 @@ int falcon_switch_mac(struct efx_nic *efx) struct efx_mac_operations *old_mac_op = efx->mac_op; efx_oword_t nic_stat; unsigned strap_val; + int rc = 0; + + /* Don't try to fetch MAC stats while we're switching MACs */ + efx_stats_disable(efx); /* Internal loopbacks override the phy speed setting */ if (efx->loopback_mode == LOOPBACK_GMAC) { @@ -2287,16 +2287,12 @@ int falcon_switch_mac(struct efx_nic *efx) efx->link_fd = true; } + WARN_ON(!mutex_is_locked(&efx->mac_lock)); efx->mac_op = (EFX_IS10G(efx) ? &falcon_xmac_operations : &falcon_gmac_operations); - if (old_mac_op == efx->mac_op) - return 0; - - WARN_ON(!mutex_is_locked(&efx->mac_lock)); - - /* Not all macs support a mac-level link state */ - efx->mac_up = true; + /* Always push the NIC_STAT_REG setting even if the mac hasn't + * changed, because this function is run post online reset */ falcon_read(efx, &nic_stat, NIC_STAT_REG); strap_val = EFX_IS10G(efx) ? 5 : 3; if (falcon_rev(efx) >= FALCON_REV_B0) { @@ -2309,9 +2305,17 @@ int falcon_switch_mac(struct efx_nic *efx) BUG_ON(EFX_OWORD_FIELD(nic_stat, STRAP_PINS) != strap_val); } + if (old_mac_op == efx->mac_op) + goto out; EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G'); - return falcon_reset_macs(efx); + /* Not all macs support a mac-level link state */ + efx->mac_up = true; + + rc = falcon_reset_macs(efx); +out: + efx_stats_enable(efx); + return rc; } /* This call is responsible for hooking in the MAC and PHY operations */ diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c index f6a1642..f9e2f95 100644 --- a/drivers/net/sfc/mdio_10g.c +++ b/drivers/net/sfc/mdio_10g.c @@ -15,6 +15,7 @@ #include "net_driver.h" #include "mdio_10g.h" #include "boards.h" +#include "workarounds.h" int mdio_clause45_reset_mmd(struct efx_nic *port, int mmd, int spins, int spintime) @@ -179,17 +180,12 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) return false; else if (efx_phy_mode_disabled(efx->phy_mode)) return false; - else if (efx->loopback_mode == LOOPBACK_PHYXS) { + else if (efx->loopback_mode == LOOPBACK_PHYXS) mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS | MDIO_MMDREG_DEVS_PCS | MDIO_MMDREG_DEVS_PMAPMD | MDIO_MMDREG_DEVS_AN); - if (!mmd_mask) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS, - MDIO_PHYXS_STATUS2); - return !(reg & (1 << MDIO_PHYXS_STATUS2_RX_FAULT_LBN)); - } - } else if (efx->loopback_mode == LOOPBACK_PCS) + else if (efx->loopback_mode == LOOPBACK_PCS) mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS | MDIO_MMDREG_DEVS_PMAPMD | MDIO_MMDREG_DEVS_AN); @@ -197,6 +193,13 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) mmd_mask &= ~(MDIO_MMDREG_DEVS_PMAPMD | MDIO_MMDREG_DEVS_AN); + if (!mmd_mask) { + /* Use presence of XGMII faults in leui of link state */ + reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS, + MDIO_PHYXS_STATUS2); + return !(reg & (1 << MDIO_PHYXS_STATUS2_RX_FAULT_LBN)); + } + while (mmd_mask) { if (mmd_mask & 1) { /* Double reads because link state is latched, and a @@ -263,7 +266,7 @@ void mdio_clause45_set_mmds_lpower(struct efx_nic *efx, } } -static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr, u32 xnp) +static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr) { int phy_id = efx->mii.phy_id; u32 result = 0; @@ -278,9 +281,6 @@ static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr, u32 xnp) result |= ADVERTISED_100baseT_Half; if (reg & ADVERTISE_100FULL) result |= ADVERTISED_100baseT_Full; - if (reg & LPA_RESV) - result |= xnp; - return result; } @@ -310,7 +310,7 @@ void mdio_clause45_get_settings(struct efx_nic *efx, */ void mdio_clause45_get_settings_ext(struct efx_nic *efx, struct ethtool_cmd *ecmd, - u32 xnp, u32 xnp_lpa) + u32 npage_adv, u32 npage_lpa) { int phy_id = efx->mii.phy_id; int reg; @@ -361,8 +361,8 @@ void mdio_clause45_get_settings_ext(struct efx_nic *efx, ecmd->autoneg = AUTONEG_ENABLE; ecmd->advertising |= ADVERTISED_Autoneg | - mdio_clause45_get_an(efx, - MDIO_AN_ADVERTISE, xnp); + mdio_clause45_get_an(efx, MDIO_AN_ADVERTISE) | + npage_adv; } else ecmd->autoneg = AUTONEG_DISABLE; } else @@ -371,27 +371,30 @@ void mdio_clause45_get_settings_ext(struct efx_nic *efx, if (ecmd->autoneg) { /* If AN is complete, report best common mode, * otherwise report best advertised mode. */ - u32 common = ecmd->advertising; + u32 modes = 0; if (mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, MDIO_MMDREG_STAT1) & - (1 << MDIO_AN_STATUS_AN_DONE_LBN)) { - common &= mdio_clause45_get_an(efx, MDIO_AN_LPA, - xnp_lpa); - } - if (common & ADVERTISED_10000baseT_Full) { + (1 << MDIO_AN_STATUS_AN_DONE_LBN)) + modes = (ecmd->advertising & + (mdio_clause45_get_an(efx, MDIO_AN_LPA) | + npage_lpa)); + if (modes == 0) + modes = ecmd->advertising; + + if (modes & ADVERTISED_10000baseT_Full) { ecmd->speed = SPEED_10000; ecmd->duplex = DUPLEX_FULL; - } else if (common & (ADVERTISED_1000baseT_Full | - ADVERTISED_1000baseT_Half)) { + } else if (modes & (ADVERTISED_1000baseT_Full | + ADVERTISED_1000baseT_Half)) { ecmd->speed = SPEED_1000; - ecmd->duplex = !!(common & ADVERTISED_1000baseT_Full); - } else if (common & (ADVERTISED_100baseT_Full | - ADVERTISED_100baseT_Half)) { + ecmd->duplex = !!(modes & ADVERTISED_1000baseT_Full); + } else if (modes & (ADVERTISED_100baseT_Full | + ADVERTISED_100baseT_Half)) { ecmd->speed = SPEED_100; - ecmd->duplex = !!(common & ADVERTISED_100baseT_Full); + ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full); } else { ecmd->speed = SPEED_10; - ecmd->duplex = !!(common & ADVERTISED_10baseT_Full); + ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full); } } else { /* Report forced settings */ @@ -415,7 +418,7 @@ int mdio_clause45_set_settings(struct efx_nic *efx, int phy_id = efx->mii.phy_id; struct ethtool_cmd prev; u32 required; - int ctrl1_bits, reg; + int reg; efx->phy_op->get_settings(efx, &prev); @@ -430,99 +433,83 @@ int mdio_clause45_set_settings(struct efx_nic *efx, if (prev.port != PORT_TP || ecmd->port != PORT_TP) return -EINVAL; - /* Check that PHY supports these settings and work out the - * basic control bits */ - if (ecmd->duplex) { + /* Check that PHY supports these settings */ + if (ecmd->autoneg) { + required = SUPPORTED_Autoneg; + } else if (ecmd->duplex) { switch (ecmd->speed) { - case SPEED_10: - ctrl1_bits = BMCR_FULLDPLX; - required = SUPPORTED_10baseT_Full; - break; - case SPEED_100: - ctrl1_bits = BMCR_SPEED100 | BMCR_FULLDPLX; - required = SUPPORTED_100baseT_Full; - break; - case SPEED_1000: - ctrl1_bits = BMCR_SPEED1000 | BMCR_FULLDPLX; - required = SUPPORTED_1000baseT_Full; - break; - case SPEED_10000: - ctrl1_bits = (BMCR_SPEED1000 | BMCR_SPEED100 | - BMCR_FULLDPLX); - required = SUPPORTED_10000baseT_Full; - break; - default: - return -EINVAL; + case SPEED_10: required = SUPPORTED_10baseT_Full; break; + case SPEED_100: required = SUPPORTED_100baseT_Full; break; + default: return -EINVAL; } } else { switch (ecmd->speed) { - case SPEED_10: - ctrl1_bits = 0; - required = SUPPORTED_10baseT_Half; - break; - case SPEED_100: - ctrl1_bits = BMCR_SPEED100; - required = SUPPORTED_100baseT_Half; - break; - case SPEED_1000: - ctrl1_bits = BMCR_SPEED1000; - required = SUPPORTED_1000baseT_Half; - break; - default: - return -EINVAL; + case SPEED_10: required = SUPPORTED_10baseT_Half; break; + case SPEED_100: required = SUPPORTED_100baseT_Half; break; + default: return -EINVAL; } } - if (ecmd->autoneg) - required |= SUPPORTED_Autoneg; required |= ecmd->advertising; if (required & ~prev.supported) return -EINVAL; - /* Set the basic control bits */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1); - reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | 0x003c); - reg |= ctrl1_bits; - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, MDIO_MMDREG_CTRL1, - reg); - - /* Set the AN registers */ - if (ecmd->autoneg != prev.autoneg || - ecmd->advertising != prev.advertising) { - bool xnp = false; - - if (efx->phy_op->set_xnp_advertise) - xnp = efx->phy_op->set_xnp_advertise(efx, - ecmd->advertising); - - if (ecmd->autoneg) { - reg = 0; - if (ecmd->advertising & ADVERTISED_10baseT_Half) - reg |= ADVERTISE_10HALF; - if (ecmd->advertising & ADVERTISED_10baseT_Full) - reg |= ADVERTISE_10FULL; - if (ecmd->advertising & ADVERTISED_100baseT_Half) - reg |= ADVERTISE_100HALF; - if (ecmd->advertising & ADVERTISED_100baseT_Full) - reg |= ADVERTISE_100FULL; - if (xnp) - reg |= ADVERTISE_RESV; - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_ADVERTISE, reg); - } + if (ecmd->autoneg) { + bool xnp = (ecmd->advertising & ADVERTISED_10000baseT_Full + || EFX_WORKAROUND_13204(efx)); + + /* Set up the base page */ + reg = ADVERTISE_CSMA; + if (ecmd->advertising & ADVERTISED_10baseT_Half) + reg |= ADVERTISE_10HALF; + if (ecmd->advertising & ADVERTISED_10baseT_Full) + reg |= ADVERTISE_10FULL; + if (ecmd->advertising & ADVERTISED_100baseT_Half) + reg |= ADVERTISE_100HALF; + if (ecmd->advertising & ADVERTISED_100baseT_Full) + reg |= ADVERTISE_100FULL; + if (xnp) + reg |= ADVERTISE_RESV; + else if (ecmd->advertising & (ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full)) + reg |= ADVERTISE_NPAGE; + reg |= efx_fc_advertise(efx->wanted_fc); + mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, + MDIO_AN_ADVERTISE, reg); + + /* Set up the (extended) next page if necessary */ + if (efx->phy_op->set_npage_adv) + efx->phy_op->set_npage_adv(efx, ecmd->advertising); + /* Enable and restart AN */ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, MDIO_MMDREG_CTRL1); - if (ecmd->autoneg) - reg |= BMCR_ANENABLE | BMCR_ANRESTART; - else - reg &= ~BMCR_ANENABLE; + reg |= BMCR_ANENABLE; + if (!(EFX_WORKAROUND_15195(efx) && + LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)) + reg |= BMCR_ANRESTART; if (xnp) reg |= 1 << MDIO_AN_CTRL_XNP_LBN; else reg &= ~(1 << MDIO_AN_CTRL_XNP_LBN); mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, MDIO_MMDREG_CTRL1, reg); + } else { + /* Disable AN */ + mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN, + MDIO_MMDREG_CTRL1, + __ffs(BMCR_ANENABLE), false); + + /* Set the basic control bits */ + reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, + MDIO_MMDREG_CTRL1); + reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | + 0x003c); + if (ecmd->speed == SPEED_100) + reg |= BMCR_SPEED100; + if (ecmd->duplex) + reg |= BMCR_FULLDPLX; + mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, + MDIO_MMDREG_CTRL1, reg); } return 0; diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h index 09bf801..8ba4977 100644 --- a/drivers/net/sfc/mdio_10g.h +++ b/drivers/net/sfc/mdio_10g.h @@ -155,7 +155,8 @@ #define MDIO_AN_XNP 22 #define MDIO_AN_LPA_XNP 25 -#define MDIO_AN_10GBT_ADVERTISE 32 +#define MDIO_AN_10GBT_CTRL 32 +#define MDIO_AN_10GBT_CTRL_ADV_10G_LBN 12 #define MDIO_AN_10GBT_STATUS (33) #define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */ #define MDIO_AN_10GBT_STATUS_MS_LBN (14) /* MASTER/SLAVE config */ diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 5f255f7..e019ad1 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -566,7 +566,7 @@ struct efx_mac_operations { * @poll: Poll for hardware state. Serialised by the mac_lock. * @get_settings: Get ethtool settings. Serialised by the mac_lock. * @set_settings: Set ethtool settings. Serialised by the mac_lock. - * @set_xnp_advertise: Set abilities advertised in Extended Next Page + * @set_npage_adv: Set abilities advertised in (Extended) Next Page * (only needed where AN bit is set in mmds) * @num_tests: Number of PHY-specific tests/results * @test_names: Names of the tests/results @@ -586,7 +586,7 @@ struct efx_phy_operations { struct ethtool_cmd *ecmd); int (*set_settings) (struct efx_nic *efx, struct ethtool_cmd *ecmd); - bool (*set_xnp_advertise) (struct efx_nic *efx, u32); + void (*set_npage_adv) (struct efx_nic *efx, u32); u32 num_tests; const char *const *test_names; int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags); @@ -754,8 +754,7 @@ union efx_multicast_hash { * &struct net_device_stats. * @stats_buffer: DMA buffer for statistics * @stats_lock: Statistics update lock. Serialises statistics fetches - * @stats_enabled: Temporarily disable statistics fetches. - * Serialised by @stats_lock + * @stats_disable_count: Nest count for disabling statistics fetches * @mac_op: MAC interface * @mac_address: Permanent MAC address * @phy_type: PHY type @@ -837,7 +836,7 @@ struct efx_nic { struct efx_mac_stats mac_stats; struct efx_buffer stats_buffer; spinlock_t stats_lock; - bool stats_enabled; + unsigned int stats_disable_count; struct efx_mac_operations *mac_op; unsigned char mac_address[ETH_ALEN]; diff --git a/drivers/net/sfc/phy.h b/drivers/net/sfc/phy.h index 58c493e..07e855c 100644 --- a/drivers/net/sfc/phy.h +++ b/drivers/net/sfc/phy.h @@ -17,7 +17,6 @@ extern struct efx_phy_operations falcon_sfx7101_phy_ops; extern struct efx_phy_operations falcon_sft9001_phy_ops; extern void tenxpress_phy_blink(struct efx_nic *efx, bool blink); -extern void tenxpress_crc_err(struct efx_nic *efx); /**************************************************************************** * Exported functions from the driver for XFP optical PHYs diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index dba0d64..0a59808 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c @@ -665,6 +665,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, { enum efx_loopback_mode loopback_mode = efx->loopback_mode; int phy_mode = efx->phy_mode; + enum reset_type reset_method = RESET_TYPE_INVISIBLE; struct ethtool_cmd ecmd; struct efx_channel *channel; int rc_test = 0, rc_reset = 0, rc; @@ -718,21 +719,21 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, mutex_unlock(&efx->mac_lock); /* free up all consumers of SRAM (including all the queues) */ - efx_reset_down(efx, &ecmd); + efx_reset_down(efx, reset_method, &ecmd); rc = efx_test_chip(efx, tests); if (rc && !rc_test) rc_test = rc; /* reset the chip to recover from the register test */ - rc_reset = falcon_reset_hw(efx, RESET_TYPE_ALL); + rc_reset = falcon_reset_hw(efx, reset_method); /* Ensure that the phy is powered and out of loopback * for the bist and loopback tests */ efx->phy_mode &= ~PHY_MODE_LOW_POWER; efx->loopback_mode = LOOPBACK_NONE; - rc = efx_reset_up(efx, &ecmd, rc_reset == 0); + rc = efx_reset_up(efx, reset_method, &ecmd, rc_reset == 0); if (rc && !rc_reset) rc_reset = rc; diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c index 16b80ac..cb25ae5 100644 --- a/drivers/net/sfc/sfe4001.c +++ b/drivers/net/sfc/sfe4001.c @@ -186,19 +186,22 @@ static int sfn4111t_reset(struct efx_nic *efx) { efx_oword_t reg; - /* GPIO pins are also used for I2C, so block that temporarily */ + /* GPIO 3 and the GPIO register are shared with I2C, so block that */ mutex_lock(&efx->i2c_adap.bus_lock); + /* Pull RST_N (GPIO 2) low then let it up again, setting the + * FLASH_CFG_1 strap (GPIO 3) appropriately. Only change the + * output enables; the output levels should always be 0 (low) + * and we rely on external pull-ups. */ falcon_read(efx, ®, GPIO_CTL_REG_KER); EFX_SET_OWORD_FIELD(reg, GPIO2_OEN, true); - EFX_SET_OWORD_FIELD(reg, GPIO2_OUT, false); falcon_write(efx, ®, GPIO_CTL_REG_KER); msleep(1000); - EFX_SET_OWORD_FIELD(reg, GPIO2_OUT, true); - EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, true); - EFX_SET_OWORD_FIELD(reg, GPIO3_OUT, - !(efx->phy_mode & PHY_MODE_SPECIAL)); + EFX_SET_OWORD_FIELD(reg, GPIO2_OEN, false); + EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, + !!(efx->phy_mode & PHY_MODE_SPECIAL)); falcon_write(efx, ®, GPIO_CTL_REG_KER); + msleep(1); mutex_unlock(&efx->i2c_adap.bus_lock); @@ -232,12 +235,18 @@ static ssize_t set_phy_flash_cfg(struct device *dev, } else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) { err = -EBUSY; } else { + /* Reset the PHY, reconfigure the MAC and enable/disable + * MAC stats accordingly. */ efx->phy_mode = new_mode; + if (new_mode & PHY_MODE_SPECIAL) + efx_stats_disable(efx); if (efx->board_info.type == EFX_BOARD_SFE4001) err = sfe4001_poweron(efx); else err = sfn4111t_reset(efx); efx_reconfigure_port(efx); + if (!(new_mode & PHY_MODE_SPECIAL)) + efx_stats_enable(efx); } rtnl_unlock(); @@ -326,6 +335,11 @@ int sfe4001_init(struct efx_nic *efx) efx->board_info.monitor = sfe4001_check_hw; efx->board_info.fini = sfe4001_fini; + if (efx->phy_mode & PHY_MODE_SPECIAL) { + /* PHY won't generate a 156.25 MHz clock and MAC stats fetch + * will fail. */ + efx_stats_disable(efx); + } rc = sfe4001_poweron(efx); if (rc) goto fail_ioexp; @@ -372,17 +386,25 @@ static void sfn4111t_fini(struct efx_nic *efx) i2c_unregister_device(efx->board_info.hwmon_client); } -static struct i2c_board_info sfn4111t_hwmon_info = { +static struct i2c_board_info sfn4111t_a0_hwmon_info = { I2C_BOARD_INFO("max6647", 0x4e), .irq = -1, }; +static struct i2c_board_info sfn4111t_r5_hwmon_info = { + I2C_BOARD_INFO("max6646", 0x4d), + .irq = -1, +}; + int sfn4111t_init(struct efx_nic *efx) { int rc; efx->board_info.hwmon_client = - i2c_new_device(&efx->i2c_adap, &sfn4111t_hwmon_info); + i2c_new_device(&efx->i2c_adap, + (efx->board_info.minor < 5) ? + &sfn4111t_a0_hwmon_info : + &sfn4111t_r5_hwmon_info); if (!efx->board_info.hwmon_client) return -EIO; @@ -394,8 +416,10 @@ int sfn4111t_init(struct efx_nic *efx) if (rc) goto fail_hwmon; - if (efx->phy_mode & PHY_MODE_SPECIAL) + if (efx->phy_mode & PHY_MODE_SPECIAL) { + efx_stats_disable(efx); sfn4111t_reset(efx); + } return 0; diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index 9ecb77d..f0efd24 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -67,6 +67,8 @@ #define PMA_PMD_EXT_CLK312_WIDTH 1 #define PMA_PMD_EXT_LPOWER_LBN 12 #define PMA_PMD_EXT_LPOWER_WIDTH 1 +#define PMA_PMD_EXT_ROBUST_LBN 14 +#define PMA_PMD_EXT_ROBUST_WIDTH 1 #define PMA_PMD_EXT_SSR_LBN 15 #define PMA_PMD_EXT_SSR_WIDTH 1 @@ -177,35 +179,24 @@ #define C22EXT_STATUS_LINK_LBN 2 #define C22EXT_STATUS_LINK_WIDTH 1 -#define C22EXT_MSTSLV_REG 49162 -#define C22EXT_MSTSLV_1000_HD_LBN 10 -#define C22EXT_MSTSLV_1000_HD_WIDTH 1 -#define C22EXT_MSTSLV_1000_FD_LBN 11 -#define C22EXT_MSTSLV_1000_FD_WIDTH 1 +#define C22EXT_MSTSLV_CTRL 49161 +#define C22EXT_MSTSLV_CTRL_ADV_1000_HD_LBN 8 +#define C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN 9 + +#define C22EXT_MSTSLV_STATUS 49162 +#define C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN 10 +#define C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN 11 /* Time to wait between powering down the LNPGA and turning off the power * rails */ #define LNPGA_PDOWN_WAIT (HZ / 5) -static int crc_error_reset_threshold = 100; -module_param(crc_error_reset_threshold, int, 0644); -MODULE_PARM_DESC(crc_error_reset_threshold, - "Max number of CRC errors before XAUI reset"); - struct tenxpress_phy_data { enum efx_loopback_mode loopback_mode; - atomic_t bad_crc_count; enum efx_phy_mode phy_mode; int bad_lp_tries; }; -void tenxpress_crc_err(struct efx_nic *efx) -{ - struct tenxpress_phy_data *phy_data = efx->phy_data; - if (phy_data != NULL) - atomic_inc(&phy_data->bad_crc_count); -} - static ssize_t show_phy_short_reach(struct device *dev, struct device_attribute *attr, char *buf) { @@ -284,7 +275,9 @@ static int tenxpress_init(struct efx_nic *efx) PMA_PMD_XCONTROL_REG); reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) | (1 << PMA_PMD_EXT_CLK_OUT_LBN) | - (1 << PMA_PMD_EXT_CLK312_LBN)); + (1 << PMA_PMD_EXT_CLK312_LBN) | + (1 << PMA_PMD_EXT_ROBUST_LBN)); + mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, @@ -346,6 +339,7 @@ static int tenxpress_phy_init(struct efx_nic *efx) rc = tenxpress_init(efx); if (rc < 0) goto fail; + mdio_clause45_set_pause(efx); if (efx->phy_type == PHY_TYPE_SFT9001B) { rc = device_create_file(&efx->pci_dev->dev, @@ -376,8 +370,8 @@ static int tenxpress_special_reset(struct efx_nic *efx) /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so * a special software reset can glitch the XGMAC sufficiently for stats - * requests to fail. Since we don't often special_reset, just lock. */ - spin_lock(&efx->stats_lock); + * requests to fail. */ + efx_stats_disable(efx); /* Initiate reset */ reg = mdio_clause45_read(efx, efx->mii.phy_id, @@ -392,17 +386,17 @@ static int tenxpress_special_reset(struct efx_nic *efx) rc = mdio_clause45_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); if (rc < 0) - goto unlock; + goto out; /* Try and reconfigure the device */ rc = tenxpress_init(efx); if (rc < 0) - goto unlock; + goto out; /* Wait for the XGXS state machine to churn */ mdelay(10); -unlock: - spin_unlock(&efx->stats_lock); +out: + efx_stats_enable(efx); return rc; } @@ -520,7 +514,7 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx) { struct tenxpress_phy_data *phy_data = efx->phy_data; struct ethtool_cmd ecmd; - bool phy_mode_change, loop_reset, loop_toggle, loopback; + bool phy_mode_change, loop_reset; if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) { phy_data->phy_mode = efx->phy_mode; @@ -531,12 +525,10 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx) phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL && phy_data->phy_mode != PHY_MODE_NORMAL); - loopback = LOOPBACK_MASK(efx) & efx->phy_op->loopbacks; - loop_toggle = LOOPBACK_CHANGED(phy_data, efx, efx->phy_op->loopbacks); loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) || LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY)); - if (loop_reset || loop_toggle || loopback || phy_mode_change) { + if (loop_reset || phy_mode_change) { int rc; efx->phy_op->get_settings(efx, &ecmd); @@ -551,20 +543,6 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx) falcon_reset_xaui(efx); } - if (efx->phy_type != PHY_TYPE_SFX7101) { - /* Only change autoneg once, on coming out or - * going into loopback */ - if (loop_toggle) - ecmd.autoneg = !loopback; - if (loopback) { - ecmd.duplex = DUPLEX_FULL; - if (efx->loopback_mode == LOOPBACK_GPHY) - ecmd.speed = SPEED_1000; - else - ecmd.speed = SPEED_10000; - } - } - rc = efx->phy_op->set_settings(efx, &ecmd); WARN_ON(rc); } @@ -623,13 +601,6 @@ static void tenxpress_phy_poll(struct efx_nic *efx) if (phy_data->phy_mode != PHY_MODE_NORMAL) return; - - if (EFX_WORKAROUND_10750(efx) && - atomic_read(&phy_data->bad_crc_count) > crc_error_reset_threshold) { - EFX_ERR(efx, "Resetting XAUI due to too many CRC errors\n"); - falcon_reset_xaui(efx); - atomic_set(&phy_data->bad_crc_count, 0); - } } static void tenxpress_phy_fini(struct efx_nic *efx) @@ -772,107 +743,76 @@ reset: return rc; } -static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx) +static void +tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - int phy = efx->mii.phy_id; - u32 lpa = 0; + int phy_id = efx->mii.phy_id; + u32 adv = 0, lpa = 0; int reg; if (efx->phy_type != PHY_TYPE_SFX7101) { - reg = mdio_clause45_read(efx, phy, MDIO_MMD_C22EXT, - C22EXT_MSTSLV_REG); - if (reg & (1 << C22EXT_MSTSLV_1000_HD_LBN)) + reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, + C22EXT_MSTSLV_CTRL); + if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN)) + adv |= ADVERTISED_1000baseT_Full; + reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, + C22EXT_MSTSLV_STATUS); + if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN)) lpa |= ADVERTISED_1000baseT_Half; - if (reg & (1 << C22EXT_MSTSLV_1000_FD_LBN)) + if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN)) lpa |= ADVERTISED_1000baseT_Full; } - reg = mdio_clause45_read(efx, phy, MDIO_MMD_AN, MDIO_AN_10GBT_STATUS); + reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, + MDIO_AN_10GBT_CTRL); + if (reg & (1 << MDIO_AN_10GBT_CTRL_ADV_10G_LBN)) + adv |= ADVERTISED_10000baseT_Full; + reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, + MDIO_AN_10GBT_STATUS); if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN)) lpa |= ADVERTISED_10000baseT_Full; - return lpa; -} -static void sfx7101_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) -{ - mdio_clause45_get_settings_ext(efx, ecmd, ADVERTISED_10000baseT_Full, - tenxpress_get_xnp_lpa(efx)); - ecmd->supported |= SUPPORTED_10000baseT_Full; - ecmd->advertising |= ADVERTISED_10000baseT_Full; + mdio_clause45_get_settings_ext(efx, ecmd, adv, lpa); + + if (efx->phy_type != PHY_TYPE_SFX7101) + ecmd->supported |= (SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full); + + /* In loopback, the PHY automatically brings up the correct interface, + * but doesn't advertise the correct speed. So override it */ + if (efx->loopback_mode == LOOPBACK_GPHY) + ecmd->speed = SPEED_1000; + else if (LOOPBACK_MASK(efx) & efx->phy_op->loopbacks) + ecmd->speed = SPEED_10000; } -static void sft9001_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) +static int tenxpress_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - int phy_id = efx->mii.phy_id; - u32 xnp_adv = 0; - int reg; - - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_SPEED_ENABLE_REG); - if (EFX_WORKAROUND_13204(efx) && (reg & (1 << PMA_PMD_100TX_ADV_LBN))) - xnp_adv |= ADVERTISED_100baseT_Full; - if (reg & (1 << PMA_PMD_1000T_ADV_LBN)) - xnp_adv |= ADVERTISED_1000baseT_Full; - if (reg & (1 << PMA_PMD_10000T_ADV_LBN)) - xnp_adv |= ADVERTISED_10000baseT_Full; - - mdio_clause45_get_settings_ext(efx, ecmd, xnp_adv, - tenxpress_get_xnp_lpa(efx)); - - ecmd->supported |= (SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full); + if (!ecmd->autoneg) + return -EINVAL; - /* Use the vendor defined C22ext register for duplex settings */ - if (ecmd->speed != SPEED_10000 && !ecmd->autoneg) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, - GPHY_XCONTROL_REG); - ecmd->duplex = (reg & (1 << GPHY_DUPLEX_LBN) ? - DUPLEX_FULL : DUPLEX_HALF); - } + return mdio_clause45_set_settings(efx, ecmd); } -static int sft9001_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) +static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising) { - int phy_id = efx->mii.phy_id; - int rc; - - rc = mdio_clause45_set_settings(efx, ecmd); - if (rc) - return rc; - - if (ecmd->speed != SPEED_10000 && !ecmd->autoneg) - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, - GPHY_XCONTROL_REG, GPHY_DUPLEX_LBN, - ecmd->duplex == DUPLEX_FULL); - - return rc; + mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_AN, + MDIO_AN_10GBT_CTRL, + MDIO_AN_10GBT_CTRL_ADV_10G_LBN, + advertising & ADVERTISED_10000baseT_Full); } -static bool sft9001_set_xnp_advertise(struct efx_nic *efx, u32 advertising) +static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising) { - int phy = efx->mii.phy_id; - int reg = mdio_clause45_read(efx, phy, MDIO_MMD_PMAPMD, - PMA_PMD_SPEED_ENABLE_REG); - bool enabled; - - reg &= ~((1 << 2) | (1 << 3)); - if (EFX_WORKAROUND_13204(efx) && - (advertising & ADVERTISED_100baseT_Full)) - reg |= 1 << PMA_PMD_100TX_ADV_LBN; - if (advertising & ADVERTISED_1000baseT_Full) - reg |= 1 << PMA_PMD_1000T_ADV_LBN; - if (advertising & ADVERTISED_10000baseT_Full) - reg |= 1 << PMA_PMD_10000T_ADV_LBN; - mdio_clause45_write(efx, phy, MDIO_MMD_PMAPMD, - PMA_PMD_SPEED_ENABLE_REG, reg); - - enabled = (advertising & - (ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full | - ADVERTISED_10000baseT_Full)); - if (EFX_WORKAROUND_13204(efx)) - enabled |= (advertising & ADVERTISED_100baseT_Full); - return enabled; + int phy_id = efx->mii.phy_id; + + mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, + C22EXT_MSTSLV_CTRL, + C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN, + advertising & ADVERTISED_1000baseT_Full); + mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN, + MDIO_AN_10GBT_CTRL, + MDIO_AN_10GBT_CTRL_ADV_10G_LBN, + advertising & ADVERTISED_10000baseT_Full); } struct efx_phy_operations falcon_sfx7101_phy_ops = { @@ -882,8 +822,9 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = { .poll = tenxpress_phy_poll, .fini = tenxpress_phy_fini, .clear_interrupt = efx_port_dummy_op_void, - .get_settings = sfx7101_get_settings, - .set_settings = mdio_clause45_set_settings, + .get_settings = tenxpress_get_settings, + .set_settings = tenxpress_set_settings, + .set_npage_adv = sfx7101_set_npage_adv, .num_tests = ARRAY_SIZE(sfx7101_test_names), .test_names = sfx7101_test_names, .run_tests = sfx7101_run_tests, @@ -898,9 +839,9 @@ struct efx_phy_operations falcon_sft9001_phy_ops = { .poll = tenxpress_phy_poll, .fini = tenxpress_phy_fini, .clear_interrupt = efx_port_dummy_op_void, - .get_settings = sft9001_get_settings, - .set_settings = sft9001_set_settings, - .set_xnp_advertise = sft9001_set_xnp_advertise, + .get_settings = tenxpress_get_settings, + .set_settings = tenxpress_set_settings, + .set_npage_adv = sft9001_set_npage_adv, .num_tests = ARRAY_SIZE(sft9001_test_names), .test_names = sft9001_test_names, .run_tests = sft9001_run_tests, diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h index 82e03e1..78de68f 100644 --- a/drivers/net/sfc/workarounds.h +++ b/drivers/net/sfc/workarounds.h @@ -18,8 +18,8 @@ #define EFX_WORKAROUND_ALWAYS(efx) 1 #define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1) #define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx) -#define EFX_WORKAROUND_SFX7101(efx) ((efx)->phy_type == PHY_TYPE_SFX7101) -#define EFX_WORKAROUND_SFT9001A(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A) +#define EFX_WORKAROUND_SFT9001(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A || \ + (efx)->phy_type == PHY_TYPE_SFT9001B) /* XAUI resets if link not detected */ #define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS @@ -29,8 +29,6 @@ #define EFX_WORKAROUND_7884 EFX_WORKAROUND_10G /* TX pkt parser problem with <= 16 byte TXes */ #define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS -/* Low rate CRC errors require XAUI reset */ -#define EFX_WORKAROUND_10750 EFX_WORKAROUND_SFX7101 /* TX_EV_PKT_ERR can be caused by a dangling TX descriptor * or a PCIe error (bug 11028) */ #define EFX_WORKAROUND_10727 EFX_WORKAROUND_ALWAYS @@ -55,8 +53,8 @@ #define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A /* Need to send XNP pages for 100BaseT */ -#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001A -/* Need to keep AN enabled */ -#define EFX_WORKAROUND_13963 EFX_WORKAROUND_SFT9001A +#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001 +/* Don't restart AN in near-side loopback */ +#define EFX_WORKAROUND_15195 EFX_WORKAROUND_SFT9001 #endif /* EFX_WORKAROUNDS_H */ diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 3668e81e..994703c 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1403,9 +1403,6 @@ static int sky2_up(struct net_device *dev) } - if (netif_msg_ifup(sky2)) - printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); - netif_carrier_off(dev); /* must be power of 2 */ @@ -1484,6 +1481,9 @@ static int sky2_up(struct net_device *dev) sky2_write32(hw, B0_IMSK, imask); sky2_set_multicast(dev); + + if (netif_msg_ifup(sky2)) + printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); return 0; err_out: diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index bf3aa2a..223cde0 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -220,9 +220,9 @@ static void smc911x_reset(struct net_device *dev) /* make sure EEPROM has finished loading before setting GPIO_CFG */ timeout=1000; - while ( timeout-- && (SMC_GET_E2P_CMD(lp) & E2P_CMD_EPC_BUSY_)) { + while (--timeout && (SMC_GET_E2P_CMD(lp) & E2P_CMD_EPC_BUSY_)) udelay(10); - } + if (timeout == 0){ PRINTK("%s: smc911x_reset timeout waiting for EEPROM busy\n", dev->name); return; diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c index d801900..a1e4b38 100644 --- a/drivers/net/smsc9420.c +++ b/drivers/net/smsc9420.c @@ -498,7 +498,7 @@ static void smsc9420_check_mac_address(struct net_device *dev) static void smsc9420_stop_tx(struct smsc9420_pdata *pd) { u32 dmac_control, mac_cr, dma_intr_ena; - int timeOut = 1000; + int timeout = 1000; /* disable TX DMAC */ dmac_control = smsc9420_reg_read(pd, DMAC_CONTROL); @@ -506,13 +506,13 @@ static void smsc9420_stop_tx(struct smsc9420_pdata *pd) smsc9420_reg_write(pd, DMAC_CONTROL, dmac_control); /* Wait max 10ms for transmit process to stop */ - while (timeOut--) { + while (--timeout) { if (smsc9420_reg_read(pd, DMAC_STATUS) & DMAC_STS_TS_) break; udelay(10); } - if (!timeOut) + if (!timeout) smsc_warn(IFDOWN, "TX DMAC failed to stop"); /* ACK Tx DMAC stop bit */ @@ -596,7 +596,7 @@ static void smsc9420_free_rx_ring(struct smsc9420_pdata *pd) static void smsc9420_stop_rx(struct smsc9420_pdata *pd) { - int timeOut = 1000; + int timeout = 1000; u32 mac_cr, dmac_control, dma_intr_ena; /* mask RX DMAC interrupts */ @@ -617,13 +617,13 @@ static void smsc9420_stop_rx(struct smsc9420_pdata *pd) smsc9420_pci_flush_write(pd); /* wait up to 10ms for receive to stop */ - while (timeOut--) { + while (--timeout) { if (smsc9420_reg_read(pd, DMAC_STATUS) & DMAC_STS_RS_) break; udelay(10); } - if (!timeOut) + if (!timeout) smsc_warn(IFDOWN, "RX DMAC did not stop! timeout."); /* ACK the Rx DMAC stop bit */ diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 86c765d..b17efa9 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -148,7 +148,7 @@ static u16 __phy_read(struct gem *gp, int phy_addr, int reg) cmd |= (MIF_FRAME_TAMSB); writel(cmd, gp->regs + MIF_FRAME); - while (limit--) { + while (--limit) { cmd = readl(gp->regs + MIF_FRAME); if (cmd & MIF_FRAME_TALSB) break; diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c index 61843fd..78f8cee 100644 --- a/drivers/net/sungem_phy.c +++ b/drivers/net/sungem_phy.c @@ -79,7 +79,7 @@ static int reset_one_mii_phy(struct mii_phy* phy, int phy_id) udelay(100); - while (limit--) { + while (--limit) { val = __phy_read(phy, phy_id, MII_BMCR); if ((val & BMCR_RESET) == 0) break; diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 6e8f377..fe0c3f2 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -227,7 +227,7 @@ static int qe_init(struct sunqe *qep, int from_irq) if (!(sbus_readb(mregs + MREGS_PHYCONFIG) & MREGS_PHYCONFIG_LTESTDIS)) { int tries = 50; - while (tries--) { + while (--tries) { u8 tmp; mdelay(5); diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c index 75461db..a9fd2b2 100644 --- a/drivers/net/tsi108_eth.c +++ b/drivers/net/tsi108_eth.c @@ -1237,7 +1237,7 @@ static void tsi108_init_phy(struct net_device *dev) spin_lock_irqsave(&phy_lock, flags); tsi108_write_mii(data, MII_BMCR, BMCR_RESET); - while (i--){ + while (--i) { if(!(tsi108_read_mii(data, MII_BMCR) & BMCR_RESET)) break; udelay(10); diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index d5d53b6..0bf2114 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -392,7 +392,7 @@ static void de_rx (struct de_private *de) unsigned drop = 0; int rc; - while (rx_work--) { + while (--rx_work) { u32 status, len; dma_addr_t mapping; struct sk_buff *skb, *copy_skb; diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 0d0fa91..fe98aca 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -455,6 +455,7 @@ static const struct usb_device_id hso_ids[] = { {icon321_port_device(0x0af0, 0xd033)}, /* Icon-322 */ {USB_DEVICE(0x0af0, 0x7301)}, /* GE40x */ {USB_DEVICE(0x0af0, 0x7361)}, /* GE40x */ + {USB_DEVICE(0x0af0, 0x7381)}, /* GE40x */ {USB_DEVICE(0x0af0, 0x7401)}, /* GI 0401 */ {USB_DEVICE(0x0af0, 0x7501)}, /* GTM 382 */ {USB_DEVICE(0x0af0, 0x7601)}, /* GE40x */ @@ -462,7 +463,8 @@ static const struct usb_device_id hso_ids[] = { {USB_DEVICE(0x0af0, 0x7801)}, {USB_DEVICE(0x0af0, 0x7901)}, {USB_DEVICE(0x0af0, 0x7361)}, - {icon321_port_device(0x0af0, 0xd051)}, + {USB_DEVICE(0x0af0, 0xd057)}, + {USB_DEVICE(0x0af0, 0xd055)}, {} }; MODULE_DEVICE_TABLE(usb, hso_ids); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b35c881..c01ea48d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -4042,6 +4042,7 @@ static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) priv->is_open = 1; } + pci_save_state(pdev); pci_set_power_state(pdev, PCI_D3hot); return 0; @@ -4052,6 +4053,7 @@ static int iwl_pci_resume(struct pci_dev *pdev) struct iwl_priv *priv = pci_get_drvdata(pdev); pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); if (priv->is_open) iwl_mac_start(priv->hw); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 412f66b..70a8b21 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -480,6 +480,9 @@ void iwl_clear_stations_table(struct iwl_priv *priv) priv->num_stations = 0; memset(priv->stations, 0, sizeof(priv->stations)); + /* clean ucode key table bit map */ + priv->ucode_key_table = 0; + spin_unlock_irqrestore(&priv->sta_lock, flags); } EXPORT_SYMBOL(iwl_clear_stations_table); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 95d0198..5b44d32 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -8143,6 +8143,7 @@ static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state) priv->is_open = 1; } + pci_save_state(pdev); pci_set_power_state(pdev, PCI_D3hot); return 0; @@ -8153,6 +8154,7 @@ static int iwl3945_pci_resume(struct pci_dev *pdev) struct iwl3945_priv *priv = pci_get_drvdata(pdev); pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); if (priv->is_open) iwl3945_mac_start(priv->hw); diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index e31fb91..2aa117c 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile @@ -5,11 +5,15 @@ obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o + +# pciehp should be linked before acpiphp in order to allow the native driver +# to attempt to bind first. We can then fall back to generic support. + +obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o -obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index b0e7de9..d8649e1 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c @@ -195,13 +195,13 @@ static void remove_slot_worker(struct work_struct *work) * Tries hard not to re-enable already existing devices; * also handles scanning of subfunctions. */ -static void pci_rescan_slot(struct pci_dev *temp) +static int pci_rescan_slot(struct pci_dev *temp) { struct pci_bus *bus = temp->bus; struct pci_dev *dev; int func; - int retval; u8 hdr_type; + int count = 0; if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { temp->hdr_type = hdr_type & 0x7f; @@ -213,17 +213,12 @@ static void pci_rescan_slot(struct pci_dev *temp) dbg("New device on %s function %x:%x\n", bus->name, temp->devfn >> 3, temp->devfn & 7); - retval = pci_bus_add_device(dev); - if (retval) - dev_err(&dev->dev, "error adding " - "device, continuing.\n"); - else - add_slot(dev); + count++; } } /* multifunction device? */ if (!(hdr_type & 0x80)) - return; + return count; /* continue scanning for other functions */ for (func = 1, temp->devfn++; func < 8; func++, temp->devfn++) { @@ -239,16 +234,13 @@ static void pci_rescan_slot(struct pci_dev *temp) dbg("New device on %s function %x:%x\n", bus->name, temp->devfn >> 3, temp->devfn & 7); - retval = pci_bus_add_device(dev); - if (retval) - dev_err(&dev->dev, "error adding " - "device, continuing.\n"); - else - add_slot(dev); + count++; } } } } + + return count; } @@ -262,6 +254,8 @@ static void pci_rescan_bus(const struct pci_bus *bus) { unsigned int devfn; struct pci_dev *dev; + int retval; + int found = 0; dev = alloc_pci_dev(); if (!dev) return; @@ -270,7 +264,23 @@ static void pci_rescan_bus(const struct pci_bus *bus) dev->sysdata = bus->sysdata; for (devfn = 0; devfn < 0x100; devfn += 8) { dev->devfn = devfn; - pci_rescan_slot(dev); + found += pci_rescan_slot(dev); + } + + if (found) { + pci_bus_assign_resources(bus); + list_for_each_entry(dev, &bus->devices, bus_list) { + /* Skip already-added devices */ + if (dev->is_added) + continue; + retval = pci_bus_add_device(dev); + if (retval) + dev_err(&dev->dev, + "Error adding device, continuing\n"); + else + add_slot(dev); + } + pci_bus_add_devices(bus); } kfree(dev); } diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 896a15d..44f15ff 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -103,6 +103,16 @@ static void msix_set_enable(struct pci_dev *dev, int enable) } } +/* + * Essentially, this is ((1 << (1 << x)) - 1), but without the + * undefinedness of a << 32. + */ +static inline __attribute_const__ u32 msi_mask(unsigned x) +{ + static const u32 mask[] = { 1, 2, 4, 0xf, 0xff, 0xffff, 0xffffffff }; + return mask[x]; +} + static void msix_flush_writes(struct irq_desc *desc) { struct msi_desc *entry; @@ -407,8 +417,7 @@ static int msi_capability_init(struct pci_dev *dev) /* All MSIs are unmasked by default, Mask them all */ pci_read_config_dword(dev, base, &maskbits); - temp = (1 << multi_msi_capable(control)); - temp = ((temp - 1) & ~temp); + temp = msi_mask((control & PCI_MSI_FLAGS_QMASK) >> 1); maskbits |= temp; pci_write_config_dword(dev, base, maskbits); entry->msi_attrib.maskbits_mask = temp; diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 9de07b7..93eac14 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -355,6 +355,8 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state) int i = 0; if (drv && drv->suspend) { + pci_power_t prev = pci_dev->current_state; + pci_dev->state_saved = false; i = drv->suspend(pci_dev, state); @@ -365,8 +367,13 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state) if (pci_dev->state_saved) goto Fixup; - if (WARN_ON_ONCE(pci_dev->current_state != PCI_D0)) + if (pci_dev->current_state != PCI_D0 + && pci_dev->current_state != PCI_UNKNOWN) { + WARN_ONCE(pci_dev->current_state != prev, + "PCI PM: Device state not saved by %pF\n", + drv->suspend); goto Fixup; + } } pci_save_state(pci_dev); @@ -419,38 +426,24 @@ static int pci_legacy_resume(struct device *dev) static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev) { pci_restore_standard_config(pci_dev); + pci_dev->state_saved = false; pci_fixup_device(pci_fixup_resume_early, pci_dev); } -static int pci_pm_default_resume(struct pci_dev *pci_dev) +static void pci_pm_default_resume(struct pci_dev *pci_dev) { pci_fixup_device(pci_fixup_resume, pci_dev); if (!pci_is_bridge(pci_dev)) pci_enable_wake(pci_dev, PCI_D0, false); - - return pci_pm_reenable_device(pci_dev); -} - -static void pci_pm_default_suspend_generic(struct pci_dev *pci_dev) -{ - /* If device is enabled at this point, disable it */ - pci_disable_enabled_device(pci_dev); - /* - * Save state with interrupts enabled, because in principle the bus the - * device is on may be put into a low power state after this code runs. - */ - pci_save_state(pci_dev); } static void pci_pm_default_suspend(struct pci_dev *pci_dev) { - pci_pm_default_suspend_generic(pci_dev); - + /* Disable non-bridge devices without PM support */ if (!pci_is_bridge(pci_dev)) - pci_prepare_to_sleep(pci_dev); - - pci_fixup_device(pci_fixup_suspend, pci_dev); + pci_disable_enabled_device(pci_dev); + pci_save_state(pci_dev); } static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev) @@ -495,21 +488,49 @@ static void pci_pm_complete(struct device *dev) static int pci_pm_suspend(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); - struct device_driver *drv = dev->driver; - int error = 0; + struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; if (pci_has_legacy_pm_support(pci_dev)) return pci_legacy_suspend(dev, PMSG_SUSPEND); - if (drv && drv->pm && drv->pm->suspend) { - error = drv->pm->suspend(dev); - suspend_report_result(drv->pm->suspend, error); + if (!pm) { + pci_pm_default_suspend(pci_dev); + goto Fixup; } - if (!error) - pci_pm_default_suspend(pci_dev); + pci_dev->state_saved = false; - return error; + if (pm->suspend) { + pci_power_t prev = pci_dev->current_state; + int error; + + error = pm->suspend(dev); + suspend_report_result(pm->suspend, error); + if (error) + return error; + + if (pci_dev->state_saved) + goto Fixup; + + if (pci_dev->current_state != PCI_D0 + && pci_dev->current_state != PCI_UNKNOWN) { + WARN_ONCE(pci_dev->current_state != prev, + "PCI PM: State of device not saved by %pF\n", + pm->suspend); + goto Fixup; + } + } + + if (!pci_dev->state_saved) { + pci_save_state(pci_dev); + if (!pci_is_bridge(pci_dev)) + pci_prepare_to_sleep(pci_dev); + } + + Fixup: + pci_fixup_device(pci_fixup_suspend, pci_dev); + + return 0; } static int pci_pm_suspend_noirq(struct device *dev) @@ -552,18 +573,29 @@ static int pci_pm_resume_noirq(struct device *dev) static int pci_pm_resume(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); - struct device_driver *drv = dev->driver; + struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; int error = 0; + /* + * This is necessary for the suspend error path in which resume is + * called without restoring the standard config registers of the device. + */ + if (pci_dev->state_saved) + pci_restore_standard_config(pci_dev); + if (pci_has_legacy_pm_support(pci_dev)) return pci_legacy_resume(dev); - error = pci_pm_default_resume(pci_dev); + pci_pm_default_resume(pci_dev); - if (!error && drv && drv->pm && drv->pm->resume) - error = drv->pm->resume(dev); + if (pm) { + if (pm->resume) + error = pm->resume(dev); + } else { + pci_pm_reenable_device(pci_dev); + } - return error; + return 0; } #else /* !CONFIG_SUSPEND */ @@ -580,21 +612,31 @@ static int pci_pm_resume(struct device *dev) static int pci_pm_freeze(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); - struct device_driver *drv = dev->driver; - int error = 0; + struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; if (pci_has_legacy_pm_support(pci_dev)) return pci_legacy_suspend(dev, PMSG_FREEZE); - if (drv && drv->pm && drv->pm->freeze) { - error = drv->pm->freeze(dev); - suspend_report_result(drv->pm->freeze, error); + if (!pm) { + pci_pm_default_suspend(pci_dev); + return 0; + } + + pci_dev->state_saved = false; + + if (pm->freeze) { + int error; + + error = pm->freeze(dev); + suspend_report_result(pm->freeze, error); + if (error) + return error; } - if (!error) - pci_pm_default_suspend_generic(pci_dev); + if (!pci_dev->state_saved) + pci_save_state(pci_dev); - return error; + return 0; } static int pci_pm_freeze_noirq(struct device *dev) @@ -637,16 +679,18 @@ static int pci_pm_thaw_noirq(struct device *dev) static int pci_pm_thaw(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); - struct device_driver *drv = dev->driver; + struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; int error = 0; if (pci_has_legacy_pm_support(pci_dev)) return pci_legacy_resume(dev); - pci_pm_reenable_device(pci_dev); - - if (drv && drv->pm && drv->pm->thaw) - error = drv->pm->thaw(dev); + if (pm) { + if (pm->thaw) + error = pm->thaw(dev); + } else { + pci_pm_reenable_device(pci_dev); + } return error; } @@ -654,19 +698,29 @@ static int pci_pm_thaw(struct device *dev) static int pci_pm_poweroff(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); - struct device_driver *drv = dev->driver; + struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; int error = 0; if (pci_has_legacy_pm_support(pci_dev)) return pci_legacy_suspend(dev, PMSG_HIBERNATE); - if (drv && drv->pm && drv->pm->poweroff) { - error = drv->pm->poweroff(dev); - suspend_report_result(drv->pm->poweroff, error); + if (!pm) { + pci_pm_default_suspend(pci_dev); + goto Fixup; } - if (!error) - pci_pm_default_suspend(pci_dev); + pci_dev->state_saved = false; + + if (pm->poweroff) { + error = pm->poweroff(dev); + suspend_report_result(pm->poweroff, error); + } + + if (!pci_dev->state_saved && !pci_is_bridge(pci_dev)) + pci_prepare_to_sleep(pci_dev); + + Fixup: + pci_fixup_device(pci_fixup_suspend, pci_dev); return error; } @@ -707,16 +761,27 @@ static int pci_pm_restore_noirq(struct device *dev) static int pci_pm_restore(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); - struct device_driver *drv = dev->driver; + struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; int error = 0; + /* + * This is necessary for the hibernation error path in which restore is + * called without restoring the standard config registers of the device. + */ + if (pci_dev->state_saved) + pci_restore_standard_config(pci_dev); + if (pci_has_legacy_pm_support(pci_dev)) return pci_legacy_resume(dev); - error = pci_pm_default_resume(pci_dev); + pci_pm_default_resume(pci_dev); - if (!error && drv && drv->pm && drv->pm->restore) - error = drv->pm->restore(dev); + if (pm) { + if (pm->restore) + error = pm->restore(dev); + } else { + pci_pm_reenable_device(pci_dev); + } return error; } diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index db7ec14..dfc4e0d 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -768,8 +768,8 @@ pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr, return -EINVAL; rom = pci_map_rom(pdev, &size); /* size starts out as PCI window size */ - if (!rom) - return 0; + if (!rom || !size) + return -EIO; if (off >= size) count = 0; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 17bd932..e3efe6b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1393,35 +1393,35 @@ int pci_restore_standard_config(struct pci_dev *dev) pci_power_t prev_state; int error; - pci_restore_state(dev); pci_update_current_state(dev, PCI_D0); prev_state = dev->current_state; if (prev_state == PCI_D0) - return 0; + goto Restore; error = pci_raw_set_power_state(dev, PCI_D0, false); if (error) return error; - if (pci_is_bridge(dev)) { - if (prev_state > PCI_D1) - mdelay(PCI_PM_BUS_WAIT); - } else { - switch(prev_state) { - case PCI_D3cold: - case PCI_D3hot: - mdelay(pci_pm_d3_delay); - break; - case PCI_D2: - udelay(PCI_PM_D2_DELAY); - break; - } + /* + * This assumes that we won't get a bus in B2 or B3 from the BIOS, but + * we've made this assumption forever and it appears to be universally + * satisfied. + */ + switch(prev_state) { + case PCI_D3cold: + case PCI_D3hot: + mdelay(pci_pm_d3_delay); + break; + case PCI_D2: + udelay(PCI_PM_D2_DELAY); + break; } - dev->current_state = PCI_D0; + pci_update_current_state(dev, PCI_D0); - return 0; + Restore: + return dev->state_saved ? pci_restore_state(dev) : 0; } /** diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 586b6f7..b0367f1 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -718,9 +718,9 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) /* * All PCIe functions are in one slot, remove one function will remove - * the the whole slot, so just wait + * the whole slot, so just wait until we are the last function left. */ - if (!list_empty(&parent->subordinate->devices)) + if (!list_is_last(&pdev->bus_list, &parent->subordinate->devices)) goto out; /* All functions are removed, so just disable ASPM for the link */ diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 99a914a..f9b874e 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -55,25 +55,13 @@ static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state) } -static int pcie_portdrv_suspend_late(struct pci_dev *dev, pm_message_t state) -{ - return pci_save_state(dev); -} - -static int pcie_portdrv_resume_early(struct pci_dev *dev) -{ - return pci_restore_state(dev); -} - static int pcie_portdrv_resume(struct pci_dev *dev) { - pcie_portdrv_restore_config(dev); + pci_set_master(dev); return pcie_port_device_resume(dev); } #else #define pcie_portdrv_suspend NULL -#define pcie_portdrv_suspend_late NULL -#define pcie_portdrv_resume_early NULL #define pcie_portdrv_resume NULL #endif @@ -292,8 +280,6 @@ static struct pci_driver pcie_portdriver = { .remove = pcie_portdrv_remove, .suspend = pcie_portdrv_suspend, - .suspend_late = pcie_portdrv_suspend_late, - .resume_early = pcie_portdrv_resume_early, .resume = pcie_portdrv_resume, .err_handler = &pcie_portdrv_err_handler, diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index 132a781..29cbe47 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c @@ -63,7 +63,7 @@ void pci_disable_rom(struct pci_dev *pdev) * The PCI window size could be much larger than the * actual image size. */ -size_t pci_get_rom_size(void __iomem *rom, size_t size) +size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size) { void __iomem *image; int last_image; @@ -72,8 +72,10 @@ size_t pci_get_rom_size(void __iomem *rom, size_t size) do { void __iomem *pds; /* Standard PCI ROMs start out with these bytes 55 AA */ - if (readb(image) != 0x55) + if (readb(image) != 0x55) { + dev_err(&pdev->dev, "Invalid ROM contents\n"); break; + } if (readb(image + 1) != 0xAA) break; /* get the PCI data structure and check its signature */ @@ -159,7 +161,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) * size is much larger than the actual size of the ROM. * True size is important if the ROM is going to be copied. */ - *size = pci_get_rom_size(rom, *size); + *size = pci_get_rom_size(pdev, rom, *size); return rom; } diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 1a266d4..9436311 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -42,6 +42,7 @@ config ASUS_LAPTOP depends on LEDS_CLASS depends on NEW_LEDS depends on BACKLIGHT_CLASS_DEVICE + depends on INPUT ---help--- This is the new Linux driver for Asus laptops. It may also support some MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 8fb8b35..56af6cf 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -46,6 +46,7 @@ #include <acpi/acpi_drivers.h> #include <acpi/acpi_bus.h> #include <asm/uaccess.h> +#include <linux/input.h> #define ASUS_LAPTOP_VERSION "0.42" @@ -181,6 +182,8 @@ struct asus_hotk { u8 light_level; //light sensor level u8 light_switch; //light sensor switch value u16 event_count[128]; //count for each event TODO make this better + struct input_dev *inputdev; + u16 *keycode_map; }; /* @@ -250,6 +253,37 @@ ASUS_LED(rled, "record"); ASUS_LED(pled, "phone"); ASUS_LED(gled, "gaming"); +struct key_entry { + char type; + u8 code; + u16 keycode; +}; + +enum { KE_KEY, KE_END }; + +static struct key_entry asus_keymap[] = { + {KE_KEY, 0x30, KEY_VOLUMEUP}, + {KE_KEY, 0x31, KEY_VOLUMEDOWN}, + {KE_KEY, 0x32, KEY_MUTE}, + {KE_KEY, 0x33, KEY_SWITCHVIDEOMODE}, + {KE_KEY, 0x34, KEY_SWITCHVIDEOMODE}, + {KE_KEY, 0x40, KEY_PREVIOUSSONG}, + {KE_KEY, 0x41, KEY_NEXTSONG}, + {KE_KEY, 0x43, KEY_STOP}, + {KE_KEY, 0x45, KEY_PLAYPAUSE}, + {KE_KEY, 0x50, KEY_EMAIL}, + {KE_KEY, 0x51, KEY_WWW}, + {KE_KEY, 0x5C, BTN_EXTRA}, /* Performance */ + {KE_KEY, 0x5D, KEY_WLAN}, + {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE}, + {KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */ + {KE_KEY, 0x82, KEY_CAMERA}, + {KE_KEY, 0x8A, KEY_TV}, + {KE_KEY, 0x95, KEY_MEDIA}, + {KE_KEY, 0x99, KEY_PHONE}, + {KE_END, 0}, +}; + /* * This function evaluates an ACPI method, given an int as parameter, the * method is searched within the scope of the handle, can be NULL. The output @@ -720,8 +754,68 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr, return store_status(buf, count, NULL, GPS_ON); } +/* + * Hotkey functions + */ +static struct key_entry *asus_get_entry_by_scancode(int code) +{ + struct key_entry *key; + + for (key = asus_keymap; key->type != KE_END; key++) + if (code == key->code) + return key; + + return NULL; +} + +static struct key_entry *asus_get_entry_by_keycode(int code) +{ + struct key_entry *key; + + for (key = asus_keymap; key->type != KE_END; key++) + if (code == key->keycode && key->type == KE_KEY) + return key; + + return NULL; +} + +static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode) +{ + struct key_entry *key = asus_get_entry_by_scancode(scancode); + + if (key && key->type == KE_KEY) { + *keycode = key->keycode; + return 0; + } + + return -EINVAL; +} + +static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) +{ + struct key_entry *key; + int old_keycode; + + if (keycode < 0 || keycode > KEY_MAX) + return -EINVAL; + + key = asus_get_entry_by_scancode(scancode); + if (key && key->type == KE_KEY) { + old_keycode = key->keycode; + key->keycode = keycode; + set_bit(keycode, dev->keybit); + if (!asus_get_entry_by_keycode(old_keycode)) + clear_bit(old_keycode, dev->keybit); + return 0; + } + + return -EINVAL; +} + static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) { + static struct key_entry *key; + /* TODO Find a better way to handle events count. */ if (!hotk) return; @@ -738,10 +832,24 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) lcd_blank(FB_BLANK_POWERDOWN); } - acpi_bus_generate_proc_event(hotk->device, event, - hotk->event_count[event % 128]++); - - return; + acpi_bus_generate_netlink_event(hotk->device->pnp.device_class, + dev_name(&hotk->device->dev), event, + hotk->event_count[event % 128]++); + + if (hotk->inputdev) { + key = asus_get_entry_by_scancode(event); + if (!key) + return ; + + switch (key->type) { + case KE_KEY: + input_report_key(hotk->inputdev, key->keycode, 1); + input_sync(hotk->inputdev); + input_report_key(hotk->inputdev, key->keycode, 0); + input_sync(hotk->inputdev); + break; + } + } } #define ASUS_CREATE_DEVICE_ATTR(_name) \ @@ -959,6 +1067,38 @@ static int asus_hotk_get_info(void) return AE_OK; } +static int asus_input_init(void) +{ + const struct key_entry *key; + int result; + + hotk->inputdev = input_allocate_device(); + if (!hotk->inputdev) { + printk(ASUS_INFO "Unable to allocate input device\n"); + return 0; + } + hotk->inputdev->name = "Asus Laptop extra buttons"; + hotk->inputdev->phys = ASUS_HOTK_FILE "/input0"; + hotk->inputdev->id.bustype = BUS_HOST; + hotk->inputdev->getkeycode = asus_getkeycode; + hotk->inputdev->setkeycode = asus_setkeycode; + + for (key = asus_keymap; key->type != KE_END; key++) { + switch (key->type) { + case KE_KEY: + set_bit(EV_KEY, hotk->inputdev->evbit); + set_bit(key->keycode, hotk->inputdev->keybit); + break; + } + } + result = input_register_device(hotk->inputdev); + if (result) { + printk(ASUS_INFO "Unable to register input device\n"); + input_free_device(hotk->inputdev); + } + return result; +} + static int asus_hotk_check(void) { int result = 0; @@ -1044,7 +1184,7 @@ static int asus_hotk_add(struct acpi_device *device) /* GPS is on by default */ write_status(NULL, 1, GPS_ON); - end: +end: if (result) { kfree(hotk->name); kfree(hotk); @@ -1091,10 +1231,17 @@ static void asus_led_exit(void) ASUS_LED_UNREGISTER(gled); } +static void asus_input_exit(void) +{ + if (hotk->inputdev) + input_unregister_device(hotk->inputdev); +} + static void __exit asus_laptop_exit(void) { asus_backlight_exit(); asus_led_exit(); + asus_input_exit(); acpi_bus_unregister_driver(&asus_hotk_driver); sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group); @@ -1216,6 +1363,10 @@ static int __init asus_laptop_init(void) printk(ASUS_INFO "Brightness ignored, must be controlled by " "ACPI video driver\n"); + result = asus_input_init(); + if (result) + goto fail_input; + result = asus_led_init(dev); if (result) goto fail_led; @@ -1242,22 +1393,25 @@ static int __init asus_laptop_init(void) return 0; - fail_sysfs: +fail_sysfs: platform_device_del(asuspf_device); - fail_platform_device2: +fail_platform_device2: platform_device_put(asuspf_device); - fail_platform_device1: +fail_platform_device1: platform_driver_unregister(&asuspf_driver); - fail_platform_driver: +fail_platform_driver: asus_led_exit(); - fail_led: +fail_led: + asus_input_exit(); + +fail_input: asus_backlight_exit(); - fail_backlight: +fail_backlight: return result; } diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c index 1e74988..d63f26e 100644 --- a/drivers/platform/x86/asus_acpi.c +++ b/drivers/platform/x86/asus_acpi.c @@ -143,6 +143,7 @@ struct asus_hotk { S1300N, S5200N*/ A4S, /* Z81sp */ F3Sa, /* (Centrino) */ + R1F, END_MODEL } model; /* Models currently supported */ u16 event_count[128]; /* Count for each event TODO make this better */ @@ -420,7 +421,18 @@ static struct model_data model_conf[END_MODEL] = { .display_get = "\\ADVG", .display_set = "SDSP", }, - + { + .name = "R1F", + .mt_bt_switch = "BLED", + .mt_mled = "MLED", + .mt_wled = "WLED", + .mt_lcd_switch = "\\Q10", + .lcd_status = "\\GP06", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\INFB" + } }; /* procdir we use */ @@ -1165,6 +1177,8 @@ static int asus_model_match(char *model) return W3V; else if (strncmp(model, "W5A", 3) == 0) return W5A; + else if (strncmp(model, "R1F", 3) == 0) + return R1F; else if (strncmp(model, "A4S", 3) == 0) return A4S; else if (strncmp(model, "F3Sa", 4) == 0) diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 9d93cb9..786ed86 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -30,6 +30,7 @@ #include <linux/uaccess.h> #include <linux/input.h> #include <linux/rfkill.h> +#include <linux/pci.h> #define EEEPC_LAPTOP_VERSION "0.1" @@ -161,6 +162,10 @@ static struct key_entry eeepc_keymap[] = { {KE_KEY, 0x13, KEY_MUTE }, {KE_KEY, 0x14, KEY_VOLUMEDOWN }, {KE_KEY, 0x15, KEY_VOLUMEUP }, + {KE_KEY, 0x1a, KEY_COFFEE }, + {KE_KEY, 0x1b, KEY_ZOOM }, + {KE_KEY, 0x1c, KEY_PROG2 }, + {KE_KEY, 0x1d, KEY_PROG3 }, {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, @@ -510,7 +515,43 @@ static int eeepc_hotk_check(void) static void notify_brn(void) { struct backlight_device *bd = eeepc_backlight_device; - bd->props.brightness = read_brightness(bd); + if (bd) + bd->props.brightness = read_brightness(bd); +} + +static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) +{ + struct pci_dev *dev; + struct pci_bus *bus = pci_find_bus(0, 1); + + if (event != ACPI_NOTIFY_BUS_CHECK) + return; + + if (!bus) { + printk(EEEPC_WARNING "Unable to find PCI bus 1?\n"); + return; + } + + if (get_acpi(CM_ASL_WLAN) == 1) { + dev = pci_get_slot(bus, 0); + if (dev) { + /* Device already present */ + pci_dev_put(dev); + return; + } + dev = pci_scan_single_device(bus, 0); + if (dev) { + pci_bus_assign_resources(bus); + if (pci_bus_add_device(dev)) + printk(EEEPC_ERR "Unable to hotplug wifi\n"); + } + } else { + dev = pci_get_slot(bus, 0); + if (dev) { + pci_remove_bus_device(dev); + pci_dev_put(dev); + } + } } static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) @@ -520,8 +561,9 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) return; if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) notify_brn(); - acpi_bus_generate_proc_event(ehotk->device, event, - ehotk->event_count[event % 128]++); + acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class, + dev_name(&ehotk->device->dev), event, + ehotk->event_count[event % 128]++); if (ehotk->inputdev) { key = eepc_get_entry_by_scancode(event); if (key) { @@ -539,6 +581,45 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) } } +static int eeepc_register_rfkill_notifier(char *node) +{ + acpi_status status = AE_OK; + acpi_handle handle; + + status = acpi_get_handle(NULL, node, &handle); + + if (ACPI_SUCCESS(status)) { + status = acpi_install_notify_handler(handle, + ACPI_SYSTEM_NOTIFY, + eeepc_rfkill_notify, + NULL); + if (ACPI_FAILURE(status)) + printk(EEEPC_WARNING + "Failed to register notify on %s\n", node); + } else + return -ENODEV; + + return 0; +} + +static void eeepc_unregister_rfkill_notifier(char *node) +{ + acpi_status status = AE_OK; + acpi_handle handle; + + status = acpi_get_handle(NULL, node, &handle); + + if (ACPI_SUCCESS(status)) { + status = acpi_remove_notify_handler(handle, + ACPI_SYSTEM_NOTIFY, + eeepc_rfkill_notify); + if (ACPI_FAILURE(status)) + printk(EEEPC_ERR + "Error removing rfkill notify handler %s\n", + node); + } +} + static int eeepc_hotk_add(struct acpi_device *device) { acpi_status status = AE_OK; @@ -558,7 +639,7 @@ static int eeepc_hotk_add(struct acpi_device *device) ehotk->device = device; result = eeepc_hotk_check(); if (result) - goto end; + goto ehotk_fail; status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, eeepc_hotk_notify, ehotk); if (ACPI_FAILURE(status)) @@ -569,18 +650,25 @@ static int eeepc_hotk_add(struct acpi_device *device) RFKILL_TYPE_WLAN); if (!ehotk->eeepc_wlan_rfkill) - goto end; + goto wlan_fail; ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state; - if (get_acpi(CM_ASL_WLAN) == 1) + if (get_acpi(CM_ASL_WLAN) == 1) { ehotk->eeepc_wlan_rfkill->state = RFKILL_STATE_UNBLOCKED; - else + rfkill_set_default(RFKILL_TYPE_WLAN, + RFKILL_STATE_UNBLOCKED); + } else { ehotk->eeepc_wlan_rfkill->state = RFKILL_STATE_SOFT_BLOCKED; - rfkill_register(ehotk->eeepc_wlan_rfkill); + rfkill_set_default(RFKILL_TYPE_WLAN, + RFKILL_STATE_SOFT_BLOCKED); + } + result = rfkill_register(ehotk->eeepc_wlan_rfkill); + if (result) + goto wlan_fail; } if (get_acpi(CM_ASL_BLUETOOTH) != -1) { @@ -588,27 +676,47 @@ static int eeepc_hotk_add(struct acpi_device *device) rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); if (!ehotk->eeepc_bluetooth_rfkill) - goto end; + goto bluetooth_fail; ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; ehotk->eeepc_bluetooth_rfkill->toggle_radio = eeepc_bluetooth_rfkill_set; ehotk->eeepc_bluetooth_rfkill->get_state = eeepc_bluetooth_rfkill_state; - if (get_acpi(CM_ASL_BLUETOOTH) == 1) + if (get_acpi(CM_ASL_BLUETOOTH) == 1) { ehotk->eeepc_bluetooth_rfkill->state = RFKILL_STATE_UNBLOCKED; - else + rfkill_set_default(RFKILL_TYPE_BLUETOOTH, + RFKILL_STATE_UNBLOCKED); + } else { ehotk->eeepc_bluetooth_rfkill->state = RFKILL_STATE_SOFT_BLOCKED; - rfkill_register(ehotk->eeepc_bluetooth_rfkill); - } + rfkill_set_default(RFKILL_TYPE_BLUETOOTH, + RFKILL_STATE_SOFT_BLOCKED); + } - end: - if (result) { - kfree(ehotk); - ehotk = NULL; + result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); + if (result) + goto bluetooth_fail; } + + eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); + eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); + + return 0; + + bluetooth_fail: + if (ehotk->eeepc_bluetooth_rfkill) + rfkill_free(ehotk->eeepc_bluetooth_rfkill); + rfkill_unregister(ehotk->eeepc_wlan_rfkill); + ehotk->eeepc_wlan_rfkill = NULL; + wlan_fail: + if (ehotk->eeepc_wlan_rfkill) + rfkill_free(ehotk->eeepc_wlan_rfkill); + ehotk_fail: + kfree(ehotk); + ehotk = NULL; + return result; } @@ -622,6 +730,10 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) eeepc_hotk_notify); if (ACPI_FAILURE(status)) printk(EEEPC_ERR "Error removing notify handler\n"); + + eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); + eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); + kfree(ehotk); return 0; } @@ -737,13 +849,21 @@ static void eeepc_backlight_exit(void) { if (eeepc_backlight_device) backlight_device_unregister(eeepc_backlight_device); - if (ehotk->inputdev) - input_unregister_device(ehotk->inputdev); + eeepc_backlight_device = NULL; +} + +static void eeepc_rfkill_exit(void) +{ if (ehotk->eeepc_wlan_rfkill) rfkill_unregister(ehotk->eeepc_wlan_rfkill); if (ehotk->eeepc_bluetooth_rfkill) rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); - eeepc_backlight_device = NULL; +} + +static void eeepc_input_exit(void) +{ + if (ehotk->inputdev) + input_unregister_device(ehotk->inputdev); } static void eeepc_hwmon_exit(void) @@ -762,6 +882,8 @@ static void eeepc_hwmon_exit(void) static void __exit eeepc_laptop_exit(void) { eeepc_backlight_exit(); + eeepc_rfkill_exit(); + eeepc_input_exit(); eeepc_hwmon_exit(); acpi_bus_unregister_driver(&eeepc_hotk_driver); sysfs_remove_group(&platform_device->dev.kobj, @@ -865,6 +987,8 @@ fail_platform_driver: fail_hwmon: eeepc_backlight_exit(); fail_backlight: + eeepc_input_exit(); + eeepc_rfkill_exit(); return result; } diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index de91dda..f41135f 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -463,9 +463,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) return 0; register_wwan_err: - rfkill_unregister(bluetooth_rfkill); + if (bluetooth_rfkill) + rfkill_unregister(bluetooth_rfkill); register_bluetooth_error: - rfkill_unregister(wifi_rfkill); + if (wifi_rfkill) + rfkill_unregister(wifi_rfkill); add_sysfs_error: cleanup_sysfs(device); return err; diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index f30db36..c47a44d 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c @@ -507,7 +507,7 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) hkey_num = result & 0xf; - if (hkey_num < 0 || hkey_num > ARRAY_SIZE(pcc->keymap)) { + if (hkey_num < 0 || hkey_num >= ARRAY_SIZE(pcc->keymap)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "hotkey number out of range: %d\n", hkey_num)); diff --git a/drivers/regulator/bq24022.c b/drivers/regulator/bq24022.c index 366565a..c175e38 100644 --- a/drivers/regulator/bq24022.c +++ b/drivers/regulator/bq24022.c @@ -152,11 +152,7 @@ static void __exit bq24022_exit(void) platform_driver_unregister(&bq24022_driver); } -/* - * make sure this is probed before gpio_vbus and pda_power, - * but after asic3 or other GPIO expander drivers. - */ -subsys_initcall(bq24022_init); +module_init(bq24022_init); module_exit(bq24022_exit); MODULE_AUTHOR("Philipp Zabel"); diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 7aa3524..5056e23 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1435,7 +1435,7 @@ int wm8350_register_led(struct wm8350 *wm8350, int lednum, int dcdc, int isink, struct platform_device *pdev; int ret; - if (lednum > ARRAY_SIZE(wm8350->pmic.led) || lednum < 0) { + if (lednum >= ARRAY_SIZE(wm8350->pmic.led) || lednum < 0) { dev_err(wm8350->dev, "Invalid LED index %d\n", lednum); return -ENODEV; } diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index cced4d1..81450fb 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -241,6 +241,12 @@ config RTC_DRV_M41T80_WDT If you say Y here you will get support for the watchdog timer in the ST M41T60 and M41T80 RTC chips series. +config RTC_DRV_DM355EVM + tristate "TI DaVinci DM355 EVM RTC" + depends on MFD_DM355EVM_MSP + help + Supports the RTC firmware in the MSP430 on the DM355 EVM. + config RTC_DRV_TWL92330 boolean "TI TWL92330/Menelaus" depends on MENELAUS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 6e28021..0e697aa 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o +obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o diff --git a/drivers/rtc/rtc-dm355evm.c b/drivers/rtc/rtc-dm355evm.c new file mode 100644 index 0000000..58d4e18 --- /dev/null +++ b/drivers/rtc/rtc-dm355evm.c @@ -0,0 +1,175 @@ +/* + * rtc-dm355evm.c - access battery-backed counter in MSP430 firmware + * + * Copyright (c) 2008 by David Brownell + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/rtc.h> +#include <linux/platform_device.h> + +#include <linux/i2c/dm355evm_msp.h> + + +/* + * The MSP430 firmware on the DM355 EVM uses a watch crystal to feed + * a 1 Hz counter. When a backup battery is supplied, that makes a + * reasonable RTC for applications where alarms and non-NTP drift + * compensation aren't important. + * + * The only real glitch is the inability to read or write all four + * counter bytes atomically: the count may increment in the middle + * of an operation, causing trouble when the LSB rolls over. + * + * This driver was tested with firmware revision A4. + */ +union evm_time { + u8 bytes[4]; + u32 value; +}; + +static int dm355evm_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + union evm_time time; + int status; + int tries = 0; + + do { + /* + * Read LSB(0) to MSB(3) bytes. Defend against the counter + * rolling over by re-reading until the value is stable, + * and assuming the four reads take at most a few seconds. + */ + status = dm355evm_msp_read(DM355EVM_MSP_RTC_0); + if (status < 0) + return status; + if (tries && time.bytes[0] == status) + break; + time.bytes[0] = status; + + status = dm355evm_msp_read(DM355EVM_MSP_RTC_1); + if (status < 0) + return status; + if (tries && time.bytes[1] == status) + break; + time.bytes[1] = status; + + status = dm355evm_msp_read(DM355EVM_MSP_RTC_2); + if (status < 0) + return status; + if (tries && time.bytes[2] == status) + break; + time.bytes[2] = status; + + status = dm355evm_msp_read(DM355EVM_MSP_RTC_3); + if (status < 0) + return status; + if (tries && time.bytes[3] == status) + break; + time.bytes[3] = status; + + } while (++tries < 5); + + dev_dbg(dev, "read timestamp %08x\n", time.value); + + rtc_time_to_tm(le32_to_cpu(time.value), tm); + return 0; +} + +static int dm355evm_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + union evm_time time; + unsigned long value; + int status; + + rtc_tm_to_time(tm, &value); + time.value = cpu_to_le32(value); + + dev_dbg(dev, "write timestamp %08x\n", time.value); + + /* + * REVISIT handle non-atomic writes ... maybe just retry until + * byte[1] sticks (no rollover)? + */ + status = dm355evm_msp_write(time.bytes[0], DM355EVM_MSP_RTC_0); + if (status < 0) + return status; + + status = dm355evm_msp_write(time.bytes[1], DM355EVM_MSP_RTC_1); + if (status < 0) + return status; + + status = dm355evm_msp_write(time.bytes[2], DM355EVM_MSP_RTC_2); + if (status < 0) + return status; + + status = dm355evm_msp_write(time.bytes[3], DM355EVM_MSP_RTC_3); + if (status < 0) + return status; + + return 0; +} + +static struct rtc_class_ops dm355evm_rtc_ops = { + .read_time = dm355evm_rtc_read_time, + .set_time = dm355evm_rtc_set_time, +}; + +/*----------------------------------------------------------------------*/ + +static int __devinit dm355evm_rtc_probe(struct platform_device *pdev) +{ + struct rtc_device *rtc; + + rtc = rtc_device_register(pdev->name, + &pdev->dev, &dm355evm_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + dev_err(&pdev->dev, "can't register RTC device, err %ld\n", + PTR_ERR(rtc)); + return PTR_ERR(rtc); + } + platform_set_drvdata(pdev, rtc); + + return 0; +} + +static int __devexit dm355evm_rtc_remove(struct platform_device *pdev) +{ + struct rtc_device *rtc = platform_get_drvdata(pdev); + + rtc_device_unregister(rtc); + platform_set_drvdata(pdev, NULL); + return 0; +} + +/* + * I2C is used to talk to the MSP430, but this platform device is + * exposed by an MFD driver that manages I2C communications. + */ +static struct platform_driver rtc_dm355evm_driver = { + .probe = dm355evm_rtc_probe, + .remove = __devexit_p(dm355evm_rtc_remove), + .driver = { + .owner = THIS_MODULE, + .name = "rtc-dm355evm", + }, +}; + +static int __init dm355evm_rtc_init(void) +{ + return platform_driver_register(&rtc_dm355evm_driver); +} +module_init(dm355evm_rtc_init); + +static void __exit dm355evm_rtc_exit(void) +{ + platform_driver_unregister(&rtc_dm355evm_driver); +} +module_exit(dm355evm_rtc_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c index e54b5c6..e01b955 100644 --- a/drivers/rtc/rtc-ds1390.c +++ b/drivers/rtc/rtc-ds1390.c @@ -122,7 +122,6 @@ static const struct rtc_class_ops ds1390_rtc_ops = { static int __devinit ds1390_probe(struct spi_device *spi) { - struct rtc_device *rtc; unsigned char tmp; struct ds1390 *chip; int res; diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c index 577c0d2..2291c5f 100644 --- a/drivers/usb/host/whci/asl.c +++ b/drivers/usb/host/whci/asl.c @@ -170,12 +170,17 @@ void asl_stop(struct whc *whc) void asl_update(struct whc *whc, uint32_t wusbcmd) { struct wusbhc *wusbhc = &whc->wusbhc; + long t; mutex_lock(&wusbhc->mutex); if (wusbhc->active) { whc_write_wusbcmd(whc, wusbcmd, wusbcmd); - wait_event(whc->async_list_wq, - (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0); + t = wait_event_timeout( + whc->async_list_wq, + (le_readl(whc->base + WUSBCMD) & WUSBCMD_ASYNC_UPDATED) == 0, + msecs_to_jiffies(1000)); + if (t == 0) + whc_hw_error(whc, "ASL update timeout"); } mutex_unlock(&wusbhc->mutex); } diff --git a/drivers/usb/host/whci/hw.c b/drivers/usb/host/whci/hw.c index d498e72..6afa2e3 100644 --- a/drivers/usb/host/whci/hw.c +++ b/drivers/usb/host/whci/hw.c @@ -87,3 +87,18 @@ out: return ret; } + +/** + * whc_hw_error - recover from a hardware error + * @whc: the WHCI HC that broke. + * @reason: a description of the failure. + * + * Recover from broken hardware with a full reset. + */ +void whc_hw_error(struct whc *whc, const char *reason) +{ + struct wusbhc *wusbhc = &whc->wusbhc; + + dev_err(&whc->umc->dev, "hardware error: %s\n", reason); + wusbhc_reset_all(wusbhc); +} diff --git a/drivers/usb/host/whci/pzl.c b/drivers/usb/host/whci/pzl.c index 2ae5abf..7dc85a0 100644 --- a/drivers/usb/host/whci/pzl.c +++ b/drivers/usb/host/whci/pzl.c @@ -183,12 +183,17 @@ void pzl_stop(struct whc *whc) void pzl_update(struct whc *whc, uint32_t wusbcmd) { struct wusbhc *wusbhc = &whc->wusbhc; + long t; mutex_lock(&wusbhc->mutex); if (wusbhc->active) { whc_write_wusbcmd(whc, wusbcmd, wusbcmd); - wait_event(whc->periodic_list_wq, - (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0); + t = wait_event_timeout( + whc->periodic_list_wq, + (le_readl(whc->base + WUSBCMD) & WUSBCMD_PERIODIC_UPDATED) == 0, + msecs_to_jiffies(1000)); + if (t == 0) + whc_hw_error(whc, "PZL update timeout"); } mutex_unlock(&wusbhc->mutex); } diff --git a/drivers/usb/host/whci/whcd.h b/drivers/usb/host/whci/whcd.h index 0f3540f..d3543a1 100644 --- a/drivers/usb/host/whci/whcd.h +++ b/drivers/usb/host/whci/whcd.h @@ -137,6 +137,7 @@ void whc_clean_up(struct whc *whc); /* hw.c */ void whc_write_wusbcmd(struct whc *whc, u32 mask, u32 val); int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len); +void whc_hw_error(struct whc *whc, const char *reason); /* wusb.c */ int whc_wusbhc_start(struct wusbhc *wusbhc); diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index e2e7e4b..8e18141 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c @@ -386,6 +386,7 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc, | USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED); port->change |= USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE; if (wusb_dev) { + dev_dbg(wusbhc->dev, "disconnecting device from port %d\n", wusb_dev->port_idx); if (!list_empty(&wusb_dev->cack_node)) list_del_init(&wusb_dev->cack_node); /* For the one in cack_add() */ diff --git a/drivers/usb/wusbcore/rh.c b/drivers/usb/wusbcore/rh.c index 3937bf6..9fe4246 100644 --- a/drivers/usb/wusbcore/rh.c +++ b/drivers/usb/wusbcore/rh.c @@ -100,6 +100,9 @@ static int wusbhc_rh_port_reset(struct wusbhc *wusbhc, u8 port_idx) struct wusb_port *port = wusb_port_by_idx(wusbhc, port_idx); struct wusb_dev *wusb_dev = port->wusb_dev; + if (wusb_dev == NULL) + return -ENOTCONN; + port->status |= USB_PORT_STAT_RESET; port->change |= USB_PORT_STAT_C_RESET; diff --git a/drivers/uwb/allocator.c b/drivers/uwb/allocator.c index c8185e6..c13cec7 100644 --- a/drivers/uwb/allocator.c +++ b/drivers/uwb/allocator.c @@ -15,7 +15,6 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <linux/version.h> #include <linux/kernel.h> #include <linux/uwb.h> diff --git a/drivers/uwb/drp.c b/drivers/uwb/drp.c index 2b4f940..4f5ca99 100644 --- a/drivers/uwb/drp.c +++ b/drivers/uwb/drp.c @@ -66,14 +66,14 @@ static void uwb_rc_set_drp_cmd_done(struct uwb_rc *rc, void *arg, } else dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: timeout\n"); - spin_lock(&rc->rsvs_lock); + spin_lock_bh(&rc->rsvs_lock); if (rc->set_drp_ie_pending > 1) { rc->set_drp_ie_pending = 0; uwb_rsv_queue_update(rc); } else { rc->set_drp_ie_pending = 0; } - spin_unlock(&rc->rsvs_lock); + spin_unlock_bh(&rc->rsvs_lock); } /** diff --git a/drivers/uwb/rsv.c b/drivers/uwb/rsv.c index ec6eecb..6b76f4b 100644 --- a/drivers/uwb/rsv.c +++ b/drivers/uwb/rsv.c @@ -114,7 +114,8 @@ void uwb_rsv_dump(char *text, struct uwb_rsv *rsv) devaddr = rsv->target.devaddr; uwb_dev_addr_print(target, sizeof(target), &devaddr); - dev_dbg(dev, "rsv %s -> %s: %s\n", owner, target, uwb_rsv_state_str(rsv->state)); + dev_dbg(dev, "rsv %s %s -> %s: %s\n", + text, owner, target, uwb_rsv_state_str(rsv->state)); } static void uwb_rsv_release(struct kref *kref) @@ -511,8 +512,7 @@ void uwb_rsv_remove(struct uwb_rsv *rsv) if (uwb_rsv_is_owner(rsv)) uwb_rsv_put_stream(rsv); - - del_timer_sync(&rsv->timer); + uwb_dev_put(rsv->owner); if (rsv->target.type == UWB_RSV_TARGET_DEV) uwb_dev_put(rsv->target.dev); @@ -870,7 +870,7 @@ void uwb_rsv_queue_update(struct uwb_rc *rc) */ void uwb_rsv_sched_update(struct uwb_rc *rc) { - spin_lock(&rc->rsvs_lock); + spin_lock_bh(&rc->rsvs_lock); if (!delayed_work_pending(&rc->rsv_update_work)) { if (rc->set_drp_ie_pending > 0) { rc->set_drp_ie_pending++; @@ -879,7 +879,7 @@ void uwb_rsv_sched_update(struct uwb_rc *rc) uwb_rsv_queue_update(rc); } unlock: - spin_unlock(&rc->rsvs_lock); + spin_unlock_bh(&rc->rsvs_lock); } /* @@ -943,13 +943,22 @@ void uwb_rsv_remove_all(struct uwb_rc *rc) mutex_lock(&rc->rsvs_mutex); list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { - uwb_rsv_remove(rsv); + if (rsv->state != UWB_RSV_STATE_NONE) + uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); + del_timer_sync(&rsv->timer); } /* Cancel any postponed update. */ rc->set_drp_ie_pending = 0; mutex_unlock(&rc->rsvs_mutex); cancel_delayed_work_sync(&rc->rsv_update_work); + flush_workqueue(rc->rsv_workq); + + mutex_lock(&rc->rsvs_mutex); + list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { + uwb_rsv_remove(rsv); + } + mutex_unlock(&rc->rsvs_mutex); } void uwb_rsv_init(struct uwb_rc *rc) diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index db16112..e6e299f 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -1475,7 +1475,7 @@ static int aty128fb_set_par(struct fb_info *info) aty128_set_pll(&par->pll, par); aty128_set_fifo(&par->fifo_reg, par); - config = aty_ld_le32(CONFIG_CNTL) & ~3; + config = aty_ld_le32(CNFG_CNTL) & ~3; #if defined(__BIG_ENDIAN) if (par->crtc.bpp == 32) @@ -1484,7 +1484,7 @@ static int aty128fb_set_par(struct fb_info *info) config |= 1; /* make aperture do 16 bit swapping */ #endif - aty_st_le32(CONFIG_CNTL, config); + aty_st_le32(CNFG_CNTL, config); aty_st_8(CRTC_EXT_CNTL + 1, 0); /* turn the video back on */ info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3; @@ -1875,7 +1875,7 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i u32 dac; /* Get the chip revision */ - chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; + chip_rev = (aty_ld_le32(CNFG_CNTL) >> 16) & 0x1F; strcpy(video_card, "Rage128 XX "); video_card[8] = ent->device >> 8; @@ -2057,7 +2057,7 @@ static int __devinit aty128_probe(struct pci_dev *pdev, const struct pci_device_ /* Grab memory size from the card */ // How does this relate to the resource length from the PCI hardware? - par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; + par->vram_size = aty_ld_le32(CNFG_MEMSIZE) & 0x03FFFFFF; /* Virtualize the framebuffer */ info->screen_base = ioremap(fb_addr, par->vram_size); @@ -2374,6 +2374,8 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend) /* Set the chip into the appropriate suspend mode (we use D2, * D3 would require a complete re-initialisation of the chip, * including PCI config registers, clocks, AGP configuration, ...) + * + * For resume, the core will have already brought us back to D0 */ if (suspend) { /* Make sure CRTC2 is reset. Remove that the day we decide to @@ -2391,17 +2393,9 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend) aty_st_le32(BUS_CNTL1, 0x00000010); aty_st_le32(MEM_POWER_MISC, 0x0c830000); mdelay(100); - pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command); + /* Switch PCI power management to D2 */ - pci_write_config_word(pdev, par->pm_reg+PCI_PM_CTRL, - (pwr_command & ~PCI_PM_CTRL_STATE_MASK) | 2); - pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command); - } else { - /* Switch back PCI power management to D0 */ - mdelay(100); - pci_write_config_word(pdev, par->pm_reg+PCI_PM_CTRL, 0); - pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command); - mdelay(100); + pci_set_power_state(pdev, PCI_D2); } } @@ -2410,6 +2404,12 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state) struct fb_info *info = pci_get_drvdata(pdev); struct aty128fb_par *par = info->par; + /* Because we may change PCI D state ourselves, we need to + * first save the config space content so the core can + * restore it properly on resume. + */ + pci_save_state(pdev); + /* We don't do anything but D2, for now we return 0, but * we may want to change that. How do we know if the BIOS * can properly take care of D3 ? Also, with swsusp, we @@ -2476,6 +2476,11 @@ static int aty128_do_resume(struct pci_dev *pdev) if (pdev->dev.power.power_state.event == PM_EVENT_ON) return 0; + /* PCI state will have been restored by the core, so + * we should be in D0 now with our config space fully + * restored + */ + /* Wakeup chip */ aty128_set_suspend(par, 0); par->asleep = 0; diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index cc6b470..1207c20 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -135,7 +135,7 @@ #if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \ defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT) static const u32 lt_lcd_regs[] = { - CONFIG_PANEL_LG, + CNFG_PANEL_LG, LCD_GEN_CNTL_LG, DSTN_CONTROL_LG, HFB_PITCH_ADDR_LG, @@ -446,7 +446,7 @@ static int __devinit correct_chipset(struct atyfb_par *par) par->pll_limits.ecp_max = aty_chips[i].ecp_max; par->features = aty_chips[i].features; - chip_id = aty_ld_le32(CONFIG_CHIP_ID, par); + chip_id = aty_ld_le32(CNFG_CHIP_ID, par); type = chip_id & CFG_CHIP_TYPE; rev = (chip_id & CFG_CHIP_REV) >> 24; @@ -629,7 +629,7 @@ static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc) crtc->lcd_index = aty_ld_le32(LCD_INDEX, par); aty_st_le32(LCD_INDEX, crtc->lcd_index, par); } - crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par); + crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par); crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par); @@ -676,7 +676,7 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc) aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par); /* update non-shadow registers first */ - aty_st_lcd(CONFIG_PANEL, crtc->lcd_config_panel, par); + aty_st_lcd(CNFG_PANEL, crtc->lcd_config_panel, par); aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl & ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par); @@ -858,7 +858,7 @@ static int aty_var_to_crtc(const struct fb_info *info, if (!M64_HAS(MOBIL_BUS)) crtc->lcd_index |= CRTC2_DISPLAY_DIS; - crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par) | 0x4000; + crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par) | 0x4000; crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT; crtc->lcd_gen_cntl &= @@ -1978,7 +1978,7 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par) return timeout ? 0 : -EIO; } -#endif +#endif /* CONFIG_PPC_PMAC */ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) { @@ -2002,9 +2002,15 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) par->asleep = 1; par->lock_blank = 1; + /* Because we may change PCI D state ourselves, we need to + * first save the config space content so the core can + * restore it properly on resume. + */ + pci_save_state(pdev); + #ifdef CONFIG_PPC_PMAC /* Set chip to "suspend" mode */ - if (aty_power_mgmt(1, par)) { + if (machine_is(powermac) && aty_power_mgmt(1, par)) { par->asleep = 0; par->lock_blank = 0; atyfb_blank(FB_BLANK_UNBLANK, info); @@ -2047,11 +2053,15 @@ static int atyfb_pci_resume(struct pci_dev *pdev) acquire_console_sem(); + /* PCI state will have been restored by the core, so + * we should be in D0 now with our config space fully + * restored + */ + #ifdef CONFIG_PPC_PMAC - if (pdev->dev.power.power_state.event == 2) + if (machine_is(powermac) && + pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) aty_power_mgmt(0, par); -#else - pci_set_power_state(pdev, PCI_D0); #endif aty_resume_chip(info); @@ -2254,7 +2264,7 @@ static int __devinit aty_init(struct fb_info *info) if (!M64_HAS(INTEGRATED)) { u32 stat0; u8 dac_type, dac_subtype, clk_type; - stat0 = aty_ld_le32(CONFIG_STAT0, par); + stat0 = aty_ld_le32(CNFG_STAT0, par); par->bus_type = (stat0 >> 0) & 0x07; par->ram_type = (stat0 >> 3) & 0x07; ramname = aty_gx_ram[par->ram_type]; @@ -2324,7 +2334,7 @@ static int __devinit aty_init(struct fb_info *info) par->dac_ops = &aty_dac_ct; par->pll_ops = &aty_pll_ct; par->bus_type = PCI; - par->ram_type = (aty_ld_le32(CONFIG_STAT0, par) & 0x07); + par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07); ramname = aty_ct_ram[par->ram_type]; /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */ if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM) @@ -2433,7 +2443,7 @@ static int __devinit aty_init(struct fb_info *info) } if (M64_HAS(MAGIC_VRAM_SIZE)) { - if (aty_ld_le32(CONFIG_STAT1, par) & 0x40000000) + if (aty_ld_le32(CNFG_STAT1, par) & 0x40000000) info->fix.smem_len += 0x400000; } @@ -2946,7 +2956,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, * Fix PROMs idea of MEM_CNTL settings... */ mem = aty_ld_le32(MEM_CNTL, par); - chip_id = aty_ld_le32(CONFIG_CHIP_ID, par); + chip_id = aty_ld_le32(CNFG_CHIP_ID, par); if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) { switch (mem & 0x0f) { case 3: @@ -2964,7 +2974,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, default: break; } - if ((aty_ld_le32(CONFIG_STAT0, par) & 7) >= SDRAM) + if ((aty_ld_le32(CNFG_STAT0, par) & 7) >= SDRAM) mem &= ~(0x00700000); } mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */ @@ -3572,7 +3582,7 @@ static int __init atyfb_atari_probe(void) } /* Fake pci_id for correct_chipset() */ - switch (aty_ld_le32(CONFIG_CHIP_ID, par) & CFG_CHIP_TYPE) { + switch (aty_ld_le32(CNFG_CHIP_ID, par) & CFG_CHIP_TYPE) { case 0x00d7: par->pci_id = PCI_CHIP_MACH64GX; break; diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c index c50c7cf..2745b85 100644 --- a/drivers/video/aty/mach64_ct.c +++ b/drivers/video/aty/mach64_ct.c @@ -8,6 +8,9 @@ #include <asm/io.h> #include <video/mach64.h> #include "atyfb.h" +#ifdef CONFIG_PPC +#include <asm/machdep.h> +#endif #undef DEBUG @@ -536,6 +539,14 @@ static int __devinit aty_init_pll_ct(const struct fb_info *info, pll->ct.xclk_post_div_real = postdividers[xpost_div]; pll->ct.mclk_fb_div = q * pll->ct.xclk_post_div_real / 8; +#ifdef CONFIG_PPC + if (machine_is(powermac)) { + /* Override PLL_EXT_CNTL & 0x07. */ + pll->ct.xclk_post_div = xpost_div; + pll->ct.xclk_ref_div = 1; + } +#endif + #ifdef DEBUG pllmclk = (1000000 * pll->ct.mclk_fb_mult * pll->ct.mclk_fb_div) / (par->ref_clk_per * pll->ct.pll_ref_div); diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index d0f1a7f..16bb7e3 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -1936,8 +1936,8 @@ static void fixup_memory_mappings(struct radeonfb_info *rinfo) OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B); mdelay(100); - aper_base = INREG(CONFIG_APER_0_BASE); - aper_size = INREG(CONFIG_APER_SIZE); + aper_base = INREG(CNFG_APER_0_BASE); + aper_size = INREG(CNFG_APER_SIZE); #ifdef SET_MC_FB_FROM_APERTURE /* Set framebuffer to be at the same address as set in PCI BAR */ @@ -2024,11 +2024,11 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo) ~CRTC_H_CUTOFF_ACTIVE_EN); } } else { - tmp = INREG(CONFIG_MEMSIZE); + tmp = INREG(CNFG_MEMSIZE); } /* mem size is bits [28:0], mask off the rest */ - rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK; + rinfo->video_ram = tmp & CNFG_MEMSIZE_MASK; /* * Hack to get around some busted production M6's @@ -2228,7 +2228,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev, */ rinfo->errata = 0; if (rinfo->family == CHIP_FAMILY_R300 && - (INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) + (INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) == CFG_ATI_REV_A11) rinfo->errata |= CHIP_ERRATA_R300_CG; diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 675abda..ca5f0dc 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -333,7 +333,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) if (!rinfo->has_CRTC2) { tmp = INPLL(pllSCLK_CNTL); - if ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13) + if ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13) tmp &= ~(SCLK_CNTL__FORCE_CP | SCLK_CNTL__FORCE_RB); tmp &= ~(SCLK_CNTL__FORCE_HDP | SCLK_CNTL__FORCE_DISP1 | SCLK_CNTL__FORCE_TOP | SCLK_CNTL__FORCE_SE | @@ -468,9 +468,9 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/ if ((rinfo->family == CHIP_FAMILY_RV250 && - ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) || + ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) || ((rinfo->family == CHIP_FAMILY_RV100) && - ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) { + ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) { tmp |= SCLK_CNTL__FORCE_CP; tmp |= SCLK_CNTL__FORCE_VIP; } @@ -486,7 +486,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) /* RV200::A11 A12 RV250::A11 A12 */ if (((rinfo->family == CHIP_FAMILY_RV200) || (rinfo->family == CHIP_FAMILY_RV250)) && - ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) + ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) tmp |= SCLK_MORE_CNTL__FORCEON; OUTPLL(pllSCLK_MORE_CNTL, tmp); @@ -497,7 +497,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) /* RV200::A11 A12, RV250::A11 A12 */ if (((rinfo->family == CHIP_FAMILY_RV200) || (rinfo->family == CHIP_FAMILY_RV250)) && - ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) { + ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) { tmp = INPLL(pllPLL_PWRMGT_CNTL); tmp |= PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE; OUTPLL(pllPLL_PWRMGT_CNTL, tmp); @@ -702,7 +702,7 @@ static void radeon_pm_restore_regs(struct radeonfb_info *rinfo) OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]); OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]); OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]); - OUTREG(CONFIG_MEMSIZE, rinfo->video_ram); + OUTREG(CNFG_MEMSIZE, rinfo->video_ram); OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]); OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]); @@ -1723,7 +1723,7 @@ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo) OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]); OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]); OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]); - OUTREG(CONFIG_MEMSIZE, rinfo->video_ram); + OUTREG(CNFG_MEMSIZE, rinfo->video_ram); OUTREG(BUS_CNTL, rinfo->save_regs[36]); OUTREG(BUS_CNTL1, rinfo->save_regs[14]); OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]); @@ -1961,7 +1961,7 @@ static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo) OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, rinfo->save_regs[68] /*0x141555ff*/); OUTMC(rinfo, ixMC_IMP_CNTL_0, rinfo->save_regs[71] /*0x00009249*/); OUTREG(MC_IND_INDEX, 0); - OUTREG(CONFIG_MEMSIZE, rinfo->video_ram); + OUTREG(CNFG_MEMSIZE, rinfo->video_ram); mdelay(20); } @@ -2361,7 +2361,7 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo) OUTMC(rinfo, ixMC_IMP_CNTL_0, 0x00009249); OUTREG(MC_IND_INDEX, 0); - OUTREG(CONFIG_MEMSIZE, rinfo->video_ram); + OUTREG(CNFG_MEMSIZE, rinfo->video_ram); radeon_pm_full_reset_sdram(rinfo); @@ -2509,9 +2509,7 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo) static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) { - u16 pwr_cmd; u32 tmp; - int i; if (!rinfo->pm_reg) return; @@ -2557,32 +2555,14 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) } } - for (i = 0; i < 64; ++i) - pci_read_config_dword(rinfo->pdev, i * 4, - &rinfo->cfg_save[i]); - /* Switch PCI power management to D2. */ pci_disable_device(rinfo->pdev); - for (;;) { - pci_read_config_word( - rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, - &pwr_cmd); - if (pwr_cmd & 2) - break; - pci_write_config_word( - rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, - (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2); - mdelay(500); - } + pci_save_state(rinfo->pdev); + pci_set_power_state(rinfo->pdev, PCI_D2); } else { printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n", pci_name(rinfo->pdev)); - /* Switch back PCI powermanagment to D0 */ - mdelay(200); - pci_write_config_word(rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 0); - mdelay(500); - if (rinfo->family <= CHIP_FAMILY_RV250) { /* Reset the SDRAM controller */ radeon_pm_full_reset_sdram(rinfo); @@ -2598,37 +2578,10 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) } } -static int radeon_restore_pci_cfg(struct radeonfb_info *rinfo) -{ - int i; - static u32 radeon_cfg_after_resume[64]; - - for (i = 0; i < 64; ++i) - pci_read_config_dword(rinfo->pdev, i * 4, - &radeon_cfg_after_resume[i]); - - if (radeon_cfg_after_resume[PCI_BASE_ADDRESS_0/4] - == rinfo->cfg_save[PCI_BASE_ADDRESS_0/4]) - return 0; /* assume everything is ok */ - - for (i = PCI_BASE_ADDRESS_0/4; i < 64; ++i) { - if (radeon_cfg_after_resume[i] != rinfo->cfg_save[i]) - pci_write_config_dword(rinfo->pdev, i * 4, - rinfo->cfg_save[i]); - } - pci_write_config_word(rinfo->pdev, PCI_CACHE_LINE_SIZE, - rinfo->cfg_save[PCI_CACHE_LINE_SIZE/4]); - pci_write_config_word(rinfo->pdev, PCI_COMMAND, - rinfo->cfg_save[PCI_COMMAND/4]); - return 1; -} - - int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) { struct fb_info *info = pci_get_drvdata(pdev); struct radeonfb_info *rinfo = info->par; - int i; if (mesg.event == pdev->dev.power.power_state.event) return 0; @@ -2674,6 +2627,11 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) pmac_suspend_agp_for_card(pdev); #endif /* CONFIG_PPC_PMAC */ + /* It's unclear whether or when the generic code will do that, so let's + * do it ourselves. We save state before we do any power management + */ + pci_save_state(pdev); + /* If we support wakeup from poweroff, we save all regs we can including cfg * space */ @@ -2698,9 +2656,6 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) mdelay(20); OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON)); } - // FIXME: Use PCI layer - for (i = 0; i < 64; ++i) - pci_read_config_dword(pdev, i * 4, &rinfo->cfg_save[i]); pci_disable_device(pdev); } /* If we support D2, we go to it (should be fixed later with a flag forcing @@ -2717,6 +2672,13 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) return 0; } +static int radeon_check_power_loss(struct radeonfb_info *rinfo) +{ + return rinfo->save_regs[4] != INPLL(CLK_PIN_CNTL) || + rinfo->save_regs[2] != INPLL(MCLK_CNTL) || + rinfo->save_regs[3] != INPLL(SCLK_CNTL); +} + int radeonfb_pci_resume(struct pci_dev *pdev) { struct fb_info *info = pci_get_drvdata(pdev); @@ -2735,20 +2697,13 @@ int radeonfb_pci_resume(struct pci_dev *pdev) printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n", pci_name(pdev), pdev->dev.power.power_state.event); - - if (pci_enable_device(pdev)) { - rc = -ENODEV; - printk(KERN_ERR "radeonfb (%s): can't enable PCI device !\n", - pci_name(pdev)); - goto bail; - } - pci_set_master(pdev); - + /* PCI state will have been restored by the core, so + * we should be in D0 now with our config space fully + * restored + */ if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { - /* Wakeup chip. Check from config space if we were powered off - * (todo: additionally, check CLK_PIN_CNTL too) - */ - if ((rinfo->pm_mode & radeon_pm_off) && radeon_restore_pci_cfg(rinfo)) { + /* Wakeup chip */ + if ((rinfo->pm_mode & radeon_pm_off) && radeon_check_power_loss(rinfo)) { if (rinfo->reinit_func != NULL) rinfo->reinit_func(rinfo); else { diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index 3ea1b00..7351e66 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h @@ -361,8 +361,6 @@ struct radeonfb_info { #ifdef CONFIG_FB_RADEON_I2C struct radeon_i2c_chan i2c[4]; #endif - - u32 cfg_save[64]; }; diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 363b3cb..63d7594 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -18,7 +18,7 @@ obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o -obj-$(CONFIG_BACKLIGHT_DA903X) += da903x.o +obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o diff --git a/drivers/video/backlight/da903x.c b/drivers/video/backlight/da903x_bl.c index 93bb434..93bb434 100644 --- a/drivers/video/backlight/da903x.c +++ b/drivers/video/backlight/da903x_bl.c diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index 91b78e6..f53b9f1 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c @@ -250,10 +250,6 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info) int rc, size = cmap->len * sizeof(u16); struct fb_cmap umap; - if (cmap->start < 0 || (!info->fbops->fb_setcolreg && - !info->fbops->fb_setcmap)) - return -EINVAL; - memset(&umap, 0, sizeof(struct fb_cmap)); rc = fb_alloc_cmap(&umap, cmap->len, cmap->transp != NULL); if (rc) @@ -262,11 +258,23 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info) copy_from_user(umap.green, cmap->green, size) || copy_from_user(umap.blue, cmap->blue, size) || (cmap->transp && copy_from_user(umap.transp, cmap->transp, size))) { - fb_dealloc_cmap(&umap); - return -EFAULT; + rc = -EFAULT; + goto out; } umap.start = cmap->start; + if (!lock_fb_info(info)) { + rc = -ENODEV; + goto out; + } + if (cmap->start < 0 || (!info->fbops->fb_setcolreg && + !info->fbops->fb_setcmap)) { + rc = -EINVAL; + goto out1; + } rc = fb_set_cmap(&umap, info); +out1: + unlock_fb_info(info); +out: fb_dealloc_cmap(&umap); return rc; } diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 756efeb..cfd9dce 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1013,132 +1013,139 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, struct fb_var_screeninfo var; struct fb_fix_screeninfo fix; struct fb_con2fbmap con2fb; + struct fb_cmap cmap_from; struct fb_cmap_user cmap; struct fb_event event; void __user *argp = (void __user *)arg; long ret = 0; - fb = info->fbops; - if (!fb) - return -ENODEV; - switch (cmd) { case FBIOGET_VSCREENINFO: - ret = copy_to_user(argp, &info->var, - sizeof(var)) ? -EFAULT : 0; + if (!lock_fb_info(info)) + return -ENODEV; + var = info->var; + unlock_fb_info(info); + + ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0; break; case FBIOPUT_VSCREENINFO: - if (copy_from_user(&var, argp, sizeof(var))) { - ret = -EFAULT; - break; - } + if (copy_from_user(&var, argp, sizeof(var))) + return -EFAULT; + if (!lock_fb_info(info)) + return -ENODEV; acquire_console_sem(); info->flags |= FBINFO_MISC_USEREVENT; ret = fb_set_var(info, &var); info->flags &= ~FBINFO_MISC_USEREVENT; release_console_sem(); - if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) + unlock_fb_info(info); + if (!ret && copy_to_user(argp, &var, sizeof(var))) ret = -EFAULT; break; case FBIOGET_FSCREENINFO: - ret = copy_to_user(argp, &info->fix, - sizeof(fix)) ? -EFAULT : 0; + if (!lock_fb_info(info)) + return -ENODEV; + fix = info->fix; + unlock_fb_info(info); + + ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0; break; case FBIOPUTCMAP: if (copy_from_user(&cmap, argp, sizeof(cmap))) - ret = -EFAULT; - else - ret = fb_set_user_cmap(&cmap, info); + return -EFAULT; + ret = fb_set_user_cmap(&cmap, info); break; case FBIOGETCMAP: if (copy_from_user(&cmap, argp, sizeof(cmap))) - ret = -EFAULT; - else - ret = fb_cmap_to_user(&info->cmap, &cmap); + return -EFAULT; + if (!lock_fb_info(info)) + return -ENODEV; + cmap_from = info->cmap; + unlock_fb_info(info); + ret = fb_cmap_to_user(&cmap_from, &cmap); break; case FBIOPAN_DISPLAY: - if (copy_from_user(&var, argp, sizeof(var))) { - ret = -EFAULT; - break; - } + if (copy_from_user(&var, argp, sizeof(var))) + return -EFAULT; + if (!lock_fb_info(info)) + return -ENODEV; acquire_console_sem(); ret = fb_pan_display(info, &var); release_console_sem(); + unlock_fb_info(info); if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) - ret = -EFAULT; + return -EFAULT; break; case FBIO_CURSOR: ret = -EINVAL; break; case FBIOGET_CON2FBMAP: if (copy_from_user(&con2fb, argp, sizeof(con2fb))) - ret = -EFAULT; - else if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) - ret = -EINVAL; - else { - con2fb.framebuffer = -1; - event.info = info; - event.data = &con2fb; - fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, - &event); - ret = copy_to_user(argp, &con2fb, - sizeof(con2fb)) ? -EFAULT : 0; - } + return -EFAULT; + if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) + return -EINVAL; + con2fb.framebuffer = -1; + event.data = &con2fb; + + if (!lock_fb_info(info)) + return -ENODEV; + event.info = info; + fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); + unlock_fb_info(info); + + ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; break; case FBIOPUT_CON2FBMAP: - if (copy_from_user(&con2fb, argp, sizeof(con2fb))) { - ret = -EFAULT; - break; - } - if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) { - ret = -EINVAL; - break; - } - if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) { - ret = -EINVAL; - break; - } + if (copy_from_user(&con2fb, argp, sizeof(con2fb))) + return -EFAULT; + if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) + return -EINVAL; + if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) + return -EINVAL; if (!registered_fb[con2fb.framebuffer]) request_module("fb%d", con2fb.framebuffer); if (!registered_fb[con2fb.framebuffer]) { ret = -EINVAL; break; } - event.info = info; event.data = &con2fb; + if (!lock_fb_info(info)) + return -ENODEV; + event.info = info; ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); + unlock_fb_info(info); break; case FBIOBLANK: + if (!lock_fb_info(info)) + return -ENODEV; acquire_console_sem(); info->flags |= FBINFO_MISC_USEREVENT; ret = fb_blank(info, arg); info->flags &= ~FBINFO_MISC_USEREVENT; release_console_sem(); - break;; + unlock_fb_info(info); + break; default: - if (fb->fb_ioctl == NULL) - ret = -ENOTTY; - else + if (!lock_fb_info(info)) + return -ENODEV; + fb = info->fbops; + if (fb->fb_ioctl) ret = fb->fb_ioctl(info, cmd, arg); + else + ret = -ENOTTY; + unlock_fb_info(info); } return ret; } static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -__acquires(&info->lock) -__releases(&info->lock) { struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); - struct fb_info *info; - long ret; + struct fb_info *info = registered_fb[fbidx]; - info = registered_fb[fbidx]; - mutex_lock(&info->lock); - ret = do_fb_ioctl(info, cmd, arg); - mutex_unlock(&info->lock); - return ret; + return do_fb_ioctl(info, cmd, arg); } #ifdef CONFIG_COMPAT @@ -1257,8 +1264,6 @@ static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd, static long fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -__acquires(&info->lock) -__releases(&info->lock) { struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); @@ -1266,7 +1271,6 @@ __releases(&info->lock) struct fb_ops *fb = info->fbops; long ret = -ENOIOCTLCMD; - mutex_lock(&info->lock); switch(cmd) { case FBIOGET_VSCREENINFO: case FBIOPUT_VSCREENINFO: @@ -1292,7 +1296,6 @@ __releases(&info->lock) ret = fb->fb_compat_ioctl(info, cmd, arg); break; } - mutex_unlock(&info->lock); return ret; } #endif diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index bef6b45..330aacb 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -192,7 +192,7 @@ static irqreturn_t vp_interrupt(int irq, void *opaque) drv = container_of(vp_dev->vdev.dev.driver, struct virtio_driver, driver); - if (drv->config_changed) + if (drv && drv->config_changed) drv->config_changed(&vp_dev->vdev); } diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 2ba8f95..efa4b36 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -498,7 +498,7 @@ static ssize_t store_target_kb(struct sys_device *dev, if (!capable(CAP_SYS_ADMIN)) return -EPERM; - target_bytes = memparse(buf, &endchar); + target_bytes = simple_strtoull(buf, &endchar, 0) * 1024; balloon_set_new_target(target_bytes >> PAGE_SHIFT); @@ -508,8 +508,39 @@ static ssize_t store_target_kb(struct sys_device *dev, static SYSDEV_ATTR(target_kb, S_IRUGO | S_IWUSR, show_target_kb, store_target_kb); + +static ssize_t show_target(struct sys_device *dev, struct sysdev_attribute *attr, + char *buf) +{ + return sprintf(buf, "%llu\n", + (u64)balloon_stats.target_pages << PAGE_SHIFT); +} + +static ssize_t store_target(struct sys_device *dev, + struct sysdev_attribute *attr, + const char *buf, + size_t count) +{ + char *endchar; + unsigned long long target_bytes; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + target_bytes = memparse(buf, &endchar); + + balloon_set_new_target(target_bytes >> PAGE_SHIFT); + + return count; +} + +static SYSDEV_ATTR(target, S_IRUGO | S_IWUSR, + show_target, store_target); + + static struct sysdev_attribute *balloon_attrs[] = { &attr_target_kb, + &attr_target, }; static struct attribute *balloon_info_attrs[] = { diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index e3ff2b9..33b7235 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1208,9 +1208,11 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma, * check for an ELF header. If we find one, dump the first page to * aid in determining what was mapped here. */ - if (FILTER(ELF_HEADERS) && vma->vm_file != NULL && vma->vm_pgoff == 0) { + if (FILTER(ELF_HEADERS) && + vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ)) { u32 __user *header = (u32 __user *) vma->vm_start; u32 word; + mm_segment_t fs = get_fs(); /* * Doing it this way gets the constant folded by GCC. */ @@ -1223,7 +1225,15 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma, magic.elfmag[EI_MAG1] = ELFMAG1; magic.elfmag[EI_MAG2] = ELFMAG2; magic.elfmag[EI_MAG3] = ELFMAG3; - if (get_user(word, header) == 0 && word == magic.cmp) + /* + * Switch to the user "segment" for get_user(), + * then put back what elf_core_dump() had in place. + */ + set_fs(USER_DS); + if (unlikely(get_user(word, header))) + word = 0; + set_fs(fs); + if (word == magic.cmp) return PAGE_SIZE; } diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig index f8fcf99..7bb3c02 100644 --- a/fs/btrfs/Kconfig +++ b/fs/btrfs/Kconfig @@ -16,3 +16,16 @@ config BTRFS_FS module will be called btrfs. If unsure, say N. + +config BTRFS_FS_POSIX_ACL + bool "Btrfs POSIX Access Control Lists" + depends on BTRFS_FS + select FS_POSIX_ACL + help + POSIX Access Control Lists (ACLs) support permissions for users and + groups beyond the owner/group/world scheme. + + To learn more about Access Control Lists, visit the POSIX ACLs for + Linux website <http://acl.bestbits.at/>. + + If you don't know what Access Control Lists are, say N diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index 8e2fec0..c84ca1f 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c @@ -16,11 +16,11 @@ * Boston, MA 021110-1307, USA. */ -#include <linux/version.h> #include <linux/kthread.h> #include <linux/list.h> #include <linux/spinlock.h> -# include <linux/freezer.h> +#include <linux/freezer.h> +#include <linux/ftrace.h> #include "async-thread.h" #define WORK_QUEUED_BIT 0 @@ -143,6 +143,7 @@ static int worker_loop(void *arg) struct btrfs_work *work; do { spin_lock_irq(&worker->lock); +again_locked: while (!list_empty(&worker->pending)) { cur = worker->pending.next; work = list_entry(cur, struct btrfs_work, list); @@ -165,14 +166,50 @@ static int worker_loop(void *arg) check_idle_worker(worker); } - worker->working = 0; if (freezing(current)) { + worker->working = 0; + spin_unlock_irq(&worker->lock); refrigerator(); } else { - set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irq(&worker->lock); - if (!kthread_should_stop()) + if (!kthread_should_stop()) { + cpu_relax(); + /* + * we've dropped the lock, did someone else + * jump_in? + */ + smp_mb(); + if (!list_empty(&worker->pending)) + continue; + + /* + * this short schedule allows more work to + * come in without the queue functions + * needing to go through wake_up_process() + * + * worker->working is still 1, so nobody + * is going to try and wake us up + */ + schedule_timeout(1); + smp_mb(); + if (!list_empty(&worker->pending)) + continue; + + /* still no more work?, sleep for real */ + spin_lock_irq(&worker->lock); + set_current_state(TASK_INTERRUPTIBLE); + if (!list_empty(&worker->pending)) + goto again_locked; + + /* + * this makes sure we get a wakeup when someone + * adds something new to the queue + */ + worker->working = 0; + spin_unlock_irq(&worker->lock); + schedule(); + } __set_current_state(TASK_RUNNING); } } while (!kthread_should_stop()); @@ -350,13 +387,14 @@ int btrfs_requeue_work(struct btrfs_work *work) { struct btrfs_worker_thread *worker = work->worker; unsigned long flags; + int wake = 0; if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags)) goto out; spin_lock_irqsave(&worker->lock, flags); - atomic_inc(&worker->num_pending); list_add_tail(&work->list, &worker->pending); + atomic_inc(&worker->num_pending); /* by definition we're busy, take ourselves off the idle * list @@ -368,10 +406,16 @@ int btrfs_requeue_work(struct btrfs_work *work) &worker->workers->worker_list); spin_unlock_irqrestore(&worker->workers->lock, flags); } + if (!worker->working) { + wake = 1; + worker->working = 1; + } spin_unlock_irqrestore(&worker->lock, flags); - + if (wake) + wake_up_process(worker->task); out: + return 0; } @@ -398,9 +442,10 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work) } spin_lock_irqsave(&worker->lock, flags); + + list_add_tail(&work->list, &worker->pending); atomic_inc(&worker->num_pending); check_busy_worker(worker); - list_add_tail(&work->list, &worker->pending); /* * avoid calling into wake_up_process if this thread has already diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index ee848d8..ab07627 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -32,7 +32,6 @@ #include <linux/swap.h> #include <linux/writeback.h> #include <linux/bit_spinlock.h> -#include <linux/version.h> #include <linux/pagevec.h> #include "compat.h" #include "ctree.h" diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 9e46c07..551177c 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -54,6 +54,31 @@ struct btrfs_path *btrfs_alloc_path(void) return path; } +/* + * set all locked nodes in the path to blocking locks. This should + * be done before scheduling + */ +noinline void btrfs_set_path_blocking(struct btrfs_path *p) +{ + int i; + for (i = 0; i < BTRFS_MAX_LEVEL; i++) { + if (p->nodes[i] && p->locks[i]) + btrfs_set_lock_blocking(p->nodes[i]); + } +} + +/* + * reset all the locked nodes in the patch to spinning locks. + */ +noinline void btrfs_clear_path_blocking(struct btrfs_path *p) +{ + int i; + for (i = 0; i < BTRFS_MAX_LEVEL; i++) { + if (p->nodes[i] && p->locks[i]) + btrfs_clear_lock_blocking(p->nodes[i]); + } +} + /* this also releases the path */ void btrfs_free_path(struct btrfs_path *p) { @@ -272,6 +297,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, if (IS_ERR(cow)) return PTR_ERR(cow); + /* cow is set to blocking by btrfs_init_new_buffer */ + copy_extent_buffer(cow, buf, 0, 0, cow->len); btrfs_set_header_bytenr(cow, cow->start); btrfs_set_header_generation(cow, trans->transid); @@ -388,17 +415,20 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans, WARN_ON(1); } - spin_lock(&root->fs_info->hash_lock); if (btrfs_header_generation(buf) == trans->transid && btrfs_header_owner(buf) == root->root_key.objectid && !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { *cow_ret = buf; - spin_unlock(&root->fs_info->hash_lock); WARN_ON(prealloc_dest); return 0; } - spin_unlock(&root->fs_info->hash_lock); + search_start = buf->start & ~((u64)(1024 * 1024 * 1024) - 1); + + if (parent) + btrfs_set_lock_blocking(parent); + btrfs_set_lock_blocking(buf); + ret = __btrfs_cow_block(trans, root, buf, parent, parent_slot, cow_ret, search_start, 0, prealloc_dest); @@ -504,6 +534,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, if (parent_nritems == 1) return 0; + btrfs_set_lock_blocking(parent); + for (i = start_slot; i < end_slot; i++) { int close = 1; @@ -564,6 +596,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, search_start = last_block; btrfs_tree_lock(cur); + btrfs_set_lock_blocking(cur); err = __btrfs_cow_block(trans, root, cur, parent, i, &cur, search_start, min(16 * blocksize, @@ -862,6 +895,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, return 0; mid = path->nodes[level]; + WARN_ON(!path->locks[level]); WARN_ON(btrfs_header_generation(mid) != trans->transid); @@ -884,6 +918,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, /* promote the child to a root */ child = read_node_slot(root, mid, 0); btrfs_tree_lock(child); + btrfs_set_lock_blocking(child); BUG_ON(!child); ret = btrfs_cow_block(trans, root, child, mid, 0, &child, 0); BUG_ON(ret); @@ -900,6 +935,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, add_root_to_dirty_list(root); btrfs_tree_unlock(child); + path->locks[level] = 0; path->nodes[level] = NULL; clean_tree_block(trans, root, mid); @@ -924,6 +960,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, left = read_node_slot(root, parent, pslot - 1); if (left) { btrfs_tree_lock(left); + btrfs_set_lock_blocking(left); wret = btrfs_cow_block(trans, root, left, parent, pslot - 1, &left, 0); if (wret) { @@ -934,6 +971,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, right = read_node_slot(root, parent, pslot + 1); if (right) { btrfs_tree_lock(right); + btrfs_set_lock_blocking(right); wret = btrfs_cow_block(trans, root, right, parent, pslot + 1, &right, 0); if (wret) { @@ -1109,6 +1147,8 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, u32 left_nr; btrfs_tree_lock(left); + btrfs_set_lock_blocking(left); + left_nr = btrfs_header_nritems(left); if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { wret = 1; @@ -1155,7 +1195,10 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, */ if (right) { u32 right_nr; + btrfs_tree_lock(right); + btrfs_set_lock_blocking(right); + right_nr = btrfs_header_nritems(right); if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { wret = 1; @@ -1210,8 +1253,7 @@ static noinline void reada_for_search(struct btrfs_root *root, struct btrfs_disk_key disk_key; u32 nritems; u64 search; - u64 lowest_read; - u64 highest_read; + u64 target; u64 nread = 0; int direction = path->reada; struct extent_buffer *eb; @@ -1235,8 +1277,7 @@ static noinline void reada_for_search(struct btrfs_root *root, return; } - highest_read = search; - lowest_read = search; + target = search; nritems = btrfs_header_nritems(node); nr = slot; @@ -1256,27 +1297,80 @@ static noinline void reada_for_search(struct btrfs_root *root, break; } search = btrfs_node_blockptr(node, nr); - if ((search >= lowest_read && search <= highest_read) || - (search < lowest_read && lowest_read - search <= 16384) || - (search > highest_read && search - highest_read <= 16384)) { + if ((search <= target && target - search <= 65536) || + (search > target && search - target <= 65536)) { readahead_tree_block(root, search, blocksize, btrfs_node_ptr_generation(node, nr)); nread += blocksize; } nscan++; - if (path->reada < 2 && (nread > (64 * 1024) || nscan > 32)) + if ((nread > 65536 || nscan > 32)) break; + } +} - if (nread > (256 * 1024) || nscan > 128) - break; +/* + * returns -EAGAIN if it had to drop the path, or zero if everything was in + * cache + */ +static noinline int reada_for_balance(struct btrfs_root *root, + struct btrfs_path *path, int level) +{ + int slot; + int nritems; + struct extent_buffer *parent; + struct extent_buffer *eb; + u64 gen; + u64 block1 = 0; + u64 block2 = 0; + int ret = 0; + int blocksize; - if (search < lowest_read) - lowest_read = search; - if (search > highest_read) - highest_read = search; + parent = path->nodes[level - 1]; + if (!parent) + return 0; + + nritems = btrfs_header_nritems(parent); + slot = path->slots[level]; + blocksize = btrfs_level_size(root, level); + + if (slot > 0) { + block1 = btrfs_node_blockptr(parent, slot - 1); + gen = btrfs_node_ptr_generation(parent, slot - 1); + eb = btrfs_find_tree_block(root, block1, blocksize); + if (eb && btrfs_buffer_uptodate(eb, gen)) + block1 = 0; + free_extent_buffer(eb); + } + if (slot < nritems) { + block2 = btrfs_node_blockptr(parent, slot + 1); + gen = btrfs_node_ptr_generation(parent, slot + 1); + eb = btrfs_find_tree_block(root, block2, blocksize); + if (eb && btrfs_buffer_uptodate(eb, gen)) + block2 = 0; + free_extent_buffer(eb); + } + if (block1 || block2) { + ret = -EAGAIN; + btrfs_release_path(root, path); + if (block1) + readahead_tree_block(root, block1, blocksize, 0); + if (block2) + readahead_tree_block(root, block2, blocksize, 0); + + if (block1) { + eb = read_tree_block(root, block1, blocksize, 0); + free_extent_buffer(eb); + } + if (block1) { + eb = read_tree_block(root, block2, blocksize, 0); + free_extent_buffer(eb); + } } + return ret; } + /* * when we walk down the tree, it is usually safe to unlock the higher layers * in the tree. The exceptions are when our path goes through slot 0, because @@ -1328,6 +1422,32 @@ static noinline void unlock_up(struct btrfs_path *path, int level, } /* + * This releases any locks held in the path starting at level and + * going all the way up to the root. + * + * btrfs_search_slot will keep the lock held on higher nodes in a few + * corner cases, such as COW of the block at slot zero in the node. This + * ignores those rules, and it should only be called when there are no + * more updates to be done higher up in the tree. + */ +noinline void btrfs_unlock_up_safe(struct btrfs_path *path, int level) +{ + int i; + + if (path->keep_locks || path->lowest_level) + return; + + for (i = level; i < BTRFS_MAX_LEVEL; i++) { + if (!path->nodes[i]) + continue; + if (!path->locks[i]) + continue; + btrfs_tree_unlock(path->nodes[i]); + path->locks[i] = 0; + } +} + +/* * look for key in the tree. path is filled in with nodes along the way * if key is found, we return zero and you can find the item in the leaf * level of the path (level 0) @@ -1387,31 +1507,30 @@ again: int wret; /* is a cow on this block not required */ - spin_lock(&root->fs_info->hash_lock); if (btrfs_header_generation(b) == trans->transid && btrfs_header_owner(b) == root->root_key.objectid && !btrfs_header_flag(b, BTRFS_HEADER_FLAG_WRITTEN)) { - spin_unlock(&root->fs_info->hash_lock); goto cow_done; } - spin_unlock(&root->fs_info->hash_lock); /* ok, we have to cow, is our old prealloc the right * size? */ if (prealloc_block.objectid && prealloc_block.offset != b->len) { + btrfs_release_path(root, p); btrfs_free_reserved_extent(root, prealloc_block.objectid, prealloc_block.offset); prealloc_block.objectid = 0; + goto again; } /* * for higher level blocks, try not to allocate blocks * with the block and the parent locks held. */ - if (level > 1 && !prealloc_block.objectid && + if (level > 0 && !prealloc_block.objectid && btrfs_path_lock_waiting(p, level)) { u32 size = b->len; u64 hint = b->start; @@ -1425,6 +1544,8 @@ again: goto again; } + btrfs_set_path_blocking(p); + wret = btrfs_cow_block(trans, root, b, p->nodes[level + 1], p->slots[level + 1], @@ -1446,6 +1567,22 @@ cow_done: if (!p->skip_locking) p->locks[level] = 1; + btrfs_clear_path_blocking(p); + + /* + * we have a lock on b and as long as we aren't changing + * the tree, there is no way to for the items in b to change. + * It is safe to drop the lock on our parent before we + * go through the expensive btree search on b. + * + * If cow is true, then we might be changing slot zero, + * which may require changing the parent. So, we can't + * drop the lock until after we know which slot we're + * operating on. + */ + if (!cow) + btrfs_unlock_up_safe(p, level + 1); + ret = check_block(root, p, level); if (ret) { ret = -1; @@ -1453,6 +1590,7 @@ cow_done: } ret = bin_search(b, key, level, &slot); + if (level != 0) { if (ret && slot > 0) slot -= 1; @@ -1460,7 +1598,16 @@ cow_done: if ((p->search_for_split || ins_len > 0) && btrfs_header_nritems(b) >= BTRFS_NODEPTRS_PER_BLOCK(root) - 3) { - int sret = split_node(trans, root, p, level); + int sret; + + sret = reada_for_balance(root, p, level); + if (sret) + goto again; + + btrfs_set_path_blocking(p); + sret = split_node(trans, root, p, level); + btrfs_clear_path_blocking(p); + BUG_ON(sret > 0); if (sret) { ret = sret; @@ -1468,9 +1615,19 @@ cow_done: } b = p->nodes[level]; slot = p->slots[level]; - } else if (ins_len < 0) { - int sret = balance_level(trans, root, p, - level); + } else if (ins_len < 0 && + btrfs_header_nritems(b) < + BTRFS_NODEPTRS_PER_BLOCK(root) / 4) { + int sret; + + sret = reada_for_balance(root, p, level); + if (sret) + goto again; + + btrfs_set_path_blocking(p); + sret = balance_level(trans, root, p, level); + btrfs_clear_path_blocking(p); + if (sret) { ret = sret; goto done; @@ -1504,7 +1661,7 @@ cow_done: * of the btree by dropping locks before * we read. */ - if (level > 1) { + if (level > 0) { btrfs_release_path(NULL, p); if (tmp) free_extent_buffer(tmp); @@ -1519,6 +1676,7 @@ cow_done: free_extent_buffer(tmp); goto again; } else { + btrfs_set_path_blocking(p); if (tmp) free_extent_buffer(tmp); if (should_reada) @@ -1528,14 +1686,29 @@ cow_done: b = read_node_slot(root, b, slot); } } - if (!p->skip_locking) - btrfs_tree_lock(b); + if (!p->skip_locking) { + int lret; + + btrfs_clear_path_blocking(p); + lret = btrfs_try_spin_lock(b); + + if (!lret) { + btrfs_set_path_blocking(p); + btrfs_tree_lock(b); + btrfs_clear_path_blocking(p); + } + } } else { p->slots[level] = slot; if (ins_len > 0 && btrfs_leaf_free_space(root, b) < ins_len) { - int sret = split_leaf(trans, root, key, + int sret; + + btrfs_set_path_blocking(p); + sret = split_leaf(trans, root, key, p, ins_len, ret == 0); + btrfs_clear_path_blocking(p); + BUG_ON(sret > 0); if (sret) { ret = sret; @@ -1549,12 +1722,16 @@ cow_done: } ret = 1; done: + /* + * we don't really know what they plan on doing with the path + * from here on, so for now just mark it as blocking + */ + btrfs_set_path_blocking(p); if (prealloc_block.objectid) { btrfs_free_reserved_extent(root, prealloc_block.objectid, prealloc_block.offset); } - return ret; } @@ -1578,6 +1755,8 @@ int btrfs_merge_path(struct btrfs_trans_handle *trans, ret = btrfs_cow_block(trans, root, eb, NULL, 0, &eb, 0); BUG_ON(ret); + btrfs_set_lock_blocking(eb); + parent = eb; while (1) { level = btrfs_header_level(parent); @@ -1602,6 +1781,7 @@ int btrfs_merge_path(struct btrfs_trans_handle *trans, eb = read_tree_block(root, bytenr, blocksize, generation); btrfs_tree_lock(eb); + btrfs_set_lock_blocking(eb); } /* @@ -1626,6 +1806,7 @@ int btrfs_merge_path(struct btrfs_trans_handle *trans, eb = read_tree_block(root, bytenr, blocksize, generation); btrfs_tree_lock(eb); + btrfs_set_lock_blocking(eb); } ret = btrfs_cow_block(trans, root, eb, parent, slot, @@ -2172,6 +2353,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root right = read_node_slot(root, upper, slot + 1); btrfs_tree_lock(right); + btrfs_set_lock_blocking(right); + free_space = btrfs_leaf_free_space(root, right); if (free_space < data_size) goto out_unlock; @@ -2367,6 +2550,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root left = read_node_slot(root, path->nodes[1], slot - 1); btrfs_tree_lock(left); + btrfs_set_lock_blocking(left); + free_space = btrfs_leaf_free_space(root, left); if (free_space < data_size) { ret = 1; @@ -2825,6 +3010,12 @@ int btrfs_split_item(struct btrfs_trans_handle *trans, path->keep_locks = 0; BUG_ON(ret); + /* + * make sure any changes to the path from split_leaf leave it + * in a blocking state + */ + btrfs_set_path_blocking(path); + leaf = path->nodes[0]; BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item)); @@ -3354,6 +3545,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans, BUG(); } out: + btrfs_unlock_up_safe(path, 1); return ret; } @@ -3441,15 +3633,22 @@ noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans, { int ret; u64 root_gen = btrfs_header_generation(path->nodes[1]); + u64 parent_start = path->nodes[1]->start; + u64 parent_owner = btrfs_header_owner(path->nodes[1]); ret = del_ptr(trans, root, path, 1, path->slots[1]); if (ret) return ret; + /* + * btrfs_free_extent is expensive, we want to make sure we + * aren't holding any locks when we call it + */ + btrfs_unlock_up_safe(path, 0); + ret = btrfs_free_extent(trans, root, bytenr, btrfs_level_size(root, 0), - path->nodes[1]->start, - btrfs_header_owner(path->nodes[1]), + parent_start, parent_owner, root_gen, 0, 1); return ret; } @@ -3721,12 +3920,14 @@ find_next_key: */ if (slot >= nritems) { path->slots[level] = slot; + btrfs_set_path_blocking(path); sret = btrfs_find_next_key(root, path, min_key, level, cache_only, min_trans); if (sret == 0) { btrfs_release_path(root, path); goto again; } else { + btrfs_clear_path_blocking(path); goto out; } } @@ -3738,16 +3939,20 @@ find_next_key: unlock_up(path, level, 1); goto out; } + btrfs_set_path_blocking(path); cur = read_node_slot(root, cur, slot); btrfs_tree_lock(cur); + path->locks[level - 1] = 1; path->nodes[level - 1] = cur; unlock_up(path, level, 1); + btrfs_clear_path_blocking(path); } out: if (ret == 0) memcpy(min_key, &found_key, sizeof(found_key)); + btrfs_set_path_blocking(path); return ret; } @@ -3843,6 +4048,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) if (ret < 0) return ret; + btrfs_set_path_blocking(path); nritems = btrfs_header_nritems(path->nodes[0]); /* * by releasing the path above we dropped all our locks. A balance @@ -3873,6 +4079,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) free_extent_buffer(next); } + /* the path was set to blocking above */ if (level == 1 && (path->locks[1] || path->skip_locking) && path->reada) reada_for_search(root, path, level, slot, 0); @@ -3881,6 +4088,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) if (!path->skip_locking) { WARN_ON(!btrfs_tree_locked(c)); btrfs_tree_lock(next); + btrfs_set_lock_blocking(next); } break; } @@ -3897,12 +4105,15 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) path->locks[level] = 1; if (!level) break; + + btrfs_set_path_blocking(path); if (level == 1 && path->locks[1] && path->reada) reada_for_search(root, path, level, slot, 0); next = read_node_slot(root, next, 0); if (!path->skip_locking) { WARN_ON(!btrfs_tree_locked(path->nodes[level])); btrfs_tree_lock(next); + btrfs_set_lock_blocking(next); } } done: @@ -3927,6 +4138,7 @@ int btrfs_previous_item(struct btrfs_root *root, while (1) { if (path->slots[0] == 0) { + btrfs_set_path_blocking(path); ret = btrfs_prev_leaf(root, path); if (ret != 0) return ret; diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index eee060f..531db11 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -454,17 +454,11 @@ struct btrfs_timespec { __le32 nsec; } __attribute__ ((__packed__)); -typedef enum { +enum btrfs_compression_type { BTRFS_COMPRESS_NONE = 0, BTRFS_COMPRESS_ZLIB = 1, BTRFS_COMPRESS_LAST = 2, -} btrfs_compression_type; - -/* we don't understand any encryption methods right now */ -typedef enum { - BTRFS_ENCRYPTION_NONE = 0, - BTRFS_ENCRYPTION_LAST = 1, -} btrfs_encryption_type; +}; struct btrfs_inode_item { /* nfs style generation number */ @@ -701,9 +695,7 @@ struct btrfs_fs_info { struct btrfs_transaction *running_transaction; wait_queue_head_t transaction_throttle; wait_queue_head_t transaction_wait; - wait_queue_head_t async_submit_wait; - wait_queue_head_t tree_log_wait; struct btrfs_super_block super_copy; struct btrfs_super_block super_for_commit; @@ -711,7 +703,6 @@ struct btrfs_fs_info { struct super_block *sb; struct inode *btree_inode; struct backing_dev_info bdi; - spinlock_t hash_lock; struct mutex trans_mutex; struct mutex tree_log_mutex; struct mutex transaction_kthread_mutex; @@ -730,10 +721,6 @@ struct btrfs_fs_info { atomic_t async_submit_draining; atomic_t nr_async_bios; atomic_t async_delalloc_pages; - atomic_t tree_log_writers; - atomic_t tree_log_commit; - unsigned long tree_log_batch; - u64 tree_log_transid; /* * this is used by the balancing code to wait for all the pending @@ -833,7 +820,14 @@ struct btrfs_root { struct kobject root_kobj; struct completion kobj_unregister; struct mutex objectid_mutex; + struct mutex log_mutex; + wait_queue_head_t log_writer_wait; + wait_queue_head_t log_commit_wait[2]; + atomic_t log_writers; + atomic_t log_commit[2]; + unsigned long log_transid; + unsigned long log_batch; u64 objectid; u64 last_trans; @@ -1841,6 +1835,10 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p); struct btrfs_path *btrfs_alloc_path(void); void btrfs_free_path(struct btrfs_path *p); void btrfs_init_path(struct btrfs_path *p); +void btrfs_set_path_blocking(struct btrfs_path *p); +void btrfs_clear_path_blocking(struct btrfs_path *p); +void btrfs_unlock_up_safe(struct btrfs_path *p, int level); + int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int slot, int nr); int btrfs_del_leaf(struct btrfs_trans_handle *trans, diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 81a3138..5aebddd 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -16,7 +16,6 @@ * Boston, MA 021110-1307, USA. */ -#include <linux/version.h> #include <linux/fs.h> #include <linux/blkdev.h> #include <linux/scatterlist.h> @@ -800,7 +799,7 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid); if (ret == 0) - buf->flags |= EXTENT_UPTODATE; + set_bit(EXTENT_BUFFER_UPTODATE, &buf->bflags); else WARN_ON(1); return buf; @@ -814,6 +813,10 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, if (btrfs_header_generation(buf) == root->fs_info->running_transaction->transid) { WARN_ON(!btrfs_tree_locked(buf)); + + /* ugh, clear_extent_buffer_dirty can be expensive */ + btrfs_set_lock_blocking(buf); + clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree, buf); } @@ -850,6 +853,14 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, spin_lock_init(&root->list_lock); mutex_init(&root->objectid_mutex); mutex_init(&root->log_mutex); + init_waitqueue_head(&root->log_writer_wait); + init_waitqueue_head(&root->log_commit_wait[0]); + init_waitqueue_head(&root->log_commit_wait[1]); + atomic_set(&root->log_commit[0], 0); + atomic_set(&root->log_commit[1], 0); + atomic_set(&root->log_writers, 0); + root->log_batch = 0; + root->log_transid = 0; extent_io_tree_init(&root->dirty_log_pages, fs_info->btree_inode->i_mapping, GFP_NOFS); @@ -934,15 +945,16 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans, return 0; } -int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, - struct btrfs_fs_info *fs_info) +static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info) { struct btrfs_root *root; struct btrfs_root *tree_root = fs_info->tree_root; + struct extent_buffer *leaf; root = kzalloc(sizeof(*root), GFP_NOFS); if (!root) - return -ENOMEM; + return ERR_PTR(-ENOMEM); __setup_root(tree_root->nodesize, tree_root->leafsize, tree_root->sectorsize, tree_root->stripesize, @@ -951,12 +963,23 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, root->root_key.objectid = BTRFS_TREE_LOG_OBJECTID; root->root_key.type = BTRFS_ROOT_ITEM_KEY; root->root_key.offset = BTRFS_TREE_LOG_OBJECTID; + /* + * log trees do not get reference counted because they go away + * before a real commit is actually done. They do store pointers + * to file data extents, and those reference counts still get + * updated (along with back refs to the log tree). + */ root->ref_cows = 0; - root->node = btrfs_alloc_free_block(trans, root, root->leafsize, - 0, BTRFS_TREE_LOG_OBJECTID, - trans->transid, 0, 0, 0); + leaf = btrfs_alloc_free_block(trans, root, root->leafsize, + 0, BTRFS_TREE_LOG_OBJECTID, + trans->transid, 0, 0, 0); + if (IS_ERR(leaf)) { + kfree(root); + return ERR_CAST(leaf); + } + root->node = leaf; btrfs_set_header_nritems(root->node, 0); btrfs_set_header_level(root->node, 0); btrfs_set_header_bytenr(root->node, root->node->start); @@ -968,7 +991,48 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, BTRFS_FSID_SIZE); btrfs_mark_buffer_dirty(root->node); btrfs_tree_unlock(root->node); - fs_info->log_root_tree = root; + return root; +} + +int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info) +{ + struct btrfs_root *log_root; + + log_root = alloc_log_tree(trans, fs_info); + if (IS_ERR(log_root)) + return PTR_ERR(log_root); + WARN_ON(fs_info->log_root_tree); + fs_info->log_root_tree = log_root; + return 0; +} + +int btrfs_add_log_tree(struct btrfs_trans_handle *trans, + struct btrfs_root *root) +{ + struct btrfs_root *log_root; + struct btrfs_inode_item *inode_item; + + log_root = alloc_log_tree(trans, root->fs_info); + if (IS_ERR(log_root)) + return PTR_ERR(log_root); + + log_root->last_trans = trans->transid; + log_root->root_key.offset = root->root_key.objectid; + + inode_item = &log_root->root_item.inode; + inode_item->generation = cpu_to_le64(1); + inode_item->size = cpu_to_le64(3); + inode_item->nlink = cpu_to_le32(1); + inode_item->nbytes = cpu_to_le64(root->leafsize); + inode_item->mode = cpu_to_le32(S_IFDIR | 0755); + + btrfs_set_root_bytenr(&log_root->root_item, log_root->node->start); + btrfs_set_root_generation(&log_root->root_item, trans->transid); + + WARN_ON(root->log_root); + root->log_root = log_root; + root->log_transid = 0; return 0; } @@ -1136,7 +1200,6 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits) { struct btrfs_fs_info *info = (struct btrfs_fs_info *)congested_data; int ret = 0; - struct list_head *cur; struct btrfs_device *device; struct backing_dev_info *bdi; #if 0 @@ -1144,8 +1207,7 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits) btrfs_congested_async(info, 0)) return 1; #endif - list_for_each(cur, &info->fs_devices->devices) { - device = list_entry(cur, struct btrfs_device, dev_list); + list_for_each_entry(device, &info->fs_devices->devices, dev_list) { if (!device->bdev) continue; bdi = blk_get_backing_dev_info(device->bdev); @@ -1163,13 +1225,11 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits) */ static void __unplug_io_fn(struct backing_dev_info *bdi, struct page *page) { - struct list_head *cur; struct btrfs_device *device; struct btrfs_fs_info *info; info = (struct btrfs_fs_info *)bdi->unplug_io_data; - list_for_each(cur, &info->fs_devices->devices) { - device = list_entry(cur, struct btrfs_device, dev_list); + list_for_each_entry(device, &info->fs_devices->devices, dev_list) { if (!device->bdev) continue; @@ -1447,7 +1507,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, INIT_LIST_HEAD(&fs_info->dead_roots); INIT_LIST_HEAD(&fs_info->hashers); INIT_LIST_HEAD(&fs_info->delalloc_inodes); - spin_lock_init(&fs_info->hash_lock); spin_lock_init(&fs_info->delalloc_lock); spin_lock_init(&fs_info->new_trans_lock); spin_lock_init(&fs_info->ref_cache_lock); @@ -1535,10 +1594,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, init_waitqueue_head(&fs_info->transaction_throttle); init_waitqueue_head(&fs_info->transaction_wait); init_waitqueue_head(&fs_info->async_submit_wait); - init_waitqueue_head(&fs_info->tree_log_wait); - atomic_set(&fs_info->tree_log_commit, 0); - atomic_set(&fs_info->tree_log_writers, 0); - fs_info->tree_log_transid = 0; __setup_root(4096, 4096, 4096, 4096, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID); @@ -1627,6 +1682,8 @@ struct btrfs_root *open_ctree(struct super_block *sb, * low idle thresh */ fs_info->endio_workers.idle_thresh = 4; + fs_info->endio_meta_workers.idle_thresh = 4; + fs_info->endio_write_workers.idle_thresh = 64; fs_info->endio_meta_write_workers.idle_thresh = 64; @@ -1740,13 +1797,13 @@ struct btrfs_root *open_ctree(struct super_block *sb, fs_info->system_alloc_profile = fs_info->metadata_alloc_profile; fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root, "btrfs-cleaner"); - if (!fs_info->cleaner_kthread) + if (IS_ERR(fs_info->cleaner_kthread)) goto fail_csum_root; fs_info->transaction_kthread = kthread_run(transaction_kthread, tree_root, "btrfs-transaction"); - if (!fs_info->transaction_kthread) + if (IS_ERR(fs_info->transaction_kthread)) goto fail_cleaner; if (btrfs_super_log_root(disk_super) != 0) { @@ -1828,13 +1885,14 @@ fail_sb_buffer: fail_iput: invalidate_inode_pages2(fs_info->btree_inode->i_mapping); iput(fs_info->btree_inode); -fail: + btrfs_close_devices(fs_info->fs_devices); btrfs_mapping_tree_free(&fs_info->mapping_tree); + bdi_destroy(&fs_info->bdi); +fail: kfree(extent_root); kfree(tree_root); - bdi_destroy(&fs_info->bdi); kfree(fs_info); kfree(chunk_root); kfree(dev_root); @@ -1995,7 +2053,6 @@ static int write_dev_supers(struct btrfs_device *device, int write_all_supers(struct btrfs_root *root, int max_mirrors) { - struct list_head *cur; struct list_head *head = &root->fs_info->fs_devices->devices; struct btrfs_device *dev; struct btrfs_super_block *sb; @@ -2011,8 +2068,7 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors) sb = &root->fs_info->super_for_commit; dev_item = &sb->dev_item; - list_for_each(cur, head) { - dev = list_entry(cur, struct btrfs_device, dev_list); + list_for_each_entry(dev, head, dev_list) { if (!dev->bdev) { total_errors++; continue; @@ -2045,8 +2101,7 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors) } total_errors = 0; - list_for_each(cur, head) { - dev = list_entry(cur, struct btrfs_device, dev_list); + list_for_each_entry(dev, head, dev_list) { if (!dev->bdev) continue; if (!dev->in_fs_metadata || !dev->writeable) @@ -2260,6 +2315,8 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf) u64 transid = btrfs_header_generation(buf); struct inode *btree_inode = root->fs_info->btree_inode; + btrfs_set_lock_blocking(buf); + WARN_ON(!btrfs_tree_locked(buf)); if (transid != root->fs_info->generation) { printk(KERN_CRIT "btrfs transid mismatch buffer %llu, " @@ -2302,14 +2359,13 @@ int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid) int ret; ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid); if (ret == 0) - buf->flags |= EXTENT_UPTODATE; + set_bit(EXTENT_BUFFER_UPTODATE, &buf->bflags); return ret; } int btree_lock_page_hook(struct page *page) { struct inode *inode = page->mapping->host; - struct btrfs_root *root = BTRFS_I(inode)->root; struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; struct extent_buffer *eb; unsigned long len; @@ -2324,9 +2380,7 @@ int btree_lock_page_hook(struct page *page) goto out; btrfs_tree_lock(eb); - spin_lock(&root->fs_info->hash_lock); btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); - spin_unlock(&root->fs_info->hash_lock); btrfs_tree_unlock(eb); free_extent_buffer(eb); out: diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index c0ff404..494a56e 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h @@ -98,5 +98,7 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info); int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info); +int btrfs_add_log_tree(struct btrfs_trans_handle *trans, + struct btrfs_root *root); int btree_lock_page_hook(struct page *page); #endif diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 293da65..7527523 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -19,7 +19,7 @@ #include <linux/pagemap.h> #include <linux/writeback.h> #include <linux/blkdev.h> -#include <linux/version.h> +#include <linux/sort.h> #include "compat.h" #include "hash.h" #include "crc32c.h" @@ -30,7 +30,6 @@ #include "volumes.h" #include "locking.h" #include "ref-cache.h" -#include "compat.h" #define PENDING_EXTENT_INSERT 0 #define PENDING_EXTENT_DELETE 1 @@ -326,10 +325,8 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info, u64 flags) { struct list_head *head = &info->space_info; - struct list_head *cur; struct btrfs_space_info *found; - list_for_each(cur, head) { - found = list_entry(cur, struct btrfs_space_info, list); + list_for_each_entry(found, head, list) { if (found->flags == flags) return found; } @@ -1525,15 +1522,55 @@ out: return ret; } -int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, - struct extent_buffer *orig_buf, struct extent_buffer *buf, - u32 *nr_extents) +/* when a block goes through cow, we update the reference counts of + * everything that block points to. The internal pointers of the block + * can be in just about any order, and it is likely to have clusters of + * things that are close together and clusters of things that are not. + * + * To help reduce the seeks that come with updating all of these reference + * counts, sort them by byte number before actual updates are done. + * + * struct refsort is used to match byte number to slot in the btree block. + * we sort based on the byte number and then use the slot to actually + * find the item. + * + * struct refsort is smaller than strcut btrfs_item and smaller than + * struct btrfs_key_ptr. Since we're currently limited to the page size + * for a btree block, there's no way for a kmalloc of refsorts for a + * single node to be bigger than a page. + */ +struct refsort { + u64 bytenr; + u32 slot; +}; + +/* + * for passing into sort() + */ +static int refsort_cmp(const void *a_void, const void *b_void) +{ + const struct refsort *a = a_void; + const struct refsort *b = b_void; + + if (a->bytenr < b->bytenr) + return -1; + if (a->bytenr > b->bytenr) + return 1; + return 0; +} + + +noinline int btrfs_inc_ref(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct extent_buffer *orig_buf, + struct extent_buffer *buf, u32 *nr_extents) { u64 bytenr; u64 ref_root; u64 orig_root; u64 ref_generation; u64 orig_generation; + struct refsort *sorted; u32 nritems; u32 nr_file_extents = 0; struct btrfs_key key; @@ -1542,6 +1579,8 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, int level; int ret = 0; int faili = 0; + int refi = 0; + int slot; int (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *, u64, u64, u64, u64, u64, u64, u64, u64); @@ -1553,6 +1592,9 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, nritems = btrfs_header_nritems(buf); level = btrfs_header_level(buf); + sorted = kmalloc(sizeof(struct refsort) * nritems, GFP_NOFS); + BUG_ON(!sorted); + if (root->ref_cows) { process_func = __btrfs_inc_extent_ref; } else { @@ -1565,6 +1607,11 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, process_func = __btrfs_update_extent_ref; } + /* + * we make two passes through the items. In the first pass we + * only record the byte number and slot. Then we sort based on + * byte number and do the actual work based on the sorted results + */ for (i = 0; i < nritems; i++) { cond_resched(); if (level == 0) { @@ -1581,6 +1628,32 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, continue; nr_file_extents++; + sorted[refi].bytenr = bytenr; + sorted[refi].slot = i; + refi++; + } else { + bytenr = btrfs_node_blockptr(buf, i); + sorted[refi].bytenr = bytenr; + sorted[refi].slot = i; + refi++; + } + } + /* + * if refi == 0, we didn't actually put anything into the sorted + * array and we're done + */ + if (refi == 0) + goto out; + + sort(sorted, refi, sizeof(struct refsort), refsort_cmp, NULL); + + for (i = 0; i < refi; i++) { + cond_resched(); + slot = sorted[i].slot; + bytenr = sorted[i].bytenr; + + if (level == 0) { + btrfs_item_key_to_cpu(buf, &key, slot); ret = process_func(trans, root, bytenr, orig_buf->start, buf->start, @@ -1589,25 +1662,25 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, key.objectid); if (ret) { - faili = i; + faili = slot; WARN_ON(1); goto fail; } } else { - bytenr = btrfs_node_blockptr(buf, i); ret = process_func(trans, root, bytenr, orig_buf->start, buf->start, orig_root, ref_root, orig_generation, ref_generation, level - 1); if (ret) { - faili = i; + faili = slot; WARN_ON(1); goto fail; } } } out: + kfree(sorted); if (nr_extents) { if (level == 0) *nr_extents = nr_file_extents; @@ -1616,6 +1689,7 @@ out: } return 0; fail: + kfree(sorted); WARN_ON(1); return ret; } @@ -2159,7 +2233,8 @@ again: ret = find_first_extent_bit(&info->extent_ins, search, &start, &end, EXTENT_WRITEBACK); if (ret) { - if (skipped && all && !num_inserts) { + if (skipped && all && !num_inserts && + list_empty(&update_list)) { skipped = 0; search = 0; continue; @@ -2547,6 +2622,7 @@ again: if (ret) { if (all && skipped && !nr) { search = 0; + skipped = 0; continue; } mutex_unlock(&info->extent_ins_mutex); @@ -2700,13 +2776,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, /* if metadata always pin */ if (owner_objectid < BTRFS_FIRST_FREE_OBJECTID) { if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) { - struct btrfs_block_group_cache *cache; - - /* btrfs_free_reserved_extent */ - cache = btrfs_lookup_block_group(root->fs_info, bytenr); - BUG_ON(!cache); - btrfs_add_free_space(cache, bytenr, num_bytes); - put_block_group(cache); + mutex_lock(&root->fs_info->pinned_mutex); + btrfs_update_pinned_extents(root, bytenr, num_bytes, 1); + mutex_unlock(&root->fs_info->pinned_mutex); update_reserved_extents(root, bytenr, num_bytes, 0); return 0; } @@ -3014,7 +3086,6 @@ loop_check: static void dump_space_info(struct btrfs_space_info *info, u64 bytes) { struct btrfs_block_group_cache *cache; - struct list_head *l; printk(KERN_INFO "space_info has %llu free, is %sfull\n", (unsigned long long)(info->total_bytes - info->bytes_used - @@ -3022,8 +3093,7 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes) (info->full) ? "" : "not "); down_read(&info->groups_sem); - list_for_each(l, &info->block_groups) { - cache = list_entry(l, struct btrfs_block_group_cache, list); + list_for_each_entry(cache, &info->block_groups, list) { spin_lock(&cache->lock); printk(KERN_INFO "block group %llu has %llu bytes, %llu used " "%llu pinned %llu reserved\n", @@ -3342,7 +3412,10 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans, btrfs_set_header_generation(buf, trans->transid); btrfs_tree_lock(buf); clean_tree_block(trans, root, buf); + + btrfs_set_lock_blocking(buf); btrfs_set_buffer_uptodate(buf); + if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) { set_extent_dirty(&root->dirty_log_pages, buf->start, buf->start + buf->len - 1, GFP_NOFS); @@ -3351,6 +3424,7 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans, buf->start + buf->len - 1, GFP_NOFS); } trans->blocks_used++; + /* this returns a buffer locked for blocking */ return buf; } @@ -3388,36 +3462,73 @@ int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans, { u64 leaf_owner; u64 leaf_generation; + struct refsort *sorted; struct btrfs_key key; struct btrfs_file_extent_item *fi; int i; int nritems; int ret; + int refi = 0; + int slot; BUG_ON(!btrfs_is_leaf(leaf)); nritems = btrfs_header_nritems(leaf); leaf_owner = btrfs_header_owner(leaf); leaf_generation = btrfs_header_generation(leaf); + sorted = kmalloc(sizeof(*sorted) * nritems, GFP_NOFS); + /* we do this loop twice. The first time we build a list + * of the extents we have a reference on, then we sort the list + * by bytenr. The second time around we actually do the + * extent freeing. + */ for (i = 0; i < nritems; i++) { u64 disk_bytenr; cond_resched(); btrfs_item_key_to_cpu(leaf, &key, i); + + /* only extents have references, skip everything else */ if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY) continue; + fi = btrfs_item_ptr(leaf, i, struct btrfs_file_extent_item); + + /* inline extents live in the btree, they don't have refs */ if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) continue; - /* - * FIXME make sure to insert a trans record that - * repeats the snapshot del on crash - */ + disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); + + /* holes don't have refs */ if (disk_bytenr == 0) continue; + sorted[refi].bytenr = disk_bytenr; + sorted[refi].slot = i; + refi++; + } + + if (refi == 0) + goto out; + + sort(sorted, refi, sizeof(struct refsort), refsort_cmp, NULL); + + for (i = 0; i < refi; i++) { + u64 disk_bytenr; + + disk_bytenr = sorted[i].bytenr; + slot = sorted[i].slot; + + cond_resched(); + + btrfs_item_key_to_cpu(leaf, &key, slot); + if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY) + continue; + + fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); + ret = __btrfs_free_extent(trans, root, disk_bytenr, btrfs_file_extent_disk_num_bytes(leaf, fi), leaf->start, leaf_owner, leaf_generation, @@ -3428,6 +3539,8 @@ int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans, wake_up(&root->fs_info->transaction_throttle); cond_resched(); } +out: + kfree(sorted); return 0; } @@ -3437,9 +3550,25 @@ static noinline int cache_drop_leaf_ref(struct btrfs_trans_handle *trans, { int i; int ret; - struct btrfs_extent_info *info = ref->extents; + struct btrfs_extent_info *info; + struct refsort *sorted; + + if (ref->nritems == 0) + return 0; + sorted = kmalloc(sizeof(*sorted) * ref->nritems, GFP_NOFS); for (i = 0; i < ref->nritems; i++) { + sorted[i].bytenr = ref->extents[i].bytenr; + sorted[i].slot = i; + } + sort(sorted, ref->nritems, sizeof(struct refsort), refsort_cmp, NULL); + + /* + * the items in the ref were sorted when the ref was inserted + * into the ref cache, so this is already in order + */ + for (i = 0; i < ref->nritems; i++) { + info = ref->extents + sorted[i].slot; ret = __btrfs_free_extent(trans, root, info->bytenr, info->num_bytes, ref->bytenr, ref->owner, ref->generation, @@ -3453,6 +3582,7 @@ static noinline int cache_drop_leaf_ref(struct btrfs_trans_handle *trans, info++; } + kfree(sorted); return 0; } @@ -3497,6 +3627,152 @@ static int drop_snap_lookup_refcount(struct btrfs_root *root, u64 start, } /* + * this is used while deleting old snapshots, and it drops the refs + * on a whole subtree starting from a level 1 node. + * + * The idea is to sort all the leaf pointers, and then drop the + * ref on all the leaves in order. Most of the time the leaves + * will have ref cache entries, so no leaf IOs will be required to + * find the extents they have references on. + * + * For each leaf, any references it has are also dropped in order + * + * This ends up dropping the references in something close to optimal + * order for reading and modifying the extent allocation tree. + */ +static noinline int drop_level_one_refs(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path) +{ + u64 bytenr; + u64 root_owner; + u64 root_gen; + struct extent_buffer *eb = path->nodes[1]; + struct extent_buffer *leaf; + struct btrfs_leaf_ref *ref; + struct refsort *sorted = NULL; + int nritems = btrfs_header_nritems(eb); + int ret; + int i; + int refi = 0; + int slot = path->slots[1]; + u32 blocksize = btrfs_level_size(root, 0); + u32 refs; + + if (nritems == 0) + goto out; + + root_owner = btrfs_header_owner(eb); + root_gen = btrfs_header_generation(eb); + sorted = kmalloc(sizeof(*sorted) * nritems, GFP_NOFS); + + /* + * step one, sort all the leaf pointers so we don't scribble + * randomly into the extent allocation tree + */ + for (i = slot; i < nritems; i++) { + sorted[refi].bytenr = btrfs_node_blockptr(eb, i); + sorted[refi].slot = i; + refi++; + } + + /* + * nritems won't be zero, but if we're picking up drop_snapshot + * after a crash, slot might be > 0, so double check things + * just in case. + */ + if (refi == 0) + goto out; + + sort(sorted, refi, sizeof(struct refsort), refsort_cmp, NULL); + + /* + * the first loop frees everything the leaves point to + */ + for (i = 0; i < refi; i++) { + u64 ptr_gen; + + bytenr = sorted[i].bytenr; + + /* + * check the reference count on this leaf. If it is > 1 + * we just decrement it below and don't update any + * of the refs the leaf points to. + */ + ret = drop_snap_lookup_refcount(root, bytenr, blocksize, &refs); + BUG_ON(ret); + if (refs != 1) + continue; + + ptr_gen = btrfs_node_ptr_generation(eb, sorted[i].slot); + + /* + * the leaf only had one reference, which means the + * only thing pointing to this leaf is the snapshot + * we're deleting. It isn't possible for the reference + * count to increase again later + * + * The reference cache is checked for the leaf, + * and if found we'll be able to drop any refs held by + * the leaf without needing to read it in. + */ + ref = btrfs_lookup_leaf_ref(root, bytenr); + if (ref && ref->generation != ptr_gen) { + btrfs_free_leaf_ref(root, ref); + ref = NULL; + } + if (ref) { + ret = cache_drop_leaf_ref(trans, root, ref); + BUG_ON(ret); + btrfs_remove_leaf_ref(root, ref); + btrfs_free_leaf_ref(root, ref); + } else { + /* + * the leaf wasn't in the reference cache, so + * we have to read it. + */ + leaf = read_tree_block(root, bytenr, blocksize, + ptr_gen); + ret = btrfs_drop_leaf_ref(trans, root, leaf); + BUG_ON(ret); + free_extent_buffer(leaf); + } + atomic_inc(&root->fs_info->throttle_gen); + wake_up(&root->fs_info->transaction_throttle); + cond_resched(); + } + + /* + * run through the loop again to free the refs on the leaves. + * This is faster than doing it in the loop above because + * the leaves are likely to be clustered together. We end up + * working in nice chunks on the extent allocation tree. + */ + for (i = 0; i < refi; i++) { + bytenr = sorted[i].bytenr; + ret = __btrfs_free_extent(trans, root, bytenr, + blocksize, eb->start, + root_owner, root_gen, 0, 1); + BUG_ON(ret); + + atomic_inc(&root->fs_info->throttle_gen); + wake_up(&root->fs_info->transaction_throttle); + cond_resched(); + } +out: + kfree(sorted); + + /* + * update the path to show we've processed the entire level 1 + * node. This will get saved into the root's drop_snapshot_progress + * field so these drops are not repeated again if this transaction + * commits. + */ + path->slots[1] = nritems; + return 0; +} + +/* * helper function for drop_snapshot, this walks down the tree dropping ref * counts as it goes. */ @@ -3511,7 +3787,6 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans, struct extent_buffer *next; struct extent_buffer *cur; struct extent_buffer *parent; - struct btrfs_leaf_ref *ref; u32 blocksize; int ret; u32 refs; @@ -3538,17 +3813,46 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans, if (path->slots[*level] >= btrfs_header_nritems(cur)) break; + + /* the new code goes down to level 1 and does all the + * leaves pointed to that node in bulk. So, this check + * for level 0 will always be false. + * + * But, the disk format allows the drop_snapshot_progress + * field in the root to leave things in a state where + * a leaf will need cleaning up here. If someone crashes + * with the old code and then boots with the new code, + * we might find a leaf here. + */ if (*level == 0) { ret = btrfs_drop_leaf_ref(trans, root, cur); BUG_ON(ret); break; } + + /* + * once we get to level one, process the whole node + * at once, including everything below it. + */ + if (*level == 1) { + ret = drop_level_one_refs(trans, root, path); + BUG_ON(ret); + break; + } + bytenr = btrfs_node_blockptr(cur, path->slots[*level]); ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]); blocksize = btrfs_level_size(root, *level - 1); ret = drop_snap_lookup_refcount(root, bytenr, blocksize, &refs); BUG_ON(ret); + + /* + * if there is more than one reference, we don't need + * to read that node to drop any references it has. We + * just drop the ref we hold on that node and move on to the + * next slot in this level. + */ if (refs != 1) { parent = path->nodes[*level]; root_owner = btrfs_header_owner(parent); @@ -3567,46 +3871,12 @@ static noinline int walk_down_tree(struct btrfs_trans_handle *trans, continue; } + /* - * at this point, we have a single ref, and since the - * only place referencing this extent is a dead root - * the reference count should never go higher. - * So, we don't need to check it again + * we need to keep freeing things in the next level down. + * read the block and loop around to process it */ - if (*level == 1) { - ref = btrfs_lookup_leaf_ref(root, bytenr); - if (ref && ref->generation != ptr_gen) { - btrfs_free_leaf_ref(root, ref); - ref = NULL; - } - if (ref) { - ret = cache_drop_leaf_ref(trans, root, ref); - BUG_ON(ret); - btrfs_remove_leaf_ref(root, ref); - btrfs_free_leaf_ref(root, ref); - *level = 0; - break; - } - } - next = btrfs_find_tree_block(root, bytenr, blocksize); - if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) { - free_extent_buffer(next); - - next = read_tree_block(root, bytenr, blocksize, - ptr_gen); - cond_resched(); -#if 0 - /* - * this is a debugging check and can go away - * the ref should never go all the way down to 1 - * at this point - */ - ret = lookup_extent_ref(NULL, root, bytenr, blocksize, - &refs); - BUG_ON(ret); - WARN_ON(refs != 1); -#endif - } + next = read_tree_block(root, bytenr, blocksize, ptr_gen); WARN_ON(*level <= 0); if (path->nodes[*level-1]) free_extent_buffer(path->nodes[*level-1]); @@ -3631,11 +3901,16 @@ out: root_owner = btrfs_header_owner(parent); root_gen = btrfs_header_generation(parent); + /* + * cleanup and free the reference on the last node + * we processed + */ ret = __btrfs_free_extent(trans, root, bytenr, blocksize, parent->start, root_owner, root_gen, *level, 1); free_extent_buffer(path->nodes[*level]); path->nodes[*level] = NULL; + *level += 1; BUG_ON(ret); @@ -3687,6 +3962,7 @@ static noinline int walk_down_subtree(struct btrfs_trans_handle *trans, next = read_tree_block(root, bytenr, blocksize, ptr_gen); btrfs_tree_lock(next); + btrfs_set_lock_blocking(next); ret = btrfs_lookup_extent_ref(trans, root, bytenr, blocksize, &refs); @@ -3754,6 +4030,13 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans, if (slot < btrfs_header_nritems(path->nodes[i]) - 1) { struct extent_buffer *node; struct btrfs_disk_key disk_key; + + /* + * there is more work to do in this level. + * Update the drop_progress marker to reflect + * the work we've done so far, and then bump + * the slot number + */ node = path->nodes[i]; path->slots[i]++; *level = i; @@ -3765,6 +4048,11 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans, return 0; } else { struct extent_buffer *parent; + + /* + * this whole node is done, free our reference + * on it and go up one level + */ if (path->nodes[*level] == root->node) parent = path->nodes[*level]; else @@ -4444,7 +4732,7 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans, u64 lock_end = 0; u64 num_bytes; u64 ext_offset; - u64 first_pos; + u64 search_end = (u64)-1; u32 nritems; int nr_scaned = 0; int extent_locked = 0; @@ -4452,7 +4740,6 @@ static noinline int replace_one_extent(struct btrfs_trans_handle *trans, int ret; memcpy(&key, leaf_key, sizeof(key)); - first_pos = INT_LIMIT(loff_t) - extent_key->offset; if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS) { if (key.objectid < ref_path->owner_objectid || (key.objectid == ref_path->owner_objectid && @@ -4501,7 +4788,7 @@ next: if ((key.objectid > ref_path->owner_objectid) || (key.objectid == ref_path->owner_objectid && key.type > BTRFS_EXTENT_DATA_KEY) || - (key.offset >= first_pos + extent_key->offset)) + key.offset >= search_end) break; } @@ -4534,8 +4821,10 @@ next: num_bytes = btrfs_file_extent_num_bytes(leaf, fi); ext_offset = btrfs_file_extent_offset(leaf, fi); - if (first_pos > key.offset - ext_offset) - first_pos = key.offset - ext_offset; + if (search_end == (u64)-1) { + search_end = key.offset - ext_offset + + btrfs_file_extent_ram_bytes(leaf, fi); + } if (!extent_locked) { lock_start = key.offset; @@ -4724,7 +5013,7 @@ next: } skip: if (ref_path->owner_objectid != BTRFS_MULTIPLE_OBJECTIDS && - key.offset >= first_pos + extent_key->offset) + key.offset >= search_end) break; cond_resched(); @@ -4778,6 +5067,7 @@ int btrfs_reloc_tree_cache_ref(struct btrfs_trans_handle *trans, ref->bytenr = buf->start; ref->owner = btrfs_header_owner(buf); ref->generation = btrfs_header_generation(buf); + ret = btrfs_add_leaf_ref(root, ref, 0); WARN_ON(ret); btrfs_free_leaf_ref(root, ref); @@ -5957,9 +6247,11 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, path = btrfs_alloc_path(); BUG_ON(!path); - btrfs_remove_free_space_cache(block_group); + spin_lock(&root->fs_info->block_group_cache_lock); rb_erase(&block_group->cache_node, &root->fs_info->block_group_cache_tree); + spin_unlock(&root->fs_info->block_group_cache_lock); + btrfs_remove_free_space_cache(block_group); down_write(&block_group->space_info->groups_sem); list_del(&block_group->list); up_write(&block_group->space_info->groups_sem); diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index e086d40..37d43b5 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -9,7 +9,6 @@ #include <linux/spinlock.h> #include <linux/blkdev.h> #include <linux/swap.h> -#include <linux/version.h> #include <linux/writeback.h> #include <linux/pagevec.h> #include "extent_io.h" @@ -31,7 +30,7 @@ static LIST_HEAD(buffers); static LIST_HEAD(states); #define LEAK_DEBUG 0 -#ifdef LEAK_DEBUG +#if LEAK_DEBUG static DEFINE_SPINLOCK(leak_lock); #endif @@ -120,7 +119,7 @@ void extent_io_tree_init(struct extent_io_tree *tree, static struct extent_state *alloc_extent_state(gfp_t mask) { struct extent_state *state; -#ifdef LEAK_DEBUG +#if LEAK_DEBUG unsigned long flags; #endif @@ -130,7 +129,7 @@ static struct extent_state *alloc_extent_state(gfp_t mask) state->state = 0; state->private = 0; state->tree = NULL; -#ifdef LEAK_DEBUG +#if LEAK_DEBUG spin_lock_irqsave(&leak_lock, flags); list_add(&state->leak_list, &states); spin_unlock_irqrestore(&leak_lock, flags); @@ -145,11 +144,11 @@ static void free_extent_state(struct extent_state *state) if (!state) return; if (atomic_dec_and_test(&state->refs)) { -#ifdef LEAK_DEBUG +#if LEAK_DEBUG unsigned long flags; #endif WARN_ON(state->tree); -#ifdef LEAK_DEBUG +#if LEAK_DEBUG spin_lock_irqsave(&leak_lock, flags); list_del(&state->leak_list); spin_unlock_irqrestore(&leak_lock, flags); @@ -2378,11 +2377,6 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, int scanned = 0; int range_whole = 0; - if (wbc->nonblocking && bdi_write_congested(bdi)) { - wbc->encountered_congestion = 1; - return 0; - } - pagevec_init(&pvec, 0); if (wbc->range_cyclic) { index = mapping->writeback_index; /* Start from prev offset */ @@ -2855,6 +2849,98 @@ out: return sector; } +int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + __u64 start, __u64 len, get_extent_t *get_extent) +{ + int ret; + u64 off = start; + u64 max = start + len; + u32 flags = 0; + u64 disko = 0; + struct extent_map *em = NULL; + int end = 0; + u64 em_start = 0, em_len = 0; + unsigned long emflags; + ret = 0; + + if (len == 0) + return -EINVAL; + + lock_extent(&BTRFS_I(inode)->io_tree, start, start + len, + GFP_NOFS); + em = get_extent(inode, NULL, 0, off, max - off, 0); + if (!em) + goto out; + if (IS_ERR(em)) { + ret = PTR_ERR(em); + goto out; + } + while (!end) { + off = em->start + em->len; + if (off >= max) + end = 1; + + em_start = em->start; + em_len = em->len; + + disko = 0; + flags = 0; + + switch (em->block_start) { + case EXTENT_MAP_LAST_BYTE: + end = 1; + flags |= FIEMAP_EXTENT_LAST; + break; + case EXTENT_MAP_HOLE: + flags |= FIEMAP_EXTENT_UNWRITTEN; + break; + case EXTENT_MAP_INLINE: + flags |= (FIEMAP_EXTENT_DATA_INLINE | + FIEMAP_EXTENT_NOT_ALIGNED); + break; + case EXTENT_MAP_DELALLOC: + flags |= (FIEMAP_EXTENT_DELALLOC | + FIEMAP_EXTENT_UNKNOWN); + break; + default: + disko = em->block_start; + break; + } + if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) + flags |= FIEMAP_EXTENT_ENCODED; + + emflags = em->flags; + free_extent_map(em); + em = NULL; + + if (!end) { + em = get_extent(inode, NULL, 0, off, max - off, 0); + if (!em) + goto out; + if (IS_ERR(em)) { + ret = PTR_ERR(em); + goto out; + } + emflags = em->flags; + } + if (test_bit(EXTENT_FLAG_VACANCY, &emflags)) { + flags |= FIEMAP_EXTENT_LAST; + end = 1; + } + + ret = fiemap_fill_next_extent(fieinfo, em_start, disko, + em_len, flags); + if (ret) + goto out_free; + } +out_free: + free_extent_map(em); +out: + unlock_extent(&BTRFS_I(inode)->io_tree, start, start + len, + GFP_NOFS); + return ret; +} + static inline struct page *extent_buffer_page(struct extent_buffer *eb, unsigned long i) { @@ -2892,15 +2978,17 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree, gfp_t mask) { struct extent_buffer *eb = NULL; -#ifdef LEAK_DEBUG +#if LEAK_DEBUG unsigned long flags; #endif eb = kmem_cache_zalloc(extent_buffer_cache, mask); eb->start = start; eb->len = len; - mutex_init(&eb->mutex); -#ifdef LEAK_DEBUG + spin_lock_init(&eb->lock); + init_waitqueue_head(&eb->lock_wq); + +#if LEAK_DEBUG spin_lock_irqsave(&leak_lock, flags); list_add(&eb->leak_list, &buffers); spin_unlock_irqrestore(&leak_lock, flags); @@ -2912,7 +3000,7 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree, static void __free_extent_buffer(struct extent_buffer *eb) { -#ifdef LEAK_DEBUG +#if LEAK_DEBUG unsigned long flags; spin_lock_irqsave(&leak_lock, flags); list_del(&eb->leak_list); @@ -2980,8 +3068,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, unlock_page(p); } if (uptodate) - eb->flags |= EXTENT_UPTODATE; - eb->flags |= EXTENT_BUFFER_FILLED; + set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); spin_lock(&tree->buffer_lock); exists = buffer_tree_insert(tree, start, &eb->rb_node); @@ -3135,7 +3222,7 @@ int clear_extent_buffer_uptodate(struct extent_io_tree *tree, unsigned long num_pages; num_pages = num_extent_pages(eb->start, eb->len); - eb->flags &= ~EXTENT_UPTODATE; + clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1, GFP_NOFS); @@ -3206,7 +3293,7 @@ int extent_buffer_uptodate(struct extent_io_tree *tree, struct page *page; int pg_uptodate = 1; - if (eb->flags & EXTENT_UPTODATE) + if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags)) return 1; ret = test_range_bit(tree, eb->start, eb->start + eb->len - 1, @@ -3242,7 +3329,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree, struct bio *bio = NULL; unsigned long bio_flags = 0; - if (eb->flags & EXTENT_UPTODATE) + if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags)) return 0; if (test_range_bit(tree, eb->start, eb->start + eb->len - 1, @@ -3273,7 +3360,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree, } if (all_uptodate) { if (start_i == 0) - eb->flags |= EXTENT_UPTODATE; + set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); goto unlock_exit; } @@ -3309,7 +3396,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree, } if (!ret) - eb->flags |= EXTENT_UPTODATE; + set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); return ret; unlock_exit: @@ -3406,7 +3493,6 @@ int map_extent_buffer(struct extent_buffer *eb, unsigned long start, unmap_extent_buffer(eb, eb->map_token, km); eb->map_token = NULL; save = 1; - WARN_ON(!mutex_is_locked(&eb->mutex)); } err = map_private_extent_buffer(eb, start, min_len, token, map, map_start, map_len, km); diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index c5b483a..1f9df88 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -22,6 +22,10 @@ /* flags for bio submission */ #define EXTENT_BIO_COMPRESSED 1 +/* these are bit numbers for test/set bit */ +#define EXTENT_BUFFER_UPTODATE 0 +#define EXTENT_BUFFER_BLOCKING 1 + /* * page->private values. Every page that is controlled by the extent * map has page->private set to one. @@ -95,11 +99,19 @@ struct extent_buffer { unsigned long map_start; unsigned long map_len; struct page *first_page; + unsigned long bflags; atomic_t refs; - int flags; struct list_head leak_list; struct rb_node rb_node; - struct mutex mutex; + + /* the spinlock is used to protect most operations */ + spinlock_t lock; + + /* + * when we keep the lock held while blocking, waiters go onto + * the wq + */ + wait_queue_head_t lock_wq; }; struct extent_map_tree; @@ -193,6 +205,8 @@ int extent_commit_write(struct extent_io_tree *tree, unsigned from, unsigned to); sector_t extent_bmap(struct address_space *mapping, sector_t iblock, get_extent_t *get_extent); +int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + __u64 start, __u64 len, get_extent_t *get_extent); int set_range_dirty(struct extent_io_tree *tree, u64 start, u64 end); int set_state_private(struct extent_io_tree *tree, u64 start, u64 private); int get_state_private(struct extent_io_tree *tree, u64 start, u64 *private); diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 4a83e33..50da69d 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c @@ -3,7 +3,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/spinlock.h> -#include <linux/version.h> #include <linux/hardirq.h> #include "extent_map.h" diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 9026833..3e8023e 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -29,7 +29,6 @@ #include <linux/writeback.h> #include <linux/statfs.h> #include <linux/compat.h> -#include <linux/version.h> #include "ctree.h" #include "disk-io.h" #include "transaction.h" @@ -1215,10 +1214,10 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync) } mutex_unlock(&root->fs_info->trans_mutex); - root->fs_info->tree_log_batch++; + root->log_batch++; filemap_fdatawrite(inode->i_mapping); btrfs_wait_ordered_range(inode, 0, (u64)-1); - root->fs_info->tree_log_batch++; + root->log_batch++; /* * ok we haven't committed the transaction yet, lets do a commit diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 8adfe05..8f07062 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -34,7 +34,6 @@ #include <linux/statfs.h> #include <linux/compat.h> #include <linux/bit_spinlock.h> -#include <linux/version.h> #include <linux/xattr.h> #include <linux/posix_acl.h> #include <linux/falloc.h> @@ -51,6 +50,7 @@ #include "tree-log.h" #include "ref-cache.h" #include "compression.h" +#include "locking.h" struct btrfs_iget_args { u64 ino; @@ -91,6 +91,16 @@ static noinline int cow_file_range(struct inode *inode, u64 start, u64 end, int *page_started, unsigned long *nr_written, int unlock); +static int btrfs_init_inode_security(struct inode *inode, struct inode *dir) +{ + int err; + + err = btrfs_init_acl(inode, dir); + if (!err) + err = btrfs_xattr_security_init(inode, dir); + return err; +} + /* * a very lame attempt at stopping writes when the FS is 85% full. There * are countless ways this is incorrect, but it is better than nothing. @@ -350,6 +360,19 @@ again: nr_pages = (end >> PAGE_CACHE_SHIFT) - (start >> PAGE_CACHE_SHIFT) + 1; nr_pages = min(nr_pages, (128 * 1024UL) / PAGE_CACHE_SIZE); + /* + * we don't want to send crud past the end of i_size through + * compression, that's just a waste of CPU time. So, if the + * end of the file is before the start of our current + * requested range of bytes, we bail out to the uncompressed + * cleanup code that can deal with all of this. + * + * It isn't really the fastest way to fix things, but this is a + * very uncommon corner. + */ + if (actual_end <= start) + goto cleanup_and_bail_uncompressed; + total_compressed = actual_end - start; /* we want to make sure that amount of ram required to uncompress @@ -494,6 +517,7 @@ again: goto again; } } else { +cleanup_and_bail_uncompressed: /* * No compression, but we still need to write the pages in * the file we've been given so far. redirty the locked @@ -1324,12 +1348,11 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans, struct inode *inode, u64 file_offset, struct list_head *list) { - struct list_head *cur; struct btrfs_ordered_sum *sum; btrfs_set_trans_block_group(trans, inode); - list_for_each(cur, list) { - sum = list_entry(cur, struct btrfs_ordered_sum, list); + + list_for_each_entry(sum, list, list) { btrfs_csum_file_blocks(trans, BTRFS_I(inode)->root->fs_info->csum_root, sum); } @@ -2013,6 +2036,7 @@ void btrfs_read_locked_inode(struct inode *inode) BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); alloc_group_block = btrfs_inode_block_group(leaf, inode_item); + BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0, alloc_group_block, 0); btrfs_free_path(path); @@ -2039,6 +2063,7 @@ void btrfs_read_locked_inode(struct inode *inode) inode->i_mapping->backing_dev_info = &root->fs_info->bdi; break; default: + inode->i_op = &btrfs_special_inode_operations; init_special_inode(inode, inode->i_mode, rdev); break; } @@ -2108,6 +2133,7 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, goto failed; } + btrfs_unlock_up_safe(path, 1); leaf = path->nodes[0]; inode_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_inode_item); @@ -2429,6 +2455,8 @@ next_node: ref->generation = leaf_gen; ref->nritems = 0; + btrfs_sort_leaf_ref(ref); + ret = btrfs_add_leaf_ref(root, ref, 0); WARN_ON(ret); btrfs_free_leaf_ref(root, ref); @@ -2476,7 +2504,7 @@ noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, struct btrfs_path *path; struct btrfs_key key; struct btrfs_key found_key; - u32 found_type; + u32 found_type = (u8)-1; struct extent_buffer *leaf; struct btrfs_file_extent_item *fi; u64 extent_start = 0; @@ -2663,6 +2691,8 @@ next: if (pending_del_nr) goto del_pending; btrfs_release_path(root, path); + if (found_type == BTRFS_INODE_ITEM_KEY) + break; goto search_again; } @@ -2679,6 +2709,8 @@ del_pending: BUG_ON(ret); pending_del_nr = 0; btrfs_release_path(root, path); + if (found_type == BTRFS_INODE_ITEM_KEY) + break; goto search_again; } } @@ -3265,7 +3297,7 @@ skip: /* Reached end of directory/root. Bump pos past the last item. */ if (key_type == BTRFS_DIR_INDEX_KEY) - filp->f_pos = INT_LIMIT(typeof(filp->f_pos)); + filp->f_pos = INT_LIMIT(off_t); else filp->f_pos++; nopos: @@ -3458,7 +3490,14 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, root->highest_inode = objectid; inode->i_uid = current_fsuid(); - inode->i_gid = current_fsgid(); + + if (dir && (dir->i_mode & S_ISGID)) { + inode->i_gid = dir->i_gid; + if (S_ISDIR(mode)) + mode |= S_ISGID; + } else + inode->i_gid = current_fsgid(); + inode->i_mode = mode; inode->i_ino = objectid; inode_set_bytes(inode, 0); @@ -3586,7 +3625,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, if (IS_ERR(inode)) goto out_unlock; - err = btrfs_init_acl(inode, dir); + err = btrfs_init_inode_security(inode, dir); if (err) { drop_inode = 1; goto out_unlock; @@ -3649,7 +3688,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, if (IS_ERR(inode)) goto out_unlock; - err = btrfs_init_acl(inode, dir); + err = btrfs_init_inode_security(inode, dir); if (err) { drop_inode = 1; goto out_unlock; @@ -3772,7 +3811,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) drop_on_err = 1; - err = btrfs_init_acl(inode, dir); + err = btrfs_init_inode_security(inode, dir); if (err) goto out_fail; @@ -4158,9 +4197,10 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, return -EINVAL; } -static sector_t btrfs_bmap(struct address_space *mapping, sector_t iblock) +static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + __u64 start, __u64 len) { - return extent_bmap(mapping, iblock, btrfs_get_extent); + return extent_fiemap(inode, fieinfo, start, len, btrfs_get_extent); } int btrfs_readpage(struct file *file, struct page *page) @@ -4733,7 +4773,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, if (IS_ERR(inode)) goto out_unlock; - err = btrfs_init_acl(inode, dir); + err = btrfs_init_inode_security(inode, dir); if (err) { drop_inode = 1; goto out_unlock; @@ -4987,13 +5027,24 @@ static struct extent_io_ops btrfs_extent_io_ops = { .clear_bit_hook = btrfs_clear_bit_hook, }; +/* + * btrfs doesn't support the bmap operation because swapfiles + * use bmap to make a mapping of extents in the file. They assume + * these extents won't change over the life of the file and they + * use the bmap result to do IO directly to the drive. + * + * the btrfs bmap call would return logical addresses that aren't + * suitable for IO and they also will change frequently as COW + * operations happen. So, swapfile + btrfs == corruption. + * + * For now we're avoiding this by dropping bmap. + */ static struct address_space_operations btrfs_aops = { .readpage = btrfs_readpage, .writepage = btrfs_writepage, .writepages = btrfs_writepages, .readpages = btrfs_readpages, .sync_page = block_sync_page, - .bmap = btrfs_bmap, .direct_IO = btrfs_direct_IO, .invalidatepage = btrfs_invalidatepage, .releasepage = btrfs_releasepage, @@ -5017,6 +5068,7 @@ static struct inode_operations btrfs_file_inode_operations = { .removexattr = btrfs_removexattr, .permission = btrfs_permission, .fallocate = btrfs_fallocate, + .fiemap = btrfs_fiemap, }; static struct inode_operations btrfs_special_inode_operations = { .getattr = btrfs_getattr, @@ -5032,4 +5084,8 @@ static struct inode_operations btrfs_symlink_inode_operations = { .follow_link = page_follow_link_light, .put_link = page_put_link, .permission = btrfs_permission, + .setxattr = btrfs_setxattr, + .getxattr = btrfs_getxattr, + .listxattr = btrfs_listxattr, + .removexattr = btrfs_removexattr, }; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index c2aa33e..988fdc8 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -38,7 +38,6 @@ #include <linux/compat.h> #include <linux/bit_spinlock.h> #include <linux/security.h> -#include <linux/version.h> #include <linux/xattr.h> #include <linux/vmalloc.h> #include "compat.h" diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c index 39bae77..68fd9cc 100644 --- a/fs/btrfs/locking.c +++ b/fs/btrfs/locking.c @@ -26,45 +26,215 @@ #include "locking.h" /* - * locks the per buffer mutex in an extent buffer. This uses adaptive locks - * and the spin is not tuned very extensively. The spinning does make a big - * difference in almost every workload, but spinning for the right amount of - * time needs some help. - * - * In general, we want to spin as long as the lock holder is doing btree - * searches, and we should give up if they are in more expensive code. + * btrfs_header_level() isn't free, so don't call it when lockdep isn't + * on */ +#ifdef CONFIG_DEBUG_LOCK_ALLOC +static inline void spin_nested(struct extent_buffer *eb) +{ + spin_lock_nested(&eb->lock, BTRFS_MAX_LEVEL - btrfs_header_level(eb)); +} +#else +static inline void spin_nested(struct extent_buffer *eb) +{ + spin_lock(&eb->lock); +} +#endif -int btrfs_tree_lock(struct extent_buffer *eb) +/* + * Setting a lock to blocking will drop the spinlock and set the + * flag that forces other procs who want the lock to wait. After + * this you can safely schedule with the lock held. + */ +void btrfs_set_lock_blocking(struct extent_buffer *eb) { - int i; + if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) { + set_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags); + spin_unlock(&eb->lock); + } + /* exit with the spin lock released and the bit set */ +} - if (mutex_trylock(&eb->mutex)) - return 0; +/* + * clearing the blocking flag will take the spinlock again. + * After this you can't safely schedule + */ +void btrfs_clear_lock_blocking(struct extent_buffer *eb) +{ + if (test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) { + spin_nested(eb); + clear_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags); + smp_mb__after_clear_bit(); + } + /* exit with the spin lock held */ +} + +/* + * unfortunately, many of the places that currently set a lock to blocking + * don't end up blocking for every long, and often they don't block + * at all. For a dbench 50 run, if we don't spin one the blocking bit + * at all, the context switch rate can jump up to 400,000/sec or more. + * + * So, we're still stuck with this crummy spin on the blocking bit, + * at least until the most common causes of the short blocks + * can be dealt with. + */ +static int btrfs_spin_on_block(struct extent_buffer *eb) +{ + int i; for (i = 0; i < 512; i++) { cpu_relax(); - if (mutex_trylock(&eb->mutex)) + if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) + return 1; + if (need_resched()) + break; + } + return 0; +} + +/* + * This is somewhat different from trylock. It will take the + * spinlock but if it finds the lock is set to blocking, it will + * return without the lock held. + * + * returns 1 if it was able to take the lock and zero otherwise + * + * After this call, scheduling is not safe without first calling + * btrfs_set_lock_blocking() + */ +int btrfs_try_spin_lock(struct extent_buffer *eb) +{ + int i; + + spin_nested(eb); + if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) + return 1; + spin_unlock(&eb->lock); + + /* spin for a bit on the BLOCKING flag */ + for (i = 0; i < 2; i++) { + if (!btrfs_spin_on_block(eb)) + break; + + spin_nested(eb); + if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) + return 1; + spin_unlock(&eb->lock); + } + return 0; +} + +/* + * the autoremove wake function will return 0 if it tried to wake up + * a process that was already awake, which means that process won't + * count as an exclusive wakeup. The waitq code will continue waking + * procs until it finds one that was actually sleeping. + * + * For btrfs, this isn't quite what we want. We want a single proc + * to be notified that the lock is ready for taking. If that proc + * already happen to be awake, great, it will loop around and try for + * the lock. + * + * So, btrfs_wake_function always returns 1, even when the proc that we + * tried to wake up was already awake. + */ +static int btrfs_wake_function(wait_queue_t *wait, unsigned mode, + int sync, void *key) +{ + autoremove_wake_function(wait, mode, sync, key); + return 1; +} + +/* + * returns with the extent buffer spinlocked. + * + * This will spin and/or wait as required to take the lock, and then + * return with the spinlock held. + * + * After this call, scheduling is not safe without first calling + * btrfs_set_lock_blocking() + */ +int btrfs_tree_lock(struct extent_buffer *eb) +{ + DEFINE_WAIT(wait); + wait.func = btrfs_wake_function; + + while(1) { + spin_nested(eb); + + /* nobody is blocking, exit with the spinlock held */ + if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) return 0; + + /* + * we have the spinlock, but the real owner is blocking. + * wait for them + */ + spin_unlock(&eb->lock); + + /* + * spin for a bit, and if the blocking flag goes away, + * loop around + */ + if (btrfs_spin_on_block(eb)) + continue; + + prepare_to_wait_exclusive(&eb->lock_wq, &wait, + TASK_UNINTERRUPTIBLE); + + if (test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) + schedule(); + + finish_wait(&eb->lock_wq, &wait); } - cpu_relax(); - mutex_lock_nested(&eb->mutex, BTRFS_MAX_LEVEL - btrfs_header_level(eb)); return 0; } +/* + * Very quick trylock, this does not spin or schedule. It returns + * 1 with the spinlock held if it was able to take the lock, or it + * returns zero if it was unable to take the lock. + * + * After this call, scheduling is not safe without first calling + * btrfs_set_lock_blocking() + */ int btrfs_try_tree_lock(struct extent_buffer *eb) { - return mutex_trylock(&eb->mutex); + if (spin_trylock(&eb->lock)) { + if (test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) { + /* + * we've got the spinlock, but the real owner is + * blocking. Drop the spinlock and return failure + */ + spin_unlock(&eb->lock); + return 0; + } + return 1; + } + /* someone else has the spinlock giveup */ + return 0; } int btrfs_tree_unlock(struct extent_buffer *eb) { - mutex_unlock(&eb->mutex); + /* + * if we were a blocking owner, we don't have the spinlock held + * just clear the bit and look for waiters + */ + if (test_and_clear_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) + smp_mb__after_clear_bit(); + else + spin_unlock(&eb->lock); + + if (waitqueue_active(&eb->lock_wq)) + wake_up(&eb->lock_wq); return 0; } int btrfs_tree_locked(struct extent_buffer *eb) { - return mutex_is_locked(&eb->mutex); + return test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags) || + spin_is_locked(&eb->lock); } /* @@ -75,12 +245,14 @@ int btrfs_path_lock_waiting(struct btrfs_path *path, int level) { int i; struct extent_buffer *eb; + for (i = level; i <= level + 1 && i < BTRFS_MAX_LEVEL; i++) { eb = path->nodes[i]; if (!eb) break; smp_mb(); - if (!list_empty(&eb->mutex.wait_list)) + if (spin_is_contended(&eb->lock) || + waitqueue_active(&eb->lock_wq)) return 1; } return 0; diff --git a/fs/btrfs/locking.h b/fs/btrfs/locking.h index bc1faef..d92e707 100644 --- a/fs/btrfs/locking.h +++ b/fs/btrfs/locking.h @@ -22,6 +22,12 @@ int btrfs_tree_lock(struct extent_buffer *eb); int btrfs_tree_unlock(struct extent_buffer *eb); int btrfs_tree_locked(struct extent_buffer *eb); + int btrfs_try_tree_lock(struct extent_buffer *eb); +int btrfs_try_spin_lock(struct extent_buffer *eb); + int btrfs_path_lock_waiting(struct btrfs_path *path, int level); + +void btrfs_set_lock_blocking(struct extent_buffer *eb); +void btrfs_clear_lock_blocking(struct extent_buffer *eb); #endif diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index a209401..77c2411 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -613,7 +613,6 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, struct btrfs_sector_sum *sector_sums; struct btrfs_ordered_extent *ordered; struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree; - struct list_head *cur; unsigned long num_sectors; unsigned long i; u32 sectorsize = BTRFS_I(inode)->root->sectorsize; @@ -624,8 +623,7 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, return 1; mutex_lock(&tree->mutex); - list_for_each_prev(cur, &ordered->list) { - ordered_sum = list_entry(cur, struct btrfs_ordered_sum, list); + list_for_each_entry_reverse(ordered_sum, &ordered->list, list) { if (disk_bytenr >= ordered_sum->bytenr) { num_sectors = ordered_sum->len / sectorsize; sector_sums = ordered_sum->sums; diff --git a/fs/btrfs/ref-cache.c b/fs/btrfs/ref-cache.c index 6f0acc4..d0cc62b 100644 --- a/fs/btrfs/ref-cache.c +++ b/fs/btrfs/ref-cache.c @@ -17,6 +17,7 @@ */ #include <linux/sched.h> +#include <linux/sort.h> #include "ctree.h" #include "ref-cache.h" #include "transaction.h" diff --git a/fs/btrfs/ref-cache.h b/fs/btrfs/ref-cache.h index 16f3183..bc283ad 100644 --- a/fs/btrfs/ref-cache.h +++ b/fs/btrfs/ref-cache.h @@ -73,5 +73,4 @@ int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref, int btrfs_remove_leaf_refs(struct btrfs_root *root, u64 max_root_gen, int shared); int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref); - #endif diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index db9fb3b..f3fd7e2 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -37,7 +37,6 @@ #include <linux/ctype.h> #include <linux/namei.h> #include <linux/miscdevice.h> -#include <linux/version.h> #include <linux/magic.h> #include "compat.h" #include "ctree.h" @@ -583,17 +582,18 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd, struct btrfs_ioctl_vol_args *vol; struct btrfs_fs_devices *fs_devices; int ret = -ENOTTY; - int len; if (!capable(CAP_SYS_ADMIN)) return -EPERM; vol = kmalloc(sizeof(*vol), GFP_KERNEL); + if (!vol) + return -ENOMEM; + if (copy_from_user(vol, (void __user *)arg, sizeof(*vol))) { ret = -EFAULT; goto out; } - len = strnlen(vol->name, BTRFS_PATH_NAME_MAX); switch (cmd) { case BTRFS_IOC_SCAN_DEV: diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 8a08f94..919172de 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -852,11 +852,9 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, { struct btrfs_pending_snapshot *pending; struct list_head *head = &trans->transaction->pending_snapshots; - struct list_head *cur; int ret; - list_for_each(cur, head) { - pending = list_entry(cur, struct btrfs_pending_snapshot, list); + list_for_each_entry(pending, head, list) { ret = create_pending_snapshot(trans, fs_info, pending); BUG_ON(ret); } diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c index 3e8358c..98d25fa 100644 --- a/fs/btrfs/tree-defrag.c +++ b/fs/btrfs/tree-defrag.c @@ -74,6 +74,7 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, u32 nritems; root_node = btrfs_lock_root_node(root); + btrfs_set_lock_blocking(root_node); nritems = btrfs_header_nritems(root_node); root->defrag_max.objectid = 0; /* from above we know this is not a leaf */ diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index d81cda2..2079429 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -78,104 +78,6 @@ static int link_to_fixup_dir(struct btrfs_trans_handle *trans, */ /* - * btrfs_add_log_tree adds a new per-subvolume log tree into the - * tree of log tree roots. This must be called with a tree log transaction - * running (see start_log_trans). - */ -static int btrfs_add_log_tree(struct btrfs_trans_handle *trans, - struct btrfs_root *root) -{ - struct btrfs_key key; - struct btrfs_root_item root_item; - struct btrfs_inode_item *inode_item; - struct extent_buffer *leaf; - struct btrfs_root *new_root = root; - int ret; - u64 objectid = root->root_key.objectid; - - leaf = btrfs_alloc_free_block(trans, root, root->leafsize, 0, - BTRFS_TREE_LOG_OBJECTID, - trans->transid, 0, 0, 0); - if (IS_ERR(leaf)) { - ret = PTR_ERR(leaf); - return ret; - } - - btrfs_set_header_nritems(leaf, 0); - btrfs_set_header_level(leaf, 0); - btrfs_set_header_bytenr(leaf, leaf->start); - btrfs_set_header_generation(leaf, trans->transid); - btrfs_set_header_owner(leaf, BTRFS_TREE_LOG_OBJECTID); - - write_extent_buffer(leaf, root->fs_info->fsid, - (unsigned long)btrfs_header_fsid(leaf), - BTRFS_FSID_SIZE); - btrfs_mark_buffer_dirty(leaf); - - inode_item = &root_item.inode; - memset(inode_item, 0, sizeof(*inode_item)); - inode_item->generation = cpu_to_le64(1); - inode_item->size = cpu_to_le64(3); - inode_item->nlink = cpu_to_le32(1); - inode_item->nbytes = cpu_to_le64(root->leafsize); - inode_item->mode = cpu_to_le32(S_IFDIR | 0755); - - btrfs_set_root_bytenr(&root_item, leaf->start); - btrfs_set_root_generation(&root_item, trans->transid); - btrfs_set_root_level(&root_item, 0); - btrfs_set_root_refs(&root_item, 0); - btrfs_set_root_used(&root_item, 0); - - memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); - root_item.drop_level = 0; - - btrfs_tree_unlock(leaf); - free_extent_buffer(leaf); - leaf = NULL; - - btrfs_set_root_dirid(&root_item, 0); - - key.objectid = BTRFS_TREE_LOG_OBJECTID; - key.offset = objectid; - btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); - ret = btrfs_insert_root(trans, root->fs_info->log_root_tree, &key, - &root_item); - if (ret) - goto fail; - - new_root = btrfs_read_fs_root_no_radix(root->fs_info->log_root_tree, - &key); - BUG_ON(!new_root); - - WARN_ON(root->log_root); - root->log_root = new_root; - - /* - * log trees do not get reference counted because they go away - * before a real commit is actually done. They do store pointers - * to file data extents, and those reference counts still get - * updated (along with back refs to the log tree). - */ - new_root->ref_cows = 0; - new_root->last_trans = trans->transid; - - /* - * we need to make sure the root block for this new tree - * is marked as dirty in the dirty_log_pages tree. This - * is how it gets flushed down to disk at tree log commit time. - * - * the tree logging mutex keeps others from coming in and changing - * the new_root->node, so we can safely access it here - */ - set_extent_dirty(&new_root->dirty_log_pages, new_root->node->start, - new_root->node->start + new_root->node->len - 1, - GFP_NOFS); - -fail: - return ret; -} - -/* * start a sub transaction and setup the log tree * this increments the log tree writer count to make the people * syncing the tree wait for us to finish @@ -184,6 +86,14 @@ static int start_log_trans(struct btrfs_trans_handle *trans, struct btrfs_root *root) { int ret; + + mutex_lock(&root->log_mutex); + if (root->log_root) { + root->log_batch++; + atomic_inc(&root->log_writers); + mutex_unlock(&root->log_mutex); + return 0; + } mutex_lock(&root->fs_info->tree_log_mutex); if (!root->fs_info->log_root_tree) { ret = btrfs_init_log_root_tree(trans, root->fs_info); @@ -193,9 +103,10 @@ static int start_log_trans(struct btrfs_trans_handle *trans, ret = btrfs_add_log_tree(trans, root); BUG_ON(ret); } - atomic_inc(&root->fs_info->tree_log_writers); - root->fs_info->tree_log_batch++; mutex_unlock(&root->fs_info->tree_log_mutex); + root->log_batch++; + atomic_inc(&root->log_writers); + mutex_unlock(&root->log_mutex); return 0; } @@ -212,13 +123,12 @@ static int join_running_log_trans(struct btrfs_root *root) if (!root->log_root) return -ENOENT; - mutex_lock(&root->fs_info->tree_log_mutex); + mutex_lock(&root->log_mutex); if (root->log_root) { ret = 0; - atomic_inc(&root->fs_info->tree_log_writers); - root->fs_info->tree_log_batch++; + atomic_inc(&root->log_writers); } - mutex_unlock(&root->fs_info->tree_log_mutex); + mutex_unlock(&root->log_mutex); return ret; } @@ -228,10 +138,11 @@ static int join_running_log_trans(struct btrfs_root *root) */ static int end_log_trans(struct btrfs_root *root) { - atomic_dec(&root->fs_info->tree_log_writers); - smp_mb(); - if (waitqueue_active(&root->fs_info->tree_log_wait)) - wake_up(&root->fs_info->tree_log_wait); + if (atomic_dec_and_test(&root->log_writers)) { + smp_mb(); + if (waitqueue_active(&root->log_writer_wait)) + wake_up(&root->log_writer_wait); + } return 0; } @@ -1704,6 +1615,7 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, btrfs_tree_lock(next); clean_tree_block(trans, root, next); + btrfs_set_lock_blocking(next); btrfs_wait_tree_block_writeback(next); btrfs_tree_unlock(next); @@ -1750,6 +1662,7 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, next = path->nodes[*level]; btrfs_tree_lock(next); clean_tree_block(trans, root, next); + btrfs_set_lock_blocking(next); btrfs_wait_tree_block_writeback(next); btrfs_tree_unlock(next); @@ -1807,6 +1720,7 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, btrfs_tree_lock(next); clean_tree_block(trans, root, next); + btrfs_set_lock_blocking(next); btrfs_wait_tree_block_writeback(next); btrfs_tree_unlock(next); @@ -1879,6 +1793,7 @@ static int walk_log_tree(struct btrfs_trans_handle *trans, btrfs_tree_lock(next); clean_tree_block(trans, log, next); + btrfs_set_lock_blocking(next); btrfs_wait_tree_block_writeback(next); btrfs_tree_unlock(next); @@ -1902,26 +1817,65 @@ static int walk_log_tree(struct btrfs_trans_handle *trans, } } btrfs_free_path(path); - if (wc->free) - free_extent_buffer(log->node); return ret; } -static int wait_log_commit(struct btrfs_root *log) +/* + * helper function to update the item for a given subvolumes log root + * in the tree of log roots + */ +static int update_log_root(struct btrfs_trans_handle *trans, + struct btrfs_root *log) +{ + int ret; + + if (log->log_transid == 1) { + /* insert root item on the first sync */ + ret = btrfs_insert_root(trans, log->fs_info->log_root_tree, + &log->root_key, &log->root_item); + } else { + ret = btrfs_update_root(trans, log->fs_info->log_root_tree, + &log->root_key, &log->root_item); + } + return ret; +} + +static int wait_log_commit(struct btrfs_root *root, unsigned long transid) { DEFINE_WAIT(wait); - u64 transid = log->fs_info->tree_log_transid; + int index = transid % 2; + /* + * we only allow two pending log transactions at a time, + * so we know that if ours is more than 2 older than the + * current transaction, we're done + */ do { - prepare_to_wait(&log->fs_info->tree_log_wait, &wait, - TASK_UNINTERRUPTIBLE); - mutex_unlock(&log->fs_info->tree_log_mutex); - if (atomic_read(&log->fs_info->tree_log_commit)) + prepare_to_wait(&root->log_commit_wait[index], + &wait, TASK_UNINTERRUPTIBLE); + mutex_unlock(&root->log_mutex); + if (root->log_transid < transid + 2 && + atomic_read(&root->log_commit[index])) schedule(); - finish_wait(&log->fs_info->tree_log_wait, &wait); - mutex_lock(&log->fs_info->tree_log_mutex); - } while (transid == log->fs_info->tree_log_transid && - atomic_read(&log->fs_info->tree_log_commit)); + finish_wait(&root->log_commit_wait[index], &wait); + mutex_lock(&root->log_mutex); + } while (root->log_transid < transid + 2 && + atomic_read(&root->log_commit[index])); + return 0; +} + +static int wait_for_writer(struct btrfs_root *root) +{ + DEFINE_WAIT(wait); + while (atomic_read(&root->log_writers)) { + prepare_to_wait(&root->log_writer_wait, + &wait, TASK_UNINTERRUPTIBLE); + mutex_unlock(&root->log_mutex); + if (atomic_read(&root->log_writers)) + schedule(); + mutex_lock(&root->log_mutex); + finish_wait(&root->log_writer_wait, &wait); + } return 0; } @@ -1933,57 +1887,114 @@ static int wait_log_commit(struct btrfs_root *log) int btrfs_sync_log(struct btrfs_trans_handle *trans, struct btrfs_root *root) { + int index1; + int index2; int ret; - unsigned long batch; struct btrfs_root *log = root->log_root; + struct btrfs_root *log_root_tree = root->fs_info->log_root_tree; - mutex_lock(&log->fs_info->tree_log_mutex); - if (atomic_read(&log->fs_info->tree_log_commit)) { - wait_log_commit(log); - goto out; + mutex_lock(&root->log_mutex); + index1 = root->log_transid % 2; + if (atomic_read(&root->log_commit[index1])) { + wait_log_commit(root, root->log_transid); + mutex_unlock(&root->log_mutex); + return 0; } - atomic_set(&log->fs_info->tree_log_commit, 1); + atomic_set(&root->log_commit[index1], 1); + + /* wait for previous tree log sync to complete */ + if (atomic_read(&root->log_commit[(index1 + 1) % 2])) + wait_log_commit(root, root->log_transid - 1); while (1) { - batch = log->fs_info->tree_log_batch; - mutex_unlock(&log->fs_info->tree_log_mutex); + unsigned long batch = root->log_batch; + mutex_unlock(&root->log_mutex); schedule_timeout_uninterruptible(1); - mutex_lock(&log->fs_info->tree_log_mutex); - - while (atomic_read(&log->fs_info->tree_log_writers)) { - DEFINE_WAIT(wait); - prepare_to_wait(&log->fs_info->tree_log_wait, &wait, - TASK_UNINTERRUPTIBLE); - mutex_unlock(&log->fs_info->tree_log_mutex); - if (atomic_read(&log->fs_info->tree_log_writers)) - schedule(); - mutex_lock(&log->fs_info->tree_log_mutex); - finish_wait(&log->fs_info->tree_log_wait, &wait); - } - if (batch == log->fs_info->tree_log_batch) + mutex_lock(&root->log_mutex); + wait_for_writer(root); + if (batch == root->log_batch) break; } ret = btrfs_write_and_wait_marked_extents(log, &log->dirty_log_pages); BUG_ON(ret); - ret = btrfs_write_and_wait_marked_extents(root->fs_info->log_root_tree, - &root->fs_info->log_root_tree->dirty_log_pages); + + btrfs_set_root_bytenr(&log->root_item, log->node->start); + btrfs_set_root_generation(&log->root_item, trans->transid); + btrfs_set_root_level(&log->root_item, btrfs_header_level(log->node)); + + root->log_batch = 0; + root->log_transid++; + log->log_transid = root->log_transid; + smp_mb(); + /* + * log tree has been flushed to disk, new modifications of + * the log will be written to new positions. so it's safe to + * allow log writers to go in. + */ + mutex_unlock(&root->log_mutex); + + mutex_lock(&log_root_tree->log_mutex); + log_root_tree->log_batch++; + atomic_inc(&log_root_tree->log_writers); + mutex_unlock(&log_root_tree->log_mutex); + + ret = update_log_root(trans, log); + BUG_ON(ret); + + mutex_lock(&log_root_tree->log_mutex); + if (atomic_dec_and_test(&log_root_tree->log_writers)) { + smp_mb(); + if (waitqueue_active(&log_root_tree->log_writer_wait)) + wake_up(&log_root_tree->log_writer_wait); + } + + index2 = log_root_tree->log_transid % 2; + if (atomic_read(&log_root_tree->log_commit[index2])) { + wait_log_commit(log_root_tree, log_root_tree->log_transid); + mutex_unlock(&log_root_tree->log_mutex); + goto out; + } + atomic_set(&log_root_tree->log_commit[index2], 1); + + if (atomic_read(&log_root_tree->log_commit[(index2 + 1) % 2])) + wait_log_commit(log_root_tree, log_root_tree->log_transid - 1); + + wait_for_writer(log_root_tree); + + ret = btrfs_write_and_wait_marked_extents(log_root_tree, + &log_root_tree->dirty_log_pages); BUG_ON(ret); btrfs_set_super_log_root(&root->fs_info->super_for_commit, - log->fs_info->log_root_tree->node->start); + log_root_tree->node->start); btrfs_set_super_log_root_level(&root->fs_info->super_for_commit, - btrfs_header_level(log->fs_info->log_root_tree->node)); + btrfs_header_level(log_root_tree->node)); + + log_root_tree->log_batch = 0; + log_root_tree->log_transid++; + smp_mb(); + + mutex_unlock(&log_root_tree->log_mutex); + + /* + * nobody else is going to jump in and write the the ctree + * super here because the log_commit atomic below is protecting + * us. We must be called with a transaction handle pinning + * the running transaction open, so a full commit can't hop + * in and cause problems either. + */ + write_ctree_super(trans, root->fs_info->tree_root, 2); - write_ctree_super(trans, log->fs_info->tree_root, 2); - log->fs_info->tree_log_transid++; - log->fs_info->tree_log_batch = 0; - atomic_set(&log->fs_info->tree_log_commit, 0); + atomic_set(&log_root_tree->log_commit[index2], 0); smp_mb(); - if (waitqueue_active(&log->fs_info->tree_log_wait)) - wake_up(&log->fs_info->tree_log_wait); + if (waitqueue_active(&log_root_tree->log_commit_wait[index2])) + wake_up(&log_root_tree->log_commit_wait[index2]); out: - mutex_unlock(&log->fs_info->tree_log_mutex); + atomic_set(&root->log_commit[index1], 0); + smp_mb(); + if (waitqueue_active(&root->log_commit_wait[index1])) + wake_up(&root->log_commit_wait[index1]); return 0; } @@ -2019,38 +2030,18 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root) start, end, GFP_NOFS); } - log = root->log_root; - ret = btrfs_del_root(trans, root->fs_info->log_root_tree, - &log->root_key); - BUG_ON(ret); + if (log->log_transid > 0) { + ret = btrfs_del_root(trans, root->fs_info->log_root_tree, + &log->root_key); + BUG_ON(ret); + } root->log_root = NULL; - kfree(root->log_root); + free_extent_buffer(log->node); + kfree(log); return 0; } /* - * helper function to update the item for a given subvolumes log root - * in the tree of log roots - */ -static int update_log_root(struct btrfs_trans_handle *trans, - struct btrfs_root *log) -{ - u64 bytenr = btrfs_root_bytenr(&log->root_item); - int ret; - - if (log->node->start == bytenr) - return 0; - - btrfs_set_root_bytenr(&log->root_item, log->node->start); - btrfs_set_root_generation(&log->root_item, trans->transid); - btrfs_set_root_level(&log->root_item, btrfs_header_level(log->node)); - ret = btrfs_update_root(trans, log->fs_info->log_root_tree, - &log->root_key, &log->root_item); - BUG_ON(ret); - return ret; -} - -/* * If both a file and directory are logged, and unlinks or renames are * mixed in, we have a few interesting corners: * @@ -2711,11 +2702,6 @@ next_slot: btrfs_free_path(path); btrfs_free_path(dst_path); - - mutex_lock(&root->fs_info->tree_log_mutex); - ret = update_log_root(trans, log); - BUG_ON(ret); - mutex_unlock(&root->fs_info->tree_log_mutex); out: return 0; } diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 3451e1c..bcd14eb 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -20,7 +20,6 @@ #include <linux/buffer_head.h> #include <linux/blkdev.h> #include <linux/random.h> -#include <linux/version.h> #include <asm/div64.h> #include "compat.h" #include "ctree.h" @@ -104,10 +103,8 @@ static noinline struct btrfs_device *__find_device(struct list_head *head, u64 devid, u8 *uuid) { struct btrfs_device *dev; - struct list_head *cur; - list_for_each(cur, head) { - dev = list_entry(cur, struct btrfs_device, dev_list); + list_for_each_entry(dev, head, dev_list) { if (dev->devid == devid && (!uuid || !memcmp(dev->uuid, uuid, BTRFS_UUID_SIZE))) { return dev; @@ -118,11 +115,9 @@ static noinline struct btrfs_device *__find_device(struct list_head *head, static noinline struct btrfs_fs_devices *find_fsid(u8 *fsid) { - struct list_head *cur; struct btrfs_fs_devices *fs_devices; - list_for_each(cur, &fs_uuids) { - fs_devices = list_entry(cur, struct btrfs_fs_devices, list); + list_for_each_entry(fs_devices, &fs_uuids, list) { if (memcmp(fsid, fs_devices->fsid, BTRFS_FSID_SIZE) == 0) return fs_devices; } @@ -159,6 +154,7 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) loop: spin_lock(&device->io_lock); +loop_lock: /* take all the bios off the list at once and process them * later on (without the lock held). But, remember the * tail and other pointers so the bios can be properly reinserted @@ -208,7 +204,7 @@ loop: * is now congested. Back off and let other work structs * run instead */ - if (pending && bdi_write_congested(bdi) && + if (pending && bdi_write_congested(bdi) && num_run > 16 && fs_info->fs_devices->open_devices > 1) { struct bio *old_head; @@ -220,7 +216,8 @@ loop: tail->bi_next = old_head; else device->pending_bio_tail = tail; - device->running_pending = 0; + + device->running_pending = 1; spin_unlock(&device->io_lock); btrfs_requeue_work(&device->work); @@ -229,6 +226,11 @@ loop: } if (again) goto loop; + + spin_lock(&device->io_lock); + if (device->pending_bios) + goto loop_lock; + spin_unlock(&device->io_lock); done: return 0; } @@ -345,14 +347,11 @@ error: int btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices) { - struct list_head *tmp; - struct list_head *cur; - struct btrfs_device *device; + struct btrfs_device *device, *next; mutex_lock(&uuid_mutex); again: - list_for_each_safe(cur, tmp, &fs_devices->devices) { - device = list_entry(cur, struct btrfs_device, dev_list); + list_for_each_entry_safe(device, next, &fs_devices->devices, dev_list) { if (device->in_fs_metadata) continue; @@ -383,14 +382,12 @@ again: static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices) { - struct list_head *cur; struct btrfs_device *device; if (--fs_devices->opened > 0) return 0; - list_for_each(cur, &fs_devices->devices) { - device = list_entry(cur, struct btrfs_device, dev_list); + list_for_each_entry(device, &fs_devices->devices, dev_list) { if (device->bdev) { close_bdev_exclusive(device->bdev, device->mode); fs_devices->open_devices--; @@ -439,7 +436,6 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, { struct block_device *bdev; struct list_head *head = &fs_devices->devices; - struct list_head *cur; struct btrfs_device *device; struct block_device *latest_bdev = NULL; struct buffer_head *bh; @@ -450,8 +446,7 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, int seeding = 1; int ret = 0; - list_for_each(cur, head) { - device = list_entry(cur, struct btrfs_device, dev_list); + list_for_each_entry(device, head, dev_list) { if (device->bdev) continue; if (!device->name) @@ -578,7 +573,7 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, *(unsigned long long *)disk_super->fsid, *(unsigned long long *)(disk_super->fsid + 8)); } - printk(KERN_INFO "devid %llu transid %llu %s\n", + printk(KERN_CONT "devid %llu transid %llu %s\n", (unsigned long long)devid, (unsigned long long)transid, path); ret = device_list_add(path, disk_super, devid, fs_devices_ret); @@ -1017,14 +1012,12 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) } if (strcmp(device_path, "missing") == 0) { - struct list_head *cur; struct list_head *devices; struct btrfs_device *tmp; device = NULL; devices = &root->fs_info->fs_devices->devices; - list_for_each(cur, devices) { - tmp = list_entry(cur, struct btrfs_device, dev_list); + list_for_each_entry(tmp, devices, dev_list) { if (tmp->in_fs_metadata && !tmp->bdev) { device = tmp; break; @@ -1280,7 +1273,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) struct btrfs_trans_handle *trans; struct btrfs_device *device; struct block_device *bdev; - struct list_head *cur; struct list_head *devices; struct super_block *sb = root->fs_info->sb; u64 total_bytes; @@ -1304,8 +1296,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) mutex_lock(&root->fs_info->volume_mutex); devices = &root->fs_info->fs_devices->devices; - list_for_each(cur, devices) { - device = list_entry(cur, struct btrfs_device, dev_list); + list_for_each_entry(device, devices, dev_list) { if (device->bdev == bdev) { ret = -EEXIST; goto error; @@ -1704,7 +1695,6 @@ static u64 div_factor(u64 num, int factor) int btrfs_balance(struct btrfs_root *dev_root) { int ret; - struct list_head *cur; struct list_head *devices = &dev_root->fs_info->fs_devices->devices; struct btrfs_device *device; u64 old_size; @@ -1723,8 +1713,7 @@ int btrfs_balance(struct btrfs_root *dev_root) dev_root = dev_root->fs_info->dev_root; /* step one make some room on all the devices */ - list_for_each(cur, devices) { - device = list_entry(cur, struct btrfs_device, dev_list); + list_for_each_entry(device, devices, dev_list) { old_size = device->total_bytes; size_to_free = div_factor(old_size, 1); size_to_free = min(size_to_free, (u64)1 * 1024 * 1024); diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 7f332e2..a9d3bf4 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -21,6 +21,7 @@ #include <linux/slab.h> #include <linux/rwsem.h> #include <linux/xattr.h> +#include <linux/security.h> #include "ctree.h" #include "btrfs_inode.h" #include "transaction.h" @@ -45,9 +46,12 @@ ssize_t __btrfs_getxattr(struct inode *inode, const char *name, /* lookup the xattr by name */ di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name, strlen(name), 0); - if (!di || IS_ERR(di)) { + if (!di) { ret = -ENODATA; goto out; + } else if (IS_ERR(di)) { + ret = PTR_ERR(di); + goto out; } leaf = path->nodes[0]; @@ -62,6 +66,14 @@ ssize_t __btrfs_getxattr(struct inode *inode, const char *name, ret = -ERANGE; goto out; } + + /* + * The way things are packed into the leaf is like this + * |struct btrfs_dir_item|name|data| + * where name is the xattr name, so security.foo, and data is the + * content of the xattr. data_ptr points to the location in memory + * where the data starts in the in memory leaf + */ data_ptr = (unsigned long)((char *)(di + 1) + btrfs_dir_name_len(leaf, di)); read_extent_buffer(leaf, buffer, data_ptr, @@ -86,7 +98,7 @@ int __btrfs_setxattr(struct inode *inode, const char *name, if (!path) return -ENOMEM; - trans = btrfs_start_transaction(root, 1); + trans = btrfs_join_transaction(root, 1); btrfs_set_trans_block_group(trans, inode); /* first lets see if we already have this xattr */ @@ -176,7 +188,6 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) goto err; - ret = 0; advance = 0; while (1) { leaf = path->nodes[0]; @@ -320,3 +331,34 @@ int btrfs_removexattr(struct dentry *dentry, const char *name) return -EOPNOTSUPP; return __btrfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE); } + +int btrfs_xattr_security_init(struct inode *inode, struct inode *dir) +{ + int err; + size_t len; + void *value; + char *suffix; + char *name; + + err = security_inode_init_security(inode, dir, &suffix, &value, &len); + if (err) { + if (err == -EOPNOTSUPP) + return 0; + return err; + } + + name = kmalloc(XATTR_SECURITY_PREFIX_LEN + strlen(suffix) + 1, + GFP_NOFS); + if (!name) { + err = -ENOMEM; + } else { + strcpy(name, XATTR_SECURITY_PREFIX); + strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix); + err = __btrfs_setxattr(inode, name, value, len, 0); + kfree(name); + } + + kfree(suffix); + kfree(value); + return err; +} diff --git a/fs/btrfs/xattr.h b/fs/btrfs/xattr.h index 5b1d08f..c71e9c3 100644 --- a/fs/btrfs/xattr.h +++ b/fs/btrfs/xattr.h @@ -36,4 +36,6 @@ extern int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); extern int btrfs_removexattr(struct dentry *dentry, const char *name); +extern int btrfs_xattr_security_init(struct inode *inode, struct inode *dir); + #endif /* __XATTR__ */ diff --git a/fs/buffer.c b/fs/buffer.c index b58208f..665d446 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2688,7 +2688,7 @@ int nobh_write_end(struct file *file, struct address_space *mapping, struct buffer_head *bh; BUG_ON(fsdata != NULL && page_has_buffers(page)); - if (unlikely(copied < len) && !page_has_buffers(page)) + if (unlikely(copied < len) && head) attach_nobh_buffers(page, head); if (page_has_buffers(page)) return generic_write_end(file, mapping, pos, len, diff --git a/fs/compat.c b/fs/compat.c index 65a070e..d0145ca 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1407,7 +1407,7 @@ int compat_do_execve(char * filename, bprm->cred = prepare_exec_creds(); if (!bprm->cred) goto out_unlock; - check_unsafe_exec(bprm); + check_unsafe_exec(bprm, current->files); file = open_exec(filename); retval = PTR_ERR(file); diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index c8f8d59..9c6d815 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -785,7 +785,7 @@ static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) if (copy_in_user(&sgio->status, &sgio32->status, (4 * sizeof(unsigned char)) + - (2 * sizeof(unsigned (short))) + + (2 * sizeof(unsigned short)) + (3 * sizeof(int)))) return -EFAULT; diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index c01e043..f6caeb1 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -1716,7 +1716,7 @@ static int ecryptfs_copy_filename(char **copied_name, size_t *copied_name_size, { int rc = 0; - (*copied_name) = kmalloc((name_size + 2), GFP_KERNEL); + (*copied_name) = kmalloc((name_size + 1), GFP_KERNEL); if (!(*copied_name)) { rc = -ENOMEM; goto out; @@ -1726,7 +1726,7 @@ static int ecryptfs_copy_filename(char **copied_name, size_t *copied_name_size, * in printing out the * string in debug * messages */ - (*copied_name_size) = (name_size + 1); + (*copied_name_size) = name_size; out: return rc; } @@ -1049,16 +1049,32 @@ EXPORT_SYMBOL(install_exec_creds); * - the caller must hold current->cred_exec_mutex to protect against * PTRACE_ATTACH */ -void check_unsafe_exec(struct linux_binprm *bprm) +void check_unsafe_exec(struct linux_binprm *bprm, struct files_struct *files) { - struct task_struct *p = current; + struct task_struct *p = current, *t; + unsigned long flags; + unsigned n_fs, n_files, n_sighand; bprm->unsafe = tracehook_unsafe_exec(p); - if (atomic_read(&p->fs->count) > 1 || - atomic_read(&p->files->count) > 1 || - atomic_read(&p->sighand->count) > 1) + n_fs = 1; + n_files = 1; + n_sighand = 1; + lock_task_sighand(p, &flags); + for (t = next_thread(p); t != p; t = next_thread(t)) { + if (t->fs == p->fs) + n_fs++; + if (t->files == files) + n_files++; + n_sighand++; + } + + if (atomic_read(&p->fs->count) > n_fs || + atomic_read(&p->files->count) > n_files || + atomic_read(&p->sighand->count) > n_sighand) bprm->unsafe |= LSM_UNSAFE_SHARE; + + unlock_task_sighand(p, &flags); } /* @@ -1273,7 +1289,7 @@ int do_execve(char * filename, bprm->cred = prepare_exec_creds(); if (!bprm->cred) goto out_unlock; - check_unsafe_exec(bprm); + check_unsafe_exec(bprm, displaced); file = open_exec(filename); retval = PTR_ERR(file); diff --git a/fs/internal.h b/fs/internal.h index 53af885..0d8ac49 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -43,7 +43,7 @@ extern void __init chrdev_init(void); /* * exec.c */ -extern void check_unsafe_exec(struct linux_binprm *); +extern void check_unsafe_exec(struct linux_binprm *, struct files_struct *); /* * namespace.c diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index d861096..60fe74035 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -5390,6 +5390,9 @@ int ocfs2_remove_btree_range(struct inode *inode, goto out; } + vfs_dq_free_space_nodirty(inode, + ocfs2_clusters_to_bytes(inode->i_sb, len)); + ret = ocfs2_remove_extent(inode, et, cpos, len, handle, meta_ac, dealloc); if (ret) { diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index b1cc7c3..e9d7c20 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -38,6 +38,7 @@ #include "dlmglue.h" #include "file.h" #include "inode.h" +#include "super.h" static int ocfs2_dentry_revalidate(struct dentry *dentry, @@ -294,6 +295,34 @@ out_attach: return ret; } +static DEFINE_SPINLOCK(dentry_list_lock); + +/* We limit the number of dentry locks to drop in one go. We have + * this limit so that we don't starve other users of ocfs2_wq. */ +#define DL_INODE_DROP_COUNT 64 + +/* Drop inode references from dentry locks */ +void ocfs2_drop_dl_inodes(struct work_struct *work) +{ + struct ocfs2_super *osb = container_of(work, struct ocfs2_super, + dentry_lock_work); + struct ocfs2_dentry_lock *dl; + int drop_count = DL_INODE_DROP_COUNT; + + spin_lock(&dentry_list_lock); + while (osb->dentry_lock_list && drop_count--) { + dl = osb->dentry_lock_list; + osb->dentry_lock_list = dl->dl_next; + spin_unlock(&dentry_list_lock); + iput(dl->dl_inode); + kfree(dl); + spin_lock(&dentry_list_lock); + } + if (osb->dentry_lock_list) + queue_work(ocfs2_wq, &osb->dentry_lock_work); + spin_unlock(&dentry_list_lock); +} + /* * ocfs2_dentry_iput() and friends. * @@ -318,16 +347,23 @@ out_attach: static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb, struct ocfs2_dentry_lock *dl) { - iput(dl->dl_inode); ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); ocfs2_lock_res_free(&dl->dl_lockres); - kfree(dl); + + /* We leave dropping of inode reference to ocfs2_wq as that can + * possibly lead to inode deletion which gets tricky */ + spin_lock(&dentry_list_lock); + if (!osb->dentry_lock_list) + queue_work(ocfs2_wq, &osb->dentry_lock_work); + dl->dl_next = osb->dentry_lock_list; + osb->dentry_lock_list = dl; + spin_unlock(&dentry_list_lock); } void ocfs2_dentry_lock_put(struct ocfs2_super *osb, struct ocfs2_dentry_lock *dl) { - int unlock = 0; + int unlock; BUG_ON(dl->dl_count == 0); diff --git a/fs/ocfs2/dcache.h b/fs/ocfs2/dcache.h index c091c34..d06e16c 100644 --- a/fs/ocfs2/dcache.h +++ b/fs/ocfs2/dcache.h @@ -29,8 +29,13 @@ extern struct dentry_operations ocfs2_dentry_ops; struct ocfs2_dentry_lock { + /* Use count of dentry lock */ unsigned int dl_count; - u64 dl_parent_blkno; + union { + /* Linked list of dentry locks to release */ + struct ocfs2_dentry_lock *dl_next; + u64 dl_parent_blkno; + }; /* * The ocfs2_dentry_lock keeps an inode reference until @@ -47,6 +52,8 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode, void ocfs2_dentry_lock_put(struct ocfs2_super *osb, struct ocfs2_dentry_lock *dl); +void ocfs2_drop_dl_inodes(struct work_struct *work); + struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno, int skip_unhashed); diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index b0c4cad..206a237 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -2860,6 +2860,10 @@ static void ocfs2_unlock_ast(void *opaque, int error) case OCFS2_UNLOCK_CANCEL_CONVERT: mlog(0, "Cancel convert success for %s\n", lockres->l_name); lockres->l_action = OCFS2_AST_INVALID; + /* Downconvert thread may have requeued this lock, we + * need to wake it. */ + if (lockres->l_flags & OCFS2_LOCK_BLOCKED) + ocfs2_wake_downconvert_thread(ocfs2_get_lockres_osb(lockres)); break; case OCFS2_UNLOCK_DROP_LOCK: lockres->l_level = DLM_LOCK_IV; diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index ad5c24a..0773841 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -210,6 +210,7 @@ struct ocfs2_journal; struct ocfs2_slot_info; struct ocfs2_recovery_map; struct ocfs2_quota_recovery; +struct ocfs2_dentry_lock; struct ocfs2_super { struct task_struct *commit_task; @@ -325,6 +326,11 @@ struct ocfs2_super struct list_head blocked_lock_list; unsigned long blocked_lock_count; + /* List of dentry locks to release. Anyone can add locks to + * the list, ocfs2_wq processes the list */ + struct ocfs2_dentry_lock *dentry_lock_list; + struct work_struct dentry_lock_work; + wait_queue_head_t osb_mount_event; /* Truncate log info */ diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index f4efa89..1ed0f7c 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c @@ -754,7 +754,9 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot) if (dquot->dq_flags & mask) sync = 1; spin_unlock(&dq_data_lock); - if (!sync) { + /* This is a slight hack but we can't afford getting global quota + * lock if we already have a transaction started. */ + if (!sync || journal_current_handle()) { status = ocfs2_write_dquot(dquot); goto out; } diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 43ed113..b1cb38f 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -1887,6 +1887,9 @@ static int ocfs2_initialize_super(struct super_block *sb, INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery); journal->j_state = OCFS2_JOURNAL_FREE; + INIT_WORK(&osb->dentry_lock_work, ocfs2_drop_dl_inodes); + osb->dentry_lock_list = NULL; + /* get some pseudo constants for clustersize bits */ osb->s_clustersize_bits = le32_to_cpu(di->id2.i_super.s_clustersize_bits); diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index e1d638a..915039f 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -4729,13 +4729,6 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, vb.vb_xv = (struct ocfs2_xattr_value_root *) (vb.vb_bh->b_data + offset % blocksize); - ret = ocfs2_xattr_bucket_journal_access(ctxt->handle, bucket, - OCFS2_JOURNAL_ACCESS_WRITE); - if (ret) { - mlog_errno(ret); - goto out; - } - /* * From here on out we have to dirty the bucket. The generic * value calls only modify one of the bucket's bhs, but we need @@ -4748,12 +4741,18 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, ret = ocfs2_xattr_value_truncate(inode, &vb, len, ctxt); if (ret) { mlog_errno(ret); - goto out_dirty; + goto out; + } + + ret = ocfs2_xattr_bucket_journal_access(ctxt->handle, bucket, + OCFS2_JOURNAL_ACCESS_WRITE); + if (ret) { + mlog_errno(ret); + goto out; } xe->xe_value_size = cpu_to_le64(len); -out_dirty: ocfs2_xattr_bucket_journal_dirty(ctxt->handle, bucket); out: diff --git a/fs/seq_file.c b/fs/seq_file.c index b569ff1..5267098 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -54,6 +54,64 @@ int seq_open(struct file *file, const struct seq_operations *op) } EXPORT_SYMBOL(seq_open); +static int traverse(struct seq_file *m, loff_t offset) +{ + loff_t pos = 0, index; + int error = 0; + void *p; + + m->version = 0; + index = 0; + m->count = m->from = 0; + if (!offset) { + m->index = index; + return 0; + } + if (!m->buf) { + m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL); + if (!m->buf) + return -ENOMEM; + } + p = m->op->start(m, &index); + while (p) { + error = PTR_ERR(p); + if (IS_ERR(p)) + break; + error = m->op->show(m, p); + if (error < 0) + break; + if (unlikely(error)) { + error = 0; + m->count = 0; + } + if (m->count == m->size) + goto Eoverflow; + if (pos + m->count > offset) { + m->from = offset - pos; + m->count -= m->from; + m->index = index; + break; + } + pos += m->count; + m->count = 0; + if (pos == offset) { + index++; + m->index = index; + break; + } + p = m->op->next(m, p, &index); + } + m->op->stop(m, p); + m->index = index; + return error; + +Eoverflow: + m->op->stop(m, p); + kfree(m->buf); + m->buf = kmalloc(m->size <<= 1, GFP_KERNEL); + return !m->buf ? -ENOMEM : -EAGAIN; +} + /** * seq_read - ->read() method for sequential files. * @file: the file to read from @@ -186,63 +244,6 @@ Efault: } EXPORT_SYMBOL(seq_read); -static int traverse(struct seq_file *m, loff_t offset) -{ - loff_t pos = 0, index; - int error = 0; - void *p; - - m->version = 0; - index = 0; - m->count = m->from = 0; - if (!offset) { - m->index = index; - return 0; - } - if (!m->buf) { - m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL); - if (!m->buf) - return -ENOMEM; - } - p = m->op->start(m, &index); - while (p) { - error = PTR_ERR(p); - if (IS_ERR(p)) - break; - error = m->op->show(m, p); - if (error < 0) - break; - if (unlikely(error)) { - error = 0; - m->count = 0; - } - if (m->count == m->size) - goto Eoverflow; - if (pos + m->count > offset) { - m->from = offset - pos; - m->count -= m->from; - m->index = index; - break; - } - pos += m->count; - m->count = 0; - if (pos == offset) { - index++; - m->index = index; - break; - } - p = m->op->next(m, p, &index); - } - m->op->stop(m, p); - return error; - -Eoverflow: - m->op->stop(m, p); - kfree(m->buf); - m->buf = kmalloc(m->size <<= 1, GFP_KERNEL); - return !m->buf ? -ENOMEM : -EAGAIN; -} - /** * seq_lseek - ->llseek() method for sequential files. * @file: the file in question @@ -301,7 +301,7 @@ void generic_shutdown_super(struct super_block *sb) /* * wait for asynchronous fs operations to finish before going further */ - async_synchronize_full_special(&sb->s_async_list); + async_synchronize_full_domain(&sb->s_async_list); /* bad name - it should be evict_inodes() */ invalidate_inodes(sb); @@ -470,7 +470,7 @@ restart: sb->s_count++; spin_unlock(&sb_lock); down_read(&sb->s_umount); - async_synchronize_full_special(&sb->s_async_list); + async_synchronize_full_domain(&sb->s_async_list); if (sb->s_root && (wait || sb->s_dirt)) sb->s_op->sync_fs(sb, wait); up_read(&sb->s_umount); diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 175f9c5..f393620 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -689,7 +689,7 @@ long long ubifs_reported_space(const struct ubifs_info *c, long long free) } /** - * ubifs_get_free_space - return amount of free space. + * ubifs_get_free_space_nolock - return amount of free space. * @c: UBIFS file-system description object * * This function calculates amount of free space to report to user-space. @@ -704,16 +704,14 @@ long long ubifs_reported_space(const struct ubifs_info *c, long long free) * traditional file-systems, because they have way less overhead than UBIFS. * So, to keep users happy, UBIFS tries to take the overhead into account. */ -long long ubifs_get_free_space(struct ubifs_info *c) +long long ubifs_get_free_space_nolock(struct ubifs_info *c) { - int min_idx_lebs, rsvd_idx_lebs, lebs; + int rsvd_idx_lebs, lebs; long long available, outstanding, free; - spin_lock(&c->space_lock); - min_idx_lebs = c->min_idx_lebs; - ubifs_assert(min_idx_lebs == ubifs_calc_min_idx_lebs(c)); + ubifs_assert(c->min_idx_lebs == ubifs_calc_min_idx_lebs(c)); outstanding = c->budg_data_growth + c->budg_dd_growth; - available = ubifs_calc_available(c, min_idx_lebs); + available = ubifs_calc_available(c, c->min_idx_lebs); /* * When reporting free space to user-space, UBIFS guarantees that it is @@ -726,15 +724,14 @@ long long ubifs_get_free_space(struct ubifs_info *c) * Note, the calculations below are similar to what we have in * 'do_budget_space()', so refer there for comments. */ - if (min_idx_lebs > c->lst.idx_lebs) - rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs; + if (c->min_idx_lebs > c->lst.idx_lebs) + rsvd_idx_lebs = c->min_idx_lebs - c->lst.idx_lebs; else rsvd_idx_lebs = 0; lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - c->lst.taken_empty_lebs; lebs -= rsvd_idx_lebs; available += lebs * (c->dark_wm - c->leb_overhead); - spin_unlock(&c->space_lock); if (available > outstanding) free = ubifs_reported_space(c, available - outstanding); @@ -742,3 +739,21 @@ long long ubifs_get_free_space(struct ubifs_info *c) free = 0; return free; } + +/** + * ubifs_get_free_space - return amount of free space. + * @c: UBIFS file-system description object + * + * This function calculates and retuns amount of free space to report to + * user-space. + */ +long long ubifs_get_free_space(struct ubifs_info *c) +{ + long long free; + + spin_lock(&c->space_lock); + free = ubifs_get_free_space_nolock(c); + spin_unlock(&c->space_lock); + + return free; +} diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 792c5a1..e975bd8 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -620,9 +620,11 @@ void dbg_dump_budg(struct ubifs_info *c) c->dark_wm, c->dead_wm, c->max_idx_node_sz); printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n", c->gc_lnum, c->ihead_lnum); - for (i = 0; i < c->jhead_cnt; i++) - printk(KERN_DEBUG "\tjhead %d\t LEB %d\n", - c->jheads[i].wbuf.jhead, c->jheads[i].wbuf.lnum); + /* If we are in R/O mode, journal heads do not exist */ + if (c->jheads) + for (i = 0; i < c->jhead_cnt; i++) + printk(KERN_DEBUG "\tjhead %d\t LEB %d\n", + c->jheads[i].wbuf.jhead, c->jheads[i].wbuf.lnum); for (rb = rb_first(&c->buds); rb; rb = rb_next(rb)) { bud = rb_entry(rb, struct ubifs_bud, rb); printk(KERN_DEBUG "\tbud LEB %d\n", bud->lnum); @@ -637,10 +639,7 @@ void dbg_dump_budg(struct ubifs_info *c) /* Print budgeting predictions */ available = ubifs_calc_available(c, c->min_idx_lebs); outstanding = c->budg_data_growth + c->budg_dd_growth; - if (available > outstanding) - free = ubifs_reported_space(c, available - outstanding); - else - free = 0; + free = ubifs_get_free_space_nolock(c); printk(KERN_DEBUG "Budgeting predictions:\n"); printk(KERN_DEBUG "\tavailable: %lld, outstanding %lld, free %lld\n", available, outstanding, free); @@ -861,6 +860,65 @@ void dbg_dump_index(struct ubifs_info *c) } /** + * dbg_save_space_info - save information about flash space. + * @c: UBIFS file-system description object + * + * This function saves information about UBIFS free space, dirty space, etc, in + * order to check it later. + */ +void dbg_save_space_info(struct ubifs_info *c) +{ + struct ubifs_debug_info *d = c->dbg; + + ubifs_get_lp_stats(c, &d->saved_lst); + + spin_lock(&c->space_lock); + d->saved_free = ubifs_get_free_space_nolock(c); + spin_unlock(&c->space_lock); +} + +/** + * dbg_check_space_info - check flash space information. + * @c: UBIFS file-system description object + * + * This function compares current flash space information with the information + * which was saved when the 'dbg_save_space_info()' function was called. + * Returns zero if the information has not changed, and %-EINVAL it it has + * changed. + */ +int dbg_check_space_info(struct ubifs_info *c) +{ + struct ubifs_debug_info *d = c->dbg; + struct ubifs_lp_stats lst; + long long avail, free; + + spin_lock(&c->space_lock); + avail = ubifs_calc_available(c, c->min_idx_lebs); + spin_unlock(&c->space_lock); + free = ubifs_get_free_space(c); + + if (free != d->saved_free) { + ubifs_err("free space changed from %lld to %lld", + d->saved_free, free); + goto out; + } + + return 0; + +out: + ubifs_msg("saved lprops statistics dump"); + dbg_dump_lstats(&d->saved_lst); + ubifs_get_lp_stats(c, &lst); + ubifs_msg("current lprops statistics dump"); + dbg_dump_lstats(&d->saved_lst); + spin_lock(&c->space_lock); + dbg_dump_budg(c); + spin_unlock(&c->space_lock); + dump_stack(); + return -EINVAL; +} + +/** * dbg_check_synced_i_size - check synchronized inode size. * @inode: inode to check * @@ -1349,7 +1407,7 @@ int dbg_check_tnc(struct ubifs_info *c, int extra) * @c: UBIFS file-system description object * @leaf_cb: called for each leaf node * @znode_cb: called for each indexing node - * @priv: private date which is passed to callbacks + * @priv: private data which is passed to callbacks * * This function walks the UBIFS index and calls the @leaf_cb for each leaf * node and @znode_cb for each indexing node. Returns zero in case of success @@ -2409,7 +2467,7 @@ void ubifs_debugging_exit(struct ubifs_info *c) * Root directory for UBIFS stuff in debugfs. Contains sub-directories which * contain the stuff specific to particular file-system mounts. */ -static struct dentry *debugfs_rootdir; +static struct dentry *dfs_rootdir; /** * dbg_debugfs_init - initialize debugfs file-system. @@ -2421,9 +2479,9 @@ static struct dentry *debugfs_rootdir; */ int dbg_debugfs_init(void) { - debugfs_rootdir = debugfs_create_dir("ubifs", NULL); - if (IS_ERR(debugfs_rootdir)) { - int err = PTR_ERR(debugfs_rootdir); + dfs_rootdir = debugfs_create_dir("ubifs", NULL); + if (IS_ERR(dfs_rootdir)) { + int err = PTR_ERR(dfs_rootdir); ubifs_err("cannot create \"ubifs\" debugfs directory, " "error %d\n", err); return err; @@ -2437,7 +2495,7 @@ int dbg_debugfs_init(void) */ void dbg_debugfs_exit(void) { - debugfs_remove(debugfs_rootdir); + debugfs_remove(dfs_rootdir); } static int open_debugfs_file(struct inode *inode, struct file *file) @@ -2452,13 +2510,13 @@ static ssize_t write_debugfs_file(struct file *file, const char __user *buf, struct ubifs_info *c = file->private_data; struct ubifs_debug_info *d = c->dbg; - if (file->f_path.dentry == d->dump_lprops) + if (file->f_path.dentry == d->dfs_dump_lprops) dbg_dump_lprops(c); - else if (file->f_path.dentry == d->dump_budg) { + else if (file->f_path.dentry == d->dfs_dump_budg) { spin_lock(&c->space_lock); dbg_dump_budg(c); spin_unlock(&c->space_lock); - } else if (file->f_path.dentry == d->dump_tnc) { + } else if (file->f_path.dentry == d->dfs_dump_tnc) { mutex_lock(&c->tnc_mutex); dbg_dump_tnc(c); mutex_unlock(&c->tnc_mutex); @@ -2469,7 +2527,7 @@ static ssize_t write_debugfs_file(struct file *file, const char __user *buf, return count; } -static const struct file_operations debugfs_fops = { +static const struct file_operations dfs_fops = { .open = open_debugfs_file, .write = write_debugfs_file, .owner = THIS_MODULE, @@ -2494,36 +2552,32 @@ int dbg_debugfs_init_fs(struct ubifs_info *c) struct dentry *dent; struct ubifs_debug_info *d = c->dbg; - sprintf(d->debugfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); - d->debugfs_dir = debugfs_create_dir(d->debugfs_dir_name, - debugfs_rootdir); - if (IS_ERR(d->debugfs_dir)) { - err = PTR_ERR(d->debugfs_dir); + sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); + d->dfs_dir = debugfs_create_dir(d->dfs_dir_name, dfs_rootdir); + if (IS_ERR(d->dfs_dir)) { + err = PTR_ERR(d->dfs_dir); ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", - d->debugfs_dir_name, err); + d->dfs_dir_name, err); goto out; } fname = "dump_lprops"; - dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c, - &debugfs_fops); + dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); if (IS_ERR(dent)) goto out_remove; - d->dump_lprops = dent; + d->dfs_dump_lprops = dent; fname = "dump_budg"; - dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c, - &debugfs_fops); + dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); if (IS_ERR(dent)) goto out_remove; - d->dump_budg = dent; + d->dfs_dump_budg = dent; fname = "dump_tnc"; - dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c, - &debugfs_fops); + dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); if (IS_ERR(dent)) goto out_remove; - d->dump_tnc = dent; + d->dfs_dump_tnc = dent; return 0; @@ -2531,7 +2585,7 @@ out_remove: err = PTR_ERR(dent); ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", fname, err); - debugfs_remove_recursive(d->debugfs_dir); + debugfs_remove_recursive(d->dfs_dir); out: return err; } @@ -2542,7 +2596,7 @@ out: */ void dbg_debugfs_exit_fs(struct ubifs_info *c) { - debugfs_remove_recursive(c->dbg->debugfs_dir); + debugfs_remove_recursive(c->dbg->dfs_dir); } #endif /* CONFIG_UBIFS_FS_DEBUG */ diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index 9820d69..c1cd73b 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h @@ -41,15 +41,17 @@ * @chk_lpt_wastage: used by LPT tree size checker * @chk_lpt_lebs: used by LPT tree size checker * @new_nhead_offs: used by LPT tree size checker - * @new_ihead_lnum: used by debugging to check ihead_lnum - * @new_ihead_offs: used by debugging to check ihead_offs + * @new_ihead_lnum: used by debugging to check @c->ihead_lnum + * @new_ihead_offs: used by debugging to check @c->ihead_offs * - * debugfs_dir_name: name of debugfs directory containing this file-system's - * files - * debugfs_dir: direntry object of the file-system debugfs directory - * dump_lprops: "dump lprops" debugfs knob - * dump_budg: "dump budgeting information" debugfs knob - * dump_tnc: "dump TNC" debugfs knob + * @saved_lst: saved lprops statistics (used by 'dbg_save_space_info()') + * @saved_free: saved free space (used by 'dbg_save_space_info()') + * + * dfs_dir_name: name of debugfs directory containing this file-system's files + * dfs_dir: direntry object of the file-system debugfs directory + * dfs_dump_lprops: "dump lprops" debugfs knob + * dfs_dump_budg: "dump budgeting information" debugfs knob + * dfs_dump_tnc: "dump TNC" debugfs knob */ struct ubifs_debug_info { void *buf; @@ -69,11 +71,14 @@ struct ubifs_debug_info { int new_ihead_lnum; int new_ihead_offs; - char debugfs_dir_name[100]; - struct dentry *debugfs_dir; - struct dentry *dump_lprops; - struct dentry *dump_budg; - struct dentry *dump_tnc; + struct ubifs_lp_stats saved_lst; + long long saved_free; + + char dfs_dir_name[100]; + struct dentry *dfs_dir; + struct dentry *dfs_dump_lprops; + struct dentry *dfs_dump_budg; + struct dentry *dfs_dump_tnc; }; #define ubifs_assert(expr) do { \ @@ -297,7 +302,8 @@ int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb, dbg_znode_callback znode_cb, void *priv); /* Checking functions */ - +void dbg_save_space_info(struct ubifs_info *c); +int dbg_check_space_info(struct ubifs_info *c); int dbg_check_lprops(struct ubifs_info *c); int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot); int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot); @@ -439,6 +445,8 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c); #define dbg_walk_index(c, leaf_cb, znode_cb, priv) 0 #define dbg_old_index_check_init(c, zroot) 0 +#define dbg_save_space_info(c) ({}) +#define dbg_check_space_info(c) 0 #define dbg_check_old_index(c, zroot) 0 #define dbg_check_cats(c) 0 #define dbg_check_ltab(c) 0 diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index f448ab1..f55d523 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -482,30 +482,29 @@ static int ubifs_dir_release(struct inode *dir, struct file *file) } /** - * lock_2_inodes - lock two UBIFS inodes. + * lock_2_inodes - a wrapper for locking two UBIFS inodes. * @inode1: first inode * @inode2: second inode + * + * We do not implement any tricks to guarantee strict lock ordering, because + * VFS has already done it for us on the @i_mutex. So this is just a simple + * wrapper function. */ static void lock_2_inodes(struct inode *inode1, struct inode *inode2) { - if (inode1->i_ino < inode2->i_ino) { - mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_2); - mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_3); - } else { - mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2); - mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_3); - } + mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1); + mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2); } /** - * unlock_2_inodes - unlock two UBIFS inodes inodes. + * unlock_2_inodes - a wrapper for unlocking two UBIFS inodes. * @inode1: first inode * @inode2: second inode */ static void unlock_2_inodes(struct inode *inode1, struct inode *inode2) { - mutex_unlock(&ubifs_inode(inode1)->ui_mutex); mutex_unlock(&ubifs_inode(inode2)->ui_mutex); + mutex_unlock(&ubifs_inode(inode1)->ui_mutex); } static int ubifs_link(struct dentry *old_dentry, struct inode *dir, @@ -527,6 +526,8 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir, dbg_gen("dent '%.*s' to ino %lu (nlink %d) in dir ino %lu", dentry->d_name.len, dentry->d_name.name, inode->i_ino, inode->i_nlink, dir->i_ino); + ubifs_assert(mutex_is_locked(&dir->i_mutex)); + ubifs_assert(mutex_is_locked(&inode->i_mutex)); err = dbg_check_synced_i_size(inode); if (err) return err; @@ -580,6 +581,8 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry) dbg_gen("dent '%.*s' from ino %lu (nlink %d) in dir ino %lu", dentry->d_name.len, dentry->d_name.name, inode->i_ino, inode->i_nlink, dir->i_ino); + ubifs_assert(mutex_is_locked(&dir->i_mutex)); + ubifs_assert(mutex_is_locked(&inode->i_mutex)); err = dbg_check_synced_i_size(inode); if (err) return err; @@ -667,7 +670,8 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry) dbg_gen("directory '%.*s', ino %lu in dir ino %lu", dentry->d_name.len, dentry->d_name.name, inode->i_ino, dir->i_ino); - + ubifs_assert(mutex_is_locked(&dir->i_mutex)); + ubifs_assert(mutex_is_locked(&inode->i_mutex)); err = check_dir_empty(c, dentry->d_inode); if (err) return err; @@ -922,59 +926,30 @@ out_budg: } /** - * lock_3_inodes - lock three UBIFS inodes for rename. + * lock_3_inodes - a wrapper for locking three UBIFS inodes. * @inode1: first inode * @inode2: second inode * @inode3: third inode * - * For 'ubifs_rename()', @inode1 may be the same as @inode2 whereas @inode3 may - * be null. + * This function is used for 'ubifs_rename()' and @inode1 may be the same as + * @inode2 whereas @inode3 may be %NULL. + * + * We do not implement any tricks to guarantee strict lock ordering, because + * VFS has already done it for us on the @i_mutex. So this is just a simple + * wrapper function. */ static void lock_3_inodes(struct inode *inode1, struct inode *inode2, struct inode *inode3) { - struct inode *i1, *i2, *i3; - - if (!inode3) { - if (inode1 != inode2) { - lock_2_inodes(inode1, inode2); - return; - } - mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1); - return; - } - - if (inode1 == inode2) { - lock_2_inodes(inode1, inode3); - return; - } - - /* 3 different inodes */ - if (inode1 < inode2) { - i3 = inode2; - if (inode1 < inode3) { - i1 = inode1; - i2 = inode3; - } else { - i1 = inode3; - i2 = inode1; - } - } else { - i3 = inode1; - if (inode2 < inode3) { - i1 = inode2; - i2 = inode3; - } else { - i1 = inode3; - i2 = inode2; - } - } - mutex_lock_nested(&ubifs_inode(i1)->ui_mutex, WB_MUTEX_1); - lock_2_inodes(i2, i3); + mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1); + if (inode2 != inode1) + mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2); + if (inode3) + mutex_lock_nested(&ubifs_inode(inode3)->ui_mutex, WB_MUTEX_3); } /** - * unlock_3_inodes - unlock three UBIFS inodes for rename. + * unlock_3_inodes - a wrapper for unlocking three UBIFS inodes for rename. * @inode1: first inode * @inode2: second inode * @inode3: third inode @@ -982,11 +957,11 @@ static void lock_3_inodes(struct inode *inode1, struct inode *inode2, static void unlock_3_inodes(struct inode *inode1, struct inode *inode2, struct inode *inode3) { - mutex_unlock(&ubifs_inode(inode1)->ui_mutex); - if (inode1 != inode2) - mutex_unlock(&ubifs_inode(inode2)->ui_mutex); if (inode3) mutex_unlock(&ubifs_inode(inode3)->ui_mutex); + if (inode1 != inode2) + mutex_unlock(&ubifs_inode(inode2)->ui_mutex); + mutex_unlock(&ubifs_inode(inode1)->ui_mutex); } static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry, @@ -1020,6 +995,11 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry, "dir ino %lu", old_dentry->d_name.len, old_dentry->d_name.name, old_inode->i_ino, old_dir->i_ino, new_dentry->d_name.len, new_dentry->d_name.name, new_dir->i_ino); + ubifs_assert(mutex_is_locked(&old_dir->i_mutex)); + ubifs_assert(mutex_is_locked(&new_dir->i_mutex)); + if (unlink) + ubifs_assert(mutex_is_locked(&new_inode->i_mutex)); + if (unlink && is_dir) { err = check_dir_empty(c, new_inode); @@ -1199,7 +1179,7 @@ int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry, return 0; } -struct inode_operations ubifs_dir_inode_operations = { +const struct inode_operations ubifs_dir_inode_operations = { .lookup = ubifs_lookup, .create = ubifs_create, .link = ubifs_link, @@ -1219,7 +1199,7 @@ struct inode_operations ubifs_dir_inode_operations = { #endif }; -struct file_operations ubifs_dir_operations = { +const struct file_operations ubifs_dir_operations = { .llseek = ubifs_dir_llseek, .release = ubifs_dir_release, .read = generic_read_dir, diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index bf37374..93b6de5 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -432,7 +432,6 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping, int uninitialized_var(err), appending = !!(pos + len > inode->i_size); struct page *page; - ubifs_assert(ubifs_inode(inode)->ui_size == inode->i_size); if (unlikely(c->ro_media)) @@ -1541,7 +1540,7 @@ static int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -struct address_space_operations ubifs_file_address_operations = { +const struct address_space_operations ubifs_file_address_operations = { .readpage = ubifs_readpage, .writepage = ubifs_writepage, .write_begin = ubifs_write_begin, @@ -1551,7 +1550,7 @@ struct address_space_operations ubifs_file_address_operations = { .releasepage = ubifs_releasepage, }; -struct inode_operations ubifs_file_inode_operations = { +const struct inode_operations ubifs_file_inode_operations = { .setattr = ubifs_setattr, .getattr = ubifs_getattr, #ifdef CONFIG_UBIFS_FS_XATTR @@ -1562,14 +1561,14 @@ struct inode_operations ubifs_file_inode_operations = { #endif }; -struct inode_operations ubifs_symlink_inode_operations = { +const struct inode_operations ubifs_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = ubifs_follow_link, .setattr = ubifs_setattr, .getattr = ubifs_getattr, }; -struct file_operations ubifs_file_operations = { +const struct file_operations ubifs_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, .write = do_sync_write, diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 9832f9a..a711d33 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -31,6 +31,26 @@ * to be reused. Garbage collection will cause the number of dirty index nodes * to grow, however sufficient space is reserved for the index to ensure the * commit will never run out of space. + * + * Notes about dead watermark. At current UBIFS implementation we assume that + * LEBs which have less than @c->dead_wm bytes of free + dirty space are full + * and not worth garbage-collecting. The dead watermark is one min. I/O unit + * size, or min. UBIFS node size, depending on what is greater. Indeed, UBIFS + * Garbage Collector has to synchronize the GC head's write buffer before + * returning, so this is about wasting one min. I/O unit. However, UBIFS GC can + * actually reclaim even very small pieces of dirty space by garbage collecting + * enough dirty LEBs, but we do not bother doing this at this implementation. + * + * Notes about dark watermark. The results of GC work depends on how big are + * the UBIFS nodes GC deals with. Large nodes make GC waste more space. Indeed, + * if GC move data from LEB A to LEB B and nodes in LEB A are large, GC would + * have to waste large pieces of free space at the end of LEB B, because nodes + * from LEB A would not fit. And the worst situation is when all nodes are of + * maximum size. So dark watermark is the amount of free + dirty space in LEB + * which are guaranteed to be reclaimable. If LEB has less space, the GC migh + * be unable to reclaim it. So, LEBs with free + dirty greater than dark + * watermark are "good" LEBs from GC's point of few. The other LEBs are not so + * good, and GC takes extra care when moving them. */ #include <linux/pagemap.h> @@ -381,7 +401,7 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) /* * Don't release the LEB until after the next commit, because - * it may contain date which is needed for recovery. So + * it may contain data which is needed for recovery. So * although we freed this LEB, it will become usable only after * the commit. */ @@ -810,8 +830,9 @@ out: * ubifs_destroy_idx_gc - destroy idx_gc list. * @c: UBIFS file-system description object * - * This function destroys the idx_gc list. It is called when unmounting or - * remounting read-only so locks are not needed. + * This function destroys the @c->idx_gc list. It is called when unmounting + * so locks are not needed. Returns zero in case of success and a negative + * error code in case of failure. */ void ubifs_destroy_idx_gc(struct ubifs_info *c) { @@ -824,7 +845,6 @@ void ubifs_destroy_idx_gc(struct ubifs_info *c) list_del(&idx_gc->list); kfree(idx_gc); } - } /** diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index 0168271..e8e632a 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -29,7 +29,7 @@ * would have been wasted for padding to the nearest minimal I/O unit boundary. * Instead, data first goes to the write-buffer and is flushed when the * buffer is full or when it is not used for some time (by timer). This is - * similarto the mechanism is used by JFFS2. + * similar to the mechanism is used by JFFS2. * * Write-buffers are defined by 'struct ubifs_wbuf' objects and protected by * mutexes defined inside these objects. Since sometimes upper-level code @@ -75,7 +75,7 @@ void ubifs_ro_mode(struct ubifs_info *c, int err) * @lnum: logical eraseblock number * @offs: offset within the logical eraseblock * @quiet: print no messages - * @chk_crc: indicates whether to always check the CRC + * @must_chk_crc: indicates whether to always check the CRC * * This function checks node magic number and CRC checksum. This function also * validates node length to prevent UBIFS from becoming crazy when an attacker @@ -83,11 +83,17 @@ void ubifs_ro_mode(struct ubifs_info *c, int err) * node length in the common header could cause UBIFS to read memory outside of * allocated buffer when checking the CRC checksum. * - * This function returns zero in case of success %-EUCLEAN in case of bad CRC - * or magic. + * This function may skip data nodes CRC checking if @c->no_chk_data_crc is + * true, which is controlled by corresponding UBIFS mount option. However, if + * @must_chk_crc is true, then @c->no_chk_data_crc is ignored and CRC is + * checked. Similarly, if @c->always_chk_crc is true, @c->no_chk_data_crc is + * ignored and CRC is checked. + * + * This function returns zero in case of success and %-EUCLEAN in case of bad + * CRC or magic. */ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, - int offs, int quiet, int chk_crc) + int offs, int quiet, int must_chk_crc) { int err = -EINVAL, type, node_len; uint32_t crc, node_crc, magic; @@ -123,9 +129,9 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, node_len > c->ranges[type].max_len) goto out_len; - if (!chk_crc && type == UBIFS_DATA_NODE && !c->always_chk_crc) - if (c->no_chk_data_crc) - return 0; + if (!must_chk_crc && type == UBIFS_DATA_NODE && !c->always_chk_crc && + c->no_chk_data_crc) + return 0; crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); node_crc = le32_to_cpu(ch->crc); diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 9b7c54e..a11ca09 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -208,7 +208,7 @@ again: offs = 0; out: - err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs, UBI_SHORTTERM); + err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs, wbuf->dtype); if (err) goto out_unlock; diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c index dfd2bce..4cdd284 100644 --- a/fs/ubifs/lprops.c +++ b/fs/ubifs/lprops.c @@ -635,10 +635,10 @@ const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c, * @c: UBIFS file-system description object * @st: return statistics */ -void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *st) +void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *lst) { spin_lock(&c->space_lock); - memcpy(st, &c->lst, sizeof(struct ubifs_lp_stats)); + memcpy(lst, &c->lst, sizeof(struct ubifs_lp_stats)); spin_unlock(&c->space_lock); } @@ -678,6 +678,9 @@ int ubifs_change_one_lp(struct ubifs_info *c, int lnum, int free, int dirty, out: ubifs_release_lprops(c); + if (err) + ubifs_err("cannot change properties of LEB %d, error %d", + lnum, err); return err; } @@ -714,6 +717,9 @@ int ubifs_update_one_lp(struct ubifs_info *c, int lnum, int free, int dirty, out: ubifs_release_lprops(c); + if (err) + ubifs_err("cannot update properties of LEB %d, error %d", + lnum, err); return err; } @@ -737,6 +743,8 @@ int ubifs_read_one_lp(struct ubifs_info *c, int lnum, struct ubifs_lprops *lp) lpp = ubifs_lpt_lookup(c, lnum); if (IS_ERR(lpp)) { err = PTR_ERR(lpp); + ubifs_err("cannot read properties of LEB %d, error %d", + lnum, err); goto out; } diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c index 96ca957..3216a1f 100644 --- a/fs/ubifs/lpt_commit.c +++ b/fs/ubifs/lpt_commit.c @@ -556,23 +556,23 @@ no_space: } /** - * next_pnode - find next pnode. + * next_pnode_to_dirty - find next pnode to dirty. * @c: UBIFS file-system description object * @pnode: pnode * - * This function returns the next pnode or %NULL if there are no more pnodes. + * This function returns the next pnode to dirty or %NULL if there are no more + * pnodes. Note that pnodes that have never been written (lnum == 0) are + * skipped. */ -static struct ubifs_pnode *next_pnode(struct ubifs_info *c, - struct ubifs_pnode *pnode) +static struct ubifs_pnode *next_pnode_to_dirty(struct ubifs_info *c, + struct ubifs_pnode *pnode) { struct ubifs_nnode *nnode; int iip; /* Try to go right */ nnode = pnode->parent; - iip = pnode->iip + 1; - if (iip < UBIFS_LPT_FANOUT) { - /* We assume here that LEB zero is never an LPT LEB */ + for (iip = pnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) { if (nnode->nbranch[iip].lnum) return ubifs_get_pnode(c, nnode, iip); } @@ -583,8 +583,11 @@ static struct ubifs_pnode *next_pnode(struct ubifs_info *c, nnode = nnode->parent; if (!nnode) return NULL; - /* We assume here that LEB zero is never an LPT LEB */ - } while (iip >= UBIFS_LPT_FANOUT || !nnode->nbranch[iip].lnum); + for (; iip < UBIFS_LPT_FANOUT; iip++) { + if (nnode->nbranch[iip].lnum) + break; + } + } while (iip >= UBIFS_LPT_FANOUT); /* Go right */ nnode = ubifs_get_nnode(c, nnode, iip); @@ -593,12 +596,29 @@ static struct ubifs_pnode *next_pnode(struct ubifs_info *c, /* Go down to level 1 */ while (nnode->level > 1) { - nnode = ubifs_get_nnode(c, nnode, 0); + for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++) { + if (nnode->nbranch[iip].lnum) + break; + } + if (iip >= UBIFS_LPT_FANOUT) { + /* + * Should not happen, but we need to keep going + * if it does. + */ + iip = 0; + } + nnode = ubifs_get_nnode(c, nnode, iip); if (IS_ERR(nnode)) return (void *)nnode; } - return ubifs_get_pnode(c, nnode, 0); + for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++) + if (nnode->nbranch[iip].lnum) + break; + if (iip >= UBIFS_LPT_FANOUT) + /* Should not happen, but we need to keep going if it does */ + iip = 0; + return ubifs_get_pnode(c, nnode, iip); } /** @@ -688,7 +708,7 @@ static int make_tree_dirty(struct ubifs_info *c) pnode = pnode_lookup(c, 0); while (pnode) { do_make_pnode_dirty(c, pnode); - pnode = next_pnode(c, pnode); + pnode = next_pnode_to_dirty(c, pnode); if (IS_ERR(pnode)) return PTR_ERR(pnode); } diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c index 71d5493..a88f338 100644 --- a/fs/ubifs/master.c +++ b/fs/ubifs/master.c @@ -354,7 +354,7 @@ int ubifs_write_master(struct ubifs_info *c) int err, lnum, offs, len; if (c->ro_media) - return -EINVAL; + return -EROFS; lnum = UBIFS_MST_LNUM; offs = c->mst_offs + c->mst_node_alsz; diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c index 9e6f403..152a7b3 100644 --- a/fs/ubifs/orphan.c +++ b/fs/ubifs/orphan.c @@ -46,7 +46,7 @@ * Orphans are accumulated in a rb-tree. When an inode's link count drops to * zero, the inode number is added to the rb-tree. It is removed from the tree * when the inode is deleted. Any new orphans that are in the orphan tree when - * the commit is run, are written to the orphan area in 1 or more orph nodes. + * the commit is run, are written to the orphan area in 1 or more orphan nodes. * If the orphan area is full, it is consolidated to make space. There is * always enough space because validation prevents the user from creating more * than the maximum number of orphans allowed. @@ -231,7 +231,7 @@ static int tot_avail_orphs(struct ubifs_info *c) } /** - * do_write_orph_node - write a node + * do_write_orph_node - write a node to the orphan head. * @c: UBIFS file-system description object * @len: length of node * @atomic: write atomically @@ -264,11 +264,11 @@ static int do_write_orph_node(struct ubifs_info *c, int len, int atomic) } /** - * write_orph_node - write an orph node + * write_orph_node - write an orphan node. * @c: UBIFS file-system description object * @atomic: write atomically * - * This function builds an orph node from the cnext list and writes it to the + * This function builds an orphan node from the cnext list and writes it to the * orphan head. On success, %0 is returned, otherwise a negative error code * is returned. */ @@ -326,11 +326,11 @@ static int write_orph_node(struct ubifs_info *c, int atomic) } /** - * write_orph_nodes - write orph nodes until there are no more to commit + * write_orph_nodes - write orphan nodes until there are no more to commit. * @c: UBIFS file-system description object * @atomic: write atomically * - * This function writes orph nodes for all the orphans to commit. On success, + * This function writes orphan nodes for all the orphans to commit. On success, * %0 is returned, otherwise a negative error code is returned. */ static int write_orph_nodes(struct ubifs_info *c, int atomic) @@ -478,14 +478,14 @@ int ubifs_orphan_end_commit(struct ubifs_info *c) } /** - * clear_orphans - erase all LEBs used for orphans. + * ubifs_clear_orphans - erase all LEBs used for orphans. * @c: UBIFS file-system description object * * If recovery is not required, then the orphans from the previous session * are not needed. This function locates the LEBs used to record * orphans, and un-maps them. */ -static int clear_orphans(struct ubifs_info *c) +int ubifs_clear_orphans(struct ubifs_info *c) { int lnum, err; @@ -547,9 +547,9 @@ static int insert_dead_orphan(struct ubifs_info *c, ino_t inum) * do_kill_orphans - remove orphan inodes from the index. * @c: UBIFS file-system description object * @sleb: scanned LEB - * @last_cmt_no: cmt_no of last orph node read is passed and returned here + * @last_cmt_no: cmt_no of last orphan node read is passed and returned here * @outofdate: whether the LEB is out of date is returned here - * @last_flagged: whether the end orph node is encountered + * @last_flagged: whether the end orphan node is encountered * * This function is a helper to the 'kill_orphans()' function. It goes through * every orphan node in a LEB and for every inode number recorded, removes @@ -580,8 +580,8 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb, /* * The commit number on the master node may be less, because * of a failed commit. If there are several failed commits in a - * row, the commit number written on orph nodes will continue to - * increase (because the commit number is adjusted here) even + * row, the commit number written on orphan nodes will continue + * to increase (because the commit number is adjusted here) even * though the commit number on the master node stays the same * because the master node has not been re-written. */ @@ -589,9 +589,9 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb, c->cmt_no = cmt_no; if (cmt_no < *last_cmt_no && *last_flagged) { /* - * The last orph node had a higher commit number and was - * flagged as the last written for that commit number. - * That makes this orph node, out of date. + * The last orphan node had a higher commit number and + * was flagged as the last written for that commit + * number. That makes this orphan node, out of date. */ if (!first) { ubifs_err("out of order commit number %llu in " @@ -658,10 +658,10 @@ static int kill_orphans(struct ubifs_info *c) /* * Orph nodes always start at c->orph_first and are written to each * successive LEB in turn. Generally unused LEBs will have been unmapped - * but may contain out of date orph nodes if the unmap didn't go - * through. In addition, the last orph node written for each commit is + * but may contain out of date orphan nodes if the unmap didn't go + * through. In addition, the last orphan node written for each commit is * marked (top bit of orph->cmt_no is set to 1). It is possible that - * there are orph nodes from the next commit (i.e. the commit did not + * there are orphan nodes from the next commit (i.e. the commit did not * complete successfully). In that case, no orphans will have been lost * due to the way that orphans are written, and any orphans added will * be valid orphans anyway and so can be deleted. @@ -718,7 +718,7 @@ int ubifs_mount_orphans(struct ubifs_info *c, int unclean, int read_only) if (unclean) err = kill_orphans(c); else if (!read_only) - err = clear_orphans(c); + err = ubifs_clear_orphans(c); return err; } diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 89556ee..1182b66 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -397,6 +397,7 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_namelen = UBIFS_MAX_NLEN; buf->f_fsid.val[0] = le32_to_cpu(uuid[0]) ^ le32_to_cpu(uuid[2]); buf->f_fsid.val[1] = le32_to_cpu(uuid[1]) ^ le32_to_cpu(uuid[3]); + ubifs_assert(buf->f_bfree <= c->block_cnt); return 0; } @@ -432,33 +433,24 @@ static int ubifs_sync_fs(struct super_block *sb, int wait) int i, err; struct ubifs_info *c = sb->s_fs_info; struct writeback_control wbc = { - .sync_mode = wait ? WB_SYNC_ALL : WB_SYNC_NONE, + .sync_mode = WB_SYNC_ALL, .range_start = 0, .range_end = LLONG_MAX, .nr_to_write = LONG_MAX, }; /* - * Note by akpm about WB_SYNC_NONE used above: zero @wait is just an - * advisory thing to help the file system shove lots of data into the - * queues. If some gets missed then it'll be picked up on the second + * Zero @wait is just an advisory thing to help the file system shove + * lots of data into the queues, and there will be the second * '->sync_fs()' call, with non-zero @wait. */ + if (!wait) + return 0; if (sb->s_flags & MS_RDONLY) return 0; /* - * Synchronize write buffers, because 'ubifs_run_commit()' does not - * do this if it waits for an already running commit. - */ - for (i = 0; i < c->jhead_cnt; i++) { - err = ubifs_wbuf_sync(&c->jheads[i].wbuf); - if (err) - return err; - } - - /* * VFS calls '->sync_fs()' before synchronizing all dirty inodes and * pages, so synchronize them first, then commit the journal. Strictly * speaking, it is not necessary to commit the journal here, @@ -469,6 +461,16 @@ static int ubifs_sync_fs(struct super_block *sb, int wait) */ generic_sync_sb_inodes(sb, &wbc); + /* + * Synchronize write buffers, because 'ubifs_run_commit()' does not + * do this if it waits for an already running commit. + */ + for (i = 0; i < c->jhead_cnt; i++) { + err = ubifs_wbuf_sync(&c->jheads[i].wbuf); + if (err) + return err; + } + err = ubifs_run_commit(c); if (err) return err; @@ -572,15 +574,8 @@ static int init_constants_early(struct ubifs_info *c) c->ranges[UBIFS_IDX_NODE].max_len = INT_MAX; /* - * Initialize dead and dark LEB space watermarks. - * - * Dead space is the space which cannot be used. Its watermark is - * equivalent to min. I/O unit or minimum node size if it is greater - * then min. I/O unit. - * - * Dark space is the space which might be used, or might not, depending - * on which node should be written to the LEB. Its watermark is - * equivalent to maximum UBIFS node size. + * Initialize dead and dark LEB space watermarks. See gc.c for comments + * about these values. */ c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size); c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size); @@ -741,12 +736,12 @@ static void init_constants_master(struct ubifs_info *c) * take_gc_lnum - reserve GC LEB. * @c: UBIFS file-system description object * - * This function ensures that the LEB reserved for garbage collection is - * unmapped and is marked as "taken" in lprops. We also have to set free space - * to LEB size and dirty space to zero, because lprops may contain out-of-date - * information if the file-system was un-mounted before it has been committed. - * This function returns zero in case of success and a negative error code in - * case of failure. + * This function ensures that the LEB reserved for garbage collection is marked + * as "taken" in lprops. We also have to set free space to LEB size and dirty + * space to zero, because lprops may contain out-of-date information if the + * file-system was un-mounted before it has been committed. This function + * returns zero in case of success and a negative error code in case of + * failure. */ static int take_gc_lnum(struct ubifs_info *c) { @@ -757,10 +752,6 @@ static int take_gc_lnum(struct ubifs_info *c) return -EINVAL; } - err = ubifs_leb_unmap(c, c->gc_lnum); - if (err) - return err; - /* And we have to tell lprops that this LEB is taken */ err = ubifs_change_one_lp(c, c->gc_lnum, c->leb_size, 0, LPROPS_TAKEN, 0, 0); @@ -966,13 +957,16 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options, token = match_token(p, tokens, args); switch (token) { + /* + * %Opt_fast_unmount and %Opt_norm_unmount options are ignored. + * We accepte them in order to be backware-compatible. But this + * should be removed at some point. + */ case Opt_fast_unmount: c->mount_opts.unmount_mode = 2; - c->fast_unmount = 1; break; case Opt_norm_unmount: c->mount_opts.unmount_mode = 1; - c->fast_unmount = 0; break; case Opt_bulk_read: c->mount_opts.bulk_read = 2; @@ -1094,12 +1088,7 @@ static int check_free_space(struct ubifs_info *c) ubifs_err("insufficient free space to mount in read/write mode"); dbg_dump_budg(c); dbg_dump_lprops(c); - /* - * We return %-EINVAL instead of %-ENOSPC because it seems to - * be the closest error code mentioned in the mount function - * documentation. - */ - return -EINVAL; + return -ENOSPC; } return 0; } @@ -1286,10 +1275,19 @@ static int mount_ubifs(struct ubifs_info *c) if (err) goto out_orphans; err = ubifs_rcvry_gc_commit(c); - } else + } else { err = take_gc_lnum(c); - if (err) - goto out_orphans; + if (err) + goto out_orphans; + + /* + * GC LEB may contain garbage if there was an unclean + * reboot, and it should be un-mapped. + */ + err = ubifs_leb_unmap(c, c->gc_lnum); + if (err) + return err; + } err = dbg_check_lprops(c); if (err) @@ -1298,6 +1296,16 @@ static int mount_ubifs(struct ubifs_info *c) err = ubifs_recover_size(c); if (err) goto out_orphans; + } else { + /* + * Even if we mount read-only, we have to set space in GC LEB + * to proper value because this affects UBIFS free space + * reporting. We do not want to have a situation when + * re-mounting from R/O to R/W changes amount of free space. + */ + err = take_gc_lnum(c); + if (err) + goto out_orphans; } spin_lock(&ubifs_infos_lock); @@ -1310,14 +1318,17 @@ static int mount_ubifs(struct ubifs_info *c) else { c->need_recovery = 0; ubifs_msg("recovery completed"); + /* GC LEB has to be empty and taken at this point */ + ubifs_assert(c->lst.taken_empty_lebs == 1); } - } + } else + ubifs_assert(c->lst.taken_empty_lebs == 1); - err = dbg_debugfs_init_fs(c); + err = dbg_check_filesystem(c); if (err) goto out_infos; - err = dbg_check_filesystem(c); + err = dbg_debugfs_init_fs(c); if (err) goto out_infos; @@ -1351,7 +1362,6 @@ static int mount_ubifs(struct ubifs_info *c) c->uuid[4], c->uuid[5], c->uuid[6], c->uuid[7], c->uuid[8], c->uuid[9], c->uuid[10], c->uuid[11], c->uuid[12], c->uuid[13], c->uuid[14], c->uuid[15]); - dbg_msg("fast unmount: %d", c->fast_unmount); dbg_msg("big_lpt %d", c->big_lpt); dbg_msg("log LEBs: %d (%d - %d)", c->log_lebs, UBIFS_LOG_LNUM, c->log_last); @@ -1475,10 +1485,8 @@ static int ubifs_remount_rw(struct ubifs_info *c) { int err, lnum; - if (c->ro_media) - return -EINVAL; - mutex_lock(&c->umount_mutex); + dbg_save_space_info(c); c->remounting_rw = 1; c->always_chk_crc = 1; @@ -1514,6 +1522,12 @@ static int ubifs_remount_rw(struct ubifs_info *c) err = ubifs_recover_inl_heads(c, c->sbuf); if (err) goto out; + } else { + /* A readonly mount is not allowed to have orphans */ + ubifs_assert(c->tot_orphans == 0); + err = ubifs_clear_orphans(c); + if (err) + goto out; } if (!(c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY))) { @@ -1569,7 +1583,7 @@ static int ubifs_remount_rw(struct ubifs_info *c) if (c->need_recovery) err = ubifs_rcvry_gc_commit(c); else - err = take_gc_lnum(c); + err = ubifs_leb_unmap(c, c->gc_lnum); if (err) goto out; @@ -1582,8 +1596,9 @@ static int ubifs_remount_rw(struct ubifs_info *c) c->vfs_sb->s_flags &= ~MS_RDONLY; c->remounting_rw = 0; c->always_chk_crc = 0; + err = dbg_check_space_info(c); mutex_unlock(&c->umount_mutex); - return 0; + return err; out: vfree(c->orph_buf); @@ -1603,43 +1618,18 @@ out: } /** - * commit_on_unmount - commit the journal when un-mounting. - * @c: UBIFS file-system description object - * - * This function is called during un-mounting and re-mounting, and it commits - * the journal unless the "fast unmount" mode is enabled. - */ -static void commit_on_unmount(struct ubifs_info *c) -{ - struct super_block *sb = c->vfs_sb; - long long bud_bytes; - - /* - * This function is called before the background thread is stopped, so - * we may race with ongoing commit, which means we have to take - * @c->bud_lock to access @c->bud_bytes. - */ - spin_lock(&c->buds_lock); - bud_bytes = c->bud_bytes; - spin_unlock(&c->buds_lock); - - if (!c->fast_unmount && !(sb->s_flags & MS_RDONLY) && bud_bytes) - ubifs_run_commit(c); -} - -/** * ubifs_remount_ro - re-mount in read-only mode. * @c: UBIFS file-system description object * - * We rely on VFS to have stopped writing. Possibly the background thread could - * be running a commit, however kthread_stop will wait in that case. + * We assume VFS has stopped writing. Possibly the background thread could be + * running a commit, however kthread_stop will wait in that case. */ static void ubifs_remount_ro(struct ubifs_info *c) { int i, err; ubifs_assert(!c->need_recovery); - commit_on_unmount(c); + ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY)); mutex_lock(&c->umount_mutex); if (c->bgt) { @@ -1647,27 +1637,29 @@ static void ubifs_remount_ro(struct ubifs_info *c) c->bgt = NULL; } + dbg_save_space_info(c); + for (i = 0; i < c->jhead_cnt; i++) { ubifs_wbuf_sync(&c->jheads[i].wbuf); del_timer_sync(&c->jheads[i].wbuf.timer); } - if (!c->ro_media) { - c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); - c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); - c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum); - err = ubifs_write_master(c); - if (err) - ubifs_ro_mode(c, err); - } + c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); + c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); + c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum); + err = ubifs_write_master(c); + if (err) + ubifs_ro_mode(c, err); - ubifs_destroy_idx_gc(c); free_wbufs(c); vfree(c->orph_buf); c->orph_buf = NULL; vfree(c->ileb_buf); c->ileb_buf = NULL; ubifs_lpt_free(c, 1); + err = dbg_check_space_info(c); + if (err) + ubifs_ro_mode(c, err); mutex_unlock(&c->umount_mutex); } @@ -1760,11 +1752,20 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) } if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { + if (c->ro_media) { + ubifs_msg("cannot re-mount due to prior errors"); + return -EROFS; + } err = ubifs_remount_rw(c); if (err) return err; - } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) + } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) { + if (c->ro_media) { + ubifs_msg("cannot re-mount due to prior errors"); + return -EROFS; + } ubifs_remount_ro(c); + } if (c->bulk_read == 1) bu_init(c); @@ -1774,10 +1775,11 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) c->bu.buf = NULL; } + ubifs_assert(c->lst.taken_empty_lebs == 1); return 0; } -struct super_operations ubifs_super_operations = { +const struct super_operations ubifs_super_operations = { .alloc_inode = ubifs_alloc_inode, .destroy_inode = ubifs_destroy_inode, .put_super = ubifs_put_super, @@ -2044,15 +2046,6 @@ out_close: static void ubifs_kill_sb(struct super_block *sb) { - struct ubifs_info *c = sb->s_fs_info; - - /* - * We do 'commit_on_unmount()' here instead of 'ubifs_put_super()' - * in order to be outside BKL. - */ - if (sb->s_root) - commit_on_unmount(c); - /* The un-mount routine is actually done in put_super() */ generic_shutdown_super(sb); } diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index f7e36f5..fa28a84 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -443,6 +443,11 @@ static int tnc_read_node_nm(struct ubifs_info *c, struct ubifs_zbranch *zbr, * This function performs that same function as ubifs_read_node except that * it does not require that there is actually a node present and instead * the return code indicates if a node was read. + * + * Note, this function does not check CRC of data nodes if @c->no_chk_data_crc + * is true (it is controlled by corresponding mount option). However, if + * @c->always_chk_crc is true, @c->no_chk_data_crc is ignored and CRC is always + * checked. */ static int try_read_node(const struct ubifs_info *c, void *buf, int type, int len, int lnum, int offs) @@ -470,9 +475,8 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type, if (node_len != len) return 0; - if (type == UBIFS_DATA_NODE && !c->always_chk_crc) - if (c->no_chk_data_crc) - return 0; + if (type == UBIFS_DATA_NODE && !c->always_chk_crc && c->no_chk_data_crc) + return 1; crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); node_crc = le32_to_cpu(ch->crc); @@ -1506,7 +1510,7 @@ out: * * Note, if the bulk-read buffer length (@bu->buf_len) is known, this function * makes sure bulk-read nodes fit the buffer. Otherwise, this function prepares - * maxumum possible amount of nodes for bulk-read. + * maximum possible amount of nodes for bulk-read. */ int ubifs_tnc_get_bu_keys(struct ubifs_info *c, struct bu_info *bu) { diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index fc2a4cc..039a68b 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -426,9 +426,9 @@ struct ubifs_unclean_leb { * LEB properties flags. * * LPROPS_UNCAT: not categorized - * LPROPS_DIRTY: dirty > 0, not index + * LPROPS_DIRTY: dirty > free, dirty >= @c->dead_wm, not index * LPROPS_DIRTY_IDX: dirty + free > @c->min_idx_node_sze and index - * LPROPS_FREE: free > 0, not empty, not index + * LPROPS_FREE: free > 0, dirty < @c->dead_wm, not empty, not index * LPROPS_HEAP_CNT: number of heaps used for storing categorized LEBs * LPROPS_EMPTY: LEB is empty, not taken * LPROPS_FREEABLE: free + dirty == leb_size, not index, not taken @@ -961,7 +961,6 @@ struct ubifs_debug_info; * @cs_lock: commit state lock * @cmt_wq: wait queue to sleep on if the log is full and a commit is running * - * @fast_unmount: do not run journal commit before un-mounting * @big_lpt: flag that LPT is too big to write whole during commit * @no_chk_data_crc: do not check CRCs when reading data nodes (except during * recovery) @@ -1202,7 +1201,6 @@ struct ubifs_info { spinlock_t cs_lock; wait_queue_head_t cmt_wq; - unsigned int fast_unmount:1; unsigned int big_lpt:1; unsigned int no_chk_data_crc:1; unsigned int bulk_read:1; @@ -1405,13 +1403,13 @@ extern struct list_head ubifs_infos; extern spinlock_t ubifs_infos_lock; extern atomic_long_t ubifs_clean_zn_cnt; extern struct kmem_cache *ubifs_inode_slab; -extern struct super_operations ubifs_super_operations; -extern struct address_space_operations ubifs_file_address_operations; -extern struct file_operations ubifs_file_operations; -extern struct inode_operations ubifs_file_inode_operations; -extern struct file_operations ubifs_dir_operations; -extern struct inode_operations ubifs_dir_inode_operations; -extern struct inode_operations ubifs_symlink_inode_operations; +extern const struct super_operations ubifs_super_operations; +extern const struct address_space_operations ubifs_file_address_operations; +extern const struct file_operations ubifs_file_operations; +extern const struct inode_operations ubifs_file_inode_operations; +extern const struct file_operations ubifs_dir_operations; +extern const struct inode_operations ubifs_dir_inode_operations; +extern const struct inode_operations ubifs_symlink_inode_operations; extern struct backing_dev_info ubifs_backing_dev_info; extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; @@ -1428,7 +1426,7 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len, int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum, int offs, int dtype); int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, - int offs, int quiet, int chk_crc); + int offs, int quiet, int must_chk_crc); void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad); void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last); int ubifs_io_init(struct ubifs_info *c); @@ -1495,6 +1493,7 @@ void ubifs_release_ino_dirty(struct ubifs_info *c, struct inode *inode, void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode, struct ubifs_budget_req *req); long long ubifs_get_free_space(struct ubifs_info *c); +long long ubifs_get_free_space_nolock(struct ubifs_info *c); int ubifs_calc_min_idx_lebs(struct ubifs_info *c); void ubifs_convert_page_budget(struct ubifs_info *c); long long ubifs_reported_space(const struct ubifs_info *c, long long free); @@ -1603,6 +1602,7 @@ void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum); int ubifs_orphan_start_commit(struct ubifs_info *c); int ubifs_orphan_end_commit(struct ubifs_info *c); int ubifs_mount_orphans(struct ubifs_info *c, int unclean, int read_only); +int ubifs_clear_orphans(struct ubifs_info *c); /* lpt.c */ int ubifs_calc_lpt_geom(struct ubifs_info *c); @@ -1646,7 +1646,7 @@ const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c, const struct ubifs_lprops *lp, int free, int dirty, int flags, int idx_gc_cnt); -void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *stats); +void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *lst); void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops, int cat); void ubifs_replace_cat(struct ubifs_info *c, struct ubifs_lprops *old_lprops, diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index 2ed0353..a608e72 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c @@ -371,7 +371,11 @@ xfs_quiesce_attr( /* flush inodes and push all remaining buffers out to disk */ xfs_quiesce_fs(mp); - ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0); + /* + * Just warn here till VFS can correctly support + * read-only remount without racing. + */ + WARN_ON(atomic_read(&mp->m_active_trans) != 0); /* Push the superblock and write an unmount record */ error = xfs_log_sbcount(mp, 1); diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index b4c1ee7..f8278cf 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -55,17 +55,11 @@ xfs_swapext( struct file *file, *target_file; int error = 0; - sxp = kmem_alloc(sizeof(xfs_swapext_t), KM_MAYFAIL); - if (!sxp) { - error = XFS_ERROR(ENOMEM); - goto out; - } - /* Pull information for the target fd */ file = fget((int)sxp->sx_fdtarget); if (!file) { error = XFS_ERROR(EINVAL); - goto out_free_sxp; + goto out; } if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND)) { @@ -109,8 +103,6 @@ xfs_swapext( fput(target_file); out_put_file: fput(file); - out_free_sxp: - kmem_free(sxp); out: return error; } diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 35cca98..b1047de 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -70,16 +70,21 @@ STATIC void xlog_recover_check_summary(xlog_t *); xfs_buf_t * xlog_get_bp( xlog_t *log, - int num_bblks) + int nbblks) { - ASSERT(num_bblks > 0); + if (nbblks <= 0 || nbblks > log->l_logBBsize) { + xlog_warn("XFS: Invalid block length (0x%x) given for buffer", nbblks); + XFS_ERROR_REPORT("xlog_get_bp(1)", + XFS_ERRLEVEL_HIGH, log->l_mp); + return NULL; + } if (log->l_sectbb_log) { - if (num_bblks > 1) - num_bblks += XLOG_SECTOR_ROUNDUP_BBCOUNT(log, 1); - num_bblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, num_bblks); + if (nbblks > 1) + nbblks += XLOG_SECTOR_ROUNDUP_BBCOUNT(log, 1); + nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks); } - return xfs_buf_get_noaddr(BBTOB(num_bblks), log->l_mp->m_logdev_targp); + return xfs_buf_get_noaddr(BBTOB(nbblks), log->l_mp->m_logdev_targp); } void @@ -102,6 +107,13 @@ xlog_bread( { int error; + if (nbblks <= 0 || nbblks > log->l_logBBsize) { + xlog_warn("XFS: Invalid block length (0x%x) given for buffer", nbblks); + XFS_ERROR_REPORT("xlog_bread(1)", + XFS_ERRLEVEL_HIGH, log->l_mp); + return EFSCORRUPTED; + } + if (log->l_sectbb_log) { blk_no = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, blk_no); nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks); @@ -139,6 +151,13 @@ xlog_bwrite( { int error; + if (nbblks <= 0 || nbblks > log->l_logBBsize) { + xlog_warn("XFS: Invalid block length (0x%x) given for buffer", nbblks); + XFS_ERROR_REPORT("xlog_bwrite(1)", + XFS_ERRLEVEL_HIGH, log->l_mp); + return EFSCORRUPTED; + } + if (log->l_sectbb_log) { blk_no = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, blk_no); nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks); diff --git a/include/acpi/pdc_intel.h b/include/acpi/pdc_intel.h index e72bfdd..552637b 100644 --- a/include/acpi/pdc_intel.h +++ b/include/acpi/pdc_intel.h @@ -14,6 +14,7 @@ #define ACPI_PDC_SMP_T_SWCOORD (0x0080) #define ACPI_PDC_C_C1_FFH (0x0100) #define ACPI_PDC_C_C2C3_FFH (0x0200) +#define ACPI_PDC_SMP_P_HWCOORD (0x0800) #define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \ ACPI_PDC_C_C1_HALT | \ @@ -22,6 +23,7 @@ #define ACPI_PDC_EST_CAPABILITY_SWSMP (ACPI_PDC_SMP_C1PT | \ ACPI_PDC_C_C1_HALT | \ ACPI_PDC_SMP_P_SWCOORD | \ + ACPI_PDC_SMP_P_HWCOORD | \ ACPI_PDC_P_FFH) #define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \ diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 2124c06..b97cdc5 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -90,7 +90,6 @@ header-y += if_ppp.h header-y += if_slip.h header-y += if_strip.h header-y += if_tun.h -header-y += if_tunnel.h header-y += in_route.h header-y += ioctl.h header-y += ip6_tunnel.h @@ -236,6 +235,7 @@ unifdef-y += if_phonet.h unifdef-y += if_pppol2tp.h unifdef-y += if_pppox.h unifdef-y += if_tr.h +unifdef-y += if_tunnel.h unifdef-y += if_vlan.h unifdef-y += igmp.h unifdef-y += inet_diag.h diff --git a/include/linux/aio_abi.h b/include/linux/aio_abi.h index 9e01729..2c87316 100644 --- a/include/linux/aio_abi.h +++ b/include/linux/aio_abi.h @@ -27,6 +27,7 @@ #ifndef __LINUX__AIO_ABI_H #define __LINUX__AIO_ABI_H +#include <linux/types.h> #include <asm/byteorder.h> typedef unsigned long aio_context_t; diff --git a/include/linux/async.h b/include/linux/async.h index c4ecacd..68a9530 100644 --- a/include/linux/async.h +++ b/include/linux/async.h @@ -17,9 +17,11 @@ typedef u64 async_cookie_t; typedef void (async_func_ptr) (void *data, async_cookie_t cookie); extern async_cookie_t async_schedule(async_func_ptr *ptr, void *data); -extern async_cookie_t async_schedule_special(async_func_ptr *ptr, void *data, struct list_head *list); +extern async_cookie_t async_schedule_domain(async_func_ptr *ptr, void *data, + struct list_head *list); extern void async_synchronize_full(void); -extern void async_synchronize_full_special(struct list_head *list); +extern void async_synchronize_full_domain(struct list_head *list); extern void async_synchronize_cookie(async_cookie_t cookie); -extern void async_synchronize_cookie_special(async_cookie_t cookie, struct list_head *list); +extern void async_synchronize_cookie_domain(async_cookie_t cookie, + struct list_head *list); diff --git a/include/linux/ata.h b/include/linux/ata.h index a53318b..08a86d5 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -731,12 +731,17 @@ static inline int ata_id_current_chs_valid(const u16 *id) static inline int ata_id_is_cfa(const u16 *id) { - if (id[ATA_ID_CONFIG] == 0x848A) /* Standard CF */ + if (id[ATA_ID_CONFIG] == 0x848A) /* Traditional CF */ return 1; - /* Could be CF hiding as standard ATA */ - if (ata_id_major_version(id) >= 3 && - id[ATA_ID_COMMAND_SET_1] != 0xFFFF && - (id[ATA_ID_COMMAND_SET_1] & (1 << 2))) + /* + * CF specs don't require specific value in the word 0 anymore and yet + * they forbid to report the ATA version in the word 80 and require the + * CFA feature set support to be indicated in the word 83 in this case. + * Unfortunately, some cards only follow either of this requirements, + * and while those that don't indicate CFA feature support need some + * sort of quirk list, it seems impractical for the ones that do... + */ + if ((id[ATA_ID_COMMAND_SET_2] & 0xC004) == 0x4004) return 1; return 0; } diff --git a/include/linux/atalk.h b/include/linux/atalk.h index e9ebac2..d34c187 100644 --- a/include/linux/atalk.h +++ b/include/linux/atalk.h @@ -1,6 +1,7 @@ #ifndef __LINUX_ATALK_H__ #define __LINUX_ATALK_H__ +#include <linux/types.h> #include <asm/byteorder.h> /* diff --git a/include/linux/atmbr2684.h b/include/linux/atmbr2684.h index 52bf72a..fdb2629 100644 --- a/include/linux/atmbr2684.h +++ b/include/linux/atmbr2684.h @@ -1,6 +1,7 @@ #ifndef _LINUX_ATMBR2684_H #define _LINUX_ATMBR2684_H +#include <linux/types.h> #include <linux/atm.h> #include <linux/if.h> /* For IFNAMSIZ */ diff --git a/include/linux/auto_fs4.h b/include/linux/auto_fs4.h index 55fa478..8b49ac4 100644 --- a/include/linux/auto_fs4.h +++ b/include/linux/auto_fs4.h @@ -12,6 +12,7 @@ #define _LINUX_AUTO_FS4_H /* Include common v3 definitions */ +#include <linux/types.h> #include <linux/auto_fs.h> /* autofs v4 definitions */ diff --git a/include/linux/bfs_fs.h b/include/linux/bfs_fs.h index 8ed6dfdc..1c0b355 100644 --- a/include/linux/bfs_fs.h +++ b/include/linux/bfs_fs.h @@ -6,6 +6,8 @@ #ifndef _LINUX_BFS_FS_H #define _LINUX_BFS_FS_H +#include <linux/types.h> + #define BFS_BSIZE_BITS 9 #define BFS_BSIZE (1<<BFS_BSIZE_BITS) @@ -17,7 +19,6 @@ #define BFS_VDIR 2L #define BFS_VREG 1L - /* BFS inode layout on disk */ struct bfs_inode { __le16 i_ino; diff --git a/include/linux/bio.h b/include/linux/bio.h index 0942765..2aa283a 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -451,12 +451,13 @@ extern struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly; #ifdef CONFIG_HIGHMEM /* - * remember to add offset! and never ever reenable interrupts between a - * bvec_kmap_irq and bvec_kunmap_irq!! + * remember never ever reenable interrupts between a bvec_kmap_irq and + * bvec_kunmap_irq! * * This function MUST be inlined - it plays with the CPU interrupt flags. */ -static inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags) +static __always_inline char *bvec_kmap_irq(struct bio_vec *bvec, + unsigned long *flags) { unsigned long addr; @@ -472,7 +473,8 @@ static inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags) return (char *) addr + bvec->bv_offset; } -static inline void bvec_kunmap_irq(char *buffer, unsigned long *flags) +static __always_inline void bvec_kunmap_irq(char *buffer, + unsigned long *flags) { unsigned long ptr = (unsigned long) buffer & PAGE_MASK; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index d08c4b8..dcaa0fd 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -455,7 +455,7 @@ struct request_queue #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ (1 << QUEUE_FLAG_CLUSTER) | \ - 1 << QUEUE_FLAG_STACKABLE) + (1 << QUEUE_FLAG_STACKABLE)) static inline int queue_is_locked(struct request_queue *q) { diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index 1dba349..25379cb 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h @@ -1,6 +1,7 @@ #ifndef BLKTRACE_H #define BLKTRACE_H +#include <linux/types.h> #ifdef __KERNEL__ #include <linux/blkdev.h> #include <linux/relay.h> diff --git a/include/linux/can/bcm.h b/include/linux/can/bcm.h index 7f29327..1432b27 100644 --- a/include/linux/can/bcm.h +++ b/include/linux/can/bcm.h @@ -14,6 +14,8 @@ #ifndef CAN_BCM_H #define CAN_BCM_H +#include <linux/types.h> + /** * struct bcm_msg_head - head of messages to/from the broadcast manager * @opcode: opcode, see enum below. diff --git a/include/linux/capability.h b/include/linux/capability.h index 02bdb76..1b98725 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -69,10 +69,6 @@ typedef struct __user_cap_data_struct { #define VFS_CAP_U32 VFS_CAP_U32_2 #define VFS_CAP_REVISION VFS_CAP_REVISION_2 -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES -extern int file_caps_enabled; -#endif - struct vfs_cap_data { __le32 magic_etc; /* Little endian */ struct { @@ -96,6 +92,10 @@ struct vfs_cap_data { #define _KERNEL_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3 #define _KERNEL_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_3 +#ifdef CONFIG_SECURITY_FILE_CAPABILITIES +extern int file_caps_enabled; +#endif + typedef struct kernel_cap_struct { __u32 cap[_KERNEL_CAPABILITY_U32S]; } kernel_cap_t; diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h index 0b49e08..78e9047 100644 --- a/include/linux/cdrom.h +++ b/include/linux/cdrom.h @@ -11,6 +11,7 @@ #ifndef _LINUX_CDROM_H #define _LINUX_CDROM_H +#include <linux/types.h> #include <asm/byteorder.h> /******************************************************* diff --git a/include/linux/cgroupstats.h b/include/linux/cgroupstats.h index 4f53abf..3753c33 100644 --- a/include/linux/cgroupstats.h +++ b/include/linux/cgroupstats.h @@ -15,6 +15,7 @@ #ifndef _LINUX_CGROUPSTATS_H #define _LINUX_CGROUPSTATS_H +#include <linux/types.h> #include <linux/taskstats.h> /* diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index cea1536..3a1dbba 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h @@ -36,6 +36,7 @@ enum clock_event_nofitiers { CLOCK_EVT_NOTIFY_BROADCAST_EXIT, CLOCK_EVT_NOTIFY_SUSPEND, CLOCK_EVT_NOTIFY_RESUME, + CLOCK_EVT_NOTIFY_CPU_DYING, CLOCK_EVT_NOTIFY_CPU_DEAD, }; diff --git a/include/linux/dlm_plock.h b/include/linux/dlm_plock.h index 18d5fdb..2dd2124 100644 --- a/include/linux/dlm_plock.h +++ b/include/linux/dlm_plock.h @@ -9,6 +9,8 @@ #ifndef __DLM_PLOCK_DOT_H__ #define __DLM_PLOCK_DOT_H__ +#include <linux/types.h> + #define DLM_PLOCK_MISC_NAME "dlm_plock" #define DLM_PLOCK_VERSION_MAJOR 1 diff --git a/include/linux/dn.h b/include/linux/dn.h index 02bba04..fe99908 100644 --- a/include/linux/dn.h +++ b/include/linux/dn.h @@ -1,6 +1,8 @@ #ifndef _LINUX_DN_H #define _LINUX_DN_H +#include <linux/types.h> + /* DECnet Data Structures and Constants diff --git a/include/linux/dvb/audio.h b/include/linux/dvb/audio.h index 89412e1..bb0df2a 100644 --- a/include/linux/dvb/audio.h +++ b/include/linux/dvb/audio.h @@ -24,12 +24,7 @@ #ifndef _DVBAUDIO_H_ #define _DVBAUDIO_H_ -#ifdef __KERNEL__ #include <linux/types.h> -#else -#include <stdint.h> -#endif - typedef enum { AUDIO_SOURCE_DEMUX, /* Select the demux as the main source */ diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h index 402fb7a..fef9437 100644 --- a/include/linux/dvb/dmx.h +++ b/include/linux/dvb/dmx.h @@ -24,7 +24,7 @@ #ifndef _DVBDMX_H_ #define _DVBDMX_H_ -#include <asm/types.h> +#include <linux/types.h> #ifdef __KERNEL__ #include <linux/time.h> #else diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index 55026b1..51c8d2d 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -26,8 +26,7 @@ #ifndef _DVBFRONTEND_H_ #define _DVBFRONTEND_H_ -#include <asm/types.h> - +#include <linux/types.h> typedef enum fe_type { FE_QPSK, diff --git a/include/linux/dvb/net.h b/include/linux/dvb/net.h index 5be474b..f451e7e 100644 --- a/include/linux/dvb/net.h +++ b/include/linux/dvb/net.h @@ -24,8 +24,7 @@ #ifndef _DVBNET_H_ #define _DVBNET_H_ -#include <asm/types.h> - +#include <linux/types.h> struct dvb_net_if { __u16 pid; diff --git a/include/linux/dvb/video.h b/include/linux/dvb/video.h index 50839fe..bd49c3e 100644 --- a/include/linux/dvb/video.h +++ b/include/linux/dvb/video.h @@ -24,17 +24,14 @@ #ifndef _DVBVIDEO_H_ #define _DVBVIDEO_H_ -#include <linux/compiler.h> - -#ifdef __KERNEL__ #include <linux/types.h> +#ifdef __KERNEL__ +#include <linux/compiler.h> #else -#include <asm/types.h> #include <stdint.h> #include <time.h> #endif - typedef enum { VIDEO_FORMAT_4_3, /* Select 4:3 format */ VIDEO_FORMAT_16_9, /* Select 16:9 format. */ diff --git a/include/linux/edd.h b/include/linux/edd.h index 5d747c5..4cbd0fe 100644 --- a/include/linux/edd.h +++ b/include/linux/edd.h @@ -30,6 +30,8 @@ #ifndef _LINUX_EDD_H #define _LINUX_EDD_H +#include <linux/types.h> + #define EDDNR 0x1e9 /* addr of number of edd_info structs at EDDBUF in boot_params - treat this as 1 byte */ #define EDDBUF 0xd00 /* addr of edd_info structs in boot_params */ diff --git a/include/linux/efs_fs_sb.h b/include/linux/efs_fs_sb.h index ff1945e..a01be90 100644 --- a/include/linux/efs_fs_sb.h +++ b/include/linux/efs_fs_sb.h @@ -9,6 +9,7 @@ #ifndef __EFS_FS_SB_H__ #define __EFS_FS_SB_H__ +#include <linux/types.h> #include <linux/magic.h> /* EFS superblock magic numbers */ diff --git a/include/linux/elf-fdpic.h b/include/linux/elf-fdpic.h index 9f5b745..7cd2e80 100644 --- a/include/linux/elf-fdpic.h +++ b/include/linux/elf-fdpic.h @@ -58,11 +58,13 @@ struct elf_fdpic_params { #define ELF_FDPIC_FLAG_PRESENT 0x80000000 /* T if this object is present */ }; +#ifdef __KERNEL__ #ifdef CONFIG_MMU extern void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params, struct elf_fdpic_params *interp_params, unsigned long *start_stack, unsigned long *start_brk); #endif +#endif /* __KERNEL__ */ #endif /* _LINUX_ELF_FDPIC_H */ diff --git a/include/linux/elf.h b/include/linux/elf.h index 0b61ca4..45a937b 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h @@ -377,6 +377,7 @@ typedef struct elf64_note { Elf64_Word n_type; /* Content type */ } Elf64_Nhdr; +#ifdef __KERNEL__ #if ELF_CLASS == ELFCLASS32 extern Elf32_Dyn _DYNAMIC []; @@ -404,5 +405,5 @@ static inline int elf_coredump_extra_notes_write(struct file *file, extern int elf_coredump_extra_notes_size(void); extern int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset); #endif - +#endif /* __KERNEL__ */ #endif /* _LINUX_ELF_H */ diff --git a/include/linux/errqueue.h b/include/linux/errqueue.h index 92f8d4f..ceb1454 100644 --- a/include/linux/errqueue.h +++ b/include/linux/errqueue.h @@ -1,6 +1,8 @@ #ifndef _LINUX_ERRQUEUE_H #define _LINUX_ERRQUEUE_H 1 +#include <linux/types.h> + struct sock_extended_err { __u32 ee_errno; diff --git a/include/linux/fb.h b/include/linux/fb.h index 818fe21..31527e1 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -960,6 +960,21 @@ extern struct fb_info *registered_fb[FB_MAX]; extern int num_registered_fb; extern struct class *fb_class; +static inline int lock_fb_info(struct fb_info *info) +{ + mutex_lock(&info->lock); + if (!info->fbops) { + mutex_unlock(&info->lock); + return 0; + } + return 1; +} + +static inline void unlock_fb_info(struct fb_info *info) +{ + mutex_unlock(&info->lock); +} + static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height) { diff --git a/include/linux/genetlink.h b/include/linux/genetlink.h index 7da02c9..b834ef6 100644 --- a/include/linux/genetlink.h +++ b/include/linux/genetlink.h @@ -1,6 +1,7 @@ #ifndef __LINUX_GENERIC_NETLINK_H #define __LINUX_GENERIC_NETLINK_H +#include <linux/types.h> #include <linux/netlink.h> #define GENL_NAMSIZ 16 /* length of family name */ diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index 14d0df0..c56b4bc 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -10,6 +10,8 @@ #ifndef __GFS2_ONDISK_DOT_H__ #define __GFS2_ONDISK_DOT_H__ +#include <linux/types.h> + #define GFS2_MAGIC 0x01161970 #define GFS2_BASIC_BLOCK 512 #define GFS2_BASIC_BLOCK_SHIFT 9 diff --git a/include/linux/hid.h b/include/linux/hid.h index 81aa84d..fa8ee9c 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -791,6 +791,7 @@ dbg_hid(const char *fmt, ...) __FILE__ , ## arg) #endif /* HID_FF */ +#ifdef __KERNEL__ #ifdef CONFIG_HID_COMPAT #define HID_COMPAT_LOAD_DRIVER(name) \ /* prototype to avoid sparse warning */ \ @@ -804,6 +805,7 @@ EXPORT_SYMBOL(hid_compat_##name) extern void hid_compat_##name(void); \ hid_compat_##name(); \ } while (0) +#endif /* __KERNEL__ */ #endif diff --git a/include/linux/hiddev.h b/include/linux/hiddev.h index c760ae0..bb6f58b 100644 --- a/include/linux/hiddev.h +++ b/include/linux/hiddev.h @@ -27,6 +27,8 @@ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic */ +#include <linux/types.h> + /* * The event structure itself */ diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h index a93a8dd..10d701e 100644 --- a/include/linux/icmpv6.h +++ b/include/linux/icmpv6.h @@ -1,6 +1,7 @@ #ifndef _LINUX_ICMPV6_H #define _LINUX_ICMPV6_H +#include <linux/types.h> #include <asm/byteorder.h> struct icmp6hdr { diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h index 43f3bed..a60c821 100644 --- a/include/linux/if_addr.h +++ b/include/linux/if_addr.h @@ -1,6 +1,7 @@ #ifndef __LINUX_IF_ADDR_H #define __LINUX_IF_ADDR_H +#include <linux/types.h> #include <linux/netlink.h> struct ifaddrmsg diff --git a/include/linux/if_addrlabel.h b/include/linux/if_addrlabel.h index 9fe79c9..89571f6 100644 --- a/include/linux/if_addrlabel.h +++ b/include/linux/if_addrlabel.h @@ -10,6 +10,8 @@ #ifndef __LINUX_IF_ADDRLABEL_H #define __LINUX_IF_ADDRLABEL_H +#include <linux/types.h> + struct ifaddrlblmsg { __u8 ifal_family; /* Address family */ diff --git a/include/linux/if_fc.h b/include/linux/if_fc.h index 376a34e..6ed7f1b 100644 --- a/include/linux/if_fc.h +++ b/include/linux/if_fc.h @@ -20,6 +20,7 @@ #ifndef _LINUX_IF_FC_H #define _LINUX_IF_FC_H +#include <linux/types.h> #define FC_ALEN 6 /* Octets in one ethernet addr */ #define FC_HLEN (sizeof(struct fch_hdr)+sizeof(struct fcllc)) diff --git a/include/linux/if_hippi.h b/include/linux/if_hippi.h index f0f2351..4a7c994 100644 --- a/include/linux/if_hippi.h +++ b/include/linux/if_hippi.h @@ -22,6 +22,7 @@ #ifndef _LINUX_IF_HIPPI_H #define _LINUX_IF_HIPPI_H +#include <linux/types.h> #include <asm/byteorder.h> /* diff --git a/include/linux/if_link.h b/include/linux/if_link.h index f9032c8..176c518 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -1,6 +1,7 @@ #ifndef _LINUX_IF_LINK_H #define _LINUX_IF_LINK_H +#include <linux/types.h> #include <linux/netlink.h> /* The struct should be in sync with struct net_device_stats */ diff --git a/include/linux/if_ppp.h b/include/linux/if_ppp.h index c3b1f85..fcef103 100644 --- a/include/linux/if_ppp.h +++ b/include/linux/if_ppp.h @@ -33,6 +33,7 @@ #ifndef _IF_PPP_H_ #define _IF_PPP_H_ +#include <linux/types.h> #include <linux/compiler.h> /* diff --git a/include/linux/if_strip.h b/include/linux/if_strip.h index fb5c5c9..6526a62 100644 --- a/include/linux/if_strip.h +++ b/include/linux/if_strip.h @@ -18,6 +18,8 @@ #ifndef __LINUX_STRIP_H #define __LINUX_STRIP_H +#include <linux/types.h> + typedef struct { __u8 c[6]; } MetricomAddress; diff --git a/include/linux/if_tr.h b/include/linux/if_tr.h index 5bcec8b..fc23aeb 100644 --- a/include/linux/if_tr.h +++ b/include/linux/if_tr.h @@ -19,6 +19,7 @@ #ifndef _LINUX_IF_TR_H #define _LINUX_IF_TR_H +#include <linux/types.h> #include <asm/byteorder.h> /* For __be16 */ /* IEEE 802.5 Token-Ring magic constants. The frame sizes omit the preamble diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h index aeab2cb..82c43624 100644 --- a/include/linux/if_tunnel.h +++ b/include/linux/if_tunnel.h @@ -2,7 +2,10 @@ #define _IF_TUNNEL_H_ #include <linux/types.h> + +#ifdef __KERNEL__ #include <linux/ip.h> +#endif #define SIOCGETTUNNEL (SIOCDEVPRIVATE + 0) #define SIOCADDTUNNEL (SIOCDEVPRIVATE + 1) diff --git a/include/linux/igmp.h b/include/linux/igmp.h index f734a0b..92fbd8c 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -16,6 +16,7 @@ #ifndef _LINUX_IGMP_H #define _LINUX_IGMP_H +#include <linux/types.h> #include <asm/byteorder.h> /* diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h index 6e8bc54..bc8c490 100644 --- a/include/linux/inet_diag.h +++ b/include/linux/inet_diag.h @@ -1,6 +1,8 @@ #ifndef _INET_DIAG_H_ #define _INET_DIAG_H_ 1 +#include <linux/types.h> + /* Just some random number */ #define TCPDIAG_GETSOCK 18 #define DCCPDIAG_GETSOCK 19 diff --git a/include/linux/ip6_tunnel.h b/include/linux/ip6_tunnel.h index 1e7cc4a..acb9ad6 100644 --- a/include/linux/ip6_tunnel.h +++ b/include/linux/ip6_tunnel.h @@ -1,6 +1,8 @@ #ifndef _IP6_TUNNEL_H #define _IP6_TUNNEL_H +#include <linux/types.h> + #define IPV6_TLV_TNL_ENCAP_LIMIT 4 #define IPV6_DEFAULT_TNL_ENCAP_LIMIT 4 diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 0b816cae..476d946 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -1,6 +1,7 @@ #ifndef _IPV6_H #define _IPV6_H +#include <linux/types.h> #include <linux/in6.h> #include <asm/byteorder.h> diff --git a/include/linux/ipv6_route.h b/include/linux/ipv6_route.h index b323ff5..1e7d8af 100644 --- a/include/linux/ipv6_route.h +++ b/include/linux/ipv6_route.h @@ -13,6 +13,8 @@ #ifndef _LINUX_IPV6_ROUTE_H #define _LINUX_IPV6_ROUTE_H +#include <linux/types.h> + #define RTF_DEFAULT 0x00010000 /* default - learned via ND */ #define RTF_ALLONLINK 0x00020000 /* (deprecated and will be removed) fallback, no routers on link */ diff --git a/include/linux/ipx.h b/include/linux/ipx.h index eb19b4e..aabb1d2 100644 --- a/include/linux/ipx.h +++ b/include/linux/ipx.h @@ -1,5 +1,6 @@ #ifndef _IPX_H_ #define _IPX_H_ +#include <linux/types.h> #include <linux/sockios.h> #include <linux/socket.h> #define IPX_NODE_LEN 6 diff --git a/include/linux/irda.h b/include/linux/irda.h index 28f88ec..00bdad0 100644 --- a/include/linux/irda.h +++ b/include/linux/irda.h @@ -25,6 +25,8 @@ #ifndef KERNEL_IRDA_H #define KERNEL_IRDA_H +#include <linux/types.h> + /* Please do *not* add any #include in this file, this file is * included as-is in user space. * Please fix the calling file to properly included needed files before diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 343df9e..7fa3718 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -480,7 +480,8 @@ static inline char *pack_hex_byte(char *buf, u8 byte) /* * swap - swap value of @a and @b */ -#define swap(a, b) ({ typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; }) +#define swap(a, b) \ + do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) /** * container_of - cast a member of a structure out to the containing structure diff --git a/include/linux/libata.h b/include/linux/libata.h index bca3ba2..5d87bc0 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -380,6 +380,7 @@ enum { ATA_HORKAGE_ATAPI_MOD16_DMA = (1 << 11), /* use ATAPI DMA for commands not multiple of 16 bytes */ ATA_HORKAGE_FIRMWARE_WARN = (1 << 12), /* firwmare update warning */ + ATA_HORKAGE_1_5_GBPS = (1 << 13), /* force 1.5 Gbps */ /* DMA mask for user DMA control: User visible values; DO NOT renumber */ @@ -580,7 +581,7 @@ struct ata_device { acpi_handle acpi_handle; union acpi_object *gtf_cache; #endif - /* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */ + /* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */ u64 n_sectors; /* size of device, if ATA */ unsigned int class; /* ATA_DEV_xxx */ unsigned long unpark_deadline; @@ -605,20 +606,22 @@ struct ata_device { u16 heads; /* Number of heads */ u16 sectors; /* Number of sectors per track */ - /* error history */ - int spdn_cnt; - struct ata_ering ering; - union { u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */ }; + + /* error history */ + int spdn_cnt; + /* ering is CLEAR_END, read comment above CLEAR_END */ + struct ata_ering ering; }; -/* Offset into struct ata_device. Fields above it are maintained - * acress device init. Fields below are zeroed. +/* Fields between ATA_DEVICE_CLEAR_BEGIN and ATA_DEVICE_CLEAR_END are + * cleared to zero on ata_dev_init(). */ -#define ATA_DEVICE_CLEAR_OFFSET offsetof(struct ata_device, n_sectors) +#define ATA_DEVICE_CLEAR_BEGIN offsetof(struct ata_device, n_sectors) +#define ATA_DEVICE_CLEAR_END offsetof(struct ata_device, ering) struct ata_eh_info { struct ata_device *dev; /* offending device */ diff --git a/include/linux/minix_fs.h b/include/linux/minix_fs.h index 0e39745..13fe09e 100644 --- a/include/linux/minix_fs.h +++ b/include/linux/minix_fs.h @@ -1,6 +1,7 @@ #ifndef _LINUX_MINIX_FS_H #define _LINUX_MINIX_FS_H +#include <linux/types.h> #include <linux/magic.h> /* diff --git a/include/linux/module.h b/include/linux/module.h index 4f7ea12..145a755 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -219,11 +219,6 @@ void *__symbol_get_gpl(const char *symbol); #endif -struct module_ref -{ - local_t count; -} ____cacheline_aligned; - enum module_state { MODULE_STATE_LIVE, @@ -344,8 +339,11 @@ struct module /* Destruction function. */ void (*exit)(void); - /* Reference counts */ - struct module_ref ref[NR_CPUS]; +#ifdef CONFIG_SMP + char *refptr; +#else + local_t ref; +#endif #endif }; #ifndef MODULE_ARCH_INIT @@ -395,13 +393,21 @@ void __symbol_put(const char *symbol); #define symbol_put(x) __symbol_put(MODULE_SYMBOL_PREFIX #x) void symbol_put_addr(void *addr); +static inline local_t *__module_ref_addr(struct module *mod, int cpu) +{ +#ifdef CONFIG_SMP + return (local_t *) (mod->refptr + per_cpu_offset(cpu)); +#else + return &mod->ref; +#endif +} + /* Sometimes we know we already have a refcount, and it's easier not to handle the error case (which only happens with rmmod --wait). */ static inline void __module_get(struct module *module) { if (module) { - BUG_ON(module_refcount(module) == 0); - local_inc(&module->ref[get_cpu()].count); + local_inc(__module_ref_addr(module, get_cpu())); put_cpu(); } } @@ -413,7 +419,7 @@ static inline int try_module_get(struct module *module) if (module) { unsigned int cpu = get_cpu(); if (likely(module_is_live(module))) - local_inc(&module->ref[cpu].count); + local_inc(__module_ref_addr(module, cpu)); else ret = 0; put_cpu(); diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index e0a9b20..ce38f1c 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h @@ -1,6 +1,7 @@ #ifndef _LINUX_MSDOS_FS_H #define _LINUX_MSDOS_FS_H +#include <linux/types.h> #include <linux/magic.h> #include <asm/byteorder.h> diff --git a/include/linux/neighbour.h b/include/linux/neighbour.h index bd3bbf6..8730d5d 100644 --- a/include/linux/neighbour.h +++ b/include/linux/neighbour.h @@ -1,6 +1,7 @@ #ifndef __LINUX_NEIGHBOUR_H #define __LINUX_NEIGHBOUR_H +#include <linux/types.h> #include <linux/netlink.h> struct ndmsg diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h index f3fd83e..8f53452 100644 --- a/include/linux/netfilter/xt_conntrack.h +++ b/include/linux/netfilter/xt_conntrack.h @@ -5,6 +5,7 @@ #ifndef _XT_CONNTRACK_H #define _XT_CONNTRACK_H +#include <linux/types.h> #include <linux/netfilter/nf_conntrack_tuple_common.h> #define XT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) diff --git a/include/linux/nfs_idmap.h b/include/linux/nfs_idmap.h index 15a9f3b..91a1c24 100644 --- a/include/linux/nfs_idmap.h +++ b/include/linux/nfs_idmap.h @@ -37,6 +37,8 @@ #ifndef NFS_IDMAP_H #define NFS_IDMAP_H +#include <linux/types.h> + /* XXX from bits/utmp.h */ #define IDMAP_NAMESZ 128 diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 5431512..bcd0201 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h @@ -10,9 +10,8 @@ #ifndef NFSD_EXPORT_H #define NFSD_EXPORT_H -#include <asm/types.h> -#ifdef __KERNEL__ # include <linux/types.h> +#ifdef __KERNEL__ # include <linux/in.h> #endif diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h index b2e0938..fa317f6 100644 --- a/include/linux/nfsd/nfsfh.h +++ b/include/linux/nfsd/nfsfh.h @@ -14,9 +14,8 @@ #ifndef _LINUX_NFSD_FH_H #define _LINUX_NFSD_FH_H -#include <asm/types.h> -#ifdef __KERNEL__ # include <linux/types.h> +#ifdef __KERNEL__ # include <linux/string.h> # include <linux/fs.h> #endif diff --git a/include/linux/nfsd/syscall.h b/include/linux/nfsd/syscall.h index 4e43976..7a3b565 100644 --- a/include/linux/nfsd/syscall.h +++ b/include/linux/nfsd/syscall.h @@ -9,9 +9,8 @@ #ifndef NFSD_SYSCALL_H #define NFSD_SYSCALL_H -#include <asm/types.h> -#ifdef __KERNEL__ # include <linux/types.h> +#ifdef __KERNEL__ # include <linux/in.h> #endif #include <linux/posix_types.h> diff --git a/include/linux/nubus.h b/include/linux/nubus.h index c435507..7382af3 100644 --- a/include/linux/nubus.h +++ b/include/linux/nubus.h @@ -12,6 +12,7 @@ #ifndef LINUX_NUBUS_H #define LINUX_NUBUS_H +#include <linux/types.h> #ifdef __KERNEL__ #include <asm/nubus.h> #endif diff --git a/include/linux/pci.h b/include/linux/pci.h index 48890cf..7bd624b 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -684,7 +684,7 @@ int pci_enable_rom(struct pci_dev *pdev); void pci_disable_rom(struct pci_dev *pdev); void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size); void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom); -size_t pci_get_rom_size(void __iomem *rom, size_t size); +size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size); /* Power management related routines */ int pci_save_state(struct pci_dev *dev); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index febc10e..52a9fe0 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2425,6 +2425,7 @@ #define PCI_DEVICE_ID_INTEL_ICH7_0 0x27b8 #define PCI_DEVICE_ID_INTEL_ICH7_1 0x27b9 #define PCI_DEVICE_ID_INTEL_ICH7_30 0x27b0 +#define PCI_DEVICE_ID_INTEL_TGP_LPC 0x27bc #define PCI_DEVICE_ID_INTEL_ICH7_31 0x27bd #define PCI_DEVICE_ID_INTEL_ICH7_17 0x27da #define PCI_DEVICE_ID_INTEL_ICH7_19 0x27dd diff --git a/include/linux/phonet.h b/include/linux/phonet.h index 4157faa..ee5e3c9 100644 --- a/include/linux/phonet.h +++ b/include/linux/phonet.h @@ -23,6 +23,8 @@ #ifndef LINUX_PHONET_H #define LINUX_PHONET_H +#include <linux/types.h> + /* Automatic protocol selection */ #define PN_PROTO_TRANSPORT 0 /* Phonet datagram socket */ diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h index e6aa848..3c842ed 100644 --- a/include/linux/pkt_cls.h +++ b/include/linux/pkt_cls.h @@ -1,6 +1,7 @@ #ifndef __LINUX_PKT_CLS_H #define __LINUX_PKT_CLS_H +#include <linux/types.h> #include <linux/pkt_sched.h> /* I think i could have done better macros ; for now this is stolen from diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index e3f133a..b2648e8 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -1,6 +1,8 @@ #ifndef __LINUX_PKT_SCHED_H #define __LINUX_PKT_SCHED_H +#include <linux/types.h> + /* Logical priority bands not depending on specific packet scheduler. Every scheduler will map them to real traffic classes, if it has no more precise mechanism to classify packets. diff --git a/include/linux/ppp_defs.h b/include/linux/ppp_defs.h index 6e8adc7..1c866bd 100644 --- a/include/linux/ppp_defs.h +++ b/include/linux/ppp_defs.h @@ -25,6 +25,8 @@ * OR MODIFICATIONS. */ +#include <linux/types.h> + /* * ==FILEVERSION 20000114== * diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h index 9491026..6ba830f 100644 --- a/include/linux/raid/md_p.h +++ b/include/linux/raid/md_p.h @@ -15,6 +15,8 @@ #ifndef _MD_P_H #define _MD_P_H +#include <linux/types.h> + /* * RAID superblock. * diff --git a/include/linux/random.h b/include/linux/random.h index 407ea36..25d02fe 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -7,6 +7,7 @@ #ifndef _LINUX_RANDOM_H #define _LINUX_RANDOM_H +#include <linux/types.h> #include <linux/ioctl.h> #include <linux/irqnr.h> diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index e88f705..1e5f673 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -1,6 +1,7 @@ #ifndef __LINUX_RTNETLINK_H #define __LINUX_RTNETLINK_H +#include <linux/types.h> #include <linux/netlink.h> #include <linux/if_link.h> #include <linux/if_addr.h> diff --git a/include/linux/sched.h b/include/linux/sched.h index 2225c20..28b3f50 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -443,6 +443,7 @@ struct pacct_struct { * @utime: time spent in user mode, in &cputime_t units * @stime: time spent in kernel mode, in &cputime_t units * @sum_exec_runtime: total time spent on the CPU, in nanoseconds + * @lock: lock for fields in this struct * * This structure groups together three kinds of CPU time that are * tracked for threads and thread groups. Most things considering diff --git a/include/linux/signalfd.h b/include/linux/signalfd.h index bef0c46..b363b91 100644 --- a/include/linux/signalfd.h +++ b/include/linux/signalfd.h @@ -8,6 +8,7 @@ #ifndef _LINUX_SIGNALFD_H #define _LINUX_SIGNALFD_H +#include <linux/types.h> /* For O_CLOEXEC and O_NONBLOCK */ #include <linux/fcntl.h> diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index 39c3a5e..6ca6a7b 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -43,10 +43,7 @@ static inline void *kmalloc(size_t size, gfp_t flags) i++; #include <linux/kmalloc_sizes.h> #undef CACHE - { - extern void __you_cannot_kmalloc_that_much(void); - __you_cannot_kmalloc_that_much(); - } + return NULL; found: #ifdef CONFIG_ZONE_DMA if (flags & GFP_DMA) @@ -77,10 +74,7 @@ static inline void *kmalloc_node(size_t size, gfp_t flags, int node) i++; #include <linux/kmalloc_sizes.h> #undef CACHE - { - extern void __you_cannot_kmalloc_that_much(void); - __you_cannot_kmalloc_that_much(); - } + return NULL; found: #ifdef CONFIG_ZONE_DMA if (flags & GFP_DMA) diff --git a/include/linux/sound.h b/include/linux/sound.h index 9e2a94f..44dcf05 100644 --- a/include/linux/sound.h +++ b/include/linux/sound.h @@ -25,6 +25,7 @@ #define SND_DEV_AMIDI 13 /* Like /dev/midi (obsolete) */ #define SND_DEV_ADMMIDI 14 /* Like /dev/dmmidi (onsolete) */ +#ifdef __KERNEL__ /* * Sound core interface functions */ @@ -40,3 +41,4 @@ extern void unregister_sound_special(int unit); extern void unregister_sound_mixer(int unit); extern void unregister_sound_midi(int unit); extern void unregister_sound_dsp(int unit); +#endif /* __KERNEL__ */ diff --git a/include/linux/spi/spidev.h b/include/linux/spi/spidev.h index c93ef9d..95251cc 100644 --- a/include/linux/spi/spidev.h +++ b/include/linux/spi/spidev.h @@ -22,6 +22,7 @@ #ifndef SPIDEV_H #define SPIDEV_H +#include <linux/types.h> /* User space versions of kernel symbols for SPI clocking modes, * matching <linux/spi/spi.h> diff --git a/include/linux/synclink.h b/include/linux/synclink.h index c844a22..99b8bdb 100644 --- a/include/linux/synclink.h +++ b/include/linux/synclink.h @@ -13,6 +13,8 @@ #define _SYNCLINK_H_ #define SYNCLINK_H_VERSION 3.6 +#include <linux/types.h> + #define BIT0 0x0001 #define BIT1 0x0002 #define BIT2 0x0004 diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h index 18269e9..341dddb 100644 --- a/include/linux/taskstats.h +++ b/include/linux/taskstats.h @@ -16,6 +16,8 @@ #ifndef _LINUX_TASKSTATS_H #define _LINUX_TASKSTATS_H +#include <linux/types.h> + /* Format for per-task data returned to userland when * - a task exits * - listener requests stats for a task diff --git a/include/linux/tc_act/tc_gact.h b/include/linux/tc_act/tc_gact.h index 23a03eb6..e895c0a 100644 --- a/include/linux/tc_act/tc_gact.h +++ b/include/linux/tc_act/tc_gact.h @@ -1,6 +1,7 @@ #ifndef __LINUX_TC_GACT_H #define __LINUX_TC_GACT_H +#include <linux/types.h> #include <linux/pkt_cls.h> #define TCA_ACT_GACT 5 diff --git a/include/linux/tc_act/tc_mirred.h b/include/linux/tc_act/tc_mirred.h index 71d6340..0a99ab6 100644 --- a/include/linux/tc_act/tc_mirred.h +++ b/include/linux/tc_act/tc_mirred.h @@ -1,6 +1,7 @@ #ifndef __LINUX_TC_MIR_H #define __LINUX_TC_MIR_H +#include <linux/types.h> #include <linux/pkt_cls.h> #define TCA_ACT_MIRRED 8 diff --git a/include/linux/tc_act/tc_pedit.h b/include/linux/tc_act/tc_pedit.h index 83e56e3..54ce906 100644 --- a/include/linux/tc_act/tc_pedit.h +++ b/include/linux/tc_act/tc_pedit.h @@ -1,6 +1,7 @@ #ifndef __LINUX_TC_PED_H #define __LINUX_TC_PED_H +#include <linux/types.h> #include <linux/pkt_cls.h> #define TCA_ACT_PEDIT 7 diff --git a/include/linux/tc_ematch/tc_em_cmp.h b/include/linux/tc_ematch/tc_em_cmp.h index c7f4d43..38e7f7b 100644 --- a/include/linux/tc_ematch/tc_em_cmp.h +++ b/include/linux/tc_ematch/tc_em_cmp.h @@ -1,6 +1,7 @@ #ifndef __LINUX_TC_EM_CMP_H #define __LINUX_TC_EM_CMP_H +#include <linux/types.h> #include <linux/pkt_cls.h> struct tcf_em_cmp diff --git a/include/linux/tc_ematch/tc_em_meta.h b/include/linux/tc_ematch/tc_em_meta.h index c50d2ba..dcfb733 100644 --- a/include/linux/tc_ematch/tc_em_meta.h +++ b/include/linux/tc_ematch/tc_em_meta.h @@ -1,6 +1,7 @@ #ifndef __LINUX_TC_EM_META_H #define __LINUX_TC_EM_META_H +#include <linux/types.h> #include <linux/pkt_cls.h> enum diff --git a/include/linux/tc_ematch/tc_em_nbyte.h b/include/linux/tc_ematch/tc_em_nbyte.h index f19d1f5..9ed8c2e 100644 --- a/include/linux/tc_ematch/tc_em_nbyte.h +++ b/include/linux/tc_ematch/tc_em_nbyte.h @@ -1,6 +1,7 @@ #ifndef __LINUX_TC_EM_NBYTE_H #define __LINUX_TC_EM_NBYTE_H +#include <linux/types.h> #include <linux/pkt_cls.h> struct tcf_em_nbyte diff --git a/include/linux/tc_ematch/tc_em_text.h b/include/linux/tc_ematch/tc_em_text.h index 7cd43e9..d12a73a 100644 --- a/include/linux/tc_ematch/tc_em_text.h +++ b/include/linux/tc_ematch/tc_em_text.h @@ -1,6 +1,7 @@ #ifndef __LINUX_TC_EM_TEXT_H #define __LINUX_TC_EM_TEXT_H +#include <linux/types.h> #include <linux/pkt_cls.h> #define TC_EM_TEXT_ALGOSIZ 16 diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h index 18a7293..3c86ed2 100644 --- a/include/linux/usb/cdc.h +++ b/include/linux/usb/cdc.h @@ -9,6 +9,8 @@ #ifndef __LINUX_USB_CDC_H #define __LINUX_USB_CDC_H +#include <linux/types.h> + #define USB_CDC_SUBCLASS_ACM 0x02 #define USB_CDC_SUBCLASS_ETHERNET 0x06 #define USB_CDC_SUBCLASS_WHCM 0x08 diff --git a/include/linux/usb/gadgetfs.h b/include/linux/usb/gadgetfs.h index ea45f26..612102e 100644 --- a/include/linux/usb/gadgetfs.h +++ b/include/linux/usb/gadgetfs.h @@ -18,7 +18,7 @@ #ifndef __LINUX_USB_GADGETFS_H #define __LINUX_USB_GADGETFS_H -#include <asm/types.h> +#include <linux/types.h> #include <asm/ioctl.h> #include <linux/usb/ch9.h> diff --git a/include/linux/video_decoder.h b/include/linux/video_decoder.h index 121e26d..e26c0c8 100644 --- a/include/linux/video_decoder.h +++ b/include/linux/video_decoder.h @@ -1,6 +1,8 @@ #ifndef _LINUX_VIDEO_DECODER_H #define _LINUX_VIDEO_DECODER_H +#include <linux/types.h> + #define HAVE_VIDEO_DECODER 1 struct video_decoder_capability { /* this name is too long */ diff --git a/include/linux/video_encoder.h b/include/linux/video_encoder.h index 4b0e690..b7b6423 100644 --- a/include/linux/video_encoder.h +++ b/include/linux/video_encoder.h @@ -1,6 +1,8 @@ #ifndef _LINUX_VIDEO_ENCODER_H #define _LINUX_VIDEO_ENCODER_H +#include <linux/types.h> + struct video_encoder_capability { /* this name is too long */ __u32 flags; #define VIDEO_ENCODER_PAL 1 /* can encode PAL signal */ diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 15a653d..837f392 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -12,6 +12,7 @@ #ifndef __LINUX_VIDEODEV_H #define __LINUX_VIDEODEV_H +#include <linux/types.h> #include <linux/ioctl.h> #include <linux/videodev2.h> diff --git a/include/linux/virtio_blk.h b/include/linux/virtio_blk.h index c1aef85..94c56d2 100644 --- a/include/linux/virtio_blk.h +++ b/include/linux/virtio_blk.h @@ -2,6 +2,7 @@ #define _LINUX_VIRTIO_BLK_H /* This header is BSD licensed so anyone can use the definitions to implement * compatible drivers/servers. */ +#include <linux/types.h> #include <linux/virtio_config.h> /* The ID for virtio_block */ diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h index 7615ffc..dc16111 100644 --- a/include/linux/virtio_console.h +++ b/include/linux/virtio_console.h @@ -1,5 +1,6 @@ #ifndef _LINUX_VIRTIO_CONSOLE_H #define _LINUX_VIRTIO_CONSOLE_H +#include <linux/types.h> #include <linux/virtio_config.h> /* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so * anyone can use the definitions to implement compatible drivers/servers. */ diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 5cdd0aa..3efa86c 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -2,6 +2,7 @@ #define _LINUX_VIRTIO_NET_H /* This header is BSD licensed so anyone can use the definitions to implement * compatible drivers/servers. */ +#include <linux/types.h> #include <linux/virtio_config.h> /* The ID for virtio_net */ diff --git a/include/linux/wait.h b/include/linux/wait.h index ef609f8..a210ede 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -132,6 +132,8 @@ static inline void __remove_wait_queue(wait_queue_head_t *head, list_del(&old->task_list); } +void __wake_up_common(wait_queue_head_t *q, unsigned int mode, + int nr_exclusive, int sync, void *key); void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr, void *key); extern void __wake_up_locked(wait_queue_head_t *q, unsigned int mode); extern void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr); @@ -333,16 +335,19 @@ do { \ for (;;) { \ prepare_to_wait_exclusive(&wq, &__wait, \ TASK_INTERRUPTIBLE); \ - if (condition) \ + if (condition) { \ + finish_wait(&wq, &__wait); \ break; \ + } \ if (!signal_pending(current)) { \ schedule(); \ continue; \ } \ ret = -ERESTARTSYS; \ + abort_exclusive_wait(&wq, &__wait, \ + TASK_INTERRUPTIBLE, NULL); \ break; \ } \ - finish_wait(&wq, &__wait); \ } while (0) #define wait_event_interruptible_exclusive(wq, condition) \ @@ -431,6 +436,8 @@ extern long interruptible_sleep_on_timeout(wait_queue_head_t *q, void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state); void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state); void finish_wait(wait_queue_head_t *q, wait_queue_t *wait); +void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait, + unsigned int mode, void *key); int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key); int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key); diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h index 9bf4ccc..55e41af 100644 --- a/include/media/v4l2-device.h +++ b/include/media/v4l2-device.h @@ -94,16 +94,16 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd); /* Call the specified callback for all subdevs matching grp_id (if 0, then match them all). Ignore any errors. Note that you cannot add or delete a subdev while walking the subdevs list. */ -#define v4l2_device_call_all(dev, grp_id, o, f, args...) \ +#define v4l2_device_call_all(dev, grpid, o, f, args...) \ __v4l2_device_call_subdevs(dev, \ - !(grp_id) || sd->grp_id == (grp_id), o, f , ##args) + !(grpid) || sd->grp_id == (grpid), o, f , ##args) /* Call the specified callback for all subdevs matching grp_id (if 0, then match them all). If the callback returns an error other than 0 or -ENOIOCTLCMD, then return with that error code. Note that you cannot add or delete a subdev while walking the subdevs list. */ -#define v4l2_device_call_until_err(dev, grp_id, o, f, args...) \ +#define v4l2_device_call_until_err(dev, grpid, o, f, args...) \ __v4l2_device_call_subdevs_until_err(dev, \ - !(grp_id) || sd->grp_id == (grp_id), o, f , ##args) + !(grpid) || sd->grp_id == (grpid), o, f , ##args) #endif diff --git a/include/mtd/inftl-user.h b/include/mtd/inftl-user.h index e17eda3..d409d48 100644 --- a/include/mtd/inftl-user.h +++ b/include/mtd/inftl-user.h @@ -6,6 +6,8 @@ #ifndef __MTD_INFTL_USER_H__ #define __MTD_INFTL_USER_H__ +#include <linux/types.h> + #define OSAK_VERSION 0x5120 #define PERCENTUSED 98 diff --git a/include/sound/hdsp.h b/include/sound/hdsp.h index dec6b1d..d98a78d 100644 --- a/include/sound/hdsp.h +++ b/include/sound/hdsp.h @@ -19,6 +19,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/types.h> + #define HDSP_MATRIX_MIXER_SIZE 2048 enum HDSP_IO_Type { diff --git a/include/video/aty128.h b/include/video/aty128.h index 7079beb..51ac69f 100644 --- a/include/video/aty128.h +++ b/include/video/aty128.h @@ -21,9 +21,9 @@ #define I2C_CNTL_1 0x0094 #define PALETTE_INDEX 0x00b0 #define PALETTE_DATA 0x00b4 -#define CONFIG_CNTL 0x00e0 +#define CNFG_CNTL 0x00e0 #define GEN_RESET_CNTL 0x00f0 -#define CONFIG_MEMSIZE 0x00f8 +#define CNFG_MEMSIZE 0x00f8 #define MEM_CNTL 0x0140 #define MEM_POWER_MISC 0x015c #define AGP_BASE 0x0170 diff --git a/include/video/mach64.h b/include/video/mach64.h index a8332e5..89e91c0 100644 --- a/include/video/mach64.h +++ b/include/video/mach64.h @@ -103,7 +103,7 @@ #define CUR_HORZ_VERT_OFF 0x0070 /* Dword offset 0_1C */ #define CUR2_HORZ_VERT_OFF 0x0070 /* Dword offset 0_1C */ -#define CONFIG_PANEL_LG 0x0074 /* Dword offset 0_1D (LG) */ +#define CNFG_PANEL_LG 0x0074 /* Dword offset 0_1D (LG) */ /* General I/O Control */ #define GP_IO 0x0078 /* Dword offset 0_1E */ @@ -146,8 +146,8 @@ #define CLOCK_SEL_CNTL 0x0090 /* Dword offset 0_24 */ /* Configuration */ -#define CONFIG_STAT1 0x0094 /* Dword offset 0_25 */ -#define CONFIG_STAT2 0x0098 /* Dword offset 0_26 */ +#define CNFG_STAT1 0x0094 /* Dword offset 0_25 */ +#define CNFG_STAT2 0x0098 /* Dword offset 0_26 */ /* Bus Control */ #define BUS_CNTL 0x00A0 /* Dword offset 0_28 */ @@ -190,9 +190,9 @@ #define POWER_MANAGEMENT_LG 0x00D8 /* Dword offset 0_36 (LG) */ /* Configuration */ -#define CONFIG_CNTL 0x00DC /* Dword offset 0_37 (CT, ET, VT) */ -#define CONFIG_CHIP_ID 0x00E0 /* Dword offset 0_38 */ -#define CONFIG_STAT0 0x00E4 /* Dword offset 0_39 */ +#define CNFG_CNTL 0x00DC /* Dword offset 0_37 (CT, ET, VT) */ +#define CNFG_CHIP_ID 0x00E0 /* Dword offset 0_38 */ +#define CNFG_STAT0 0x00E4 /* Dword offset 0_39 */ /* Test and Debug */ #define CRC_SIG 0x00E8 /* Dword offset 0_3A */ @@ -851,17 +851,17 @@ #define PLL_YCLK_CNTL 0x29 #define PM_DYN_CLK_CNTL 0x2A -/* CONFIG_CNTL register constants */ +/* CNFG_CNTL register constants */ #define APERTURE_4M_ENABLE 1 #define APERTURE_8M_ENABLE 2 #define VGA_APERTURE_ENABLE 4 -/* CONFIG_STAT0 register constants (GX, CX) */ +/* CNFG_STAT0 register constants (GX, CX) */ #define CFG_BUS_TYPE 0x00000007 #define CFG_MEM_TYPE 0x00000038 #define CFG_INIT_DAC_TYPE 0x00000e00 -/* CONFIG_STAT0 register constants (CT, ET, VT) */ +/* CNFG_STAT0 register constants (CT, ET, VT) */ #define CFG_MEM_TYPE_xT 0x00000007 #define ISA 0 @@ -942,7 +942,7 @@ #define PCI_ATI_VENDOR_ID 0x1002 -/* CONFIG_CHIP_ID register constants */ +/* CNFG_CHIP_ID register constants */ #define CFG_CHIP_TYPE 0x0000FFFF #define CFG_CHIP_CLASS 0x00FF0000 #define CFG_CHIP_REV 0xFF000000 @@ -951,7 +951,7 @@ #define CFG_CHIP_MINOR 0xC0000000 -/* Chip IDs read from CONFIG_CHIP_ID */ +/* Chip IDs read from CNFG_CHIP_ID */ /* mach64GX family */ #define GX_CHIP_ID 0xD7 /* mach64GX (ATI888GX00) */ @@ -1254,7 +1254,7 @@ #define CRTC2_DISPLAY_DIS 0x00000400 /* LCD register indices */ -#define CONFIG_PANEL 0x00 +#define CNFG_PANEL 0x00 #define LCD_GEN_CNTL 0x01 #define DSTN_CONTROL 0x02 #define HFB_PITCH_ADDR 0x03 diff --git a/include/video/radeon.h b/include/video/radeon.h index 1cd09cc..e072b16 100644 --- a/include/video/radeon.h +++ b/include/video/radeon.h @@ -11,13 +11,13 @@ #define HI_STAT 0x004C #define BUS_CNTL1 0x0034 #define I2C_CNTL_1 0x0094 -#define CONFIG_CNTL 0x00E0 -#define CONFIG_MEMSIZE 0x00F8 -#define CONFIG_APER_0_BASE 0x0100 -#define CONFIG_APER_1_BASE 0x0104 -#define CONFIG_APER_SIZE 0x0108 -#define CONFIG_REG_1_BASE 0x010C -#define CONFIG_REG_APER_SIZE 0x0110 +#define CNFG_CNTL 0x00E0 +#define CNFG_MEMSIZE 0x00F8 +#define CNFG_APER_0_BASE 0x0100 +#define CNFG_APER_1_BASE 0x0104 +#define CNFG_APER_SIZE 0x0108 +#define CNFG_REG_1_BASE 0x010C +#define CNFG_REG_APER_SIZE 0x0110 #define PAD_AGPINPUT_DELAY 0x0164 #define PAD_CTLR_STRENGTH 0x0168 #define PAD_CTLR_UPDATE 0x016C @@ -509,7 +509,7 @@ /* CLOCK_CNTL_INDEX bit constants */ #define PLL_WR_EN 0x00000080 -/* CONFIG_CNTL bit constants */ +/* CNFG_CNTL bit constants */ #define CFG_VGA_RAM_EN 0x00000100 #define CFG_ATI_REV_ID_MASK (0xf << 16) #define CFG_ATI_REV_A11 (0 << 16) @@ -980,7 +980,7 @@ /* masks */ -#define CONFIG_MEMSIZE_MASK 0x1f000000 +#define CNFG_MEMSIZE_MASK 0x1f000000 #define MEM_CFG_TYPE 0x40000000 #define DST_OFFSET_MASK 0x003fffff #define DST_PITCH_MASK 0x3fc00000 diff --git a/include/video/sisfb.h b/include/video/sisfb.h index e402eb5..fdd74f1 100644 --- a/include/video/sisfb.h +++ b/include/video/sisfb.h @@ -21,8 +21,8 @@ #ifndef _LINUX_SISFB_H_ #define _LINUX_SISFB_H_ +#include <linux/types.h> #include <asm/ioctl.h> -#include <asm/types.h> /**********************************************/ /* PUBLIC */ diff --git a/include/video/uvesafb.h b/include/video/uvesafb.h index 95bcef1..0993a22 100644 --- a/include/video/uvesafb.h +++ b/include/video/uvesafb.h @@ -1,6 +1,8 @@ #ifndef _UVESAFB_H #define _UVESAFB_H +#include <linux/types.h> + struct v86_regs { __u32 ebx; __u32 ecx; @@ -368,14 +368,14 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) file = hugetlb_file_setup(name, size); shp->mlock_user = current_user(); } else { - int acctflag = VM_ACCOUNT; + int acctflag = 0; /* * Do not allow no accounting for OVERCOMMIT_NEVER, even * if it's asked for. */ if ((shmflg & SHM_NORESERVE) && sysctl_overcommit_memory != OVERCOMMIT_NEVER) - acctflag = 0; + acctflag = VM_NORESERVE; file = shmem_file_setup(name, size, acctflag); } error = PTR_ERR(file); @@ -565,11 +565,15 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss, struct hstate *h = hstate_file(shp->shm_file); *rss += pages_per_huge_page(h) * mapping->nrpages; } else { +#ifdef CONFIG_SHMEM struct shmem_inode_info *info = SHMEM_I(inode); spin_lock(&info->lock); *rss += inode->i_mapping->nrpages; *swp += info->swapped; spin_unlock(&info->lock); +#else + *rss += inode->i_mapping->nrpages; +#endif } total++; diff --git a/kernel/async.c b/kernel/async.c index 608b32b..f565891 100644 --- a/kernel/async.c +++ b/kernel/async.c @@ -54,6 +54,7 @@ asynchronous and synchronous parts of the kernel. #include <linux/sched.h> #include <linux/init.h> #include <linux/kthread.h> +#include <linux/delay.h> #include <asm/atomic.h> static async_cookie_t next_cookie = 1; @@ -132,21 +133,23 @@ static void run_one_entry(void) entry = list_first_entry(&async_pending, struct async_entry, list); /* 2) move it to the running queue */ - list_del(&entry->list); - list_add_tail(&entry->list, &async_running); + list_move_tail(&entry->list, entry->running); spin_unlock_irqrestore(&async_lock, flags); /* 3) run it (and print duration)*/ if (initcall_debug && system_state == SYSTEM_BOOTING) { - printk("calling %lli_%pF @ %i\n", entry->cookie, entry->func, task_pid_nr(current)); + printk("calling %lli_%pF @ %i\n", (long long)entry->cookie, + entry->func, task_pid_nr(current)); calltime = ktime_get(); } entry->func(entry->data, entry->cookie); if (initcall_debug && system_state == SYSTEM_BOOTING) { rettime = ktime_get(); delta = ktime_sub(rettime, calltime); - printk("initcall %lli_%pF returned 0 after %lld usecs\n", entry->cookie, - entry->func, ktime_to_ns(delta) >> 10); + printk("initcall %lli_%pF returned 0 after %lld usecs\n", + (long long)entry->cookie, + entry->func, + (long long)ktime_to_ns(delta) >> 10); } /* 4) remove it from the running queue */ @@ -205,18 +208,44 @@ static async_cookie_t __async_schedule(async_func_ptr *ptr, void *data, struct l return newcookie; } +/** + * async_schedule - schedule a function for asynchronous execution + * @ptr: function to execute asynchronously + * @data: data pointer to pass to the function + * + * Returns an async_cookie_t that may be used for checkpointing later. + * Note: This function may be called from atomic or non-atomic contexts. + */ async_cookie_t async_schedule(async_func_ptr *ptr, void *data) { - return __async_schedule(ptr, data, &async_pending); + return __async_schedule(ptr, data, &async_running); } EXPORT_SYMBOL_GPL(async_schedule); -async_cookie_t async_schedule_special(async_func_ptr *ptr, void *data, struct list_head *running) +/** + * async_schedule_domain - schedule a function for asynchronous execution within a certain domain + * @ptr: function to execute asynchronously + * @data: data pointer to pass to the function + * @running: running list for the domain + * + * Returns an async_cookie_t that may be used for checkpointing later. + * @running may be used in the async_synchronize_*_domain() functions + * to wait within a certain synchronization domain rather than globally. + * A synchronization domain is specified via the running queue @running to use. + * Note: This function may be called from atomic or non-atomic contexts. + */ +async_cookie_t async_schedule_domain(async_func_ptr *ptr, void *data, + struct list_head *running) { return __async_schedule(ptr, data, running); } -EXPORT_SYMBOL_GPL(async_schedule_special); +EXPORT_SYMBOL_GPL(async_schedule_domain); +/** + * async_synchronize_full - synchronize all asynchronous function calls + * + * This function waits until all asynchronous function calls have been done. + */ void async_synchronize_full(void) { do { @@ -225,13 +254,30 @@ void async_synchronize_full(void) } EXPORT_SYMBOL_GPL(async_synchronize_full); -void async_synchronize_full_special(struct list_head *list) +/** + * async_synchronize_full_domain - synchronize all asynchronous function within a certain domain + * @list: running list to synchronize on + * + * This function waits until all asynchronous function calls for the + * synchronization domain specified by the running list @list have been done. + */ +void async_synchronize_full_domain(struct list_head *list) { - async_synchronize_cookie_special(next_cookie, list); + async_synchronize_cookie_domain(next_cookie, list); } -EXPORT_SYMBOL_GPL(async_synchronize_full_special); +EXPORT_SYMBOL_GPL(async_synchronize_full_domain); -void async_synchronize_cookie_special(async_cookie_t cookie, struct list_head *running) +/** + * async_synchronize_cookie_domain - synchronize asynchronous function calls within a certain domain with cookie checkpointing + * @cookie: async_cookie_t to use as checkpoint + * @running: running list to synchronize on + * + * This function waits until all asynchronous function calls for the + * synchronization domain specified by the running list @list submitted + * prior to @cookie have been done. + */ +void async_synchronize_cookie_domain(async_cookie_t cookie, + struct list_head *running) { ktime_t starttime, delta, endtime; @@ -247,14 +293,22 @@ void async_synchronize_cookie_special(async_cookie_t cookie, struct list_head *r delta = ktime_sub(endtime, starttime); printk("async_continuing @ %i after %lli usec\n", - task_pid_nr(current), ktime_to_ns(delta) >> 10); + task_pid_nr(current), + (long long)ktime_to_ns(delta) >> 10); } } -EXPORT_SYMBOL_GPL(async_synchronize_cookie_special); +EXPORT_SYMBOL_GPL(async_synchronize_cookie_domain); +/** + * async_synchronize_cookie - synchronize asynchronous function calls with cookie checkpointing + * @cookie: async_cookie_t to use as checkpoint + * + * This function waits until all asynchronous function calls prior to @cookie + * have been done. + */ void async_synchronize_cookie(async_cookie_t cookie) { - async_synchronize_cookie_special(cookie, &async_running); + async_synchronize_cookie_domain(cookie, &async_running); } EXPORT_SYMBOL_GPL(async_synchronize_cookie); @@ -315,7 +369,11 @@ static int async_manager_thread(void *unused) ec = atomic_read(&entry_count); while (tc < ec && tc < MAX_THREADS) { - kthread_run(async_thread, NULL, "async/%i", tc); + if (IS_ERR(kthread_run(async_thread, NULL, "async/%i", + tc))) { + msleep(100); + continue; + } atomic_inc(&thread_count); tc++; } @@ -330,7 +388,9 @@ static int async_manager_thread(void *unused) static int __init async_init(void) { if (async_enabled) - kthread_run(async_manager_thread, NULL, "async/mgr"); + if (IS_ERR(kthread_run(async_manager_thread, NULL, + "async/mgr"))) + async_enabled = 0; return 0; } diff --git a/kernel/cpuset.c b/kernel/cpuset.c index a856788..f76db9d 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -61,6 +61,14 @@ #include <linux/cgroup.h> /* + * Workqueue for cpuset related tasks. + * + * Using kevent workqueue may cause deadlock when memory_migrate + * is set. So we create a separate workqueue thread for cpuset. + */ +static struct workqueue_struct *cpuset_wq; + +/* * Tracks how many cpusets are currently defined in system. * When there is only one cpuset (the root cpuset) we can * short circuit some hooks. @@ -831,7 +839,7 @@ static DECLARE_WORK(rebuild_sched_domains_work, do_rebuild_sched_domains); */ static void async_rebuild_sched_domains(void) { - schedule_work(&rebuild_sched_domains_work); + queue_work(cpuset_wq, &rebuild_sched_domains_work); } /* @@ -2111,6 +2119,9 @@ void __init cpuset_init_smp(void) hotcpu_notifier(cpuset_track_online_cpus, 0); hotplug_memory_notifier(cpuset_track_online_nodes, 10); + + cpuset_wq = create_singlethread_workqueue("cpuset"); + BUG_ON(!cpuset_wq); } /** diff --git a/kernel/fork.c b/kernel/fork.c index 99309df..c078438 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1010,6 +1010,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, * triggers too late. This doesn't hurt, the check is only there * to stop root fork bombs. */ + retval = -EAGAIN; if (nr_threads >= max_threads) goto bad_fork_cleanup_count; diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index f33afb0..f394d2a 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -501,6 +501,13 @@ static void hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base) continue; timer = rb_entry(base->first, struct hrtimer, node); expires = ktime_sub(hrtimer_get_expires(timer), base->offset); + /* + * clock_was_set() has changed base->offset so the + * result might be negative. Fix it up to prevent a + * false positive in clockevents_program_event() + */ + if (expires.tv64 < 0) + expires.tv64 = 0; if (expires.tv64 < cpu_base->expires_next.tv64) cpu_base->expires_next = expires; } @@ -1158,6 +1165,29 @@ static void __run_hrtimer(struct hrtimer *timer) #ifdef CONFIG_HIGH_RES_TIMERS +static int force_clock_reprogram; + +/* + * After 5 iteration's attempts, we consider that hrtimer_interrupt() + * is hanging, which could happen with something that slows the interrupt + * such as the tracing. Then we force the clock reprogramming for each future + * hrtimer interrupts to avoid infinite loops and use the min_delta_ns + * threshold that we will overwrite. + * The next tick event will be scheduled to 3 times we currently spend on + * hrtimer_interrupt(). This gives a good compromise, the cpus will spend + * 1/4 of their time to process the hrtimer interrupts. This is enough to + * let it running without serious starvation. + */ + +static inline void +hrtimer_interrupt_hanging(struct clock_event_device *dev, + ktime_t try_time) +{ + force_clock_reprogram = 1; + dev->min_delta_ns = (unsigned long)try_time.tv64 * 3; + printk(KERN_WARNING "hrtimer: interrupt too slow, " + "forcing clock min delta to %lu ns\n", dev->min_delta_ns); +} /* * High resolution timer interrupt * Called with interrupts disabled @@ -1167,6 +1197,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); struct hrtimer_clock_base *base; ktime_t expires_next, now; + int nr_retries = 0; int i; BUG_ON(!cpu_base->hres_active); @@ -1174,6 +1205,10 @@ void hrtimer_interrupt(struct clock_event_device *dev) dev->next_event.tv64 = KTIME_MAX; retry: + /* 5 retries is enough to notice a hang */ + if (!(++nr_retries % 5)) + hrtimer_interrupt_hanging(dev, ktime_sub(ktime_get(), now)); + now = ktime_get(); expires_next.tv64 = KTIME_MAX; @@ -1226,7 +1261,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) /* Reprogramming necessary ? */ if (expires_next.tv64 != KTIME_MAX) { - if (tick_program_event(expires_next, 0)) + if (tick_program_event(expires_next, force_clock_reprogram)) goto retry; } } @@ -1580,6 +1615,10 @@ static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self, break; #ifdef CONFIG_HOTPLUG_CPU + case CPU_DYING: + case CPU_DYING_FROZEN: + clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DYING, &scpu); + break; case CPU_DEAD: case CPU_DEAD_FROZEN: { diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index c248eba..122fef4 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -386,6 +386,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) out_unlock: spin_unlock(&desc->lock); } +EXPORT_SYMBOL_GPL(handle_level_irq); /** * handle_fasteoi_irq - irq handler for transparent controllers @@ -596,6 +597,7 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, } spin_unlock_irqrestore(&desc->lock, flags); } +EXPORT_SYMBOL_GPL(__set_irq_handler); void set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip, diff --git a/kernel/irq/numa_migrate.c b/kernel/irq/numa_migrate.c index 666260e..7f9b804 100644 --- a/kernel/irq/numa_migrate.c +++ b/kernel/irq/numa_migrate.c @@ -78,7 +78,7 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc, desc = irq_desc_ptrs[irq]; if (desc && old_desc != desc) - goto out_unlock; + goto out_unlock; node = cpu_to_node(cpu); desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node); @@ -97,10 +97,15 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc, } irq_desc_ptrs[irq] = desc; + spin_unlock_irqrestore(&sparse_irq_lock, flags); /* free the old one */ free_one_irq_desc(old_desc, desc); + spin_unlock(&old_desc->lock); kfree(old_desc); + spin_lock(&desc->lock); + + return desc; out_unlock: spin_unlock_irqrestore(&sparse_irq_lock, flags); diff --git a/kernel/module.c b/kernel/module.c index e8b51d4..ba22484 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -573,13 +573,13 @@ static char last_unloaded_module[MODULE_NAME_LEN+1]; /* Init the unload section of the module. */ static void module_unload_init(struct module *mod) { - unsigned int i; + int cpu; INIT_LIST_HEAD(&mod->modules_which_use_me); - for (i = 0; i < NR_CPUS; i++) - local_set(&mod->ref[i].count, 0); + for_each_possible_cpu(cpu) + local_set(__module_ref_addr(mod, cpu), 0); /* Hold reference count during initialization. */ - local_set(&mod->ref[raw_smp_processor_id()].count, 1); + local_set(__module_ref_addr(mod, raw_smp_processor_id()), 1); /* Backwards compatibility macros put refcount during init. */ mod->waiter = current; } @@ -717,10 +717,11 @@ static int try_stop_module(struct module *mod, int flags, int *forced) unsigned int module_refcount(struct module *mod) { - unsigned int i, total = 0; + unsigned int total = 0; + int cpu; - for (i = 0; i < NR_CPUS; i++) - total += local_read(&mod->ref[i].count); + for_each_possible_cpu(cpu) + total += local_read(__module_ref_addr(mod, cpu)); return total; } EXPORT_SYMBOL(module_refcount); @@ -894,7 +895,7 @@ void module_put(struct module *module) { if (module) { unsigned int cpu = get_cpu(); - local_dec(&module->ref[cpu].count); + local_dec(__module_ref_addr(module, cpu)); /* Maybe they're waiting for us to drop reference? */ if (unlikely(!module_is_live(module))) wake_up_process(module->waiter); @@ -1464,7 +1465,10 @@ static void free_module(struct module *mod) kfree(mod->args); if (mod->percpu) percpu_modfree(mod->percpu); - +#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) + if (mod->refptr) + percpu_modfree(mod->refptr); +#endif /* Free lock-classes: */ lockdep_free_key_range(mod->module_core, mod->core_size); @@ -2011,6 +2015,14 @@ static noinline struct module *load_module(void __user *umod, if (err < 0) goto free_mod; +#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) + mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), + mod->name); + if (!mod->refptr) { + err = -ENOMEM; + goto free_mod; + } +#endif if (pcpuindex) { /* We have a special allocation for this section. */ percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size, @@ -2018,7 +2030,7 @@ static noinline struct module *load_module(void __user *umod, mod->name); if (!percpu) { err = -ENOMEM; - goto free_mod; + goto free_percpu; } sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC; mod->percpu = percpu; @@ -2282,6 +2294,9 @@ static noinline struct module *load_module(void __user *umod, free_percpu: if (percpu) percpu_modfree(percpu); +#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) + percpu_modfree(mod->refptr); +#endif free_mod: kfree(args); free_hdr: diff --git a/kernel/power/main.c b/kernel/power/main.c index 2399888..b4d2190 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -57,16 +57,6 @@ int pm_notifier_call_chain(unsigned long val) #ifdef CONFIG_PM_DEBUG int pm_test_level = TEST_NONE; -static int suspend_test(int level) -{ - if (pm_test_level == level) { - printk(KERN_INFO "suspend debug: Waiting for 5 seconds.\n"); - mdelay(5000); - return 1; - } - return 0; -} - static const char * const pm_tests[__TEST_AFTER_LAST] = { [TEST_NONE] = "none", [TEST_CORE] = "core", @@ -125,14 +115,24 @@ static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr, } power_attr(pm_test); -#else /* !CONFIG_PM_DEBUG */ -static inline int suspend_test(int level) { return 0; } -#endif /* !CONFIG_PM_DEBUG */ +#endif /* CONFIG_PM_DEBUG */ #endif /* CONFIG_PM_SLEEP */ #ifdef CONFIG_SUSPEND +static int suspend_test(int level) +{ +#ifdef CONFIG_PM_DEBUG + if (pm_test_level == level) { + printk(KERN_INFO "suspend debug: Waiting for 5 seconds.\n"); + mdelay(5000); + return 1; + } +#endif /* !CONFIG_PM_DEBUG */ + return 0; +} + #ifdef CONFIG_PM_TEST_SUSPEND /* diff --git a/kernel/sched.c b/kernel/sched.c index c71d7d5..fc17fd9 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2266,6 +2266,16 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync) if (!sched_feat(SYNC_WAKEUPS)) sync = 0; + if (!sync) { + if (current->se.avg_overlap < sysctl_sched_migration_cost && + p->se.avg_overlap < sysctl_sched_migration_cost) + sync = 1; + } else { + if (current->se.avg_overlap >= sysctl_sched_migration_cost || + p->se.avg_overlap >= sysctl_sched_migration_cost) + sync = 0; + } + #ifdef CONFIG_SMP if (sched_feat(LB_WAKEUP_UPDATE)) { struct sched_domain *sd; @@ -4687,8 +4697,8 @@ EXPORT_SYMBOL(default_wake_function); * started to run but is not in state TASK_RUNNING. try_to_wake_up() returns * zero in this (rare) case, and we handle it by continuing to scan the queue. */ -static void __wake_up_common(wait_queue_head_t *q, unsigned int mode, - int nr_exclusive, int sync, void *key) +void __wake_up_common(wait_queue_head_t *q, unsigned int mode, + int nr_exclusive, int sync, void *key) { wait_queue_t *curr, *next; diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 5cc1c16..a7e50ba 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -719,7 +719,7 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup) __enqueue_entity(cfs_rq, se); } -static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se) +static void __clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se) { if (cfs_rq->last == se) cfs_rq->last = NULL; @@ -728,6 +728,12 @@ static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se) cfs_rq->next = NULL; } +static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se) +{ + for_each_sched_entity(se) + __clear_buddies(cfs_rq_of(se), se); +} + static void dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) { @@ -768,8 +774,14 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr) ideal_runtime = sched_slice(cfs_rq, curr); delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime; - if (delta_exec > ideal_runtime) + if (delta_exec > ideal_runtime) { resched_task(rq_of(cfs_rq)->curr); + /* + * The current task ran long enough, ensure it doesn't get + * re-elected due to buddy favours. + */ + clear_buddies(cfs_rq, curr); + } } static void @@ -1179,20 +1191,15 @@ wake_affine(struct sched_domain *this_sd, struct rq *this_rq, int idx, unsigned long load, unsigned long this_load, unsigned int imbalance) { - struct task_struct *curr = this_rq->curr; - struct task_group *tg; unsigned long tl = this_load; unsigned long tl_per_task; + struct task_group *tg; unsigned long weight; int balanced; if (!(this_sd->flags & SD_WAKE_AFFINE) || !sched_feat(AFFINE_WAKEUPS)) return 0; - if (sync && (curr->se.avg_overlap > sysctl_sched_migration_cost || - p->se.avg_overlap > sysctl_sched_migration_cost)) - sync = 0; - /* * If sync wakeup then subtract the (maximum possible) * effect of the currently running task from the load @@ -1419,9 +1426,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int sync) if (!sched_feat(WAKEUP_PREEMPT)) return; - if (sched_feat(WAKEUP_OVERLAP) && (sync || - (se->avg_overlap < sysctl_sched_migration_cost && - pse->avg_overlap < sysctl_sched_migration_cost))) { + if (sched_feat(WAKEUP_OVERLAP) && sync) { resched_task(curr); return; } @@ -1452,6 +1457,11 @@ static struct task_struct *pick_next_task_fair(struct rq *rq) do { se = pick_next_entity(cfs_rq); + /* + * If se was a buddy, clear it so that it will have to earn + * the favour again. + */ + __clear_buddies(cfs_rq, se); set_next_entity(cfs_rq, se); cfs_rq = group_cfs_rq(se); } while (cfs_rq); diff --git a/kernel/signal.c b/kernel/signal.c index e737597..b6b3676 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -909,7 +909,9 @@ static void print_fatal_signal(struct pt_regs *regs, int signr) } #endif printk("\n"); + preempt_disable(); show_regs(regs); + preempt_enable(); } static int __init setup_print_fatal_signals(char *str) diff --git a/kernel/smp.c b/kernel/smp.c index 5cfa0e5..bbedbb7 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -18,6 +18,7 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_function_lock); enum { CSD_FLAG_WAIT = 0x01, CSD_FLAG_ALLOC = 0x02, + CSD_FLAG_LOCK = 0x04, }; struct call_function_data { @@ -186,6 +187,9 @@ void generic_smp_call_function_single_interrupt(void) if (data_flags & CSD_FLAG_WAIT) { smp_wmb(); data->flags &= ~CSD_FLAG_WAIT; + } else if (data_flags & CSD_FLAG_LOCK) { + smp_wmb(); + data->flags &= ~CSD_FLAG_LOCK; } else if (data_flags & CSD_FLAG_ALLOC) kfree(data); } @@ -196,6 +200,8 @@ void generic_smp_call_function_single_interrupt(void) } } +static DEFINE_PER_CPU(struct call_single_data, csd_data); + /* * smp_call_function_single - Run a function on a specific CPU * @func: The function to run. This must be fast and non-blocking. @@ -224,14 +230,38 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, func(info); local_irq_restore(flags); } else if ((unsigned)cpu < nr_cpu_ids && cpu_online(cpu)) { - struct call_single_data *data = NULL; + struct call_single_data *data; if (!wait) { + /* + * We are calling a function on a single CPU + * and we are not going to wait for it to finish. + * We first try to allocate the data, but if we + * fail, we fall back to use a per cpu data to pass + * the information to that CPU. Since all callers + * of this code will use the same data, we must + * synchronize the callers to prevent a new caller + * from corrupting the data before the callee + * can access it. + * + * The CSD_FLAG_LOCK is used to let us know when + * the IPI handler is done with the data. + * The first caller will set it, and the callee + * will clear it. The next caller must wait for + * it to clear before we set it again. This + * will make sure the callee is done with the + * data before a new caller will use it. + */ data = kmalloc(sizeof(*data), GFP_ATOMIC); if (data) data->flags = CSD_FLAG_ALLOC; - } - if (!data) { + else { + data = &per_cpu(csd_data, me); + while (data->flags & CSD_FLAG_LOCK) + cpu_relax(); + data->flags = CSD_FLAG_LOCK; + } + } else { data = &d; data->flags = CSD_FLAG_WAIT; } diff --git a/kernel/sys.c b/kernel/sys.c index e7dc0e1..f145c41 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1525,22 +1525,14 @@ SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim) return -EINVAL; if (copy_from_user(&new_rlim, rlim, sizeof(*rlim))) return -EFAULT; + if (new_rlim.rlim_cur > new_rlim.rlim_max) + return -EINVAL; old_rlim = current->signal->rlim + resource; if ((new_rlim.rlim_max > old_rlim->rlim_max) && !capable(CAP_SYS_RESOURCE)) return -EPERM; - - if (resource == RLIMIT_NOFILE) { - if (new_rlim.rlim_max == RLIM_INFINITY) - new_rlim.rlim_max = sysctl_nr_open; - if (new_rlim.rlim_cur == RLIM_INFINITY) - new_rlim.rlim_cur = sysctl_nr_open; - if (new_rlim.rlim_max > sysctl_nr_open) - return -EPERM; - } - - if (new_rlim.rlim_cur > new_rlim.rlim_max) - return -EINVAL; + if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open) + return -EPERM; retval = security_task_setrlimit(resource, &new_rlim); if (retval) diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 63e05d4..21a5ca8 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -274,6 +274,21 @@ out_bc: } /* + * Transfer the do_timer job away from a dying cpu. + * + * Called with interrupts disabled. + */ +static void tick_handover_do_timer(int *cpup) +{ + if (*cpup == tick_do_timer_cpu) { + int cpu = cpumask_first(cpu_online_mask); + + tick_do_timer_cpu = (cpu < nr_cpu_ids) ? cpu : + TICK_DO_TIMER_NONE; + } +} + +/* * Shutdown an event device on a given cpu: * * This is called on a life CPU, when a CPU is dead. So we cannot @@ -297,13 +312,6 @@ static void tick_shutdown(unsigned int *cpup) clockevents_exchange_device(dev, NULL); td->evtdev = NULL; } - /* Transfer the do_timer job away from this cpu */ - if (*cpup == tick_do_timer_cpu) { - int cpu = cpumask_first(cpu_online_mask); - - tick_do_timer_cpu = (cpu < nr_cpu_ids) ? cpu : - TICK_DO_TIMER_NONE; - } spin_unlock_irqrestore(&tick_device_lock, flags); } @@ -357,6 +365,10 @@ static int tick_notify(struct notifier_block *nb, unsigned long reason, tick_broadcast_oneshot_control(reason); break; + case CLOCK_EVT_NOTIFY_CPU_DYING: + tick_handover_do_timer(dev); + break; + case CLOCK_EVT_NOTIFY_CPU_DEAD: tick_shutdown_broadcast_oneshot(dev); tick_shutdown_broadcast(dev); diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 2f32969..9a236ff 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -17,6 +17,7 @@ #include <linux/clocksource.h> #include <linux/kallsyms.h> #include <linux/seq_file.h> +#include <linux/suspend.h> #include <linux/debugfs.h> #include <linux/hardirq.h> #include <linux/kthread.h> @@ -1736,9 +1737,12 @@ static void clear_ftrace_pid(struct pid *pid) { struct task_struct *p; + rcu_read_lock(); do_each_pid_task(pid, PIDTYPE_PID, p) { clear_tsk_trace_trace(p); } while_each_pid_task(pid, PIDTYPE_PID, p); + rcu_read_unlock(); + put_pid(pid); } @@ -1746,9 +1750,11 @@ static void set_ftrace_pid(struct pid *pid) { struct task_struct *p; + rcu_read_lock(); do_each_pid_task(pid, PIDTYPE_PID, p) { set_tsk_trace_trace(p); } while_each_pid_task(pid, PIDTYPE_PID, p); + rcu_read_unlock(); } static void clear_ftrace_pid_task(struct pid **pid) @@ -1965,6 +1971,7 @@ ftrace_enable_sysctl(struct ctl_table *table, int write, #ifdef CONFIG_FUNCTION_GRAPH_TRACER static atomic_t ftrace_graph_active; +static struct notifier_block ftrace_suspend_notifier; int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace) { @@ -2043,6 +2050,27 @@ static int start_graph_tracing(void) return ret; } +/* + * Hibernation protection. + * The state of the current task is too much unstable during + * suspend/restore to disk. We want to protect against that. + */ +static int +ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state, + void *unused) +{ + switch (state) { + case PM_HIBERNATION_PREPARE: + pause_graph_tracing(); + break; + + case PM_POST_HIBERNATION: + unpause_graph_tracing(); + break; + } + return NOTIFY_DONE; +} + int register_ftrace_graph(trace_func_graph_ret_t retfunc, trace_func_graph_ent_t entryfunc) { @@ -2050,6 +2078,9 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc, mutex_lock(&ftrace_sysctl_lock); + ftrace_suspend_notifier.notifier_call = ftrace_suspend_notifier_call; + register_pm_notifier(&ftrace_suspend_notifier); + atomic_inc(&ftrace_graph_active); ret = start_graph_tracing(); if (ret) { @@ -2075,6 +2106,7 @@ void unregister_ftrace_graph(void) ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub; ftrace_graph_entry = ftrace_graph_entry_stub; ftrace_shutdown(FTRACE_STOP_FUNC_RET); + unregister_pm_notifier(&ftrace_suspend_notifier); mutex_unlock(&ftrace_sysctl_lock); } diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 8b0daf0..bd38c5c 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -246,7 +246,7 @@ static inline int test_time_stamp(u64 delta) return 0; } -#define BUF_PAGE_SIZE (PAGE_SIZE - sizeof(struct buffer_data_page)) +#define BUF_PAGE_SIZE (PAGE_SIZE - offsetof(struct buffer_data_page, data)) /* * head_page == tail_page && head == tail then buffer is empty. @@ -1025,12 +1025,8 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer, } if (next_page == head_page) { - if (!(buffer->flags & RB_FL_OVERWRITE)) { - /* reset write */ - if (tail <= BUF_PAGE_SIZE) - local_set(&tail_page->write, tail); + if (!(buffer->flags & RB_FL_OVERWRITE)) goto out_unlock; - } /* tail_page has not moved yet? */ if (tail_page == cpu_buffer->tail_page) { @@ -1105,6 +1101,10 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer, return event; out_unlock: + /* reset write */ + if (tail <= BUF_PAGE_SIZE) + local_set(&tail_page->write, tail); + __raw_spin_unlock(&cpu_buffer->lock); local_irq_restore(flags); return NULL; @@ -2174,6 +2174,9 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) cpu_buffer->overrun = 0; cpu_buffer->entries = 0; + + cpu_buffer->write_stamp = 0; + cpu_buffer->read_stamp = 0; } /** diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index c580233..17bb88d 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -40,7 +40,7 @@ #define TRACE_BUFFER_FLAGS (RB_FL_OVERWRITE) -unsigned long __read_mostly tracing_max_latency = (cycle_t)ULONG_MAX; +unsigned long __read_mostly tracing_max_latency; unsigned long __read_mostly tracing_thresh; /* @@ -3736,7 +3736,7 @@ static struct notifier_block trace_die_notifier = { * it if we decide to change what log level the ftrace dump * should be at. */ -#define KERN_TRACE KERN_INFO +#define KERN_TRACE KERN_EMERG static void trace_printk_seq(struct trace_seq *s) @@ -3770,6 +3770,7 @@ void ftrace_dump(void) dump_ran = 1; /* No turning back! */ + tracing_off(); ftrace_kill(); for_each_tracing_cpu(cpu) { diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c index 7c2e326..62a78d9 100644 --- a/kernel/trace/trace_irqsoff.c +++ b/kernel/trace/trace_irqsoff.c @@ -380,6 +380,7 @@ static void stop_irqsoff_tracer(struct trace_array *tr) static void __irqsoff_tracer_init(struct trace_array *tr) { + tracing_max_latency = 0; irqsoff_trace = tr; /* make sure that the tracer is visible */ smp_wmb(); diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c index 43586b6..42ae1e7 100644 --- a/kernel/trace/trace_sched_wakeup.c +++ b/kernel/trace/trace_sched_wakeup.c @@ -333,6 +333,7 @@ static void stop_wakeup_tracer(struct trace_array *tr) static int wakeup_tracer_init(struct trace_array *tr) { + tracing_max_latency = 0; wakeup_trace = tr; start_wakeup_tracer(tr); return 0; diff --git a/kernel/wait.c b/kernel/wait.c index cd87131..42a2dbc 100644 --- a/kernel/wait.c +++ b/kernel/wait.c @@ -91,6 +91,15 @@ prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state) } EXPORT_SYMBOL(prepare_to_wait_exclusive); +/* + * finish_wait - clean up after waiting in a queue + * @q: waitqueue waited on + * @wait: wait descriptor + * + * Sets current thread back to running state and removes + * the wait descriptor from the given waitqueue if still + * queued. + */ void finish_wait(wait_queue_head_t *q, wait_queue_t *wait) { unsigned long flags; @@ -117,6 +126,39 @@ void finish_wait(wait_queue_head_t *q, wait_queue_t *wait) } EXPORT_SYMBOL(finish_wait); +/* + * abort_exclusive_wait - abort exclusive waiting in a queue + * @q: waitqueue waited on + * @wait: wait descriptor + * @state: runstate of the waiter to be woken + * @key: key to identify a wait bit queue or %NULL + * + * Sets current thread back to running state and removes + * the wait descriptor from the given waitqueue if still + * queued. + * + * Wakes up the next waiter if the caller is concurrently + * woken up through the queue. + * + * This prevents waiter starvation where an exclusive waiter + * aborts and is woken up concurrently and noone wakes up + * the next waiter. + */ +void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait, + unsigned int mode, void *key) +{ + unsigned long flags; + + __set_current_state(TASK_RUNNING); + spin_lock_irqsave(&q->lock, flags); + if (!list_empty(&wait->task_list)) + list_del_init(&wait->task_list); + else if (waitqueue_active(q)) + __wake_up_common(q, mode, 1, 0, key); + spin_unlock_irqrestore(&q->lock, flags); +} +EXPORT_SYMBOL(abort_exclusive_wait); + int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key) { int ret = default_wake_function(wait, mode, sync, key); @@ -177,17 +219,20 @@ int __sched __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q, int (*action)(void *), unsigned mode) { - int ret = 0; - do { + int ret; + prepare_to_wait_exclusive(wq, &q->wait, mode); - if (test_bit(q->key.bit_nr, q->key.flags)) { - if ((ret = (*action)(q->key.flags))) - break; - } + if (!test_bit(q->key.bit_nr, q->key.flags)) + continue; + ret = action(q->key.flags); + if (!ret) + continue; + abort_exclusive_wait(wq, &q->wait, mode, &q->key); + return ret; } while (test_and_set_bit(q->key.bit_nr, q->key.flags)); finish_wait(wq, &q->wait); - return ret; + return 0; } EXPORT_SYMBOL(__wait_on_bit_lock); diff --git a/mm/memory.c b/mm/memory.c index 22bfa7a..baa999e 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1999,7 +1999,7 @@ gotten: * Don't let another task, with possibly unlocked vma, * keep the mlocked page. */ - if (vma->vm_flags & VM_LOCKED) { + if ((vma->vm_flags & VM_LOCKED) && old_page) { lock_page(old_page); /* for LRU manipulation */ clear_page_mlock(old_page); unlock_page(old_page); @@ -294,14 +294,10 @@ static inline int __mlock_posix_error_return(long retval) * * return number of pages [> 0] to be removed from locked_vm on success * of "special" vmas. - * - * return negative error if vma spanning @start-@range disappears while - * mmap semaphore is dropped. Unlikely? */ long mlock_vma_pages_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - struct mm_struct *mm = vma->vm_mm; int nr_pages = (end - start) / PAGE_SIZE; BUG_ON(!(vma->vm_flags & VM_LOCKED)); @@ -314,20 +310,8 @@ long mlock_vma_pages_range(struct vm_area_struct *vma, if (!((vma->vm_flags & (VM_DONTEXPAND | VM_RESERVED)) || is_vm_hugetlb_page(vma) || vma == get_gate_vma(current))) { - long error; - downgrade_write(&mm->mmap_sem); - - error = __mlock_vma_pages_range(vma, start, end, 1); - up_read(&mm->mmap_sem); - /* vma can change or disappear */ - down_write(&mm->mmap_sem); - vma = find_vma(mm, start); - /* non-NULL vma must contain @start, but need to check @end */ - if (!vma || end > vma->vm_end) - return -ENOMEM; - - return 0; /* hide other errors from mmap(), et al */ + return __mlock_vma_pages_range(vma, start, end, 1); } /* @@ -438,41 +422,14 @@ success: vma->vm_flags = newflags; if (lock) { - /* - * mmap_sem is currently held for write. Downgrade the write - * lock to a read lock so that other faults, mmap scans, ... - * while we fault in all pages. - */ - downgrade_write(&mm->mmap_sem); - ret = __mlock_vma_pages_range(vma, start, end, 1); - /* - * Need to reacquire mmap sem in write mode, as our callers - * expect this. We have no support for atomically upgrading - * a sem to write, so we need to check for ranges while sem - * is unlocked. - */ - up_read(&mm->mmap_sem); - /* vma can change or disappear */ - down_write(&mm->mmap_sem); - *prev = find_vma(mm, start); - /* non-NULL *prev must contain @start, but need to check @end */ - if (!(*prev) || end > (*prev)->vm_end) - ret = -ENOMEM; - else if (ret > 0) { + if (ret > 0) { mm->locked_vm -= ret; ret = 0; } else ret = __mlock_posix_error_return(ret); /* translate if needed */ } else { - /* - * TODO: for unlocking, pages will already be resident, so - * we don't need to wait for allocations/reclaim/pagein, ... - * However, unlocking a very large region can still take a - * while. Should we downgrade the semaphore for both lock - * AND unlock ? - */ __mlock_vma_pages_range(vma, start, end, 0); } @@ -1090,6 +1090,15 @@ int vma_wants_writenotify(struct vm_area_struct *vma) mapping_cap_account_dirty(vma->vm_file->f_mapping); } +/* + * We account for memory if it's a private writeable mapping, + * and VM_NORESERVE wasn't set. + */ +static inline int accountable_mapping(unsigned int vm_flags) +{ + return (vm_flags & (VM_NORESERVE | VM_SHARED | VM_WRITE)) == VM_WRITE; +} + unsigned long mmap_region(struct file *file, unsigned long addr, unsigned long len, unsigned long flags, unsigned int vm_flags, unsigned long pgoff, @@ -1117,23 +1126,24 @@ munmap_back: if (!may_expand_vm(mm, len >> PAGE_SHIFT)) return -ENOMEM; - if (flags & MAP_NORESERVE) + /* + * Set 'VM_NORESERVE' if we should not account for the + * memory use of this mapping. We only honor MAP_NORESERVE + * if we're allowed to overcommit memory. + */ + if ((flags & MAP_NORESERVE) && sysctl_overcommit_memory != OVERCOMMIT_NEVER) + vm_flags |= VM_NORESERVE; + if (!accountable) vm_flags |= VM_NORESERVE; - if (accountable && (!(flags & MAP_NORESERVE) || - sysctl_overcommit_memory == OVERCOMMIT_NEVER)) { - if (vm_flags & VM_SHARED) { - /* Check memory availability in shmem_file_setup? */ - vm_flags |= VM_ACCOUNT; - } else if (vm_flags & VM_WRITE) { - /* - * Private writable mapping: check memory availability - */ - charged = len >> PAGE_SHIFT; - if (security_vm_enough_memory(charged)) - return -ENOMEM; - vm_flags |= VM_ACCOUNT; - } + /* + * Private writable mapping: check memory availability + */ + if (accountable_mapping(vm_flags)) { + charged = len >> PAGE_SHIFT; + if (security_vm_enough_memory(charged)) + return -ENOMEM; + vm_flags |= VM_ACCOUNT; } /* @@ -1184,14 +1194,6 @@ munmap_back: goto free_vma; } - /* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform - * shmem_zero_setup (perhaps called through /dev/zero's ->mmap) - * that memory reservation must be checked; but that reservation - * belongs to shared memory object, not to vma: so now clear it. - */ - if ((vm_flags & (VM_SHARED|VM_ACCOUNT)) == (VM_SHARED|VM_ACCOUNT)) - vma->vm_flags &= ~VM_ACCOUNT; - /* Can addr have changed?? * * Answer: Yes, several device drivers can do it in their diff --git a/mm/page-writeback.c b/mm/page-writeback.c index b493db7..dc32dae 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -1051,13 +1051,22 @@ continue_unlock: } } - if (wbc->sync_mode == WB_SYNC_NONE) { - wbc->nr_to_write--; - if (wbc->nr_to_write <= 0) { - done = 1; - break; - } + if (nr_to_write > 0) + nr_to_write--; + else if (wbc->sync_mode == WB_SYNC_NONE) { + /* + * We stop writing back only if we are not + * doing integrity sync. In case of integrity + * sync we have to keep going because someone + * may be concurrently dirtying pages, and we + * might have synced a lot of newly appeared + * dirty pages, but have not synced all of the + * old dirty pages. + */ + done = 1; + break; } + if (wbc->nonblocking && bdi_write_congested(bdi)) { wbc->encountered_congestion = 1; done = 1; @@ -2628,7 +2628,7 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags) goto close_file; #ifdef CONFIG_SHMEM - SHMEM_I(inode)->flags = flags & VM_ACCOUNT; + SHMEM_I(inode)->flags = (flags & VM_NORESERVE) ? 0 : VM_ACCOUNT; #endif d_instantiate(dentry, inode); inode->i_size = size; @@ -1996,7 +1996,7 @@ static struct kmem_cache_cpu *alloc_kmem_cache_cpu(struct kmem_cache *s, static void free_kmem_cache_cpu(struct kmem_cache_cpu *c, int cpu) { if (c < per_cpu(kmem_cache_cpu, cpu) || - c > per_cpu(kmem_cache_cpu, cpu) + NR_KMEM_CACHE_CPU) { + c >= per_cpu(kmem_cache_cpu, cpu) + NR_KMEM_CACHE_CPU) { kfree(c); return; } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 557fe16..dda42f0 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -663,14 +663,10 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, th->urg_ptr = 0; /* The urg_mode check is necessary during a below snd_una win probe */ - if (unlikely(tcp_urg_mode(tp))) { - if (between(tp->snd_up, tcb->seq + 1, tcb->seq + 0xFFFF)) { - th->urg_ptr = htons(tp->snd_up - tcb->seq); - th->urg = 1; - } else if (after(tcb->seq + 0xFFFF, tp->snd_nxt)) { - th->urg_ptr = 0xFFFF; - th->urg = 1; - } + if (unlikely(tcp_urg_mode(tp) && + between(tp->snd_up, tcb->seq + 1, tcb->seq + 0xFFFF))) { + th->urg_ptr = htons(tp->snd_up - tcb->seq); + th->urg = 1; } tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index b7faffe..cc3a0a0 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1015,9 +1015,11 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) { /* Note that an ENOMEM error is charged twice */ - if (rc == -ENOMEM) + if (rc == -ENOMEM) { UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, is_udplite); + atomic_inc(&sk->sk_drops); + } goto drop; } @@ -1229,7 +1231,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, int proto) { struct sock *sk; - struct udphdr *uh = udp_hdr(skb); + struct udphdr *uh; unsigned short ulen; struct rtable *rt = (struct rtable*)skb->dst; __be32 saddr = ip_hdr(skb)->saddr; @@ -1242,6 +1244,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, if (!pskb_may_pull(skb, sizeof(struct udphdr))) goto drop; /* No space for header. */ + uh = udp_hdr(skb); ulen = ntohs(uh->len); if (ulen > skb->len) goto short_packet; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4b15938..9fb49c3 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1105,6 +1105,18 @@ static inline int ip6_ufo_append_data(struct sock *sk, return err; } +static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src, + gfp_t gfp) +{ + return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; +} + +static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, + gfp_t gfp) +{ + return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; +} + int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), void *from, int length, int transhdrlen, @@ -1130,17 +1142,37 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, * setup for corking */ if (opt) { - if (np->cork.opt == NULL) { - np->cork.opt = kmalloc(opt->tot_len, - sk->sk_allocation); - if (unlikely(np->cork.opt == NULL)) - return -ENOBUFS; - } else if (np->cork.opt->tot_len < opt->tot_len) { - printk(KERN_DEBUG "ip6_append_data: invalid option length\n"); + if (WARN_ON(np->cork.opt)) return -EINVAL; - } - memcpy(np->cork.opt, opt, opt->tot_len); - inet->cork.flags |= IPCORK_OPT; + + np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation); + if (unlikely(np->cork.opt == NULL)) + return -ENOBUFS; + + np->cork.opt->tot_len = opt->tot_len; + np->cork.opt->opt_flen = opt->opt_flen; + np->cork.opt->opt_nflen = opt->opt_nflen; + + np->cork.opt->dst0opt = ip6_opt_dup(opt->dst0opt, + sk->sk_allocation); + if (opt->dst0opt && !np->cork.opt->dst0opt) + return -ENOBUFS; + + np->cork.opt->dst1opt = ip6_opt_dup(opt->dst1opt, + sk->sk_allocation); + if (opt->dst1opt && !np->cork.opt->dst1opt) + return -ENOBUFS; + + np->cork.opt->hopopt = ip6_opt_dup(opt->hopopt, + sk->sk_allocation); + if (opt->hopopt && !np->cork.opt->hopopt) + return -ENOBUFS; + + np->cork.opt->srcrt = ip6_rthdr_dup(opt->srcrt, + sk->sk_allocation); + if (opt->srcrt && !np->cork.opt->srcrt) + return -ENOBUFS; + /* need source address above miyazawa*/ } dst_hold(&rt->u.dst); @@ -1167,8 +1199,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, } else { rt = (struct rt6_info *)inet->cork.dst; fl = &inet->cork.fl; - if (inet->cork.flags & IPCORK_OPT) - opt = np->cork.opt; + opt = np->cork.opt; transhdrlen = 0; exthdrlen = 0; mtu = inet->cork.fragsize; @@ -1407,9 +1438,15 @@ error: static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) { - inet->cork.flags &= ~IPCORK_OPT; - kfree(np->cork.opt); - np->cork.opt = NULL; + if (np->cork.opt) { + kfree(np->cork.opt->dst0opt); + kfree(np->cork.opt->dst1opt); + kfree(np->cork.opt->hopopt); + kfree(np->cork.opt->srcrt); + kfree(np->cork.opt); + np->cork.opt = NULL; + } + if (inet->cork.dst) { dst_release(inet->cork.dst); inet->cork.dst = NULL; diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index d19a84b..228be55 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -48,6 +48,7 @@ #include <linux/pim.h> #include <net/addrconf.h> #include <linux/netfilter_ipv6.h> +#include <net/ip6_checksum.h> /* Big lock, protecting vif table, mrt cache and mroute socket state. Note that the changes are semaphored via rtnl_lock. diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 5f94db2..1fc4a78 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -77,6 +77,7 @@ #include <linux/poll.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/mutex.h> #ifdef CONFIG_INET #include <net/inet_common.h> @@ -175,6 +176,7 @@ struct packet_sock { #endif struct packet_type prot_hook; spinlock_t bind_lock; + struct mutex pg_vec_lock; unsigned int running:1, /* prot_hook is attached*/ auxdata:1, origdev:1; @@ -220,13 +222,13 @@ static void *packet_lookup_frame(struct packet_sock *po, unsigned int position, h.raw = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size); switch (po->tp_version) { case TPACKET_V1: - if (status != h.h1->tp_status ? TP_STATUS_USER : - TP_STATUS_KERNEL) + if (status != (h.h1->tp_status ? TP_STATUS_USER : + TP_STATUS_KERNEL)) return NULL; break; case TPACKET_V2: - if (status != h.h2->tp_status ? TP_STATUS_USER : - TP_STATUS_KERNEL) + if (status != (h.h2->tp_status ? TP_STATUS_USER : + TP_STATUS_KERNEL)) return NULL; break; } @@ -1069,6 +1071,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol) */ spin_lock_init(&po->bind_lock); + mutex_init(&po->pg_vec_lock); po->prot_hook.func = packet_rcv; if (sock->type == SOCK_PACKET) @@ -1865,6 +1868,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing synchronize_net(); err = -EBUSY; + mutex_lock(&po->pg_vec_lock); if (closing || atomic_read(&po->mapped) == 0) { err = 0; #define XC(a, b) ({ __typeof__ ((a)) __t; __t = (a); (a) = (b); __t; }) @@ -1886,6 +1890,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing if (atomic_read(&po->mapped)) printk(KERN_DEBUG "packet_mmap: vma is busy: %d\n", atomic_read(&po->mapped)); } + mutex_unlock(&po->pg_vec_lock); spin_lock(&po->bind_lock); if (was_running && !po->running) { @@ -1918,7 +1923,7 @@ static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_st size = vma->vm_end - vma->vm_start; - lock_sock(sk); + mutex_lock(&po->pg_vec_lock); if (po->pg_vec == NULL) goto out; if (size != po->pg_vec_len*po->pg_vec_pages*PAGE_SIZE) @@ -1941,7 +1946,7 @@ static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_st err = 0; out: - release_sock(sk); + mutex_unlock(&po->pg_vec_lock); return err; } #endif diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index dcef600..5592883 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -6,7 +6,7 @@ config SUNRPC_GSS config SUNRPC_XPRT_RDMA tristate - depends on SUNRPC && INFINIBAND && EXPERIMENTAL + depends on SUNRPC && INFINIBAND && INFINIBAND_ADDR_TRANS && EXPERIMENTAL default SUNRPC && INFINIBAND help This option allows the NFS client and server to support diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index e178366..0a1798e 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1767,7 +1767,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) AFMT_S8 | AFMT_U16_LE | AFMT_U16_BE | AFMT_S32_LE | AFMT_S32_BE | - AFMT_S24_LE | AFMT_S24_LE | + AFMT_S24_LE | AFMT_S24_BE | AFMT_S24_PACKED; params = kmalloc(sizeof(*params), GFP_KERNEL); if (!params) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index b7bba7d..0b70813 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -487,7 +487,6 @@ int /*__devinit*/ snd_hda_bus_new(struct snd_card *card, { struct hda_bus *bus; int err; - char qname[8]; static struct snd_device_ops dev_ops = { .dev_register = snd_hda_bus_dev_register, .dev_free = snd_hda_bus_dev_free, @@ -517,10 +516,12 @@ int /*__devinit*/ snd_hda_bus_new(struct snd_card *card, mutex_init(&bus->cmd_mutex); INIT_LIST_HEAD(&bus->codec_list); - snprintf(qname, sizeof(qname), "hda%d", card->number); - bus->workq = create_workqueue(qname); + snprintf(bus->workq_name, sizeof(bus->workq_name), + "hd-audio%d", card->number); + bus->workq = create_singlethread_workqueue(bus->workq_name); if (!bus->workq) { - snd_printk(KERN_ERR "cannot create workqueue %s\n", qname); + snd_printk(KERN_ERR "cannot create workqueue %s\n", + bus->workq_name); kfree(bus); return -ENOMEM; } diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 5810ef5..09a332a 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -614,6 +614,7 @@ struct hda_bus { /* unsolicited event queue */ struct hda_bus_unsolicited *unsol; + char workq_name[16]; struct workqueue_struct *workq; /* common workqueue for codecs */ /* assigned PCMs */ diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 7ca66d6..144b852 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -399,7 +399,8 @@ static void print_conn_list(struct snd_info_buffer *buffer, { int c, curr = -1; - if (conn_len > 1 && wid_type != AC_WID_AUD_MIX) + if (conn_len > 1 && wid_type != AC_WID_AUD_MIX && + wid_type != AC_WID_VOL_KNB) curr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0); snd_iprintf(buffer, " Connection: %d\n", conn_len); diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7884a4e..ae5c8a0 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1037,6 +1037,7 @@ do_sku: case 0x10ec0267: case 0x10ec0268: case 0x10ec0269: + case 0x10ec0272: case 0x10ec0660: case 0x10ec0662: case 0x10ec0663: @@ -1065,6 +1066,7 @@ do_sku: case 0x10ec0882: case 0x10ec0883: case 0x10ec0885: + case 0x10ec0887: case 0x10ec0889: snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7); @@ -7012,6 +7014,7 @@ static int patch_alc882(struct hda_codec *codec) break; case 0x106b1000: /* iMac 24 */ case 0x106b2800: /* AppleTV */ + case 0x106b3e00: /* iMac 24 Aluminium */ board_config = ALC885_IMAC24; break; case 0x106b00a1: /* Macbook (might be wrong - PCI SSID?) */ @@ -8514,6 +8517,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD), SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), + SND_PCI_QUIRK(0x1734, 0x1107, "FSC AMILO Xi2550", + ALC883_FUJITSU_PI2515), SND_PCI_QUIRK(0x1734, 0x1108, "Fujitsu AMILO Pi2515", ALC883_FUJITSU_PI2515), SND_PCI_QUIRK(0x1734, 0x113d, "Fujitsu AMILO Xa3530", ALC888_FUJITSU_XA3530), diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index b787b3c..38428e2 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1804,6 +1804,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { "HP dv4", STAC_HP_DV5), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30fc, "HP dv7", STAC_HP_M4), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3600, + "HP dv5", STAC_HP_DV5), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3603, "HP dv5", STAC_HP_DV5), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 19d3391..e900cdc 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -617,7 +617,7 @@ static int snd_intel8x0_ali_codec_semaphore(struct intel8x0 *chip) int time = 100; if (chip->buggy_semaphore) return 0; /* just ignore ... */ - while (time-- && (igetdword(chip, ICHREG(ALI_CAS)) & ALI_CAS_SEM_BUSY)) + while (--time && (igetdword(chip, ICHREG(ALI_CAS)) & ALI_CAS_SEM_BUSY)) udelay(1); if (! time && ! chip->in_ac97_init) snd_printk(KERN_WARNING "ali_codec_semaphore timeout\n"); diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index c5d6790..ff0054b 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -10,7 +10,7 @@ * Based on at91-ssc.c by * Frank Mandarino <fmandarino@endrelia.com> * Based on pxa2xx Platform drivers by - * Liam Girdwood <liam.girdwood@wolfsonmicro.com> + * Liam Girdwood <lrg@slimlogic.co.uk> * * 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 diff --git a/sound/soc/atmel/atmel_ssc_dai.h b/sound/soc/atmel/atmel_ssc_dai.h index a828746..391135f 100644 --- a/sound/soc/atmel/atmel_ssc_dai.h +++ b/sound/soc/atmel/atmel_ssc_dai.h @@ -10,7 +10,7 @@ * Based on at91-ssc.c by * Frank Mandarino <fmandarino@endrelia.com> * Based on pxa2xx Platform drivers by - * Liam Girdwood <liam.girdwood@wolfsonmicro.com> + * Liam Girdwood <lrg@slimlogic.co.uk> * * 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 diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index e3989d4..35d9975 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -3,7 +3,7 @@ * * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC. * - * Author: Liam Girdwood <lg@opensource.wolfsonmicro.com> + * Author: Liam Girdwood <lrg@slimlogic.co.uk> * * 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 diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 5b5afc1..1cbb7b9 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -2,8 +2,7 @@ * wm8990.c -- WM8990 ALSA Soc Audio driver * * Copyright 2008 Wolfson Microelectronics PLC. - * Author: Liam Girdwood - * lg@opensource.wolfsonmicro.com or linux@wolfsonmicro.com + * Author: Liam Girdwood <lrg@slimlogic.co.uk> * * 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 diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index b0362df..dd3bb29 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -175,9 +175,10 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_pcm_runtime *runtime = substream->runtime; struct omap_runtime_data *prtd = runtime->private_data; + unsigned long flags; int ret = 0; - spin_lock_irq(&prtd->lock); + spin_lock_irqsave(&prtd->lock, flags); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: @@ -195,7 +196,7 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) default: ret = -EINVAL; } - spin_unlock_irq(&prtd->lock); + spin_unlock_irqrestore(&prtd->lock, flags); return ret; } diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index c709b95..2ab8312 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2966,6 +2966,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, return -EINVAL; } alts = &iface->altsetting[fp->altset_idx]; + fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); usb_set_interface(chip->dev, fp->iface, 0); init_usb_pitch(chip->dev, fp->iface, alts, fp); init_usb_sample_rate(chip->dev, fp->iface, alts, fp, fp->rate_max); |